diff --git a/next-ui/src/components.d.ts b/next-ui/src/components.d.ts index fbae7f4be..96d01c02a 100644 --- a/next-ui/src/components.d.ts +++ b/next-ui/src/components.d.ts @@ -20,6 +20,7 @@ declare module 'vue' { FragmentSnackQueue: typeof import('./fragments/fragment/SnackQueue.vue')['default'] FragmentThemeSelector: typeof import('./fragments/fragment/ThemeSelector.vue')['default'] FragmentUserFormCreateEdit: typeof import('./fragments/fragment/user/form/CreateEdit.vue')['default'] + FragmentUserTable: typeof import('./fragments/fragment/user/Table.vue')['default'] HelloWorld: typeof import('./components/HelloWorld.vue')['default'] LayoutAppBar: typeof import('./fragments/layout/app/Bar.vue')['default'] LayoutAppDrawer: typeof import('./fragments/layout/app/drawer/Drawer.vue')['default'] @@ -36,6 +37,5 @@ declare module 'vue' { RouterView: typeof import('vue-router')['RouterView'] 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/fragments/fragment/user/Table.stories.ts b/next-ui/src/fragments/fragment/user/Table.stories.ts new file mode 100644 index 000000000..3483d3f8f --- /dev/null +++ b/next-ui/src/fragments/fragment/user/Table.stories.ts @@ -0,0 +1,50 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import Table from './Table.vue' +import { users } from '@/mocks/api/handlers/users' +import { fn } from 'storybook/test' + +const meta = { + component: Table, + render: (args: object) => ({ + components: { Table }, + setup() { + return { args } + }, + template: '', + }), + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + }, + args: { + onAddUser: fn(), + onEnterAddUser: fn(), + onEnterEditUser: fn(), + onEnterDeleteUser: fn(), + onEnterChangePassword: fn(), + onChangePassword: fn(), + onEditUser: fn(), + onDeleteUser: fn(), + }, +} satisfies Meta + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + users: users, + }, +} + +export const Loading: Story = { + args: { + loading: true, + }, +} + +export const NoData: Story = { + args: { + users: [], + }, +} diff --git a/next-ui/src/fragments/fragment/user/Table.vue b/next-ui/src/fragments/fragment/user/Table.vue new file mode 100644 index 000000000..8ca423921 --- /dev/null +++ b/next-ui/src/fragments/fragment/user/Table.vue @@ -0,0 +1,209 @@ + + + diff --git a/next-ui/src/mocks/api/handlers/users.ts b/next-ui/src/mocks/api/handlers/users.ts index 1d7898d47..4ec94ce3b 100644 --- a/next-ui/src/mocks/api/handlers/users.ts +++ b/next-ui/src/mocks/api/handlers/users.ts @@ -1,45 +1,39 @@ import { httpTyped } from '@/mocks/api/httpTyped' -export const users = [ - { - id: '0JEDA00AV4Z7G', - email: 'admin@example.org', - roles: ['ADMIN', 'FILE_DOWNLOAD', 'KOBO_SYNC', 'KOREADER_SYNC', 'PAGE_STREAMING', 'USER'], - sharedAllLibraries: true, - sharedLibrariesIds: [], - labelsAllow: [], - labelsExclude: [], - ageRestriction: null, - }, - { - id: '0JEDA00AZ4QXH', - email: 'user@example.org', - roles: ['KOBO_SYNC', 'PAGE_STREAMING', 'USER'], - sharedAllLibraries: true, - sharedLibrariesIds: [], - labelsAllow: [], - labelsExclude: ['book'], - ageRestriction: null, - }, -] +export const userAdmin = { + id: '0JEDA00AV4Z7G', + email: 'admin@example.org', + roles: ['ADMIN', 'FILE_DOWNLOAD', 'KOBO_SYNC', 'KOREADER_SYNC', 'PAGE_STREAMING', 'USER'], + sharedAllLibraries: true, + sharedLibrariesIds: [], + labelsAllow: [], + labelsExclude: [], +} +export const userRegular = { + id: '0JEDA00AZ4QXH', + email: 'user@example.org', + roles: ['KOBO_SYNC', 'PAGE_STREAMING', 'USER'], + sharedAllLibraries: true, + sharedLibrariesIds: [], + labelsAllow: [], + labelsExclude: ['book'], +} +export const users = [userAdmin, userRegular] const latestActivity = { userId: '0JEDA00AV4Z7G', email: 'admin@example.org', - apiKeyId: null, - apiKeyComment: null, ip: '127.0.0.1', userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:139.0) Gecko/20100101 Firefox/139.0', success: true, - error: null, dateTime: new Date('2025-06-30T06:56:33Z'), source: 'Password', } export const usersHandlers = [ - httpTyped.get('/api/v2/users/me', ({ response }) => response(200).json(users[0])), + httpTyped.get('/api/v2/users/me', ({ response }) => response(200).json(userAdmin)), httpTyped.get('/api/v2/users', ({ response }) => response(200).json(users)), - httpTyped.get('/api/v2/users/{userId}/authentication-activity/latest', ({ response }) => + httpTyped.get('/api/v2/users/{id}/authentication-activity/latest', ({ response }) => response(200).json(latestActivity), ), ] diff --git a/next-ui/src/pages/server/users.vue b/next-ui/src/pages/server/users.vue index 5ad9dc1e9..0de44ef22 100644 --- a/next-ui/src/pages/server/users.vue +++ b/next-ui/src/pages/server/users.vue @@ -7,90 +7,25 @@ />