add: entry metadata
This commit is contained in:
parent
d80368e6c2
commit
b505199492
11 changed files with 631 additions and 45 deletions
|
@ -1,4 +1,7 @@
|
|||
use crate::{State, model::Entry};
|
||||
use crate::{
|
||||
State,
|
||||
model::{Entry, EntryMetadata},
|
||||
};
|
||||
use axum::{
|
||||
Extension, Json, Router,
|
||||
extract::Path,
|
||||
|
@ -6,6 +9,7 @@ use axum::{
|
|||
routing::{get, get_service, post},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_valid::Validate;
|
||||
use tera::Context;
|
||||
use tetratto_core::{
|
||||
model::{
|
||||
|
@ -99,38 +103,66 @@ async fn view_request(
|
|||
}
|
||||
};
|
||||
|
||||
let (views_id, views) = match data
|
||||
.query(&SimplifiedQuery {
|
||||
query: AppDataSelectQuery::KeyIs(format!("entries.views('{}')", slug)),
|
||||
mode: AppDataSelectMode::One(0),
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(r) => match r {
|
||||
AppDataQueryResult::One(r) => (r.id, r.value.parse::<usize>().unwrap()),
|
||||
AppDataQueryResult::Many(_) => unreachable!(),
|
||||
},
|
||||
// check metadata
|
||||
let metadata: EntryMetadata = match toml::from_str(&entry.metadata) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
let mut ctx = default_context(&data, &build_code);
|
||||
ctx.insert("error", &e.to_string());
|
||||
|
||||
return Html(tera.render("error.lisp", &ctx).unwrap());
|
||||
}
|
||||
};
|
||||
|
||||
// count view
|
||||
if let Err(e) = data.update(views_id, (views + 1).to_string()).await {
|
||||
if let Err(e) = metadata.validate() {
|
||||
let mut ctx = default_context(&data, &build_code);
|
||||
ctx.insert("error", &e.to_string());
|
||||
|
||||
return Html(tera.render("error.lisp", &ctx).unwrap());
|
||||
}
|
||||
|
||||
// pull views
|
||||
let views = if !metadata.option_disable_views {
|
||||
match data
|
||||
.query(&SimplifiedQuery {
|
||||
query: AppDataSelectQuery::KeyIs(format!("entries.views('{}')", slug)),
|
||||
mode: AppDataSelectMode::One(0),
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(r) => match r {
|
||||
AppDataQueryResult::One(r) => {
|
||||
// count view
|
||||
let views = r.value.parse::<usize>().unwrap();
|
||||
|
||||
if let Err(e) = data.update(r.id, (views + 1).to_string()).await {
|
||||
let mut ctx = default_context(&data, &build_code);
|
||||
ctx.insert("error", &e.to_string());
|
||||
|
||||
return Html(tera.render("error.lisp", &ctx).unwrap());
|
||||
}
|
||||
|
||||
views
|
||||
}
|
||||
AppDataQueryResult::Many(_) => unreachable!(),
|
||||
},
|
||||
Err(e) => {
|
||||
let mut ctx = default_context(&data, &build_code);
|
||||
ctx.insert("error", &e.to_string());
|
||||
|
||||
return Html(tera.render("error.lisp", &ctx).unwrap());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
// ...
|
||||
let mut ctx = default_context(&data, &build_code);
|
||||
|
||||
ctx.insert("entry", &entry);
|
||||
ctx.insert("views", &views);
|
||||
ctx.insert("metadata", &metadata);
|
||||
ctx.insert("metadata_head", &metadata.head_tags());
|
||||
ctx.insert("metadata_css", &metadata.css());
|
||||
|
||||
Html(tera.render("view.lisp", &ctx).unwrap())
|
||||
}
|
||||
|
@ -201,6 +233,8 @@ async fn exists_request(
|
|||
#[derive(Deserialize)]
|
||||
struct CreateEntry {
|
||||
content: String,
|
||||
#[serde(default)]
|
||||
metadata: String,
|
||||
#[serde(default = "default_random")]
|
||||
slug: String,
|
||||
#[serde(default = "default_random")]
|
||||
|
@ -234,6 +268,16 @@ async fn create_request(
|
|||
return Json(Error::DataTooLong("content".to_string()).into());
|
||||
}
|
||||
|
||||
// check metadata
|
||||
let metadata: EntryMetadata = match toml::from_str(&req.metadata) {
|
||||
Ok(x) => x,
|
||||
Err(e) => return Json(Error::MiscError(e.to_string()).into()),
|
||||
};
|
||||
|
||||
if let Err(e) = metadata.validate() {
|
||||
return Json(Error::MiscError(e.to_string()).into());
|
||||
}
|
||||
|
||||
// check for existing
|
||||
if data
|
||||
.query(&SimplifiedQuery {
|
||||
|
@ -260,6 +304,7 @@ async fn create_request(
|
|||
created,
|
||||
edited: created,
|
||||
content: req.content,
|
||||
metadata: req.metadata,
|
||||
})
|
||||
.unwrap(),
|
||||
)
|
||||
|
@ -292,6 +337,8 @@ struct EditEntry {
|
|||
#[serde(default)]
|
||||
new_edit_code: Option<String>,
|
||||
#[serde(default)]
|
||||
metadata: String,
|
||||
#[serde(default)]
|
||||
delete: bool,
|
||||
}
|
||||
|
||||
|
@ -311,6 +358,16 @@ async fn edit_request(
|
|||
return Json(Error::DataTooLong("content".to_string()).into());
|
||||
}
|
||||
|
||||
// check metadata
|
||||
let metadata: EntryMetadata = match toml::from_str(&req.metadata) {
|
||||
Ok(x) => x,
|
||||
Err(e) => return Json(Error::MiscError(e.to_string()).into()),
|
||||
};
|
||||
|
||||
if let Err(e) = metadata.validate() {
|
||||
return Json(Error::MiscError(e.to_string()).into());
|
||||
}
|
||||
|
||||
// ...
|
||||
let (id, mut entry) = match data
|
||||
.query(&SimplifiedQuery {
|
||||
|
@ -418,6 +475,7 @@ async fn edit_request(
|
|||
|
||||
// update
|
||||
entry.content = req.content;
|
||||
entry.metadata = req.metadata;
|
||||
entry.edited = unix_epoch_timestamp();
|
||||
|
||||
if let Err(e) = data
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue