🐛 Fix issue with creation of app / widget

This commit is contained in:
Meierschlumpf
2022-12-24 11:11:51 +01:00
parent ab523a55d0
commit 654107f60d
8 changed files with 44 additions and 91 deletions

View File

@@ -14,6 +14,7 @@ import { useState } from 'react';
import { useConfigContext } from '../../../../config/provider'; import { useConfigContext } from '../../../../config/provider';
import { useConfigStore } from '../../../../config/store'; import { useConfigStore } from '../../../../config/store';
import { AppType } from '../../../../types/app'; import { AppType } from '../../../../types/app';
import { useEditModeStore } from '../../Views/useEditModeStore';
import { AppearanceTab } from './Tabs/AppereanceTab/AppereanceTab'; import { AppearanceTab } from './Tabs/AppereanceTab/AppereanceTab';
import { BehaviourTab } from './Tabs/BehaviourTab/BehaviourTab'; import { BehaviourTab } from './Tabs/BehaviourTab/BehaviourTab';
import { GeneralTab } from './Tabs/GeneralTab/GeneralTab'; import { GeneralTab } from './Tabs/GeneralTab/GeneralTab';
@@ -33,6 +34,7 @@ export const EditAppModal = ({
const { t } = useTranslation(['layout/modals/add-app', 'common']); const { t } = useTranslation(['layout/modals/add-app', 'common']);
const { name: configName, config } = useConfigContext(); const { name: configName, config } = useConfigContext();
const updateConfig = useConfigStore((store) => store.updateConfig); const updateConfig = useConfigStore((store) => store.updateConfig);
const { enabled: isEditMode } = useEditModeStore();
const [allowAppNamePropagation, setAllowAppNamePropagation] = useState<boolean>( const [allowAppNamePropagation, setAllowAppNamePropagation] = useState<boolean>(
innerProps.allowAppNamePropagation innerProps.allowAppNamePropagation
); );
@@ -87,9 +89,15 @@ export const EditAppModal = ({
configName, configName,
(previousConfig) => ({ (previousConfig) => ({
...previousConfig, ...previousConfig,
apps: [...previousConfig.apps.filter((x) => x.id !== form.values.id), form.values], apps: [
...previousConfig.apps.filter((x) => x.id !== values.id),
{
...values,
},
],
}), }),
true true,
!isEditMode
); );
// also close the parent modal // also close the parent modal

View File

@@ -3,8 +3,10 @@ import { IconBox, IconStack } from '@tabler/icons';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { useConfigContext } from '../../../../../../config/provider';
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 { useStyles } from '../Shared/styles'; import { useStyles } from '../Shared/styles';
interface AvailableElementTypesProps { interface AvailableElementTypesProps {
@@ -17,6 +19,8 @@ export const AvailableElementTypes = ({
onOpenStaticElements, onOpenStaticElements,
}: AvailableElementTypesProps) => { }: AvailableElementTypesProps) => {
const { t } = useTranslation('layout/element-selector/selector'); const { t } = useTranslation('layout/element-selector/selector');
const { config } = useConfigContext();
const getLowestWrapper = () => config?.wrappers.sort((a, b) => a.position - b.position)[0];
return ( return (
<> <>
@@ -45,10 +49,11 @@ export const AvailableElementTypes = ({
isOpeningNewTab: true, isOpeningNewTab: true,
externalUrl: '', externalUrl: '',
}, },
area: { area: {
type: 'sidebar', type: 'wrapper',
properties: { properties: {
location: 'right', id: getLowestWrapper()?.id ?? '',
}, },
}, },
shape: { shape: {
@@ -57,8 +62,8 @@ export const AvailableElementTypes = ({
y: 0, y: 0,
}, },
size: { size: {
height: 1, width: appTileDefinition.minWidth,
width: 1, height: appTileDefinition.minHeight,
}, },
}, },
integration: { integration: {

View File

@@ -4,6 +4,7 @@ import { useTranslation } from 'next-i18next';
import { useConfigContext } from '../../../../../../config/provider'; import { useConfigContext } from '../../../../../../config/provider';
import { useConfigStore } from '../../../../../../config/store'; import { useConfigStore } from '../../../../../../config/store';
import { IWidget, IWidgetDefinition } from '../../../../../../widgets/widgets'; import { IWidget, IWidgetDefinition } from '../../../../../../widgets/widgets';
import { useEditModeStore } from '../../../../Views/useEditModeStore';
import { GenericAvailableElementType } from '../Shared/GenericElementType'; import { GenericAvailableElementType } from '../Shared/GenericElementType';
interface WidgetElementTypeProps { interface WidgetElementTypeProps {
@@ -18,6 +19,7 @@ export const WidgetElementType = ({ id, image, disabled, widget }: WidgetElement
const { t } = useTranslation(`modules/${id}`); const { t } = useTranslation(`modules/${id}`);
const { name: configName, config } = useConfigContext(); const { name: configName, config } = useConfigContext();
const updateConfig = useConfigStore((x) => x.updateConfig); const updateConfig = useConfigStore((x) => x.updateConfig);
const isEditMode = useEditModeStore((x) => x.enabled);
if (!configName) return null; if (!configName) return null;
@@ -56,9 +58,10 @@ export const WidgetElementType = ({ id, image, disabled, widget }: WidgetElement
}, },
], ],
}), }),
true true,
!isEditMode
); );
// TODO: safe to file system
closeModal('selectElement'); closeModal('selectElement');
}; };

