@vc-shell/framework 1.1.77 → 1.1.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/core/services/dashboard-service.ts +5 -11
- package/dist/core/services/dashboard-service.d.ts.map +1 -1
- package/dist/framework.js +2541 -2520
- package/dist/index.css +1 -1
- package/dist/shared/components/draggable-dashboard/DraggableDashboard.vue.d.ts.map +1 -1
- package/dist/shared/components/draggable-dashboard/composables/useDashboardGrid.d.ts +1 -0
- package/dist/shared/components/draggable-dashboard/composables/useDashboardGrid.d.ts.map +1 -1
- package/dist/shared/components/draggable-dashboard/composables/useLayoutPersistence.d.ts +1 -0
- package/dist/shared/components/draggable-dashboard/composables/useLayoutPersistence.d.ts.map +1 -1
- package/dist/shared/components/draggable-dashboard/composables/useWidgetLayout.d.ts +1 -0
- package/dist/shared/components/draggable-dashboard/composables/useWidgetLayout.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/molecules/vc-field/vc-field.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-radio-button/vc-radio-button.vue.d.ts.map +1 -1
- package/package.json +4 -4
- package/shared/components/draggable-dashboard/DraggableDashboard.vue +23 -0
- package/shared/components/draggable-dashboard/composables/useDashboardGrid.ts +25 -0
- package/shared/components/draggable-dashboard/composables/useLayoutPersistence.ts +10 -0
- package/shared/components/draggable-dashboard/composables/useWidgetLayout.ts +39 -0
- package/ui/components/molecules/vc-field/vc-field.vue +1 -6
- package/ui/components/molecules/vc-radio-button/vc-radio-button.vue +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vc-field.vue.d.ts","sourceRoot":"","sources":["../../../../../ui/components/molecules/vc-field/vc-field.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vc-field.vue.d.ts","sourceRoot":"","sources":["../../../../../ui/components/molecules/vc-field/vc-field.vue"],"names":[],"mappings":"AA8GA,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;IACvD;;OAEG;IAEH,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;;UAlBQ,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO;iBAaxC,YAAY,GAAG,UAAU;iBAIzB,CAAC,MAAM,EAAE,MAAM,CAAC;;AAmJhC,wBAOG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vc-radio-button.vue.d.ts","sourceRoot":"","sources":["../../../../../ui/components/molecules/vc-radio-button/vc-radio-button.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vc-radio-button.vue.d.ts","sourceRoot":"","sources":["../../../../../ui/components/molecules/vc-radio-button/vc-radio-button.vue"],"names":[],"mappings":"AA2MA,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,KAAK,EAAE,GAAG,CAAC;IACX;;OAEG;IACH,UAAU,EAAE,GAAG,CAAC;IAChB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;CAChD;AAyED,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAuB7C,QAAA,MAAM,eAAe;;;;;UAtHZ,MAAM;6EA8Hb,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAa1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vc-shell/framework",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.78",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/framework.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -90,9 +90,9 @@
|
|
|
90
90
|
"@fullhuman/postcss-purgecss": "^7.0.2",
|
|
91
91
|
"@laynezh/vite-plugin-lib-assets": "v1.1.0",
|
|
92
92
|
"@types/dompurify": "^3.0.5",
|
|
93
|
-
"@vc-shell/api-client-generator": "^1.1.
|
|
94
|
-
"@vc-shell/config-generator": "^1.1.
|
|
95
|
-
"@vc-shell/ts-config": "^1.1.
|
|
93
|
+
"@vc-shell/api-client-generator": "^1.1.78",
|
|
94
|
+
"@vc-shell/config-generator": "^1.1.78",
|
|
95
|
+
"@vc-shell/ts-config": "^1.1.78",
|
|
96
96
|
"@vitejs/plugin-vue": "^5.2.3",
|
|
97
97
|
"@vue/test-utils": "^2.4.5",
|
|
98
98
|
"cypress-signalr-mock": "^1.5.0",
|
|
@@ -84,6 +84,7 @@ const {
|
|
|
84
84
|
saveLayoutToLocalStorage,
|
|
85
85
|
loadLayoutFromLocalStorage,
|
|
86
86
|
initializeWithBuiltInPositions,
|
|
87
|
+
handleNewWidget,
|
|
87
88
|
} = useDashboardGrid();
|
|
88
89
|
|
|
89
90
|
// Initialize cellSize calculator
|
|
@@ -116,6 +117,28 @@ watch(gridContainerRef, (container) => {
|
|
|
116
117
|
}
|
|
117
118
|
});
|
|
118
119
|
|
|
120
|
+
// Watch for new widgets and handle their placement
|
|
121
|
+
watch(
|
|
122
|
+
widgets,
|
|
123
|
+
(newWidgets, oldWidgets) => {
|
|
124
|
+
if (!oldWidgets || newWidgets.length > oldWidgets.length) {
|
|
125
|
+
// New widgets have been added
|
|
126
|
+
const newWidgetIds = newWidgets
|
|
127
|
+
.filter(w => !oldWidgets?.some(ow => ow.id === w.id))
|
|
128
|
+
.map(w => w.id);
|
|
129
|
+
|
|
130
|
+
newWidgetIds.forEach(widgetId => {
|
|
131
|
+
const widget = newWidgets.find(w => w.id === widgetId);
|
|
132
|
+
if (widget && !layout.value.has(widgetId)) {
|
|
133
|
+
// Widget doesn't have a position yet, find a free one
|
|
134
|
+
handleNewWidget(widget);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{ immediate: false },
|
|
140
|
+
);
|
|
141
|
+
|
|
119
142
|
// Watch for layout changes and save to localStorage
|
|
120
143
|
watch(
|
|
121
144
|
layout,
|
|
@@ -78,6 +78,15 @@ export function useDashboardGrid() {
|
|
|
78
78
|
const initializeLayout = (): void => {
|
|
79
79
|
// Priority 1: Loading from localStorage
|
|
80
80
|
const layoutLoadedFromStorage = loadLayoutFromLocalStorage();
|
|
81
|
+
|
|
82
|
+
// Check for new widgets that don't have positions in localStorage
|
|
83
|
+
const savedPositions = persistence.getSavedPositions();
|
|
84
|
+
const widgetsWithoutSavedPosition = widgets.value.filter(w => !savedPositions[w.id] && !layout.value.has(w.id));
|
|
85
|
+
|
|
86
|
+
if (widgetsWithoutSavedPosition.length > 0) {
|
|
87
|
+
// Place new widgets without collisions
|
|
88
|
+
widgetLayout.placeNewWidgets(widgetsWithoutSavedPosition, widgets.value, layout.value);
|
|
89
|
+
}
|
|
81
90
|
|
|
82
91
|
// Priority 2: Using built-in widget positions
|
|
83
92
|
if (!layoutLoadedFromStorage) {
|
|
@@ -90,6 +99,21 @@ export function useDashboardGrid() {
|
|
|
90
99
|
}
|
|
91
100
|
};
|
|
92
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Handles registration of new widgets after initialization
|
|
104
|
+
*/
|
|
105
|
+
const handleNewWidget = (widget: IDashboardWidget): void => {
|
|
106
|
+
// Check if widget already has a valid position from localStorage
|
|
107
|
+
const savedPositions = persistence.getSavedPositions();
|
|
108
|
+
if (savedPositions[widget.id]) {
|
|
109
|
+
return; // Position already loaded from localStorage
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Find a free position for the new widget
|
|
113
|
+
const position = widgetLayout.findFreePosition(widget, widgets.value, layout.value);
|
|
114
|
+
dashboard.updateWidgetPosition(widget.id, position);
|
|
115
|
+
};
|
|
116
|
+
|
|
93
117
|
return {
|
|
94
118
|
widgets,
|
|
95
119
|
layout,
|
|
@@ -100,5 +124,6 @@ export function useDashboardGrid() {
|
|
|
100
124
|
arrangeWidgetsInRows,
|
|
101
125
|
initializeWithBuiltInPositions,
|
|
102
126
|
initializeLayout,
|
|
127
|
+
handleNewWidget,
|
|
103
128
|
};
|
|
104
129
|
}
|
|
@@ -66,6 +66,15 @@ export function useLayoutPersistence(
|
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Gets saved positions for specific widgets
|
|
71
|
+
*
|
|
72
|
+
* @returns The saved positions
|
|
73
|
+
*/
|
|
74
|
+
const getSavedPositions = (): Record<string, DashboardWidgetPosition> => {
|
|
75
|
+
return savedLayout.value;
|
|
76
|
+
};
|
|
77
|
+
|
|
69
78
|
/**
|
|
70
79
|
* Clears the saved layout from localStorage
|
|
71
80
|
*/
|
|
@@ -85,5 +94,6 @@ export function useLayoutPersistence(
|
|
|
85
94
|
loadLayout,
|
|
86
95
|
clearSavedLayout,
|
|
87
96
|
hasSavedLayout,
|
|
97
|
+
getSavedPositions,
|
|
88
98
|
};
|
|
89
99
|
}
|
|
@@ -255,10 +255,49 @@ export function useWidgetLayout(updatePositionCallback: (widgetId: string, posit
|
|
|
255
255
|
return true;
|
|
256
256
|
};
|
|
257
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Places new widgets without collisions with existing ones
|
|
260
|
+
*
|
|
261
|
+
* @param newWidgets The array of new widgets to place
|
|
262
|
+
* @param allWidgets The array of all widgets
|
|
263
|
+
* @param layout The map of widget positions
|
|
264
|
+
*/
|
|
265
|
+
const placeNewWidgets = (
|
|
266
|
+
newWidgets: IDashboardWidget[],
|
|
267
|
+
allWidgets: IDashboardWidget[],
|
|
268
|
+
layout: Map<string, DashboardWidgetPosition>,
|
|
269
|
+
): void => {
|
|
270
|
+
if (newWidgets.length === 0) return;
|
|
271
|
+
|
|
272
|
+
// Create a map of occupied cells from existing widgets
|
|
273
|
+
const occupiedCells = grid.createOccupiedCellsMap(allWidgets, layout);
|
|
274
|
+
|
|
275
|
+
// Sort new widgets by size (bigger first)
|
|
276
|
+
const sortedWidgets = [...newWidgets].sort((a, b) => {
|
|
277
|
+
const aSize = a.size.width * a.size.height;
|
|
278
|
+
const bSize = b.size.width * b.size.height;
|
|
279
|
+
return bSize - aSize;
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Place each new widget
|
|
283
|
+
for (const widget of sortedWidgets) {
|
|
284
|
+
const position = findOptimalPosition(widget, occupiedCells, grid.dynamicRows.value + grid.ROWS_BUFFER);
|
|
285
|
+
updatePositionCallback(widget.id, position);
|
|
286
|
+
|
|
287
|
+
// Update the map of occupied cells
|
|
288
|
+
for (let x = position.x; x < position.x + widget.size.width; x++) {
|
|
289
|
+
for (let y = position.y; y < position.y + widget.size.height; y++) {
|
|
290
|
+
occupiedCells.add(`${x},${y}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
258
296
|
return {
|
|
259
297
|
findFreePosition,
|
|
260
298
|
findOptimalPosition,
|
|
261
299
|
arrangeWidgetsInRows,
|
|
262
300
|
initializeWithBuiltInPositions,
|
|
301
|
+
placeNewWidgets,
|
|
263
302
|
};
|
|
264
303
|
}
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
<!-- Field label -->
|
|
11
11
|
<VcLabel
|
|
12
12
|
v-if="label"
|
|
13
|
-
class="vc-field__label"
|
|
14
13
|
>
|
|
15
14
|
<span>{{ label }}</span>
|
|
16
15
|
<template
|
|
@@ -92,17 +91,13 @@ function copy(value: string) {
|
|
|
92
91
|
@apply tw-flex;
|
|
93
92
|
|
|
94
93
|
&--vertical {
|
|
95
|
-
@apply tw-flex-col;
|
|
94
|
+
@apply tw-flex-col tw-gap-2;
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
&--horizontal {
|
|
99
98
|
@apply tw-flex-row tw-items-center;
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
&__label {
|
|
103
|
-
@apply tw-mb-2;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
101
|
&__copy-button {
|
|
107
102
|
@apply tw-ml-2;
|
|
108
103
|
}
|