mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-14 09:25:47 +01:00
@@ -13,6 +13,7 @@
|
|||||||
"previous": "Previous",
|
"previous": "Previous",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"enabled": "Enabled",
|
"enabled": "Enabled",
|
||||||
|
"duplicate": "Duplicate",
|
||||||
"disabled": "Disabled",
|
"disabled": "Disabled",
|
||||||
"enableAll": "Enable all",
|
"enableAll": "Enable all",
|
||||||
"disableAll": "Disable all",
|
"disableAll": "Disable all",
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export const EditAppModal = ({
|
|||||||
|
|
||||||
values.url = removeTrailingSlash(values.url);
|
values.url = removeTrailingSlash(values.url);
|
||||||
|
|
||||||
updateConfig(
|
void updateConfig(
|
||||||
configName,
|
configName,
|
||||||
(previousConfig) => ({
|
(previousConfig) => ({
|
||||||
...previousConfig,
|
...previousConfig,
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import { AppType } from '~/types/app';
|
|||||||
|
|
||||||
import { CategoryEditModalInnerProps } from '../../../../Wrappers/Category/CategoryEditModal';
|
import { CategoryEditModalInnerProps } from '../../../../Wrappers/Category/CategoryEditModal';
|
||||||
import { useStyles } from '../Shared/styles';
|
import { useStyles } from '../Shared/styles';
|
||||||
|
import { getLowestWrapper } from '~/tools/config/wrapper-finder';
|
||||||
|
import { ConfigType } from '~/types/config';
|
||||||
|
|
||||||
interface AvailableElementTypesProps {
|
interface AvailableElementTypesProps {
|
||||||
modalId: string;
|
modalId: string;
|
||||||
@@ -30,8 +32,6 @@ export const AvailableElementTypes = ({
|
|||||||
const { updateConfig } = useConfigStore();
|
const { updateConfig } = useConfigStore();
|
||||||
const { data } = useSession();
|
const { data } = useSession();
|
||||||
|
|
||||||
const getLowestWrapper = () => config?.wrappers.sort((a, b) => a.position - b.position)[0];
|
|
||||||
|
|
||||||
const onClickCreateCategory = async () => {
|
const onClickCreateCategory = async () => {
|
||||||
openContextModalGeneric<CategoryEditModalInnerProps>({
|
openContextModalGeneric<CategoryEditModalInnerProps>({
|
||||||
modal: 'categoryEditModal',
|
modal: 'categoryEditModal',
|
||||||
@@ -89,8 +89,7 @@ export const AvailableElementTypes = ({
|
|||||||
openContextModalGeneric<{ app: AppType; allowAppNamePropagation: boolean }>({
|
openContextModalGeneric<{ app: AppType; allowAppNamePropagation: boolean }>({
|
||||||
modal: 'editApp',
|
modal: 'editApp',
|
||||||
innerProps: {
|
innerProps: {
|
||||||
app: generateDefaultApp(getLowestWrapper()?.id ?? 'default'),
|
app: generateDefaultApp(getLowestWrapper(config as ConfigType)?.id ?? 'default'),
|
||||||
// TODO: Add translation? t('app.defaultName')
|
|
||||||
allowAppNamePropagation: true,
|
allowAppNamePropagation: true,
|
||||||
},
|
},
|
||||||
size: 'xl',
|
size: 'xl',
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { useConfigContext } from '~/config/provider';
|
import { useConfigContext } from '~/config/provider';
|
||||||
import { useConfigStore } from '~/config/store';
|
import { useConfigStore } from '~/config/store';
|
||||||
import { openContextModalGeneric } from '~/tools/mantineModalManagerExtensions';
|
import { openContextModalGeneric } from '~/tools/mantineModalManagerExtensions';
|
||||||
|
import { generateDefaultApp } from '~/tools/shared/app';
|
||||||
import { AppType } from '~/types/app';
|
import { AppType } from '~/types/app';
|
||||||
|
|
||||||
import { GenericTileMenu } from '../GenericTileMenu';
|
import { GenericTileMenu } from '../GenericTileMenu';
|
||||||
|
import { getLowestWrapper } from '~/tools/config/wrapper-finder';
|
||||||
|
|
||||||
interface TileMenuProps {
|
interface TileMenuProps {
|
||||||
app: AppType;
|
app: AppType;
|
||||||
@@ -13,6 +15,35 @@ export const AppMenu = ({ app }: TileMenuProps) => {
|
|||||||
const { config, name: configName } = useConfigContext();
|
const { config, name: configName } = useConfigContext();
|
||||||
const { updateConfig } = useConfigStore();
|
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 = () => {
|
const handleClickEdit = () => {
|
||||||
openContextModalGeneric<{ app: AppType; allowAppNamePropagation: boolean }>({
|
openContextModalGeneric<{ app: AppType; allowAppNamePropagation: boolean }>({
|
||||||
modal: 'editApp',
|
modal: 'editApp',
|
||||||
@@ -59,6 +90,7 @@ export const AppMenu = ({ app }: TileMenuProps) => {
|
|||||||
handleClickEdit={handleClickEdit}
|
handleClickEdit={handleClickEdit}
|
||||||
handleClickChangePosition={handleClickChangePosition}
|
handleClickChangePosition={handleClickChangePosition}
|
||||||
handleClickDelete={handleClickDelete}
|
handleClickDelete={handleClickDelete}
|
||||||
|
handleDuplicate={handleDuplicate}
|
||||||
displayEdit
|
displayEdit
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { ActionIcon, Menu } from '@mantine/core';
|
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 { useTranslation } from 'next-i18next';
|
||||||
import { useColorTheme } from '~/tools/color';
|
|
||||||
|
|
||||||
import { useEditModeStore } from '../Views/useEditModeStore';
|
import { useEditModeStore } from '../Views/useEditModeStore';
|
||||||
|
|
||||||
@@ -9,6 +14,7 @@ interface GenericTileMenuProps {
|
|||||||
handleClickEdit: () => void;
|
handleClickEdit: () => void;
|
||||||
handleClickChangePosition: () => void;
|
handleClickChangePosition: () => void;
|
||||||
handleClickDelete: () => void;
|
handleClickDelete: () => void;
|
||||||
|
handleDuplicate?: () => void;
|
||||||
displayEdit: boolean;
|
displayEdit: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,6 +22,7 @@ export const GenericTileMenu = ({
|
|||||||
handleClickEdit,
|
handleClickEdit,
|
||||||
handleClickChangePosition,
|
handleClickChangePosition,
|
||||||
handleClickDelete,
|
handleClickDelete,
|
||||||
|
handleDuplicate,
|
||||||
displayEdit,
|
displayEdit,
|
||||||
}: GenericTileMenuProps) => {
|
}: GenericTileMenuProps) => {
|
||||||
const { t } = useTranslation('common');
|
const { t } = useTranslation('common');
|
||||||
@@ -47,6 +54,11 @@ export const GenericTileMenu = ({
|
|||||||
{t('edit')}
|
{t('edit')}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
)}
|
)}
|
||||||
|
{handleDuplicate && (
|
||||||
|
<Menu.Item icon={<IconCopy size={'1rem'} />} onClick={handleDuplicate}>
|
||||||
|
{t('duplicate')}
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
icon={<IconLayoutKanban size={16} stroke={1.5} />}
|
icon={<IconLayoutKanban size={16} stroke={1.5} />}
|
||||||
onClick={handleClickChangePosition}
|
onClick={handleClickChangePosition}
|
||||||
|
|||||||
3
src/tools/config/wrapper-finder.ts
Normal file
3
src/tools/config/wrapper-finder.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { ConfigType } from '~/types/config';
|
||||||
|
|
||||||
|
export const getLowestWrapper = (config: ConfigType) => config?.wrappers.sort((a, b) => a.position - b.position)[0];
|
||||||
Reference in New Issue
Block a user