View File

@@ -88,3 +88,11 @@ const useStyles = createStyles((theme, _params, getRef) => ({
}, },
}, },
})); }));
export const appTileDefinition = {
component: AppTile,
minWidth: 2,
maxWidth: 12,
minHeight: 2,
maxHeight: 12,
};

View File

@@ -1,77 +0,0 @@
import calendarDefinition from '../../../widgets/calendar/CalendarTile';
import clockDefinition from '../../../widgets/date/DateTile';
import dashDotDefinition from '../../../widgets/dashDot/DashDotTile';
import useNetDefinition from '../../../widgets/useNet/UseNetTile';
import weatherDefinition from '../../../widgets/weather/WeatherTile';
import { EmptyTile } from './EmptyTile';
import { AppTile } from './Apps/AppTile';
// TODO: just remove and use app (later app) directly. For widgets the the definition should contain min/max width/height
type TileDefinitionProps = {
[key in keyof any | 'app']: {
minWidth?: number;
minHeight?: number;
maxWidth?: number;
maxHeight?: number;
component: React.ElementType;
};
};
export const Tiles: TileDefinitionProps = {
app: {
component: AppTile,
minWidth: 2,
maxWidth: 12,
minHeight: 2,
maxHeight: 12,
},
bitTorrent: {
component: EmptyTile,
minWidth: 4,
maxWidth: 12,
minHeight: 5,
maxHeight: 12,
},
calendar: {
component: calendarDefinition.component,
minWidth: 4,
maxWidth: 12,
minHeight: 5,
maxHeight: 12,
},
clock: {
component: clockDefinition.component,
minWidth: 4,
maxWidth: 12,
minHeight: 2,
maxHeight: 12,
},
dashDot: {
component: dashDotDefinition.component,
minWidth: 4,
maxWidth: 9,
minHeight: 5,
maxHeight: 14,
},
torrentNetworkTraffic: {
component: EmptyTile,
minWidth: 4,
maxWidth: 12,
minHeight: 5,
maxHeight: 12,
},
useNet: {
component: useNetDefinition.component,
minWidth: 4,
maxWidth: 12,
minHeight: 5,
maxHeight: 12,
},
weather: {
component: weatherDefinition.component,
minWidth: 4,
maxWidth: 12,
minHeight: 2,
maxHeight: 12,
},
};

