Skip to content

Commit b60ed60

Browse files
committed
refactor: Separate StatusCookie and OperationStatus
1 parent 62c810f commit b60ed60

File tree

6 files changed

+292
-162
lines changed

6 files changed

+292
-162
lines changed

src/routes/category.rs

Lines changed: 42 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ use askama::Template;
22
use askama_web::WebTemplate;
33
use axum::Form;
44
use axum::extract::Path;
5-
use axum::response::{IntoResponse, Redirect};
65
use axum_extra::extract::CookieJar;
76
use serde::{Deserialize, Serialize};
87
use snafu::prelude::*;
98

109
use crate::database::category;
11-
use crate::database::category::CategoryError;
1210
use crate::database::content_folder::PathBreadcrumb;
1311
use crate::extractors::normalized_path::*;
1412
use crate::filesystem::FileSystemEntry;
15-
use crate::state::flash_message::{OperationStatus, get_cookie};
13+
use crate::state::flash_message::{
14+
FallibleTemplate, FlashRedirect, FlashTemplate, OperationStatus, StatusCookie,
15+
};
1616
use crate::state::{AppStateContext, error::*};
1717

1818
#[derive(Clone, Debug, Deserialize, Serialize)]
@@ -26,73 +26,50 @@ pub struct CategoryForm {
2626
pub struct NewCategoryTemplate {
2727
/// Global application state
2828
pub state: AppStateContext,
29-
/// Error
30-
pub error: Option<CategoryError>,
3129
/// Default form with value
3230
pub category_form: Option<CategoryForm>,
3331
}
3432

35-
pub async fn new(
36-
app_state_context: AppStateContext,
37-
) -> Result<impl axum::response::IntoResponse, AppStateError> {
38-
Ok(NewCategoryTemplate {
33+
pub async fn new(app_state_context: AppStateContext) -> NewCategoryTemplate {
34+
NewCategoryTemplate {
3935
state: app_state_context,
4036
category_form: None,
41-
error: None,
42-
})
37+
}
4338
}
4439

4540
pub async fn delete(
4641
context: AppStateContext,
4742
Path(id): Path<i32>,
4843
jar: CookieJar,
49-
) -> Result<impl axum::response::IntoResponse, AppStateError> {
50-
let operation_status = match context.db.category().delete(id).await {
51-
Ok(name) => OperationStatus {
52-
success: true,
53-
message: format!("The category {} has been successfully deleted", name),
54-
},
55-
Err(error) => OperationStatus {
56-
success: false,
57-
message: format!("{}", error),
58-
},
44+
) -> FlashRedirect {
45+
let status = match context.db.category().delete(id).await {
46+
Ok(name) => StatusCookie::success(
47+
jar,
48+
format!("The category {} has been successfully deleted", name),
49+
),
50+
Err(error) => StatusCookie::error(jar, error.to_string()),
5951
};
6052

61-
let jar = operation_status.set_cookie(jar);
62-
63-
Ok((jar, Redirect::to("/categories")))
53+
status.redirect("/categories")
6454
}
6555

6656
pub async fn create(
6757
context: AppStateContext,
6858
jar: CookieJar,
6959
Form(form): Form<CategoryForm>,
70-
) -> Result<impl axum::response::IntoResponse, AppStateError> {
71-
match context.db.category().create(&form).await {
72-
Ok(created) => {
73-
let operation_status = OperationStatus {
74-
success: true,
75-
message: format!(
76-
"The category {} has been successfully created (ID {})",
77-
created.name, created.id
78-
),
79-
};
80-
81-
let jar = operation_status.set_cookie(jar);
82-
83-
Ok((jar, Redirect::to("/").into_response()))
84-
}
85-
Err(error) => {
86-
let operation_status = OperationStatus {
87-
success: false,
88-
message: format!("{}", error),
89-
};
90-
91-
let jar = operation_status.set_cookie(jar);
92-
93-
Ok((jar, Redirect::to("/").into_response()))
94-
}
95-
}
60+
) -> FlashRedirect {
61+
let status = match context.db.category().create(&form).await {
62+
Ok(created) => StatusCookie::success(
63+
jar,
64+
format!(
65+
"The category {} has been successfully created (ID {})",
66+
created.name, created.id
67+
),
68+
),
69+
Err(error) => StatusCookie::error(jar, error.to_string()),
70+
};
71+
72+
status.redirect("/")
9673
}
9774

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

90+
impl FallibleTemplate for CategoryShowTemplate {
91+
fn with_optional_flash(&mut self, flash: Option<OperationStatus>) {
92+
self.flash = flash;
93+
}
94+
}
95+
11396
pub async fn show(
11497
context: AppStateContext,
11598
Path(category_name): Path<String>,
116-
jar: CookieJar,
117-
) -> Result<impl IntoResponse, AppStateError> {
99+
status: StatusCookie,
100+
) -> Result<FlashTemplate<CategoryShowTemplate>, AppStateError> {
118101
let categories = context.db.category();
119102

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

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

133-
let (jar, operation_status) = get_cookie(jar);
134-
135116
let breadcrumbs = PathBreadcrumb::for_filesystem_path(category.name.as_str());
136117

137-
Ok((
138-
jar,
139-
CategoryShowTemplate {
140-
category,
141-
children,
142-
state: context,
143-
flash: operation_status,
144-
breadcrumbs,
145-
},
146-
))
118+
Ok(status.with_template(CategoryShowTemplate {
119+
category,
120+
children,
121+
state: context,
122+
flash: None,
123+
breadcrumbs,
124+
}))
147125
}

src/routes/content_folder.rs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use askama::Template;
22
use askama_web::WebTemplate;
33
use axum::Form;
4-
use axum::response::{IntoResponse, Redirect};
4+
use axum::response::Redirect;
55
use axum_extra::extract::CookieJar;
66
use camino::Utf8PathBuf;
77
use serde::{Deserialize, Serialize};
@@ -11,7 +11,9 @@ use crate::database::content_folder::PathBreadcrumb;
1111
use crate::database::{category, content_folder};
1212
use crate::extractors::folder_request::FolderRequest;
1313
use crate::filesystem::FileSystemEntry;
14-
use crate::state::flash_message::{OperationStatus, get_cookie};
14+
use crate::state::flash_message::{
15+
FallibleTemplate, FlashRedirect, FlashTemplate, OperationStatus, StatusCookie,
16+
};
1517
use crate::state::{AppStateContext, error::*};
1618

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

44+
impl FallibleTemplate for ContentFolderShowTemplate {
45+
fn with_optional_flash(&mut self, flash: Option<OperationStatus>) {
46+
self.flash = flash;
47+
}
48+
}
49+
4250
pub async fn show(
4351
context: AppStateContext,
4452
folder: FolderRequest,
45-
jar: CookieJar,
46-
) -> Result<(CookieJar, ContentFolderShowTemplate), AppStateError> {
47-
let (jar, operation_status) = get_cookie(jar);
48-
49-
Ok((
50-
jar,
51-
ContentFolderShowTemplate {
52-
breadcrumbs: folder.breadcrumbs,
53-
children: folder.children,
54-
current_content_folder: folder.folder,
55-
category: folder.category,
56-
state: context,
57-
flash: operation_status,
58-
},
59-
))
53+
status: StatusCookie,
54+
) -> FlashTemplate<ContentFolderShowTemplate> {
55+
status.with_template(ContentFolderShowTemplate {
56+
breadcrumbs: folder.breadcrumbs,
57+
children: folder.children,
58+
current_content_folder: folder.folder,
59+
category: folder.category,
60+
state: context,
61+
flash: None,
62+
})
6063
}
6164

6265
pub async fn create(
6366
context: AppStateContext,
6467
jar: CookieJar,
6568
Form(mut form): Form<ContentFolderForm>,
66-
) -> Result<impl axum::response::IntoResponse, AppStateError> {
69+
) -> Result<FlashRedirect, AppStateError> {
6770
let categories = context.db.category();
6871
let content_folders = context.db.content_folder();
6972

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

8790
// If name contains "/" returns an error
8891
if form.name.contains("/") {
89-
let operation_status = OperationStatus {
90-
success: false,
91-
message: format!(
92+
let status = StatusCookie::error(
93+
jar,
94+
format!(
9295
"Failed to create Folder, {} is not valid (it contains '/')",
9396
form.name
9497
),
95-
};
96-
let jar = operation_status.set_cookie(jar);
98+
);
9799

98100
let uri = format!("/folders/{}{}", category.name, parent_path.into_string());
99-
100-
return Ok((jar, Redirect::to(uri.as_str()).into_response()));
101+
return Ok(status.redirect(&uri));
101102
}
102103

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

114-
let operation_status = OperationStatus {
115-
success: true,
116-
message: format!(
115+
let status = StatusCookie::success(
116+
jar,
117+
format!(
117118
"The folder {} has been successfully created (ID: {})",
118119
created.name, created.id
119120
),
120-
};
121+
);
121122

122-
let jar = operation_status.set_cookie(jar);
123123
let uri = format!("/folders/{}{}", category.name, created.path);
124-
125-
Ok((jar, Redirect::to(uri.as_str()).into_response()))
124+
Ok(status.redirect(&uri))
126125
}
127-
Err(_error) => Ok((jar, Redirect::to("/").into_response())),
126+
// TODO: why don't we produce an error here?
127+
Err(_error) => Ok((jar, Redirect::to("/"))),
128128
}
129129
}

src/routes/index.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use askama::Template;
22
use askama_web::WebTemplate;
3-
use axum_extra::extract::CookieJar;
43
use snafu::prelude::*;
54

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

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

21+
impl FallibleTemplate for IndexTemplate {
22+
fn with_optional_flash(&mut self, flash: Option<OperationStatus>) {
23+
self.flash = flash;
24+
}
25+
}
26+
2227
#[derive(Template, WebTemplate)]
2328
#[template(path = "upload.html")]
2429
pub struct UploadTemplate {
@@ -31,21 +36,16 @@ pub struct UploadTemplate {
3136
impl IndexTemplate {
3237
pub async fn new(
3338
context: AppStateContext,
34-
jar: CookieJar,
35-
) -> Result<(CookieJar, Self), AppStateError> {
39+
status: StatusCookie,
40+
) -> Result<FlashTemplate<Self>, AppStateError> {
3641
let categories = context.db.category().list().await.context(CategorySnafu)?;
3742
let children = FileSystemEntry::from_categories(&categories);
3843

39-
let (jar, operation_status) = get_cookie(jar);
40-
41-
Ok((
42-
jar,
43-
IndexTemplate {
44-
state: context,
45-
flash: operation_status,
46-
children,
47-
},
48-
))
44+
Ok(status.with_template(IndexTemplate {
45+
state: context,
46+
flash: None,
47+
children,
48+
}))
4949
}
5050
}
5151

@@ -70,9 +70,9 @@ impl UploadTemplate {
7070

7171
pub async fn index(
7272
context: AppStateContext,
73-
jar: CookieJar,
74-
) -> Result<(CookieJar, IndexTemplate), AppStateError> {
75-
IndexTemplate::new(context, jar).await
73+
status: StatusCookie,
74+
) -> Result<FlashTemplate<IndexTemplate>, AppStateError> {
75+
IndexTemplate::new(context, status).await
7676
}
7777

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

0 commit comments

Comments
 (0)