From aa04ca4e8269794eead996876cc3d8adba014e05 Mon Sep 17 00:00:00 2001 From: gabatxo1312 Date: Mon, 1 Dec 2025 14:51:34 +0100 Subject: [PATCH] Add category index on homepage --- src/database/category.rs | 20 +++- src/lib.rs | 2 + src/routes/category.rs | 30 ++++++ src/routes/index.rs | 39 +++++++- templates/categories/dropdown_actions.html | 8 ++ templates/categories/show.html | 28 ++++++ templates/index.html | 102 ++++++++------------- templates/layouts/file_system_base.html | 57 ++++++++++++ templates/menus/header.html | 2 +- templates/upload.html | 71 ++++++++++++++ 10 files changed, 289 insertions(+), 70 deletions(-) create mode 100644 templates/categories/dropdown_actions.html create mode 100644 templates/categories/show.html create mode 100644 templates/layouts/file_system_base.html create mode 100644 templates/upload.html diff --git a/src/database/category.rs b/src/database/category.rs index 4f66e4b..d6a6583 100644 --- a/src/database/category.rs +++ b/src/database/category.rs @@ -45,7 +45,9 @@ pub enum CategoryError { #[snafu(display("Database error"))] DB { source: sea_orm::DbErr }, #[snafu(display("The category (ID: {id}) does not exist"))] - NotFound { id: i32 }, + IDNotFound { id: i32 }, + #[snafu(display("The category (Name: {name}) does not exist"))] + NameNotFound { name: String }, #[snafu(display("Failed to save the operation log"))] Logger { source: LoggerError }, } @@ -71,6 +73,20 @@ impl CategoryOperator { .context(DBSnafu) } + /// Find one category by Name + pub async fn find_by_name(&self, name: String) -> Result { + let category = Entity::find() + .filter(Column::Name.contains(name.clone())) + .one(&self.state.database) + .await + .context(DBSnafu)?; + + match category { + Some(category) => Ok(category), + None => Err(CategoryError::NameNotFound { name }), + } + } + /// Delete a category pub async fn delete(&self, id: i32, user: Option) -> Result { let db = &self.state.database; @@ -101,7 +117,7 @@ impl CategoryOperator { Ok(category_clone.name) } - None => Err(CategoryError::NotFound { id }), + None => Err(CategoryError::IDNotFound { id }), } } diff --git a/src/lib.rs b/src/lib.rs index ad27452..00473d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,11 +20,13 @@ pub fn router(state: state::AppState) -> Router { Router::new() // Register dynamic routes .route("/", get(routes::index::index)) + .route("/upload", get(routes::index::upload)) .route("/progress/{view_request}", get(routes::progress::progress)) .route("/categories", get(routes::category::index)) .route("/categories", post(routes::category::create)) .route("/categories/new", get(routes::category::new)) .route("/categories/{id}/delete", get(routes::category::delete)) + .route("/folders/{category_id}", get(routes::category::show)) .route("/logs", get(routes::logs::index)) // Register static assets routes .nest("/assets", static_router()) diff --git a/src/routes/category.rs b/src/routes/category.rs index ca0b88d..2459d50 100644 --- a/src/routes/category.rs +++ b/src/routes/category.rs @@ -144,3 +144,33 @@ pub async fn index( }, )) } + +#[derive(Template, WebTemplate)] +#[template(path = "categories/show.html")] +pub struct CategoryShowTemplate { + /// Global application state + pub state: AppStateContext, + /// Logged-in user. + pub user: Option, + /// Category + category: category::Model, +} + +pub async fn show( + State(app_state): State, + user: Option, + Path(category_name): Path, +) -> Result { + let app_state_context = app_state.context().await?; + + let category: category::Model = CategoryOperator::new(app_state.clone(), user.clone()) + .find_by_name(category_name.to_string()) + .await + .context(CategorySnafu)?; + + Ok(CategoryShowTemplate { + category, + state: app_state_context, + user, + }) +} diff --git a/src/routes/index.rs b/src/routes/index.rs index 62e83d4..7ce03fc 100644 --- a/src/routes/index.rs +++ b/src/routes/index.rs @@ -4,13 +4,24 @@ use axum::extract::State; use snafu::prelude::*; // TUTORIAL: https://github.com/SeaQL/sea-orm/blob/master/examples/axum_example/ -use crate::database::category::CategoryOperator; +use crate::database::category::{self, CategoryOperator}; use crate::extractors::user::User; use crate::state::{AppState, AppStateContext, error::*}; #[derive(Template, WebTemplate)] #[template(path = "index.html")] pub struct IndexTemplate { + /// Global application state (errors/warnings) + pub state: AppStateContext, + /// Logged-in user. + pub user: Option, + /// Categories + pub categories: Vec, +} + +#[derive(Template, WebTemplate)] +#[template(path = "upload.html")] +pub struct UploadTemplate { /// Global application state (errors/warnings) pub state: AppStateContext, /// Logged-in user. @@ -20,6 +31,23 @@ pub struct IndexTemplate { } impl IndexTemplate { + pub async fn new(app_state: AppState, user: Option) -> Result { + let app_state_context = app_state.context().await?; + + let categories = CategoryOperator::new(app_state.clone(), user.clone()) + .list() + .await + .context(CategorySnafu)?; + + Ok(IndexTemplate { + state: app_state_context, + user, + categories, + }) + } +} + +impl UploadTemplate { pub async fn new(app_state: AppState, user: Option) -> Result { let categories: Vec = CategoryOperator::new(app_state.clone(), user.clone()) .list() @@ -29,7 +57,7 @@ impl IndexTemplate { .map(|x| x.name) .collect(); - Ok(IndexTemplate { + Ok(UploadTemplate { state: app_state.context().await?, user, categories, @@ -43,3 +71,10 @@ pub async fn index( ) -> Result { IndexTemplate::new(app_state, user).await } + +pub async fn upload( + State(app_state): State, + user: Option, +) -> Result { + UploadTemplate::new(app_state, user).await +} diff --git a/templates/categories/dropdown_actions.html b/templates/categories/dropdown_actions.html new file mode 100644 index 0000000..ce2adc1 --- /dev/null +++ b/templates/categories/dropdown_actions.html @@ -0,0 +1,8 @@ + diff --git a/templates/categories/show.html b/templates/categories/show.html new file mode 100644 index 0000000..07db9fa --- /dev/null +++ b/templates/categories/show.html @@ -0,0 +1,28 @@ +{% extends "layouts/file_system_base.html" %} + +{% block breadcrumb %} + + + +{% endblock %} + +{% block folder_title %} + {{ category.name }} +{% endblock%} + +{% block additional_buttons %} + + Go up + +{% endblock %} + +{% block system_list %} +{% endblock %} diff --git a/templates/index.html b/templates/index.html index 05a8542..c58fe6f 100755 --- a/templates/index.html +++ b/templates/index.html @@ -1,71 +1,43 @@ -{% extends "base.html" %} - -{% block main %} -
-

Download files

- - {% if state.free_space.free_space_percent < 5 %} -
- The disks are almost full : {{ state.free_space.free_space_gib }} GiB left -
- {% endif %} +{% extends "layouts/file_system_base.html" %} + +{% block breadcrumb %} + +{% endblock %} -
-
-
-
- -
Choose the type of content you want to download.
- +{% block folder_title %} + All categories +{% endblock%} + +{% block actions_buttons %} + {% include "categories/dropdown_actions.html" %} +{% endblock actions_buttons %} + +{% block system_list %} + {% for category in categories %} +
  • + +
    +
    +
    + +
    + {{ category.name }} {{ category.path }} +
    +
    -
    -
  • - -
    -
    - {% include "sources/magnet.html" %} -
    - -
    -
    -

    OR

    +
    +

    + +

    +
    + + {% endfor %} +{% endblock %} -
    - {% include "sources/torrent.html" %} -
    -
    - -
    - -
    - - - {% if categories.len() == 0 %} - - - {% endif %} -
    -{% endblock %} diff --git a/templates/layouts/file_system_base.html b/templates/layouts/file_system_base.html new file mode 100644 index 0000000..01a8c72 --- /dev/null +++ b/templates/layouts/file_system_base.html @@ -0,0 +1,57 @@ +{% extends "base.html" %} + +{% block main %} +
    +

    File System

    + + {% block alert_message %}{% endblock alert_message %} + + {% if state.free_space.free_space_percent < 5 %} +
    + The disks are almost full : {{ state.free_space.free_space_gib }} GiB left +
    + {% endif %} + +
    +
    + +
    + +
    + {% block actions_buttons %}{% endblock actions_buttons %} +
    +
    + +
    +
    +
    +
    +

    {% block folder_title %}{% endblock folder_title %}

    {% block additional_buttons %}{% endblock additional_buttons %}
    +
    + +
      + {% block system_list %}{% endblock system_list %} +
    +
    +
    +
    +
    + + + +{% endblock %} diff --git a/templates/menus/header.html b/templates/menus/header.html index 33071ae..e59b6f0 100755 --- a/templates/menus/header.html +++ b/templates/menus/header.html @@ -33,7 +33,7 @@ - + Download new torrent diff --git a/templates/upload.html b/templates/upload.html new file mode 100644 index 0000000..05a8542 --- /dev/null +++ b/templates/upload.html @@ -0,0 +1,71 @@ +{% extends "base.html" %} + +{% block main %} +
    +

    Download files

    + + {% if state.free_space.free_space_percent < 5 %} +
    + The disks are almost full : {{ state.free_space.free_space_gib }} GiB left +
    + {% endif %} + +
    +
    +
    +
    + +
    Choose the type of content you want to download.
    + +
    +
    +
    + +
    +
    + {% include "sources/magnet.html" %} +
    + +
    +
    +

    OR

    +
    +
    + +
    + {% include "sources/torrent.html" %} +
    +
    + +
    + +
    +
    + + {% if categories.len() == 0 %} + + + + {% endif %} +
    +{% endblock %}