@vc-shell/vc-app-skill 2.0.4 → 2.0.6
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 +10 -0
- package/README.md +7 -7
- package/package.json +1 -1
- package/runtime/VERSION +1 -1
- package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
- package/runtime/knowledge/docs/core/api/platform.docs.md +6 -6
- package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/bladeContext/index.docs.md +2 -2
- package/runtime/knowledge/docs/core/composables/useApiClient/useApiClient.docs.md +67 -42
- package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +2 -2
- package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +15 -13
- package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +11 -11
- package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +17 -14
- package/runtime/knowledge/docs/core/composables/useBeforeUnload/useBeforeUnload.docs.md +4 -2
- package/runtime/knowledge/docs/core/composables/useBlade/useBlade.docs.md +31 -23
- package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +46 -26
- package/runtime/knowledge/docs/core/composables/useDashboard/useDashboard.docs.md +1 -0
- package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/useMenuExpanded/index.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/useMenuService/useMenuService.docs.md +1 -0
- package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +20 -6
- package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +2 -1
- package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +2 -2
- package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +109 -133
- package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +1 -2
- package/runtime/knowledge/docs/core/notifications/composables/useBladeNotifications.docs.md +184 -0
- package/runtime/knowledge/docs/core/notifications/composables/useBroadcastFilter.docs.md +117 -0
- package/runtime/knowledge/docs/core/notifications/composables/useNotificationContext.docs.md +150 -0
- package/runtime/knowledge/docs/core/notifications/composables/useNotificationStore.docs.md +113 -0
- package/runtime/knowledge/docs/core/notifications/notifications.docs.md +12 -15
- package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +1 -1
- package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +54 -116
- package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +12 -3
- package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +20 -20
- package/runtime/knowledge/docs/injection-keys.docs.md +1 -1
- package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/notification-dropdown/notification-dropdown.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +7 -7
- package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +2 -2
- package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +4 -4
- package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +21 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +22 -6
- package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +2 -2
- package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +32 -26
- package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +3 -3
- package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md +13 -13
- package/runtime/knowledge/docs/ui/components/molecules/vc-form/vc-form.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +4 -4
- package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +39 -37
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +17 -17
- package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +16 -7
- package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +1 -1
|
@@ -23,14 +23,22 @@ Unified composable for blade navigation, identity, communication, guards, and er
|
|
|
23
23
|
<script setup lang="ts">
|
|
24
24
|
import { useBlade } from "@vc-shell/framework";
|
|
25
25
|
|
|
26
|
-
//
|
|
27
|
-
|
|
26
|
+
// List blade -- typical destructure: open children, expose parent methods, read param
|
|
27
|
+
interface BladeOptions {
|
|
28
|
+
item?: Order;
|
|
29
|
+
}
|
|
30
|
+
const { openBlade, exposeToChildren, param, options, callParent } = useBlade<BladeOptions>();
|
|
28
31
|
|
|
29
|
-
//
|
|
30
|
-
|
|
32
|
+
// Expose a reload method so child details blades can refresh the list after save
|
|
33
|
+
async function reload() {
|
|
34
|
+
/* refetch items */
|
|
35
|
+
}
|
|
36
|
+
exposeToChildren({ reload });
|
|
31
37
|
|
|
32
|
-
//
|
|
33
|
-
|
|
38
|
+
// Open a child details blade
|
|
39
|
+
function onRowClick(order: Order) {
|
|
40
|
+
openBlade({ name: "OrderDetails", param: order.id, options: { item: order } });
|
|
41
|
+
}
|
|
34
42
|
</script>
|
|
35
43
|
```
|
|
36
44
|
|
|
@@ -41,7 +49,7 @@ import { useBlade } from "@vc-shell/framework";
|
|
|
41
49
|
// Outside a blade (e.g. dashboard widget) -- only navigation works
|
|
42
50
|
const { openBlade } = useBlade();
|
|
43
51
|
|
|
44
|
-
openBlade({ name: "
|
|
52
|
+
openBlade({ name: "OrdersList", isWorkspace: true });
|
|
45
53
|
</script>
|
|
46
54
|
```
|
|
47
55
|
|
|
@@ -49,13 +57,14 @@ openBlade({ name: "OrderDetails", param: "order-123" });
|
|
|
49
57
|
<script setup lang="ts">
|
|
50
58
|
import { useBlade } from "@vc-shell/framework";
|
|
51
59
|
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
sellerProduct?: SellerProduct;
|
|
55
|
-
}
|
|
56
|
-
const { param, options, callParent } = useBlade<BladeOptions>();
|
|
60
|
+
// Details blade -- call back into the parent after save
|
|
61
|
+
const { param, options, callParent, closeSelf } = useBlade<{ item?: Order }>();
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
async function onSave() {
|
|
64
|
+
await saveOrder();
|
|
65
|
+
await callParent("reload");
|
|
66
|
+
await closeSelf();
|
|
67
|
+
}
|
|
59
68
|
</script>
|
|
60
69
|
```
|
|
61
70
|
|
|
@@ -518,7 +527,7 @@ The most common pattern: a list workspace that opens a details blade on row clic
|
|
|
518
527
|
<script setup lang="ts">
|
|
519
528
|
import { useBlade } from "@vc-shell/framework";
|
|
520
529
|
|
|
521
|
-
|
|
530
|
+
defineBlade({ name: "ProductsList", url: "/products", isWorkspace: true });
|
|
522
531
|
|
|
523
532
|
const { openBlade } = useBlade();
|
|
524
533
|
const selectedItemId = ref<string>();
|
|
@@ -552,7 +561,7 @@ defineExpose({ reload, title: "Products" });
|
|
|
552
561
|
<script setup lang="ts">
|
|
553
562
|
import { useBlade, usePopup } from "@vc-shell/framework";
|
|
554
563
|
|
|
555
|
-
|
|
564
|
+
defineBlade({ name: "ProductDetails", url: "/product-details" });
|
|
556
565
|
|
|
557
566
|
const { param, onBeforeClose, closeSelf, callParent } = useBlade();
|
|
558
567
|
const { showConfirmation } = usePopup();
|
|
@@ -764,11 +773,10 @@ if (param.value) {
|
|
|
764
773
|
|
|
765
774
|
## Related
|
|
766
775
|
|
|
767
|
-
| Resource
|
|
768
|
-
|
|
|
769
|
-
| [`defineBladeContext` / `injectBladeContext`](../
|
|
770
|
-
| [`useBladeRegistry`](../useBladeRegistry/)
|
|
771
|
-
| [`VcBlade`](../../../ui/components/organisms/vc-blade/)
|
|
772
|
-
| [`
|
|
773
|
-
| [`
|
|
774
|
-
| [`usePopup`](../../../shared/composables/usePopup/) | Confirmation dialogs, commonly used in close guards |
|
|
776
|
+
| Resource | Description |
|
|
777
|
+
| ---------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
|
778
|
+
| [`defineBladeContext` / `injectBladeContext`](../bladeContext/index.docs.md) | Share reactive blade data with descendant widgets |
|
|
779
|
+
| [`useBladeRegistry`](../useBladeRegistry/) | Look up registered blade components by name |
|
|
780
|
+
| [`VcBlade`](../../../ui/components/organisms/vc-blade/vc-blade.docs.md) | The blade UI shell component (header, toolbar, content area) |
|
|
781
|
+
| [`useToolbar`](../useToolbar/useToolbar.docs.md) | Dynamic toolbar management for blades |
|
|
782
|
+
| [`usePopup`](../usePopup/usePopup.docs.md) | Confirmation dialogs, commonly used in close guards |
|
|
@@ -24,34 +24,54 @@ Headless widgets are defined as plain configuration objects with reactive refs f
|
|
|
24
24
|
|
|
25
25
|
## Basic Usage
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
import { useBladeWidgets } from "@vc-shell/framework";
|
|
27
|
+
In production apps, the widget array is almost never declared inline in the blade's `<script setup>`. The recommended pattern is to extract widget setup into a sibling composable (`useXxxWidgets.ts`) so the blade stays clean, the widgets are testable in isolation, and they can be reused across blades that share a domain.
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
29
|
+
```typescript title="modules/products/widgets/useProductWidgets.ts"
|
|
30
|
+
import { useBlade, useBladeWidgets, type UseBladeWidgetsReturn } from "@vc-shell/framework";
|
|
31
|
+
import type { Ref, ComputedRef } from "vue";
|
|
32
|
+
import { useOfferCount } from "./useOfferCount";
|
|
33
|
+
|
|
34
|
+
interface Options {
|
|
35
|
+
item: Ref<Product | undefined>;
|
|
36
|
+
isVisible: ComputedRef<boolean>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function useProductWidgets({ item, isVisible }: Options): UseBladeWidgetsReturn {
|
|
40
|
+
const { openBlade } = useBlade();
|
|
41
|
+
const { count: offersCount, loading, refresh } = useOfferCount(item);
|
|
42
|
+
|
|
43
|
+
return useBladeWidgets([
|
|
44
|
+
{
|
|
45
|
+
id: "OffersWidget",
|
|
46
|
+
icon: "lucide-tag",
|
|
47
|
+
title: "OFFERS.TITLE",
|
|
48
|
+
badge: offersCount,
|
|
49
|
+
loading,
|
|
50
|
+
isVisible,
|
|
51
|
+
onClick: () => openBlade({ name: "OffersList", options: { productId: item.value?.id } }),
|
|
52
|
+
onRefresh: refresh,
|
|
53
|
+
},
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
49
57
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
```vue title="modules/products/pages/product-details.vue"
|
|
59
|
+
<script setup lang="ts">
|
|
60
|
+
import { useProductWidgets } from "../widgets/useProductWidgets";
|
|
61
|
+
|
|
62
|
+
const { item } = useProductDetails();
|
|
63
|
+
const isVisible = computed(() => !!item.value?.id);
|
|
64
|
+
const { refreshAll } = useProductWidgets({ item, isVisible });
|
|
65
|
+
|
|
66
|
+
async function onSave() {
|
|
67
|
+
await saveProduct();
|
|
68
|
+
refreshAll();
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
53
71
|
```
|
|
54
72
|
|
|
73
|
+
Inline `useBladeWidgets([...])` is fine for one-off widgets, but extracting becomes essential when widget data comes from API calls (which need their own composables anyway).
|
|
74
|
+
|
|
55
75
|
## API
|
|
56
76
|
|
|
57
77
|
### Parameters
|
|
@@ -119,7 +139,7 @@ A complete example of an external widget that shows an unread message count and
|
|
|
119
139
|
**1. Register the external widget (module index.ts):**
|
|
120
140
|
|
|
121
141
|
```typescript
|
|
122
|
-
import {
|
|
142
|
+
import { registerExternalWidget, BladeDescriptor } from "@vc-shell/framework";
|
|
123
143
|
import { markRaw } from "vue";
|
|
124
144
|
import { MessageWidget } from "./components/widgets";
|
|
125
145
|
|
|
@@ -304,7 +324,7 @@ const { refreshAll } = useBladeWidgets([]);
|
|
|
304
324
|
|
|
305
325
|
## Related
|
|
306
326
|
|
|
307
|
-
- [`defineBladeContext` / `injectBladeContext`](../bladeContext/) -- expose/consume blade data in external widgets
|
|
327
|
+
- [`defineBladeContext` / `injectBladeContext`](../bladeContext/index.docs.md) -- expose/consume blade data in external widgets
|
|
308
328
|
- `registerExternalWidget` -- register a component-based widget globally for target blades
|
|
309
329
|
|
|
310
330
|
<!-- internal:start -->
|
|
@@ -270,6 +270,7 @@ export function registerAnalyticsDashboard() {
|
|
|
270
270
|
### Widget Component Template
|
|
271
271
|
|
|
272
272
|
```typescript
|
|
273
|
+
// pseudo-code: replace OrderClient with your generated API client
|
|
273
274
|
<!-- widgets/OrdersSummary.vue -->
|
|
274
275
|
<script setup lang="ts">
|
|
275
276
|
import { ref, onMounted } from "vue";
|
package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md
CHANGED
|
@@ -163,4 +163,4 @@ useDynamicProperties/
|
|
|
163
163
|
## Related
|
|
164
164
|
|
|
165
165
|
- [useBladeForm](../useBladeForm/useBladeForm.docs.md) — form state management that uses `semanticEqual` for modification detection. `cleanEmptyValues` ensures compatibility.
|
|
166
|
-
- [VcDynamicProperty](
|
|
166
|
+
- [VcDynamicProperty](../../../ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md) — UI component that renders dynamic properties
|
|
@@ -76,7 +76,7 @@ const isVisuallyExpanded = computed(() => isExpanded.value || isHoverExpanded.va
|
|
|
76
76
|
|
|
77
77
|
## Details
|
|
78
78
|
|
|
79
|
-
- **Storage key scoping**: The key is scoped per application using the first URL path segment: `VC_APP_MENU_EXPANDED_{appName}`. For example, if the app is hosted at `/
|
|
79
|
+
- **Storage key scoping**: The key is scoped per application using the first URL path segment: `VC_APP_MENU_EXPANDED_{appName}`. For example, if the app is hosted at `/operations/`, the key is `VC_APP_MENU_EXPANDED_operations`. This allows multiple vc-shell apps on the same domain to maintain independent sidebar states.
|
|
80
80
|
- **Hover delay**: Opening uses a 200ms debounce to prevent accidental expansion when the cursor briefly passes over the sidebar. Closing is immediate to feel responsive.
|
|
81
81
|
- **Cleanup**: Pending hover timeouts are cleaned up via `onScopeDispose` to prevent memory leaks when the composable's effect scope is destroyed.
|
|
82
82
|
- **Default state**: The sidebar starts pinned open (`true`) on first visit, which is the most user-friendly default for new users.
|
|
@@ -193,6 +193,7 @@ removeRegisteredMenuItem({ routeId: "ReturnsList" } as MenuItem);
|
|
|
193
193
|
### Dynamic Badge Based on API Data
|
|
194
194
|
|
|
195
195
|
```typescript
|
|
196
|
+
// pseudo-code: replace OrderClient with your generated API client
|
|
196
197
|
<script setup lang="ts">
|
|
197
198
|
import { onMounted, ref } from "vue";
|
|
198
199
|
import { setMenuBadge, useApiClient } from "@vc-shell/framework";
|
|
@@ -18,22 +18,36 @@ Provides access to the push-notification system: reading notification history, f
|
|
|
18
18
|
|
|
19
19
|
## Quick Start
|
|
20
20
|
|
|
21
|
+
In new code, prefer `useBladeNotifications` — it integrates with the blade effect scope and auto-cleans on unmount.
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { useBladeNotifications } from "@vc-shell/framework";
|
|
25
|
+
|
|
26
|
+
// Blade-scoped subscription with automatic cleanup
|
|
27
|
+
const { messages, unreadCount, markAsRead } = useBladeNotifications({
|
|
28
|
+
types: ["OrderStatusChanged"],
|
|
29
|
+
filter: (msg) => msg.orderId === currentOrderId.value,
|
|
30
|
+
onMessage: () => refreshOrderList(),
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use `useNotifications` (this composable) only in legacy code or when you need to subscribe outside a blade scope:
|
|
35
|
+
|
|
21
36
|
```typescript
|
|
22
37
|
import { useNotifications } from "@vc-shell/framework";
|
|
23
38
|
|
|
24
|
-
//
|
|
25
|
-
const { notifications,
|
|
39
|
+
// Legacy: type-filtered subscription with manual lifecycle
|
|
40
|
+
const { notifications, setNotificationHandler, loadFromHistory } = useNotifications("OrderStatusChanged");
|
|
26
41
|
|
|
27
|
-
// Register a handler for real-time notifications
|
|
28
42
|
setNotificationHandler((notification) => {
|
|
29
|
-
console.log("Order status changed:", notification);
|
|
30
43
|
refreshOrderList();
|
|
31
44
|
});
|
|
32
45
|
|
|
33
|
-
// Load historical notifications on mount
|
|
34
46
|
onMounted(() => loadFromHistory(50));
|
|
35
47
|
```
|
|
36
48
|
|
|
49
|
+
For the canonical blade-side example and the registration of notification types at module load, see the [Notifications system reference](../../notifications/notifications.docs.md).
|
|
50
|
+
|
|
37
51
|
## API
|
|
38
52
|
|
|
39
53
|
### Parameters
|
|
@@ -155,6 +169,6 @@ onMounted(refreshInventory);
|
|
|
155
169
|
|
|
156
170
|
## Related
|
|
157
171
|
|
|
158
|
-
- [
|
|
172
|
+
- [Notification system reference](../../notifications/notifications.docs.md) -- includes the recommended `useBladeNotifications` composable with blade lifecycle integration
|
|
159
173
|
- `useNotificationStore()` -- direct Pinia-based store access for full control
|
|
160
174
|
- `MIGRATION_GUIDE.md#notifications` -- migration guide from useNotifications to useBladeNotifications
|
|
@@ -38,6 +38,7 @@ The `hasAccess` function evaluates permissions from the current user object (loa
|
|
|
38
38
|
| Input | Result |
|
|
39
39
|
| -------------------------------- | ------------------------------------------------------------------- |
|
|
40
40
|
| `undefined` | `true` -- no permission required, everyone has access |
|
|
41
|
+
| `[]` (empty array) | `true` -- empty array means no restriction, same as `undefined` |
|
|
41
42
|
| `"order:read"` | `true` if the user has this exact permission string |
|
|
42
43
|
| `["order:read", "order:update"]` | `true` if the user has **any** of the listed permissions (OR logic) |
|
|
43
44
|
| Any value, administrator user | Always `true` -- administrators bypass all checks |
|
|
@@ -279,7 +280,7 @@ if (hasAccess("order:delete")) {
|
|
|
279
280
|
- Permissions are read from `useUserManagement().user.value.permissions` at composable initialization.
|
|
280
281
|
- If `user.value.isAdministrator` is `true`, `hasAccess` always returns `true` regardless of the input.
|
|
281
282
|
- An array input uses OR logic: the user needs at least one of the listed permissions.
|
|
282
|
-
- Passing `undefined` returns `true`, allowing unrestricted access by default.
|
|
283
|
+
- Passing `undefined` or an empty array (`[]`) returns `true`, allowing unrestricted access by default.
|
|
283
284
|
|
|
284
285
|
## Related
|
|
285
286
|
|
|
@@ -94,8 +94,8 @@ const { applySettings } = useSettings();
|
|
|
94
94
|
|
|
95
95
|
// Override default platform settings with module-specific branding
|
|
96
96
|
applySettings({
|
|
97
|
-
logo: "/modules/
|
|
98
|
-
title: "
|
|
97
|
+
logo: "/modules/operations-console/logo.svg",
|
|
98
|
+
title: "Operations Console",
|
|
99
99
|
});
|
|
100
100
|
</script>
|
|
101
101
|
```
|