From 6fdf1dfaa8a8faa39d83631c96a65f1e37bf440c Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Sun, 28 Jan 2024 21:15:08 +0100 Subject: [PATCH] feat: #1835 copy apps (#1854) --- public/locales/en/common.json | 1 + .../Modals/EditAppModal/EditAppModal.tsx | 2 +- .../Overview/AvailableElementsOverview.tsx | 7 ++-- .../Dashboard/Tiles/Apps/AppMenu.tsx | 32 +++++++++++++++++++ .../Dashboard/Tiles/GenericTileMenu.tsx | 16 ++++++++-- src/tools/config/wrapper-finder.ts | 3 ++ 6 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 src/tools/config/wrapper-finder.ts diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 18cc8e650..bebc69de8 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -13,6 +13,7 @@ "previous": "Previous", "confirm": "Confirm", "enabled": "Enabled", + "duplicate": "Duplicate", "disabled": "Disabled", "enableAll": "Enable all", "disableAll": "Disable all", diff --git a/src/components/Dashboard/Modals/EditAppModal/EditAppModal.tsx b/src/components/Dashboard/Modals/EditAppModal/EditAppModal.tsx index b70f70b1d..7b5010604 100644 --- a/src/components/Dashboard/Modals/EditAppModal/EditAppModal.tsx +++ b/src/components/Dashboard/Modals/EditAppModal/EditAppModal.tsx @@ -93,7 +93,7 @@ export const EditAppModal = ({ values.url = removeTrailingSlash(values.url); - updateConfig( + void updateConfig( configName, (previousConfig) => ({ ...previousConfig, diff --git a/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx b/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx index 3c7ce5262..87a121e07 100644 --- a/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx +++ b/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx @@ -15,6 +15,8 @@ import { AppType } from '~/types/app'; import { CategoryEditModalInnerProps } from '../../../../Wrappers/Category/CategoryEditModal'; import { useStyles } from '../Shared/styles'; +import { getLowestWrapper } from '~/tools/config/wrapper-finder'; +import { ConfigType } from '~/types/config'; interface AvailableElementTypesProps { modalId: string; @@ -30,8 +32,6 @@ export const AvailableElementTypes = ({ const { updateConfig } = useConfigStore(); const { data } = useSession(); - const getLowestWrapper = () => config?.wrappers.sort((a, b) => a.position - b.position)[0]; - const onClickCreateCategory = async () => { openContextModalGeneric({ modal: 'categoryEditModal', @@ -89,8 +89,7 @@ export const AvailableElementTypes = ({ openContextModalGeneric<{ app: AppType; allowAppNamePropagation: boolean }>({ modal: 'editApp', innerProps: { - app: generateDefaultApp(getLowestWrapper()?.id ?? 'default'), - // TODO: Add translation? t('app.defaultName') + app: generateDefaultApp(getLowestWrapper(config as ConfigType)?.id ?? 'default'), allowAppNamePropagation: true, }, size: 'xl', diff --git a/src/components/Dashboard/Tiles/Apps/AppMenu.tsx b/src/components/Dashboard/Tiles/Apps/AppMenu.tsx index a8f9715eb..e823d640e 100644 --- a/src/components/Dashboard/Tiles/Apps/AppMenu.tsx +++ b/src/components/Dashboard/Tiles/Apps/AppMenu.tsx @@ -1,9 +1,11 @@ import { useConfigContext } from '~/config/provider'; import { useConfigStore } from '~/config/store'; import { openContextModalGeneric } from '~/tools/mantineModalManagerExtensions'; +import { generateDefaultApp } from '~/tools/shared/app'; import { AppType } from '~/types/app'; import { GenericTileMenu } from '../GenericTileMenu'; +import { getLowestWrapper } from '~/tools/config/wrapper-finder'; interface TileMenuProps { app: AppType; @@ -13,6 +15,35 @@ export const AppMenu = ({ app }: TileMenuProps) => { const { config, name: configName } = useConfigContext(); const { updateConfig } = useConfigStore(); + const handleDuplicate = () => { + if (!configName || !config) { + return; + } + + const newApp = generateDefaultApp(getLowestWrapper(config)?.id ?? 'default'); + newApp.name = app.name; + newApp.url = app.url; + newApp.behaviour = app.behaviour; + newApp.network = app.network; + newApp.appearance = app.appearance; + newApp.integration = app.integration; + + void updateConfig( + configName, + (previousConfig) => ({ + ...previousConfig, + apps: [ + ...previousConfig.apps, + { + ...newApp, + }, + ], + }), + true, + true + ); + }; + const handleClickEdit = () => { openContextModalGeneric<{ app: AppType; allowAppNamePropagation: boolean }>({ modal: 'editApp', @@ -59,6 +90,7 @@ export const AppMenu = ({ app }: TileMenuProps) => { handleClickEdit={handleClickEdit} handleClickChangePosition={handleClickChangePosition} handleClickDelete={handleClickDelete} + handleDuplicate={handleDuplicate} displayEdit /> ); diff --git a/src/components/Dashboard/Tiles/GenericTileMenu.tsx b/src/components/Dashboard/Tiles/GenericTileMenu.tsx index 32cb94fa4..815e831ed 100644 --- a/src/components/Dashboard/Tiles/GenericTileMenu.tsx +++ b/src/components/Dashboard/Tiles/GenericTileMenu.tsx @@ -1,7 +1,12 @@ import { ActionIcon, Menu } from '@mantine/core'; -import { IconLayoutKanban, IconPencil, IconSettings, IconTrash } from '@tabler/icons-react'; +import { + IconCopy, + IconLayoutKanban, + IconPencil, + IconSettings, + IconTrash, +} from '@tabler/icons-react'; import { useTranslation } from 'next-i18next'; -import { useColorTheme } from '~/tools/color'; import { useEditModeStore } from '../Views/useEditModeStore'; @@ -9,6 +14,7 @@ interface GenericTileMenuProps { handleClickEdit: () => void; handleClickChangePosition: () => void; handleClickDelete: () => void; + handleDuplicate?: () => void; displayEdit: boolean; } @@ -16,6 +22,7 @@ export const GenericTileMenu = ({ handleClickEdit, handleClickChangePosition, handleClickDelete, + handleDuplicate, displayEdit, }: GenericTileMenuProps) => { const { t } = useTranslation('common'); @@ -47,6 +54,11 @@ export const GenericTileMenu = ({ {t('edit')} )} + {handleDuplicate && ( + } onClick={handleDuplicate}> + {t('duplicate')} + + )} } onClick={handleClickChangePosition} diff --git a/src/tools/config/wrapper-finder.ts b/src/tools/config/wrapper-finder.ts new file mode 100644 index 000000000..c67576927 --- /dev/null +++ b/src/tools/config/wrapper-finder.ts @@ -0,0 +1,3 @@ +import { ConfigType } from '~/types/config'; + +export const getLowestWrapper = (config: ConfigType) => config?.wrappers.sort((a, b) => a.position - b.position)[0]; \ No newline at end of file