@vc-shell/vc-app-skill 2.0.0-alpha.33 → 2.0.0-alpha.34
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 +78 -54
- package/README.md +42 -12
- package/package.json +4 -4
- package/runtime/VERSION +1 -1
- package/runtime/agents/api-analyzer.md +31 -16
- package/runtime/agents/blade-enhancer.md +15 -9
- package/runtime/agents/details-blade-generator.md +47 -31
- package/runtime/agents/list-blade-generator.md +21 -37
- package/runtime/agents/locales-generator.md +3 -0
- package/runtime/agents/migration-agent.md +18 -7
- package/runtime/agents/module-analyzer.md +2 -0
- package/runtime/agents/module-assembler.md +15 -0
- package/runtime/agents/promote-agent.md +15 -4
- package/runtime/agents/type-checker.md +11 -0
- package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
- package/runtime/knowledge/docs/core/api/platform.docs.md +30 -30
- package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +41 -41
- package/runtime/knowledge/docs/core/composables/bladeContext/index.docs.md +12 -10
- package/runtime/knowledge/docs/core/composables/useApiClient/useApiClient.docs.md +11 -14
- package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +35 -35
- package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +35 -35
- package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +15 -15
- package/runtime/knowledge/docs/core/composables/useAssets/useAssets.docs.md +21 -18
- package/runtime/knowledge/docs/core/composables/useAssetsManager/useAssetsManager.docs.md +28 -24
- package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +90 -61
- package/runtime/knowledge/docs/core/composables/useBeforeUnload/useBeforeUnload.docs.md +19 -18
- package/runtime/knowledge/docs/core/composables/useBlade/useBlade.docs.md +89 -68
- package/runtime/knowledge/docs/core/composables/useBladeForm/useBladeForm.docs.md +27 -25
- package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +15 -15
- package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +43 -47
- package/runtime/knowledge/docs/core/composables/useBreadcrumbs/useBreadcrumbs.docs.md +11 -11
- package/runtime/knowledge/docs/core/composables/useConnectionStatus/useConnectionStatus.docs.md +27 -15
- package/runtime/knowledge/docs/core/composables/useDashboard/useDashboard.docs.md +30 -30
- package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +34 -36
- package/runtime/knowledge/docs/core/composables/useErrorHandler/useErrorHandler.docs.md +44 -23
- package/runtime/knowledge/docs/core/composables/useFunctions/useFunctions.docs.md +14 -11
- package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +47 -38
- package/runtime/knowledge/docs/core/composables/useLanguages/useLanguages.docs.md +37 -28
- package/runtime/knowledge/docs/core/composables/useLoading/useLoading.docs.md +23 -17
- package/runtime/knowledge/docs/core/composables/useMenuExpanded/index.docs.md +9 -9
- package/runtime/knowledge/docs/core/composables/useMenuService/useMenuService.docs.md +42 -42
- package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +22 -12
- package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +33 -41
- package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +16 -16
- package/runtime/knowledge/docs/core/composables/usePlatformLocaleSync/usePlatformLocaleSync.docs.md +28 -0
- package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +32 -24
- package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +32 -11
- package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +22 -13
- package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +7 -7
- package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +32 -24
- package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +21 -17
- package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +24 -24
- package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +28 -31
- package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +43 -24
- package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +68 -48
- package/runtime/knowledge/docs/core/composables/useWebVitals/useWebVitals.docs.md +19 -19
- package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +42 -47
- package/runtime/knowledge/docs/core/directives/autofocus/autofocus.docs.md +10 -4
- package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +35 -20
- package/runtime/knowledge/docs/core/notifications/notifications.docs.md +36 -35
- package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +38 -38
- package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +79 -62
- package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +10 -10
- package/runtime/knowledge/docs/core/plugins/i18n/i18n.docs.md +21 -23
- package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +91 -83
- package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +10 -16
- package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +9 -9
- package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +65 -22
- package/runtime/knowledge/docs/core/services/services.docs.md +19 -22
- package/runtime/knowledge/docs/core/types/types.docs.md +40 -40
- package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +27 -27
- package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +23 -23
- package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +22 -25
- package/runtime/knowledge/docs/core/utilities/utilities.docs.md +64 -64
- package/runtime/knowledge/docs/injection-keys.docs.md +52 -51
- package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +9 -9
- package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +23 -43
- package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +5 -5
- package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +5 -5
- package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +8 -7
- package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +7 -7
- package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +8 -7
- package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +29 -13
- package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +13 -16
- package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +1 -7
- package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +5 -5
- package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -9
- package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +11 -17
- package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +34 -65
- package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +16 -26
- package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +2 -2
- package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +7 -9
- package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +30 -40
- package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +26 -19
- package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +15 -12
- package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +15 -26
- package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +21 -19
- package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +83 -67
- package/runtime/knowledge/docs/ui/components/atoms/vc-card/vc-card.docs.md +100 -59
- package/runtime/knowledge/docs/ui/components/atoms/vc-col/vc-col.docs.md +28 -11
- package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +20 -17
- package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +26 -17
- package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +30 -32
- package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +25 -48
- package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +29 -24
- package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +23 -15
- package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +22 -13
- package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +33 -18
- package/runtime/knowledge/docs/ui/components/atoms/vc-row/vc-row.docs.md +56 -15
- package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +28 -15
- package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +40 -20
- package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +25 -14
- package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +40 -14
- package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +54 -42
- package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +17 -17
- package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +21 -21
- package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +23 -10
- package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +55 -44
- package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +23 -20
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +92 -65
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +22 -36
- package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +65 -23
- package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +52 -73
- package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +91 -85
- package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md +38 -42
- package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +56 -73
- package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +61 -27
- package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +42 -50
- package/runtime/knowledge/docs/ui/components/molecules/vc-form/vc-form.docs.md +35 -64
- package/runtime/knowledge/docs/ui/components/molecules/vc-image-tile/vc-image-tile.docs.md +38 -41
- package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +109 -131
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +47 -88
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +50 -64
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +29 -24
- package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +32 -28
- package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +57 -65
- package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +28 -26
- package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +55 -20
- package/runtime/knowledge/docs/ui/components/molecules/vc-radio-group/vc-radio-group.docs.md +21 -35
- package/runtime/knowledge/docs/ui/components/molecules/vc-rating/vc-rating.docs.md +38 -33
- package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +72 -83
- package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +21 -16
- package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +55 -64
- package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +51 -70
- package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +58 -57
- package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +49 -26
- package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +82 -28
- package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +90 -75
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +99 -48
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +548 -367
- package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +35 -52
- package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +33 -62
- package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +17 -23
- package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +109 -68
- package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +82 -44
- package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +8 -8
- package/runtime/knowledge/docs/ui/composables/useDataTablePagination.docs.md +164 -0
- package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +34 -26
- package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +48 -40
- package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +30 -17
- package/runtime/knowledge/docs/ui/types/ui-types.docs.md +40 -29
- package/runtime/knowledge/examples/offers-module.md +15 -13
- package/runtime/knowledge/examples/team-module.md +82 -119
- package/runtime/knowledge/examples/videos-module.md +44 -17
- package/runtime/knowledge/index.md +22 -0
- package/runtime/knowledge/migration-prompts/blade-form-migration.md +17 -8
- package/runtime/knowledge/migration-prompts/blade-props-migration.md +1 -2
- package/runtime/knowledge/migration-prompts/datatable-migration.md +801 -0
- package/runtime/knowledge/migration-prompts/icon-migration.md +97 -0
- package/runtime/knowledge/migration-prompts/manual-migration-audit.md +117 -0
- package/runtime/knowledge/migration-prompts/notifications-migration.md +8 -3
- package/runtime/knowledge/migration-prompts/nswag-migration.md +25 -29
- package/runtime/knowledge/migration-prompts/use-assets-migration.md +164 -0
- package/runtime/knowledge/migration-prompts/use-data-table-pagination-migration.md +176 -0
- package/runtime/knowledge/migration-prompts/widgets-migration.md +48 -27
- package/runtime/knowledge/patterns/assets-management.md +20 -20
- package/runtime/knowledge/patterns/blade-navigation.md +7 -14
- package/runtime/knowledge/patterns/blade-widget.md +19 -17
- package/runtime/knowledge/patterns/child-blade-flow.md +19 -7
- package/runtime/knowledge/patterns/composable-details.md +20 -50
- package/runtime/knowledge/patterns/composable-list.md +43 -31
- package/runtime/knowledge/patterns/dashboard-widget.md +14 -16
- package/runtime/knowledge/patterns/datatable-pattern.md +521 -0
- package/runtime/knowledge/patterns/details-blade-pattern.md +78 -116
- package/runtime/knowledge/patterns/extension-points-usage.md +53 -44
- package/runtime/knowledge/patterns/form-validation.md +28 -64
- package/runtime/knowledge/patterns/list-blade-pattern.md +33 -21
- package/runtime/knowledge/patterns/module-structure.md +7 -1
- package/runtime/knowledge/patterns/multilanguage-fields.md +8 -14
- package/runtime/knowledge/patterns/notification-template.md +21 -14
- package/runtime/knowledge/patterns/signalr-notifications.md +30 -32
- package/runtime/knowledge/patterns/toolbar-pattern.md +18 -20
- package/runtime/vc-app.md +241 -62
|
@@ -18,7 +18,7 @@ For each blade that calls `registerWidget()`, create a `widgets/useXxxWidgets.ts
|
|
|
18
18
|
import { useWidgets, useBlade } from "@vc-shell/framework";
|
|
19
19
|
import type { BladeInstance } from "@vc-shell/framework";
|
|
20
20
|
import { onMounted, onUnmounted } from "vue";
|
|
21
|
-
import
|
|
21
|
+
import ChildListWidget from "../widgets/ChildListWidget.vue";
|
|
22
22
|
|
|
23
23
|
const { registerWidget, clearBladeWidgets } = useWidgets();
|
|
24
24
|
const { openBlade } = useBlade();
|
|
@@ -26,11 +26,11 @@ const { openBlade } = useBlade();
|
|
|
26
26
|
onMounted(() => {
|
|
27
27
|
registerWidget(
|
|
28
28
|
{
|
|
29
|
-
id: "
|
|
30
|
-
component:
|
|
29
|
+
id: "ChildListWidget",
|
|
30
|
+
component: ChildListWidget,
|
|
31
31
|
props: {
|
|
32
|
-
count:
|
|
33
|
-
onClick: () => openBlade({ name: "
|
|
32
|
+
count: childCount,
|
|
33
|
+
onClick: () => openBlade({ name: "ChildEntityList", options: { entityId: entity.value.id } }),
|
|
34
34
|
},
|
|
35
35
|
},
|
|
36
36
|
bladeContext.id,
|
|
@@ -45,35 +45,35 @@ onUnmounted(() => {
|
|
|
45
45
|
**AFTER:**
|
|
46
46
|
|
|
47
47
|
```typescript
|
|
48
|
-
// widgets/
|
|
48
|
+
// widgets/useEntityWidgets.ts
|
|
49
49
|
import { useBladeWidgets, useBlade } from "@vc-shell/framework";
|
|
50
50
|
import type { UseBladeWidgetsReturn } from "@vc-shell/framework";
|
|
51
51
|
import { computed, type Ref } from "vue";
|
|
52
52
|
|
|
53
|
-
interface
|
|
54
|
-
item: Ref<
|
|
53
|
+
interface UseEntityWidgetsOptions {
|
|
54
|
+
item: Ref<Entity | undefined>;
|
|
55
55
|
isVisible: Ref<boolean> | boolean;
|
|
56
|
-
|
|
56
|
+
childCount: Ref<number>;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
export function
|
|
60
|
-
const { item, isVisible,
|
|
59
|
+
export function useEntityWidgets(options: UseEntityWidgetsOptions): UseBladeWidgetsReturn {
|
|
60
|
+
const { item, isVisible, childCount } = options;
|
|
61
61
|
const { openBlade } = useBlade();
|
|
62
62
|
|
|
63
63
|
return useBladeWidgets([
|
|
64
64
|
{
|
|
65
|
-
id: "
|
|
65
|
+
id: "ChildListWidget",
|
|
66
66
|
icon: "lucide-tag",
|
|
67
|
-
title: "
|
|
68
|
-
badge: computed(() =>
|
|
67
|
+
title: "MODULE.WIDGETS.CHILD_LIST.TITLE",
|
|
68
|
+
badge: computed(() => childCount.value),
|
|
69
69
|
isVisible,
|
|
70
70
|
onClick: () =>
|
|
71
71
|
openBlade({
|
|
72
|
-
name: "
|
|
73
|
-
options: {
|
|
72
|
+
name: "ChildEntityList",
|
|
73
|
+
options: { entityId: item.value?.id },
|
|
74
74
|
}),
|
|
75
75
|
onRefresh: async () => {
|
|
76
|
-
// load
|
|
76
|
+
// load child count logic here
|
|
77
77
|
},
|
|
78
78
|
},
|
|
79
79
|
]);
|
|
@@ -89,14 +89,14 @@ Import the new composable and destructure `{ refreshAll }`.
|
|
|
89
89
|
```typescript
|
|
90
90
|
// XxxDetails.vue <script setup>
|
|
91
91
|
import { useWidgets } from "@vc-shell/framework";
|
|
92
|
-
import
|
|
93
|
-
import
|
|
92
|
+
import ChildListWidget from "../widgets/ChildListWidget.vue";
|
|
93
|
+
import RelatedItemsWidget from "../widgets/RelatedItemsWidget.vue";
|
|
94
94
|
|
|
95
95
|
const { registerWidget, clearBladeWidgets } = useWidgets();
|
|
96
96
|
|
|
97
97
|
onMounted(() => {
|
|
98
|
-
registerWidget({ id: "
|
|
99
|
-
registerWidget({ id: "
|
|
98
|
+
registerWidget({ id: "ChildListWidget", component: ChildListWidget, props: { ... } }, bladeId);
|
|
99
|
+
registerWidget({ id: "RelatedItemsWidget", component: RelatedItemsWidget, props: { ... } }, bladeId);
|
|
100
100
|
});
|
|
101
101
|
|
|
102
102
|
onUnmounted(() => {
|
|
@@ -108,17 +108,29 @@ onUnmounted(() => {
|
|
|
108
108
|
|
|
109
109
|
```typescript
|
|
110
110
|
// XxxDetails.vue <script setup>
|
|
111
|
-
import {
|
|
111
|
+
import { useEntityWidgets } from "../widgets/useEntityWidgets";
|
|
112
112
|
|
|
113
113
|
const isExisting = computed(() => !!param.value);
|
|
114
114
|
|
|
115
|
-
const { refreshAll } =
|
|
115
|
+
const { refreshAll } = useEntityWidgets({
|
|
116
116
|
item: entity,
|
|
117
117
|
isVisible: isExisting,
|
|
118
|
-
|
|
118
|
+
childCount,
|
|
119
119
|
});
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
+
If the old code used `updateActiveWidget()`, replace it with `refreshAll()` from the widget composable return:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// BEFORE
|
|
126
|
+
const { updateActiveWidget } = useWidgets();
|
|
127
|
+
updateActiveWidget();
|
|
128
|
+
|
|
129
|
+
// AFTER
|
|
130
|
+
const { refreshAll } = useEntityWidgets({ item: entity, isVisible: isExisting, childCount });
|
|
131
|
+
refreshAll();
|
|
132
|
+
```
|
|
133
|
+
|
|
122
134
|
## RULE 3: Remove Widget .vue Components
|
|
123
135
|
|
|
124
136
|
Delete widget `.vue` files that only render a standard sidebar item (icon + title + badge + click handler). These are replaced by the declarative config in `useBladeWidgets()`.
|
|
@@ -126,10 +138,12 @@ Delete widget `.vue` files that only render a standard sidebar item (icon + titl
|
|
|
126
138
|
**Keep** the `.vue` component only if it has custom rendering beyond the standard widget layout.
|
|
127
139
|
|
|
128
140
|
**Delete:**
|
|
129
|
-
|
|
130
|
-
- `widgets/
|
|
141
|
+
|
|
142
|
+
- `widgets/ChildListWidget.vue` (if it only shows icon, title, badge, click)
|
|
143
|
+
- `widgets/RelatedItemsWidget.vue` (same)
|
|
131
144
|
|
|
132
145
|
**Keep:**
|
|
146
|
+
|
|
133
147
|
- `widgets/CustomChartWidget.vue` (has custom chart rendering)
|
|
134
148
|
|
|
135
149
|
## RULE 4: Remove Old Imports
|
|
@@ -142,9 +156,15 @@ import { useWidgets } from "@vc-shell/framework";
|
|
|
142
156
|
import type { BladeInstance } from "@vc-shell/framework"; // if only used for widgets
|
|
143
157
|
import { registerWidget, unregisterWidget, clearBladeWidgets } from "...";
|
|
144
158
|
import { onUnmounted } from "vue"; // if only used for widget cleanup
|
|
145
|
-
import
|
|
159
|
+
import ChildListWidget from "../widgets/ChildListWidget.vue"; // deleted component
|
|
146
160
|
```
|
|
147
161
|
|
|
162
|
+
## RULE 5: `defineBladeContext` only for external widgets
|
|
163
|
+
|
|
164
|
+
Do not add `defineBladeContext()` by default in this migration.
|
|
165
|
+
|
|
166
|
+
Add it only if the blade hosts external widget components that use `injectBladeContext()`.
|
|
167
|
+
|
|
148
168
|
## Verification
|
|
149
169
|
|
|
150
170
|
After migration:
|
|
@@ -155,3 +175,4 @@ After migration:
|
|
|
155
175
|
4. Confirm clicking a widget opens the correct child blade
|
|
156
176
|
5. Confirm widgets are hidden when `isVisible` is false (e.g., on "create new" blades)
|
|
157
177
|
6. Confirm no console errors about widget registration/cleanup on blade close
|
|
178
|
+
7. Confirm `updateActiveWidget()` calls are removed and replaced with `refreshAll()` from `useEntityWidgets` return
|
|
@@ -68,7 +68,9 @@ const { showConfirmation } = usePopup();
|
|
|
68
68
|
|
|
69
69
|
const images = computed({
|
|
70
70
|
get: () => item.value?.images ?? [],
|
|
71
|
-
set: (val) => {
|
|
71
|
+
set: (val) => {
|
|
72
|
+
if (item.value) item.value.images = val;
|
|
73
|
+
},
|
|
72
74
|
});
|
|
73
75
|
|
|
74
76
|
const assets = useAssetsManager(images, {
|
|
@@ -101,13 +103,7 @@ Use when assets are a secondary concern shown as a widget badge. Clicking the wi
|
|
|
101
103
|
```ts
|
|
102
104
|
// widgets/useEntityWidgets.ts
|
|
103
105
|
import { computed, markRaw, type Ref, type ComputedRef } from "vue";
|
|
104
|
-
import {
|
|
105
|
-
useBlade,
|
|
106
|
-
useBladeWidgets,
|
|
107
|
-
useAssetsManager,
|
|
108
|
-
usePopup,
|
|
109
|
-
type UseBladeWidgetsReturn,
|
|
110
|
-
} from "@vc-shell/framework";
|
|
106
|
+
import { useBlade, useBladeWidgets, useAssetsManager, usePopup, type UseBladeWidgetsReturn } from "@vc-shell/framework";
|
|
111
107
|
|
|
112
108
|
interface Options {
|
|
113
109
|
item: Ref<Entity | undefined>;
|
|
@@ -145,7 +141,7 @@ export function useEntityWidgets({ item, disabled, isVisible }: Options): UseBla
|
|
|
145
141
|
openBlade({
|
|
146
142
|
name: "AssetsManager",
|
|
147
143
|
options: {
|
|
148
|
-
manager: markRaw(assetsManager),
|
|
144
|
+
manager: markRaw(assetsManager), // markRaw prevents Vue from making it reactive
|
|
149
145
|
disabled: disabled.value,
|
|
150
146
|
},
|
|
151
147
|
}),
|
|
@@ -186,14 +182,18 @@ Each manager operates on a different writable computed pointing to a different a
|
|
|
186
182
|
// Gallery assets (images)
|
|
187
183
|
const productImages = computed({
|
|
188
184
|
get: () => item.value.productData?.images ?? [],
|
|
189
|
-
set: (val) => {
|
|
185
|
+
set: (val) => {
|
|
186
|
+
if (item.value.productData) item.value.productData.images = val;
|
|
187
|
+
},
|
|
190
188
|
});
|
|
191
189
|
const imageAssets = useAssetsManager(productImages, { uploadPath: () => `/catalog/${item.value.id}` });
|
|
192
190
|
|
|
193
191
|
// Widget assets (files)
|
|
194
192
|
const productFiles = computed({
|
|
195
193
|
get: () => (item.value?.productData?.assets ?? []) as Asset[],
|
|
196
|
-
set: (val) => {
|
|
194
|
+
set: (val) => {
|
|
195
|
+
if (item.value?.productData) item.value.productData.assets = val;
|
|
196
|
+
},
|
|
197
197
|
});
|
|
198
198
|
const fileAssets = useAssetsManager(productFiles, { uploadPath: () => `/catalog/${item.value.id}` });
|
|
199
199
|
```
|
|
@@ -202,12 +202,12 @@ const fileAssets = useAssetsManager(productFiles, { uploadPath: () => `/catalog/
|
|
|
202
202
|
|
|
203
203
|
## Key Points
|
|
204
204
|
|
|
205
|
-
| Concern
|
|
206
|
-
|
|
207
|
-
| Binding to entity
|
|
208
|
-
| Upload path
|
|
209
|
-
| Remove confirmation
|
|
210
|
-
| Passing to AssetsManager blade | Wrap with `markRaw()` — prevents Vue from making the manager deeply reactive
|
|
211
|
-
| Multiple asset types
|
|
212
|
-
| Gallery edit
|
|
213
|
-
| Widget visibility
|
|
205
|
+
| Concern | Approach |
|
|
206
|
+
| ------------------------------ | -------------------------------------------------------------------------------------- |
|
|
207
|
+
| Binding to entity | Writable `computed` — getter reads nested array, setter writes it back |
|
|
208
|
+
| Upload path | Callback `() => string` — resolved at upload time, so entity ID is available |
|
|
209
|
+
| Remove confirmation | Pass `confirmRemove` returning `Promise<boolean>` via `usePopup().showConfirmation` |
|
|
210
|
+
| Passing to AssetsManager blade | Wrap with `markRaw()` — prevents Vue from making the manager deeply reactive |
|
|
211
|
+
| Multiple asset types | Create separate `useAssetsManager` instances per array (images vs files) |
|
|
212
|
+
| Gallery edit | Open `AssetsDetails` blade, pass `assetEditHandler` and `assetRemoveHandler` callbacks |
|
|
213
|
+
| Widget visibility | Use `isVisible: computed(() => !!param.value)` to hide on "create new" mode |
|
|
@@ -9,15 +9,7 @@ Blades are stacked panels rendered by `VcBladeNavigation`. Navigation between bl
|
|
|
9
9
|
```ts
|
|
10
10
|
import { useBlade } from "@vc-shell/framework";
|
|
11
11
|
|
|
12
|
-
const {
|
|
13
|
-
openBlade,
|
|
14
|
-
closeSelf,
|
|
15
|
-
callParent,
|
|
16
|
-
exposeToChildren,
|
|
17
|
-
onBeforeClose,
|
|
18
|
-
param,
|
|
19
|
-
options,
|
|
20
|
-
} = useBlade<OptionsType>();
|
|
12
|
+
const { openBlade, closeSelf, callParent, exposeToChildren, onBeforeClose, param, options } = useBlade<OptionsType>();
|
|
21
13
|
```
|
|
22
14
|
|
|
23
15
|
`useBlade()` must be called inside `<script setup>` of a blade component. It uses provide/inject to wire the blade hierarchy.
|
|
@@ -58,6 +50,7 @@ entity.value.name = options.value?.prefilledName ?? "";
|
|
|
58
50
|
## `openBlade()` — Open a child blade
|
|
59
51
|
|
|
60
52
|
Full signature:
|
|
53
|
+
|
|
61
54
|
```ts
|
|
62
55
|
openBlade({
|
|
63
56
|
name: string, // defineBlade name of the target blade
|
|
@@ -133,7 +126,7 @@ const { callParent } = useBlade();
|
|
|
133
126
|
|
|
134
127
|
// In details blade after save:
|
|
135
128
|
await updateXxx(entity.value);
|
|
136
|
-
callParent("reload");
|
|
129
|
+
callParent("reload"); // calls parent's reload() function
|
|
137
130
|
closeSelf();
|
|
138
131
|
```
|
|
139
132
|
|
|
@@ -170,19 +163,19 @@ const { showConfirmation } = usePopup();
|
|
|
170
163
|
onBeforeClose(async () => {
|
|
171
164
|
if (modified.value) {
|
|
172
165
|
// returns true to BLOCK close, false to ALLOW close
|
|
173
|
-
return !(await showConfirmation(
|
|
174
|
-
unref(computed(() => t("MODULE.PAGES.ALERTS.CLOSE_CONFIRMATION"))),
|
|
175
|
-
));
|
|
166
|
+
return !(await showConfirmation(unref(computed(() => t("MODULE.PAGES.ALERTS.CLOSE_CONFIRMATION")))));
|
|
176
167
|
}
|
|
177
|
-
return false;
|
|
168
|
+
return false; // no unsaved changes — allow close
|
|
178
169
|
});
|
|
179
170
|
```
|
|
180
171
|
|
|
181
172
|
Return value semantics:
|
|
173
|
+
|
|
182
174
|
- `false` → close is allowed
|
|
183
175
|
- `true` → close is blocked (user stays on the blade)
|
|
184
176
|
|
|
185
177
|
The pattern `!(await showConfirmation(...))` works as:
|
|
178
|
+
|
|
186
179
|
- User clicks "Confirm" → `showConfirmation` returns `true` → `!true` = `false` → close allowed
|
|
187
180
|
- User clicks "Cancel" → `showConfirmation` returns `false` → `!false` = `true` → close blocked
|
|
188
181
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Blade Widget Pattern
|
|
2
2
|
|
|
3
|
-
Blade widgets are sidebar items displayed alongside a details blade. They allow navigation to related child blades (e.g., "
|
|
3
|
+
Blade widgets are sidebar items displayed alongside a details blade. They allow navigation to related child blades (e.g., "Children of this entity", "Associated items"). Each widget shows an icon, a title, and an optional reactive badge count.
|
|
4
4
|
|
|
5
5
|
Blade widgets use `useBladeWidgets()` — the headless widget API. No `.vue` component is needed per widget; the framework renders a standard `<VcWidget>` from the config object.
|
|
6
6
|
|
|
@@ -17,18 +17,18 @@ import { useBladeWidgets, useBlade } from "@vc-shell/framework";
|
|
|
17
17
|
import { computed } from "vue";
|
|
18
18
|
|
|
19
19
|
const { openBlade } = useBlade();
|
|
20
|
-
const
|
|
20
|
+
const childCount = ref(0);
|
|
21
21
|
|
|
22
22
|
useBladeWidgets([
|
|
23
23
|
{
|
|
24
|
-
id: "
|
|
24
|
+
id: "ChildListWidget",
|
|
25
25
|
icon: "lucide-tag",
|
|
26
|
-
title: "
|
|
27
|
-
badge: computed(() =>
|
|
28
|
-
isVisible: computed(() => !!param.value),
|
|
29
|
-
onClick: () => openBlade({ name: "
|
|
26
|
+
title: "MODULE.WIDGETS.CHILD_LIST.TITLE",
|
|
27
|
+
badge: computed(() => childCount.value),
|
|
28
|
+
isVisible: computed(() => !!param.value), // hide on "create new"
|
|
29
|
+
onClick: () => openBlade({ name: "ChildEntityList", options: { entityId: entity.value.id } }),
|
|
30
30
|
onRefresh: async () => {
|
|
31
|
-
|
|
31
|
+
childCount.value = await loadChildCount(entity.value.id);
|
|
32
32
|
},
|
|
33
33
|
},
|
|
34
34
|
]);
|
|
@@ -66,10 +66,11 @@ export function useXxxWidgets(options: UseXxxWidgetsOptions): UseBladeWidgetsRet
|
|
|
66
66
|
title: "XXX.WIDGETS.RELATED_ITEMS.TITLE",
|
|
67
67
|
badge: relatedCount,
|
|
68
68
|
isVisible,
|
|
69
|
-
onClick: () =>
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
onClick: () =>
|
|
70
|
+
openBlade({
|
|
71
|
+
name: "RelatedItemsList",
|
|
72
|
+
options: { parentId: item.value?.id },
|
|
73
|
+
}),
|
|
73
74
|
},
|
|
74
75
|
]);
|
|
75
76
|
}
|
|
@@ -96,9 +97,9 @@ const { refreshAll } = useXxxWidgets({
|
|
|
96
97
|
|
|
97
98
|
```ts
|
|
98
99
|
interface HeadlessWidgetDeclaration {
|
|
99
|
-
id: string;
|
|
100
|
-
icon: string;
|
|
101
|
-
title: string;
|
|
100
|
+
id: string; // unique within the blade
|
|
101
|
+
icon: string; // lucide icon name
|
|
102
|
+
title: string; // i18n key or plain string
|
|
102
103
|
badge?: Ref<number | string> | ComputedRef<number | string>;
|
|
103
104
|
loading?: Ref<boolean> | ComputedRef<boolean>;
|
|
104
105
|
disabled?: Ref<boolean> | ComputedRef<boolean> | boolean;
|
|
@@ -112,8 +113,8 @@ interface HeadlessWidgetDeclaration {
|
|
|
112
113
|
|
|
113
114
|
```ts
|
|
114
115
|
interface UseBladeWidgetsReturn {
|
|
115
|
-
refresh: (widgetId: string) => void;
|
|
116
|
-
refreshAll: () => void;
|
|
116
|
+
refresh: (widgetId: string) => void; // trigger onRefresh for one widget
|
|
117
|
+
refreshAll: () => void; // trigger onRefresh for all widgets
|
|
117
118
|
}
|
|
118
119
|
```
|
|
119
120
|
|
|
@@ -124,6 +125,7 @@ Call `refreshAll()` from `onMounted` or after data loads to populate badge count
|
|
|
124
125
|
## Lifecycle
|
|
125
126
|
|
|
126
127
|
`useBladeWidgets()` automatically:
|
|
128
|
+
|
|
127
129
|
- Registers all widgets with the `WidgetService` on `onMounted`
|
|
128
130
|
- Unregisters all widgets from the `WidgetService` on `onUnmounted`
|
|
129
131
|
|
|
@@ -13,10 +13,14 @@ const { openBlade } = useBlade();
|
|
|
13
13
|
|
|
14
14
|
openBlade({
|
|
15
15
|
name: "ProductDetails",
|
|
16
|
-
param: product.id,
|
|
17
|
-
options: { mode: "edit", origin: "catalog" },
|
|
18
|
-
onOpen() {
|
|
19
|
-
|
|
16
|
+
param: product.id, // string — entity ID, appears in URL
|
|
17
|
+
options: { mode: "edit", origin: "catalog" }, // object — runtime-only, not in URL
|
|
18
|
+
onOpen() {
|
|
19
|
+
selectedItemId.value = product.id;
|
|
20
|
+
},
|
|
21
|
+
onClose() {
|
|
22
|
+
selectedItemId.value = undefined;
|
|
23
|
+
},
|
|
20
24
|
});
|
|
21
25
|
```
|
|
22
26
|
|
|
@@ -93,10 +97,12 @@ onBeforeClose(async () => {
|
|
|
93
97
|
```
|
|
94
98
|
|
|
95
99
|
Return value semantics:
|
|
100
|
+
|
|
96
101
|
- `false` — close is **allowed**
|
|
97
102
|
- `true` — close is **blocked** (user stays on the blade)
|
|
98
103
|
|
|
99
104
|
The `!(await showConfirmation(...))` idiom:
|
|
105
|
+
|
|
100
106
|
- User clicks "Confirm" (discard) -> `true` -> `!true` = `false` -> close allowed
|
|
101
107
|
- User clicks "Cancel" (stay) -> `false` -> `!false` = `true` -> close blocked
|
|
102
108
|
|
|
@@ -187,8 +193,12 @@ function onItemClick(event: { data: { id?: string } }) {
|
|
|
187
193
|
openBlade({
|
|
188
194
|
name: "ProductDetails",
|
|
189
195
|
param: event.data.id,
|
|
190
|
-
onOpen() {
|
|
191
|
-
|
|
196
|
+
onOpen() {
|
|
197
|
+
selectedItemId.value = event.data.id;
|
|
198
|
+
},
|
|
199
|
+
onClose() {
|
|
200
|
+
selectedItemId.value = undefined;
|
|
201
|
+
},
|
|
192
202
|
});
|
|
193
203
|
}
|
|
194
204
|
|
|
@@ -250,7 +260,9 @@ A "middle" blade acts as both child (calls its parent) and parent (exposes metho
|
|
|
250
260
|
const { openBlade, callParent, exposeToChildren, closeSelf } = useBlade();
|
|
251
261
|
|
|
252
262
|
// As a parent — expose reload for child blades
|
|
253
|
-
async function reload() {
|
|
263
|
+
async function reload() {
|
|
264
|
+
await loadOrder(param.value!);
|
|
265
|
+
}
|
|
254
266
|
exposeToChildren({ reload });
|
|
255
267
|
|
|
256
268
|
// As a child — open sub-details blade
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Details Composable Pattern (`use<Entity>`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Generic worked example for the canonical `useTeamMember` / `useEntity` composable shape.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
@@ -13,19 +13,9 @@ Naming convention: `use<Entity>` (singular) for details, `use<Entity>s` (plural)
|
|
|
13
13
|
## Full Code Skeleton
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
|
-
import {
|
|
17
|
-
useModificationTracker,
|
|
18
|
-
useApiClient,
|
|
19
|
-
useAsync,
|
|
20
|
-
useLoading,
|
|
21
|
-
} from "@vc-shell/framework";
|
|
16
|
+
import { useModificationTracker, useApiClient, useAsync, useLoading } from "@vc-shell/framework";
|
|
22
17
|
import type { AsyncAction } from "@vc-shell/framework";
|
|
23
|
-
import {
|
|
24
|
-
XxxClient,
|
|
25
|
-
XxxType,
|
|
26
|
-
CreateXxxCommand,
|
|
27
|
-
UpdateXxxCommand,
|
|
28
|
-
} from "../../api_client/xxx-client";
|
|
18
|
+
import { XxxClient, XxxType, CreateXxxCommand, UpdateXxxCommand } from "../../api_client/xxx-client";
|
|
29
19
|
import { computed, ComputedRef, Ref, ref } from "vue";
|
|
30
20
|
|
|
31
21
|
// NOTE: useI18n is NOT imported here. Translations belong in blade components.
|
|
@@ -50,15 +40,11 @@ export default (): IUseXxx => {
|
|
|
50
40
|
// --- Entity ref and modification tracker ---
|
|
51
41
|
// entityRef is internal; currentValue is exposed as `entity`
|
|
52
42
|
const entityRef = ref({} as XxxType) as Ref<XxxType>;
|
|
53
|
-
const { currentValue, pristineValue, resetModificationState, isModified } =
|
|
54
|
-
useModificationTracker(entityRef);
|
|
43
|
+
const { currentValue, pristineValue, resetModificationState, isModified } = useModificationTracker(entityRef);
|
|
55
44
|
|
|
56
45
|
// --- CRUD operations (each has its own loading ref) ---
|
|
57
46
|
|
|
58
|
-
const { action: getXxx, loading: getXxxLoading } = useAsync<
|
|
59
|
-
{ id: string },
|
|
60
|
-
void
|
|
61
|
-
>(async (args) => {
|
|
47
|
+
const { action: getXxx, loading: getXxxLoading } = useAsync<{ id: string }, void>(async (args) => {
|
|
62
48
|
if (!args?.id) {
|
|
63
49
|
throw new Error("Id is required");
|
|
64
50
|
}
|
|
@@ -74,10 +60,7 @@ export default (): IUseXxx => {
|
|
|
74
60
|
resetModificationState();
|
|
75
61
|
});
|
|
76
62
|
|
|
77
|
-
const { action: createXxx, loading: createXxxLoading } = useAsync<
|
|
78
|
-
XxxType,
|
|
79
|
-
void
|
|
80
|
-
>(async (details) => {
|
|
63
|
+
const { action: createXxx, loading: createXxxLoading } = useAsync<XxxType, void>(async (details) => {
|
|
81
64
|
const client = await getApiClient();
|
|
82
65
|
|
|
83
66
|
const command = {
|
|
@@ -93,10 +76,7 @@ export default (): IUseXxx => {
|
|
|
93
76
|
resetModificationState();
|
|
94
77
|
});
|
|
95
78
|
|
|
96
|
-
const { action: updateXxx, loading: updateXxxLoading } = useAsync<
|
|
97
|
-
XxxType,
|
|
98
|
-
void
|
|
99
|
-
>(async (details) => {
|
|
79
|
+
const { action: updateXxx, loading: updateXxxLoading } = useAsync<XxxType, void>(async (details) => {
|
|
100
80
|
if (!details?.id) {
|
|
101
81
|
throw new Error("Id is required");
|
|
102
82
|
}
|
|
@@ -116,10 +96,7 @@ export default (): IUseXxx => {
|
|
|
116
96
|
resetModificationState();
|
|
117
97
|
});
|
|
118
98
|
|
|
119
|
-
const { action: deleteXxx, loading: deleteXxxLoading } = useAsync<
|
|
120
|
-
{ id: string },
|
|
121
|
-
void
|
|
122
|
-
>(async (args) => {
|
|
99
|
+
const { action: deleteXxx, loading: deleteXxxLoading } = useAsync<{ id: string }, void>(async (args) => {
|
|
123
100
|
if (!args?.id) {
|
|
124
101
|
throw new Error("Id is required");
|
|
125
102
|
}
|
|
@@ -138,12 +115,7 @@ export default (): IUseXxx => {
|
|
|
138
115
|
// --- Return ---
|
|
139
116
|
return {
|
|
140
117
|
// Aggregate all async loading refs into a single computed boolean
|
|
141
|
-
loading: useLoading(
|
|
142
|
-
getXxxLoading,
|
|
143
|
-
createXxxLoading,
|
|
144
|
-
updateXxxLoading,
|
|
145
|
-
deleteXxxLoading,
|
|
146
|
-
),
|
|
118
|
+
loading: useLoading(getXxxLoading, createXxxLoading, updateXxxLoading, deleteXxxLoading),
|
|
147
119
|
// currentValue is the reactive entity — alias as `entity` for the blade
|
|
148
120
|
entity: currentValue,
|
|
149
121
|
modified: computed(() => isModified.value),
|
|
@@ -263,9 +235,9 @@ export default (): IUseXxx => {
|
|
|
263
235
|
|
|
264
236
|
---
|
|
265
237
|
|
|
266
|
-
## Route Params (when entity scope requires
|
|
238
|
+
## Route Params (when entity scope requires a parent ownerId / tenantId)
|
|
267
239
|
|
|
268
|
-
Some API calls require a scope parameter (e.g., `
|
|
240
|
+
Some API calls require a scope parameter (e.g., `ownerId`) extracted from the route. Use `useRoute()`:
|
|
269
241
|
|
|
270
242
|
```ts
|
|
271
243
|
import { useRoute } from "vue-router";
|
|
@@ -274,20 +246,18 @@ export default (): IUseXxx => {
|
|
|
274
246
|
const route = useRoute();
|
|
275
247
|
const { getApiClient } = useApiClient(XxxClient);
|
|
276
248
|
|
|
277
|
-
async function
|
|
278
|
-
return route?.params?.
|
|
249
|
+
async function getOwnerId(): Promise<string> {
|
|
250
|
+
return route?.params?.ownerId as string;
|
|
279
251
|
}
|
|
280
252
|
|
|
281
|
-
const { action: getXxx, loading: getXxxLoading } = useAsync<{ id: string }>(
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const sellerId = await getSellerId();
|
|
253
|
+
const { action: getXxx, loading: getXxxLoading } = useAsync<{ id: string }>(async (args) => {
|
|
254
|
+
const client = await getApiClient();
|
|
255
|
+
const ownerId = await getOwnerId();
|
|
285
256
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
);
|
|
257
|
+
const result = await client.getXxx(args.id, ownerId);
|
|
258
|
+
currentValue.value = result;
|
|
259
|
+
resetModificationState();
|
|
260
|
+
});
|
|
291
261
|
|
|
292
262
|
// ...
|
|
293
263
|
};
|