mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 07:25:48 +01:00
Fixing console errors and adding category modal
This commit is contained in:
@@ -23,7 +23,6 @@ export const AppearanceTab = ({
|
|||||||
<Tabs.Panel value="appearance" pt="lg">
|
<Tabs.Panel value="appearance" pt="lg">
|
||||||
<Flex gap={5}>
|
<Flex gap={5}>
|
||||||
<TextInput
|
<TextInput
|
||||||
defaultValue={form.values.appearance.iconUrl}
|
|
||||||
className={classes.textInput}
|
className={classes.textInput}
|
||||||
icon={<DebouncedAppIcon form={form} width={20} height={20} />}
|
icon={<DebouncedAppIcon form={form} width={20} height={20} />}
|
||||||
label={t('appearance.icon.label')}
|
label={t('appearance.icon.label')}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ interface IconSelectorProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const IconSelector = ({ onChange, allowAppNamePropagation, form }: IconSelectorProps) => {
|
export const IconSelector = ({ onChange, allowAppNamePropagation, form }: IconSelectorProps) => {
|
||||||
|
const { t } = useTranslation('layout/tools');
|
||||||
|
|
||||||
const { data, isLoading } = useRepositoryIconsQuery<WalkxcodeRepositoryIcon>({
|
const { data, isLoading } = useRepositoryIconsQuery<WalkxcodeRepositoryIcon>({
|
||||||
url: 'https://api.github.com/repos/walkxcode/Dashboard-Icons/contents/png',
|
url: 'https://api.github.com/repos/walkxcode/Dashboard-Icons/contents/png',
|
||||||
converter: (item) => ({
|
converter: (item) => ({
|
||||||
@@ -73,8 +75,6 @@ export const IconSelector = ({ onChange, allowAppNamePropagation, form }: IconSe
|
|||||||
const isTruncated =
|
const isTruncated =
|
||||||
slicedFilteredItems.length > 0 && slicedFilteredItems.length !== filteredItems.length;
|
slicedFilteredItems.length > 0 && slicedFilteredItems.length !== filteredItems.length;
|
||||||
|
|
||||||
const { t } = useTranslation('layout/tools');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover width={310}>
|
<Popover width={310}>
|
||||||
<Popover.Target>
|
<Popover.Target>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Group, Space, Stack, Text, UnstyledButton } from '@mantine/core';
|
import { Group, Space, Stack, Text, UnstyledButton } from '@mantine/core';
|
||||||
import { closeModal } from '@mantine/modals';
|
import { closeModal } from '@mantine/modals';
|
||||||
|
import { showNotification } from '@mantine/notifications';
|
||||||
import { IconBox, IconBoxAlignTop, IconStack } from '@tabler/icons';
|
import { IconBox, IconBoxAlignTop, IconStack } from '@tabler/icons';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
@@ -9,6 +10,7 @@ import { useConfigStore } from '../../../../../../config/store';
|
|||||||
import { openContextModalGeneric } from '../../../../../../tools/mantineModalManagerExtensions';
|
import { openContextModalGeneric } from '../../../../../../tools/mantineModalManagerExtensions';
|
||||||
import { AppType } from '../../../../../../types/app';
|
import { AppType } from '../../../../../../types/app';
|
||||||
import { appTileDefinition } from '../../../../Tiles/Apps/AppTile';
|
import { appTileDefinition } from '../../../../Tiles/Apps/AppTile';
|
||||||
|
import { CategoryEditModalInnerProps } from '../../../../Wrappers/Category/CategoryEditModal';
|
||||||
import { useStyles } from '../Shared/styles';
|
import { useStyles } from '../Shared/styles';
|
||||||
|
|
||||||
interface AvailableElementTypesProps {
|
interface AvailableElementTypesProps {
|
||||||
@@ -28,33 +30,50 @@ export const AvailableElementTypes = ({
|
|||||||
const getLowestWrapper = () => config?.wrappers.sort((a, b) => a.position - b.position)[0];
|
const getLowestWrapper = () => config?.wrappers.sort((a, b) => a.position - b.position)[0];
|
||||||
|
|
||||||
const onClickCreateCategory = async () => {
|
const onClickCreateCategory = async () => {
|
||||||
if (!configName) {
|
openContextModalGeneric<CategoryEditModalInnerProps>({
|
||||||
return;
|
modal: 'categoryEditModal',
|
||||||
}
|
title: 'Name of new category',
|
||||||
|
withCloseButton: false,
|
||||||
|
innerProps: {
|
||||||
|
category: {
|
||||||
|
id: uuidv4(),
|
||||||
|
name: 'New category',
|
||||||
|
position: 0,
|
||||||
|
},
|
||||||
|
onSuccess: async (category) => {
|
||||||
|
if (!configName) return;
|
||||||
|
|
||||||
await updateConfig(configName, (previousConfig) => ({
|
await updateConfig(configName, (previousConfig) => ({
|
||||||
...previousConfig,
|
...previousConfig,
|
||||||
wrappers:
|
wrappers:
|
||||||
previousConfig.wrappers.length <= previousConfig.categories.length
|
previousConfig.wrappers.length <= previousConfig.categories.length
|
||||||
? [
|
? [
|
||||||
...previousConfig.wrappers,
|
...previousConfig.wrappers,
|
||||||
|
{
|
||||||
|
id: uuidv4(),
|
||||||
|
position: previousConfig.categories.length,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: previousConfig.wrappers,
|
||||||
|
categories: [
|
||||||
|
...previousConfig.categories,
|
||||||
{
|
{
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
|
name: category.name,
|
||||||
position: previousConfig.categories.length,
|
position: previousConfig.categories.length,
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
: previousConfig.wrappers,
|
})).then(() => {
|
||||||
categories: [
|
closeModal(modalId);
|
||||||
...previousConfig.categories,
|
showNotification({
|
||||||
{
|
title: 'Category created',
|
||||||
id: uuidv4(),
|
message: `The category ${category.name} has been created`,
|
||||||
name: `Category ${previousConfig.categories.length + 1}`,
|
color: 'teal',
|
||||||
position: previousConfig.categories.length,
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
}));
|
});
|
||||||
|
|
||||||
closeModal(modalId);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export const CategoryEditModal = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={form.onSubmit(handleSubmit)}>
|
<form onSubmit={form.onSubmit(handleSubmit)}>
|
||||||
<TextInput data-autoFocus {...form.getInputProps('name')} label="Name of category" />
|
<TextInput data-autoFocus {...form.getInputProps('name')} autoFocus />
|
||||||
|
|
||||||
<Group mt="md" grow>
|
<Group mt="md" grow>
|
||||||
<Button onClick={() => context.closeModal(id)} variant="filled" color="gray">
|
<Button onClick={() => context.closeModal(id)} variant="filled" color="gray">
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ export const useCategoryActions = (configName: string | undefined, category: Cat
|
|||||||
const edit = async () => {
|
const edit = async () => {
|
||||||
openContextModalGeneric<CategoryEditModalInnerProps>({
|
openContextModalGeneric<CategoryEditModalInnerProps>({
|
||||||
modal: 'categoryEditModal',
|
modal: 'categoryEditModal',
|
||||||
|
withCloseButton: false,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
category,
|
category,
|
||||||
onSuccess: async (category) => {
|
onSuccess: async (category) => {
|
||||||
|
|||||||
@@ -59,14 +59,14 @@ export const ToggleEditModeAction = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip label={t('tooltip')} withinPortal>
|
<Popover
|
||||||
<Popover
|
opened={enabled && !smallerThanSm && !popoverManuallyHidden}
|
||||||
opened={enabled && !smallerThanSm && !popoverManuallyHidden}
|
width={250}
|
||||||
width={250}
|
zIndex={199}
|
||||||
zIndex={199}
|
withArrow
|
||||||
withArrow
|
>
|
||||||
>
|
<Popover.Target>
|
||||||
<Popover.Target>
|
<Tooltip label={t('tooltip')} withinPortal>
|
||||||
{smallerThanSm ? (
|
{smallerThanSm ? (
|
||||||
enabled ? (
|
enabled ? (
|
||||||
<Group style={{ flexWrap: 'nowrap' }}>
|
<Group style={{ flexWrap: 'nowrap' }}>
|
||||||
@@ -84,22 +84,22 @@ export const ToggleEditModeAction = () => {
|
|||||||
) : (
|
) : (
|
||||||
<ToggleButtonDesktop />
|
<ToggleButtonDesktop />
|
||||||
)}
|
)}
|
||||||
</Popover.Target>
|
</Tooltip>
|
||||||
|
</Popover.Target>
|
||||||
|
|
||||||
<Popover.Dropdown p={4} px={6}>
|
<Popover.Dropdown p={4} px={6}>
|
||||||
<div style={{ position: 'absolute', top: 2, right: 2 }}>
|
<div style={{ position: 'absolute', top: 2, right: 2 }}>
|
||||||
<ActionIcon onClick={() => setPopoverManuallyHidden(true)}>
|
<ActionIcon onClick={() => setPopoverManuallyHidden(true)}>
|
||||||
<IconX size={18} />
|
<IconX size={18} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</div>
|
</div>
|
||||||
<Text align="center" size="sm">
|
<Text align="center" size="sm">
|
||||||
<Text weight="bold">{t('popover.title')}</Text>
|
<Text weight="bold">{t('popover.title')}</Text>
|
||||||
<Text>
|
<Text>
|
||||||
<Trans i18nKey="layout/header/actions/toggle-edit-mode:popover.text" />
|
<Trans i18nKey="layout/header/actions/toggle-edit-mode:popover.text" />
|
||||||
</Text>
|
|
||||||
</Text>
|
</Text>
|
||||||
</Popover.Dropdown>
|
</Text>
|
||||||
</Popover>
|
</Popover.Dropdown>
|
||||||
</Tooltip>
|
</Popover>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,35 +13,33 @@ export function SettingsMenu({ newVersionAvailable }: { newVersionAvailable: str
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tooltip label="Open Menu">
|
<Menu width={250}>
|
||||||
<Menu width={250}>
|
<Menu.Target>
|
||||||
<Menu.Target>
|
<ActionIcon variant="default" radius="md" size="xl" color="blue">
|
||||||
<ActionIcon variant="default" radius="md" size="xl" color="blue">
|
<IconMenu2 />
|
||||||
<IconMenu2 />
|
</ActionIcon>
|
||||||
</ActionIcon>
|
</Menu.Target>
|
||||||
</Menu.Target>
|
<Menu.Dropdown>
|
||||||
<Menu.Dropdown>
|
<ColorSchemeSwitch />
|
||||||
<ColorSchemeSwitch />
|
<Menu.Divider />
|
||||||
<Menu.Divider />
|
<Menu.Item icon={<IconSettings strokeWidth={1.2} size={18} />} onClick={drawer.open}>
|
||||||
<Menu.Item icon={<IconSettings strokeWidth={1.2} size={18} />} onClick={drawer.open}>
|
{t('sections.settings')}
|
||||||
{t('sections.settings')}
|
</Menu.Item>
|
||||||
</Menu.Item>
|
<Menu.Item
|
||||||
<Menu.Item
|
icon={<IconInfoCircle strokeWidth={1.2} size={18} />}
|
||||||
icon={<IconInfoCircle strokeWidth={1.2} size={18} />}
|
rightSection={
|
||||||
rightSection={
|
newVersionAvailable && (
|
||||||
newVersionAvailable && (
|
<Badge variant="light" color="blue">
|
||||||
<Badge variant="light" color="blue">
|
New
|
||||||
New
|
</Badge>
|
||||||
</Badge>
|
)
|
||||||
)
|
}
|
||||||
}
|
onClick={() => aboutModal.open()}
|
||||||
onClick={() => aboutModal.open()}
|
>
|
||||||
>
|
{t('about')}
|
||||||
{t('about')}
|
</Menu.Item>
|
||||||
</Menu.Item>
|
</Menu.Dropdown>
|
||||||
</Menu.Dropdown>
|
</Menu>
|
||||||
</Menu>
|
|
||||||
</Tooltip>
|
|
||||||
<SettingsDrawer
|
<SettingsDrawer
|
||||||
opened={drawerOpened}
|
opened={drawerOpened}
|
||||||
closeDrawer={drawer.close}
|
closeDrawer={drawer.close}
|
||||||
|
|||||||
Reference in New Issue
Block a user