View File

@@ -4,7 +4,7 @@ import { AppType } from '../../../types/app';
import Widgets from '../../../widgets'; import Widgets from '../../../widgets';
import { IWidget, IWidgetDefinition } from '../../../widgets/widgets'; import { IWidget, IWidgetDefinition } from '../../../widgets/widgets';
import { WidgetWrapper } from '../../../widgets/WidgetWrapper'; import { WidgetWrapper } from '../../../widgets/WidgetWrapper';
import { Tiles } from '../Tiles/tilesDefinitions'; import { appTileDefinition } from '../Tiles/Apps/AppTile';
import { GridstackTileWrapper } from '../Tiles/TileWrapper'; import { GridstackTileWrapper } from '../Tiles/TileWrapper';
interface WrapperContentProps { interface WrapperContentProps {
@@ -21,7 +21,7 @@ export function WrapperContent({ apps, refs, widgets }: WrapperContentProps) {
return ( return (
<> <>
{apps?.map((app) => { {apps?.map((app) => {
const { component: TileComponent, ...tile } = Tiles.app; const { component: TileComponent, ...tile } = appTileDefinition;
return ( return (
<GridstackTileWrapper <GridstackTileWrapper
id={app.id} id={app.id}

View File

@@ -1,3 +1,4 @@
import axios from 'axios';
import create from 'zustand'; import create from 'zustand';
import { ConfigType } from '../types/config'; import { ConfigType } from '../types/config';
@@ -15,7 +16,8 @@ export const useConfigStore = create<UseConfigStoreType>((set, get) => ({
updateConfig: async ( updateConfig: async (
name, name,
updateCallback: (previous: ConfigType) => ConfigType, updateCallback: (previous: ConfigType) => ConfigType,
shouldRegenerateGridstack = false shouldRegenerateGridstack = false,
shouldSaveConfigToFileSystem = false
) => { ) => {
const { configs } = get(); const { configs } = get();
const currentConfig = configs.find((x) => x.value.configProperties.name === name); const currentConfig = configs.find((x) => x.value.configProperties.name === name);
@@ -23,7 +25,6 @@ export const useConfigStore = create<UseConfigStoreType>((set, get) => ({
// copies the value of currentConfig and creates a non reference object named previousConfig // copies the value of currentConfig and creates a non reference object named previousConfig
const previousConfig: ConfigType = JSON.parse(JSON.stringify(currentConfig.value)); const previousConfig: ConfigType = JSON.parse(JSON.stringify(currentConfig.value));
// TODO: update config on server
const updatedConfig = updateCallback(currentConfig.value); const updatedConfig = updateCallback(currentConfig.value);
set((old) => ({ set((old) => ({
...old, ...old,
@@ -40,6 +41,10 @@ export const useConfigStore = create<UseConfigStoreType>((set, get) => ({
) { ) {
currentConfig.increaseVersion(); currentConfig.increaseVersion();
} }
if (shouldSaveConfigToFileSystem) {
axios.put(`/api/configs/${name}`, { ...updatedConfig });
}
}, },
})); }));
@@ -51,6 +56,7 @@ interface UseConfigStoreType {
updateCallback: (previous: ConfigType) => ConfigType, updateCallback: (previous: ConfigType) => ConfigType,
shouldRegenerateGridstace?: shouldRegenerateGridstace?:
| boolean | boolean
| ((previousConfig: ConfigType, currentConfig: ConfigType) => boolean) | ((previousConfig: ConfigType, currentConfig: ConfigType) => boolean),
shouldSaveConfigToFileSystem?: boolean
) => Promise<void>; ) => Promise<void>;
} }

View File

@@ -9,7 +9,7 @@
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": false,
"noEmit": true, "noEmit": true,
"esModuleInterop": true, "esModuleInterop": true,
"module": "esnext", "module": "esnext",