From 83e7c6fac3e58ffa005b086ea398e46714f9f3c4 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 26 Jun 2025 11:31:59 +0800 Subject: [PATCH] refactor components into fragments --- next-ui/README.md | 16 +++++++- next-ui/src/App.vue | 6 +-- next-ui/src/components.d.ts | 40 +++++++++---------- .../src/components/app/drawer/menu/Menu.vue | 16 -------- next-ui/src/components/form/README.md | 1 - next-ui/src/components/notice/README.md | 1 - .../DeletionWarning.vue} | 0 .../user => user/form}/ChangePassword.vue | 0 .../Edit.vue => user/form/CreateEdit.vue} | 0 next-ui/src/fragments/README.md | 35 ++++++++++++++++ .../fragment}/BuildCommit.stories.ts | 0 .../fragment}/BuildCommit.vue | 0 .../fragment}/BuildVersion.stories.ts | 0 .../fragment}/BuildVersion.vue | 0 .../fragment}/LocaleSelector.vue | 0 .../fragment}/SnackQueue.vue | 0 .../fragment}/ThemeSelector.vue | 0 .../fragment/dialog}/Confirm.vue | 0 .../fragment/dialog}/ConfirmEdit.vue | 0 .../layout}/app/Bar.vue | 4 +- .../layout}/app/drawer/Drawer.vue | 4 +- .../layout}/app/drawer/Footer.vue | 4 +- .../layout}/app/drawer/menu/Account.vue | 0 .../layout}/app/drawer/menu/History.vue | 0 .../layout}/app/drawer/menu/Import.vue | 0 .../layout}/app/drawer/menu/Logout.vue | 0 .../layout}/app/drawer/menu/Media.vue | 0 .../fragments/layout/app/drawer/menu/Menu.vue | 16 ++++++++ .../layout}/app/drawer/menu/Server.vue | 0 next-ui/src/layouts/default.vue | 4 +- next-ui/src/pages/login.vue | 4 +- next-ui/src/pages/server/users.vue | 14 +++---- next-ui/vite.config.mts | 3 +- 33 files changed, 108 insertions(+), 60 deletions(-) delete mode 100644 next-ui/src/components/app/drawer/menu/Menu.vue delete mode 100644 next-ui/src/components/form/README.md delete mode 100644 next-ui/src/components/notice/README.md rename next-ui/src/components/{notice/UserDeletion.vue => user/DeletionWarning.vue} (100%) rename next-ui/src/components/{form/user => user/form}/ChangePassword.vue (100%) rename next-ui/src/components/{form/user/Edit.vue => user/form/CreateEdit.vue} (100%) create mode 100644 next-ui/src/fragments/README.md rename next-ui/src/{components => fragments/fragment}/BuildCommit.stories.ts (100%) rename next-ui/src/{components => fragments/fragment}/BuildCommit.vue (100%) rename next-ui/src/{components => fragments/fragment}/BuildVersion.stories.ts (100%) rename next-ui/src/{components => fragments/fragment}/BuildVersion.vue (100%) rename next-ui/src/{components => fragments/fragment}/LocaleSelector.vue (100%) rename next-ui/src/{components => fragments/fragment}/SnackQueue.vue (100%) rename next-ui/src/{components => fragments/fragment}/ThemeSelector.vue (100%) rename next-ui/src/{components/dialog/instance => fragments/fragment/dialog}/Confirm.vue (100%) rename next-ui/src/{components/dialog/instance => fragments/fragment/dialog}/ConfirmEdit.vue (100%) rename next-ui/src/{components => fragments/layout}/app/Bar.vue (89%) rename next-ui/src/{components => fragments/layout}/app/drawer/Drawer.vue (80%) rename next-ui/src/{components => fragments/layout}/app/drawer/Footer.vue (92%) rename next-ui/src/{components => fragments/layout}/app/drawer/menu/Account.vue (100%) rename next-ui/src/{components => fragments/layout}/app/drawer/menu/History.vue (100%) rename next-ui/src/{components => fragments/layout}/app/drawer/menu/Import.vue (100%) rename next-ui/src/{components => fragments/layout}/app/drawer/menu/Logout.vue (100%) rename next-ui/src/{components => fragments/layout}/app/drawer/menu/Media.vue (100%) create mode 100644 next-ui/src/fragments/layout/app/drawer/menu/Menu.vue rename next-ui/src/{components => fragments/layout}/app/drawer/menu/Server.vue (100%) diff --git a/next-ui/README.md b/next-ui/README.md index f867b43f..99592e5f 100644 --- a/next-ui/README.md +++ b/next-ui/README.md @@ -10,7 +10,7 @@ The `openapi-generate` tasks will generate bindings, and should be run when the ## Tests -We use Vitest projects to separate different kind of tests: +Vitest projects are used to specify different kind of tests: - `unit`: unit tests - `storybook`: component tests, defined in Storybook stories. Those can be run from Storybook directly or through Vitest. @@ -43,3 +43,17 @@ Tasks: - `i18n:compile`: compiles the translated files in `i18n` into `./src/i18n`. This folder is what the application uses at runtime. The Vite plugin [dir2json](https://github.com/buddywang/vite-plugin-dir2json) is used to load the available translation files, see `./src/utils/locale-helper.ts` for more details. + +## Components + +Vue template files are segregated in different categories depending on usage: +- `./src/components`: Pure UI components, driven by model/props. Those are reusable components. +- `./src/fragments`: Fragments interact with other layers of the application, like API or Pinia stores. They are split into separate files for easier organization, but are not necessarily reused. +- `./src/pages`: Pages make use of components/fragments as well as API / Pinia stores. Each Component in that folder is converted to a navigable route using [unplugin-vue-router](https://github.com/posva/unplugin-vue-router). Pages contain a special `` to define the layout to use as well as other router meta attributes. +- `./src/layouts`: Wrapper component around Pages. + +Components and Fragments are automatically imported using [unplugin-vue-components](https://github.com/unplugin/unplugin-vue-components). + +## Icons + +[UnoCSS Icons preset](https://unocss.dev/presets/icons) is used for icons, with the MDI set from Iconify. diff --git a/next-ui/src/App.vue b/next-ui/src/App.vue index 8fbd5f4d..9677c3cb 100644 --- a/next-ui/src/App.vue +++ b/next-ui/src/App.vue @@ -2,9 +2,9 @@ - - - + + + diff --git a/next-ui/src/components.d.ts b/next-ui/src/components.d.ts index b83e2aae..e122b8c2 100644 --- a/next-ui/src/components.d.ts +++ b/next-ui/src/components.d.ts @@ -8,31 +8,31 @@ export {} /* prettier-ignore */ declare module 'vue' { export interface GlobalComponents { - AppBar: typeof import('./components/app/Bar.vue')['default'] - AppDrawer: typeof import('./components/app/drawer/Drawer.vue')['default'] - AppDrawerFooter: typeof import('./components/app/drawer/Footer.vue')['default'] - AppDrawerMenu: typeof import('./components/app/drawer/menu/Menu.vue')['default'] - AppDrawerMenuAccount: typeof import('./components/app/drawer/menu/Account.vue')['default'] - AppDrawerMenuHistory: typeof import('./components/app/drawer/menu/History.vue')['default'] - AppDrawerMenuImport: typeof import('./components/app/drawer/menu/Import.vue')['default'] - AppDrawerMenuLogout: typeof import('./components/app/drawer/menu/Logout.vue')['default'] - AppDrawerMenuMedia: typeof import('./components/app/drawer/menu/Media.vue')['default'] - AppDrawerMenuServer: typeof import('./components/app/drawer/menu/Server.vue')['default'] AppFooter: typeof import('./components/AppFooter.vue')['default'] - BuildCommit: typeof import('./components/BuildCommit.vue')['default'] - BuildVersion: typeof import('./components/BuildVersion.vue')['default'] DialogConfirm: typeof import('./components/dialog/Confirm.vue')['default'] DialogConfirmEdit: typeof import('./components/dialog/ConfirmEdit.vue')['default'] - DialogInstanceConfirm: typeof import('./components/dialog/instance/Confirm.vue')['default'] - DialogInstanceConfirmEdit: typeof import('./components/dialog/instance/ConfirmEdit.vue')['default'] - FormUserChangePassword: typeof import('./components/form/user/ChangePassword.vue')['default'] - FormUserEdit: typeof import('./components/form/user/Edit.vue')['default'] + FragmentBuildCommit: typeof import('./fragments/fragment/BuildCommit.vue')['default'] + FragmentBuildVersion: typeof import('./fragments/fragment/BuildVersion.vue')['default'] + FragmentDialogConfirm: typeof import('./fragments/fragment/dialog/Confirm.vue')['default'] + FragmentDialogConfirmEdit: typeof import('./fragments/fragment/dialog/ConfirmEdit.vue')['default'] + FragmentLocaleSelector: typeof import('./fragments/fragment/LocaleSelector.vue')['default'] + FragmentSnackQueue: typeof import('./fragments/fragment/SnackQueue.vue')['default'] + FragmentThemeSelector: typeof import('./fragments/fragment/ThemeSelector.vue')['default'] HelloWorld: typeof import('./components/HelloWorld.vue')['default'] - LocaleSelector: typeof import('./components/LocaleSelector.vue')['default'] - NoticeUserDeletion: typeof import('./components/notice/UserDeletion.vue')['default'] + LayoutAppBar: typeof import('./fragments/layout/app/Bar.vue')['default'] + LayoutAppDrawer: typeof import('./fragments/layout/app/drawer/Drawer.vue')['default'] + LayoutAppDrawerFooter: typeof import('./fragments/layout/app/drawer/Footer.vue')['default'] + LayoutAppDrawerMenu: typeof import('./fragments/layout/app/drawer/menu/Menu.vue')['default'] + LayoutAppDrawerMenuAccount: typeof import('./fragments/layout/app/drawer/menu/Account.vue')['default'] + LayoutAppDrawerMenuHistory: typeof import('./fragments/layout/app/drawer/menu/History.vue')['default'] + LayoutAppDrawerMenuImport: typeof import('./fragments/layout/app/drawer/menu/Import.vue')['default'] + LayoutAppDrawerMenuLogout: typeof import('./fragments/layout/app/drawer/menu/Logout.vue')['default'] + LayoutAppDrawerMenuMedia: typeof import('./fragments/layout/app/drawer/menu/Media.vue')['default'] + LayoutAppDrawerMenuServer: typeof import('./fragments/layout/app/drawer/menu/Server.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] - SnackQueue: typeof import('./components/SnackQueue.vue')['default'] - ThemeSelector: typeof import('./components/ThemeSelector.vue')['default'] + UserDeletionWarning: typeof import('./components/user/DeletionWarning.vue')['default'] + UserFormChangePassword: typeof import('./components/user/form/ChangePassword.vue')['default'] + UserFormCreateEdit: typeof import('./components/user/form/CreateEdit.vue')['default'] } } diff --git a/next-ui/src/components/app/drawer/menu/Menu.vue b/next-ui/src/components/app/drawer/menu/Menu.vue deleted file mode 100644 index d17fb2c9..00000000 --- a/next-ui/src/components/app/drawer/menu/Menu.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/next-ui/src/components/form/README.md b/next-ui/src/components/form/README.md deleted file mode 100644 index d4abb81f..00000000 --- a/next-ui/src/components/form/README.md +++ /dev/null @@ -1 +0,0 @@ -Simple forms that can be wrapped by a `v-form`, or used within a `DialogEditConfirm`. diff --git a/next-ui/src/components/notice/README.md b/next-ui/src/components/notice/README.md deleted file mode 100644 index f05ff680..00000000 --- a/next-ui/src/components/notice/README.md +++ /dev/null @@ -1 +0,0 @@ -Components that can be used within a `DialogConfirm`. diff --git a/next-ui/src/components/notice/UserDeletion.vue b/next-ui/src/components/user/DeletionWarning.vue similarity index 100% rename from next-ui/src/components/notice/UserDeletion.vue rename to next-ui/src/components/user/DeletionWarning.vue diff --git a/next-ui/src/components/form/user/ChangePassword.vue b/next-ui/src/components/user/form/ChangePassword.vue similarity index 100% rename from next-ui/src/components/form/user/ChangePassword.vue rename to next-ui/src/components/user/form/ChangePassword.vue diff --git a/next-ui/src/components/form/user/Edit.vue b/next-ui/src/components/user/form/CreateEdit.vue similarity index 100% rename from next-ui/src/components/form/user/Edit.vue rename to next-ui/src/components/user/form/CreateEdit.vue diff --git a/next-ui/src/fragments/README.md b/next-ui/src/fragments/README.md new file mode 100644 index 00000000..f9293a48 --- /dev/null +++ b/next-ui/src/fragments/README.md @@ -0,0 +1,35 @@ +# Fragments + +Vue template files in this folder are automatically imported. + +## 🚀 Usage + +Importing is handled by [unplugin-vue-components](https://github.com/unplugin/unplugin-vue-components). This plugin automatically imports `.vue` files created in the `src/components` directory, and registers them as global components. This means that you can use any component in your application without having to manually import it. + +The following example assumes a component located at `src/components/MyComponent.vue`: + +```vue + + + +``` + +When your template is rendered, the component's import will automatically be inlined, which renders to this: + +```vue + + + +``` diff --git a/next-ui/src/components/BuildCommit.stories.ts b/next-ui/src/fragments/fragment/BuildCommit.stories.ts similarity index 100% rename from next-ui/src/components/BuildCommit.stories.ts rename to next-ui/src/fragments/fragment/BuildCommit.stories.ts diff --git a/next-ui/src/components/BuildCommit.vue b/next-ui/src/fragments/fragment/BuildCommit.vue similarity index 100% rename from next-ui/src/components/BuildCommit.vue rename to next-ui/src/fragments/fragment/BuildCommit.vue diff --git a/next-ui/src/components/BuildVersion.stories.ts b/next-ui/src/fragments/fragment/BuildVersion.stories.ts similarity index 100% rename from next-ui/src/components/BuildVersion.stories.ts rename to next-ui/src/fragments/fragment/BuildVersion.stories.ts diff --git a/next-ui/src/components/BuildVersion.vue b/next-ui/src/fragments/fragment/BuildVersion.vue similarity index 100% rename from next-ui/src/components/BuildVersion.vue rename to next-ui/src/fragments/fragment/BuildVersion.vue diff --git a/next-ui/src/components/LocaleSelector.vue b/next-ui/src/fragments/fragment/LocaleSelector.vue similarity index 100% rename from next-ui/src/components/LocaleSelector.vue rename to next-ui/src/fragments/fragment/LocaleSelector.vue diff --git a/next-ui/src/components/SnackQueue.vue b/next-ui/src/fragments/fragment/SnackQueue.vue similarity index 100% rename from next-ui/src/components/SnackQueue.vue rename to next-ui/src/fragments/fragment/SnackQueue.vue diff --git a/next-ui/src/components/ThemeSelector.vue b/next-ui/src/fragments/fragment/ThemeSelector.vue similarity index 100% rename from next-ui/src/components/ThemeSelector.vue rename to next-ui/src/fragments/fragment/ThemeSelector.vue diff --git a/next-ui/src/components/dialog/instance/Confirm.vue b/next-ui/src/fragments/fragment/dialog/Confirm.vue similarity index 100% rename from next-ui/src/components/dialog/instance/Confirm.vue rename to next-ui/src/fragments/fragment/dialog/Confirm.vue diff --git a/next-ui/src/components/dialog/instance/ConfirmEdit.vue b/next-ui/src/fragments/fragment/dialog/ConfirmEdit.vue similarity index 100% rename from next-ui/src/components/dialog/instance/ConfirmEdit.vue rename to next-ui/src/fragments/fragment/dialog/ConfirmEdit.vue diff --git a/next-ui/src/components/app/Bar.vue b/next-ui/src/fragments/layout/app/Bar.vue similarity index 89% rename from next-ui/src/components/app/Bar.vue rename to next-ui/src/fragments/layout/app/Bar.vue index f8b70e57..45064ad9 100644 --- a/next-ui/src/components/app/Bar.vue +++ b/next-ui/src/fragments/layout/app/Bar.vue @@ -11,8 +11,8 @@ Komga - - + + diff --git a/next-ui/src/components/app/drawer/Drawer.vue b/next-ui/src/fragments/layout/app/drawer/Drawer.vue similarity index 80% rename from next-ui/src/components/app/drawer/Drawer.vue rename to next-ui/src/fragments/layout/app/drawer/Drawer.vue index cee175f7..4180899b 100644 --- a/next-ui/src/components/app/drawer/Drawer.vue +++ b/next-ui/src/fragments/layout/app/drawer/Drawer.vue @@ -1,9 +1,9 @@ diff --git a/next-ui/src/components/app/drawer/Footer.vue b/next-ui/src/fragments/layout/app/drawer/Footer.vue similarity index 92% rename from next-ui/src/components/app/drawer/Footer.vue rename to next-ui/src/fragments/layout/app/drawer/Footer.vue index fe13ba0b..3df16bd9 100644 --- a/next-ui/src/components/app/drawer/Footer.vue +++ b/next-ui/src/fragments/layout/app/drawer/Footer.vue @@ -25,8 +25,8 @@ class="d-flex align-center text-caption text-medium-emphasis pa-2" >
- - + +
diff --git a/next-ui/src/components/app/drawer/menu/Account.vue b/next-ui/src/fragments/layout/app/drawer/menu/Account.vue similarity index 100% rename from next-ui/src/components/app/drawer/menu/Account.vue rename to next-ui/src/fragments/layout/app/drawer/menu/Account.vue diff --git a/next-ui/src/components/app/drawer/menu/History.vue b/next-ui/src/fragments/layout/app/drawer/menu/History.vue similarity index 100% rename from next-ui/src/components/app/drawer/menu/History.vue rename to next-ui/src/fragments/layout/app/drawer/menu/History.vue diff --git a/next-ui/src/components/app/drawer/menu/Import.vue b/next-ui/src/fragments/layout/app/drawer/menu/Import.vue similarity index 100% rename from next-ui/src/components/app/drawer/menu/Import.vue rename to next-ui/src/fragments/layout/app/drawer/menu/Import.vue diff --git a/next-ui/src/components/app/drawer/menu/Logout.vue b/next-ui/src/fragments/layout/app/drawer/menu/Logout.vue similarity index 100% rename from next-ui/src/components/app/drawer/menu/Logout.vue rename to next-ui/src/fragments/layout/app/drawer/menu/Logout.vue diff --git a/next-ui/src/components/app/drawer/menu/Media.vue b/next-ui/src/fragments/layout/app/drawer/menu/Media.vue similarity index 100% rename from next-ui/src/components/app/drawer/menu/Media.vue rename to next-ui/src/fragments/layout/app/drawer/menu/Media.vue diff --git a/next-ui/src/fragments/layout/app/drawer/menu/Menu.vue b/next-ui/src/fragments/layout/app/drawer/menu/Menu.vue new file mode 100644 index 00000000..b88592a4 --- /dev/null +++ b/next-ui/src/fragments/layout/app/drawer/menu/Menu.vue @@ -0,0 +1,16 @@ + + + diff --git a/next-ui/src/components/app/drawer/menu/Server.vue b/next-ui/src/fragments/layout/app/drawer/menu/Server.vue similarity index 100% rename from next-ui/src/components/app/drawer/menu/Server.vue rename to next-ui/src/fragments/layout/app/drawer/menu/Server.vue diff --git a/next-ui/src/layouts/default.vue b/next-ui/src/layouts/default.vue index da890404..14bea86e 100644 --- a/next-ui/src/layouts/default.vue +++ b/next-ui/src/layouts/default.vue @@ -1,7 +1,7 @@