Rename to Collections, use pict-rs's 'resize' instead of 'thumbnail'
This commit is contained in:
parent
4f270a5d41
commit
f7d1baf3ec
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1334,7 +1334,7 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
|||
|
||||
[[package]]
|
||||
name = "pict-rs-aggregator"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pict-rs-aggregator"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
authors = ["asonix <asonix@asonix.dog>"]
|
||||
edition = "2018"
|
||||
build = "src/build.rs"
|
||||
|
|
|
@ -2,7 +2,7 @@ version: '3.3'
|
|||
|
||||
services:
|
||||
pictrs:
|
||||
image: asonix/pictrs:v0.2.6-r0
|
||||
image: asonix/pictrs:v0.3.0-alpha.0-r0
|
||||
user: root
|
||||
restart: always
|
||||
volumes:
|
||||
|
|
|
@ -88,7 +88,7 @@ impl Connection {
|
|||
fn thumbnail_url(&self, size: u16, file: &str, extension: Extension) -> String {
|
||||
let mut url = self.upstream.clone();
|
||||
url.set_path(&format!("/image/process.{}", extension));
|
||||
url.set_query(Some(&format!("src={}&thumbnail={}", file, size)));
|
||||
url.set_query(Some(&format!("src={}&resize={}", file, size)));
|
||||
|
||||
url.to_string()
|
||||
}
|
||||
|
|
138
src/lib.rs
138
src/lib.rs
|
@ -77,41 +77,41 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
fn create_aggregation_path(&self) -> String {
|
||||
fn create_collection_path(&self) -> String {
|
||||
self.scoped("")
|
||||
}
|
||||
|
||||
fn edit_aggregation_path(&self, id: Uuid, token: &ValidToken) -> String {
|
||||
fn edit_collection_path(&self, id: Uuid, token: &ValidToken) -> String {
|
||||
self.scoped(&format!("{}?token={}", id, token.token))
|
||||
}
|
||||
|
||||
fn update_aggregation_path(&self, id: Uuid, token: &ValidToken) -> String {
|
||||
fn update_collection_path(&self, id: Uuid, token: &ValidToken) -> String {
|
||||
self.scoped(&format!("{}?token={}", id, token.token))
|
||||
}
|
||||
|
||||
fn delete_aggregation_path(&self, id: Uuid, token: &ValidToken) -> String {
|
||||
fn delete_collection_path(&self, id: Uuid, token: &ValidToken) -> String {
|
||||
self.scoped(&format!("{}/delete?token={}", id, token.token))
|
||||
}
|
||||
|
||||
fn public_aggregation_path(&self, id: Uuid) -> String {
|
||||
fn public_collection_path(&self, id: Uuid) -> String {
|
||||
self.scoped(&format!("{}", id))
|
||||
}
|
||||
|
||||
fn create_entry_path(&self, aggregation_id: Uuid, token: &ValidToken) -> String {
|
||||
self.scoped(&format!("{}/entry?token={}", aggregation_id, token.token))
|
||||
fn create_entry_path(&self, collection_id: Uuid, token: &ValidToken) -> String {
|
||||
self.scoped(&format!("{}/entry?token={}", collection_id, token.token))
|
||||
}
|
||||
|
||||
fn update_entry_path(&self, aggregation_id: Uuid, id: Uuid, token: &ValidToken) -> String {
|
||||
fn update_entry_path(&self, collection_id: Uuid, id: Uuid, token: &ValidToken) -> String {
|
||||
self.scoped(&format!(
|
||||
"{}/entry/{}?token={}",
|
||||
aggregation_id, id, token.token
|
||||
collection_id, id, token.token
|
||||
))
|
||||
}
|
||||
|
||||
fn delete_entry_path(&self, aggregation_id: Uuid, id: Uuid, token: &ValidToken) -> String {
|
||||
fn delete_entry_path(&self, collection_id: Uuid, id: Uuid, token: &ValidToken) -> String {
|
||||
self.scoped(&format!(
|
||||
"{}/entry/{}/delete?token={}",
|
||||
aggregation_id, id, token.token
|
||||
collection_id, id, token.token
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -162,17 +162,17 @@ pub fn service(client: Client, state: State) -> Scope {
|
|||
.service(
|
||||
web::resource("")
|
||||
.route(web::get().to(index))
|
||||
.route(web::post().to(create_aggregation)),
|
||||
.route(web::post().to(create_collection)),
|
||||
)
|
||||
.service(
|
||||
web::scope("/{aggregation}")
|
||||
web::scope("/{collection}")
|
||||
.wrap(middleware::Verify)
|
||||
.service(
|
||||
web::resource("")
|
||||
.route(web::get().to(aggregation))
|
||||
.route(web::post().to(update_aggregation)),
|
||||
.route(web::get().to(collection))
|
||||
.route(web::post().to(update_collection)),
|
||||
)
|
||||
.service(web::resource("/delete").route(web::get().to(delete_aggregation)))
|
||||
.service(web::resource("/delete").route(web::get().to(delete_collection)))
|
||||
.service(
|
||||
web::scope("/entry")
|
||||
.service(web::resource("").route(web::post().to(upload)))
|
||||
|
@ -189,19 +189,19 @@ pub fn service(client: Client, state: State) -> Scope {
|
|||
|
||||
fn to_edit_page(id: Uuid, token: &ValidToken, state: &State) -> HttpResponse {
|
||||
HttpResponse::SeeOther()
|
||||
.header(LOCATION, state.edit_aggregation_path(id, token))
|
||||
.header(LOCATION, state.edit_collection_path(id, token))
|
||||
.finish()
|
||||
}
|
||||
|
||||
fn to_404(state: &State) -> HttpResponse {
|
||||
HttpResponse::MovedPermanently()
|
||||
.header(LOCATION, state.create_aggregation_path())
|
||||
.header(LOCATION, state.create_collection_path())
|
||||
.finish()
|
||||
}
|
||||
|
||||
fn to_home(state: &State) -> HttpResponse {
|
||||
HttpResponse::SeeOther()
|
||||
.header(LOCATION, state.create_aggregation_path())
|
||||
.header(LOCATION, state.create_collection_path())
|
||||
.finish()
|
||||
}
|
||||
|
||||
|
@ -266,7 +266,7 @@ impl ResponseError for Error {
|
|||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
pub struct Aggregation {
|
||||
pub struct Collection {
|
||||
title: String,
|
||||
description: String,
|
||||
}
|
||||
|
@ -306,17 +306,17 @@ impl TokenStorage {
|
|||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct AggregationPath {
|
||||
aggregation: Uuid,
|
||||
struct CollectionPath {
|
||||
collection: Uuid,
|
||||
}
|
||||
|
||||
impl AggregationPath {
|
||||
impl CollectionPath {
|
||||
fn key(&self) -> String {
|
||||
format!("{}", self.aggregation)
|
||||
format!("{}", self.collection)
|
||||
}
|
||||
|
||||
fn entry_range(&self) -> std::ops::Range<Vec<u8>> {
|
||||
let base = format!("{}/entry/", self.aggregation).as_bytes().to_vec();
|
||||
let base = format!("{}/entry/", self.collection).as_bytes().to_vec();
|
||||
let mut start = base.clone();
|
||||
let mut end = base;
|
||||
|
||||
|
@ -327,26 +327,26 @@ impl AggregationPath {
|
|||
}
|
||||
|
||||
fn token_key(&self) -> String {
|
||||
format!("{}/token", self.aggregation)
|
||||
format!("{}/token", self.collection)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct EntryPath {
|
||||
aggregation: Uuid,
|
||||
collection: Uuid,
|
||||
entry: Uuid,
|
||||
}
|
||||
|
||||
impl EntryPath {
|
||||
fn key(&self) -> String {
|
||||
format!("{}/entry/{}", self.aggregation, self.entry)
|
||||
format!("{}/entry/{}", self.collection, self.entry)
|
||||
}
|
||||
}
|
||||
|
||||
async fn upload(
|
||||
req: HttpRequest,
|
||||
pl: web::Payload,
|
||||
path: web::Path<AggregationPath>,
|
||||
path: web::Path<CollectionPath>,
|
||||
token: ValidToken,
|
||||
conn: web::Data<Connection>,
|
||||
state: web::Data<State>,
|
||||
|
@ -370,7 +370,7 @@ async fn upload(
|
|||
};
|
||||
|
||||
let entry_path = EntryPath {
|
||||
aggregation: path.aggregation,
|
||||
collection: path.collection,
|
||||
entry: Uuid::new_v4(),
|
||||
};
|
||||
|
||||
|
@ -381,7 +381,7 @@ async fn upload(
|
|||
.exec(&state.store)
|
||||
.await?;
|
||||
|
||||
Ok(to_edit_page(path.aggregation, &token, &state))
|
||||
Ok(to_edit_page(path.collection, &token, &state))
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
|
@ -428,30 +428,30 @@ async fn index(state: web::Data<State>) -> Result<HttpResponse, Error> {
|
|||
.body(cursor.into_inner()))
|
||||
}
|
||||
|
||||
async fn aggregation(
|
||||
path: web::Path<AggregationPath>,
|
||||
async fn collection(
|
||||
path: web::Path<CollectionPath>,
|
||||
token: Option<ValidToken>,
|
||||
state: web::Data<State>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
match token {
|
||||
Some(token) => edit_aggregation(path, token, state).await,
|
||||
None => view_aggregation(path, state).await,
|
||||
Some(token) => edit_collection(path, token, state).await,
|
||||
None => view_collection(path, state).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn view_aggregation(
|
||||
path: web::Path<AggregationPath>,
|
||||
async fn view_collection(
|
||||
path: web::Path<CollectionPath>,
|
||||
state: web::Data<State>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let aggregation = state.store.aggregation(&path).await?;
|
||||
let collection = state.store.collection(&path).await?;
|
||||
let entries = state.store.entries(path.entry_range()).await?;
|
||||
|
||||
let mut cursor = Cursor::new(vec![]);
|
||||
|
||||
self::templates::view_aggregation(
|
||||
self::templates::view_collection(
|
||||
&mut cursor,
|
||||
path.aggregation,
|
||||
&aggregation,
|
||||
path.collection,
|
||||
&collection,
|
||||
&entries,
|
||||
&state,
|
||||
)?;
|
||||
|
@ -461,20 +461,20 @@ async fn view_aggregation(
|
|||
.body(cursor.into_inner()))
|
||||
}
|
||||
|
||||
async fn edit_aggregation(
|
||||
path: web::Path<AggregationPath>,
|
||||
async fn edit_collection(
|
||||
path: web::Path<CollectionPath>,
|
||||
token: ValidToken,
|
||||
state: web::Data<State>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let aggregation = state.store.aggregation(&path).await?;
|
||||
let collection = state.store.collection(&path).await?;
|
||||
let entries = state.store.entries(path.entry_range()).await?;
|
||||
|
||||
let mut cursor = Cursor::new(vec![]);
|
||||
|
||||
self::templates::edit_aggregation(
|
||||
self::templates::edit_collection(
|
||||
&mut cursor,
|
||||
&aggregation,
|
||||
path.aggregation,
|
||||
&collection,
|
||||
path.collection,
|
||||
&entries,
|
||||
&token,
|
||||
&state,
|
||||
|
@ -485,47 +485,47 @@ async fn edit_aggregation(
|
|||
.body(cursor.into_inner()))
|
||||
}
|
||||
|
||||
async fn create_aggregation(
|
||||
aggregation: web::Form<Aggregation>,
|
||||
async fn create_collection(
|
||||
collection: web::Form<Collection>,
|
||||
state: web::Data<State>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let aggregation_id = Uuid::new_v4();
|
||||
let aggregation_path = AggregationPath {
|
||||
aggregation: aggregation_id,
|
||||
let collection_id = Uuid::new_v4();
|
||||
let collection_path = CollectionPath {
|
||||
collection: collection_id,
|
||||
};
|
||||
let token = Token {
|
||||
token: Uuid::new_v4(),
|
||||
};
|
||||
|
||||
store::CreateAggregation {
|
||||
aggregation_path: &aggregation_path,
|
||||
aggregation: &aggregation,
|
||||
store::CreateCollection {
|
||||
collection_path: &collection_path,
|
||||
collection: &collection,
|
||||
token: &token,
|
||||
}
|
||||
.exec(&state.store)
|
||||
.await?;
|
||||
|
||||
Ok(to_edit_page(
|
||||
aggregation_path.aggregation,
|
||||
collection_path.collection,
|
||||
&ValidToken { token: token.token },
|
||||
&state,
|
||||
))
|
||||
}
|
||||
|
||||
async fn update_aggregation(
|
||||
path: web::Path<AggregationPath>,
|
||||
form: web::Form<Aggregation>,
|
||||
async fn update_collection(
|
||||
path: web::Path<CollectionPath>,
|
||||
form: web::Form<Collection>,
|
||||
token: ValidToken,
|
||||
state: web::Data<State>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
store::UpdateAggregation {
|
||||
aggregation_path: &path,
|
||||
aggregation: &form,
|
||||
store::UpdateCollection {
|
||||
collection_path: &path,
|
||||
collection: &form,
|
||||
}
|
||||
.exec(&state.store)
|
||||
.await?;
|
||||
|
||||
Ok(to_edit_page(path.aggregation, &token, &state))
|
||||
Ok(to_edit_page(path.collection, &token, &state))
|
||||
}
|
||||
|
||||
async fn update_entry(
|
||||
|
@ -541,7 +541,7 @@ async fn update_entry(
|
|||
.exec(&state.store)
|
||||
.await?;
|
||||
|
||||
Ok(to_edit_page(entry_path.aggregation, &token, &state))
|
||||
Ok(to_edit_page(entry_path.collection, &token, &state))
|
||||
}
|
||||
|
||||
async fn delete_entry(
|
||||
|
@ -560,11 +560,11 @@ async fn delete_entry(
|
|||
.exec(&state.store)
|
||||
.await?;
|
||||
|
||||
Ok(to_edit_page(entry_path.aggregation, &token, &state))
|
||||
Ok(to_edit_page(entry_path.collection, &token, &state))
|
||||
}
|
||||
|
||||
async fn delete_aggregation(
|
||||
path: web::Path<AggregationPath>,
|
||||
async fn delete_collection(
|
||||
path: web::Path<CollectionPath>,
|
||||
_token: ValidToken,
|
||||
conn: web::Data<Connection>,
|
||||
state: web::Data<State>,
|
||||
|
@ -578,8 +578,8 @@ async fn delete_aggregation(
|
|||
|
||||
futures::future::try_join_all(future_vec).await?;
|
||||
|
||||
store::DeleteAggregation {
|
||||
aggregation_path: &path,
|
||||
store::DeleteCollection {
|
||||
collection_path: &path,
|
||||
}
|
||||
.exec(&state.store)
|
||||
.await?;
|
||||
|
|
|
@ -3,6 +3,7 @@ use actix_web::{
|
|||
middleware::{Compress, Logger},
|
||||
App, HttpServer,
|
||||
};
|
||||
use std::time::Duration;
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[actix_web::main]
|
||||
|
@ -20,6 +21,7 @@ async fn main() -> Result<(), anyhow::Error> {
|
|||
|
||||
HttpServer::new(move || {
|
||||
let client = Client::builder()
|
||||
.timeout(Duration::from_secs(30))
|
||||
.header("User-Agent", "pict_rs_aggregator-v0.1.0")
|
||||
.finish();
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ where
|
|||
|
||||
let state_fut = web::Data::<crate::State>::extract(&req);
|
||||
let token_fut = Option::<web::Query<crate::Token>>::extract(&req);
|
||||
let path_fut = web::Path::<crate::AggregationPath>::extract(&req);
|
||||
let path_fut = web::Path::<crate::CollectionPath>::extract(&req);
|
||||
|
||||
let req = ServiceRequest::from_parts(req, pl)
|
||||
.map_err(|_| VerifyError)
|
||||
|
@ -136,7 +136,7 @@ where
|
|||
}
|
||||
|
||||
async fn verify(
|
||||
path: &crate::AggregationPath,
|
||||
path: &crate::CollectionPath,
|
||||
token: crate::Token,
|
||||
state: &crate::State,
|
||||
) -> Result<(), VerifyError> {
|
||||
|
|
76
src/store.rs
76
src/store.rs
|
@ -1,4 +1,4 @@
|
|||
use crate::{Aggregation, AggregationPath, Entry, EntryPath, Token};
|
||||
use crate::{Collection, CollectionPath, Entry, EntryPath, Token};
|
||||
use actix_web::web;
|
||||
use sled::{Db, Tree};
|
||||
use std::ops::Range;
|
||||
|
@ -9,19 +9,19 @@ pub(crate) struct Store {
|
|||
tree: Tree,
|
||||
}
|
||||
|
||||
pub(crate) struct CreateAggregation<'a> {
|
||||
pub(crate) aggregation_path: &'a AggregationPath,
|
||||
pub(crate) aggregation: &'a Aggregation,
|
||||
pub(crate) struct CreateCollection<'a> {
|
||||
pub(crate) collection_path: &'a CollectionPath,
|
||||
pub(crate) collection: &'a Collection,
|
||||
pub(crate) token: &'a Token,
|
||||
}
|
||||
|
||||
pub(crate) struct UpdateAggregation<'a> {
|
||||
pub(crate) aggregation_path: &'a AggregationPath,
|
||||
pub(crate) aggregation: &'a Aggregation,
|
||||
pub(crate) struct UpdateCollection<'a> {
|
||||
pub(crate) collection_path: &'a CollectionPath,
|
||||
pub(crate) collection: &'a Collection,
|
||||
}
|
||||
|
||||
pub(crate) struct DeleteAggregation<'a> {
|
||||
pub(crate) aggregation_path: &'a AggregationPath,
|
||||
pub(crate) struct DeleteCollection<'a> {
|
||||
pub(crate) collection_path: &'a CollectionPath,
|
||||
}
|
||||
|
||||
pub(crate) struct CreateEntry<'a> {
|
||||
|
@ -38,21 +38,21 @@ pub(crate) struct DeleteEntry<'a> {
|
|||
pub(crate) entry_path: &'a EntryPath,
|
||||
}
|
||||
|
||||
impl<'a> CreateAggregation<'a> {
|
||||
impl<'a> CreateCollection<'a> {
|
||||
pub(crate) async fn exec(self, store: &Store) -> Result<(), Error> {
|
||||
store.create_aggregation(self).await
|
||||
store.create_collection(self).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> UpdateAggregation<'a> {
|
||||
impl<'a> UpdateCollection<'a> {
|
||||
pub(crate) async fn exec(self, store: &Store) -> Result<(), Error> {
|
||||
store.update_aggregation(self).await
|
||||
store.update_collection(self).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DeleteAggregation<'a> {
|
||||
impl<'a> DeleteCollection<'a> {
|
||||
pub(crate) async fn exec(self, store: &Store) -> Result<(), Error> {
|
||||
store.delete_aggregation(self).await
|
||||
store.delete_collection(self).await
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,15 +77,15 @@ impl<'a> DeleteEntry<'a> {
|
|||
impl Store {
|
||||
pub(crate) fn new(db: &Db) -> Result<Self, sled::Error> {
|
||||
Ok(Store {
|
||||
tree: db.open_tree("aggregations")?,
|
||||
tree: db.open_tree("collections")?,
|
||||
})
|
||||
}
|
||||
|
||||
async fn create_aggregation(&self, config: CreateAggregation<'_>) -> Result<(), Error> {
|
||||
let aggregation_key = config.aggregation_path.key();
|
||||
let aggregation_value = serde_json::to_string(&config.aggregation)?;
|
||||
async fn create_collection(&self, config: CreateCollection<'_>) -> Result<(), Error> {
|
||||
let collection_key = config.collection_path.key();
|
||||
let collection_value = serde_json::to_string(&config.collection)?;
|
||||
|
||||
let token_key = config.aggregation_path.token_key();
|
||||
let token_key = config.collection_path.token_key();
|
||||
let token2 = config.token.clone();
|
||||
let token_value = serde_json::to_string(&web::block(move || token2.hash()).await?)?;
|
||||
|
||||
|
@ -93,7 +93,7 @@ impl Store {
|
|||
|
||||
web::block(move || {
|
||||
tree.transaction(move |tree| {
|
||||
tree.insert(aggregation_key.as_bytes(), aggregation_value.as_bytes())?;
|
||||
tree.insert(collection_key.as_bytes(), collection_value.as_bytes())?;
|
||||
tree.insert(token_key.as_bytes(), token_value.as_bytes())?;
|
||||
Ok(())
|
||||
})
|
||||
|
@ -103,22 +103,22 @@ impl Store {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_aggregation(&self, config: UpdateAggregation<'_>) -> Result<(), Error> {
|
||||
let aggregation_key = config.aggregation_path.key();
|
||||
let aggregation_value = serde_json::to_string(&config.aggregation)?;
|
||||
async fn update_collection(&self, config: UpdateCollection<'_>) -> Result<(), Error> {
|
||||
let collection_key = config.collection_path.key();
|
||||
let collection_value = serde_json::to_string(&config.collection)?;
|
||||
|
||||
let tree = self.tree.clone();
|
||||
|
||||
web::block(move || tree.insert(aggregation_key.as_bytes(), aggregation_value.as_bytes()))
|
||||
web::block(move || tree.insert(collection_key.as_bytes(), collection_value.as_bytes()))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_aggregation(&self, config: DeleteAggregation<'_>) -> Result<(), Error> {
|
||||
let entry_range = config.aggregation_path.entry_range();
|
||||
let token_key = config.aggregation_path.token_key();
|
||||
let aggregation_key = config.aggregation_path.key();
|
||||
async fn delete_collection(&self, config: DeleteCollection<'_>) -> Result<(), Error> {
|
||||
let entry_range = config.collection_path.entry_range();
|
||||
let token_key = config.collection_path.token_key();
|
||||
let collection_key = config.collection_path.key();
|
||||
|
||||
let tree = self.tree.clone();
|
||||
|
||||
|
@ -133,7 +133,7 @@ impl Store {
|
|||
tree.remove(key)?;
|
||||
}
|
||||
tree.remove(token_key.as_bytes())?;
|
||||
tree.remove(aggregation_key.as_bytes())?;
|
||||
tree.remove(collection_key.as_bytes())?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
|
@ -175,19 +175,19 @@ impl Store {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn aggregation(
|
||||
pub(crate) async fn collection(
|
||||
&self,
|
||||
path: &AggregationPath,
|
||||
) -> Result<crate::Aggregation, Error> {
|
||||
let aggregation_key = path.key();
|
||||
path: &CollectionPath,
|
||||
) -> Result<crate::Collection, Error> {
|
||||
let collection_key = path.key();
|
||||
let tree = self.tree.clone();
|
||||
|
||||
let opt = web::block(move || tree.get(aggregation_key.as_bytes())).await?;
|
||||
let opt = web::block(move || tree.get(collection_key.as_bytes())).await?;
|
||||
|
||||
match opt {
|
||||
Some(a) => {
|
||||
let aggregation = serde_json::from_slice(&a)?;
|
||||
Ok(aggregation)
|
||||
let collection = serde_json::from_slice(&a)?;
|
||||
Ok(collection)
|
||||
}
|
||||
None => Err(Error::NotFound),
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ impl Store {
|
|||
Ok(v)
|
||||
}
|
||||
|
||||
pub(crate) async fn token(&self, path: &AggregationPath) -> Result<crate::TokenStorage, Error> {
|
||||
pub(crate) async fn token(&self, path: &CollectionPath) -> Result<crate::TokenStorage, Error> {
|
||||
let token_key = path.token_key();
|
||||
let tree = self.tree.clone();
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
@use crate::{ui::ButtonKind, Aggregation, Entry, State, ValidToken};
|
||||
@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 uuid::Uuid;
|
||||
|
||||
@(aggregation: &Aggregation, aggregation_id: Uuid, entries: &[(Uuid, Entry)], token: &ValidToken, state: &State)
|
||||
@(collection: &Collection, collection_id: Uuid, entries: &[(Uuid, Entry)], token: &ValidToken, state: &State)
|
||||
|
||||
@:layout(state, "Edit Aggregation", None, {
|
||||
@:layout(state, "Edit Collection", None, {
|
||||
<script
|
||||
src="@state.statics_path(&file_upload_js.name)"
|
||||
type="text/javascript"
|
||||
|
@ -13,11 +13,11 @@
|
|||
}, {
|
||||
<section>
|
||||
<article class="content-group">
|
||||
<h3>Share Aggregation</h3>
|
||||
<h3>Share Collection</h3>
|
||||
</article>
|
||||
<article class="content-group">
|
||||
<a
|
||||
href="@state.public_aggregation_path(aggregation_id)"
|
||||
href="@state.public_collection_path(collection_id)"
|
||||
target="_blank"
|
||||
rel="noopen noreferer"
|
||||
>
|
||||
|
@ -27,18 +27,18 @@
|
|||
</section>
|
||||
<section>
|
||||
<article class="content-group">
|
||||
<h3>Edit Aggregation</h3>
|
||||
<h3>Edit Collection</h3>
|
||||
</article>
|
||||
<article class="content-group">
|
||||
<p class="subtitle"><a href="@state.edit_aggregation_path(aggregation_id, token)">Do not lose this link</a></p>
|
||||
<p class="subtitle"><a href="@state.edit_collection_path(collection_id, token)">Do not lose this link</a></p>
|
||||
</article>
|
||||
<article class="content-group">
|
||||
<form method="POST" action="@state.update_aggregation_path(aggregation_id, token)">
|
||||
@:text_input("title", Some("Title"), Some(&aggregation.title))
|
||||
@:text_area("description", Some("Description"), Some(&aggregation.description))
|
||||
<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">
|
||||
@:button("Update Aggregation", ButtonKind::Submit)
|
||||
@:button_link("Delete Aggregation", &state.delete_aggregation_path(aggregation_id, token), ButtonKind::Outline)
|
||||
@:button("Update Collection", ButtonKind::Submit)
|
||||
@:button_link("Delete Collection", &state.delete_collection_path(collection_id, token), ButtonKind::Outline)
|
||||
</div>
|
||||
</form>
|
||||
</article>
|
||||
|
@ -55,14 +55,14 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="edit-item">
|
||||
<form method="POST" action="@state.update_entry_path(aggregation_id, *id, token)">
|
||||
<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))
|
||||
<input type="hidden" name="filename" value="@entry.filename" />
|
||||
<input type="hidden" name="delete_token" value="@entry.delete_token" />
|
||||
<div class="button-space">
|
||||
@:button("Update Image", ButtonKind::Submit)
|
||||
@:button_link("Delete Image", &state.delete_entry_path(aggregation_id, *id, token), ButtonKind::Outline)
|
||||
@:button_link("Delete Image", &state.delete_entry_path(collection_id, *id, token), ButtonKind::Outline)
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -76,7 +76,7 @@
|
|||
<article>
|
||||
<form
|
||||
method="POST"
|
||||
action="@state.create_entry_path(aggregation_id, token)"
|
||||
action="@state.create_entry_path(collection_id, token)"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
<div class="content-group">
|
|
@ -3,19 +3,19 @@
|
|||
|
||||
@(state: &State)
|
||||
|
||||
@:layout(state, "Aggregation", None, {}, {
|
||||
@:layout(state, "Collection", None, {}, {
|
||||
<section>
|
||||
<article>
|
||||
<form method="POST" action="@state.create_aggregation_path()">
|
||||
<form method="POST" action="@state.create_collection_path()">
|
||||
<div class="content-group">
|
||||
<h3><legend>Create Aggregation</legend></h3>
|
||||
<h3><legend>Create Collection</legend></h3>
|
||||
</div>
|
||||
<div class="content-group">
|
||||
@:text_input("title", Some("Title"), None)
|
||||
@:text_area("description", Some("Description"), None)
|
||||
</div>
|
||||
<div class="content-group">
|
||||
@:button("Create Aggregation", ButtonKind::Submit)
|
||||
@:button("Create Collection", ButtonKind::Submit)
|
||||
</div>
|
||||
</form>
|
||||
</article>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
@if let Some(description) = description {
|
||||
<meta property="og:description" content="@description" />
|
||||
} else {
|
||||
<meta property="og:description" content="Aggregate and share images" />
|
||||
<meta property="og:description" content="Collect and share images" />
|
||||
}
|
||||
<meta property="og:type" content="website" />
|
||||
<link rel="shortcut icon" type="image/png" href="@state.statics_path(&favicon_ico.name)">
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<h3>Not Found</h3>
|
||||
</article>
|
||||
<article class="content-group">
|
||||
<p><a href="@state.create_aggregation_path()">Return Home</a></p>
|
||||
<p><a href="@state.create_collection_path()">Return Home</a></p>
|
||||
</article>
|
||||
</section>
|
||||
})
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@use crate::{Aggregation, Entry, State};
|
||||
@use crate::{Collection, Entry, State};
|
||||
@use super::{layout, image_preview};
|
||||
@use uuid::Uuid;
|
||||
|
||||
@(id: Uuid, aggregation: &Aggregation, entries: &[(Uuid, Entry)], state: &State)
|
||||
@(id: Uuid, collection: &Collection, entries: &[(Uuid, Entry)], state: &State)
|
||||
|
||||
@:layout(state, &aggregation.title, Some(&aggregation.description), {
|
||||
<meta property="og:url" content="@state.public_aggregation_path(id)" />
|
||||
@:layout(state, &collection.title, Some(&collection.description), {
|
||||
<meta property="og:url" content="@state.public_collection_path(id)" />
|
||||
@for (_, entry) in entries {
|
||||
<meta property="og:image" content="@state.image_path(entry)" />
|
||||
}
|
||||
|
@ -13,10 +13,10 @@
|
|||
<section>
|
||||
<article>
|
||||
<div class="content-group">
|
||||
<h3>@aggregation.title</h3>
|
||||
<h3>@collection.title</h3>
|
||||
</div>
|
||||
<div class="content-group">
|
||||
<p class="subtitle">@aggregation.description</p>
|
||||
<p class="subtitle">@collection.description</p>
|
||||
</div>
|
||||
</article>
|
||||
<ul>
|
Loading…
Reference in a new issue