From 4301f1dbabffbc8105c91f13f28b016a6f23c954 Mon Sep 17 00:00:00 2001 From: lonelyhentxi Date: Wed, 30 Apr 2025 01:59:14 +0800 Subject: [PATCH] feature: add subscription manage --- Cargo.lock | 2 + apps/proxy/.whistle/rules/files/0.konobangu | 3 +- apps/recorder/Cargo.toml | 10 +- apps/recorder/src/auth/oidc.rs | 5 +- apps/recorder/src/migrations/defs.rs | 16 +- .../src/migrations/m20220101_000001_init.rs | 14 +- .../m20240224_082543_add_downloads.rs | 4 +- ...240225_060853_subscriber_add_downloader.rs | 3 +- .../src/migrations/m20241231_000001_auth.rs | 4 +- apps/recorder/src/models/auth.rs | 4 +- apps/recorder/src/models/bangumi.rs | 4 +- apps/recorder/src/models/downloaders.rs | 4 +- apps/recorder/src/models/downloads.rs | 4 +- apps/recorder/src/models/episodes.rs | 4 +- apps/recorder/src/models/subscribers.rs | 6 +- apps/recorder/src/models/subscriptions.rs | 4 +- apps/webui/components.json | 10 +- apps/webui/package.json | 2 + .../components/layout/app-icon.tsx | 4 +- .../components/layout/app-layout.tsx | 14 +- .../components/layout/app-not-found.tsx | 0 .../components/layout/app-sidebar.tsx | 4 +- .../components/layout/app-skeleton.tsx | 0 .../components/layout/nav-main.tsx | 4 +- .../components/layout/nav-projects.tsx | 4 +- .../components/layout/nav-user.tsx | 10 +- .../{views => }/components/ui/accordion.tsx | 2 +- .../components/ui/alert-dialog.tsx | 4 +- .../src/{views => }/components/ui/alert.tsx | 2 +- .../components/ui/aspect-ratio.tsx | 0 .../src/{views => }/components/ui/avatar.tsx | 2 +- .../src/{views => }/components/ui/badge.tsx | 2 +- .../{views => }/components/ui/breadcrumb.tsx | 2 +- .../src/{views => }/components/ui/button.tsx | 2 +- .../{views => }/components/ui/calendar.tsx | 4 +- .../src/{views => }/components/ui/card.tsx | 2 +- .../{views => }/components/ui/carousel.tsx | 4 +- .../src/{views => }/components/ui/chart.tsx | 2 +- .../{views => }/components/ui/checkbox.tsx | 2 +- .../{views => }/components/ui/collapsible.tsx | 0 .../src/{views => }/components/ui/command.tsx | 4 +- .../components/ui/context-menu.tsx | 2 +- .../ui/data-table-column-header.tsx | 67 ++ .../components/ui/data-table-pagination.tsx | 109 +++ .../components/ui/data-table-row-actions.tsx | 70 ++ .../components/ui/data-table-view-options.tsx | 59 ++ .../src/{views => }/components/ui/dialog.tsx | 2 +- .../src/{views => }/components/ui/drawer.tsx | 2 +- .../components/ui/dropdown-menu.tsx | 2 +- .../src/{views => }/components/ui/form.tsx | 4 +- .../{views => }/components/ui/hover-card.tsx | 2 +- .../src/{views => }/components/ui/image.tsx | 0 .../{views => }/components/ui/input-otp.tsx | 2 +- .../src/{views => }/components/ui/input.tsx | 2 +- .../src/{views => }/components/ui/label.tsx | 2 +- .../src/{views => }/components/ui/menubar.tsx | 2 +- .../components/ui/navigation-menu.tsx | 2 +- .../{views => }/components/ui/pagination.tsx | 4 +- .../src/{views => }/components/ui/popover.tsx | 2 +- .../{views => }/components/ui/pro-link.tsx | 0 .../components/ui/progress-circle.tsx | 2 +- .../{views => }/components/ui/progress.tsx | 2 +- .../src/components/ui/query-error-view.tsx | 34 + .../{views => }/components/ui/radio-group.tsx | 2 +- .../{views => }/components/ui/resizable.tsx | 2 +- .../{views => }/components/ui/scroll-area.tsx | 2 +- .../src/{views => }/components/ui/select.tsx | 2 +- .../{views => }/components/ui/separator.tsx | 2 +- .../src/{views => }/components/ui/sheet.tsx | 2 +- .../src/{views => }/components/ui/sidebar.tsx | 16 +- .../{views => }/components/ui/skeleton.tsx | 2 +- .../src/{views => }/components/ui/slider.tsx | 2 +- .../src/{views => }/components/ui/sonner.tsx | 0 .../src/{views => }/components/ui/spinner.tsx | 2 +- .../src/{views => }/components/ui/switch.tsx | 2 +- .../src/{views => }/components/ui/table.tsx | 2 +- .../src/{views => }/components/ui/tabs.tsx | 2 +- .../{views => }/components/ui/textarea.tsx | 2 +- .../components/ui/toggle-group.tsx | 4 +- .../src/{views => }/components/ui/toggle.tsx | 2 +- .../src/{views => }/components/ui/tooltip.tsx | 2 +- .../src/infra/graphql/gql/fragment-masking.ts | 61 +- apps/webui/src/infra/graphql/gql/gql.ts | 41 +- apps/webui/src/infra/graphql/gql/graphql.ts | 388 +++------- apps/webui/src/infra/graphql/gql/index.ts | 4 +- apps/webui/src/infra/intl/context.ts | 10 + apps/webui/src/infra/intl/hooks.ts | 9 + apps/webui/src/infra/intl/intl.service.ts | 27 + apps/webui/src/infra/routes/traits.ts | 2 +- apps/webui/src/infra/routes/utils.ts | 2 +- apps/webui/src/main.tsx | 4 +- .../hooks/use-debounded-skeleton.ts | 40 ++ .../webui/src/presentation/hooks/use-event.ts | 18 + .../hooks/use-mobile.ts | 0 .../src/presentation/hooks/use-state-ref.ts | 28 + apps/webui/src/presentation/routeTree.gen.ts | 663 ++++++++++++++++++ .../{views => presentation}/routes/404.tsx | 2 +- .../{views => presentation}/routes/__root.tsx | 13 +- .../routes/_app/_explore/explore.tsx | 0 .../routes/_app/_explore/feed.tsx | 0 .../presentation/routes/_app/bangumi/-defs.ts | 0 .../routes/_app/bangumi/manage.tsx | 13 + .../routes/_app/bangumi/route.tsx | 8 + .../_app/playground/graphql-api.lazy.tsx | 0 .../routes/_app/playground/graphql-api.tsx | 2 +- .../routes/_app/playground/route.tsx | 0 .../routes/_app/route.tsx | 2 +- .../routes/_app/settings/downloader.tsx | 0 .../routes/_app/settings/route.tsx | 0 .../routes/_app/subscriptions/-defs.ts | 108 +++ .../routes/_app/subscriptions/create.tsx | 14 +- .../subscriptions/detail.$subscriptionId.tsx | 38 + .../subscriptions/edit.$subscriptionId.tsx} | 2 +- .../routes/_app/subscriptions/manage.tsx | 289 ++++++++ .../routes/_app/subscriptions/route.tsx | 0 .../{views => presentation}/routes/about.tsx | 0 .../routes/auth/oidc/callback.tsx | 4 +- .../routes/auth/sign-in.tsx | 0 .../routes/auth/sign-up.tsx | 0 .../{views => presentation}/routes/index.tsx | 4 +- .../routes}/routeTree.gen.ts | 189 ++++- .../{views => presentation}/utils/index.ts | 0 .../routes/_app/subscriptions/manage.tsx | 218 ------ apps/webui/tsr.config.json | 4 +- biome.json | 17 +- dev.kdl | 9 +- justfile | 8 +- pnpm-lock.yaml | 185 ++++- 128 files changed, 2286 insertions(+), 740 deletions(-) rename apps/webui/src/{views => }/components/layout/app-icon.tsx (91%) rename apps/webui/src/{views => }/components/layout/app-layout.tsx (94%) rename apps/webui/src/{views => }/components/layout/app-not-found.tsx (100%) rename apps/webui/src/{views => }/components/layout/app-sidebar.tsx (95%) rename apps/webui/src/{views => }/components/layout/app-skeleton.tsx (100%) rename apps/webui/src/{views => }/components/layout/nav-main.tsx (97%) rename apps/webui/src/{views => }/components/layout/nav-projects.tsx (96%) rename apps/webui/src/{views => }/components/layout/nav-user.tsx (94%) rename apps/webui/src/{views => }/components/ui/accordion.tsx (97%) rename apps/webui/src/{views => }/components/ui/alert-dialog.tsx (97%) rename apps/webui/src/{views => }/components/ui/alert.tsx (97%) rename apps/webui/src/{views => }/components/ui/aspect-ratio.tsx (100%) rename apps/webui/src/{views => }/components/ui/avatar.tsx (96%) rename apps/webui/src/{views => }/components/ui/badge.tsx (97%) rename apps/webui/src/{views => }/components/ui/breadcrumb.tsx (98%) rename apps/webui/src/{views => }/components/ui/button.tsx (97%) rename apps/webui/src/{views => }/components/ui/calendar.tsx (96%) rename apps/webui/src/{views => }/components/ui/card.tsx (97%) rename apps/webui/src/{views => }/components/ui/carousel.tsx (98%) rename apps/webui/src/{views => }/components/ui/chart.tsx (99%) rename apps/webui/src/{views => }/components/ui/checkbox.tsx (96%) rename apps/webui/src/{views => }/components/ui/collapsible.tsx (100%) rename apps/webui/src/{views => }/components/ui/command.tsx (98%) rename apps/webui/src/{views => }/components/ui/context-menu.tsx (99%) create mode 100644 apps/webui/src/components/ui/data-table-column-header.tsx create mode 100644 apps/webui/src/components/ui/data-table-pagination.tsx create mode 100644 apps/webui/src/components/ui/data-table-row-actions.tsx create mode 100644 apps/webui/src/components/ui/data-table-view-options.tsx rename apps/webui/src/{views => }/components/ui/dialog.tsx (98%) rename apps/webui/src/{views => }/components/ui/drawer.tsx (98%) rename apps/webui/src/{views => }/components/ui/dropdown-menu.tsx (99%) rename apps/webui/src/{views => }/components/ui/form.tsx (97%) rename apps/webui/src/{views => }/components/ui/hover-card.tsx (97%) rename apps/webui/src/{views => }/components/ui/image.tsx (100%) rename apps/webui/src/{views => }/components/ui/input-otp.tsx (98%) rename apps/webui/src/{views => }/components/ui/input.tsx (95%) rename apps/webui/src/{views => }/components/ui/label.tsx (93%) rename apps/webui/src/{views => }/components/ui/menubar.tsx (99%) rename apps/webui/src/{views => }/components/ui/navigation-menu.tsx (99%) rename apps/webui/src/{views => }/components/ui/pagination.tsx (96%) rename apps/webui/src/{views => }/components/ui/popover.tsx (97%) rename apps/webui/src/{views => }/components/ui/pro-link.tsx (100%) rename apps/webui/src/{views => }/components/ui/progress-circle.tsx (98%) rename apps/webui/src/{views => }/components/ui/progress.tsx (94%) create mode 100644 apps/webui/src/components/ui/query-error-view.tsx rename apps/webui/src/{views => }/components/ui/radio-group.tsx (97%) rename apps/webui/src/{views => }/components/ui/resizable.tsx (97%) rename apps/webui/src/{views => }/components/ui/scroll-area.tsx (97%) rename apps/webui/src/{views => }/components/ui/select.tsx (99%) rename apps/webui/src/{views => }/components/ui/separator.tsx (94%) rename apps/webui/src/{views => }/components/ui/sheet.tsx (98%) rename apps/webui/src/{views => }/components/ui/sidebar.tsx (98%) rename apps/webui/src/{views => }/components/ui/skeleton.tsx (86%) rename apps/webui/src/{views => }/components/ui/slider.tsx (97%) rename apps/webui/src/{views => }/components/ui/sonner.tsx (100%) rename apps/webui/src/{views => }/components/ui/spinner.tsx (99%) rename apps/webui/src/{views => }/components/ui/switch.tsx (96%) rename apps/webui/src/{views => }/components/ui/table.tsx (98%) rename apps/webui/src/{views => }/components/ui/tabs.tsx (97%) rename apps/webui/src/{views => }/components/ui/textarea.tsx (94%) rename apps/webui/src/{views => }/components/ui/toggle-group.tsx (94%) rename apps/webui/src/{views => }/components/ui/toggle.tsx (97%) rename apps/webui/src/{views => }/components/ui/tooltip.tsx (97%) create mode 100644 apps/webui/src/infra/intl/context.ts create mode 100644 apps/webui/src/infra/intl/hooks.ts create mode 100644 apps/webui/src/infra/intl/intl.service.ts create mode 100644 apps/webui/src/presentation/hooks/use-debounded-skeleton.ts create mode 100644 apps/webui/src/presentation/hooks/use-event.ts rename apps/webui/src/{views => presentation}/hooks/use-mobile.ts (100%) create mode 100644 apps/webui/src/presentation/hooks/use-state-ref.ts create mode 100644 apps/webui/src/presentation/routeTree.gen.ts rename apps/webui/src/{views => presentation}/routes/404.tsx (64%) rename apps/webui/src/{views => presentation}/routes/__root.tsx (60%) rename apps/webui/src/{views => presentation}/routes/_app/_explore/explore.tsx (100%) rename apps/webui/src/{views => presentation}/routes/_app/_explore/feed.tsx (100%) create mode 100644 apps/webui/src/presentation/routes/_app/bangumi/-defs.ts create mode 100644 apps/webui/src/presentation/routes/_app/bangumi/manage.tsx create mode 100644 apps/webui/src/presentation/routes/_app/bangumi/route.tsx rename apps/webui/src/{views => presentation}/routes/_app/playground/graphql-api.lazy.tsx (100%) rename apps/webui/src/{views => presentation}/routes/_app/playground/graphql-api.tsx (80%) rename apps/webui/src/{views => presentation}/routes/_app/playground/route.tsx (100%) rename apps/webui/src/{views => presentation}/routes/_app/route.tsx (84%) rename apps/webui/src/{views => presentation}/routes/_app/settings/downloader.tsx (100%) rename apps/webui/src/{views => presentation}/routes/_app/settings/route.tsx (100%) create mode 100644 apps/webui/src/presentation/routes/_app/subscriptions/-defs.ts rename apps/webui/src/{views => presentation}/routes/_app/subscriptions/create.tsx (96%) create mode 100644 apps/webui/src/presentation/routes/_app/subscriptions/detail.$subscriptionId.tsx rename apps/webui/src/{views/routes/_app/subscriptions/edit.$subscription-id.tsx => presentation/routes/_app/subscriptions/edit.$subscriptionId.tsx} (89%) create mode 100644 apps/webui/src/presentation/routes/_app/subscriptions/manage.tsx rename apps/webui/src/{views => presentation}/routes/_app/subscriptions/route.tsx (100%) rename apps/webui/src/{views => presentation}/routes/about.tsx (100%) rename apps/webui/src/{views => presentation}/routes/auth/oidc/callback.tsx (96%) rename apps/webui/src/{views => presentation}/routes/auth/sign-in.tsx (100%) rename apps/webui/src/{views => presentation}/routes/auth/sign-up.tsx (100%) rename apps/webui/src/{views => presentation}/routes/index.tsx (66%) rename apps/webui/src/{views => presentation/routes}/routeTree.gen.ts (70%) rename apps/webui/src/{views => presentation}/utils/index.ts (100%) delete mode 100644 apps/webui/src/views/routes/_app/subscriptions/manage.tsx diff --git a/Cargo.lock b/Cargo.lock index b6a1375..0288bbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,6 +250,7 @@ dependencies = [ "async-stream", "async-trait", "base64 0.22.1", + "bigdecimal", "bytes", "chrono", "fast_chemail", @@ -273,6 +274,7 @@ dependencies = [ "static_assertions_next", "tempfile", "thiserror 1.0.69", + "time", ] [[package]] diff --git a/apps/proxy/.whistle/rules/files/0.konobangu b/apps/proxy/.whistle/rules/files/0.konobangu index 12852f7..b6e688e 100644 --- a/apps/proxy/.whistle/rules/files/0.konobangu +++ b/apps/proxy/.whistle/rules/files/0.konobangu @@ -5,6 +5,7 @@ } ``` -^https://konobangu.com/api*** reqHeaders://{x-forwarded.json} http://127.0.0.1:5001/api$1 +#^https://konobangu.com/api*** statusCode://500 +^https://konobangu.com/api*** reqHeaders://{x-forwarded.json} http://127.0.0.1:5001/api$1 ^https://konobangu.com/*** reqHeaders://{x-forwarded.json} http://127.0.0.1:5000/$1 excludeFilter://^https://konobangu.com/api*** ^wss://konobangu.com/*** reqHeaders://{x-forwarded.json} ws://127.0.0.1:5000/$1 excludeFilter://^wss://konobangu.com/api \ No newline at end of file diff --git a/apps/recorder/Cargo.toml b/apps/recorder/Cargo.toml index a78c0b4..df59072 100644 --- a/apps/recorder/Cargo.toml +++ b/apps/recorder/Cargo.toml @@ -72,7 +72,15 @@ jwt-authorizer = "0.15.0" log = "0.4" async-graphql = { version = "7", features = [] } async-graphql-axum = "7" -seaography = { version = "1.1" } +seaography = { version = "1.1", features = [ + "with-json", + "with-chrono", + "with-time", + "with-uuid", + "with-decimal", + "with-bigdecimal", + "with-postgres-array", +] } base64 = "0.22.1" tower = "0.5.2" tower-http = { version = "0.6", features = [ diff --git a/apps/recorder/src/auth/oidc.rs b/apps/recorder/src/auth/oidc.rs index 37e28d7..0820967 100644 --- a/apps/recorder/src/auth/oidc.rs +++ b/apps/recorder/src/auth/oidc.rs @@ -366,7 +366,10 @@ impl AuthServiceTrait for OidcAuthService { }) => crate::models::auth::Model::create_from_oidc(ctx, sub.to_string()).await, r => r, } - .map_err(|_| AuthError::FindAuthRecordError)?; + .map_err(|e| { + tracing::error!("Error finding auth record: {:?}", e); + AuthError::FindAuthRecordError + })?; Ok(AuthUserInfo { subscriber_auth, diff --git a/apps/recorder/src/migrations/defs.rs b/apps/recorder/src/migrations/defs.rs index f91bd6b..00381c6 100644 --- a/apps/recorder/src/migrations/defs.rs +++ b/apps/recorder/src/migrations/defs.rs @@ -2,7 +2,10 @@ use std::collections::HashSet; use async_trait::async_trait; use sea_orm::{DeriveIden, Statement}; -use sea_orm_migration::prelude::{extension::postgres::IntoTypeRef, *}; +use sea_orm_migration::{ + prelude::{extension::postgres::IntoTypeRef, *}, + schema::timestamp_with_time_zone, +}; use crate::migrations::extension::postgres::Type; @@ -144,6 +147,17 @@ macro_rules! create_postgres_enum_for_active_enum { }; } +pub fn timestamps_z(t: TableCreateStatement) -> TableCreateStatement { + let mut t = t; + t.col(timestamp_with_time_zone(GeneralIds::CreatedAt).default(Expr::current_timestamp())) + .col(timestamp_with_time_zone(GeneralIds::UpdatedAt).default(Expr::current_timestamp())) + .take() +} + +pub fn table_auto_z(name: T) -> TableCreateStatement { + timestamps_z(Table::create().table(name).if_not_exists().take()) +} + #[async_trait] pub trait CustomSchemaManagerExt { async fn create_postgres_auto_update_ts_fn(&self, col_name: &str) -> Result<(), DbErr>; diff --git a/apps/recorder/src/migrations/m20220101_000001_init.rs b/apps/recorder/src/migrations/m20220101_000001_init.rs index 67ab2e5..3062833 100644 --- a/apps/recorder/src/migrations/m20220101_000001_init.rs +++ b/apps/recorder/src/migrations/m20220101_000001_init.rs @@ -3,7 +3,7 @@ use sea_orm_migration::{prelude::*, schema::*}; use super::defs::{ Bangumi, CustomSchemaManagerExt, Episodes, GeneralIds, Subscribers, SubscriptionBangumi, - SubscriptionEpisode, Subscriptions, + SubscriptionEpisode, Subscriptions, table_auto_z, }; use crate::models::{ subscribers::SEED_SUBSCRIBER, @@ -22,7 +22,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(Subscribers::Table) + table_auto_z(Subscribers::Table) .col(pk_auto(Subscribers::Id)) .col(string(Subscribers::DisplayName)) .col(json_binary_null(Subscribers::BangumiConf)) @@ -57,7 +57,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(Subscriptions::Table) + table_auto_z(Subscriptions::Table) .col(pk_auto(Subscriptions::Id)) .col(string(Subscriptions::DisplayName)) .col(integer(Subscriptions::SubscriberId)) @@ -89,7 +89,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(Bangumi::Table) + table_auto_z(Bangumi::Table) .col(pk_auto(Bangumi::Id)) .col(text_null(Bangumi::MikanBangumiId)) .col(integer(Bangumi::SubscriberId)) @@ -156,7 +156,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(SubscriptionBangumi::Table) + table_auto_z(SubscriptionBangumi::Table) .col(pk_auto(SubscriptionBangumi::Id)) .col(integer(SubscriptionBangumi::SubscriberId)) .col(integer(SubscriptionBangumi::SubscriptionId)) @@ -206,7 +206,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(Episodes::Table) + table_auto_z(Episodes::Table) .col(pk_auto(Episodes::Id)) .col(text_null(Episodes::MikanEpisodeId)) .col(text(Episodes::RawName)) @@ -275,7 +275,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(SubscriptionEpisode::Table) + table_auto_z(SubscriptionEpisode::Table) .col(pk_auto(SubscriptionEpisode::Id)) .col(integer(SubscriptionEpisode::SubscriptionId)) .col(integer(SubscriptionEpisode::EpisodeId)) diff --git a/apps/recorder/src/migrations/m20240224_082543_add_downloads.rs b/apps/recorder/src/migrations/m20240224_082543_add_downloads.rs index 89e3cc9..fb3994d 100644 --- a/apps/recorder/src/migrations/m20240224_082543_add_downloads.rs +++ b/apps/recorder/src/migrations/m20240224_082543_add_downloads.rs @@ -23,7 +23,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(Downloaders::Table) + table_auto_z(Downloaders::Table) .col(pk_auto(Downloaders::Id)) .col(text(Downloaders::Endpoint)) .col(string_null(Downloaders::Username)) @@ -78,7 +78,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(Downloads::Table) + table_auto_z(Downloads::Table) .col(pk_auto(Downloads::Id)) .col(string(Downloads::RawName)) .col(string(Downloads::DisplayName)) diff --git a/apps/recorder/src/migrations/m20240225_060853_subscriber_add_downloader.rs b/apps/recorder/src/migrations/m20240225_060853_subscriber_add_downloader.rs index 6866bde..fa41e4a 100644 --- a/apps/recorder/src/migrations/m20240225_060853_subscriber_add_downloader.rs +++ b/apps/recorder/src/migrations/m20240225_060853_subscriber_add_downloader.rs @@ -1,5 +1,6 @@ use sea_orm_migration::{prelude::*, schema::*}; +use super::defs::table_auto_z; use crate::{ migrations::defs::{CustomSchemaManagerExt, Downloaders, GeneralIds, Subscribers}, models::downloaders::{DownloaderCategory, DownloaderCategoryEnum}, @@ -20,7 +21,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(Downloaders::Table) + table_auto_z(Downloaders::Table) .col(pk_auto(Downloaders::Id)) .col(text(Downloaders::Endpoint)) .col(string_null(Downloaders::Username)) diff --git a/apps/recorder/src/migrations/m20241231_000001_auth.rs b/apps/recorder/src/migrations/m20241231_000001_auth.rs index 5319172..1d8eb2b 100644 --- a/apps/recorder/src/migrations/m20241231_000001_auth.rs +++ b/apps/recorder/src/migrations/m20241231_000001_auth.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use sea_orm_migration::{prelude::*, schema::*}; -use super::defs::Auth; +use super::defs::{Auth, table_auto_z}; use crate::{ migrations::defs::{CustomSchemaManagerExt, GeneralIds, Subscribers}, models::{ @@ -26,7 +26,7 @@ impl MigrationTrait for Migration { manager .create_table( - table_auto(Auth::Table) + table_auto_z(Auth::Table) .col(pk_auto(Auth::Id)) .col(text(Auth::Pid)) .col(enumeration( diff --git a/apps/recorder/src/models/auth.rs b/apps/recorder/src/models/auth.rs index 6c63b6a..04d90da 100644 --- a/apps/recorder/src/models/auth.rs +++ b/apps/recorder/src/models/auth.rs @@ -24,9 +24,9 @@ pub enum AuthType { #[sea_orm(table_name = "auth")] pub struct Model { #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub created_at: DateTime, + pub created_at: DateTimeUtc, #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub updated_at: DateTime, + pub updated_at: DateTimeUtc, #[sea_orm(primary_key)] pub id: i32, #[sea_orm(unique)] diff --git a/apps/recorder/src/models/bangumi.rs b/apps/recorder/src/models/bangumi.rs index 4eb4a7b..7fdee2c 100644 --- a/apps/recorder/src/models/bangumi.rs +++ b/apps/recorder/src/models/bangumi.rs @@ -30,9 +30,9 @@ pub struct BangumiExtra { #[sea_orm(table_name = "bangumi")] pub struct Model { #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub created_at: DateTime, + pub created_at: DateTimeUtc, #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub updated_at: DateTime, + pub updated_at: DateTimeUtc, #[sea_orm(primary_key)] pub id: i32, pub mikan_bangumi_id: Option, diff --git a/apps/recorder/src/models/downloaders.rs b/apps/recorder/src/models/downloaders.rs index d51f971..f125dd2 100644 --- a/apps/recorder/src/models/downloaders.rs +++ b/apps/recorder/src/models/downloaders.rs @@ -23,9 +23,9 @@ pub enum DownloaderCategory { #[sea_orm(table_name = "downloaders")] pub struct Model { #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub created_at: DateTime, + pub created_at: DateTimeUtc, #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub updated_at: DateTime, + pub updated_at: DateTimeUtc, #[sea_orm(primary_key)] pub id: i32, pub category: DownloaderCategory, diff --git a/apps/recorder/src/models/downloads.rs b/apps/recorder/src/models/downloads.rs index d3d5416..9138508 100644 --- a/apps/recorder/src/models/downloads.rs +++ b/apps/recorder/src/models/downloads.rs @@ -39,9 +39,9 @@ pub enum DownloadMime { #[sea_orm(table_name = "downloads")] pub struct Model { #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub created_at: DateTime, + pub created_at: DateTimeUtc, #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub updated_at: DateTime, + pub updated_at: DateTimeUtc, #[sea_orm(primary_key)] pub id: i32, pub raw_name: String, diff --git a/apps/recorder/src/models/episodes.rs b/apps/recorder/src/models/episodes.rs index 97ca2ff..d9e4325 100644 --- a/apps/recorder/src/models/episodes.rs +++ b/apps/recorder/src/models/episodes.rs @@ -28,9 +28,9 @@ pub struct EpisodeExtra { #[sea_orm(table_name = "episodes")] pub struct Model { #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub created_at: DateTime, + pub created_at: DateTimeUtc, #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub updated_at: DateTime, + pub updated_at: DateTimeUtc, #[sea_orm(primary_key)] pub id: i32, #[sea_orm(indexed)] diff --git a/apps/recorder/src/models/subscribers.rs b/apps/recorder/src/models/subscribers.rs index 90ca205..f916674 100644 --- a/apps/recorder/src/models/subscribers.rs +++ b/apps/recorder/src/models/subscribers.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::{ app::AppContextTrait, - errors::app_error::{RecorderResult, RecorderError}, + errors::app_error::{RecorderError, RecorderResult}, }; pub const SEED_SUBSCRIBER: &str = "konobangu"; @@ -21,9 +21,9 @@ pub struct SubscriberBangumiConfig { #[sea_orm(table_name = "subscribers")] pub struct Model { #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub created_at: DateTime, + pub created_at: DateTimeUtc, #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub updated_at: DateTime, + pub updated_at: DateTimeUtc, #[sea_orm(primary_key)] pub id: i32, pub display_name: String, diff --git a/apps/recorder/src/models/subscriptions.rs b/apps/recorder/src/models/subscriptions.rs index 7c58a51..8f89275 100644 --- a/apps/recorder/src/models/subscriptions.rs +++ b/apps/recorder/src/models/subscriptions.rs @@ -44,9 +44,9 @@ pub enum SubscriptionCategory { #[sea_orm(table_name = "subscriptions")] pub struct Model { #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub created_at: DateTime, + pub created_at: DateTimeUtc, #[sea_orm(default_expr = "Expr::current_timestamp()")] - pub updated_at: DateTime, + pub updated_at: DateTimeUtc, #[sea_orm(primary_key)] pub id: i32, pub display_name: String, diff --git a/apps/webui/components.json b/apps/webui/components.json index 834db9e..19232a9 100644 --- a/apps/webui/components.json +++ b/apps/webui/components.json @@ -10,11 +10,11 @@ "cssVariables": true }, "aliases": { - "components": "@/views/components", - "utils": "@/views/utils", - "ui": "@/views/components/ui", - "lib": "@/views/lib", - "hooks": "@/views/hooks" + "components": "@/components", + "utils": "@/presentation/utils", + "ui": "@/components/ui", + "lib": "@/presentation/lib", + "hooks": "@/presentation/hooks" }, "iconLibrary": "lucide" } diff --git a/apps/webui/package.json b/apps/webui/package.json index 8679bb9..7ff6a35 100644 --- a/apps/webui/package.json +++ b/apps/webui/package.json @@ -49,6 +49,7 @@ "@rsbuild/plugin-react": "^1.2.0", "@tanstack/react-query": "^5.75.6", "@tanstack/react-router": "^1.112.13", + "@tanstack/react-table": "^8.21.3", "@tanstack/router-devtools": "^1.112.13", "arktype": "^2.1.6", "chart.js": "^4.4.8", @@ -84,6 +85,7 @@ "@graphql-codegen/client-preset": "^4.8.1", "@graphql-codegen/typescript": "^4.1.6", "@graphql-typed-document-node/core": "^3.2.0", + "@parcel/watcher": "^2.5.1", "@rsbuild/core": "^1.2.15", "@tailwindcss/postcss": "^4.0.9", "@tanstack/react-router": "^1.112.0", diff --git a/apps/webui/src/views/components/layout/app-icon.tsx b/apps/webui/src/components/layout/app-icon.tsx similarity index 91% rename from apps/webui/src/views/components/layout/app-icon.tsx rename to apps/webui/src/components/layout/app-icon.tsx index 1412256..9526392 100644 --- a/apps/webui/src/views/components/layout/app-icon.tsx +++ b/apps/webui/src/components/layout/app-icon.tsx @@ -2,9 +2,9 @@ import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, -} from '@/views/components/ui/sidebar'; +} from '@/components/ui/sidebar'; -import { Image } from '@/views/components/ui/image'; +import { Image } from '@/components/ui/image'; export function AppIcon() { return ( diff --git a/apps/webui/src/views/components/layout/app-layout.tsx b/apps/webui/src/components/layout/app-layout.tsx similarity index 94% rename from apps/webui/src/views/components/layout/app-layout.tsx rename to apps/webui/src/components/layout/app-layout.tsx index c16bdb7..501df77 100644 --- a/apps/webui/src/views/components/layout/app-layout.tsx +++ b/apps/webui/src/components/layout/app-layout.tsx @@ -1,6 +1,4 @@ -import type { RouteStateDataOption } from '@/infra/routes/traits'; -import type { RouteBreadcrumbItem } from '@/infra/routes/traits'; -import { AppSidebar } from '@/views/components/layout/app-sidebar'; +import { AppSidebar } from '@/components/layout/app-sidebar'; import { Breadcrumb, BreadcrumbItem, @@ -8,14 +6,16 @@ import { BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, -} from '@/views/components/ui/breadcrumb'; -import { Separator } from '@/views/components/ui/separator'; +} from '@/components/ui/breadcrumb'; +import { Separator } from '@/components/ui/separator'; import { SidebarInset, SidebarProvider, SidebarTrigger, -} from '@/views/components/ui/sidebar'; -import { cn } from '@/views/utils'; +} from '@/components/ui/sidebar'; +import type { RouteStateDataOption } from '@/infra/routes/traits'; +import type { RouteBreadcrumbItem } from '@/infra/routes/traits'; +import { cn } from '@/presentation/utils'; import { useMatches } from '@tanstack/react-router'; import { type DetailedHTMLProps, diff --git a/apps/webui/src/views/components/layout/app-not-found.tsx b/apps/webui/src/components/layout/app-not-found.tsx similarity index 100% rename from apps/webui/src/views/components/layout/app-not-found.tsx rename to apps/webui/src/components/layout/app-not-found.tsx diff --git a/apps/webui/src/views/components/layout/app-sidebar.tsx b/apps/webui/src/components/layout/app-sidebar.tsx similarity index 95% rename from apps/webui/src/views/components/layout/app-sidebar.tsx rename to apps/webui/src/components/layout/app-sidebar.tsx index f303f10..4d23a44 100644 --- a/apps/webui/src/views/components/layout/app-sidebar.tsx +++ b/apps/webui/src/components/layout/app-sidebar.tsx @@ -1,11 +1,11 @@ -import { AppNavMainData } from '@/infra/routes/nav'; import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarRail, -} from '@/views/components/ui/sidebar'; +} from '@/components/ui/sidebar'; +import { AppNavMainData } from '@/infra/routes/nav'; import type { ComponentPropsWithoutRef } from 'react'; import { AppIcon } from './app-icon'; import { NavMain } from './nav-main'; diff --git a/apps/webui/src/views/components/layout/app-skeleton.tsx b/apps/webui/src/components/layout/app-skeleton.tsx similarity index 100% rename from apps/webui/src/views/components/layout/app-skeleton.tsx rename to apps/webui/src/components/layout/app-skeleton.tsx diff --git a/apps/webui/src/views/components/layout/nav-main.tsx b/apps/webui/src/components/layout/nav-main.tsx similarity index 97% rename from apps/webui/src/views/components/layout/nav-main.tsx rename to apps/webui/src/components/layout/nav-main.tsx index b6bdb53..45209b0 100644 --- a/apps/webui/src/views/components/layout/nav-main.tsx +++ b/apps/webui/src/components/layout/nav-main.tsx @@ -6,7 +6,7 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger, -} from '@/views/components/ui/collapsible'; +} from '@/components/ui/collapsible'; import { SidebarGroup, SidebarGroupLabel, @@ -16,7 +16,7 @@ import { SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, -} from '@/views/components/ui/sidebar'; +} from '@/components/ui/sidebar'; import { useMatches } from '@tanstack/react-router'; import { ProLink, type ProLinkProps } from '../ui/pro-link'; diff --git a/apps/webui/src/views/components/layout/nav-projects.tsx b/apps/webui/src/components/layout/nav-projects.tsx similarity index 96% rename from apps/webui/src/views/components/layout/nav-projects.tsx rename to apps/webui/src/components/layout/nav-projects.tsx index 2aff406..0d7d745 100644 --- a/apps/webui/src/views/components/layout/nav-projects.tsx +++ b/apps/webui/src/components/layout/nav-projects.tsx @@ -16,7 +16,7 @@ import { DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, -} from '@/views/components/ui/dropdown-menu'; +} from '@/components/ui/dropdown-menu'; import { SidebarGroup, SidebarGroupLabel, @@ -25,7 +25,7 @@ import { SidebarMenuButton, SidebarMenuItem, useSidebar, -} from '@/views/components/ui/sidebar'; +} from '@/components/ui/sidebar'; import type { ComponentProps } from 'react'; export function NavProjects({ diff --git a/apps/webui/src/views/components/layout/nav-user.tsx b/apps/webui/src/components/layout/nav-user.tsx similarity index 94% rename from apps/webui/src/views/components/layout/nav-user.tsx rename to apps/webui/src/components/layout/nav-user.tsx index 5c2c452..f138ae2 100644 --- a/apps/webui/src/views/components/layout/nav-user.tsx +++ b/apps/webui/src/components/layout/nav-user.tsx @@ -9,11 +9,7 @@ import { Sparkles, } from 'lucide-react'; -import { - Avatar, - AvatarFallback, - AvatarImage, -} from '@/views/components/ui/avatar'; +import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { DropdownMenu, DropdownMenuContent, @@ -22,13 +18,13 @@ import { DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, -} from '@/views/components/ui/dropdown-menu'; +} from '@/components/ui/dropdown-menu'; import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar, -} from '@/views/components/ui/sidebar'; +} from '@/components/ui/sidebar'; export function NavUser({ user, diff --git a/apps/webui/src/views/components/ui/accordion.tsx b/apps/webui/src/components/ui/accordion.tsx similarity index 97% rename from apps/webui/src/views/components/ui/accordion.tsx rename to apps/webui/src/components/ui/accordion.tsx index e228043..64947a0 100644 --- a/apps/webui/src/views/components/ui/accordion.tsx +++ b/apps/webui/src/components/ui/accordion.tsx @@ -2,7 +2,7 @@ import * as AccordionPrimitive from "@radix-ui/react-accordion"; import { ChevronDownIcon } from "lucide-react"; import * as React from "react"; -import { cn } from "@/views/utils"; +import { cn } from "@/presentation/utils"; function Accordion({ ...props diff --git a/apps/webui/src/views/components/ui/alert-dialog.tsx b/apps/webui/src/components/ui/alert-dialog.tsx similarity index 97% rename from apps/webui/src/views/components/ui/alert-dialog.tsx rename to apps/webui/src/components/ui/alert-dialog.tsx index 03fddb0..b1ccb80 100644 --- a/apps/webui/src/views/components/ui/alert-dialog.tsx +++ b/apps/webui/src/components/ui/alert-dialog.tsx @@ -3,8 +3,8 @@ import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; import * as React from "react"; -import { buttonVariants } from "@/views/components/ui/button"; -import { cn } from "@/views/utils"; +import { buttonVariants } from "@/components/ui/button"; +import { cn } from "@/presentation/utils"; function AlertDialog({ ...props diff --git a/apps/webui/src/views/components/ui/alert.tsx b/apps/webui/src/components/ui/alert.tsx similarity index 97% rename from apps/webui/src/views/components/ui/alert.tsx rename to apps/webui/src/components/ui/alert.tsx index 6bc97f7..6ddb6ed 100644 --- a/apps/webui/src/views/components/ui/alert.tsx +++ b/apps/webui/src/components/ui/alert.tsx @@ -1,7 +1,7 @@ import { type VariantProps, cva } from "class-variance-authority"; import * as React from "react"; -import { cn } from "@/views/utils"; +import { cn } from "@/presentation/utils"; const alertVariants = cva( "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", diff --git a/apps/webui/src/views/components/ui/aspect-ratio.tsx b/apps/webui/src/components/ui/aspect-ratio.tsx similarity index 100% rename from apps/webui/src/views/components/ui/aspect-ratio.tsx rename to apps/webui/src/components/ui/aspect-ratio.tsx diff --git a/apps/webui/src/views/components/ui/avatar.tsx b/apps/webui/src/components/ui/avatar.tsx similarity index 96% rename from apps/webui/src/views/components/ui/avatar.tsx rename to apps/webui/src/components/ui/avatar.tsx index 3fab008..684c5ab 100644 --- a/apps/webui/src/views/components/ui/avatar.tsx +++ b/apps/webui/src/components/ui/avatar.tsx @@ -3,7 +3,7 @@ import * as AvatarPrimitive from "@radix-ui/react-avatar"; import * as React from "react"; -import { cn } from "@/views/utils"; +import { cn } from "@/presentation/utils"; function Avatar({ className, diff --git a/apps/webui/src/views/components/ui/badge.tsx b/apps/webui/src/components/ui/badge.tsx similarity index 97% rename from apps/webui/src/views/components/ui/badge.tsx rename to apps/webui/src/components/ui/badge.tsx index 68fc6bf..5b1b0a2 100644 --- a/apps/webui/src/views/components/ui/badge.tsx +++ b/apps/webui/src/components/ui/badge.tsx @@ -2,7 +2,7 @@ import { Slot } from "@radix-ui/react-slot"; import { type VariantProps, cva } from "class-variance-authority"; import * as React from "react"; -import { cn } from "@/views/utils"; +import { cn } from "@/presentation/utils"; const badgeVariants = cva( "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", diff --git a/apps/webui/src/views/components/ui/breadcrumb.tsx b/apps/webui/src/components/ui/breadcrumb.tsx similarity index 98% rename from apps/webui/src/views/components/ui/breadcrumb.tsx rename to apps/webui/src/components/ui/breadcrumb.tsx index 5d6339d..2a99cb2 100644 --- a/apps/webui/src/views/components/ui/breadcrumb.tsx +++ b/apps/webui/src/components/ui/breadcrumb.tsx @@ -2,7 +2,7 @@ import { Slot } from "@radix-ui/react-slot"; import { ChevronRight, MoreHorizontal } from "lucide-react"; import * as React from "react"; -import { cn } from "@/views/utils"; +import { cn } from "@/presentation/utils"; function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { return