diff --git a/data/configs/default.json b/data/configs/default.json index 03aebc127..7eebc4a93 100644 --- a/data/configs/default.json +++ b/data/configs/default.json @@ -1,387 +1,389 @@ { - "schemaVersion": 1, - "configProperties": { - "name": "default" - }, - "categories": [ - { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f", - "position": 1, - "name": "Welcome to Homarr 🎉", - "type": "category" + "schemaVersion": 1, + "configProperties": { + "name": "default" + }, + "categories": [ + { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f", + "position": 1, + "name": "Welcome to Homarr 🎉", + "type": "category" + } + ], + "wrappers": [ + { + "id": "default", + "position": 0 + }, + { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a326", + "position": 1 + } + ], + "apps": [ + { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a337", + "name": "Discord", + "url": "https://discord.com/invite/aCsmEV5RgA", + "behaviour": { + "onClickUrl": "https://discord.com/invite/aCsmEV5RgA", + "isOpeningNewTab": true, + "externalUrl": "https://discord.com/invite/aCsmEV5RgA" + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [ + 200 + ] + }, + "appearance": { + "iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/discord.png" + }, + "integration": { + "type": null, + "properties": [] + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "md": { + "location": { + "x": 3, + "y": 1 + }, + "size": { + "width": 3, + "height": 1 + } + }, + "sm": { + "location": { + "x": 2, + "y": 1 + }, + "size": { + "width": 1, + "height": 1 + } + }, + "lg": { + "location": { + "x": 2, + "y": 1 + }, + "size": { + "width": 1, + "height": 1 + } + } + } + }, + { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990", + "name": "Donate", + "url": "https://ko-fi.com/ajnart", + "behaviour": { + "onClickUrl": "https://ko-fi.com/ajnart", + "externalUrl": "https://ko-fi.com/ajnart", + "isOpeningNewTab": true + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [ + 200 + ] + }, + "appearance": { + "iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/ko-fi.png" + }, + "integration": { + "type": null, + "properties": [] + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "md": { + "location": { + "x": 2, + "y": 1 + }, + "size": { + "width": 1, + "height": 1 + } + }, + "sm": { + "location": { + "x": 2, + "y": 2 + }, + "size": { + "width": 1, + "height": 1 + } + }, + "lg": { + "location": { + "x": 3, + "y": 1 + }, + "size": { + "width": 1, + "height": 1 + } + } + } + }, + { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330", + "name": "Contribute", + "url": "https://github.com/ajnart/homarr", + "behaviour": { + "onClickUrl": "https://github.com/ajnart/homarr", + "externalUrl": "https://github.com/ajnart/homarr", + "isOpeningNewTab": true + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [] + }, + "appearance": { + "iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/github.png" + }, + "integration": { + "type": null, + "properties": [] + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "md": { + "location": { + "x": 2, + "y": 0 + }, + "size": { + "width": 2, + "height": 1 + } + }, + "sm": { + "location": { + "x": 0, + "y": 2 + }, + "size": { + "width": 2, + "height": 1 + } + }, + "lg": { + "location": { + "x": 4, + "y": 0 + }, + "size": { + "width": 2, + "height": 2 + } + } + } + }, + { + "id": "5df743d9-5cb1-457c-85d2-64ff86855652", + "name": "Documentation", + "url": "https://homarr.dev", + "behaviour": { + "onClickUrl": "https://homarr.dev", + "externalUrl": "https://homarr.dev", + "isOpeningNewTab": true + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [ + 200 + ] + }, + "appearance": { + "iconUrl": "/imgs/logo/logo.png" + }, + "integration": { + "type": null, + "properties": [] + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "md": { + "location": { + "x": 0, + "y": 1 + }, + "size": { + "width": 2, + "height": 1 + } + }, + "sm": { + "location": { + "x": 0, + "y": 0 + }, + "size": { + "width": 1, + "height": 1 + } + }, + "lg": { + "location": { + "x": 0, + "y": 1 + }, + "size": { + "width": 2, + "height": 1 + } + } + } + } + ], + "widgets": [ + { + "id": "971aa859-8570-49a1-8d34-dd5c7b3638d1", + "type": "date", + "properties": { + "display24HourFormat": true + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "sm": { + "location": { + "x": 0, + "y": 1 + }, + "size": { + "width": 2, + "height": 1 + } + }, + "md": { + "location": { + "x": 4, + "y": 0 + }, + "size": { + "width": 2, + "height": 1 + } + }, + "lg": { + "location": { + "x": 2, + "y": 0 + }, + "size": { + "width": 2, + "height": 1 + } + } + } + }, + { + "id": "e3004052-6b83-480e-b458-56e8ccdca5f0", + "type": "weather", + "properties": { + "displayInFahrenheit": false, + "location": "Paris" + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "md": { + "location": { + "x": 0, + "y": 0 + }, + "size": { + "width": 2, + "height": 1 + } + }, + "sm": { + "location": { + "x": 1, + "y": 0 + }, + "size": { + "width": 2, + "height": 1 + } + }, + "lg": { + "location": { + "x": 0, + "y": 0 + }, + "size": { + "width": 2, + "height": 1 + } + } + } + } + ], + "settings": { + "common": { + "searchEngine": { + "type": "google", + "properties": {} + } + }, + "customization": { + "layout": { + "enabledLeftSidebar": false, + "enabledRightSidebar": false, + "enabledDocker": false, + "enabledPing": false, + "enabledSearchbar": true + }, + "pageTitle": "Homarr v0.11 ⭐️", + "logoImageUrl": "/imgs/logo/logo.png", + "faviconUrl": "/imgs/favicon/favicon-squared", + "backgroundImageUrl": "", + "customCss": "", + "colors": { + "primary": "red", + "secondary": "yellow", + "shade": 7 + }, + "appOpacity": 100 + } } - ], - "wrappers": [ - { - "id": "default", - "position": 0 - }, - { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a326", - "position": 1 - } - ], - "apps": [ - { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a337", - "name": "Discord", - "url": "https://discord.com/invite/aCsmEV5RgA", - "behaviour": { - "onClickUrl": "https://discord.com/invite/aCsmEV5RgA", - "isOpeningNewTab": true, - "externalUrl": "https://discord.com/invite/aCsmEV5RgA" - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [ - 200 - ] - }, - "appearance": { - "iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/discord.png" - }, - "integration": { - "type": null, - "properties": [] - }, - "area": { - "type": "category", - "properties": { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" - } - }, - "shape": { - "md": { - "location": { - "x": 3, - "y": 1 - }, - "size": { - "width": 3, - "height": 1 - } - }, - "sm": { - "location": { - "x": 2, - "y": 1 - }, - "size": { - "width": 1, - "height": 1 - } - }, - "lg": { - "location": { - "x": 2, - "y": 1 - }, - "size": { - "width": 1, - "height": 1 - } - } - } - }, - { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990", - "name": "Donate", - "url": "https://ko-fi.com/ajnart", - "behaviour": { - "onClickUrl": "https://ko-fi.com/ajnart", - "externalUrl": "https://ko-fi.com/ajnart", - "isOpeningNewTab": true - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [ - 200 - ] - }, - "appearance": { - "iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/ko-fi.png" - }, - "integration": { - "type": null, - "properties": [] - }, - "area": { - "type": "category", - "properties": { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" - } - }, - "shape": { - "md": { - "location": { - "x": 2, - "y": 1 - }, - "size": { - "width": 1, - "height": 1 - } - }, - "sm": { - "location": { - "x": 2, - "y": 2 - }, - "size": { - "width": 1, - "height": 1 - } - }, - "lg": { - "location": { - "x": 3, - "y": 1 - }, - "size": { - "width": 1, - "height": 1 - } - } - } - }, - { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330", - "name": "Contribute", - "url": "https://github.com/ajnart/homarr", - "behaviour": { - "onClickUrl": "https://github.com/ajnart/homarr", - "externalUrl": "https://github.com/ajnart/homarr", - "isOpeningNewTab": true - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [] - }, - "appearance": { - "iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/github.png" - }, - "integration": { - "type": null, - "properties": [] - }, - "area": { - "type": "category", - "properties": { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" - } - }, - "shape": { - "md": { - "location": { - "x": 2, - "y": 0 - }, - "size": { - "width": 2, - "height": 1 - } - }, - "sm": { - "location": { - "x": 0, - "y": 2 - }, - "size": { - "width": 2, - "height": 1 - } - }, - "lg": { - "location": { - "x": 4, - "y": 0 - }, - "size": { - "width": 2, - "height": 2 - } - } - } - }, - { - "id": "5df743d9-5cb1-457c-85d2-64ff86855652", - "name": "Documentation", - "url": "https://homarr.dev", - "behaviour": { - "onClickUrl": "https://homarr.dev", - "externalUrl": "https://homarr.dev", - "isOpeningNewTab": true - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [ - 200 - ] - }, - "appearance": { - "iconUrl": "/imgs/logo/logo.png" - }, - "integration": { - "type": null, - "properties": [] - }, - "area": { - "type": "category", - "properties": { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" - } - }, - "shape": { - "md": { - "location": { - "x": 0, - "y": 1 - }, - "size": { - "width": 2, - "height": 1 - } - }, - "sm": { - "location": { - "x": 0, - "y": 0 - }, - "size": { - "width": 1, - "height": 1 - } - }, - "lg": { - "location": { - "x": 0, - "y": 1 - }, - "size": { - "width": 2, - "height": 1 - } - } - } - } - ], - "widgets": [ - { - "id": "date", - "properties": { - "display24HourFormat": true - }, - "area": { - "type": "category", - "properties": { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" - } - }, - "shape": { - "sm": { - "location": { - "x": 0, - "y": 1 - }, - "size": { - "width": 2, - "height": 1 - } - }, - "md": { - "location": { - "x": 4, - "y": 0 - }, - "size": { - "width": 2, - "height": 1 - } - }, - "lg": { - "location": { - "x": 2, - "y": 0 - }, - "size": { - "width": 2, - "height": 1 - } - } - } - }, - { - "id": "weather", - "properties": { - "displayInFahrenheit": false, - "location": "Paris" - }, - "area": { - "type": "category", - "properties": { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" - } - }, - "shape": { - "md": { - "location": { - "x": 0, - "y": 0 - }, - "size": { - "width": 2, - "height": 1 - } - }, - "sm": { - "location": { - "x": 1, - "y": 0 - }, - "size": { - "width": 2, - "height": 1 - } - }, - "lg": { - "location": { - "x": 0, - "y": 0 - }, - "size": { - "width": 2, - "height": 1 - } - } - } - } - ], - "settings": { - "common": { - "searchEngine": { - "type": "google", - "properties": {} - } - }, - "customization": { - "layout": { - "enabledLeftSidebar": false, - "enabledRightSidebar": false, - "enabledDocker": false, - "enabledPing": false, - "enabledSearchbar": true - }, - "pageTitle": "Homarr v0.11 ⭐️", - "logoImageUrl": "/imgs/logo/logo.png", - "faviconUrl": "/imgs/favicon/favicon-squared", - "backgroundImageUrl": "", - "customCss": "", - "colors": { - "primary": "red", - "secondary": "yellow", - "shade": 7 - }, - "appOpacity": 100 - } - } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 133f1e81d..58ee7ec5a 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "uuid": "^8.3.2", "xml-js": "^1.6.11", "yarn": "^1.22.19", + "zod": "^3.21.4", "zustand": "^4.1.4" }, "devDependencies": { diff --git a/src/components/Dashboard/Modals/ChangePosition/ChangeWidgetPositionModal.tsx b/src/components/Dashboard/Modals/ChangePosition/ChangeWidgetPositionModal.tsx index 241503adb..b6a9e3677 100644 --- a/src/components/Dashboard/Modals/ChangePosition/ChangeWidgetPositionModal.tsx +++ b/src/components/Dashboard/Modals/ChangePosition/ChangeWidgetPositionModal.tsx @@ -54,8 +54,8 @@ export const ChangeWidgetPositionModal = ({ closeModal(id); }; - const widthData = useWidthData(innerProps.widgetId); - const heightData = useHeightData(innerProps.widgetId); + const widthData = useWidthData(innerProps.widgetType); + const heightData = useHeightData(innerProps.widgetType); return ( { const { t } = useTranslation('layout/element-selector/selector'); - const activeWidgets = useConfigContext().config?.widgets ?? []; return ( <> @@ -23,11 +21,9 @@ export const AvailableIntegrationElements = ({ - {Object.entries(widgets) - .filter(([widgetId]) => !activeWidgets.some((aw) => aw.id === widgetId)) - .map(([k, v]) => ( - - ))} + {Object.entries(widgets).map(([k, v]) => ( + + ))} ); diff --git a/src/components/Dashboard/Modals/SelectElement/Components/WidgetsTab/WidgetElementType.tsx b/src/components/Dashboard/Modals/SelectElement/Components/WidgetsTab/WidgetElementType.tsx index ce3a2b708..8ff521b09 100644 --- a/src/components/Dashboard/Modals/SelectElement/Components/WidgetsTab/WidgetElementType.tsx +++ b/src/components/Dashboard/Modals/SelectElement/Components/WidgetsTab/WidgetElementType.tsx @@ -2,6 +2,7 @@ import { useModals } from '@mantine/modals'; import { showNotification } from '@mantine/notifications'; import { IconChecks, TablerIcon } from '@tabler/icons'; import { useTranslation } from 'next-i18next'; +import { v4 as uuidv4 } from 'uuid'; import { useConfigContext } from '../../../../../../config/provider'; import { useConfigStore } from '../../../../../../config/store'; import { IWidget, IWidgetDefinition } from '../../../../../../widgets/widgets'; @@ -32,9 +33,10 @@ export const WidgetElementType = ({ id, image, disabled, widget }: WidgetElement (prev) => ({ ...prev, widgets: [ - ...prev.widgets.filter((w) => w.id !== widget.id), + ...prev.widgets, { - id: widget.id, + id: uuidv4(), + type: widget.id, properties: Object.entries(widget.options).reduce((prev, [k, v]) => { const newPrev = prev; newPrev[k] = v.defaultValue; diff --git a/src/components/Dashboard/Tiles/Widgets/WidgetsEditModal.tsx b/src/components/Dashboard/Tiles/Widgets/WidgetsEditModal.tsx index f58f30750..e89d32176 100644 --- a/src/components/Dashboard/Tiles/Widgets/WidgetsEditModal.tsx +++ b/src/components/Dashboard/Tiles/Widgets/WidgetsEditModal.tsx @@ -26,6 +26,7 @@ import { DraggableList } from './DraggableList'; export type WidgetEditModalInnerProps = { widgetId: string; + widgetType: string; options: IWidget['properties']; widgetOptions: IWidget['properties']; }; @@ -37,7 +38,7 @@ export const WidgetsEditModal = ({ id, innerProps, }: ContextModalProps) => { - const { t } = useTranslation([`modules/${innerProps.widgetId}`, 'common']); + const { t } = useTranslation([`modules/${innerProps.widgetType}`, 'common']); const [moduleProperties, setModuleProperties] = useState(innerProps.options); const items = Object.entries(innerProps.widgetOptions ?? {}) as [ string, @@ -45,7 +46,7 @@ export const WidgetsEditModal = ({ ][]; // Find the Key in the "Widgets" Object that matches the widgetId - const currentWidgetDefinition = Widgets[innerProps.widgetId as keyof typeof Widgets]; + const currentWidgetDefinition = Widgets[innerProps.widgetType as keyof typeof Widgets]; const { name: configName } = useConfigContext(); const updateConfig = useConfigStore((x) => x.updateConfig); @@ -100,7 +101,7 @@ export const WidgetsEditModal = ({ ; wrapperColumnCount: number; }; @@ -27,8 +28,8 @@ export const WidgetsMenu = ({ integration, widget }: WidgetsMenuProps) => { // Match widget.id with WidgetsDefinitions // First get the keys const keys = Object.keys(WidgetsDefinitions); - // Then find the key that matches the widget.id - const widgetDefinition = keys.find((key) => key === widget.id); + // Then find the key that matches the widget.type + const widgetDefinition = keys.find((key) => key === widget.type); // Then get the widget definition const widgetDefinitionObject = WidgetsDefinitions[widgetDefinition as keyof typeof WidgetsDefinitions]; @@ -38,13 +39,8 @@ export const WidgetsMenu = ({ integration, widget }: WidgetsMenuProps) => { modal: 'integrationRemove', title: {t('common:remove')}, innerProps: { - widgetId: integration, - }, - styles: { - inner: { - position: 'sticky', - top: 30, - }, + widgetId: widget.id, + widgetType: integration, }, }); }; @@ -55,16 +51,11 @@ export const WidgetsMenu = ({ integration, widget }: WidgetsMenuProps) => { size: 'xl', title: null, innerProps: { - widgetId: integration, + widgetId: widget.id, + widgetType: integration, widget, wrapperColumnCount, }, - styles: { - inner: { - position: 'sticky', - top: 30, - }, - }, }); }; @@ -73,19 +64,13 @@ export const WidgetsMenu = ({ integration, widget }: WidgetsMenuProps) => { modal: 'integrationOptions', title: {t('descriptor.settings.title')}, innerProps: { - widgetId: integration, + widgetId: widget.id, + widgetType: integration, options: widget.properties, // Cast as the right type for the correct widget widgetOptions: widgetDefinitionObject.options as any, }, zIndex: 5, - styles: { - inner: { - position: 'sticky', - top: 30, - maxHeight: '100%', - }, - }, }); }; diff --git a/src/components/Dashboard/Tiles/Widgets/WidgetsRemoveModal.tsx b/src/components/Dashboard/Tiles/Widgets/WidgetsRemoveModal.tsx index f92e34380..e50229c0b 100644 --- a/src/components/Dashboard/Tiles/Widgets/WidgetsRemoveModal.tsx +++ b/src/components/Dashboard/Tiles/Widgets/WidgetsRemoveModal.tsx @@ -7,6 +7,7 @@ import { useConfigStore } from '../../../../config/store'; export type WidgetsRemoveModalInnerProps = { widgetId: string; + widgetType: string; }; export const WidgetsRemoveModal = ({ @@ -14,7 +15,7 @@ export const WidgetsRemoveModal = ({ id, innerProps, }: ContextModalProps) => { - const { t } = useTranslation([`modules/${innerProps.widgetId}`, 'common']); + const { t } = useTranslation([`modules/${innerProps.widgetType}`, 'common']); const { name: configName } = useConfigContext(); if (!configName) return null; const updateConfig = useConfigStore((x) => x.updateConfig); @@ -35,7 +36,7 @@ export const WidgetsRemoveModal = ({ ]} - values={{ item: innerProps.widgetId }} + values={{ item: innerProps.widgetType }} /> ), diff --git a/src/widgets/calendar/CalendarTile.tsx b/src/widgets/calendar/CalendarTile.tsx index 3c812599b..b5cf83531 100644 --- a/src/widgets/calendar/CalendarTile.tsx +++ b/src/widgets/calendar/CalendarTile.tsx @@ -63,7 +63,7 @@ function CalendarTile({ widget }: CalendarTileProps) { await fetch( `/api/modules/calendar?year=${month.getFullYear()}&month=${ month.getMonth() + 1 - }&configName=${configName}` + }&configName=${configName}&widgetId=${widget.id}` ) ).json()) as MediasType, }); diff --git a/src/widgets/dashDot/DashDotCompactStorage.tsx b/src/widgets/dashDot/DashDotCompactStorage.tsx index b69b0f2d5..319ffe10c 100644 --- a/src/widgets/dashDot/DashDotCompactStorage.tsx +++ b/src/widgets/dashDot/DashDotCompactStorage.tsx @@ -9,11 +9,12 @@ import { DashDotInfo } from './DashDotCompactNetwork'; interface DashDotCompactStorageProps { info: DashDotInfo; + widgetId: string; } -export const DashDotCompactStorage = ({ info }: DashDotCompactStorageProps) => { +export const DashDotCompactStorage = ({ info, widgetId }: DashDotCompactStorageProps) => { const { t } = useTranslation('modules/dashdot'); - const { data: storageLoad } = useDashDotStorage(); + const { data: storageLoad } = useDashDotStorage(widgetId); const totalUsed = calculateTotalLayoutSize({ layout: storageLoad?.layout ?? [], @@ -50,7 +51,7 @@ interface CalculateTotalLayoutSizeProps { key: keyof TLayoutItem; } -const useDashDotStorage = () => { +const useDashDotStorage = (widgetId: string) => { const { name: configName, config } = useConfigContext(); return useQuery({ @@ -58,17 +59,18 @@ const useDashDotStorage = () => { 'dashdot/storage', { configName, - url: config?.widgets.find((x) => x.id === 'dashdot')?.properties.url, + url: config?.widgets.find((x) => x.type === 'dashdot')?.properties.url, + widgetId, }, ], - queryFn: () => fetchDashDotStorageLoad(configName), + queryFn: () => fetchDashDotStorageLoad(configName, widgetId), }); }; -async function fetchDashDotStorageLoad(configName: string | undefined) { +async function fetchDashDotStorageLoad(configName: string | undefined, widgetId: string) { if (!configName) throw new Error('configName is undefined'); return (await ( - await axios.get('/api/modules/dashdot/storage', { params: { configName } }) + await axios.get('/api/modules/dashdot/storage', { params: { configName, widgetId } }) ).data) as DashDotStorageLoad; } diff --git a/src/widgets/dashDot/DashDotGraph.tsx b/src/widgets/dashDot/DashDotGraph.tsx index dd9fda585..d26bd0e90 100644 --- a/src/widgets/dashDot/DashDotGraph.tsx +++ b/src/widgets/dashDot/DashDotGraph.tsx @@ -11,6 +11,7 @@ interface DashDotGraphProps { dashDotUrl: string; usePercentages: boolean; info: DashDotInfo; + widgetId: string; } export const DashDotGraph = ({ @@ -21,12 +22,13 @@ export const DashDotGraph = ({ dashDotUrl, usePercentages, info, + widgetId, }: DashDotGraphProps) => { const { t } = useTranslation('modules/dashdot'); const { classes } = useStyles(); if (graph === 'storage' && isCompact) { - return ; + return ; } if (graph === 'network' && isCompact) { diff --git a/src/widgets/dashDot/DashDotTile.tsx b/src/widgets/dashDot/DashDotTile.tsx index 33bdf820d..fe19b0110 100644 --- a/src/widgets/dashDot/DashDotTile.tsx +++ b/src/widgets/dashDot/DashDotTile.tsx @@ -160,6 +160,7 @@ function DashDotTile({ widget }: DashDotTileProps) { const { data: info } = useDashDotInfo({ dashDotUrl, enabled: !detectedProtocolDowngrade, + widgetId: widget.id, }); if (detectedProtocolDowngrade) { @@ -197,6 +198,7 @@ function DashDotTile({ widget }: DashDotTileProps) { isCompact={g.subValues.compactView ?? false} multiView={g.subValues.multiView ?? false} usePercentages={usePercentages} + widgetId={widget.id} /> ))} @@ -207,7 +209,15 @@ function DashDotTile({ widget }: DashDotTileProps) { ); } -const useDashDotInfo = ({ dashDotUrl, enabled }: { dashDotUrl: string; enabled: boolean }) => { +const useDashDotInfo = ({ + dashDotUrl, + enabled, + widgetId, +}: { + dashDotUrl: string; + enabled: boolean; + widgetId: string; +}) => { const { name: configName } = useConfigContext(); return useQuery({ refetchInterval: 50000, @@ -218,15 +228,15 @@ const useDashDotInfo = ({ dashDotUrl, enabled }: { dashDotUrl: string; enabled: dashDotUrl, }, ], - queryFn: () => fetchDashDotInfo(configName), + queryFn: () => fetchDashDotInfo(configName, widgetId), enabled, }); }; -const fetchDashDotInfo = async (configName: string | undefined) => { +const fetchDashDotInfo = async (configName: string | undefined, widgetId: string) => { if (!configName) return {} as DashDotInfo; return (await ( - await axios.get('/api/modules/dashdot/info', { params: { configName } }) + await axios.get('/api/modules/dashdot/info', { params: { configName, widgetId } }) ).data) as DashDotInfo; }; diff --git a/src/widgets/rss/RssWidgetTile.tsx b/src/widgets/rss/RssWidgetTile.tsx index b594803e6..b1eab57cd 100644 --- a/src/widgets/rss/RssWidgetTile.tsx +++ b/src/widgets/rss/RssWidgetTile.tsx @@ -29,8 +29,8 @@ import dayjs from 'dayjs'; import { useTranslation } from 'next-i18next'; import Link from 'next/link'; import { useState } from 'react'; -import { defineWidget } from '../helper'; import { IWidget } from '../widgets'; +import { defineWidget } from '../helper'; const definition = defineWidget({ id: 'rss', @@ -56,11 +56,11 @@ interface RssTileProps { widget: IRssWidget; } -const useGetRssFeed = (feedUrl: string) => +export const useGetRssFeed = (feedUrl: string, widgetId: string) => useQuery({ queryKey: ['rss-feed', feedUrl], queryFn: async () => { - const response = await fetch('/api/modules/rss'); + const response = await fetch(`/api/modules/rss?widgetId=${widgetId}`); return response.json(); }, }); @@ -68,7 +68,8 @@ const useGetRssFeed = (feedUrl: string) => function RssTile({ widget }: RssTileProps) { const { t } = useTranslation('modules/rss'); const { data, isLoading, isFetching, isError, refetch } = useGetRssFeed( - widget.properties.rssFeedUrl + widget.properties.rssFeedUrl, + widget.id ); const { classes } = useStyles(); const [loadingOverlayVisible, setLoadingOverlayVisible] = useState(false); diff --git a/src/widgets/widgets.ts b/src/widgets/widgets.ts index d6559ed25..998413fea 100644 --- a/src/widgets/widgets.ts +++ b/src/widgets/widgets.ts @@ -13,7 +13,8 @@ import { ShapeType } from '../types/shape'; // Type of widgets which are saved to config export type IWidget = { - id: TKey; + id: string; + type: TKey; properties: { [key in keyof TDefinition['options']]: MakeLessSpecific< TDefinition['options'][key]['defaultValue'] diff --git a/yarn.lock b/yarn.lock index 04d9d2160..53d9a46ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4914,6 +4914,7 @@ __metadata: vitest-fetch-mock: ^0.2.2 xml-js: ^1.6.11 yarn: ^1.22.19 + zod: ^3.21.4 zustand: ^4.1.4 languageName: unknown linkType: soft @@ -8760,6 +8761,13 @@ __metadata: languageName: node linkType: hard +"zod@npm:^3.21.4": + version: 3.21.4 + resolution: "zod@npm:3.21.4" + checksum: f185ba87342ff16f7a06686767c2b2a7af41110c7edf7c1974095d8db7a73792696bcb4a00853de0d2edeb34a5b2ea6a55871bc864227dace682a0a28de33e1f + languageName: node + linkType: hard + "zustand@npm:^4.1.4": version: 4.3.6 resolution: "zustand@npm:4.3.6"