Files
Homarr/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts

111 lines
3.7 KiB
TypeScript
Raw Normal View History

2023-01-07 23:25:13 +01:00
import { GridItemHTMLElement, GridStack, GridStackNode } from 'fily-publish-gridstack';
2022-12-04 17:36:30 +01:00
import { MutableRefObject, RefObject } from 'react';
import { AppType } from '../../../../types/app';
2023-01-06 23:50:08 +01:00
import { ShapeType } from '../../../../types/shape';
import { IWidget } from '../../../../widgets/widgets';
2022-12-04 17:36:30 +01:00
export const initializeGridstack = (
areaType: 'wrapper' | 'category' | 'sidebar',
wrapperRef: RefObject<HTMLDivElement>,
gridRef: MutableRefObject<GridStack | undefined>,
itemRefs: MutableRefObject<Record<string, RefObject<HTMLDivElement>>>,
areaId: string,
items: AppType[],
widgets: IWidget<string, any>[],
2022-12-04 17:36:30 +01:00
isEditMode: boolean,
2023-01-04 19:06:19 +01:00
wrapperColumnCount: 3 | 6 | 12,
2023-01-06 23:50:08 +01:00
shapeSize: 'sm' | 'md' | 'lg',
2023-01-07 23:25:13 +01:00
tilesWithUnknownLocation: TileWithUnknownLocation[],
2022-12-04 17:36:30 +01:00
events: {
onChange: (changedNode: GridStackNode) => void;
onAdd: (addedNode: GridStackNode) => void;
}
) => {
if (!wrapperRef.current) return;
// calculates the currently available count of columns
2023-01-06 22:46:07 +01:00
const columnCount = areaType === 'sidebar' ? 2 : wrapperColumnCount;
2023-01-06 23:50:08 +01:00
const minRow = areaType !== 'sidebar' ? 1 : Math.floor(wrapperRef.current.offsetHeight / 128);
2022-12-04 17:36:30 +01:00
// initialize gridstack
2022-12-22 11:45:48 +09:00
const newGrid = gridRef;
newGrid.current = GridStack.init(
2022-12-04 17:36:30 +01:00
{
column: columnCount,
margin: 10,
2023-01-06 23:50:08 +01:00
cellHeight: 128,
2022-12-04 17:36:30 +01:00
float: true,
alwaysShowResizeHandle: 'mobile',
acceptWidgets: true,
disableOneColumnMode: true,
staticGrid: !isEditMode,
minRow,
2023-01-06 22:46:07 +01:00
animate: false,
2022-12-04 17:36:30 +01:00
},
// selector of the gridstack item (it's eather category or wrapper)
`.grid-stack-${areaType}[data-${areaType}='${areaId}']`
);
2022-12-22 11:45:48 +09:00
const grid = newGrid.current;
2023-01-06 22:46:07 +01:00
// Must be used to update the column count after the initialization
grid.column(columnCount);
2022-12-04 17:36:30 +01:00
// Add listener for moving items around in a wrapper
grid.on('change', (_, el) => {
const nodes = el as GridStackNode[];
const firstNode = nodes.at(0);
if (!firstNode) return;
events.onChange(firstNode);
});
// Add listener for moving items in config from one wrapper to another
grid.on('added', (_, el) => {
const nodes = el as GridStackNode[];
const firstNode = nodes.at(0);
if (!firstNode) return;
events.onAdd(firstNode);
});
2022-12-04 17:36:30 +01:00
grid.batchUpdate();
grid.removeAll(false);
2023-01-07 09:45:00 +01:00
items.forEach(({ id, shape }) => {
const item = itemRefs.current[id]?.current;
setAttributesFromShape(item, shape[shapeSize]);
item && grid.makeWidget(item as HTMLDivElement);
2023-01-07 23:25:13 +01:00
if (!shape[shapeSize] && item) {
const gridItemElement = item as GridItemHTMLElement;
if (gridItemElement.gridstackNode) {
const { x, y, w, h } = gridItemElement.gridstackNode;
tilesWithUnknownLocation.push({ x, y, w, h, type: 'app', id });
}
}
2023-01-07 09:45:00 +01:00
});
widgets.forEach(({ id, shape }) => {
const item = itemRefs.current[id]?.current;
setAttributesFromShape(item, shape[shapeSize]);
item && grid.makeWidget(item as HTMLDivElement);
2023-01-07 23:25:13 +01:00
if (!shape[shapeSize] && item) {
const gridItemElement = item as GridItemHTMLElement;
if (gridItemElement.gridstackNode) {
const { x, y, w, h } = gridItemElement.gridstackNode;
tilesWithUnknownLocation.push({ x, y, w, h, type: 'widget', id });
}
}
2023-01-07 09:45:00 +01:00
});
2022-12-04 17:36:30 +01:00
grid.batchUpdate(false);
};
2023-01-06 23:50:08 +01:00
function setAttributesFromShape(ref: HTMLDivElement | null, sizedShape: ShapeType['lg']) {
if (!sizedShape || !ref) return;
ref.setAttribute('gs-x', sizedShape.location.x.toString());
ref.setAttribute('gs-y', sizedShape.location.y.toString());
ref.setAttribute('gs-w', sizedShape.size.width.toString());
ref.setAttribute('gs-h', sizedShape.size.height.toString());
}
2023-01-07 23:25:13 +01:00
export type TileWithUnknownLocation = {
x?: number;
y?: number;
w?: number;
h?: number;
type: 'app' | 'widget';
id: string;
};