@vc-shell/framework 1.2.3-beta.0 → 1.2.3
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 +0 -2
- package/core/composables/useAssets/index.ts +28 -72
- package/core/composables/useAsync/index.ts +1 -4
- package/core/composables/useBladeRegistry/index.ts +5 -6
- package/core/composables/useBreadcrumbs/index.ts +1 -4
- package/core/composables/useErrorHandler/index.ts +1 -4
- package/core/composables/useFunctions/debounce.ts +1 -0
- package/core/composables/useFunctions/delay.ts +1 -0
- package/core/composables/useFunctions/index.ts +1 -0
- package/core/composables/useFunctions/once.ts +1 -0
- package/core/composables/useFunctions/sleep.ts +1 -0
- package/core/composables/useFunctions/throttle.ts +1 -0
- package/core/composables/useGlobalSearch/index.ts +3 -3
- package/core/composables/useMenuService/index.ts +12 -7
- package/core/composables/useNotifications/index.ts +2 -5
- package/core/composables/useTheme/index.ts +1 -4
- package/core/composables/useUser/index.ts +20 -189
- package/core/composables/useWidgets/index.ts +2 -5
- package/core/constants/index.ts +0 -2
- package/core/interceptors/index.ts +2 -5
- package/core/plugins/modularity/index.ts +6 -8
- package/core/plugins/modularity/loader.ts +33 -36
- package/core/plugins/signalR/index.ts +3 -6
- package/core/services/app-bar-menu-service.ts +1 -4
- package/core/services/dashboard-service.ts +1 -4
- package/core/services/global-search-service.ts +36 -0
- package/core/services/index.ts +0 -2
- package/core/services/menu-service.ts +41 -5
- package/core/services/settings-menu-service.ts +1 -4
- package/core/services/toolbar-service.ts +3 -18
- package/core/services/widget-service.ts +4 -7
- package/core/types/index.ts +47 -3
- package/core/utilities/index.ts +0 -2
- 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 +2 -2
- 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 +0 -8
- 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/index.d.ts +0 -2
- package/dist/core/constants/index.d.ts.map +1 -1
- package/dist/core/interceptors/index.d.ts.map +1 -1
- 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/global-search-service.d.ts +10 -0
- package/dist/core/services/global-search-service.d.ts.map +1 -0
- package/dist/core/services/menu-service.d.ts +24 -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 +34 -0
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/utilities/index.d.ts +0 -2
- package/dist/core/utilities/index.d.ts.map +1 -1
- package/dist/framework.js +8664 -9720
- package/dist/index.css +1 -1
- package/dist/index.d.ts +0 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/injection-keys.d.ts +6 -21
- 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/useExternalWidgets.d.ts.map +1 -1
- package/dist/shared/composables/useMenuExpanded.d.ts.map +1 -1
- package/dist/shared/composables/useTableSelection.d.ts.map +1 -1
- 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 +6 -0
- package/dist/shared/utilities/colorUtils.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/atoms/vc-badge/vc-badge.vue.d.ts +3 -0
- package/dist/ui/components/atoms/vc-badge/vc-badge.vue.d.ts.map +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 +15 -0
- 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 +5 -0
- 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/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/useBadge.d.ts +18 -0
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/useBadge.d.ts.map +1 -0
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts +4 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.d.ts +4 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.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-SgOIjJF8.js → vendor-lodash-es-BqkGj3Jl.js} +0 -2
- package/package.json +5 -5
- package/shared/components/app-switcher/composables/useAppSwitcher/index.ts +1 -4
- package/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue +4 -67
- package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +10 -13
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.ts +4 -7
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.ts +1 -4
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.ts +1 -4
- package/shared/components/change-password/change-password.vue +1 -1
- package/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.ts +5 -14
- package/shared/components/draggable-dashboard/composables/useLayoutPersistence.ts +2 -5
- package/shared/components/index.ts +0 -2
- package/shared/components/notifications/composables/useContainer/index.ts +6 -8
- package/shared/components/notifications/composables/useInstance/index.ts +1 -4
- package/shared/components/notifications/core/notification.ts +7 -10
- package/shared/components/popup-handler/components/vc-popup-container/vc-popup-container.vue +1 -20
- package/shared/components/sign-in/useExternalProvider.ts +4 -6
- package/shared/composables/useExternalWidgets.ts +4 -7
- package/shared/composables/useMenuExpanded.ts +1 -15
- package/shared/composables/useTableSelection.ts +0 -6
- package/shared/composables/useTableSort.ts +4 -4
- package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +3 -6
- package/shared/pages/LoginPage/components/login/Login.vue +1 -4
- package/shared/utilities/colorUtils.ts +12 -5
- package/ui/components/atoms/vc-badge/vc-badge.vue +59 -0
- package/ui/components/atoms/vc-banner/vc-banner.vue +1 -4
- package/ui/components/atoms/vc-button/vc-button.vue +25 -2
- package/ui/components/atoms/vc-container/vc-container.vue +3 -12
- package/ui/components/atoms/vc-icon/vc-icon.vue +10 -0
- package/ui/components/atoms/vc-icon/vc-lucide-icon.vue +2 -5
- package/ui/components/atoms/vc-image/vc-image.vue +1 -4
- package/ui/components/atoms/vc-link/vc-link.vue +54 -59
- package/ui/components/atoms/vc-loading/vc-loading.vue +0 -4
- package/ui/components/atoms/vc-status/vc-status.vue +5 -0
- package/ui/components/atoms/vc-status-icon/vc-status-icon.vue +4 -4
- package/ui/components/atoms/vc-tooltip/vc-tooltip.vue +1 -8
- package/ui/components/atoms/vc-video/vc-video.vue +2 -4
- package/ui/components/atoms/vc-widget/vc-widget.vue +1 -4
- package/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue +2 -7
- package/ui/components/molecules/vc-input/vc-input.vue +1 -0
- package/ui/components/molecules/vc-pagination/vc-pagination.vue +1 -6
- 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 +1 -11
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/useBadge.ts +80 -0
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue +53 -10
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue +10 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue +3 -0
- package/ui/components/organisms/vc-app/vc-app.vue +3 -22
- 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 +1 -4
- 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 +1 -3
- package/ui/components/organisms/vc-login-form/vc-login-form.vue +1 -3
- package/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +2 -34
- package/ui/components/organisms/vc-table/composables/useTableActions.ts +10 -7
- package/ui/components/organisms/vc-table/composables/useTableColumnResize.ts +1 -4
- package/ui/components/organisms/vc-table/composables/useTableRowReorder.ts +2 -5
- package/ui/components/organisms/vc-table/composables/useTableSelection.ts +18 -26
- package/ui/components/organisms/vc-table/composables/useTableState.ts +1 -4
- package/core/constants/defaults.ts +0 -76
- package/core/constants/ui.ts +0 -68
- package/core/plugins/ai-agent/README.md +0 -336
- package/core/plugins/ai-agent/components/VcAiAgentPanel.vue +0 -125
- package/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue +0 -182
- package/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue +0 -77
- package/core/plugins/ai-agent/components/index.ts +0 -1
- package/core/plugins/ai-agent/composables/index.ts +0 -4
- package/core/plugins/ai-agent/composables/useAiAgent.ts +0 -231
- package/core/plugins/ai-agent/composables/useAiAgentContext.ts +0 -280
- package/core/plugins/ai-agent/constants.ts +0 -89
- package/core/plugins/ai-agent/index.ts +0 -91
- package/core/plugins/ai-agent/services/ai-agent-service.ts +0 -598
- package/core/plugins/ai-agent/types.ts +0 -310
- package/core/types/services.ts +0 -194
- package/core/utilities/errorTypes.ts +0 -126
- package/core/utilities/logger.ts +0 -120
- package/dist/core/constants/defaults.d.ts +0 -63
- package/dist/core/constants/defaults.d.ts.map +0 -1
- package/dist/core/constants/ui.d.ts +0 -50
- package/dist/core/constants/ui.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/components/VcAiAgentPanel.vue.d.ts +0 -3
- package/dist/core/plugins/ai-agent/components/VcAiAgentPanel.vue.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue.d.ts +0 -15
- package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue.d.ts +0 -10
- package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/components/index.d.ts +0 -2
- package/dist/core/plugins/ai-agent/components/index.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/composables/index.d.ts +0 -4
- package/dist/core/plugins/ai-agent/composables/index.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/composables/useAiAgent.d.ts +0 -95
- package/dist/core/plugins/ai-agent/composables/useAiAgent.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/composables/useAiAgentContext.d.ts +0 -55
- package/dist/core/plugins/ai-agent/composables/useAiAgentContext.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/constants.d.ts +0 -47
- package/dist/core/plugins/ai-agent/constants.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/index.d.ts +0 -48
- package/dist/core/plugins/ai-agent/index.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/services/ai-agent-service.d.ts +0 -45
- package/dist/core/plugins/ai-agent/services/ai-agent-service.d.ts.map +0 -1
- package/dist/core/plugins/ai-agent/types.d.ts +0 -258
- package/dist/core/plugins/ai-agent/types.d.ts.map +0 -1
- package/dist/core/types/services.d.ts +0 -169
- package/dist/core/types/services.d.ts.map +0 -1
- package/dist/core/utilities/errorTypes.d.ts +0 -61
- package/dist/core/utilities/errorTypes.d.ts.map +0 -1
- package/dist/core/utilities/logger.d.ts +0 -259
- package/dist/core/utilities/logger.d.ts.map +0 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { computed, unref, isRef, type ComputedRef, type Ref } from "vue";
|
|
2
|
+
import type { MenuItemBadgeConfig, MenuItemBadge } from "./../../../../../../../../../core/types";
|
|
3
|
+
import { getMenuBadges } from "./../../../../../../../../../core/services/menu-service";
|
|
4
|
+
|
|
5
|
+
export interface ResolvedBadge {
|
|
6
|
+
content: string | number | undefined;
|
|
7
|
+
variant: "primary" | "success" | "warning" | "danger" | "info" | "secondary";
|
|
8
|
+
isDot: boolean;
|
|
9
|
+
isVisible: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Composable to resolve badge configuration for menu items.
|
|
14
|
+
* Supports direct badge config, routeId lookup, or groupId lookup.
|
|
15
|
+
*
|
|
16
|
+
* @param badgeConfig - Direct badge configuration (takes priority)
|
|
17
|
+
* @param routeId - Route ID to lookup badge from registry
|
|
18
|
+
* @param groupId - Group ID to lookup badge from registry
|
|
19
|
+
*/
|
|
20
|
+
export function useBadge(
|
|
21
|
+
badgeConfig: MenuItemBadgeConfig | undefined,
|
|
22
|
+
routeId?: string,
|
|
23
|
+
groupId?: string,
|
|
24
|
+
): ComputedRef<ResolvedBadge> {
|
|
25
|
+
const menuBadges = getMenuBadges();
|
|
26
|
+
|
|
27
|
+
return computed(() => {
|
|
28
|
+
// Priority: direct badge config > badge from registry by routeId > badge from registry by groupId
|
|
29
|
+
let config: MenuItemBadgeConfig | undefined = badgeConfig;
|
|
30
|
+
if (!config && routeId) {
|
|
31
|
+
config = menuBadges.value.get(routeId);
|
|
32
|
+
}
|
|
33
|
+
if (!config && groupId) {
|
|
34
|
+
config = menuBadges.value.get(groupId);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!config) {
|
|
38
|
+
return { content: undefined, variant: "primary", isDot: false, isVisible: false };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Normalize shorthand to full config object
|
|
42
|
+
let badge: MenuItemBadge;
|
|
43
|
+
if (typeof config === "object" && !isRef(config) && "content" in config) {
|
|
44
|
+
badge = config as MenuItemBadge;
|
|
45
|
+
} else {
|
|
46
|
+
badge = { content: config as MenuItemBadge["content"] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Resolve reactive content
|
|
50
|
+
let rawContent: string | number | undefined = undefined;
|
|
51
|
+
if (typeof badge.content === "function") {
|
|
52
|
+
rawContent = badge.content();
|
|
53
|
+
} else if (isRef(badge.content)) {
|
|
54
|
+
rawContent = unref(badge.content as Ref<string | number | undefined>);
|
|
55
|
+
} else {
|
|
56
|
+
rawContent = badge.content;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Truncate values > 99
|
|
60
|
+
let displayContent: string | number | undefined = rawContent;
|
|
61
|
+
if (typeof rawContent === "number" && rawContent > 99) {
|
|
62
|
+
displayContent = "99+";
|
|
63
|
+
} else if (typeof rawContent === "string") {
|
|
64
|
+
const numValue = parseInt(rawContent, 10);
|
|
65
|
+
if (!isNaN(numValue) && numValue > 99) {
|
|
66
|
+
displayContent = "99+";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const isDot = badge.isDot ?? false;
|
|
71
|
+
const isVisible = isDot || (displayContent != null && displayContent !== "" && displayContent !== 0);
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
content: displayContent,
|
|
75
|
+
variant: badge.variant ?? "primary",
|
|
76
|
+
isDot,
|
|
77
|
+
isVisible,
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
@@ -45,6 +45,15 @@
|
|
|
45
45
|
<div class="vc-app-menu-link__title-truncate">
|
|
46
46
|
{{ $t(title ?? "") }}
|
|
47
47
|
</div>
|
|
48
|
+
<VcBadge
|
|
49
|
+
v-if="resolvedBadge.isVisible"
|
|
50
|
+
:content="resolvedBadge.isDot ? undefined : resolvedBadge.content"
|
|
51
|
+
:variant="resolvedBadge.variant"
|
|
52
|
+
:is-dot="resolvedBadge.isDot"
|
|
53
|
+
size="s"
|
|
54
|
+
inline
|
|
55
|
+
class="vc-app-menu-link__badge"
|
|
56
|
+
/>
|
|
48
57
|
<div
|
|
49
58
|
v-if="(!!children?.length && expand) || false"
|
|
50
59
|
class="vc-app-menu-link__title-icon"
|
|
@@ -119,15 +128,28 @@
|
|
|
119
128
|
{{ twoLettersTitle(nested.title) }}
|
|
120
129
|
</div>
|
|
121
130
|
<Transition name="opacity">
|
|
122
|
-
<
|
|
131
|
+
<div
|
|
123
132
|
v-show="expand"
|
|
124
|
-
class="vc-app-menu-link__child-item-
|
|
125
|
-
:class="{
|
|
126
|
-
'vc-app-menu-link__child-item-title--no-icon': !nested.icon,
|
|
127
|
-
}"
|
|
133
|
+
class="vc-app-menu-link__child-item-content"
|
|
128
134
|
>
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
<p
|
|
136
|
+
class="vc-app-menu-link__child-item-title"
|
|
137
|
+
:class="{
|
|
138
|
+
'vc-app-menu-link__child-item-title--no-icon': !nested.icon,
|
|
139
|
+
}"
|
|
140
|
+
>
|
|
141
|
+
{{ $t(nested.title) }}
|
|
142
|
+
</p>
|
|
143
|
+
<VcBadge
|
|
144
|
+
v-if="getChildBadge(nested).isVisible"
|
|
145
|
+
:content="getChildBadge(nested).isDot ? undefined : getChildBadge(nested).content"
|
|
146
|
+
:variant="getChildBadge(nested).variant"
|
|
147
|
+
:is-dot="getChildBadge(nested).isDot"
|
|
148
|
+
size="s"
|
|
149
|
+
inline
|
|
150
|
+
class="vc-app-menu-link__badge"
|
|
151
|
+
/>
|
|
152
|
+
</div>
|
|
131
153
|
</Transition>
|
|
132
154
|
</div>
|
|
133
155
|
</div>
|
|
@@ -139,9 +161,10 @@
|
|
|
139
161
|
|
|
140
162
|
<script lang="ts" setup>
|
|
141
163
|
import { ref, watch, computed, onMounted, Component, MaybeRef, unref } from "vue";
|
|
142
|
-
import { MenuItem } from "./../../../../../../../../../core/types";
|
|
143
|
-
import { VcIcon } from "./../../../../../../../";
|
|
164
|
+
import { MenuItem, MenuItemBadgeConfig } from "./../../../../../../../../../core/types";
|
|
165
|
+
import { VcIcon, VcBadge } from "./../../../../../../../";
|
|
144
166
|
import { useRoute } from "vue-router";
|
|
167
|
+
import { useBadge } from "./useBadge";
|
|
145
168
|
|
|
146
169
|
export interface Props {
|
|
147
170
|
children?: MenuItem[];
|
|
@@ -151,6 +174,9 @@ export interface Props {
|
|
|
151
174
|
url?: string;
|
|
152
175
|
expand?: boolean;
|
|
153
176
|
id?: string | number;
|
|
177
|
+
badge?: MenuItemBadgeConfig;
|
|
178
|
+
routeId?: string;
|
|
179
|
+
groupId?: string;
|
|
154
180
|
}
|
|
155
181
|
|
|
156
182
|
export interface Emits {
|
|
@@ -163,6 +189,14 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
163
189
|
|
|
164
190
|
const emit = defineEmits<Emits>();
|
|
165
191
|
|
|
192
|
+
// Badge resolution for parent menu item
|
|
193
|
+
const resolvedBadge = useBadge(props.badge, props.routeId, props.groupId);
|
|
194
|
+
|
|
195
|
+
// Helper to get resolved badge for child items
|
|
196
|
+
const getChildBadge = (child: MenuItem) => {
|
|
197
|
+
return useBadge(child.badge, child.routeId, child.groupId).value;
|
|
198
|
+
};
|
|
199
|
+
|
|
166
200
|
const isOpened = ref(false);
|
|
167
201
|
const route = useRoute();
|
|
168
202
|
const params = Object.fromEntries(Object.entries(route.params).filter(([key]) => key !== "pathMatch"));
|
|
@@ -346,7 +380,7 @@ watch(isOpened, (newValue) => {
|
|
|
346
380
|
|
|
347
381
|
&__child-item {
|
|
348
382
|
@apply tw-cursor-pointer tw-min-w-0 tw-flex tw-h-[var(--app-menu-item-height)]
|
|
349
|
-
tw-items-center tw-transition-[padding] tw-duration-150 tw-w-full tw-py-2 tw-
|
|
383
|
+
tw-items-center tw-transition-[padding] tw-duration-150 tw-w-full tw-py-2 tw-pl-3 tw-pr-2
|
|
350
384
|
tw-text-[color:var(--app-menu-item-title-color)] tw-text-sm
|
|
351
385
|
hover:tw-bg-[var(--app-menu-item-background-color-hover)]
|
|
352
386
|
hover:tw-text-[color:var(--app-menu-item-title-color-active)] tw-gap-5;
|
|
@@ -389,6 +423,15 @@ watch(isOpened, (newValue) => {
|
|
|
389
423
|
&__icon-collapsed {
|
|
390
424
|
@apply tw-p-0 tw-m-0;
|
|
391
425
|
}
|
|
426
|
+
|
|
427
|
+
// Badge styles for menu items - positioned after text
|
|
428
|
+
&__badge {
|
|
429
|
+
@apply tw-shrink-0 tw-ml-auto;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
&__child-item-content {
|
|
433
|
+
@apply tw-flex tw-items-center tw-w-full tw-min-w-0;
|
|
434
|
+
}
|
|
392
435
|
}
|
|
393
436
|
|
|
394
437
|
.opacity-enter-active,
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
:title="title ?? ''"
|
|
14
14
|
:url="url"
|
|
15
15
|
:expand="expand"
|
|
16
|
+
:badge="badge"
|
|
17
|
+
:route-id="routeId"
|
|
18
|
+
:group-id="groupId"
|
|
16
19
|
@on-click="$emit('click')"
|
|
17
20
|
/>
|
|
18
21
|
</router-link>
|
|
@@ -26,6 +29,9 @@
|
|
|
26
29
|
:icon="icon ?? ''"
|
|
27
30
|
:title="title ?? ''"
|
|
28
31
|
:expand="expand"
|
|
32
|
+
:badge="badge"
|
|
33
|
+
:route-id="routeId"
|
|
34
|
+
:group-id="groupId"
|
|
29
35
|
@on-click="$emit('click', $event)"
|
|
30
36
|
/>
|
|
31
37
|
</template>
|
|
@@ -34,7 +40,7 @@
|
|
|
34
40
|
|
|
35
41
|
<script lang="ts" setup>
|
|
36
42
|
import VcAppMenuLink from "./_internal/vc-app-menu-link.vue";
|
|
37
|
-
import { MenuItem } from "../../../../../../../../core/types";
|
|
43
|
+
import { MenuItem, MenuItemBadgeConfig } from "../../../../../../../../core/types";
|
|
38
44
|
import type { Component } from "vue";
|
|
39
45
|
export interface Props {
|
|
40
46
|
sticky?: boolean;
|
|
@@ -45,6 +51,9 @@ export interface Props {
|
|
|
45
51
|
children?: MenuItem[];
|
|
46
52
|
expand?: boolean;
|
|
47
53
|
id?: string | number;
|
|
54
|
+
badge?: MenuItemBadgeConfig;
|
|
55
|
+
routeId?: string;
|
|
56
|
+
groupId?: string;
|
|
48
57
|
}
|
|
49
58
|
|
|
50
59
|
export interface Emits {
|
|
@@ -36,6 +36,9 @@
|
|
|
36
36
|
:title="item.title as string"
|
|
37
37
|
:children="item.children"
|
|
38
38
|
:expand="$isDesktop.value ? isExpanded || isHoverExpanded : true"
|
|
39
|
+
:badge="item.badge"
|
|
40
|
+
:route-id="item.routeId"
|
|
41
|
+
:group-id="item.groupId"
|
|
39
42
|
@click="handleMenuItemClick(item, $event)"
|
|
40
43
|
/>
|
|
41
44
|
</div>
|
|
@@ -30,8 +30,6 @@
|
|
|
30
30
|
class="vc-app__workspace"
|
|
31
31
|
>
|
|
32
32
|
<VcBladeNavigation />
|
|
33
|
-
<!-- AI Agent Panel (shown when plugin is installed) -->
|
|
34
|
-
<VcAiAgentPanel v-if="aiAgentConfig?.url" />
|
|
35
33
|
</div>
|
|
36
34
|
|
|
37
35
|
<!-- Popup container -->
|
|
@@ -51,8 +49,6 @@ import {
|
|
|
51
49
|
BladeRoutesRecord,
|
|
52
50
|
} from "./../../../../shared/components";
|
|
53
51
|
import { useAppSwitcher } from "../../../../shared/components/app-switcher/composables/useAppSwitcher";
|
|
54
|
-
import { VcAiAgentPanel, provideAiAgentService } from "../../../../core/plugins/ai-agent";
|
|
55
|
-
import type { IAiAgentConfig } from "../../../../core/plugins/ai-agent";
|
|
56
52
|
import { provideAppBarWidget, useNotifications } from "../../../../core/composables";
|
|
57
53
|
import { useRoute, useRouter } from "vue-router";
|
|
58
54
|
import { watchOnce } from "@vueuse/core";
|
|
@@ -68,7 +64,6 @@ import { DynamicModulesKey, EMBEDDED_MODE } from "../../../../injection-keys";
|
|
|
68
64
|
import { provideMenuService } from "../../../../core/composables/useMenuService";
|
|
69
65
|
import { provideAppBarMobileButtonsService } from "../../../../core/composables/useAppBarMobileButtons";
|
|
70
66
|
import { useUserManagement } from "../../../../core/composables/useUserManagement";
|
|
71
|
-
import { createLogger } from "../../../../core/utilities";
|
|
72
67
|
|
|
73
68
|
export interface Props {
|
|
74
69
|
isReady: boolean;
|
|
@@ -97,13 +92,10 @@ defineSlots<{
|
|
|
97
92
|
const props = defineProps<Props>();
|
|
98
93
|
const slots = useSlots();
|
|
99
94
|
|
|
100
|
-
|
|
101
|
-
logger.debug("Init vc-app");
|
|
95
|
+
console.debug("vc-app: Init vc-app");
|
|
102
96
|
|
|
103
97
|
const internalRoutes = inject("bladeRoutes") as BladeRoutesRecord[];
|
|
104
98
|
const dynamicModules = inject(DynamicModulesKey, undefined);
|
|
105
|
-
const aiAgentConfig = inject<IAiAgentConfig | undefined>("aiAgentConfig", undefined);
|
|
106
|
-
const aiAgentAddGlobalToolbarButton = inject<boolean>("aiAgentAddGlobalToolbarButton", true);
|
|
107
99
|
|
|
108
100
|
const isAppReady = ref(props.isReady);
|
|
109
101
|
|
|
@@ -171,7 +163,7 @@ registerMobileButton({
|
|
|
171
163
|
});
|
|
172
164
|
|
|
173
165
|
const onMenuItemClick = function (item: MenuItem) {
|
|
174
|
-
|
|
166
|
+
console.debug(`vc-app#onMenuItemClick() called.`);
|
|
175
167
|
|
|
176
168
|
if (item.routeId) {
|
|
177
169
|
const bladeComponent = resolveBladeByName(item.routeId);
|
|
@@ -183,7 +175,7 @@ const onMenuItemClick = function (item: MenuItem) {
|
|
|
183
175
|
true,
|
|
184
176
|
);
|
|
185
177
|
} else {
|
|
186
|
-
|
|
178
|
+
console.error(`Blade component with routeId '${item.routeId}' not found.`);
|
|
187
179
|
}
|
|
188
180
|
} else if (!item.routeId && item.url) {
|
|
189
181
|
const menuRoute = routes.find((r) => {
|
|
@@ -226,14 +218,6 @@ provideDashboardService();
|
|
|
226
218
|
provideMenuService();
|
|
227
219
|
provideGlobalSearch();
|
|
228
220
|
provide(EMBEDDED_MODE, isEmbedded);
|
|
229
|
-
|
|
230
|
-
// Provide AI Agent service if config is available (via plugin)
|
|
231
|
-
if (aiAgentConfig?.url) {
|
|
232
|
-
provideAiAgentService({
|
|
233
|
-
config: aiAgentConfig,
|
|
234
|
-
addGlobalToolbarButton: aiAgentAddGlobalToolbarButton,
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
221
|
// Provide slots to child components with all necessary props and handlers
|
|
238
222
|
provideAppSlots(
|
|
239
223
|
slots,
|
|
@@ -261,9 +245,6 @@ onUnmounted(() => {
|
|
|
261
245
|
<style lang="scss">
|
|
262
246
|
:root {
|
|
263
247
|
--app-background: var(--secondary-200);
|
|
264
|
-
// Shared transition timing for synchronized animations
|
|
265
|
-
--app-panel-transition-duration: 0.3s;
|
|
266
|
-
--app-panel-transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
267
248
|
}
|
|
268
249
|
|
|
269
250
|
.vc-app {
|
|
@@ -43,9 +43,6 @@
|
|
|
43
43
|
<script lang="ts" setup>
|
|
44
44
|
import { ref } from "vue";
|
|
45
45
|
import { VcIcon, VcTooltip } from "../../../../../../../../";
|
|
46
|
-
import { createLogger } from "../../../../../../../../../../core/utilities";
|
|
47
|
-
|
|
48
|
-
const logger = createLogger("vc-blade-toolbar-button");
|
|
49
46
|
|
|
50
47
|
export interface Props {
|
|
51
48
|
isExpanded: boolean;
|
|
@@ -84,7 +81,7 @@ const emit = defineEmits<Emits>();
|
|
|
84
81
|
const isWaiting = ref(false);
|
|
85
82
|
|
|
86
83
|
async function onClick(): Promise<void> {
|
|
87
|
-
|
|
84
|
+
console.debug("vc-blade-toolbar-item#onClick()");
|
|
88
85
|
|
|
89
86
|
if (!props.disabled && !isWaiting.value) {
|
|
90
87
|
if (props.clickHandler && typeof props.clickHandler === "function") {
|
|
@@ -25,10 +25,10 @@ import { useLocalStorage } from "@vueuse/core";
|
|
|
25
25
|
import { usePermissions, useToolbar } from "../../../../../../core/composables";
|
|
26
26
|
import { IBladeToolbar } from "../../../../../../core/types";
|
|
27
27
|
import VcBladeToolbarButtons from "./_internal/vc-blade-toolbar-buttons/vc-blade-toolbar-buttons.vue";
|
|
28
|
+
import { BladeInstance } from "../../../../../../injection-keys";
|
|
28
29
|
import { FALLBACK_BLADE_ID } from "../../../../../../core/constants";
|
|
29
30
|
import { IBladeInstance } from "../../../../../../shared/components/blade-navigation/types";
|
|
30
31
|
import { IToolbarItem } from "../../../../../../core/services";
|
|
31
|
-
import { useBlade } from "../../../../../../core/composables";
|
|
32
32
|
|
|
33
33
|
export interface Props {
|
|
34
34
|
items: IBladeToolbar[];
|
|
@@ -41,17 +41,21 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
41
41
|
const slots = useSlots();
|
|
42
42
|
const isExpanded = useLocalStorage("VC_BLADE_TOOLBAR_IS_EXPANDED", true);
|
|
43
43
|
const { hasAccess } = usePermissions();
|
|
44
|
-
const {
|
|
45
|
-
|
|
46
|
-
unregisterToolbarItem,
|
|
47
|
-
getToolbarItems,
|
|
48
|
-
clearBladeToolbarItems,
|
|
49
|
-
updateToolbarItem,
|
|
50
|
-
registeredToolbarItems,
|
|
51
|
-
} = useToolbar();
|
|
44
|
+
const { registerToolbarItem, unregisterToolbarItem, getToolbarItems, clearBladeToolbarItems, updateToolbarItem } =
|
|
45
|
+
useToolbar();
|
|
52
46
|
|
|
53
47
|
// Get the ID of the current blade
|
|
54
|
-
const blade =
|
|
48
|
+
const blade = inject<ComputedRef<IBladeInstance>>(
|
|
49
|
+
BladeInstance,
|
|
50
|
+
computed(() => ({
|
|
51
|
+
id: FALLBACK_BLADE_ID,
|
|
52
|
+
expandable: false,
|
|
53
|
+
maximized: false,
|
|
54
|
+
error: undefined,
|
|
55
|
+
navigation: undefined,
|
|
56
|
+
breadcrumbs: undefined,
|
|
57
|
+
})),
|
|
58
|
+
);
|
|
55
59
|
|
|
56
60
|
const bladeId = computed(() => (blade.value?.id ?? FALLBACK_BLADE_ID).toLowerCase());
|
|
57
61
|
|
|
@@ -122,10 +126,6 @@ function clearToolbarItems(): void {
|
|
|
122
126
|
|
|
123
127
|
// Filter visible items from service
|
|
124
128
|
const visibleItems = computed(() => {
|
|
125
|
-
// Access registeredToolbarItems.length to create reactive dependency
|
|
126
|
-
// This ensures computed recalculates when new items are registered
|
|
127
|
-
void registeredToolbarItems.length;
|
|
128
|
-
|
|
129
129
|
return getToolbarItems()
|
|
130
130
|
.filter(
|
|
131
131
|
(item) =>
|
|
@@ -288,10 +288,8 @@ const openErrorDetails = () => {
|
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
.vc-blade {
|
|
291
|
-
@apply tw-relative tw-flex tw-shrink-0 tw-flex-col tw-overflow-hidden;
|
|
291
|
+
@apply tw-relative tw-flex tw-shrink-0 tw-flex-col tw-overflow-hidden tw-transition-[width] tw-duration-200;
|
|
292
292
|
@apply tw-bg-[color:var(--blade-background-color)] tw-border tw-border-solid tw-border-[--blade-border-color];
|
|
293
|
-
// Use shared transition timing for synchronized animations with AI panel
|
|
294
|
-
transition: width var(--app-panel-transition-duration, 0.3s) var(--app-panel-transition-timing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
295
293
|
|
|
296
294
|
&__back-button {
|
|
297
295
|
@apply tw-mr-[14px];
|
|
@@ -24,7 +24,6 @@
|
|
|
24
24
|
<script lang="ts" setup>
|
|
25
25
|
import { computed } from "vue";
|
|
26
26
|
import { useRouter } from "vue-router";
|
|
27
|
-
import { createLogger } from "../../../../core/utilities";
|
|
28
27
|
|
|
29
28
|
export interface Props {
|
|
30
29
|
logo?: string;
|
|
@@ -58,8 +57,7 @@ const logoImageHandler = computed(() => {
|
|
|
58
57
|
|
|
59
58
|
const version = router.currentRoute.value.meta?.appVersion;
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
logger.debug("Init vc-login-form");
|
|
60
|
+
console.debug("Init vc-login-form");
|
|
63
61
|
</script>
|
|
64
62
|
|
|
65
63
|
<style lang="scss">
|
|
@@ -290,38 +290,6 @@ import { Field } from "vee-validate";
|
|
|
290
290
|
import type { TableItem } from "../../types";
|
|
291
291
|
import { ITableColumns } from "../../../../../../core/types";
|
|
292
292
|
|
|
293
|
-
// Cache for sanitized HTML to avoid repeated DOMPurify calls across table cells
|
|
294
|
-
const sanitizedHtmlCache = new Map<string, string>();
|
|
295
|
-
const MAX_CACHE_SIZE = 500;
|
|
296
|
-
|
|
297
|
-
function getSanitizedHtml(html: string): string {
|
|
298
|
-
if (sanitizedHtmlCache.has(html)) {
|
|
299
|
-
return sanitizedHtmlCache.get(html)!;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const sanitized = DOMPurify.default.sanitize(html, {
|
|
303
|
-
ALLOWED_TAGS: [
|
|
304
|
-
"p", "br", "strong", "em", "u", "s", "h1", "h2", "h3", "h4", "h5", "h6",
|
|
305
|
-
"ul", "ol", "li", "blockquote", "pre", "code", "a", "img", "table",
|
|
306
|
-
"thead", "tbody", "tr", "th", "td", "hr", "div", "span",
|
|
307
|
-
],
|
|
308
|
-
ALLOWED_ATTR: ["href", "src", "alt", "title", "class", "id", "colspan", "rowspan", "align", "valign"],
|
|
309
|
-
FORBID_TAGS: ["script", "object", "embed", "form", "input"],
|
|
310
|
-
FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover", "onfocus", "onblur", "style"],
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
// Limit cache size to prevent memory leaks
|
|
314
|
-
if (sanitizedHtmlCache.size >= MAX_CACHE_SIZE) {
|
|
315
|
-
const firstKey = sanitizedHtmlCache.keys().next().value;
|
|
316
|
-
if (firstKey !== undefined) {
|
|
317
|
-
sanitizedHtmlCache.delete(firstKey);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
sanitizedHtmlCache.set(html, sanitized);
|
|
322
|
-
return sanitized;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
293
|
export interface Props {
|
|
326
294
|
cell: ITableColumns;
|
|
327
295
|
item: string | TableItem;
|
|
@@ -345,8 +313,8 @@ const value = computed((): any => _.get(props.item, props.cell.field || props.ce
|
|
|
345
313
|
const isEditable = computed(() => props.cell.editable && props.editing);
|
|
346
314
|
|
|
347
315
|
const sanitizedHtml = computed(() => {
|
|
348
|
-
if (props.cell.type === "html"
|
|
349
|
-
return
|
|
316
|
+
if (props.cell.type === "html") {
|
|
317
|
+
return DOMPurify.default.sanitize(value.value as string, { USE_PROFILES: { html: true } });
|
|
350
318
|
}
|
|
351
319
|
return "";
|
|
352
320
|
});
|
|
@@ -20,13 +20,16 @@ export function useTableActions<T extends TableItem | string>(options: UseTableA
|
|
|
20
20
|
const builder = unref(itemActionBuilder);
|
|
21
21
|
|
|
22
22
|
if (unref(enableItemActions) && typeof builder === "function") {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
const populatedItems: IActionBuilderResult<T>[][] = [];
|
|
24
|
+
for (let index = 0; index < items.length; index++) {
|
|
25
|
+
if (typeof items[index] === "object") {
|
|
26
|
+
const elementWithActions = await builder(items[index]);
|
|
27
|
+
if (elementWithActions) {
|
|
28
|
+
populatedItems.push(elementWithActions);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
itemActions.value = populatedItems;
|
|
30
33
|
} else {
|
|
31
34
|
itemActions.value = [];
|
|
32
35
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { ref, Ref } from "vue";
|
|
2
2
|
import { TableColPartial } from "../types";
|
|
3
|
-
import { createLogger } from "../../../../../core/utilities";
|
|
4
|
-
|
|
5
|
-
const logger = createLogger("vc-table-column-resize");
|
|
6
3
|
|
|
7
4
|
export function useTableColumnResize(
|
|
8
5
|
internalColumns: Ref<TableColPartial[]>,
|
|
@@ -38,7 +35,7 @@ export function useTableColumnResize(
|
|
|
38
35
|
e.stopImmediatePropagation();
|
|
39
36
|
|
|
40
37
|
if (!item.id) {
|
|
41
|
-
|
|
38
|
+
console.warn("Column has no id, cannot resize:", item);
|
|
42
39
|
return;
|
|
43
40
|
}
|
|
44
41
|
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { computed, ref, Ref } from "vue";
|
|
2
2
|
import { TableItem } from "../types";
|
|
3
|
-
import { createLogger } from "../../../../../core/utilities";
|
|
4
|
-
|
|
5
|
-
const logger = createLogger("vc-table-row-reorder");
|
|
6
3
|
|
|
7
4
|
export function useTableRowReorder<T extends TableItem | string>(
|
|
8
5
|
items: Ref<T[]>,
|
|
@@ -30,7 +27,7 @@ export function useTableRowReorder<T extends TableItem | string>(
|
|
|
30
27
|
function onRowMouseDown(event: MouseEvent) {
|
|
31
28
|
if (event.currentTarget instanceof HTMLElement) {
|
|
32
29
|
const row = event.currentTarget;
|
|
33
|
-
|
|
30
|
+
console.log("row", row);
|
|
34
31
|
const rowRect = row.getBoundingClientRect();
|
|
35
32
|
|
|
36
33
|
dragOffset.value = {
|
|
@@ -57,7 +54,7 @@ export function useTableRowReorder<T extends TableItem | string>(
|
|
|
57
54
|
}
|
|
58
55
|
|
|
59
56
|
function onRowDragStart(event: DragEvent, item: T) {
|
|
60
|
-
|
|
57
|
+
console.log("onRowDragStart", event, item);
|
|
61
58
|
rowDragged.value = true;
|
|
62
59
|
const index = internalItems.value.indexOf(item);
|
|
63
60
|
draggedRow.value = index;
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
import { computed, ref, Ref, watch } from "vue";
|
|
2
2
|
import { TableItem } from "../types";
|
|
3
|
+
import * as _ from "lodash-es";
|
|
3
4
|
|
|
4
5
|
type TableItemType = TableItem | string;
|
|
5
6
|
|
|
6
|
-
/**
|
|
7
|
-
* Gets a unique identifier for a table item
|
|
8
|
-
*/
|
|
9
|
-
function getItemId(item: TableItemType): string {
|
|
10
|
-
if (typeof item === "string") return item;
|
|
11
|
-
return (item as TableItem).id ?? JSON.stringify(item);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
7
|
export interface UseTableSelectionOptions<T extends TableItemType> {
|
|
15
8
|
items: Ref<T[]>;
|
|
16
9
|
disableItemCheckbox?: (item: T) => boolean;
|
|
@@ -44,11 +37,8 @@ export function useTableSelection<T extends TableItemType>(options: UseTableSele
|
|
|
44
37
|
return selection.value.length === items.value.length && (options.totalCount || 0) > items.value.length;
|
|
45
38
|
});
|
|
46
39
|
|
|
47
|
-
// Use Set for O(1) selection lookups instead of O(n) array search with deep equality
|
|
48
|
-
const selectionIds = computed(() => new Set(selection.value.map(getItemId)));
|
|
49
|
-
|
|
50
40
|
function isSelected(item: T): boolean {
|
|
51
|
-
return
|
|
41
|
+
return selection.value.some((x) => _.isEqual(x, item));
|
|
52
42
|
}
|
|
53
43
|
|
|
54
44
|
function handleSelectAll(): void {
|
|
@@ -62,15 +52,14 @@ export function useTableSelection<T extends TableItemType>(options: UseTableSele
|
|
|
62
52
|
}
|
|
63
53
|
|
|
64
54
|
function rowCheckbox(item: T): void {
|
|
65
|
-
|
|
66
|
-
const disabledIds = new Set(disabledSelection.value.map(getItemId));
|
|
67
|
-
|
|
68
|
-
if (disabledIds.has(itemId)) {
|
|
55
|
+
if (disabledSelection.value.includes(item)) {
|
|
69
56
|
return;
|
|
70
57
|
}
|
|
71
58
|
|
|
72
|
-
|
|
73
|
-
|
|
59
|
+
const index = selection.value.findIndex((x) => _.isEqual(x, item));
|
|
60
|
+
|
|
61
|
+
if (index !== -1) {
|
|
62
|
+
selection.value = selection.value.filter((_, i) => i !== index);
|
|
74
63
|
} else {
|
|
75
64
|
selection.value = [...selection.value, item];
|
|
76
65
|
}
|
|
@@ -78,11 +67,16 @@ export function useTableSelection<T extends TableItemType>(options: UseTableSele
|
|
|
78
67
|
|
|
79
68
|
async function handleMultiselect(items: T[]): Promise<void> {
|
|
80
69
|
if (disableItemCheckbox && typeof disableItemCheckbox === "function") {
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
70
|
+
const disabledMultiselect: T[] = [];
|
|
71
|
+
for (const item of items) {
|
|
72
|
+
if (typeof item === "object") {
|
|
73
|
+
const element = await disableItemCheckbox(item);
|
|
74
|
+
if (element) {
|
|
75
|
+
disabledMultiselect.push(item);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
disabledSelection.value = disabledMultiselect;
|
|
86
80
|
}
|
|
87
81
|
}
|
|
88
82
|
|
|
@@ -90,9 +84,7 @@ export function useTableSelection<T extends TableItemType>(options: UseTableSele
|
|
|
90
84
|
() => items.value,
|
|
91
85
|
(newItems) => {
|
|
92
86
|
handleMultiselect(newItems);
|
|
93
|
-
|
|
94
|
-
const newItemIds = new Set(newItems.map(getItemId));
|
|
95
|
-
selection.value = selection.value.filter((item) => newItemIds.has(getItemId(item)));
|
|
87
|
+
selection.value = selection.value.filter((item) => newItems.includes(item));
|
|
96
88
|
},
|
|
97
89
|
{ deep: true, immediate: true },
|
|
98
90
|
);
|
|
@@ -4,9 +4,6 @@ import { useLocalStorage } from "@vueuse/core";
|
|
|
4
4
|
import { cloneDeep, pick, unionBy } from "lodash-es";
|
|
5
5
|
import { TableColPartial } from "../types";
|
|
6
6
|
import { ITableColumns } from "../../../../../core/types";
|
|
7
|
-
import { createLogger } from "../../../../../core/utilities";
|
|
8
|
-
|
|
9
|
-
const logger = createLogger("vc-table-state");
|
|
10
7
|
|
|
11
8
|
export interface UseTableStateOptions {
|
|
12
9
|
stateKey: Ref<string, string>;
|
|
@@ -50,7 +47,7 @@ export function useTableState(options: UseTableStateOptions) {
|
|
|
50
47
|
});
|
|
51
48
|
|
|
52
49
|
function saveState() {
|
|
53
|
-
|
|
50
|
+
console.debug("[@vc-shell/framework#vc-table.vue] - Save state");
|
|
54
51
|
const colsClone = cloneDeep(internalColumns.value);
|
|
55
52
|
state.value = colsClone.map((col) => pick(col, "id", "visible", "width", "predefined", "title"));
|
|
56
53
|
}
|