move templates and static pages into rust source code to ditch i/o on page load
This commit is contained in:
parent
f0f4048835
commit
d3a5cac4be
10 changed files with 214 additions and 180 deletions
|
@ -1,4 +1,4 @@
|
|||
# My website
|
||||
# crablog
|
||||
|
||||
Pure rust. Built with actix, diesel, tera, serde and sqlite3.
|
||||
Environment variables are documented in [variables](./doc/environment.md)
|
||||
Environment variables are documented in [variables.md](./doc/environment.md)
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>mtrx' site</title>
|
||||
<link rel="stylesheet" href="/static/css/index.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi, I'm mtrx.</h1>
|
||||
<p>
|
||||
I have a <a href="/blog">blog.</a><br>
|
||||
This site is 100% <a href="https://github.com/leonardlorenz/website">open source</a>.<br>
|
||||
If you have questions or input for me please send me an E-Mail to me[at]mtrx.tech
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
|
@ -1,25 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>mtrx' blog</title>
|
||||
<link rel="stylesheet" href="/static/css/blog.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1><a href="/blog" class="post-link" style="text-decoration:none;color:black;">mtrx' blog</a></h1>
|
||||
<ul>
|
||||
{% for post in posts %}
|
||||
<article>
|
||||
<a href="/blog/id/{{ post.id }}" class="post-link">[link]</a>
|
||||
<div class="post-content">
|
||||
<h2 class="post-title">{{ post.title }}</h2>
|
||||
<sub class="post-publish-date"> {{ post.publish_date | date(format="%Y-%m-%d at %H:%M") }}</sub>
|
||||
<p class="post-body">{{ post.body }}</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -1,19 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>mtrx' blog</title>
|
||||
<link rel="stylesheet" href="/static/css/blog.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1><a href="/blog" class="post-link" style="text-decoration:none;color:black;">mtrx' blog</a></h1>
|
||||
<h2>Edit posts</h2>
|
||||
<ul style="list-style: none;">
|
||||
{% for post in posts %}
|
||||
<li><a href="/blog/edit/{{ post.id }}">{{ post.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -1,39 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Edit Post</title>
|
||||
<link rel="stylesheet" href="/static/css/blog.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="cookie-block" hidden>
|
||||
<p>Please set your token cookie first.</p>
|
||||
<input id="set-token" type="text" name="set-token">
|
||||
<button onclick="setTokenCookie()">Set Token Cookie</button>
|
||||
</div>
|
||||
<button onclick="clearTokenCookie()">Clear Token Cookie</button>
|
||||
|
||||
<form id="submit-form" action="/api/blog/posts/edit/{{ id }}" method=POST>
|
||||
<input class="token" type="text" name="token" hidden>
|
||||
<label for="title">Title</label>
|
||||
<textarea id="submit-title" type="text" name="title">{{ title }}</textarea>
|
||||
<br>
|
||||
<label for="submit-body">Content</label>
|
||||
<textarea id="submit-body" type="text" name="body">{{ body }}</textarea>
|
||||
<br>
|
||||
<button id="submit-button" type="submit">Edit Post</button>
|
||||
</form>
|
||||
|
||||
<form action="/api/blog/posts/hide/{{ id }}" method="POST">
|
||||
<input class="token" type="text" name="token" hidden>
|
||||
<button type="submit">Hide Post</button>
|
||||
</form>
|
||||
<form action="/api/blog/posts/delete/{{ id }}" method="POST">
|
||||
<input class="token" type="text" name="token" hidden>
|
||||
<button type="submit">Delete Post</button>
|
||||
</form>
|
||||
<script src="/static/js/blog.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,30 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Submit Post</title>
|
||||
<link rel="stylesheet" href="/static/css/blog.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="cookie-block" hidden>
|
||||
<p>Please set your token cookie first.</p>
|
||||
<input id="set-token" type="text" name="set-token">
|
||||
<button onclick="setTokenCookie()">Set Token Cookie</button>
|
||||
</div>
|
||||
<button onclick="clearTokenCookie()">Clear Token Cookie</button>
|
||||
|
||||
<form id="submit-form" action="/api/blog/create" method=POST>
|
||||
<input class="token" type="text" name="token" hidden>
|
||||
<label for="title">Title</label>
|
||||
<textarea id="submit-title" type="text" name="title">{{ title }}</textarea>
|
||||
<br>
|
||||
<label for="submit-body">Content</label>
|
||||
<textarea id="submit-body" type="text" name="body">{{ body }}</textarea>
|
||||
<br>
|
||||
<button id="submit-button" type="submit">Submit</button>
|
||||
</form>
|
||||
<script src="/static/js/blog.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +1,8 @@
|
|||
# Environment Variables
|
||||
|
||||
- SUBMIT_TOKEN: Alphanumeric string to be used for creating blog posts
|
||||
- ROOT_PATH: path where html, static and database reside
|
||||
- BIND_PORT: port to bind to
|
||||
- DATABASE_URL: path to the sqlite3 database
|
||||
- USERNAME: who does this site belong to?
|
||||
- EMAIL: email to contact the site owner
|
||||
- SUBMIT_TOKEN: Alphanumeric string to be used for creating blog posts
|
||||
|
|
162
site/src/html.rs
Normal file
162
site/src/html.rs
Normal file
|
@ -0,0 +1,162 @@
|
|||
pub const INDEX: &str = r#"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="{{ username }}' site'" />
|
||||
<meta property="og:image" content="/static/site-image.png" />
|
||||
|
||||
<title>{{ username }}' site</title>
|
||||
<link rel="stylesheet" href="/static/css/index.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Hi, I'm {{ username }}</h1>
|
||||
<p>
|
||||
I have a <a href="/blog">blog.</a><br>
|
||||
If you have questions or input for me please send me an E-Mail to {{ email }}
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
"#;
|
||||
|
||||
pub const BLOG: &str = r#"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="{{ sitetitle }}" />
|
||||
<meta property="og:image" content="/static/site-image.png" />
|
||||
|
||||
<title> {{ sitetitle }} </title>
|
||||
<link rel="stylesheet" href="/static/css/blog.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><a href="/blog" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
|
||||
<ul>
|
||||
{% for post in posts %}
|
||||
<article>
|
||||
<a href="/blog/id/{{ post.id }}" class="post-link">[link]</a>
|
||||
<div class="post-content">
|
||||
<h2 class="post-title">{{ post.title }}</h2>
|
||||
<sub class="post-publish-date"> {{ post.publish_date | date(format="%Y-%m-%d at %H:%M") }}</sub>
|
||||
<p class="post-body">{{ post.body }}</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
"#;
|
||||
|
||||
pub const SUBMIT: &str = r#"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="Submit post" />
|
||||
<meta property="og:image" content="/static/site-image.png" />
|
||||
|
||||
<title>Submit post</title>
|
||||
<link rel="stylesheet" href="/static/css/blog.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="cookie-block" hidden>
|
||||
<p>Please set your token cookie first.</p>
|
||||
<input id="set-token" type="text" name="set-token">
|
||||
<button onclick="setTokenCookie()">Set Token Cookie</button>
|
||||
</div>
|
||||
<button onclick="clearTokenCookie()">Clear Token Cookie</button>
|
||||
|
||||
<form id="submit-form" action="/api/blog/create" method=POST>
|
||||
<input class="token" type="text" name="token" hidden>
|
||||
<label for="title">Title</label>
|
||||
<textarea id="submit-title" type="text" name="title">{{ title }}</textarea>
|
||||
<br>
|
||||
<label for="submit-body">Content</label>
|
||||
<textarea id="submit-body" type="text" name="body">{{ body }}</textarea>
|
||||
<br>
|
||||
<button id="submit-button" type="submit">Submit</button>
|
||||
</form>
|
||||
<script src="/static/js/blog.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
"#;
|
||||
|
||||
pub const EDIT: &str = r#"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="Edit posts..." />
|
||||
<meta property="og:image" content="/static/site-image.png" />
|
||||
|
||||
<title>Edit posts...</title>
|
||||
<link rel="stylesheet" href="/static/css/blog.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1><a href="/blog" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
|
||||
<h2>Edit posts</h2>
|
||||
<ul style="list-style: none;">
|
||||
{% for post in posts %}
|
||||
<li><a href="/blog/edit/{{ post.id }}">{{ post.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
"#;
|
||||
|
||||
pub const POST_EDIT_FORM: &str = r#"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="Edit '{{ title }}'"/>
|
||||
<meta property="og:image" content="/static/site-image.png" />
|
||||
|
||||
<title>Edit '{{ title }}'</title>
|
||||
<link rel="stylesheet" href="/static/css/blog.css">
|
||||
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="cookie-block" hidden>
|
||||
<p>Please set your token cookie first.</p>
|
||||
<input id="set-token" type="text" name="set-token">
|
||||
<button onclick="setTokenCookie()">Set Token Cookie</button>
|
||||
</div>
|
||||
<button onclick="clearTokenCookie()">Clear Token Cookie</button>
|
||||
|
||||
<form id="submit-form" action="/api/blog/posts/edit/{{ id }}" method=POST>
|
||||
<input class="token" type="text" name="token" hidden>
|
||||
<label for="title">Title</label>
|
||||
<textarea id="submit-title" type="text" name="title">{{ title }}</textarea>
|
||||
<br>
|
||||
<label for="submit-body">Content</label>
|
||||
<textarea id="submit-body" type="text" name="body">{{ body }}</textarea>
|
||||
<br>
|
||||
<button id="submit-button" type="submit">Edit post</button>
|
||||
</form>
|
||||
|
||||
<form action="/api/blog/posts/hide/{{ id }}" method="POST">
|
||||
<input class="token" type="text" name="token" hidden>
|
||||
<button type="submit">Hide post</button>
|
||||
</form>
|
||||
<form action="/api/blog/posts/delete/{{ id }}" method="POST">
|
||||
<input class="token" type="text" name="token" hidden>
|
||||
<button type="submit">Delete post</button>
|
||||
</form>
|
||||
<script src="/static/js/blog.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
"#;
|
||||
|
|
@ -2,6 +2,7 @@ mod api;
|
|||
mod config;
|
||||
mod db;
|
||||
mod routes;
|
||||
mod html;
|
||||
|
||||
#[macro_use]
|
||||
extern crate diesel;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::config;
|
||||
use crate::db;
|
||||
use crate::html;
|
||||
|
||||
use actix_files as fs;
|
||||
use actix_web::{get, http::StatusCode, web, HttpResponse, Responder};
|
||||
use tera::{Context, Tera};
|
||||
|
||||
|
@ -45,48 +45,38 @@ pub fn replace_br_tags(x: &str) -> String {
|
|||
|
||||
#[get("/")]
|
||||
async fn root() -> impl Responder {
|
||||
let root_path = config::get_from_env("ROOT_PATH", true);
|
||||
fs::NamedFile::open(root_path + "/html/index.html")
|
||||
let mut context = Context::new();
|
||||
|
||||
context.insert("username", &config::get_from_env("USERNAME", true));
|
||||
context.insert("email", &config::get_from_env("EMAIL", true));
|
||||
|
||||
let result = Tera::one_off(
|
||||
html::INDEX,
|
||||
&context,
|
||||
false,
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't render blog template.\n{}", e));
|
||||
|
||||
HttpResponse::Ok().content_type("text/html").body(result)
|
||||
}
|
||||
|
||||
#[get("/blog")]
|
||||
async fn blog() -> impl Responder {
|
||||
let root_path = config::get_from_env("ROOT_PATH", true);
|
||||
|
||||
let posts = db::get_last_five_posts();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("posts", &posts);
|
||||
context.insert("username", &(config::get_from_env("USERNAME", true)));
|
||||
context.insert("sitetitle", &(config::get_from_env("USERNAME", true) + "' blog"));
|
||||
|
||||
// one-off render blog template with context
|
||||
let result = Tera::one_off(
|
||||
&(std::fs::read_to_string(root_path + "/templates/blog.html")
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't load blog template.\n{}", e))
|
||||
.as_str()),
|
||||
html::BLOG,
|
||||
&context,
|
||||
false,
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't render blog template.\n{}", e));
|
||||
HttpResponse::Ok().content_type("text/html").body(result)
|
||||
}
|
||||
|
||||
#[get("/blog/submit")]
|
||||
async fn blog_submit() -> impl Responder {
|
||||
let root_path = config::get_from_env("ROOT_PATH", true);
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("title", "");
|
||||
context.insert("body", "");
|
||||
|
||||
// one-off render blog template with context
|
||||
let result = Tera::one_off(
|
||||
&(std::fs::read_to_string(root_path + "/templates/post-submit.html")
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't load blog template.\n{}", e))
|
||||
.as_str()),
|
||||
&context,
|
||||
false,
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't render blog template.\n{}", e));
|
||||
HttpResponse::Ok().content_type("text/html").body(result)
|
||||
}
|
||||
|
||||
|
@ -94,40 +84,53 @@ async fn blog_submit() -> impl Responder {
|
|||
async fn blog_by_id(web::Path(post_id): web::Path<std::string::String>) -> impl Responder {
|
||||
let (valid, id) = id_valid(post_id);
|
||||
if valid {
|
||||
let root_path = config::get_from_env("ROOT_PATH", true);
|
||||
|
||||
let post = db::get_post_by_id(id as i32);
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("posts", &[post]);
|
||||
context.insert("posts", &[&post]);
|
||||
context.insert("username", &(config::get_from_env("USERNAME", true)));
|
||||
context.insert("sitetitle", &post.title);
|
||||
|
||||
// one-off render blog template with context
|
||||
let result = Tera::one_off(
|
||||
&(std::fs::read_to_string(root_path + "/templates/blog.html")
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't load blog template.\n{}", e))
|
||||
.as_str()),
|
||||
html::BLOG,
|
||||
&context,
|
||||
false,
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't render blog template.\n{}", e));
|
||||
|
||||
return HttpResponse::Ok().content_type("text/html").body(result);
|
||||
} else {
|
||||
return HttpResponse::new(StatusCode::NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/blog/edit")]
|
||||
async fn blog_edit() -> impl Responder {
|
||||
let root_path = config::get_from_env("ROOT_PATH", true);
|
||||
|
||||
#[get("/blog/submit")]
|
||||
async fn blog_submit() -> impl Responder {
|
||||
let mut context = Context::new();
|
||||
context.insert("posts", &db::get_all_posts());
|
||||
context.insert("title", "");
|
||||
context.insert("body", "");
|
||||
|
||||
// one-off render blog template with context
|
||||
let result = Tera::one_off(
|
||||
&(std::fs::read_to_string(root_path + "/templates/edit.html")
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't load edit template.\n{}", e))
|
||||
.as_str()),
|
||||
html::SUBMIT,
|
||||
&context,
|
||||
false,
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't render blog template.\n{}", e));
|
||||
|
||||
HttpResponse::Ok().content_type("text/html").body(result)
|
||||
}
|
||||
|
||||
#[get("/blog/edit")]
|
||||
async fn blog_edit() -> impl Responder {
|
||||
let mut context = Context::new();
|
||||
context.insert("posts", &db::get_all_posts());
|
||||
context.insert("username", &config::get_from_env("USERNAME", true));
|
||||
|
||||
// one-off render blog template with context
|
||||
let result = Tera::one_off(
|
||||
html::EDIT,
|
||||
&context,
|
||||
false,
|
||||
)
|
||||
|
@ -140,8 +143,6 @@ async fn blog_edit() -> impl Responder {
|
|||
async fn blog_edit_by_id(web::Path(post_id): web::Path<std::string::String>) -> impl Responder {
|
||||
let (valid, id) = id_valid(post_id);
|
||||
if valid {
|
||||
let root_path = config::get_from_env("ROOT_PATH", true);
|
||||
|
||||
let mut post = db::get_post_by_id(id as i32);
|
||||
|
||||
post.title = replace_br_tags(&post.title);
|
||||
|
@ -154,9 +155,7 @@ async fn blog_edit_by_id(web::Path(post_id): web::Path<std::string::String>) ->
|
|||
|
||||
// one-off render blog template with context
|
||||
let result = Tera::one_off(
|
||||
&(std::fs::read_to_string(root_path + "/templates/post-edit.html")
|
||||
.unwrap_or_else(|e| panic!("Error, couldn't load blog template.\n{}", e))
|
||||
.as_str()),
|
||||
html::POST_EDIT_FORM,
|
||||
&context,
|
||||
false,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue