From 589f06b460843bdf532cc61b4b29aae24f86c87e Mon Sep 17 00:00:00 2001 From: diced Date: Mon, 8 Dec 2025 23:30:04 -0800 Subject: [PATCH] feat: new actions page + finish impl v4 export --- src/client/pages/dashboard/admin/actions.tsx | 10 +++ src/client/routes.tsx | 1 + src/components/Layout.tsx | 7 +++ .../pages/serverActions/ActionButton.tsx | 19 ++++++ .../actions}/ClearTempButton.tsx | 10 +-- .../actions}/ClearZerosButton.tsx | 10 +-- .../actions}/GenThumbsButton.tsx | 8 +-- .../ImportExportButton/ExportButton.tsx | 0 .../ImportV3Button/Export3Details.tsx | 0 .../ImportV3Button/Export3ImportSettings.tsx | 0 .../ImportV3Button/Export3UserChoose.tsx | 0 .../ImportV3Button/index.tsx | 2 - .../ImportV4Button/Export4Details.tsx | 0 .../ImportV4Button/Export4ImportSettings.tsx | 0 .../ImportV4Button/Export4UserChoose.tsx | 0 .../Export4WarningSameInstance.tsx | 0 .../ImportV4Button/index.tsx | 33 ++++++++++ .../actions}/ImportExportButton/index.tsx | 9 ++- .../actions}/RequerySizeButton.tsx | 6 +- src/components/pages/serverActions/index.tsx | 61 +++++++++++++++++++ .../pages/serverSettings/settingsOnSubmit.tsx | 1 - src/components/pages/settings/index.tsx | 6 -- .../parts/SettingsServerUtil/index.tsx | 25 -------- 23 files changed, 146 insertions(+), 62 deletions(-) create mode 100644 src/client/pages/dashboard/admin/actions.tsx create mode 100644 src/components/pages/serverActions/ActionButton.tsx rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ClearTempButton.tsx (84%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ClearZerosButton.tsx (84%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/GenThumbsButton.tsx (88%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ExportButton.tsx (100%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ImportV3Button/Export3Details.tsx (100%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ImportV3Button/Export3ImportSettings.tsx (100%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ImportV3Button/Export3UserChoose.tsx (100%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ImportV3Button/index.tsx (99%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ImportV4Button/Export4Details.tsx (100%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ImportV4Button/Export4ImportSettings.tsx (100%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ImportV4Button/Export4UserChoose.tsx (100%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ImportV4Button/Export4WarningSameInstance.tsx (100%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/ImportV4Button/index.tsx (90%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/ImportExportButton/index.tsx (67%) rename src/components/pages/{settings/parts/SettingsServerUtil => serverActions/actions}/RequerySizeButton.tsx (93%) create mode 100644 src/components/pages/serverActions/index.tsx delete mode 100755 src/components/pages/settings/parts/SettingsServerUtil/index.tsx diff --git a/src/client/pages/dashboard/admin/actions.tsx b/src/client/pages/dashboard/admin/actions.tsx new file mode 100644 index 00000000..c19f123c --- /dev/null +++ b/src/client/pages/dashboard/admin/actions.tsx @@ -0,0 +1,10 @@ +import DashboardServerActions from '@/components/pages/serverActions'; +import { useTitle } from '@/lib/hooks/useTitle'; + +export function Component() { + useTitle('Server Actions'); + + return ; +} + +Component.displayName = 'Dashboard/Admin/Actions'; diff --git a/src/client/routes.tsx b/src/client/routes.tsx index 71a09a3b..c87a8fb8 100644 --- a/src/client/routes.tsx +++ b/src/client/routes.tsx @@ -82,6 +82,7 @@ export const router = createBrowserRouter([ children: [ { path: 'invites', lazy: () => import('./pages/dashboard/admin/invites') }, { path: 'settings', lazy: () => import('./pages/dashboard/admin/settings') }, + { path: 'actions', lazy: () => import('./pages/dashboard/admin/actions') }, { path: 'users', children: [ diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index e7a48f9b..36a5601f 100755 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -41,6 +41,7 @@ import { IconRefreshDot, IconSettingsFilled, IconShieldLockFilled, + IconStopwatch, IconTags, IconUpload, IconUsersGroup, @@ -126,6 +127,12 @@ const navLinks: NavLinks[] = [ if: (user) => user?.role === 'SUPERADMIN', href: '/dashboard/admin/settings', }, + { + label: 'Actions', + icon: , + active: (path: string) => path === '/dashboard/admin/actions', + href: '/dashboard/admin/actions', + }, { label: 'Users', icon: , diff --git a/src/components/pages/serverActions/ActionButton.tsx b/src/components/pages/serverActions/ActionButton.tsx new file mode 100644 index 00000000..4b1fb11e --- /dev/null +++ b/src/components/pages/serverActions/ActionButton.tsx @@ -0,0 +1,19 @@ +import { ActionIcon } from '@mantine/core'; +import { IconPlayerPlayFilled } from '@tabler/icons-react'; + +const ICON_SIZE = '1.75rem'; + +export default function ActionButton({ onClick, Icon }: { onClick: () => void; Icon?: React.FC }) { + return ( + + {Icon ? : } + + ); +} diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ClearTempButton.tsx b/src/components/pages/serverActions/actions/ClearTempButton.tsx similarity index 84% rename from src/components/pages/settings/parts/SettingsServerUtil/ClearTempButton.tsx rename to src/components/pages/serverActions/actions/ClearTempButton.tsx index 42131f9d..dd57c6b9 100755 --- a/src/components/pages/settings/parts/SettingsServerUtil/ClearTempButton.tsx +++ b/src/components/pages/serverActions/actions/ClearTempButton.tsx @@ -1,9 +1,9 @@ import { Response } from '@/lib/api/response'; import { fetchApi } from '@/lib/fetchApi'; -import { Button } from '@mantine/core'; import { modals } from '@mantine/modals'; import { showNotification } from '@mantine/notifications'; import { IconTrashFilled } from '@tabler/icons-react'; +import ActionButton from '../ActionButton'; export default function ClearTempButton() { const openModal = () => @@ -30,11 +30,5 @@ export default function ClearTempButton() { }, }); - return ( - <> - - - ); + return ; } diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ClearZerosButton.tsx b/src/components/pages/serverActions/actions/ClearZerosButton.tsx similarity index 84% rename from src/components/pages/settings/parts/SettingsServerUtil/ClearZerosButton.tsx rename to src/components/pages/serverActions/actions/ClearZerosButton.tsx index aa2dad22..edc92296 100755 --- a/src/components/pages/settings/parts/SettingsServerUtil/ClearZerosButton.tsx +++ b/src/components/pages/serverActions/actions/ClearZerosButton.tsx @@ -1,10 +1,10 @@ import { Response } from '@/lib/api/response'; import { fetchApi } from '@/lib/fetchApi'; -import { Button } from '@mantine/core'; import { modals } from '@mantine/modals'; import { showNotification } from '@mantine/notifications'; import { IconTrashFilled } from '@tabler/icons-react'; import useSWR from 'swr'; +import ActionButton from '../ActionButton'; export default function ClearZerosButton() { const { data } = useSWR('/api/server/clear_zeros'); @@ -32,11 +32,5 @@ export default function ClearZerosButton() { }, }); - return ( - <> - - - ); + return ; } diff --git a/src/components/pages/settings/parts/SettingsServerUtil/GenThumbsButton.tsx b/src/components/pages/serverActions/actions/GenThumbsButton.tsx similarity index 88% rename from src/components/pages/settings/parts/SettingsServerUtil/GenThumbsButton.tsx rename to src/components/pages/serverActions/actions/GenThumbsButton.tsx index a44490ab..3719e9ad 100644 --- a/src/components/pages/settings/parts/SettingsServerUtil/GenThumbsButton.tsx +++ b/src/components/pages/serverActions/actions/GenThumbsButton.tsx @@ -2,8 +2,9 @@ import { Response } from '@/lib/api/response'; import { fetchApi } from '@/lib/fetchApi'; import { Button, Group, Modal, Stack, Switch } from '@mantine/core'; import { showNotification } from '@mantine/notifications'; -import { IconVideo, IconVideoOff } from '@tabler/icons-react'; +import { IconVideoOff, IconVideoPlusFilled } from '@tabler/icons-react'; import { useState } from 'react'; +import ActionButton from '../ActionButton'; export default function GenThumbsButton() { const [rerun, setRerun] = useState(false); @@ -53,9 +54,8 @@ export default function GenThumbsButton() { - + + setOpen(true)} Icon={IconVideoPlusFilled} /> ); } diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ExportButton.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ExportButton.tsx similarity index 100% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ExportButton.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ExportButton.tsx diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV3Button/Export3Details.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ImportV3Button/Export3Details.tsx similarity index 100% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV3Button/Export3Details.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ImportV3Button/Export3Details.tsx diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV3Button/Export3ImportSettings.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ImportV3Button/Export3ImportSettings.tsx similarity index 100% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV3Button/Export3ImportSettings.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ImportV3Button/Export3ImportSettings.tsx diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV3Button/Export3UserChoose.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ImportV3Button/Export3UserChoose.tsx similarity index 100% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV3Button/Export3UserChoose.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ImportV3Button/Export3UserChoose.tsx diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV3Button/index.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ImportV3Button/index.tsx similarity index 99% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV3Button/index.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ImportV3Button/index.tsx index 3613d59b..a8aeb71d 100644 --- a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV3Button/index.tsx +++ b/src/components/pages/serverActions/actions/ImportExportButton/ImportV3Button/index.tsx @@ -93,8 +93,6 @@ export default function ImportV3Button() { color: 'green', icon: , }); - - await fetch('/reload'); } }; diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/Export4Details.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/Export4Details.tsx similarity index 100% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/Export4Details.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/Export4Details.tsx diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/Export4ImportSettings.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/Export4ImportSettings.tsx similarity index 100% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/Export4ImportSettings.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/Export4ImportSettings.tsx diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/Export4UserChoose.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/Export4UserChoose.tsx similarity index 100% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/Export4UserChoose.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/Export4UserChoose.tsx diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/Export4WarningSameInstance.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/Export4WarningSameInstance.tsx similarity index 100% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/Export4WarningSameInstance.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/Export4WarningSameInstance.tsx diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/index.tsx b/src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/index.tsx similarity index 90% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/index.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/index.tsx index f6f7c758..12755afb 100644 --- a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/ImportV4Button/index.tsx +++ b/src/components/pages/serverActions/actions/ImportExportButton/ImportV4Button/index.tsx @@ -11,6 +11,7 @@ import { useUserStore } from '@/lib/store/user'; import { modals } from '@mantine/modals'; import { fetchApi } from '@/lib/fetchApi'; import { Response } from '@/lib/api/response'; +import { mutate } from 'swr'; export default function ImportV4Button() { const [open, setOpen] = useState(false); @@ -52,6 +53,36 @@ export default function ImportV4Button() { setExport4(validated.data); }; + const handleImportSettings = async () => { + if (!export4) return; + + const { error } = await fetchApi( + '/api/server/settings', + 'PATCH', + export4.data.settings, + ); + + if (error) { + showNotification({ + title: 'Failed to import settings', + message: error.issues + ? error.issues.map((x: { message: string }) => x.message).join('\n') + : error.error, + color: 'red', + }); + } else { + showNotification({ + title: 'Settings imported', + message: 'To ensure that all settings take effect, it is recommended to restart Zipline.', + color: 'green', + }); + + mutate('/api/server/settings'); + mutate('/api/server/settings/web'); + mutate('/api/server/public'); + } + }; + const handleImport = async () => { if (!export4) return; @@ -88,6 +119,8 @@ export default function ImportV4Button() { setOpen(false); + await handleImportSettings(); + const { error, data } = await fetchApi( '/api/server/import/v4', 'POST', diff --git a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/index.tsx b/src/components/pages/serverActions/actions/ImportExportButton/index.tsx similarity index 67% rename from src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/index.tsx rename to src/components/pages/serverActions/actions/ImportExportButton/index.tsx index 004dfd5d..6692120c 100644 --- a/src/components/pages/settings/parts/SettingsServerUtil/ImportExportButton/index.tsx +++ b/src/components/pages/serverActions/actions/ImportExportButton/index.tsx @@ -1,9 +1,10 @@ -import { Button, Divider, Group, Modal } from '@mantine/core'; -import { IconDatabaseExport } from '@tabler/icons-react'; +import { Divider, Group, Modal } from '@mantine/core'; import { useState } from 'react'; import ImportV3Button from './ImportV3Button'; import ImportV4Button from './ImportV4Button'; import ExportButton from './ExportButton'; +import ActionButton from '../../ActionButton'; +import { IconDatabasePlus } from '@tabler/icons-react'; export default function ImportExport() { const [open, setOpen] = useState(false); @@ -21,9 +22,7 @@ export default function ImportExport() { - + setOpen(true)} Icon={IconDatabasePlus} /> ); } diff --git a/src/components/pages/settings/parts/SettingsServerUtil/RequerySizeButton.tsx b/src/components/pages/serverActions/actions/RequerySizeButton.tsx similarity index 93% rename from src/components/pages/settings/parts/SettingsServerUtil/RequerySizeButton.tsx rename to src/components/pages/serverActions/actions/RequerySizeButton.tsx index d44d93d1..7b1f25a3 100755 --- a/src/components/pages/settings/parts/SettingsServerUtil/RequerySizeButton.tsx +++ b/src/components/pages/serverActions/actions/RequerySizeButton.tsx @@ -4,6 +4,7 @@ import { Button, Group, Modal, Stack, Switch } from '@mantine/core'; import { showNotification } from '@mantine/notifications'; import { IconFileSearch } from '@tabler/icons-react'; import { useState } from 'react'; +import ActionButton from '../ActionButton'; export default function RequerySizeButton() { const [forceUpdate, setForceUpdate] = useState(false); @@ -65,9 +66,8 @@ export default function RequerySizeButton() { - + + setOpen(true)} /> ); } diff --git a/src/components/pages/serverActions/index.tsx b/src/components/pages/serverActions/index.tsx new file mode 100644 index 00000000..80522e70 --- /dev/null +++ b/src/components/pages/serverActions/index.tsx @@ -0,0 +1,61 @@ +import { Group, Paper, Stack, Text, Title } from '@mantine/core'; +import ClearTempButton from './actions/ClearTempButton'; +import ClearZerosButton from './actions/ClearZerosButton'; +import GenThumbsButton from './actions/GenThumbsButton'; +import ImportExport from './actions/ImportExportButton'; +import RequerySizeButton from './actions/RequerySizeButton'; + +const ACTIONS = [ + { + name: 'Import/Export Data', + desc: 'Allows you to import or export server data and configurations.', + Component: ImportExport, + }, + { + name: 'Clear Temporary Files', + desc: 'Removes all temporary files from the temporary directory.', + Component: ClearTempButton, + }, + { + name: 'Clear Zero Byte Files', + desc: 'Deletes all files with zero bytes from the database and/or storage.', + Component: ClearZerosButton, + }, + { + name: 'Requery File Sizes', + desc: 'Recalculates and updates the sizes of all files in the database.', + Component: RequerySizeButton, + }, + { + name: 'Generate Thumbnails', + desc: 'Creates thumbnails for all image and video files that lack them.', + Component: GenThumbsButton, + }, +]; + +export default function DashboardServerActions() { + return ( + <> + + Server Actions + + + Useful tools and scripts for server management. + + + {ACTIONS.map(({ name, desc, Component }) => ( + + + + +
+ {name} + {desc} +
+
+
+ ))} +
+ + ); +} diff --git a/src/components/pages/serverSettings/settingsOnSubmit.tsx b/src/components/pages/serverSettings/settingsOnSubmit.tsx index b080567b..f50639f3 100644 --- a/src/components/pages/serverSettings/settingsOnSubmit.tsx +++ b/src/components/pages/serverSettings/settingsOnSubmit.tsx @@ -39,7 +39,6 @@ export function settingsOnSubmit(navigate: NavigateFunction, form: ReturnType, }); - await fetch('/reload'); mutate('/api/server/settings', data); mutate('/api/server/settings/web'); mutate('/api/server/public'); diff --git a/src/components/pages/settings/index.tsx b/src/components/pages/settings/index.tsx index 9e003ba8..ba1135e1 100755 --- a/src/components/pages/settings/index.tsx +++ b/src/components/pages/settings/index.tsx @@ -1,7 +1,5 @@ import { useConfig } from '@/components/ConfigProvider'; import { eitherTrue } from '@/lib/primitive'; -import { isAdministrator } from '@/lib/role'; -import { useUserStore } from '@/lib/store/user'; import { Group, SimpleGrid, Stack, Title } from '@mantine/core'; import { lazy } from 'react'; @@ -10,7 +8,6 @@ const SettingsDashboard = lazy(() => import('./parts/SettingsDashboard')); const SettingsFileView = lazy(() => import('./parts/SettingsFileView')); const SettingsGenerators = lazy(() => import('./parts/SettingsGenerators')); const SettingsMfa = lazy(() => import('./parts/SettingsMfa')); -const SettingsServerActions = lazy(() => import('./parts/SettingsServerUtil')); const SettingsUser = lazy(() => import('./parts/SettingsUser')); const SettingsExports = lazy(() => import('./parts/SettingsExports')); const SettingsSessions = lazy(() => import('./parts/SettingsSessions')); @@ -18,7 +15,6 @@ const SettingsOAuth = lazy(() => import('./parts/SettingsOAuth')); export default function DashboardSettings() { const config = useConfig(); - const user = useUserStore((state) => state.user); return ( <> @@ -49,8 +45,6 @@ export default function DashboardSettings() { - - {isAdministrator(user?.role) && } ); diff --git a/src/components/pages/settings/parts/SettingsServerUtil/index.tsx b/src/components/pages/settings/parts/SettingsServerUtil/index.tsx deleted file mode 100755 index bf7ca9d5..00000000 --- a/src/components/pages/settings/parts/SettingsServerUtil/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Group, Paper, Text, Title } from '@mantine/core'; -import ClearTempButton from './ClearTempButton'; -import ClearZerosButton from './ClearZerosButton'; -import GenThumbsButton from './GenThumbsButton'; -import RequerySizeButton from './RequerySizeButton'; -import ImportExportButton from './ImportExportButton'; - -export default function SettingsServerActions() { - return ( - - Server Actions - - Helpful scripts and tools for server management. - - - - - - - - - - - ); -}