226 lines
5.8 KiB
Rust
226 lines
5.8 KiB
Rust
use chrono::NaiveDate;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum SiteMode {
|
|
Blog,
|
|
Atelier,
|
|
}
|
|
|
|
impl Default for SiteMode {
|
|
fn default() -> Self {
|
|
Self::Atelier
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
pub struct ContactLink {
|
|
pub kind: String,
|
|
pub label: String,
|
|
pub value: String,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
pub struct SiteConfig {
|
|
pub title: String,
|
|
pub subtitle: String,
|
|
pub welcome_title: String,
|
|
pub welcome_subtitle: String,
|
|
pub footer: String,
|
|
pub favicon: String,
|
|
pub theme: String,
|
|
pub custom_css: String,
|
|
#[serde(default)]
|
|
pub contact_intro: String,
|
|
#[serde(default)]
|
|
pub contact_links: Vec<ContactLink>,
|
|
}
|
|
|
|
impl Default for SiteConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
title: "Ela's Atelier".to_string(),
|
|
subtitle: "Works on paper, canvas, and elsewhere".to_string(),
|
|
welcome_title: "Works on view".to_string(),
|
|
welcome_subtitle: "An ongoing arrangement of pieces, sketches, and stray observations."
|
|
.to_string(),
|
|
footer: "Hand-arranged with care".to_string(),
|
|
favicon: "/favicon.svg".to_string(),
|
|
theme: "salon".to_string(),
|
|
custom_css: "".to_string(),
|
|
contact_intro: "".to_string(),
|
|
contact_links: Vec::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Default)]
|
|
pub struct SiteConfigPatch {
|
|
#[serde(default)]
|
|
pub title: Option<String>,
|
|
#[serde(default)]
|
|
pub subtitle: Option<String>,
|
|
#[serde(default)]
|
|
pub welcome_title: Option<String>,
|
|
#[serde(default)]
|
|
pub welcome_subtitle: Option<String>,
|
|
#[serde(default)]
|
|
pub footer: Option<String>,
|
|
#[serde(default)]
|
|
pub favicon: Option<String>,
|
|
#[serde(default)]
|
|
pub theme: Option<String>,
|
|
#[serde(default)]
|
|
pub custom_css: Option<String>,
|
|
#[serde(default)]
|
|
pub contact_intro: Option<String>,
|
|
#[serde(default)]
|
|
pub contact_links: Option<Vec<ContactLink>>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Default)]
|
|
pub struct PostMeta {
|
|
pub date: NaiveDate,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub title: Option<String>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub summary: Option<String>,
|
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
pub tags: Vec<String>,
|
|
#[serde(default)]
|
|
pub draft: bool,
|
|
}
|
|
|
|
#[derive(Serialize, Clone, Copy)]
|
|
pub struct ImageDim {
|
|
pub w: u32,
|
|
pub h: u32,
|
|
}
|
|
|
|
#[derive(Serialize, Clone)]
|
|
pub struct CoverImage {
|
|
pub url: String,
|
|
pub alt: String,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub w: Option<u32>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub h: Option<u32>,
|
|
}
|
|
|
|
#[derive(Serialize, Clone)]
|
|
pub struct PostInfo {
|
|
pub slug: String,
|
|
pub date: NaiveDate,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub title: Option<String>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub summary: Option<String>,
|
|
pub tags: Vec<String>,
|
|
pub draft: bool,
|
|
pub reading_time: u32,
|
|
pub excerpt: String,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub cover_image: Option<CoverImage>,
|
|
pub image_count: u32,
|
|
}
|
|
|
|
#[derive(Serialize, Clone)]
|
|
pub struct PostNeighbor {
|
|
pub slug: String,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub title: Option<String>,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
pub struct PostDetail {
|
|
pub slug: String,
|
|
pub date: NaiveDate,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub title: Option<String>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub summary: Option<String>,
|
|
pub tags: Vec<String>,
|
|
pub draft: bool,
|
|
pub reading_time: u32,
|
|
pub content: String,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub cover_image: Option<CoverImage>,
|
|
pub image_count: u32,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub prev: Option<PostNeighbor>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub next: Option<PostNeighbor>,
|
|
#[serde(skip_serializing_if = "HashMap::is_empty")]
|
|
pub dimensions: HashMap<String, ImageDim>,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct CreatePostRequest {
|
|
pub slug: String,
|
|
#[serde(default)]
|
|
pub old_slug: Option<String>,
|
|
#[serde(default)]
|
|
pub title: Option<String>,
|
|
#[serde(default)]
|
|
pub date: Option<NaiveDate>,
|
|
#[serde(default)]
|
|
pub summary: Option<String>,
|
|
#[serde(default)]
|
|
pub tags: Vec<String>,
|
|
#[serde(default)]
|
|
pub draft: bool,
|
|
pub content: String,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct ContactSubmission {
|
|
#[serde(default)]
|
|
pub name: Option<String>,
|
|
#[serde(default)]
|
|
pub email: Option<String>,
|
|
#[serde(default)]
|
|
pub subject: Option<String>,
|
|
pub message: String,
|
|
#[serde(default)]
|
|
pub website: Option<String>,
|
|
pub started_at: i64,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
pub struct Message {
|
|
pub id: String,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub name: Option<String>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub email: Option<String>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub subject: Option<String>,
|
|
pub body: String,
|
|
pub received_at: i64,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub ip_hash: Option<String>,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
pub struct ContactResponse {
|
|
pub ok: bool,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
pub struct ErrorResponse {
|
|
pub error: String,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
pub struct UploadResponse {
|
|
pub url: String,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
pub struct FileInfo {
|
|
pub name: String,
|
|
pub url: String,
|
|
}
|