133 lines
3.6 KiB
Rust
133 lines
3.6 KiB
Rust
use crate::webutil::{internal_error, TemplatedHtml};
|
|
use crate::WebConfig;
|
|
use askama::Template;
|
|
use axum::extract::{Extension, Form};
|
|
use axum::response::IntoResponse;
|
|
use itertools::Itertools;
|
|
use serde::Deserialize;
|
|
use sqlx::SqlitePool;
|
|
use std::collections::{BTreeSet, HashMap};
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
|
|
pub type SeedTagColumn = Vec<SeedTagGroup>;
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct SeedTagGroup {
|
|
name: String,
|
|
tags: Vec<SeedTag>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct SeedTag {
|
|
name: String,
|
|
id: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Template)]
|
|
#[template(path = "seed_collection.html.askama")]
|
|
pub struct SeedCollectionFormTemplate {
|
|
column1: SeedTagColumn,
|
|
column2: SeedTagColumn,
|
|
column3: SeedTagColumn,
|
|
thanks_for_submitting: bool,
|
|
contact: Vec<(String, String)>,
|
|
}
|
|
|
|
pub async fn seed_collection_root(
|
|
Extension(web_config): Extension<WebConfig>,
|
|
) -> impl IntoResponse {
|
|
// TODO(perf): cloning is a bit ugly; can we do better?
|
|
let seed_config = &web_config.seed_collection;
|
|
TemplatedHtml(SeedCollectionFormTemplate {
|
|
column1: seed_config.column1.clone(),
|
|
column2: seed_config.column2.clone(),
|
|
column3: seed_config.column3.clone(),
|
|
thanks_for_submitting: false,
|
|
contact: seed_config.contact.clone(),
|
|
})
|
|
}
|
|
|
|
#[derive(Deserialize, Debug, Clone)]
|
|
pub struct SeedCollectionPostForm {
|
|
pub url: String,
|
|
pub opendata_agree: bool,
|
|
pub extratags: String,
|
|
pub remarks_private: String,
|
|
/// Mostly expecting `tag_xyz` bools to be here.
|
|
#[serde(flatten)]
|
|
pub leftovers: HashMap<String, String>,
|
|
}
|
|
|
|
pub async fn seed_collection_root_post_inner(
|
|
Form(form): Form<SeedCollectionPostForm>,
|
|
Extension(web_config): Extension<WebConfig>,
|
|
Extension(pool): Extension<SqlitePool>,
|
|
) -> anyhow::Result<TemplatedHtml<SeedCollectionFormTemplate>> {
|
|
// TODO(perf): cloning is a bit ugly; can we do better?
|
|
eprintln!("{:?}", form);
|
|
|
|
let mut tags = BTreeSet::new();
|
|
let seed_config = &web_config.seed_collection;
|
|
|
|
for tag_group in itertools::chain!(
|
|
&seed_config.column1,
|
|
&seed_config.column2,
|
|
&seed_config.column3
|
|
) {
|
|
for tag in &tag_group.tags {
|
|
if form.leftovers.contains_key(&format!("tag_{}", tag.id)) {
|
|
tags.insert(tag.id.clone());
|
|
}
|
|
}
|
|
}
|
|
|
|
let tags_str = tags.iter().join(",");
|
|
|
|
let extra_tags = form
|
|
.extratags
|
|
.trim()
|
|
.replace(',', " ")
|
|
.split_whitespace()
|
|
.join(",");
|
|
|
|
let remarks_private: String = form.remarks_private.trim().chars().take(512).collect();
|
|
|
|
let ts = SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.expect("Duration since Unix Epoch failed.")
|
|
.as_secs() as i64;
|
|
|
|
let url = form.url.trim();
|
|
|
|
sqlx::query!(
|
|
"INSERT INTO collected_seeds (
|
|
collected_ts, url, tags, extra_tags, remarks_private
|
|
) VALUES (?, ?, ?, ?, ?)",
|
|
ts,
|
|
url,
|
|
tags_str,
|
|
extra_tags,
|
|
remarks_private
|
|
)
|
|
.execute(&pool)
|
|
.await?;
|
|
|
|
Ok(TemplatedHtml(SeedCollectionFormTemplate {
|
|
column1: seed_config.column1.clone(),
|
|
column2: seed_config.column2.clone(),
|
|
column3: seed_config.column3.clone(),
|
|
thanks_for_submitting: true,
|
|
contact: seed_config.contact.clone(),
|
|
}))
|
|
}
|
|
|
|
pub async fn seed_collection_root_post(
|
|
form: Form<SeedCollectionPostForm>,
|
|
web_config: Extension<WebConfig>,
|
|
pool: Extension<SqlitePool>,
|
|
) -> impl IntoResponse {
|
|
seed_collection_root_post_inner(form, web_config, pool)
|
|
.await
|
|
.map_err(internal_error)
|
|
}
|