@vc-shell/framework 1.2.2 → 1.2.3-beta.0
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/core/composables/index.ts +2 -0
- package/core/composables/useAssets/index.ts +72 -28
- package/core/composables/useAsync/index.ts +4 -1
- package/core/composables/useBladeRegistry/index.ts +6 -5
- package/core/composables/useBreadcrumbs/index.ts +4 -1
- package/core/composables/useErrorHandler/index.ts +4 -1
- package/core/composables/useFunctions/debounce.ts +0 -1
- package/core/composables/useFunctions/delay.ts +0 -1
- package/core/composables/useFunctions/index.ts +0 -1
- package/core/composables/useFunctions/once.ts +0 -1
- package/core/composables/useFunctions/sleep.ts +0 -1
- package/core/composables/useFunctions/throttle.ts +0 -1
- package/core/composables/useGlobalSearch/index.ts +3 -3
- package/core/composables/useMenuService/index.ts +5 -2
- package/core/composables/useNotifications/index.ts +5 -2
- package/core/composables/useTheme/index.ts +4 -1
- package/core/composables/useUser/index.ts +189 -20
- package/core/composables/useWidgets/index.ts +5 -2
- package/core/constants/defaults.ts +76 -0
- package/core/constants/index.ts +2 -0
- package/core/constants/ui.ts +68 -0
- package/core/interceptors/index.ts +5 -2
- package/core/plugins/ai-agent/README.md +336 -0
- package/core/plugins/ai-agent/components/VcAiAgentPanel.vue +125 -0
- package/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue +182 -0
- package/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue +77 -0
- package/core/plugins/ai-agent/components/index.ts +1 -0
- package/core/plugins/ai-agent/composables/index.ts +4 -0
- package/core/plugins/ai-agent/composables/useAiAgent.ts +231 -0
- package/core/plugins/ai-agent/composables/useAiAgentContext.ts +280 -0
- package/core/plugins/ai-agent/constants.ts +89 -0
- package/core/plugins/ai-agent/index.ts +91 -0
- package/core/plugins/ai-agent/services/ai-agent-service.ts +598 -0
- package/core/plugins/ai-agent/types.ts +310 -0
- package/core/plugins/modularity/index.ts +8 -6
- package/core/plugins/modularity/loader.ts +36 -33
- package/core/plugins/signalR/index.ts +6 -3
- package/core/services/app-bar-menu-service.ts +4 -1
- package/core/services/dashboard-service.ts +4 -1
- package/core/services/index.ts +2 -0
- package/core/services/menu-service.ts +4 -1
- package/core/services/settings-menu-service.ts +4 -1
- package/core/services/toolbar-service.ts +18 -3
- package/core/services/widget-service.ts +7 -4
- package/core/types/index.ts +3 -0
- package/core/types/services.ts +194 -0
- package/core/utilities/errorTypes.ts +126 -0
- package/core/utilities/index.ts +2 -0
- package/core/utilities/logger.ts +120 -0
- package/dist/core/composables/useAssets/index.d.ts.map +1 -1
- package/dist/core/composables/useAsync/index.d.ts.map +1 -1
- package/dist/core/composables/useBladeRegistry/index.d.ts.map +1 -1
- package/dist/core/composables/useBreadcrumbs/index.d.ts.map +1 -1
- package/dist/core/composables/useErrorHandler/index.d.ts.map +1 -1
- package/dist/core/composables/useFunctions/debounce.d.ts.map +1 -1
- package/dist/core/composables/useFunctions/delay.d.ts.map +1 -1
- package/dist/core/composables/useFunctions/index.d.ts.map +1 -1
- package/dist/core/composables/useFunctions/once.d.ts.map +1 -1
- package/dist/core/composables/useFunctions/sleep.d.ts.map +1 -1
- package/dist/core/composables/useFunctions/throttle.d.ts.map +1 -1
- package/dist/core/composables/useGlobalSearch/index.d.ts.map +1 -1
- package/dist/core/composables/useMenuService/index.d.ts.map +1 -1
- package/dist/core/composables/useNotifications/index.d.ts.map +1 -1
- package/dist/core/composables/useTheme/index.d.ts.map +1 -1
- package/dist/core/composables/useUser/index.d.ts +8 -0
- package/dist/core/composables/useUser/index.d.ts.map +1 -1
- package/dist/core/composables/useWidgets/index.d.ts.map +1 -1
- package/dist/core/constants/defaults.d.ts +63 -0
- package/dist/core/constants/defaults.d.ts.map +1 -0
- package/dist/core/constants/index.d.ts +2 -0
- package/dist/core/constants/index.d.ts.map +1 -1
- package/dist/core/constants/ui.d.ts +50 -0
- package/dist/core/constants/ui.d.ts.map +1 -0
- package/dist/core/interceptors/index.d.ts.map +1 -1
- package/dist/core/plugins/ai-agent/components/VcAiAgentPanel.vue.d.ts +3 -0
- package/dist/core/plugins/ai-agent/components/VcAiAgentPanel.vue.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue.d.ts +15 -0
- package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue.d.ts +10 -0
- package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/components/index.d.ts +2 -0
- package/dist/core/plugins/ai-agent/components/index.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/composables/index.d.ts +4 -0
- package/dist/core/plugins/ai-agent/composables/index.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/composables/useAiAgent.d.ts +95 -0
- package/dist/core/plugins/ai-agent/composables/useAiAgent.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/composables/useAiAgentContext.d.ts +55 -0
- package/dist/core/plugins/ai-agent/composables/useAiAgentContext.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/constants.d.ts +47 -0
- package/dist/core/plugins/ai-agent/constants.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/index.d.ts +48 -0
- package/dist/core/plugins/ai-agent/index.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/services/ai-agent-service.d.ts +45 -0
- package/dist/core/plugins/ai-agent/services/ai-agent-service.d.ts.map +1 -0
- package/dist/core/plugins/ai-agent/types.d.ts +258 -0
- package/dist/core/plugins/ai-agent/types.d.ts.map +1 -0
- package/dist/core/plugins/modularity/index.d.ts.map +1 -1
- package/dist/core/plugins/modularity/loader.d.ts.map +1 -1
- package/dist/core/plugins/signalR/index.d.ts.map +1 -1
- package/dist/core/services/app-bar-menu-service.d.ts.map +1 -1
- package/dist/core/services/dashboard-service.d.ts.map +1 -1
- package/dist/core/services/menu-service.d.ts.map +1 -1
- package/dist/core/services/settings-menu-service.d.ts.map +1 -1
- package/dist/core/services/toolbar-service.d.ts.map +1 -1
- package/dist/core/services/widget-service.d.ts.map +1 -1
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/services.d.ts +169 -0
- package/dist/core/types/services.d.ts.map +1 -0
- package/dist/core/utilities/errorTypes.d.ts +61 -0
- package/dist/core/utilities/errorTypes.d.ts.map +1 -0
- package/dist/core/utilities/index.d.ts +2 -0
- package/dist/core/utilities/index.d.ts.map +1 -1
- package/dist/core/utilities/logger.d.ts +259 -0
- package/dist/core/utilities/logger.d.ts.map +1 -0
- package/dist/framework.js +9623 -8417
- package/dist/index.css +1 -1
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/injection-keys.d.ts +21 -6
- package/dist/injection-keys.d.ts.map +1 -1
- package/dist/shared/components/app-switcher/composables/useAppSwitcher/index.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.d.ts.map +1 -1
- package/dist/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.d.ts.map +1 -1
- package/dist/shared/components/draggable-dashboard/composables/useLayoutPersistence.d.ts.map +1 -1
- package/dist/shared/components/notifications/composables/useContainer/index.d.ts.map +1 -1
- package/dist/shared/components/notifications/composables/useInstance/index.d.ts.map +1 -1
- package/dist/shared/components/notifications/core/notification.d.ts.map +1 -1
- package/dist/shared/components/popup-handler/components/vc-popup-container/vc-popup-container.vue.d.ts.map +1 -1
- package/dist/shared/components/sign-in/useExternalProvider.d.ts.map +1 -1
- package/dist/shared/composables/index.d.ts +1 -0
- package/dist/shared/composables/index.d.ts.map +1 -1
- package/dist/shared/composables/useExternalWidgets.d.ts.map +1 -1
- package/dist/shared/composables/useMenuExpanded.d.ts.map +1 -1
- package/dist/shared/composables/useTableSelection.d.ts +57 -0
- package/dist/shared/composables/useTableSelection.d.ts.map +1 -0
- package/dist/shared/composables/useTableSort.d.ts.map +1 -1
- package/dist/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts.map +1 -1
- package/dist/shared/pages/LoginPage/components/login/Login.vue.d.ts.map +1 -1
- package/dist/shared/utilities/colorUtils.d.ts +0 -6
- package/dist/shared/utilities/colorUtils.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/atoms/vc-banner/vc-banner.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-button/vc-button.vue.d.ts +0 -15
- package/dist/ui/components/atoms/vc-button/vc-button.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-container/vc-container.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-icon/vc-icon.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-icon/vc-lucide-icon.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-image/vc-image.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-link/vc-link.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-loading/vc-loading.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-status/vc-status.vue.d.ts +0 -5
- package/dist/ui/components/atoms/vc-status/vc-status.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-tooltip/vc-tooltip.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-video/vc-video.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-widget/vc-widget.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-input/vc-input.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-pagination/vc-pagination.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-toast/vc-toast.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-buttons/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-login-form/vc-login-form.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableActions.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableColumnResize.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableRowReorder.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableSelection.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableState.d.ts.map +1 -1
- package/dist/{vendor-lodash-es-BqkGj3Jl.js → vendor-lodash-es-SgOIjJF8.js} +2 -0
- package/package.json +5 -5
- package/shared/components/app-switcher/composables/useAppSwitcher/index.ts +4 -1
- package/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue +67 -4
- package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +13 -10
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.ts +7 -4
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.ts +4 -1
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.ts +4 -1
- package/shared/components/change-password/change-password.vue +1 -1
- package/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.ts +14 -5
- package/shared/components/draggable-dashboard/composables/useLayoutPersistence.ts +5 -2
- package/shared/components/index.ts +2 -0
- package/shared/components/notifications/composables/useContainer/index.ts +8 -6
- package/shared/components/notifications/composables/useInstance/index.ts +4 -1
- package/shared/components/notifications/core/notification.ts +10 -7
- package/shared/components/popup-handler/components/vc-popup-container/vc-popup-container.vue +20 -1
- package/shared/components/sign-in/useExternalProvider.ts +6 -4
- package/shared/composables/index.ts +1 -0
- package/shared/composables/useExternalWidgets.ts +7 -4
- package/shared/composables/useMenuExpanded.ts +15 -1
- package/shared/composables/useTableSelection.ts +151 -0
- package/shared/composables/useTableSort.ts +4 -4
- package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +6 -3
- package/shared/pages/LoginPage/components/login/Login.vue +4 -1
- package/shared/utilities/colorUtils.ts +5 -12
- package/ui/components/atoms/vc-banner/vc-banner.vue +4 -1
- package/ui/components/atoms/vc-button/vc-button.vue +2 -25
- package/ui/components/atoms/vc-container/vc-container.vue +12 -3
- package/ui/components/atoms/vc-icon/vc-icon.vue +0 -10
- package/ui/components/atoms/vc-icon/vc-lucide-icon.vue +5 -2
- package/ui/components/atoms/vc-image/vc-image.vue +4 -1
- package/ui/components/atoms/vc-link/vc-link.vue +59 -54
- package/ui/components/atoms/vc-loading/vc-loading.vue +4 -0
- package/ui/components/atoms/vc-status/vc-status.vue +0 -5
- package/ui/components/atoms/vc-status-icon/vc-status-icon.vue +4 -4
- package/ui/components/atoms/vc-tooltip/vc-tooltip.vue +8 -1
- package/ui/components/atoms/vc-video/vc-video.vue +4 -2
- package/ui/components/atoms/vc-widget/vc-widget.vue +4 -1
- package/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue +7 -2
- package/ui/components/molecules/vc-input/vc-input.vue +0 -1
- package/ui/components/molecules/vc-pagination/vc-pagination.vue +6 -1
- package/ui/components/molecules/vc-rating/vc-rating.vue +1 -1
- package/ui/components/molecules/vc-textarea/vc-textarea.vue +1 -1
- package/ui/components/molecules/vc-toast/vc-toast.vue +11 -1
- package/ui/components/organisms/vc-app/vc-app.vue +22 -3
- package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-buttons/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue +4 -1
- package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/vc-blade-toolbar.vue +14 -14
- package/ui/components/organisms/vc-blade/vc-blade.vue +3 -1
- package/ui/components/organisms/vc-login-form/vc-login-form.vue +3 -1
- package/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +34 -2
- package/ui/components/organisms/vc-table/composables/useTableActions.ts +7 -10
- package/ui/components/organisms/vc-table/composables/useTableColumnResize.ts +4 -1
- package/ui/components/organisms/vc-table/composables/useTableRowReorder.ts +5 -2
- package/ui/components/organisms/vc-table/composables/useTableSelection.ts +26 -18
- package/ui/components/organisms/vc-table/composables/useTableState.ts +4 -1
- package/core/services/global-search-service.ts +0 -36
- package/dist/core/services/global-search-service.d.ts +0 -10
- package/dist/core/services/global-search-service.d.ts.map +0 -1
|
@@ -11,6 +11,15 @@ import { useGridPosition, type CellSize } from "./useGridPosition";
|
|
|
11
11
|
// Value of 80px is defined in DraggableDashboard.vue
|
|
12
12
|
const CELL_HEIGHT = 80;
|
|
13
13
|
|
|
14
|
+
/** Minimum movement threshold in pixels to start dragging */
|
|
15
|
+
const DRAG_THRESHOLD = 3;
|
|
16
|
+
/** Gap between widgets in pixels */
|
|
17
|
+
const WIDGET_GAP = 20;
|
|
18
|
+
/** Delay in ms for animation style application */
|
|
19
|
+
const ANIMATION_STYLE_DELAY = 20;
|
|
20
|
+
/** Delay in ms for state reset after drag ends */
|
|
21
|
+
const STATE_RESET_DELAY = 50;
|
|
22
|
+
|
|
14
23
|
/**
|
|
15
24
|
* Return type for the useDashboardDragAndDrop composable.
|
|
16
25
|
*/
|
|
@@ -169,7 +178,7 @@ export function useDashboardDragAndDrop(
|
|
|
169
178
|
|
|
170
179
|
if (originalWidget) {
|
|
171
180
|
const cellSize = calculateCellSize();
|
|
172
|
-
const widgetGap =
|
|
181
|
+
const widgetGap = WIDGET_GAP;
|
|
173
182
|
|
|
174
183
|
// Get the current position of the clone (where the user released the mouse)
|
|
175
184
|
const cloneRect = dragClone.value.getBoundingClientRect();
|
|
@@ -215,7 +224,7 @@ export function useDashboardDragAndDrop(
|
|
|
215
224
|
setTimeout(() => {
|
|
216
225
|
originalWidget.style.transition = `transform var(--dashboard-transition-duration) var(--dashboard-transition-timing)`;
|
|
217
226
|
originalWidget.style.transform = `translate(${finalX}px, ${finalY}px)`;
|
|
218
|
-
},
|
|
227
|
+
}, ANIMATION_STYLE_DELAY);
|
|
219
228
|
} else {
|
|
220
229
|
// If the original is not found, simply remove the clone and update the data
|
|
221
230
|
removeDragClone();
|
|
@@ -250,7 +259,7 @@ export function useDashboardDragAndDrop(
|
|
|
250
259
|
isDragging.value = false;
|
|
251
260
|
draggedWidget.value = null;
|
|
252
261
|
resetPosition();
|
|
253
|
-
},
|
|
262
|
+
}, STATE_RESET_DELAY);
|
|
254
263
|
};
|
|
255
264
|
|
|
256
265
|
// Mouse/touch event handler with passive listeners
|
|
@@ -284,8 +293,8 @@ export function useDashboardDragAndDrop(
|
|
|
284
293
|
|
|
285
294
|
const currentCoords = getEventCoordinates(moveEvent);
|
|
286
295
|
|
|
287
|
-
// Start dragging only if the mouse has moved
|
|
288
|
-
if (hasMovedBeyondThreshold(currentCoords,
|
|
296
|
+
// Start dragging only if the mouse has moved beyond threshold
|
|
297
|
+
if (hasMovedBeyondThreshold(currentCoords, DRAG_THRESHOLD)) {
|
|
289
298
|
hasDragStarted = true;
|
|
290
299
|
isDragging.value = true;
|
|
291
300
|
draggedWidget.value = widget;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { useLocalStorage } from "@vueuse/core";
|
|
2
2
|
import type { DashboardWidgetPosition } from "../types";
|
|
3
|
+
import { createLogger } from "../../../../core/utilities";
|
|
4
|
+
|
|
5
|
+
const logger = createLogger("use-layout-persistence");
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* Hook for managing the saving and loading of the dashboard layout
|
|
@@ -34,7 +37,7 @@ export function useLayoutPersistence(
|
|
|
34
37
|
// Save to localStorage through the reactive variable
|
|
35
38
|
savedLayout.value = layoutData;
|
|
36
39
|
} catch (error) {
|
|
37
|
-
|
|
40
|
+
logger.error("Failed to save dashboard layout to localStorage:", error);
|
|
38
41
|
}
|
|
39
42
|
};
|
|
40
43
|
|
|
@@ -61,7 +64,7 @@ export function useLayoutPersistence(
|
|
|
61
64
|
|
|
62
65
|
return true;
|
|
63
66
|
} catch (error) {
|
|
64
|
-
|
|
67
|
+
logger.error("Failed to load dashboard layout from localStorage:", error);
|
|
65
68
|
return false;
|
|
66
69
|
}
|
|
67
70
|
};
|
|
@@ -16,3 +16,5 @@ export * from "./generic-dropdown";
|
|
|
16
16
|
export * from "./draggable-dashboard";
|
|
17
17
|
export * from "./dashboard-widget-card";
|
|
18
18
|
export * from "./multilanguage-selector";
|
|
19
|
+
// ai-agent-panel is now part of the ai-agent plugin
|
|
20
|
+
// export * from "./core/plugins/ai-agent";
|
|
@@ -3,7 +3,9 @@ import { NotificationOptions, NotificationPosition } from "../../types";
|
|
|
3
3
|
import { NotificationContainer } from "../../components";
|
|
4
4
|
import { useInstance } from "../useInstance";
|
|
5
5
|
import * as _ from "lodash-es";
|
|
6
|
-
import { generateId } from "../../../../../core/utilities";
|
|
6
|
+
import { generateId, createLogger } from "../../../../../core/utilities";
|
|
7
|
+
|
|
8
|
+
const logger = createLogger("notification-container");
|
|
7
9
|
|
|
8
10
|
export interface PendingNotification {
|
|
9
11
|
notificationId: string | number;
|
|
@@ -304,7 +306,7 @@ export function useContainer(): IUseContainer {
|
|
|
304
306
|
|
|
305
307
|
// If we found the notification and container to update
|
|
306
308
|
if (notification && containerToUpdate) {
|
|
307
|
-
|
|
309
|
+
logger.debug(`Updating notification ${option.notificationId} in position ${containerPosition}`);
|
|
308
310
|
|
|
309
311
|
// If the position changes, move the notification between containers
|
|
310
312
|
if (option.position && option.position !== containerPosition) {
|
|
@@ -325,16 +327,16 @@ export function useContainer(): IUseContainer {
|
|
|
325
327
|
// Check if a container already exists for the target position
|
|
326
328
|
if (!getInstanceByPosition(targetPosition)) {
|
|
327
329
|
// If no container exists for the target position, create a new one
|
|
328
|
-
|
|
330
|
+
logger.debug(`Creating new container for position ${targetPosition}`);
|
|
329
331
|
appendInstance(updatedNotification);
|
|
330
332
|
} else {
|
|
331
333
|
// If a container exists for the target position, add the updated notification
|
|
332
|
-
|
|
334
|
+
logger.debug(`Adding to existing container for position ${targetPosition}`);
|
|
333
335
|
notificationContainers[targetPosition].value.push(updatedNotification);
|
|
334
336
|
}
|
|
335
337
|
} else {
|
|
336
338
|
// Standard update of notification properties
|
|
337
|
-
|
|
339
|
+
logger.debug(`Standard update of notification properties`);
|
|
338
340
|
|
|
339
341
|
// Apply all new properties from option to notification
|
|
340
342
|
Object.keys(option).forEach((key) => {
|
|
@@ -353,7 +355,7 @@ export function useContainer(): IUseContainer {
|
|
|
353
355
|
|
|
354
356
|
return true;
|
|
355
357
|
} else {
|
|
356
|
-
|
|
358
|
+
logger.warn(`Notification with ID ${option.notificationId} not found for update`);
|
|
357
359
|
return false;
|
|
358
360
|
}
|
|
359
361
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { App, Ref, ref } from "vue";
|
|
2
2
|
import { NotificationPosition } from "../../types";
|
|
3
|
+
import { createLogger } from "../../../../../core/utilities";
|
|
4
|
+
|
|
5
|
+
const logger = createLogger("notification-instance");
|
|
3
6
|
|
|
4
7
|
interface IUseInstance {
|
|
5
8
|
saveInstance(app: App<Element>, id: string, position: NotificationPosition): void;
|
|
@@ -51,7 +54,7 @@ export function useInstance(): IUseInstance {
|
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
} catch (error) {
|
|
54
|
-
|
|
57
|
+
logger.error("Failed to unmount notification component:", error);
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { mergeProps } from "vue";
|
|
2
2
|
import { Content, InternalNotificationOptions, NotificationOptions, NotificationPosition } from "../types";
|
|
3
3
|
import { useContainer } from "../composables/useContainer";
|
|
4
|
+
import { createLogger } from "../../../../core/utilities";
|
|
5
|
+
|
|
6
|
+
const logger = createLogger("notification");
|
|
4
7
|
|
|
5
8
|
const {
|
|
6
9
|
defaultOptions,
|
|
@@ -103,7 +106,7 @@ notification.remove = (notificationId?: number | string) => {
|
|
|
103
106
|
notification.update = (notificationId: string | number, options: NotificationOptions) => {
|
|
104
107
|
// Check if notification exists
|
|
105
108
|
if (!hasNotification(notificationId)) {
|
|
106
|
-
|
|
109
|
+
logger.warn(`Cannot update: notification with ID ${notificationId} not found`);
|
|
107
110
|
return notificationId;
|
|
108
111
|
}
|
|
109
112
|
|
|
@@ -195,12 +198,12 @@ notification.clearPosition = (position: NotificationPosition) => {
|
|
|
195
198
|
notification.debug = () => {
|
|
196
199
|
// Default settings information
|
|
197
200
|
Object.entries(defaultOptions).forEach(([key, value]) => {
|
|
198
|
-
|
|
201
|
+
logger.debug(`Default option ${key}: `, value);
|
|
199
202
|
});
|
|
200
203
|
|
|
201
204
|
// Available actions
|
|
202
205
|
Object.entries(actions).forEach(([key]) => {
|
|
203
|
-
|
|
206
|
+
logger.debug(`Available action: ${key}`);
|
|
204
207
|
});
|
|
205
208
|
|
|
206
209
|
// Collect statistics on notifications in different positions
|
|
@@ -231,14 +234,14 @@ notification.debug = () => {
|
|
|
231
234
|
|
|
232
235
|
// Display group information
|
|
233
236
|
Object.entries(groupedNotifications).forEach(([position, items]) => {
|
|
234
|
-
|
|
235
|
-
items.forEach((item) =>
|
|
237
|
+
logger.debug(`Position ${position}: ${items.length} notifications`);
|
|
238
|
+
items.forEach((item) => logger.debug(` - ${item.id} (${item.type}): ${item.content}`));
|
|
236
239
|
});
|
|
237
240
|
|
|
238
241
|
// Collect statistics on pending notifications
|
|
239
|
-
|
|
242
|
+
logger.debug(`Pending notifications: ${pending.items.length}`);
|
|
240
243
|
pending.items.forEach((item) => {
|
|
241
|
-
|
|
244
|
+
logger.debug(` - ${item.notificationId} (position: ${item.position})`);
|
|
242
245
|
});
|
|
243
246
|
|
|
244
247
|
return {
|
package/shared/components/popup-handler/components/vc-popup-container/vc-popup-container.vue
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<div
|
|
15
15
|
v-if="typeof slot === 'string'"
|
|
16
16
|
class="tw-h-full tw-w-full"
|
|
17
|
-
v-html="slot"
|
|
17
|
+
v-html="sanitizeHtml(slot)"
|
|
18
18
|
></div>
|
|
19
19
|
<component
|
|
20
20
|
:is="slot"
|
|
@@ -25,6 +25,25 @@
|
|
|
25
25
|
</template>
|
|
26
26
|
|
|
27
27
|
<script setup lang="ts">
|
|
28
|
+
// eslint-disable-next-line import/no-named-as-default
|
|
29
|
+
import DOMPurify from "dompurify";
|
|
28
30
|
import { getPopupPlugin } from "./../../utils";
|
|
31
|
+
|
|
29
32
|
const popupPlugin = getPopupPlugin();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Sanitize HTML content to prevent XSS attacks
|
|
36
|
+
*/
|
|
37
|
+
function sanitizeHtml(html: string): string {
|
|
38
|
+
return DOMPurify.sanitize(html, {
|
|
39
|
+
ALLOWED_TAGS: [
|
|
40
|
+
"p", "br", "strong", "em", "u", "s", "h1", "h2", "h3", "h4", "h5", "h6",
|
|
41
|
+
"ul", "ol", "li", "blockquote", "pre", "code", "a", "img", "table",
|
|
42
|
+
"thead", "tbody", "tr", "th", "td", "hr", "div", "span",
|
|
43
|
+
],
|
|
44
|
+
ALLOWED_ATTR: ["href", "src", "alt", "title", "class", "id", "colspan", "rowspan", "align", "valign"],
|
|
45
|
+
FORBID_TAGS: ["script", "object", "embed", "form", "input"],
|
|
46
|
+
FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover", "onfocus", "onblur", "style"],
|
|
47
|
+
});
|
|
48
|
+
}
|
|
30
49
|
</script>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { useLocalStorage } from "@vueuse/core";
|
|
2
2
|
import type { Ref } from "vue";
|
|
3
3
|
import { ExternalSignInClient, ExternalSignInProviderInfo } from "../../../core/api/platform";
|
|
4
|
+
import { createLogger } from "../../../core/utilities";
|
|
5
|
+
|
|
6
|
+
const logger = createLogger("use-external-provider");
|
|
4
7
|
|
|
5
8
|
export interface IUseExternalProvider {
|
|
6
9
|
storage: Ref<{ providerType?: string | undefined }>;
|
|
@@ -53,7 +56,7 @@ export const useExternalProvider = (): IUseExternalProvider => {
|
|
|
53
56
|
// Redirect to the constructed URL
|
|
54
57
|
window.location.assign(url);
|
|
55
58
|
} catch (e) {
|
|
56
|
-
|
|
59
|
+
logger.error("External sign-in failed:", e);
|
|
57
60
|
throw e;
|
|
58
61
|
}
|
|
59
62
|
}
|
|
@@ -75,7 +78,7 @@ export const useExternalProvider = (): IUseExternalProvider => {
|
|
|
75
78
|
// Redirect to the sign-out URL
|
|
76
79
|
window.location.assign(url);
|
|
77
80
|
} catch (e) {
|
|
78
|
-
|
|
81
|
+
logger.error("External sign-out failed:", e);
|
|
79
82
|
throw e;
|
|
80
83
|
}
|
|
81
84
|
}
|
|
@@ -85,8 +88,7 @@ export const useExternalProvider = (): IUseExternalProvider => {
|
|
|
85
88
|
try {
|
|
86
89
|
result = await externalSecurityClient.getExternalLoginProviders();
|
|
87
90
|
} catch (e) {
|
|
88
|
-
|
|
89
|
-
// TODO check error in app!!!
|
|
91
|
+
logger.error("Failed to get external login providers:", e);
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
return result;
|
|
@@ -2,6 +2,9 @@ import { computed, inject, onMounted, onUnmounted, watch, toValue, Ref, Computed
|
|
|
2
2
|
import { WidgetServiceKey, BladeInstance } from "../../injection-keys";
|
|
3
3
|
import { IWidget } from "../../core/services";
|
|
4
4
|
import { useBlade } from "../../core/composables";
|
|
5
|
+
import { createLogger } from "../../core/utilities";
|
|
6
|
+
|
|
7
|
+
const logger = createLogger("use-external-widgets");
|
|
5
8
|
|
|
6
9
|
export interface UseExternalWidgetsOptions {
|
|
7
10
|
bladeId: Ref<string> | string;
|
|
@@ -21,7 +24,7 @@ export function useExternalWidgets(options: UseExternalWidgetsOptions) {
|
|
|
21
24
|
|
|
22
25
|
const registerExternalWidgets = () => {
|
|
23
26
|
if (!widgetService || !blade?.value.id) {
|
|
24
|
-
|
|
27
|
+
logger.warn("Widget service or blade instance not available");
|
|
25
28
|
return;
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -48,7 +51,7 @@ export function useExternalWidgets(options: UseExternalWidgetsOptions) {
|
|
|
48
51
|
widgetService.registerWidget(newWidget, normalizedBladeId.value);
|
|
49
52
|
registeredExternalWidgetIds.add(externalWidget.id);
|
|
50
53
|
} catch (error) {
|
|
51
|
-
|
|
54
|
+
logger.error(`Failed to register external widget '${externalWidget.id}':`, error);
|
|
52
55
|
}
|
|
53
56
|
});
|
|
54
57
|
};
|
|
@@ -68,7 +71,7 @@ export function useExternalWidgets(options: UseExternalWidgetsOptions) {
|
|
|
68
71
|
widget: { props: resolvedProps },
|
|
69
72
|
});
|
|
70
73
|
} catch (error) {
|
|
71
|
-
|
|
74
|
+
logger.error(`Failed to update props for widget '${widget.id}':`, error);
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
});
|
|
@@ -81,7 +84,7 @@ export function useExternalWidgets(options: UseExternalWidgetsOptions) {
|
|
|
81
84
|
try {
|
|
82
85
|
widgetService.unregisterWidget(widgetId, normalizedBladeId.value);
|
|
83
86
|
} catch (error) {
|
|
84
|
-
|
|
87
|
+
logger.error(`Failed to unregister external widget '${widgetId}':`, error);
|
|
85
88
|
}
|
|
86
89
|
});
|
|
87
90
|
registeredExternalWidgetIds.clear();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useLocalStorage } from "@vueuse/core";
|
|
2
|
-
import { ref } from "vue";
|
|
2
|
+
import { ref, onScopeDispose } from "vue";
|
|
3
3
|
|
|
4
4
|
const STORAGE_KEY_PREFIX = "VC_APP_MENU_EXPANDED";
|
|
5
5
|
const HOVER_DELAY = 200;
|
|
@@ -42,6 +42,20 @@ export const useMenuExpanded = () => {
|
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Cleanup timeout when the effect scope is disposed
|
|
47
|
+
* This prevents memory leaks when component using this composable is unmounted
|
|
48
|
+
*/
|
|
49
|
+
const cleanup = () => {
|
|
50
|
+
if (expandTimeout) {
|
|
51
|
+
clearTimeout(expandTimeout);
|
|
52
|
+
expandTimeout = null;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Register cleanup function to be called when effect scope is disposed
|
|
57
|
+
onScopeDispose(cleanup);
|
|
58
|
+
|
|
45
59
|
return {
|
|
46
60
|
isExpanded,
|
|
47
61
|
toggleExpanded,
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { ref, computed, Ref, ComputedRef } from "vue";
|
|
2
|
+
import { createLogger } from "../../core/utilities";
|
|
3
|
+
|
|
4
|
+
const logger = createLogger("use-table-selection");
|
|
5
|
+
|
|
6
|
+
export interface UseTableSelectionOptions<T> {
|
|
7
|
+
/**
|
|
8
|
+
* The field to use for extracting IDs from items.
|
|
9
|
+
* Can be a key of T or a function that extracts the ID.
|
|
10
|
+
* @default 'id'
|
|
11
|
+
*/
|
|
12
|
+
idField?: keyof T | ((item: T) => string | undefined);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface UseTableSelectionReturn<T> {
|
|
16
|
+
/**
|
|
17
|
+
* Array of currently selected item objects.
|
|
18
|
+
*/
|
|
19
|
+
selectedItems: Ref<T[]>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Computed array of IDs extracted from selected items.
|
|
23
|
+
*/
|
|
24
|
+
selectedIds: ComputedRef<string[]>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Whether "select all" across pagination is active.
|
|
28
|
+
*/
|
|
29
|
+
allSelected: Ref<boolean>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Number of currently selected items.
|
|
33
|
+
*/
|
|
34
|
+
selectionCount: ComputedRef<number>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Whether any items are currently selected.
|
|
38
|
+
*/
|
|
39
|
+
hasSelection: ComputedRef<boolean>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Handler for VcTable's @selection-changed event.
|
|
43
|
+
*/
|
|
44
|
+
handleSelectionChange: (items: T[]) => void;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Handler for VcTable's @select:all event.
|
|
48
|
+
*/
|
|
49
|
+
handleSelectAll: (selected: boolean) => void;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Clears all selection state.
|
|
53
|
+
*/
|
|
54
|
+
resetSelection: () => void;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Checks if a specific item is selected.
|
|
58
|
+
*/
|
|
59
|
+
isSelected: (item: T) => boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Programmatically select items.
|
|
63
|
+
*/
|
|
64
|
+
selectItems: (items: T[]) => void;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Deselect items by their IDs.
|
|
68
|
+
*/
|
|
69
|
+
deselectByIds: (ids: string[]) => void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function useTableSelection<T extends object>(
|
|
73
|
+
options?: UseTableSelectionOptions<T>
|
|
74
|
+
): UseTableSelectionReturn<T> {
|
|
75
|
+
const idField = options?.idField ?? ("id" as keyof T);
|
|
76
|
+
|
|
77
|
+
const getItemId = (item: T): string | undefined => {
|
|
78
|
+
if (typeof idField === "function") {
|
|
79
|
+
return idField(item);
|
|
80
|
+
}
|
|
81
|
+
const value = item[idField as keyof T];
|
|
82
|
+
return typeof value === "string" ? value : undefined;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const selectedItems = ref<T[]>([]) as Ref<T[]>;
|
|
86
|
+
const allSelected = ref(false);
|
|
87
|
+
|
|
88
|
+
const selectedIds = computed<string[]>(() => {
|
|
89
|
+
return selectedItems.value.flatMap((item) => {
|
|
90
|
+
const id = getItemId(item);
|
|
91
|
+
return id ? [id] : [];
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const selectionCount = computed(() => selectedItems.value.length);
|
|
96
|
+
const hasSelection = computed(() => selectedItems.value.length > 0);
|
|
97
|
+
const selectedIdSet = computed(() => new Set(selectedIds.value));
|
|
98
|
+
|
|
99
|
+
const handleSelectionChange = (items: T[]): void => {
|
|
100
|
+
selectedItems.value = items;
|
|
101
|
+
if (items.length === 0) {
|
|
102
|
+
allSelected.value = false;
|
|
103
|
+
}
|
|
104
|
+
logger.debug("Selection changed", { count: items.length });
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const handleSelectAll = (selected: boolean): void => {
|
|
108
|
+
allSelected.value = selected;
|
|
109
|
+
if (!selected) {
|
|
110
|
+
selectedItems.value = [];
|
|
111
|
+
}
|
|
112
|
+
logger.debug("Select all changed", { selected });
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const resetSelection = (): void => {
|
|
116
|
+
selectedItems.value = [];
|
|
117
|
+
allSelected.value = false;
|
|
118
|
+
logger.debug("Selection reset");
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const isSelected = (item: T): boolean => {
|
|
122
|
+
const id = getItemId(item);
|
|
123
|
+
return id ? selectedIdSet.value.has(id) : false;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const selectItems = (items: T[]): void => {
|
|
127
|
+
selectedItems.value = items;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const deselectByIds = (ids: string[]): void => {
|
|
131
|
+
const idsToRemove = new Set(ids);
|
|
132
|
+
selectedItems.value = selectedItems.value.filter((item) => {
|
|
133
|
+
const id = getItemId(item);
|
|
134
|
+
return id ? !idsToRemove.has(id) : true;
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
selectedItems,
|
|
140
|
+
selectedIds,
|
|
141
|
+
allSelected,
|
|
142
|
+
selectionCount,
|
|
143
|
+
hasSelection,
|
|
144
|
+
handleSelectionChange,
|
|
145
|
+
handleSelectAll,
|
|
146
|
+
resetSelection,
|
|
147
|
+
isSelected,
|
|
148
|
+
selectItems,
|
|
149
|
+
deselectByIds,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
// framework/composables/useTableSort.ts
|
|
3
3
|
import { ref, computed, Ref, WritableComputedRef } from "vue";
|
|
4
|
+
import { createLogger } from "../../core/utilities";
|
|
5
|
+
|
|
6
|
+
const logger = createLogger("use-table-sort");
|
|
4
7
|
|
|
5
8
|
export type ITableSortDirection = "ASC" | "DESC";
|
|
6
9
|
|
|
@@ -48,8 +51,6 @@ export function useTableSort(options?: UseTableSortOptions): UseTableSortReturn
|
|
|
48
51
|
});
|
|
49
52
|
|
|
50
53
|
const handleSortChange = (sortParam: SortParam) => {
|
|
51
|
-
console.log("[useTableSort] handleSortChange triggered. Received sortParam:", JSON.stringify(sortParam));
|
|
52
|
-
|
|
53
54
|
let newSortProperty: string | undefined = undefined;
|
|
54
55
|
let newSortDirection: ITableSortDirection | undefined = undefined;
|
|
55
56
|
|
|
@@ -79,9 +80,8 @@ export function useTableSort(options?: UseTableSortOptions): UseTableSortReturn
|
|
|
79
80
|
currentSortProperty.value = newSortProperty;
|
|
80
81
|
currentSortDirection.value = newSortDirection || "ASC"; // Default to ASC if no direction provided
|
|
81
82
|
}
|
|
82
|
-
console.log(`[useTableSort] New sort state: ${currentSortProperty.value}:${currentSortDirection.value}`);
|
|
83
83
|
} else {
|
|
84
|
-
|
|
84
|
+
logger.warn("Could not determine valid sort property from sortParam:", sortParam);
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
87
|
|
|
@@ -160,6 +160,9 @@ import moment from "moment";
|
|
|
160
160
|
import { isImage, getFileThumbnail, readableSize } from "./../../../../utilities/assets";
|
|
161
161
|
import * as _ from "lodash-es";
|
|
162
162
|
import { IParentCallArgs, useBladeNavigation } from "../../../../components";
|
|
163
|
+
import { createLogger } from "../../../../../core/utilities";
|
|
164
|
+
|
|
165
|
+
const logger = createLogger("assets-manager");
|
|
163
166
|
|
|
164
167
|
export interface Props {
|
|
165
168
|
expanded?: boolean;
|
|
@@ -317,7 +320,7 @@ async function onDrop(event: DragEvent) {
|
|
|
317
320
|
try {
|
|
318
321
|
await upload(fileList);
|
|
319
322
|
} catch (error) {
|
|
320
|
-
|
|
323
|
+
logger.error("Failed to upload dropped files:", error);
|
|
321
324
|
throw error;
|
|
322
325
|
}
|
|
323
326
|
|
|
@@ -362,7 +365,7 @@ async function upload(files: FileList) {
|
|
|
362
365
|
try {
|
|
363
366
|
defaultAssets.value = await props.options.assetsUploadHandler(modifiedFileList.files);
|
|
364
367
|
} catch (error) {
|
|
365
|
-
|
|
368
|
+
logger.error("Failed to upload assets:", error);
|
|
366
369
|
throw error;
|
|
367
370
|
}
|
|
368
371
|
}
|
|
@@ -376,7 +379,7 @@ async function inputUpload(event: Event) {
|
|
|
376
379
|
try {
|
|
377
380
|
await upload(fileList);
|
|
378
381
|
} catch (error) {
|
|
379
|
-
|
|
382
|
+
logger.error("Failed to upload files:", error);
|
|
380
383
|
throw error;
|
|
381
384
|
}
|
|
382
385
|
|
|
@@ -183,6 +183,9 @@ import { useI18n } from "vue-i18n";
|
|
|
183
183
|
import { default as ExternalProviders } from "./../../../../../shared/components/sign-in/external-providers.vue";
|
|
184
184
|
import { useExternalProvider } from "./../../../../../shared/components/sign-in/useExternalProvider";
|
|
185
185
|
import { ExtensionSlot, useExtensionSlot } from '../../../../../core/plugins/extension-points';
|
|
186
|
+
import { createLogger } from "../../../../../core/utilities";
|
|
187
|
+
|
|
188
|
+
const logger = createLogger("login-page");
|
|
186
189
|
|
|
187
190
|
type ForgotPasswordFunc = (args: { loginOrEmail: string }) => Promise<void>;
|
|
188
191
|
|
|
@@ -305,7 +308,7 @@ const togglePassRequest = () => {
|
|
|
305
308
|
}
|
|
306
309
|
};
|
|
307
310
|
|
|
308
|
-
|
|
311
|
+
logger.debug("Init login-page");
|
|
309
312
|
</script>
|
|
310
313
|
|
|
311
314
|
<style lang="scss">
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { createLogger } from "../../core/utilities";
|
|
2
|
+
|
|
3
|
+
const logger = createLogger("color-utils");
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* Convert CSS color name to hex code using Canvas API
|
|
3
7
|
* @param colorName - CSS color name (e.g., "red", "blue", "lime")
|
|
@@ -27,22 +31,11 @@ export function convertColorNameToHex(colorName: string): string | null {
|
|
|
27
31
|
|
|
28
32
|
return ctx.fillStyle; // Returns hex format
|
|
29
33
|
} catch (error) {
|
|
30
|
-
|
|
34
|
+
logger.warn("Error converting color name to hex:", error);
|
|
31
35
|
return null;
|
|
32
36
|
}
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
/**
|
|
36
|
-
* Convert hex code to human-readable color name
|
|
37
|
-
* @param hex - Hex color code (e.g., "#ff0000", "ff0000")
|
|
38
|
-
* @returns Always returns null - don't auto-fill color names
|
|
39
|
-
*/
|
|
40
|
-
export function convertHexToColorName(hex: string): string | null {
|
|
41
|
-
// Always return null - don't auto-fill
|
|
42
|
-
// User should enter custom color name manually
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
39
|
/**
|
|
47
40
|
* Check if a string is a valid hex color
|
|
48
41
|
* @param value - String to check
|
|
@@ -73,6 +73,9 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
73
73
|
iconSize: "xxl",
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
+
/** Maximum height in pixels before content is collapsed */
|
|
77
|
+
const COLLAPSED_MAX_HEIGHT = 100;
|
|
78
|
+
|
|
76
79
|
const contentRef = ref<HTMLDivElement>();
|
|
77
80
|
const isExpanded = ref(false);
|
|
78
81
|
const hasOverflow = ref(false);
|
|
@@ -83,7 +86,7 @@ const toggle = () => {
|
|
|
83
86
|
|
|
84
87
|
const checkOverflow = () => {
|
|
85
88
|
if (contentRef.value) {
|
|
86
|
-
hasOverflow.value = contentRef.value.scrollHeight >
|
|
89
|
+
hasOverflow.value = contentRef.value.scrollHeight > COLLAPSED_MAX_HEIGHT;
|
|
87
90
|
}
|
|
88
91
|
};
|
|
89
92
|
|