mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-14 17:26:26 +01:00
Update default config
This commit is contained in:
@@ -20,7 +20,6 @@ export const GeneralTab = ({ form, openTab }: GeneralTabProps) => {
|
||||
description={t('general.appname.description')}
|
||||
placeholder="My example app"
|
||||
variant="default"
|
||||
mb="md"
|
||||
withAsterisk
|
||||
required
|
||||
{...form.getInputProps('name')}
|
||||
@@ -45,7 +44,7 @@ export const GeneralTab = ({ form, openTab }: GeneralTabProps) => {
|
||||
description={t('general.externalAddress.description')}
|
||||
placeholder="https://homarr.mywebsite.com/"
|
||||
variant="default"
|
||||
mb="md"
|
||||
required
|
||||
{...form.getInputProps('behaviour.externalUrl')}
|
||||
/>
|
||||
</Tabs.Panel>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ContextModalProps } from '@mantine/modals';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useState } from 'react';
|
||||
import Widgets from '../../../../widgets';
|
||||
import type { IWidgetOptionValue } from '../../../../widgets/widgets';
|
||||
import { useConfigContext } from '../../../../config/provider';
|
||||
import { useConfigStore } from '../../../../config/store';
|
||||
import { IWidget } from '../../../../widgets/widgets';
|
||||
@@ -23,6 +24,8 @@ export const WidgetsEditModal = ({
|
||||
const [moduleProperties, setModuleProperties] = useState(innerProps.options);
|
||||
const items = Object.entries(moduleProperties ?? {}) as [string, IntegrationOptionsValueType][];
|
||||
|
||||
// Find the Key in the "Widgets" Object that matches the widgetId
|
||||
const currentWidgetDefinition = Widgets[innerProps.widgetId as keyof typeof Widgets];
|
||||
const { name: configName } = useConfigContext();
|
||||
const updateConfig = useConfigStore((x) => x.updateConfig);
|
||||
|
||||
@@ -63,33 +66,38 @@ export const WidgetsEditModal = ({
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
{items.map(([key, value]) => (
|
||||
<>
|
||||
{typeof value === 'boolean' ? (
|
||||
<Switch
|
||||
label={t(`descriptor.settings.${key}.label`)}
|
||||
checked={value}
|
||||
onChange={(ev) => handleChange(key, ev.currentTarget.checked)}
|
||||
/>
|
||||
) : null}
|
||||
{typeof value === 'string' ? (
|
||||
<TextInput
|
||||
label={t(`descriptor.settings.${key}.label`)}
|
||||
value={value}
|
||||
onChange={(ev) => handleChange(key, ev.currentTarget.value)}
|
||||
/>
|
||||
) : null}
|
||||
{typeof value === 'object' && Array.isArray(value) ? (
|
||||
<MultiSelect
|
||||
data={getMutliselectData(key)}
|
||||
label={t(`descriptor.settings.${key}.label`)}
|
||||
value={value}
|
||||
onChange={(v) => handleChange(key, v)}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
))}
|
||||
|
||||
{items.map(([key, value]) => {
|
||||
const option = (currentWidgetDefinition as any).options[key] as IWidgetOptionValue;
|
||||
switch (option.type) {
|
||||
case 'switch':
|
||||
return (
|
||||
<Switch
|
||||
label={t(`descriptor.settings.${key}.label`)}
|
||||
checked={value as boolean}
|
||||
onChange={(ev) => handleChange(key, ev.currentTarget.checked)}
|
||||
/>
|
||||
);
|
||||
case 'text':
|
||||
return (
|
||||
<TextInput
|
||||
label={t(`descriptor.settings.${key}.label`)}
|
||||
value={value as string}
|
||||
onChange={(ev) => handleChange(key, ev.currentTarget.value)}
|
||||
/>
|
||||
);
|
||||
case 'multi-select':
|
||||
return (
|
||||
<MultiSelect
|
||||
data={getMutliselectData(key)}
|
||||
label={t(`descriptor.settings.${key}.label`)}
|
||||
value={value as string[]}
|
||||
onChange={(v) => handleChange(key, v)}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
<Group position="right">
|
||||
<Button onClick={() => context.closeModal(id)} variant="light">
|
||||
{t('common:cancel')}
|
||||
@@ -99,3 +107,41 @@ export const WidgetsEditModal = ({
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
// <Stack>
|
||||
// {items.map(([key, value]) => (
|
||||
// <>
|
||||
// {typeof value === 'boolean' ? (
|
||||
// <Switch
|
||||
// label={t(`descriptor.settings.${key}.label`)}
|
||||
// checked={value}
|
||||
// onChange={(ev) => handleChange(key, ev.currentTarget.checked)}
|
||||
// />
|
||||
// ) : null}
|
||||
// {typeof value === 'string' ? (
|
||||
// <TextInput
|
||||
// label={t(`descriptor.settings.${key}.label`)}
|
||||
// value={value}
|
||||
// onChange={(ev) => handleChange(key, ev.currentTarget.value)}
|
||||
// />
|
||||
// ) : null}
|
||||
// {typeof value === 'object' && Array.isArray(value) ? (
|
||||
// <MultiSelect
|
||||
// data={getMutliselectData(key)}
|
||||
// label={t(`descriptor.settings.${key}.label`)}
|
||||
// value={value}
|
||||
// onChange={(v) => handleChange(key, v)}
|
||||
// />
|
||||
// ) : null}
|
||||
// </>
|
||||
// ))}
|
||||
|
||||
// <Group position="right">
|
||||
// <Button onClick={() => context.closeModal(id)} variant="light">
|
||||
// {t('common:cancel')}
|
||||
// </Button>
|
||||
// <Button onClick={handleSave}>{t('common:save')}</Button>
|
||||
// </Group>
|
||||
// </Stack>
|
||||
// );
|
||||
// };
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
IconRowInsertTop,
|
||||
IconRowInsertBottom,
|
||||
IconEdit,
|
||||
IconTrash,
|
||||
} from '@tabler/icons';
|
||||
import { useConfigContext } from '../../../../config/provider';
|
||||
import { CategoryType } from '../../../../types/category';
|
||||
@@ -17,11 +18,11 @@ interface CategoryEditMenuProps {
|
||||
|
||||
export const CategoryEditMenu = ({ category }: CategoryEditMenuProps) => {
|
||||
const { name: configName } = useConfigContext();
|
||||
const { addCategoryAbove, addCategoryBelow, moveCategoryUp, moveCategoryDown, edit } =
|
||||
const { addCategoryAbove, addCategoryBelow, moveCategoryUp, moveCategoryDown, edit, remove } =
|
||||
useCategoryActions(configName, category);
|
||||
|
||||
return (
|
||||
<Menu withinPortal>
|
||||
<Menu withinPortal position="left-start" withArrow>
|
||||
<Menu.Target>
|
||||
<ActionIcon>
|
||||
<IconDots />
|
||||
@@ -31,6 +32,9 @@ export const CategoryEditMenu = ({ category }: CategoryEditMenuProps) => {
|
||||
<Menu.Item icon={<IconEdit size={20} />} onClick={edit}>
|
||||
Edit
|
||||
</Menu.Item>
|
||||
<Menu.Item icon={<IconTrash size={20} />} onClick={remove}>
|
||||
Remove
|
||||
</Menu.Item>
|
||||
<Menu.Label>Change positon</Menu.Label>
|
||||
<Menu.Item icon={<IconTransitionTop size={20} />} onClick={moveCategoryUp}>
|
||||
Move up
|
||||
|
||||
@@ -39,7 +39,7 @@ export const CategoryEditModal = ({
|
||||
<TextInput data-autoFocus {...form.getInputProps('name')} label="Name of category" />
|
||||
|
||||
<Group mt="md" grow>
|
||||
<Button onClick={() => context.closeModal(id)} variant="light" color="gray">
|
||||
<Button onClick={() => context.closeModal(id)} variant="filled" color="gray">
|
||||
{t('cancel')}
|
||||
</Button>
|
||||
<Button type="submit">{t('save')}</Button>
|
||||
|
||||
@@ -176,6 +176,37 @@ export const useCategoryActions = (configName: string | undefined, category: Cat
|
||||
);
|
||||
};
|
||||
|
||||
// Removes the current category
|
||||
const remove = () => {
|
||||
if (!configName) return;
|
||||
updateConfig(
|
||||
configName,
|
||||
(previous) => {
|
||||
const currentItem = previous.categories.find((x) => x.id === category.id);
|
||||
if (!currentItem) return previous;
|
||||
// Find the main wrapper
|
||||
const mainWrapper = previous.wrappers.find((x) => x.position === 1);
|
||||
|
||||
// Check that the app has an area.type or "category" and that the area.id is the current category
|
||||
const appsToMove = previous.apps.filter(
|
||||
(x) => x.area && x.area.type === 'category' && x.area.properties.id === currentItem.id
|
||||
);
|
||||
appsToMove.forEach((x) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
x.area = { type: 'wrapper', properties: { id: mainWrapper?.id ?? 'default' } };
|
||||
});
|
||||
|
||||
return {
|
||||
...previous,
|
||||
apps: previous.apps,
|
||||
categories: previous.categories.filter((x) => x.id !== category.id),
|
||||
wrappers: previous.wrappers.filter((x) => x.position !== currentItem.position),
|
||||
};
|
||||
},
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
const edit = async () => {
|
||||
openContextModalGeneric<CategoryEditModalInnerProps>({
|
||||
modal: 'categoryEditModal',
|
||||
@@ -201,6 +232,7 @@ export const useCategoryActions = (configName: string | undefined, category: Cat
|
||||
addCategoryBelow,
|
||||
moveCategoryUp,
|
||||
moveCategoryDown,
|
||||
remove,
|
||||
edit,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -15,10 +15,8 @@ export function Logo({ size = 'md', withoutText = false }: LogoProps) {
|
||||
<Group spacing={size === 'md' ? 'xs' : 4} noWrap>
|
||||
<Image
|
||||
width={size === 'md' ? 50 : 12}
|
||||
src={config?.settings.customization.logoImageUrl || '/imgs/logo/logo.png'}
|
||||
style={{
|
||||
position: 'relative',
|
||||
}}
|
||||
src={config?.settings.customization.logoImageUrl || '/imgs/logo/logo-color.svg'}
|
||||
alt="Homarr Logo"
|
||||
/>
|
||||
{withoutText ? null : (
|
||||
<Text
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { ActionIcon, Button, Popover, Text, Tooltip } from '@mantine/core';
|
||||
import { IconEditCircle, IconEditCircleOff, IconX } from '@tabler/icons';
|
||||
import axios from 'axios';
|
||||
import Consola from 'consola';
|
||||
import { getCookie } from 'cookies-next';
|
||||
import { Trans, useTranslation } from 'next-i18next';
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useConfigContext } from '../../../../../config/provider';
|
||||
import { useScreenSmallerThan } from '../../../../../hooks/useScreenSmallerThan';
|
||||
|
||||
import { useEditModeStore } from '../../../../Dashboard/Views/useEditModeStore';
|
||||
@@ -13,9 +17,18 @@ export const ToggleEditModeAction = () => {
|
||||
const { t } = useTranslation('layout/header/actions/toggle-edit-mode');
|
||||
|
||||
const smallerThanSm = useScreenSmallerThan('sm');
|
||||
const { config } = useConfigContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (enabled || config === undefined || config?.schemaVersion === undefined) return;
|
||||
const configName = getCookie('config-name')?.toString() ?? 'default';
|
||||
axios.put(`/api/configs/${configName}`, { ...config });
|
||||
Consola.log('Saved config to server', configName);
|
||||
}, [enabled]);
|
||||
|
||||
const toggleButtonClicked = () => {
|
||||
toggleEditMode();
|
||||
|
||||
setPopoverManuallyHidden(false);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user