mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge pull request #6526 from thornbill/api-keys-table-page
Refactor api keys to use TablePage component
This commit is contained in:
commit
a367e61a8c
3 changed files with 58 additions and 77 deletions
|
@ -1,4 +1,5 @@
|
|||
import Box from '@mui/material/Box/Box';
|
||||
import Stack from '@mui/material/Stack/Stack';
|
||||
import Typography from '@mui/material/Typography/Typography';
|
||||
import { type MRT_RowData, type MRT_TableInstance, MaterialReactTable } from 'material-react-table';
|
||||
import React from 'react';
|
||||
|
@ -7,6 +8,7 @@ import Page, { type PageProps } from 'components/Page';
|
|||
|
||||
interface TablePageProps<T extends MRT_RowData> extends PageProps {
|
||||
title: string
|
||||
subtitle?: string
|
||||
table: MRT_TableInstance<T>
|
||||
}
|
||||
|
||||
|
@ -27,6 +29,7 @@ export const DEFAULT_TABLE_OPTIONS = {
|
|||
|
||||
const TablePage = <T extends MRT_RowData>({
|
||||
title,
|
||||
subtitle,
|
||||
table,
|
||||
children,
|
||||
...pageProps
|
||||
|
@ -44,7 +47,8 @@ const TablePage = <T extends MRT_RowData>({
|
|||
height: '100%'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
<Stack
|
||||
spacing={2}
|
||||
sx={{
|
||||
marginBottom: 1
|
||||
}}
|
||||
|
@ -52,7 +56,12 @@ const TablePage = <T extends MRT_RowData>({
|
|||
<Typography variant='h2'>
|
||||
{title}
|
||||
</Typography>
|
||||
</Box>
|
||||
{subtitle && (
|
||||
<Typography>
|
||||
{subtitle}
|
||||
</Typography>
|
||||
)}
|
||||
</Stack>
|
||||
<MaterialReactTable table={table} />
|
||||
</Box>
|
||||
{children}
|
||||
|
|
|
@ -40,7 +40,7 @@ const getUserCell = (users: UsersRecords) => function UserCell({ row }: Activity
|
|||
);
|
||||
};
|
||||
|
||||
const Activity = () => {
|
||||
export const Component = () => {
|
||||
const [ searchParams, setSearchParams ] = useSearchParams();
|
||||
|
||||
const [ activityView, setActivityView ] = useState(
|
||||
|
@ -61,7 +61,13 @@ const Activity = () => {
|
|||
hasUserId: activityView !== ActivityView.All ? activityView === ActivityView.User : undefined
|
||||
}), [activityView, pagination.pageIndex, pagination.pageSize]);
|
||||
|
||||
const { data: logEntries, isLoading: isLogEntriesLoading } = useLogEntries(activityParams);
|
||||
const { data, isLoading: isLogEntriesLoading } = useLogEntries(activityParams);
|
||||
const logEntries = useMemo(() => (
|
||||
data?.Items || []
|
||||
), [ data ]);
|
||||
const rowCount = useMemo(() => (
|
||||
data?.TotalRecordCount || 0
|
||||
), [ data ]);
|
||||
|
||||
const isLoading = isUsersLoading || isLogEntriesLoading;
|
||||
|
||||
|
@ -154,7 +160,7 @@ const Activity = () => {
|
|||
...DEFAULT_TABLE_OPTIONS,
|
||||
|
||||
columns,
|
||||
data: logEntries?.Items || [],
|
||||
data: logEntries,
|
||||
|
||||
// State
|
||||
initialState: {
|
||||
|
@ -168,7 +174,7 @@ const Activity = () => {
|
|||
// Server pagination
|
||||
manualPagination: true,
|
||||
onPaginationChange: setPagination,
|
||||
rowCount: logEntries?.TotalRecordCount || 0,
|
||||
rowCount,
|
||||
|
||||
// Custom toolbar contents
|
||||
renderTopToolbarCustomActions: () => (
|
||||
|
@ -201,4 +207,4 @@ const Activity = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export default Activity;
|
||||
Component.displayName = 'ActivityPage';
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
import parseISO from 'date-fns/parseISO';
|
||||
|
||||
import DateTimeCell from 'apps/dashboard/components/table/DateTimeCell';
|
||||
import Page from 'components/Page';
|
||||
import { useApi } from 'hooks/useApi';
|
||||
import globalize from 'lib/globalize';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import type { AuthenticationInfo } from '@jellyfin/sdk/lib/generated-client/models/authentication-info';
|
||||
import confirm from 'components/confirm/confirm';
|
||||
import { useApiKeys } from 'apps/dashboard/features/keys/api/useApiKeys';
|
||||
import { useRevokeKey } from 'apps/dashboard/features/keys/api/useRevokeKey';
|
||||
import { useCreateKey } from 'apps/dashboard/features/keys/api/useCreateKey';
|
||||
import Box from '@mui/material/Box';
|
||||
import Button from '@mui/material/Button';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { MaterialReactTable, MRT_ColumnDef, useMaterialReactTable } from 'material-react-table';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import parseISO from 'date-fns/parseISO';
|
||||
import { type MRT_ColumnDef, useMaterialReactTable } from 'material-react-table';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
|
||||
const ApiKeys = () => {
|
||||
import DateTimeCell from 'apps/dashboard/components/table/DateTimeCell';
|
||||
import TablePage, { DEFAULT_TABLE_OPTIONS } from 'apps/dashboard/components/table/TablePage';
|
||||
import { useApiKeys } from 'apps/dashboard/features/keys/api/useApiKeys';
|
||||
import { useRevokeKey } from 'apps/dashboard/features/keys/api/useRevokeKey';
|
||||
import { useCreateKey } from 'apps/dashboard/features/keys/api/useCreateKey';
|
||||
import confirm from 'components/confirm/confirm';
|
||||
import prompt from 'components/prompt/prompt';
|
||||
import { useApi } from 'hooks/useApi';
|
||||
import globalize from 'lib/globalize';
|
||||
|
||||
export const Component = () => {
|
||||
const { api } = useApi();
|
||||
const { data: keys, isLoading } = useApiKeys();
|
||||
const { data, isLoading } = useApiKeys();
|
||||
const keys = useMemo(() => (
|
||||
data?.Items || []
|
||||
), [ data ]);
|
||||
const revokeKey = useRevokeKey();
|
||||
const createKey = useCreateKey();
|
||||
|
||||
|
@ -48,26 +50,15 @@ const ApiKeys = () => {
|
|||
], []);
|
||||
|
||||
const table = useMaterialReactTable({
|
||||
...DEFAULT_TABLE_OPTIONS,
|
||||
|
||||
columns,
|
||||
data: keys?.Items || [],
|
||||
data: keys,
|
||||
|
||||
state: {
|
||||
isLoading
|
||||
},
|
||||
|
||||
rowCount: keys?.TotalRecordCount || 0,
|
||||
|
||||
enableColumnPinning: true,
|
||||
enableColumnResizing: true,
|
||||
|
||||
enableStickyFooter: true,
|
||||
enableStickyHeader: true,
|
||||
muiTableContainerProps: {
|
||||
sx: {
|
||||
maxHeight: 'calc(100% - 7rem)' // 2 x 3.5rem for header and footer
|
||||
}
|
||||
},
|
||||
|
||||
// Enable (delete) row actions
|
||||
enableRowActions: true,
|
||||
positionActionsColumn: 'last',
|
||||
|
@ -119,7 +110,6 @@ const ApiKeys = () => {
|
|||
const showNewKeyPopup = useCallback(() => {
|
||||
if (!api) return;
|
||||
|
||||
import('../../../../components/prompt/prompt').then(({ default: prompt }) => {
|
||||
prompt({
|
||||
title: globalize.translate('HeaderNewApiKey'),
|
||||
label: globalize.translate('LabelAppName'),
|
||||
|
@ -131,41 +121,17 @@ const ApiKeys = () => {
|
|||
}).catch(() => {
|
||||
// popup closed
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error('[apikeys] failed to load api key popup', err);
|
||||
});
|
||||
}, [api, createKey]);
|
||||
|
||||
return (
|
||||
<Page
|
||||
<TablePage
|
||||
id='apiKeysPage'
|
||||
title={globalize.translate('HeaderApiKeys')}
|
||||
subtitle={globalize.translate('HeaderApiKeysHelp')}
|
||||
className='mainAnimatedPage type-interior'
|
||||
>
|
||||
<Box
|
||||
className='content-primary'
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
marginBottom: 1
|
||||
}}
|
||||
>
|
||||
<Stack spacing={2}>
|
||||
<Typography variant='h2'>
|
||||
{globalize.translate('HeaderApiKeys')}
|
||||
</Typography>
|
||||
<Typography>{globalize.translate('HeaderApiKeysHelp')}</Typography>
|
||||
</Stack>
|
||||
</Box>
|
||||
<MaterialReactTable table={table} />
|
||||
</Box>
|
||||
</Page>
|
||||
table={table}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApiKeys;
|
||||
Component.displayName = 'ApiKeysPage';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue