feat: tera template

This commit is contained in:
Kilerd Chan 2019-04-18 21:22:44 +08:00
parent df0edc4435
commit 89ae721a90
17 changed files with 127 additions and 16 deletions

View File

@ -13,12 +13,13 @@ r2d2 = "0.8"
lazy_static = "1.1"
serde = "1.0"
serde_derive = "1.0"
tera = "*"
tera = "0.11.0"
pulldown-cmark = { version = "0.1.2", default-features = false }
chrono = { version = "*", features = ["serde"] }
rust-crypto = "^0.2"
rss = "1.6.1"
actix-web="1.0.0-alpha.6"
actix-web= "1.0.0-alpha.6"
actix-files = "0.1.0-alpha.6"
actix = "0.8.1"
diesel_migrations = "1.4.0"

View File

@ -13,6 +13,9 @@ use actix_web::{
use dotenv::dotenv;
use crate::pg_pool::database_pool_establish;
use std::rc::Rc;
use std::sync::Arc;
use tera::compile_templates;
mod guard;
mod models;
@ -21,28 +24,38 @@ mod request;
mod response;
mod routers;
mod schema;
mod template;
mod view;
embed_migrations!();
fn main() -> std::io::Result<()> {
let sys = actix::System::new("lemmy");
dotenv().ok();
// let sys = actix::System::new("lemmy");
let database_url = std::env::var("DATABASE_URL").expect("database_url must be set");
let pool = database_pool_establish(&database_url);
let tera = Arc::new(compile_templates!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/templates/**/*.html"
)));
embedded_migrations::run(&pool.get().expect("cannot get connection"));
HttpServer::new(move || {
App::new()
.data(pool.clone())
.data(tera.clone())
.wrap(Logger::default())
.wrap(Cors::default())
.default_service(web::route().to(|| "hello world"))
.service(routers::article::homepage)
.service(actix_files::Files::new(
"/statics",
"./templates/resources/",
))
})
.bind(("127.0.0.1", 8000))?
.system_exit()
.start();
sys.run();
Ok(())
// .system_exit()
.run()
}

View File

@ -43,7 +43,7 @@ impl CRUD<NewArticle, NewArticle, i32> for Article {
fn read(conn: &PgConnection) -> Vec<Self> {
articles::table
.order(articles::publish_at.desc())
.load::<Article>(conn)
.load::<Self>(conn)
.expect("something wrong")
}

View File

@ -5,6 +5,8 @@ use diesel::prelude::*;
use diesel::result::Error;
use diesel::{AsChangeset, Insertable, Queryable};
use serde::Serialize;
use std::collections::HashMap;
#[derive(Queryable, Debug, Serialize, Insertable, AsChangeset)]
#[table_name = "setting"]
pub struct Setting {
@ -12,6 +14,43 @@ pub struct Setting {
pub value: Option<String>,
}
#[derive(Serialize)]
pub struct SettingMap {
pub title: String,
pub description: String,
pub url: String,
pub analysis: String,
}
impl Setting {
pub fn load(conn: &PgConnection) -> SettingMap {
let settings = setting::table.load::<Setting>(conn).unwrap();
let mut settings_map: HashMap<String, String> = HashMap::new();
for one_setting in settings {
settings_map.insert(
one_setting.name,
one_setting.value.unwrap_or("".to_string()),
);
}
SettingMap {
title: settings_map.get("title").unwrap_or(&"".to_string()).clone(),
description: settings_map
.get("description")
.unwrap_or(&"".to_string())
.clone(),
url: settings_map.get("url").unwrap_or(&"".to_string()).clone(),
analysis: settings_map
.get("analysis")
.unwrap_or(&"".to_string())
.clone(),
}
}
}
impl CRUD<(), Setting, String> for Setting {
fn create(conn: &PgConnection, from: &()) -> Result<Self, Error> {
unimplemented!()

View File

@ -26,6 +26,32 @@
//
// Template::render("index", &context)
//}
use crate::models::article::Article;
use crate::models::setting::Setting;
use crate::models::CRUD;
use crate::pg_pool::Pool;
use crate::view::article::ArticleView;
use actix_web::{get, web, HttpResponse, Responder};
use std::sync::Arc;
use tera::{Context, Tera};
#[get("/")]
pub fn homepage(tera: web::Data<Arc<Tera>>, conn: web::Data<Pool>) -> impl Responder {
let connection = conn.get().unwrap();
let vec = Article::read(&connection);
let articles: Vec<ArticleView> = vec.iter().map(ArticleView::from).collect();
let settings = Setting::load(&connection);
let mut context = Context::new();
context.insert("setting", &settings);
context.insert("articles", &articles);
HttpResponse::Ok()
.content_type("text/html")
.body(tera.render("homepage.html", &context).unwrap())
}
//
////#[get("/archives/<archives_id>")]
//pub fn single_article(setting: SettingMap, conn: DbConn, archives_id: i32) -> Result<Template, Status> {
@ -49,7 +75,7 @@
//
////#[get("/statics/<file..>")]
//pub fn static_content(file: PathBuf) -> Result<NamedFile, Status> {
// let path = Path::new("static/resources/").join(file);
// let path = Path::new("templates/resources/").join(file);
// let result = NamedFile::open(&path);
// if let Ok(file) = result {
// Ok(file)

View File

@ -1,4 +1,4 @@
//pub mod article;
pub mod article;
//pub mod admin;
//pub mod rss;
//pub mod catacher;

1
src/template.rs Normal file
View File

@ -0,0 +1 @@

30
src/view/article.rs Normal file
View File

@ -0,0 +1,30 @@
use crate::models::article::Article;
use pulldown_cmark::html;
use pulldown_cmark::Parser;
use serde::Serialize;
#[derive(Debug, Serialize)]
pub struct ArticleView<'a> {
pub article: &'a Article,
pub timestamp: i64,
pub markdown_content: String,
pub description: String,
}
impl<'a> ArticleView<'a> {
pub fn from(article: &'a Article) -> ArticleView {
let content_split: Vec<_> = article.body.split("<!--more-->").collect();
let description_parser = Parser::new(&content_split[0]);
let parser = Parser::new(&article.body);
let mut description_buf = String::new();
let mut content_buf = String::new();
html::push_html(&mut content_buf, parser);
html::push_html(&mut description_buf, description_parser);
ArticleView {
article,
timestamp: article.publish_at.timestamp(),
markdown_content: content_buf,
description: description_buf,
}
}
}

1
src/view/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod article;

View File

@ -1,4 +1,4 @@
{% extends "base" %}
{% extends "base.html" %}
{% block title %}{{ setting.title }}{% endblock title %}
@ -12,15 +12,15 @@
</header>
<section class="container">
{% for article in articles %}
{% for article in articles %}
<section class="article">
<p class="mate">{{ article.timestamp | date(format="%B %d, %Y") }}</p>
<a class="title" href="{% if article.article.url %}{{ article.article.url }}{% else %}archives/{{ article.article.id }}{% endif %}">{{ article.article.title }}</a>
<section class="yue desc">
{{ article.description }}
{{ article.description|safe }}
</section>
</section>
{% endfor %}
{% endfor %}
</section>