From 03d31b936572b4209b0cb2659f24700a579f9163 Mon Sep 17 00:00:00 2001 From: asonix Date: Mon, 20 Jun 2022 20:49:42 -0500 Subject: [PATCH] Allow optional title, description, link --- src/lib.rs | 13 +++--- src/optional.rs | 72 +++++++++++++++++++++++++++++++ templates/edit_collection.rs.html | 7 +-- templates/image.rs.html | 13 +++++- templates/image_preview.rs.html | 3 +- 5 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 src/optional.rs diff --git a/src/lib.rs b/src/lib.rs index 1b0a5c8..6de2d93 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,11 +28,12 @@ const DAYS: u32 = 24 * HOURS; mod connection; mod middleware; +mod optional; mod pict; mod store; mod ui; -use self::{connection::Connection, middleware::ValidToken, store::Store}; +use self::{connection::Connection, middleware::ValidToken, optional::Optional, store::Store}; #[derive(Clone, Debug, Parser)] pub struct Config { @@ -483,8 +484,9 @@ pub enum EntryKind { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct Entry { - title: String, - description: String, + title: Optional, + description: Optional, + link: Optional, #[serde(flatten)] file_info: EntryKind, @@ -634,8 +636,9 @@ async fn upload( .stateful(&state)?; let entry = Entry { - title: String::new(), - description: String::new(), + title: None.into(), + description: None.into(), + link: None.into(), file_info: EntryKind::Pending { upload_id: upload.id().to_owned(), }, diff --git a/src/optional.rs b/src/optional.rs new file mode 100644 index 0000000..bd02ca6 --- /dev/null +++ b/src/optional.rs @@ -0,0 +1,72 @@ +use serde::{de::Error, Deserialize}; +use std::{ + fmt::Display, + ops::{Deref, DerefMut}, + str::FromStr, +}; + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)] +#[serde(transparent)] +pub(crate) struct Optional { + #[serde(skip_serializing_if = "Option::is_none")] + inner: Option, +} + +impl Deref for Optional { + type Target = Option; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for Optional { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +impl From> for Optional { + fn from(inner: Option) -> Self { + Optional { inner } + } +} + +impl From> for Option { + fn from(e: Optional) -> Self { + e.inner + } +} + +impl Optional { + pub fn as_ref(&self) -> Option<&T> { + self.inner.as_ref() + } + + pub fn as_deref(&self) -> Option<&T::Target> + where + T: Deref, + { + self.inner.as_deref() + } +} + +impl<'de, T> Deserialize<'de> for Optional +where + T: FromStr, + T::Err: Display, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s: Option = Deserialize::<'de>::deserialize(deserializer)?; + match s.as_deref() { + None | Some("") => Ok(Optional { inner: None }), + Some(s) => T::from_str(&s) + .map_err(D::Error::custom) + .map(Some) + .map(|inner| Optional { inner }), + } + } +} diff --git a/templates/edit_collection.rs.html b/templates/edit_collection.rs.html index ef77717..26a3ff8 100644 --- a/templates/edit_collection.rs.html +++ b/templates/edit_collection.rs.html @@ -52,15 +52,15 @@ statics::file_upload_js};
- @:text_input("title", Some("Image Title"), Some(&entry.title)) - @:text_area("description", Some("Image Description"), Some(&entry.description)) @if let Some(upload_id) = entry.upload_id() { } @if let Some((filename, delete_token)) = entry.file_parts() { + @:text_input("title", Some("Image Title"), entry.title.as_deref()) + @:text_area("description", Some("Image Description"), entry.description.as_deref()) + @:text_input("link", Some("https://..."), entry.link.as_ref().map(|l| l.as_str())) - }
@:button("Update Image", ButtonKind::Submit) @:button_link("Delete Image", &state.delete_entry_path(collection_id, *id, token, false), @@ -78,6 +78,7 @@ statics::file_upload_js}; ButtonKind::Outline) }
+ }
diff --git a/templates/image.rs.html b/templates/image.rs.html index b4115bc..36a1a48 100644 --- a/templates/image.rs.html +++ b/templates/image.rs.html @@ -5,6 +5,15 @@ @:image_preview(entry, state)
-
@entry.title
-
@entry.description
+ @if let Some(title) = entry.title.as_ref() { +
@title
+ } + @if let Some(description) = entry.description.as_ref() { +
@description
+ } + @if let Some(link) = entry.link.as_ref() { +
+ @link +
+ }
diff --git a/templates/image_preview.rs.html b/templates/image_preview.rs.html index 230f6d2..f122610 100644 --- a/templates/image_preview.rs.html +++ b/templates/image_preview.rs.html @@ -7,7 +7,8 @@ - @entry.description + @description } else {