mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 15:35:55 +01:00
🐛 Fix Change Position not working with gridstack
This commit is contained in:
@@ -22,13 +22,17 @@ export const ChangeAppPositionModal = ({
|
||||
return;
|
||||
}
|
||||
|
||||
updateConfig(configName, (previousConfig) => ({
|
||||
...previousConfig,
|
||||
apps: [
|
||||
...previousConfig.apps.filter((x) => x.id !== innerProps.app.id),
|
||||
{ ...innerProps.app, shape: { location: { x, y }, size: { width, height } } },
|
||||
],
|
||||
}));
|
||||
updateConfig(
|
||||
configName,
|
||||
(previousConfig) => ({
|
||||
...previousConfig,
|
||||
apps: [
|
||||
...previousConfig.apps.filter((x) => x.id !== innerProps.app.id),
|
||||
{ ...innerProps.app, shape: { location: { x, y }, size: { width, height } } },
|
||||
],
|
||||
}),
|
||||
true
|
||||
);
|
||||
context.closeModal(id);
|
||||
};
|
||||
|
||||
|
||||
@@ -19,25 +19,28 @@ export const ChangeWidgetPositionModal = ({
|
||||
return;
|
||||
}
|
||||
|
||||
updateConfig(configName, (prev) => {
|
||||
let currentWidget = prev.widgets.find((x) => x.id === innerProps.widgetId);
|
||||
currentWidget!.shape = {
|
||||
location: {
|
||||
x,
|
||||
y,
|
||||
},
|
||||
size: {
|
||||
height,
|
||||
width,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
...prev,
|
||||
widgets: [...prev.widgets.filter((x) => x.id !== innerProps.widgetId), currentWidget!],
|
||||
};
|
||||
});
|
||||
updateConfig(
|
||||
configName,
|
||||
(prev) => {
|
||||
let currentWidget = prev.widgets.find((x) => x.id === innerProps.widgetId);
|
||||
currentWidget!.shape = {
|
||||
location: {
|
||||
x,
|
||||
y,
|
||||
},
|
||||
size: {
|
||||
height,
|
||||
width,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
...prev,
|
||||
widgets: [...prev.widgets.filter((x) => x.id !== innerProps.widgetId), currentWidget!],
|
||||
};
|
||||
},
|
||||
true
|
||||
);
|
||||
context.closeModal(id);
|
||||
};
|
||||
|
||||
|
||||
@@ -83,10 +83,14 @@ export const EditAppModal = ({
|
||||
return;
|
||||
}
|
||||
|
||||
updateConfig(configName, (previousConfig) => ({
|
||||
...previousConfig,
|
||||
apps: [...previousConfig.apps.filter((x) => x.id !== form.values.id), form.values],
|
||||
}));
|
||||
updateConfig(
|
||||
configName,
|
||||
(previousConfig) => ({
|
||||
...previousConfig,
|
||||
apps: [...previousConfig.apps.filter((x) => x.id !== form.values.id), form.values],
|
||||
}),
|
||||
true
|
||||
);
|
||||
|
||||
// also close the parent modal
|
||||
context.closeAll();
|
||||
|
||||
@@ -26,35 +26,39 @@ export const WidgetElementType = ({ id, image, disabled, widget }: WidgetElement
|
||||
};
|
||||
|
||||
const handleAddition = async () => {
|
||||
updateConfig(configName, (prev) => ({
|
||||
...prev,
|
||||
widgets: [
|
||||
...prev.widgets.filter((w) => w.id !== widget.id),
|
||||
{
|
||||
id: widget.id,
|
||||
properties: Object.entries(widget.options).reduce((prev, [k, v]) => {
|
||||
prev[k] = v.defaultValue;
|
||||
return prev;
|
||||
}, {} as IWidget<string, any>['properties']),
|
||||
area: {
|
||||
type: 'wrapper',
|
||||
properties: {
|
||||
id: getLowestWrapper()?.id ?? '',
|
||||
updateConfig(
|
||||
configName,
|
||||
(prev) => ({
|
||||
...prev,
|
||||
widgets: [
|
||||
...prev.widgets.filter((w) => w.id !== widget.id),
|
||||
{
|
||||
id: widget.id,
|
||||
properties: Object.entries(widget.options).reduce((prev, [k, v]) => {
|
||||
prev[k] = v.defaultValue;
|
||||
return prev;
|
||||
}, {} as IWidget<string, any>['properties']),
|
||||
area: {
|
||||
type: 'wrapper',
|
||||
properties: {
|
||||
id: getLowestWrapper()?.id ?? '',
|
||||
},
|
||||
},
|
||||
shape: {
|
||||
location: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
size: {
|
||||
width: widget.gridstack.minWidth,
|
||||
height: widget.gridstack.minHeight,
|
||||
},
|
||||
},
|
||||
},
|
||||
shape: {
|
||||
location: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
size: {
|
||||
width: widget.gridstack.minWidth,
|
||||
height: widget.gridstack.minHeight,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
],
|
||||
}),
|
||||
true
|
||||
);
|
||||
// TODO: safe to file system
|
||||
closeModal('selectElement');
|
||||
};
|
||||
|
||||
@@ -45,15 +45,19 @@ export const WidgetsEditModal = ({
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
updateConfig(configName, (prev) => {
|
||||
let currentWidget = prev.widgets.find((x) => x.id === innerProps.widgetId);
|
||||
currentWidget!.properties = moduleProperties;
|
||||
updateConfig(
|
||||
configName,
|
||||
(prev) => {
|
||||
let currentWidget = prev.widgets.find((x) => x.id === innerProps.widgetId);
|
||||
currentWidget!.properties = moduleProperties;
|
||||
|
||||
return {
|
||||
...prev,
|
||||
widgets: [...prev.widgets.filter((x) => x.id !== innerProps.widgetId), currentWidget!],
|
||||
};
|
||||
});
|
||||
return {
|
||||
...prev,
|
||||
widgets: [...prev.widgets.filter((x) => x.id !== innerProps.widgetId), currentWidget!],
|
||||
};
|
||||
},
|
||||
true
|
||||
);
|
||||
context.closeModal(id);
|
||||
};
|
||||
|
||||
|
||||
@@ -19,10 +19,14 @@ export const WidgetsRemoveModal = ({
|
||||
if (!configName) return null;
|
||||
const updateConfig = useConfigStore((x) => x.updateConfig);
|
||||
const handleDeletion = () => {
|
||||
updateConfig(configName, (prev) => ({
|
||||
...prev,
|
||||
widgets: prev.widgets.filter((w) => w.id !== innerProps.widgetId),
|
||||
}));
|
||||
updateConfig(
|
||||
configName,
|
||||
(prev) => ({
|
||||
...prev,
|
||||
widgets: prev.widgets.filter((w) => w.id !== innerProps.widgetId),
|
||||
}),
|
||||
true
|
||||
);
|
||||
context.closeModal(id);
|
||||
};
|
||||
|
||||
|
||||
@@ -29,29 +29,35 @@ export const useCategoryActions = (configName: string | undefined, category: Cat
|
||||
};
|
||||
|
||||
// Adding category and wrapper and moving other items down
|
||||
updateConfig(configName, (previous) => {
|
||||
const aboveWrappers = previous.wrappers.filter((x) => x.position <= abovePosition);
|
||||
const aboveCategories = previous.categories.filter((x) => x.position <= abovePosition);
|
||||
updateConfig(
|
||||
configName,
|
||||
(previous) => {
|
||||
const aboveWrappers = previous.wrappers.filter((x) => x.position <= abovePosition);
|
||||
const aboveCategories = previous.categories.filter(
|
||||
(x) => x.position <= abovePosition
|
||||
);
|
||||
|
||||
const belowWrappers = previous.wrappers.filter((x) => x.position > abovePosition);
|
||||
const belowCategories = previous.categories.filter((x) => x.position > abovePosition);
|
||||
const belowWrappers = previous.wrappers.filter((x) => x.position > abovePosition);
|
||||
const belowCategories = previous.categories.filter((x) => x.position > abovePosition);
|
||||
|
||||
return {
|
||||
...previous,
|
||||
categories: [
|
||||
...aboveCategories,
|
||||
category,
|
||||
// Move categories below down
|
||||
...belowCategories.map((x) => ({ ...x, position: x.position + 2 })),
|
||||
],
|
||||
wrappers: [
|
||||
...aboveWrappers,
|
||||
newWrapper,
|
||||
// Move wrappers below down
|
||||
...belowWrappers.map((x) => ({ ...x, position: x.position + 2 })),
|
||||
],
|
||||
};
|
||||
});
|
||||
return {
|
||||
...previous,
|
||||
categories: [
|
||||
...aboveCategories,
|
||||
category,
|
||||
// Move categories below down
|
||||
...belowCategories.map((x) => ({ ...x, position: x.position + 2 })),
|
||||
],
|
||||
wrappers: [
|
||||
...aboveWrappers,
|
||||
newWrapper,
|
||||
// Move wrappers below down
|
||||
...belowWrappers.map((x) => ({ ...x, position: x.position + 2 })),
|
||||
],
|
||||
};
|
||||
},
|
||||
true
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -78,29 +84,35 @@ export const useCategoryActions = (configName: string | undefined, category: Cat
|
||||
};
|
||||
|
||||
// Adding category and wrapper and moving other items down
|
||||
updateConfig(configName, (previous) => {
|
||||
const aboveWrappers = previous.wrappers.filter((x) => x.position < belowPosition);
|
||||
const aboveCategories = previous.categories.filter((x) => x.position < belowPosition);
|
||||
updateConfig(
|
||||
configName,
|
||||
(previous) => {
|
||||
const aboveWrappers = previous.wrappers.filter((x) => x.position < belowPosition);
|
||||
const aboveCategories = previous.categories.filter((x) => x.position < belowPosition);
|
||||
|
||||
const belowWrappers = previous.wrappers.filter((x) => x.position >= belowPosition);
|
||||
const belowCategories = previous.categories.filter((x) => x.position >= belowPosition);
|
||||
const belowWrappers = previous.wrappers.filter((x) => x.position >= belowPosition);
|
||||
const belowCategories = previous.categories.filter(
|
||||
(x) => x.position >= belowPosition
|
||||
);
|
||||
|
||||
return {
|
||||
...previous,
|
||||
categories: [
|
||||
...aboveCategories,
|
||||
category,
|
||||
// Move categories below down
|
||||
...belowCategories.map((x) => ({ ...x, position: x.position + 2 })),
|
||||
],
|
||||
wrappers: [
|
||||
...aboveWrappers,
|
||||
newWrapper,
|
||||
// Move wrappers below down
|
||||
...belowWrappers.map((x) => ({ ...x, position: x.position + 2 })),
|
||||
],
|
||||
};
|
||||
});
|
||||
return {
|
||||
...previous,
|
||||
categories: [
|
||||
...aboveCategories,
|
||||
category,
|
||||
// Move categories below down
|
||||
...belowCategories.map((x) => ({ ...x, position: x.position + 2 })),
|
||||
],
|
||||
wrappers: [
|
||||
...aboveWrappers,
|
||||
newWrapper,
|
||||
// Move wrappers below down
|
||||
...belowWrappers.map((x) => ({ ...x, position: x.position + 2 })),
|
||||
],
|
||||
};
|
||||
},
|
||||
true
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -109,51 +121,59 @@ export const useCategoryActions = (configName: string | undefined, category: Cat
|
||||
const moveCategoryUp = () => {
|
||||
if (!configName) return;
|
||||
|
||||
updateConfig(configName, (previous) => {
|
||||
const currentItem = previous.categories.find((x) => x.id === category.id);
|
||||
if (!currentItem) return previous;
|
||||
updateConfig(
|
||||
configName,
|
||||
(previous) => {
|
||||
const currentItem = previous.categories.find((x) => x.id === category.id);
|
||||
if (!currentItem) return previous;
|
||||
|
||||
const upperItem = previous.categories.find((x) => x.position === currentItem.position - 2);
|
||||
const upperItem = previous.categories.find((x) => x.position === currentItem.position - 2);
|
||||
|
||||
if (!upperItem) return previous;
|
||||
if (!upperItem) return previous;
|
||||
|
||||
currentItem.position -= 2;
|
||||
upperItem.position += 2;
|
||||
currentItem.position -= 2;
|
||||
upperItem.position += 2;
|
||||
|
||||
return {
|
||||
...previous,
|
||||
categories: [
|
||||
...previous.categories.filter((c) => ![currentItem.id, upperItem.id].includes(c.id)),
|
||||
{ ...upperItem },
|
||||
{ ...currentItem },
|
||||
],
|
||||
};
|
||||
});
|
||||
return {
|
||||
...previous,
|
||||
categories: [
|
||||
...previous.categories.filter((c) => ![currentItem.id, upperItem.id].includes(c.id)),
|
||||
{ ...upperItem },
|
||||
{ ...currentItem },
|
||||
],
|
||||
};
|
||||
},
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
const moveCategoryDown = () => {
|
||||
if (!configName) return;
|
||||
|
||||
updateConfig(configName, (previous) => {
|
||||
const currentItem = previous.categories.find((x) => x.id === category.id);
|
||||
if (!currentItem) return previous;
|
||||
updateConfig(
|
||||
configName,
|
||||
(previous) => {
|
||||
const currentItem = previous.categories.find((x) => x.id === category.id);
|
||||
if (!currentItem) return previous;
|
||||
|
||||
const belowItem = previous.categories.find((x) => x.position === currentItem.position + 2);
|
||||
const belowItem = previous.categories.find((x) => x.position === currentItem.position + 2);
|
||||
|
||||
if (!belowItem) return previous;
|
||||
if (!belowItem) return previous;
|
||||
|
||||
currentItem.position += 2;
|
||||
belowItem.position -= 2;
|
||||
currentItem.position += 2;
|
||||
belowItem.position -= 2;
|
||||
|
||||
return {
|
||||
...previous,
|
||||
categories: [
|
||||
...previous.categories.filter((c) => ![currentItem.id, belowItem.id].includes(c.id)),
|
||||
{ ...currentItem },
|
||||
{ ...belowItem },
|
||||
],
|
||||
};
|
||||
});
|
||||
return {
|
||||
...previous,
|
||||
categories: [
|
||||
...previous.categories.filter((c) => ![currentItem.id, belowItem.id].includes(c.id)),
|
||||
{ ...currentItem },
|
||||
{ ...belowItem },
|
||||
],
|
||||
};
|
||||
},
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
const edit = async () => {
|
||||
|
||||
@@ -14,6 +14,7 @@ interface WrapperContentProps {
|
||||
wrapper: RefObject<HTMLDivElement>;
|
||||
items: MutableRefObject<Record<string, RefObject<HTMLDivElement>>>;
|
||||
gridstack: MutableRefObject<GridStack | undefined>;
|
||||
updateGridstackRef: MutableRefObject<(() => void) | undefined>;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ export const initializeGridstack = (
|
||||
if (!firstNode) return;
|
||||
events.onAdd(firstNode);
|
||||
});
|
||||
|
||||
grid.batchUpdate();
|
||||
grid.removeAll(false);
|
||||
items.forEach(
|
||||
|
||||
@@ -31,7 +31,7 @@ export const useGridstack = (
|
||||
areaId: string
|
||||
): UseGristackReturnType => {
|
||||
const isEditMode = useEditModeStore((x) => x.enabled);
|
||||
const { config, name: configName } = useConfigContext();
|
||||
const { config, configVersion, name: configName } = useConfigContext();
|
||||
const updateConfig = useConfigStore((x) => x.updateConfig);
|
||||
// define reference for wrapper - is used to calculate the width of the wrapper
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
@@ -51,7 +51,7 @@ export const useGridstack = (
|
||||
? x.area.properties.location === areaId
|
||||
: x.area.properties.id === areaId)
|
||||
) ?? [],
|
||||
[config]
|
||||
[configVersion]
|
||||
);
|
||||
const widgets = useMemo(() => {
|
||||
if (!config) return [];
|
||||
@@ -62,7 +62,7 @@ export const useGridstack = (
|
||||
? w.area.properties.location === areaId
|
||||
: w.area.properties.id === areaId)
|
||||
);
|
||||
}, [config]);
|
||||
}, [configVersion]);
|
||||
|
||||
// define items in itemRefs for easy access and reference to items
|
||||
if (Object.keys(itemRefs.current).length !== items.length + (widgets ?? []).length) {
|
||||
@@ -208,7 +208,7 @@ export const useGridstack = (
|
||||
onAdd,
|
||||
}
|
||||
);
|
||||
}, [items.length, wrapperRef.current, (widgets ?? []).length]);
|
||||
}, [items, wrapperRef.current, widgets]);
|
||||
|
||||
return {
|
||||
apps: items,
|
||||
|
||||
@@ -45,22 +45,26 @@ export const LayoutSelector = ({ defaultLayout }: LayoutSelectorProps) => {
|
||||
) => {
|
||||
const value = event.target.checked;
|
||||
setState(value);
|
||||
updateConfig(configName, (prev) => {
|
||||
const { layout } = prev.settings.customization;
|
||||
updateConfig(
|
||||
configName,
|
||||
(prev) => {
|
||||
const { layout } = prev.settings.customization;
|
||||
|
||||
layout[key] = value;
|
||||
layout[key] = value;
|
||||
|
||||
return {
|
||||
...prev,
|
||||
settings: {
|
||||
...prev.settings,
|
||||
customization: {
|
||||
...prev.settings.customization,
|
||||
layout,
|
||||
return {
|
||||
...prev,
|
||||
settings: {
|
||||
...prev.settings,
|
||||
customization: {
|
||||
...prev.settings.customization,
|
||||
layout,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
},
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user