Fix index mobile styles, add delete confirmations
This commit is contained in:
parent
dabff41156
commit
fbf10e2eea
|
@ -1334,7 +1334,7 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
|||
|
||||
[[package]]
|
||||
name = "pict-rs-aggregator"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pict-rs-aggregator"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
authors = ["asonix <asonix@asonix.dog>"]
|
||||
edition = "2018"
|
||||
build = "src/build.rs"
|
||||
|
|
|
@ -51,6 +51,11 @@ article .content-group {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.delete-confirmation {
|
||||
margin: 0;
|
||||
padding: 16px 0 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -135,8 +140,11 @@ a {
|
|||
}
|
||||
}
|
||||
|
||||
.button-space {
|
||||
.button-group {
|
||||
margin: 0 -8px;
|
||||
}
|
||||
|
||||
.button-space {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
|
@ -237,7 +245,7 @@ ul {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.button-space {
|
||||
.button-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
@ -248,6 +256,9 @@ ul {
|
|||
flex: 1;
|
||||
min-width: 150px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
|
|
80
src/lib.rs
80
src/lib.rs
|
@ -89,8 +89,15 @@ impl State {
|
|||
self.scoped(&format!("{}?token={}", id, token.token))
|
||||
}
|
||||
|
||||
fn delete_collection_path(&self, id: Uuid, token: &ValidToken) -> String {
|
||||
self.scoped(&format!("{}/delete?token={}", id, token.token))
|
||||
fn delete_collection_path(&self, id: Uuid, token: &ValidToken, confirmed: bool) -> String {
|
||||
if confirmed {
|
||||
self.scoped(&format!(
|
||||
"{}/delete?token={}&confirmed=true",
|
||||
id, token.token
|
||||
))
|
||||
} else {
|
||||
self.scoped(&format!("{}/delete?token={}", id, token.token))
|
||||
}
|
||||
}
|
||||
|
||||
fn public_collection_path(&self, id: Uuid) -> String {
|
||||
|
@ -108,11 +115,24 @@ impl State {
|
|||
))
|
||||
}
|
||||
|
||||
fn delete_entry_path(&self, collection_id: Uuid, id: Uuid, token: &ValidToken) -> String {
|
||||
self.scoped(&format!(
|
||||
"{}/entry/{}/delete?token={}",
|
||||
collection_id, id, token.token
|
||||
))
|
||||
fn delete_entry_path(
|
||||
&self,
|
||||
collection_id: Uuid,
|
||||
id: Uuid,
|
||||
token: &ValidToken,
|
||||
confirmed: bool,
|
||||
) -> String {
|
||||
if confirmed {
|
||||
self.scoped(&format!(
|
||||
"{}/entry/{}/delete?token={}&confirmed=true",
|
||||
collection_id, id, token.token
|
||||
))
|
||||
} else {
|
||||
self.scoped(&format!(
|
||||
"{}/entry/{}/delete?token={}",
|
||||
collection_id, id, token.token
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn statics_path(&self, file: &str) -> String {
|
||||
|
@ -448,13 +468,7 @@ async fn view_collection(
|
|||
|
||||
let mut cursor = Cursor::new(vec![]);
|
||||
|
||||
self::templates::view_collection(
|
||||
&mut cursor,
|
||||
path.collection,
|
||||
&collection,
|
||||
&entries,
|
||||
&state,
|
||||
)?;
|
||||
self::templates::view_collection(&mut cursor, path.collection, &collection, &entries, &state)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type(mime::TEXT_HTML.essence_str())
|
||||
|
@ -544,12 +558,36 @@ async fn update_entry(
|
|||
Ok(to_edit_page(entry_path.collection, &token, &state))
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct ConfirmQuery {
|
||||
confirmed: Option<bool>,
|
||||
}
|
||||
|
||||
async fn delete_entry(
|
||||
entry_path: web::Path<EntryPath>,
|
||||
query: web::Query<ConfirmQuery>,
|
||||
token: ValidToken,
|
||||
conn: web::Data<Connection>,
|
||||
state: web::Data<State>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
if !query.confirmed.unwrap_or(false) {
|
||||
let entry = state.store.entry(&entry_path).await?;
|
||||
|
||||
let mut cursor = Cursor::new(vec![]);
|
||||
self::templates::confirm_entry_delete(
|
||||
&mut cursor,
|
||||
entry_path.collection,
|
||||
entry_path.entry,
|
||||
&entry,
|
||||
&token,
|
||||
&state,
|
||||
)?;
|
||||
|
||||
return Ok(HttpResponse::Ok()
|
||||
.content_type(mime::TEXT_HTML.essence_str())
|
||||
.body(cursor.into_inner()));
|
||||
}
|
||||
|
||||
let entry = state.store.entry(&entry_path).await?;
|
||||
|
||||
conn.delete(&entry.filename, &entry.delete_token).await?;
|
||||
|
@ -565,10 +603,22 @@ async fn delete_entry(
|
|||
|
||||
async fn delete_collection(
|
||||
path: web::Path<CollectionPath>,
|
||||
_token: ValidToken,
|
||||
query: web::Query<ConfirmQuery>,
|
||||
token: ValidToken,
|
||||
conn: web::Data<Connection>,
|
||||
state: web::Data<State>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
if !query.confirmed.unwrap_or(false) {
|
||||
let collection = state.store.collection(&path).await?;
|
||||
|
||||
let mut cursor = Cursor::new(vec![]);
|
||||
self::templates::confirm_delete(&mut cursor, path.collection, &collection, &token, &state)?;
|
||||
|
||||
return Ok(HttpResponse::Ok()
|
||||
.content_type(mime::TEXT_HTML.essence_str())
|
||||
.body(cursor.into_inner()));
|
||||
}
|
||||
|
||||
let entries = state.store.entries(path.entry_range()).await?;
|
||||
|
||||
let future_vec = entries
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
@use crate::{ui::ButtonKind, Collection, State, ValidToken};
|
||||
@use super::{layout, button_link, return_home};
|
||||
@use uuid::Uuid;
|
||||
|
||||
@(id: Uuid, collection: &Collection, token: &ValidToken, state: &State)
|
||||
|
||||
@:layout(state, &format!("Delete: {}", collection.title), Some(&format!("Are you sure you want to delete {}", collection.title)), {
|
||||
<meta property="og:url" content="@state.delete_collection_path(id, token, false)" />
|
||||
}, {
|
||||
<section>
|
||||
<article>
|
||||
<div class="content-group">
|
||||
<h3>Delete @collection.title</h3>
|
||||
</div>
|
||||
<div class="content-group">
|
||||
<p class="subtitle">Are you sure you want to delete @collection.title</p>
|
||||
</div>
|
||||
<div class="content-group">
|
||||
<div class="button-group">
|
||||
@:button_link("Delete Collection", &state.delete_collection_path(id, token, true), ButtonKind::Submit)
|
||||
@:button_link("Cancel", &state.edit_collection_path(id, token), ButtonKind::Outline)
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@:return_home(state)
|
||||
})
|
|
@ -0,0 +1,33 @@
|
|||
@use crate::{ui::ButtonKind, Entry, State, ValidToken};
|
||||
@use super::{layout, button_link, image, return_home};
|
||||
@use uuid::Uuid;
|
||||
|
||||
@(collection_id: Uuid, id: Uuid, entry: &Entry, token: &ValidToken, state: &State)
|
||||
|
||||
@:layout(state, "Delete Image", Some("Are you sure you want to delete this image?"), {
|
||||
<meta property="og:url" content="@state.delete_entry_path(collection_id, id, token, false)" />
|
||||
}, {
|
||||
<section>
|
||||
<article>
|
||||
<div class="content-group">
|
||||
<h3>Delete Image</h3>
|
||||
</div>
|
||||
<div class="content-group">
|
||||
<div class="edit-row">
|
||||
<div class="edit-item">
|
||||
@:image(entry, state)
|
||||
</div>
|
||||
<div class="edit-item">
|
||||
<p class="delete-confirmation">Are you sure you want to delete this image?</p>
|
||||
<div class="button-group button-space">
|
||||
@:button_link("Delete Image", &state.delete_entry_path(collection_id, id, token, true), ButtonKind::Submit)
|
||||
@:button_link("Cancel", &state.edit_collection_path(collection_id, token), ButtonKind::Outline)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@:return_home(state)
|
||||
})
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
@use crate::{ui::ButtonKind, Collection, Entry, State, ValidToken};
|
||||
@use super::{button, button_link, image_preview, file_input, layout, text_area, text_input, statics::file_upload_js};
|
||||
@use super::{button, button_link, image, file_input, layout, return_home, text_area, text_input, statics::file_upload_js};
|
||||
@use uuid::Uuid;
|
||||
|
||||
@(collection: &Collection, collection_id: Uuid, entries: &[(Uuid, Entry)], token: &ValidToken, state: &State)
|
||||
|
@ -34,11 +34,11 @@
|
|||
</article>
|
||||
<article class="content-group">
|
||||
<form method="POST" action="@state.update_collection_path(collection_id, token)">
|
||||
@:text_input("title", Some("Title"), Some(&collection.title))
|
||||
@:text_area("description", Some("Description"), Some(&collection.description))
|
||||
<div class="button-space">
|
||||
@:text_input("title", Some("Collection Title"), Some(&collection.title))
|
||||
@:text_area("description", Some("Collection Description"), Some(&collection.description))
|
||||
<div class="button-group button-space">
|
||||
@:button("Update Collection", ButtonKind::Submit)
|
||||
@:button_link("Delete Collection", &state.delete_collection_path(collection_id, token), ButtonKind::Outline)
|
||||
@:button_link("Delete Collection", &state.delete_collection_path(collection_id, token, false), ButtonKind::Outline)
|
||||
</div>
|
||||
</form>
|
||||
</article>
|
||||
|
@ -48,21 +48,17 @@
|
|||
<article>
|
||||
<div class="edit-row">
|
||||
<div class="edit-item">
|
||||
@:image_preview(entry, state)
|
||||
<div class="image-meta">
|
||||
<div class="image-title">@entry.title</div>
|
||||
<div class="image-description">@entry.description</div>
|
||||
</div>
|
||||
@:image(entry, state)
|
||||
</div>
|
||||
<div class="edit-item">
|
||||
<form method="POST" action="@state.update_entry_path(collection_id, *id, token)">
|
||||
@:text_input("title", Some("Title"), Some(&entry.title))
|
||||
@:text_area("description", Some("Description"), Some(&entry.description))
|
||||
@:text_input("title", Some("Image Title"), Some(&entry.title))
|
||||
@:text_area("description", Some("Image Description"), Some(&entry.description))
|
||||
<input type="hidden" name="filename" value="@entry.filename" />
|
||||
<input type="hidden" name="delete_token" value="@entry.delete_token" />
|
||||
<div class="button-space">
|
||||
<div class="button-group button-space">
|
||||
@:button("Update Image", ButtonKind::Submit)
|
||||
@:button_link("Delete Image", &state.delete_entry_path(collection_id, *id, token), ButtonKind::Outline)
|
||||
@:button_link("Delete Image", &state.delete_entry_path(collection_id, *id, token, false), ButtonKind::Outline)
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -83,14 +79,15 @@
|
|||
<h3><legend>Add Image</legend></h3>
|
||||
</div>
|
||||
<div class="content-group" id="file-input-container">
|
||||
<div class="button-space">
|
||||
<div class="button-group">
|
||||
@:file_input("images[]", Some("Select Image"), Some(crate::accept()), false)
|
||||
</div>
|
||||
<div class="button-space">
|
||||
<div class="button-group button-space">
|
||||
@:button("Upload", ButtonKind::Submit)
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</article>
|
||||
</section>
|
||||
@:return_home(state)
|
||||
})
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
@use crate::{Entry, State};
|
||||
@use super::image_preview;
|
||||
|
||||
@(entry: &Entry, state: &State)
|
||||
|
||||
@:image_preview(entry, state)
|
||||
<div class="image-meta">
|
||||
<div class="image-title">@entry.title</div>
|
||||
<div class="image-description">@entry.description</div>
|
||||
</div>
|
|
@ -15,7 +15,9 @@
|
|||
@:text_area("description", Some("Description"), None)
|
||||
</div>
|
||||
<div class="content-group">
|
||||
@:button("Create Collection", ButtonKind::Submit)
|
||||
<div class="button-group">
|
||||
@:button("Create Collection", ButtonKind::Submit)
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</article>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
@use crate::State;
|
||||
|
||||
@(state: &State)
|
||||
|
||||
<section>
|
||||
<article class="content-group">
|
||||
<a href="@state.create_collection_path()">Return Home</a>
|
||||
</article>
|
||||
</section>
|
|
@ -1,5 +1,5 @@
|
|||
@use crate::{Collection, Entry, State};
|
||||
@use super::{layout, image_preview};
|
||||
@use super::{layout, image, return_home};
|
||||
@use uuid::Uuid;
|
||||
|
||||
@(id: Uuid, collection: &Collection, entries: &[(Uuid, Entry)], state: &State)
|
||||
|
@ -23,15 +23,12 @@
|
|||
@for (_, entry) in entries {
|
||||
<li class="content-group even">
|
||||
<article>
|
||||
@:image_preview(entry, state)
|
||||
<div class="image-meta">
|
||||
<div class="image-title">@entry.title</div>
|
||||
<div class="image-description">@entry.description</div>
|
||||
</div>
|
||||
@:image(entry, state)
|
||||
</article>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</section>
|
||||
@:return_home(state)
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in New Issue