From f61d0f5f8dd92c6a5746071bfbadb7976e6fe6d5 Mon Sep 17 00:00:00 2001 From: Manuel Date: Sun, 30 Jul 2023 22:20:20 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20manage=20dashboards=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../layout/admin/main-admin.layout.tsx | 11 ++ .../create-dashboard.modal.tsx | 56 ++++++++ src/modals/modals.ts | 4 +- src/pages/manage/boards/index.tsx | 129 ++++++++++++++++++ src/tools/config/getFallbackConfig.ts | 62 +++++++++ src/types/settings.ts | 1 - src/validations/dashboards.ts | 5 + 7 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 src/modals/create-dashboard/create-dashboard.modal.tsx create mode 100644 src/pages/manage/boards/index.tsx create mode 100644 src/validations/dashboards.ts diff --git a/src/components/layout/admin/main-admin.layout.tsx b/src/components/layout/admin/main-admin.layout.tsx index 6a0767659..515896bc8 100644 --- a/src/components/layout/admin/main-admin.layout.tsx +++ b/src/components/layout/admin/main-admin.layout.tsx @@ -27,6 +27,7 @@ import { IconDashboard, IconGitFork, IconHome, + IconLayoutDashboard, IconLogout, IconMailForward, IconQuestionMark, @@ -75,6 +76,16 @@ export const MainLayout = ({ children }: MainLayoutProps) => { component={Link} href="/manage/" /> + + + + } + component={Link} + href="/manage/boards" + /> ) => { + const apiContext = api.useContext(); + const { isLoading, mutateAsync } = api.config.save.useMutation({ + onSuccess: async () => { + await apiContext.config.all.invalidate(); + modals.close(id); + }, + }); + + const { i18nZodResolver } = useI18nZodResolver(); + + const form = useForm({ + initialValues: { + name: '', + }, + validate: i18nZodResolver(createDashboardSchemaValidation), + }); + + return ( + + A name cannot be changed after a dashboard has been created. + + + + + + + + + ); +}; diff --git a/src/modals/modals.ts b/src/modals/modals.ts index 6dad48ffe..f80948a8d 100644 --- a/src/modals/modals.ts +++ b/src/modals/modals.ts @@ -9,6 +9,7 @@ import { CategoryEditModal } from '~/components/Dashboard/Wrappers/Category/Cate import { DeleteUserModal } from './delete-user/delete-user.modal'; import { CreateRegistrationTokenModal } from './create-registration-token/create-registration-token.modal'; import { DeleteRegistrationTokenModal } from './delete-registration-token/delete-registration-token.modal'; +import { CreateDashboardModal } from './create-dashboard/create-dashboard.modal'; export const modals = { editApp: EditAppModal, @@ -20,7 +21,8 @@ export const modals = { changeIntegrationPositionModal: ChangeWidgetPositionModal, deleteUserModal: DeleteUserModal, createRegistrationTokenModal: CreateRegistrationTokenModal, - deleteRegistrationTokenModal: DeleteRegistrationTokenModal + deleteRegistrationTokenModal: DeleteRegistrationTokenModal, + createDashboardModal: CreateDashboardModal }; declare module '@mantine/modals' { diff --git a/src/pages/manage/boards/index.tsx b/src/pages/manage/boards/index.tsx new file mode 100644 index 000000000..337196175 --- /dev/null +++ b/src/pages/manage/boards/index.tsx @@ -0,0 +1,129 @@ +import { + ActionIcon, + Badge, + Button, + Card, + Flex, + Group, + LoadingOverlay, + Menu, + SimpleGrid, + Table, + Text, + Title, +} from '@mantine/core'; +import { useListState } from '@mantine/hooks'; +import { modals } from '@mantine/modals'; +import { IconDotsVertical, IconPlus, IconTrash } from '@tabler/icons-react'; +import Link from 'next/link'; +import { MainLayout } from '~/components/layout/admin/main-admin.layout'; +import { CommonHeader } from '~/components/layout/common-header'; +import { sleep } from '~/tools/client/time'; +import { api } from '~/utils/api'; + +const BoardsPage = () => { + const { data } = api.config.all.useQuery(); + const context = api.useContext(); + const { mutateAsync: deletionMutationAsync } = api.config.delete.useMutation({ + onSettled: () => { + void context.config.all.invalidate(); + }, + }); + + const [deletingDashboards, { append, filter }] = useListState([]); + + return ( + + + Boards • Homarr + + + Boards + + + + + + {data && ( + + {data.map((board, index) => ( + + + + {board} + + Filesystem + + + + + With Fjord Tours you can explore more of the magical fjord landscapes with tours and + activities on and around the fjords of Norway + + + + + + + + + + + + { + append(board); + // give user feedback, that it's being deleted + await sleep(500); + deletionMutationAsync({ + name: board, + }).finally(async () => { + await sleep(500); + filter((item, _) => item !== board); + }); + }} + icon={} + color="red" + > + Permanently delete + + + + + + ))} + + )} + + ); +}; + +export default BoardsPage; diff --git a/src/tools/config/getFallbackConfig.ts b/src/tools/config/getFallbackConfig.ts index f6fd248ae..5cc72bf09 100644 --- a/src/tools/config/getFallbackConfig.ts +++ b/src/tools/config/getFallbackConfig.ts @@ -1,3 +1,4 @@ +import { ConfigType } from '~/types/config'; import defaultConfig from '../../../data/configs/default.json'; export const getFallbackConfig = (name?: string) => ({ @@ -6,3 +7,64 @@ export const getFallbackConfig = (name?: string) => ({ name: name ?? 'default', }, }); + +export const getStaticFallbackConfig = (name: string): ConfigType => ({ + schemaVersion: 1, + configProperties: { + name: name, + }, + categories: [ + { + id: '47af36c0-47c1-4e5b-bfc7-ad645ee6a33f', + position: 1, + name: 'Welcome to Homarr 🎉', + }, + ], + wrappers: [ + { + id: 'default', + position: 0, + }, + { + id: '47af36c0-47c1-4e5b-bfc7-ad645ee6a326', + position: 1, + }, + ], + apps: [], + widgets: [], + settings: { + common: { + searchEngine: { + type: 'google', + properties: { + enabled: true, + openInNewTab: true, + }, + }, + }, + customization: { + layout: { + enabledLeftSidebar: false, + enabledRightSidebar: false, + enabledDocker: false, + enabledPing: false, + enabledSearchbar: true, + }, + accessibility: { + disablePingPulse: false, + replacePingDotsWithIcons: false + }, + pageTitle: 'Homarr ⭐️', + logoImageUrl: '/imgs/logo/logo.png', + faviconUrl: '/imgs/favicon/favicon-squared.png', + backgroundImageUrl: '', + customCss: '', + colors: { + primary: 'red', + secondary: 'yellow', + shade: 7, + }, + appOpacity: 100, + }, + }, +}); diff --git a/src/types/settings.ts b/src/types/settings.ts index ddf2e3a0d..d09764d3f 100644 --- a/src/types/settings.ts +++ b/src/types/settings.ts @@ -7,7 +7,6 @@ export interface SettingsType { export interface CommonSettingsType { searchEngine: SearchEngineCommonSettingsType; - defaultConfig: string; } export type SearchEngineCommonSettingsType = diff --git a/src/validations/dashboards.ts b/src/validations/dashboards.ts new file mode 100644 index 000000000..e4bc4e3d4 --- /dev/null +++ b/src/validations/dashboards.ts @@ -0,0 +1,5 @@ +import { z } from 'zod'; + +export const createDashboardSchemaValidation = z.object({ + name: z.string().min(2).max(25), +});