Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 42 additions & 64 deletions src/routes/category.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ use askama::Template;
use askama_web::WebTemplate;
use axum::Form;
use axum::extract::Path;
use axum::response::{IntoResponse, Redirect};
use axum_extra::extract::CookieJar;
use serde::{Deserialize, Serialize};
use snafu::prelude::*;

use crate::database::category;
use crate::database::category::CategoryError;
use crate::database::content_folder::PathBreadcrumb;
use crate::extractors::normalized_path::*;
use crate::filesystem::FileSystemEntry;
use crate::state::flash_message::{OperationStatus, get_cookie};
use crate::state::flash_message::{
FallibleTemplate, FlashRedirect, FlashTemplate, OperationStatus, StatusCookie,
};
use crate::state::{AppStateContext, error::*};

#[derive(Clone, Debug, Deserialize, Serialize)]
Expand All @@ -26,73 +26,50 @@ pub struct CategoryForm {
pub struct NewCategoryTemplate {
/// Global application state
pub state: AppStateContext,
/// Error
pub error: Option<CategoryError>,
/// Default form with value
pub category_form: Option<CategoryForm>,
}

pub async fn new(
app_state_context: AppStateContext,
) -> Result<impl axum::response::IntoResponse, AppStateError> {
Ok(NewCategoryTemplate {
pub async fn new(app_state_context: AppStateContext) -> NewCategoryTemplate {
NewCategoryTemplate {
state: app_state_context,
category_form: None,
error: None,
})
}
}

pub async fn delete(
context: AppStateContext,
Path(id): Path<i32>,
jar: CookieJar,
) -> Result<impl axum::response::IntoResponse, AppStateError> {
let operation_status = match context.db.category().delete(id).await {
Ok(name) => OperationStatus {
success: true,
message: format!("The category {} has been successfully deleted", name),
},
Err(error) => OperationStatus {
success: false,
message: format!("{}", error),
},
) -> FlashRedirect {
let status = match context.db.category().delete(id).await {
Ok(name) => StatusCookie::success(
jar,
format!("The category {} has been successfully deleted", name),
),
Err(error) => StatusCookie::error(jar, error.to_string()),
};

let jar = operation_status.set_cookie(jar);

Ok((jar, Redirect::to("/categories")))
status.redirect("/categories")
}

pub async fn create(
context: AppStateContext,
jar: CookieJar,
Form(form): Form<CategoryForm>,
) -> Result<impl axum::response::IntoResponse, AppStateError> {
match context.db.category().create(&form).await {
Ok(created) => {
let operation_status = OperationStatus {
success: true,
message: format!(
"The category {} has been successfully created (ID {})",
created.name, created.id
),
};

let jar = operation_status.set_cookie(jar);

Ok((jar, Redirect::to("/").into_response()))
}
Err(error) => {
let operation_status = OperationStatus {
success: false,
message: format!("{}", error),
};

let jar = operation_status.set_cookie(jar);

Ok((jar, Redirect::to("/").into_response()))
}
}
) -> FlashRedirect {
let status = match context.db.category().create(&form).await {
Ok(created) => StatusCookie::success(
jar,
format!(
"The category {} has been successfully created (ID {})",
created.name, created.id
),
),
Err(error) => StatusCookie::error(jar, error.to_string()),
};

status.redirect("/")
}

#[derive(Template, WebTemplate)]
Expand All @@ -110,11 +87,17 @@ pub struct CategoryShowTemplate {
pub breadcrumbs: Vec<PathBreadcrumb>,
}

impl FallibleTemplate for CategoryShowTemplate {
fn with_optional_flash(&mut self, flash: Option<OperationStatus>) {
self.flash = flash;
}
}

pub async fn show(
context: AppStateContext,
Path(category_name): Path<String>,
jar: CookieJar,
) -> Result<impl IntoResponse, AppStateError> {
status: StatusCookie,
) -> Result<FlashTemplate<CategoryShowTemplate>, AppStateError> {
let categories = context.db.category();

let category = categories
Expand All @@ -130,18 +113,13 @@ pub async fn show(

let children = FileSystemEntry::from_content_folders(&category, &content_folders);

let (jar, operation_status) = get_cookie(jar);

let breadcrumbs = PathBreadcrumb::for_filesystem_path(category.name.as_str());

Ok((
jar,
CategoryShowTemplate {
category,
children,
state: context,
flash: operation_status,
breadcrumbs,
},
))
Ok(status.with_template(CategoryShowTemplate {
category,
children,
state: context,
flash: None,
breadcrumbs,
}))
}
66 changes: 33 additions & 33 deletions src/routes/content_folder.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use askama::Template;
use askama_web::WebTemplate;
use axum::Form;
use axum::response::{IntoResponse, Redirect};
use axum::response::Redirect;
use axum_extra::extract::CookieJar;
use camino::Utf8PathBuf;
use serde::{Deserialize, Serialize};
Expand All @@ -11,7 +11,9 @@ use crate::database::content_folder::PathBreadcrumb;
use crate::database::{category, content_folder};
use crate::extractors::folder_request::FolderRequest;
use crate::filesystem::FileSystemEntry;
use crate::state::flash_message::{OperationStatus, get_cookie};
use crate::state::flash_message::{
FallibleTemplate, FlashRedirect, FlashTemplate, OperationStatus, StatusCookie,
};
use crate::state::{AppStateContext, error::*};

#[derive(Clone, Debug, Deserialize, Serialize)]
Expand Down Expand Up @@ -39,31 +41,32 @@ pub struct ContentFolderShowTemplate {
pub flash: Option<OperationStatus>,
}

impl FallibleTemplate for ContentFolderShowTemplate {
fn with_optional_flash(&mut self, flash: Option<OperationStatus>) {
self.flash = flash;
}
}

pub async fn show(
context: AppStateContext,
folder: FolderRequest,
jar: CookieJar,
) -> Result<(CookieJar, ContentFolderShowTemplate), AppStateError> {
let (jar, operation_status) = get_cookie(jar);

Ok((
jar,
ContentFolderShowTemplate {
breadcrumbs: folder.breadcrumbs,
children: folder.children,
current_content_folder: folder.folder,
category: folder.category,
state: context,
flash: operation_status,
},
))
status: StatusCookie,
) -> FlashTemplate<ContentFolderShowTemplate> {
status.with_template(ContentFolderShowTemplate {
breadcrumbs: folder.breadcrumbs,
children: folder.children,
current_content_folder: folder.folder,
category: folder.category,
state: context,
flash: None,
})
}

pub async fn create(
context: AppStateContext,
jar: CookieJar,
Form(mut form): Form<ContentFolderForm>,
) -> Result<impl axum::response::IntoResponse, AppStateError> {
) -> Result<FlashRedirect, AppStateError> {
let categories = context.db.category();
let content_folders = context.db.content_folder();

Expand All @@ -86,18 +89,16 @@ pub async fn create(

// If name contains "/" returns an error
if form.name.contains("/") {
let operation_status = OperationStatus {
success: false,
message: format!(
let status = StatusCookie::error(
jar,
format!(
"Failed to create Folder, {} is not valid (it contains '/')",
form.name
),
};
let jar = operation_status.set_cookie(jar);
);

let uri = format!("/folders/{}{}", category.name, parent_path.into_string());

return Ok((jar, Redirect::to(uri.as_str()).into_response()));
return Ok(status.redirect(&uri));
}

// build final path with parent_path and path of form
Expand All @@ -111,19 +112,18 @@ pub async fn create(
.await
.context(IOSnafu)?;

let operation_status = OperationStatus {
success: true,
message: format!(
let status = StatusCookie::success(
jar,
format!(
"The folder {} has been successfully created (ID: {})",
created.name, created.id
),
};
);

let jar = operation_status.set_cookie(jar);
let uri = format!("/folders/{}{}", category.name, created.path);

Ok((jar, Redirect::to(uri.as_str()).into_response()))
Ok(status.redirect(&uri))
}
Err(_error) => Ok((jar, Redirect::to("/").into_response())),
// TODO: why don't we produce an error here?
Err(_error) => Ok((jar, Redirect::to("/"))),
}
}
34 changes: 17 additions & 17 deletions src/routes/index.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use askama::Template;
use askama_web::WebTemplate;
use axum_extra::extract::CookieJar;
use snafu::prelude::*;

// TUTORIAL: https://github.com/SeaQL/sea-orm/blob/master/examples/axum_example/
use crate::filesystem::FileSystemEntry;
use crate::state::flash_message::{OperationStatus, get_cookie};
use crate::state::flash_message::{FallibleTemplate, FlashTemplate, OperationStatus, StatusCookie};
use crate::state::{AppStateContext, error::*};

#[derive(Template, WebTemplate)]
Expand All @@ -19,6 +18,12 @@ pub struct IndexTemplate {
pub flash: Option<OperationStatus>,
}

impl FallibleTemplate for IndexTemplate {
fn with_optional_flash(&mut self, flash: Option<OperationStatus>) {
self.flash = flash;
}
}

#[derive(Template, WebTemplate)]
#[template(path = "upload.html")]
pub struct UploadTemplate {
Expand All @@ -31,21 +36,16 @@ pub struct UploadTemplate {
impl IndexTemplate {
pub async fn new(
context: AppStateContext,
jar: CookieJar,
) -> Result<(CookieJar, Self), AppStateError> {
status: StatusCookie,
) -> Result<FlashTemplate<Self>, AppStateError> {
let categories = context.db.category().list().await.context(CategorySnafu)?;
let children = FileSystemEntry::from_categories(&categories);

let (jar, operation_status) = get_cookie(jar);

Ok((
jar,
IndexTemplate {
state: context,
flash: operation_status,
children,
},
))
Ok(status.with_template(IndexTemplate {
state: context,
flash: None,
children,
}))
}
}

Expand All @@ -70,9 +70,9 @@ impl UploadTemplate {

pub async fn index(
context: AppStateContext,
jar: CookieJar,
) -> Result<(CookieJar, IndexTemplate), AppStateError> {
IndexTemplate::new(context, jar).await
status: StatusCookie,
) -> Result<FlashTemplate<IndexTemplate>, AppStateError> {
IndexTemplate::new(context, status).await
}

pub async fn upload(context: AppStateContext) -> Result<UploadTemplate, AppStateError> {
Expand Down
Loading