@vc-shell/vc-app-skill 2.1.0-pr255.4dc5c0d → 2.1.0-pr256.0fe3abb
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/package.json +1 -1
- package/runtime/knowledge/docs/core/api/platform.docs.md +20 -18
- package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +43 -34
- package/runtime/knowledge/docs/core/blade-navigation/table-query-state/useTableQueryState.docs.md +95 -0
- package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +5 -3
- package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +12 -10
- package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +7 -5
- package/runtime/knowledge/docs/core/composables/useAssets/useAssets.docs.md +8 -6
- package/runtime/knowledge/docs/core/composables/useAssetsManager/useAssetsManager.docs.md +3 -1
- package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +8 -5
- package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +12 -12
- package/runtime/knowledge/docs/core/composables/useBreadcrumbs/useBreadcrumbs.docs.md +3 -3
- package/runtime/knowledge/docs/core/composables/useConnectionStatus/useConnectionStatus.docs.md +4 -3
- package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +1 -0
- package/runtime/knowledge/docs/core/composables/useFunctions/useFunctions.docs.md +3 -3
- package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +5 -4
- package/runtime/knowledge/docs/core/composables/useLanguages/useLanguages.docs.md +3 -3
- package/runtime/knowledge/docs/core/composables/useLoading/useLoading.docs.md +2 -0
- package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +1 -2
- package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +3 -3
- package/runtime/knowledge/docs/core/composables/usePlatformLocaleSync/usePlatformLocaleSync.docs.md +35 -0
- package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +2 -2
- package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +2 -1
- package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +18 -18
- package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +3 -3
- package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +10 -7
- package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +7 -7
- package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +18 -12
- package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +2 -2
- package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +20 -20
- package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +15 -24
- package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +2 -2
- package/runtime/knowledge/docs/core/notifications/composables/useBladeNotifications.docs.md +183 -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 +114 -0
- package/runtime/knowledge/docs/core/notifications/notifications.docs.md +50 -30
- package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +30 -11
- package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +1 -1
- package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +2 -3
- package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +26 -26
- package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +2 -3
- package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +11 -50
- package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +9 -6
- package/runtime/knowledge/docs/core/services/services.docs.md +15 -13
- package/runtime/knowledge/docs/core/types/types.docs.md +37 -40
- package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +1 -2
- package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +21 -30
- package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +2 -2
- package/runtime/knowledge/docs/core/utilities/utilities.docs.md +9 -8
- package/runtime/knowledge/docs/injection-keys.docs.md +6 -11
- package/runtime/knowledge/docs/modules/assets/assets-details.docs.md +123 -0
- package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +1 -1
- package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +20 -12
- package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +10 -10
- package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +6 -6
- package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +4 -4
- package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +16 -14
- package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +1 -1
- package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +12 -11
- package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +10 -3
- package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +3 -3
- package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +9 -2
- package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +4 -2
- package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/notification-dropdown/notification-dropdown.docs.md +35 -31
- package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -11
- package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +8 -7
- package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +23 -21
- package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +5 -3
- package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +7 -7
- package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +11 -11
- package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +28 -16
- package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +17 -19
- package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/dashboard-widget-skeleton.docs.md +33 -0
- package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +21 -0
- package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +2 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +2 -2
- package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +15 -14
- package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +9 -6
- package/runtime/knowledge/docs/ui/components/atoms/vc-environment-banner/vc-environment-banner.docs.md +42 -0
- package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +10 -9
- package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +19 -4
- package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +2 -2
- package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +5 -4
- package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +5 -4
- package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +9 -8
- package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +7 -0
- package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +2 -2
- package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +11 -10
- package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +28 -8
- package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +22 -19
- package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +8 -8
- package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +16 -6
- package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +9 -8
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +42 -34
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +14 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +3 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +34 -33
- package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +26 -24
- package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +12 -14
- package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +30 -30
- package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +2 -2
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +34 -31
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +14 -12
- package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +36 -27
- package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +5 -1
- package/runtime/knowledge/docs/ui/components/molecules/{vc-dropdown-panel/vc-dropdown-panel.docs.md → vc-popover/vc-popover.docs.md} +26 -25
- package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +10 -9
- package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +44 -19
- package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +11 -11
- package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +15 -14
- package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +15 -15
- package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +15 -13
- package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +5 -1
- package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +18 -0
- package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +48 -78
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +9 -11
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +71 -43
- package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +27 -20
- package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +2 -2
- package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +12 -12
- package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +33 -24
- package/runtime/knowledge/docs/ui/components/organisms/vc-scheduler/vc-scheduler.docs.md +412 -0
- package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +43 -26
- package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +15 -9
- package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +8 -6
- package/runtime/knowledge/docs/ui/composables/useTableSearch.docs.md +130 -0
- package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +4 -4
- package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +2 -3
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: useNotificationStore
|
|
3
|
+
category: composables
|
|
4
|
+
group: notifications
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# useNotificationStore
|
|
8
|
+
|
|
9
|
+
!!! warning "Advanced — most apps do not need this"
|
|
10
|
+
Reach for [useBladeNotifications](./useBladeNotifications.md), [useBroadcastFilter](./useBroadcastFilter.md), and the `notifications` option on `defineAppModule` first. The bell dropdown, unread badge, and toast pipeline are already wired by the shell. This composable is an **escape hatch** for the small set of cases where those facades do not fit.
|
|
11
|
+
|
|
12
|
+
Returns the singleton store that backs the framework's notification system. Direct access exposes the full reactive state plus low-level actions: subscribing, ingesting synthetic messages, controlling the broadcast filter, paging history.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
There are only two cases where this composable belongs in app code:
|
|
17
|
+
|
|
18
|
+
- **A test or scripted harness** that needs to push synthetic messages through the same pipeline SignalR uses, via `ingest`. Real-time production code never calls `ingest` directly.
|
|
19
|
+
- **A custom shell** that replaces the framework's bell dropdown entirely — typically a module-federation host with its own chrome — and therefore needs to bind to `history`, `unreadCount`, and `markAllAsRead` outside the default surface. Apps that use the standard `VcApp` shell do not need this; the dropdown is already there.
|
|
20
|
+
|
|
21
|
+
For everything else — reacting in a blade, gating broadcasts, registering types, displaying a toast — use the facades. Direct store mutations can bypass invariants the facades enforce (broadcast filter, scope-aware cleanup, type validation).
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { useNotificationStore } from "@vc-shell/framework";
|
|
27
|
+
|
|
28
|
+
const store = useNotificationStore();
|
|
29
|
+
|
|
30
|
+
await store.loadHistory(50);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## API
|
|
34
|
+
|
|
35
|
+
The store exposes the full reactive state plus actions. The shape is summarized below; the underlying types live in `core/notifications/store.ts` and `core/notifications/types.ts`.
|
|
36
|
+
|
|
37
|
+
| Member | Type | Description |
|
|
38
|
+
| ------------------------ | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
39
|
+
| `registry` | `Map<string, NotificationTypeConfig>` | Notification types registered through `defineAppModule({ notifications })`. |
|
|
40
|
+
| `history` | `Ref<PushNotification[]>` | Full history. `loadHistory` replaces it with the server's returned order; `ingest` appends new messages in arrival order. Not sorted — sort in the consumer for newest-first display. |
|
|
41
|
+
| `realtime` | `Ref<PushNotification[]>` | Session-only realtime queue from the SignalR hub. Drives `messages` in `useBladeNotifications`. |
|
|
42
|
+
| `unreadCount` | `ComputedRef<number>` | Count of unread items in `history`. Drives the bell badge. |
|
|
43
|
+
| `hasUnread` | `ComputedRef<boolean>` | Convenience boolean over `unreadCount`. |
|
|
44
|
+
| `registerType(t, cfg)` | `(string, NotificationTypeConfig) => void` | Register a type. Called by the framework when `defineAppModule({ notifications })` runs — rarely needed manually. |
|
|
45
|
+
| `ingest(msg, opts?)` | `(PushNotification, { broadcast?: boolean }?) => void` | Push a message through the same pipeline SignalR uses. Broadcasts pass through the active broadcast filter. |
|
|
46
|
+
| `setBroadcastFilter(fn)` | `((PushNotification) => boolean) => void` | Install a filter for broadcast messages. Prefer [useBroadcastFilter](./useBroadcastFilter.md) — same method. |
|
|
47
|
+
| `clearBroadcastFilter()` | `() => void` | Remove the broadcast filter. |
|
|
48
|
+
| `markAsRead(msg)` | `(PushNotification) => void` | Mark one message as read locally (flips `isNew` on the matching history and realtime entries). Local-only — no server call; server read-state is reconciled by `markAllAsRead`/`loadHistory`. |
|
|
49
|
+
| `markAllAsRead()` | `() => Promise<void>` | Flips local state to read immediately and syncs to the server. Server failure is logged only (no rollback) and reconciled on the next `loadHistory`. |
|
|
50
|
+
| `loadHistory(take?)` | `(number?) => Promise<void>` | Fetch history from the platform. Default page size is 10. The shell already calls this at bootstrap. |
|
|
51
|
+
| `subscribe(opts)` | `({ types, filter?, handler? }) => () => void` | Low-level pub/sub. Returns an `unsub` function. Inside blades use [useBladeNotifications](./useBladeNotifications.md) — it wraps this and registers cleanup automatically. |
|
|
52
|
+
| `getByType(type)` | `(string) => PushNotification[]` | Filter `history` by `notifyType`. |
|
|
53
|
+
|
|
54
|
+
## Escape-hatch patterns
|
|
55
|
+
|
|
56
|
+
### Manually ingest a message (tests, scripted replay)
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
const store = useNotificationStore();
|
|
60
|
+
|
|
61
|
+
store.ingest({
|
|
62
|
+
id: "test-1",
|
|
63
|
+
notifyType: "OrderCreatedDomainEvent",
|
|
64
|
+
title: "Test order",
|
|
65
|
+
isNew: true,
|
|
66
|
+
created: new Date().toISOString(),
|
|
67
|
+
} as PushNotification);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The ingest pipeline runs the configured toast logic and notifies subscribers exactly like a real SignalR message would, so you can verify the end-to-end behavior of `defineAppModule({ notifications })` + `useBladeNotifications` without a live hub.
|
|
71
|
+
|
|
72
|
+
`ingest` with `{ broadcast: true }` simulates `SendSystemEvents` and runs the broadcast filter; without it the message is treated as targeted and bypasses the filter.
|
|
73
|
+
|
|
74
|
+
### Custom shell surface (replace the bell dropdown)
|
|
75
|
+
|
|
76
|
+
When you are building a shell variant that omits the framework's bell dropdown — for example, a module-federation host that renders its own header — bind to the store directly:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { useNotificationStore } from "@vc-shell/framework";
|
|
80
|
+
import { onMounted } from "vue";
|
|
81
|
+
|
|
82
|
+
const store = useNotificationStore();
|
|
83
|
+
|
|
84
|
+
onMounted(() => store.loadHistory(100));
|
|
85
|
+
// Use store.history, store.unreadCount, store.markAllAsRead in your own components.
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
If you are using `VcApp` (the default shell), do **not** do this — the dropdown is already mounted and binding to the same store, so a second surface duplicates what is already on screen.
|
|
89
|
+
|
|
90
|
+
## Resolution
|
|
91
|
+
|
|
92
|
+
`useNotificationStore()` resolves in this order:
|
|
93
|
+
|
|
94
|
+
1. If called inside a Vue component's `setup` (or `app.runWithContext()`), it uses `inject(NotificationStoreKey)`.
|
|
95
|
+
2. Otherwise it returns a module-level singleton created on first call.
|
|
96
|
+
|
|
97
|
+
The fallback exists so module-federation remotes and standalone scripts see the same store the host app uses.
|
|
98
|
+
|
|
99
|
+
## Tips
|
|
100
|
+
|
|
101
|
+
- **Prefer facades.** Every time you find yourself writing `store.subscribe(...)` inside a blade, you want `useBladeNotifications`. Every time you write `store.setBroadcastFilter(...)`, you want `useBroadcastFilter`. The facades exist to keep cleanup, typing, and invariants in one place.
|
|
102
|
+
- **Do not iterate `realtime` for unread counts inside a blade.** That is what `useBladeNotifications` does correctly. Touching `realtime` directly couples your component to shell internals.
|
|
103
|
+
- **`loadHistory` replaces.** It overwrites `history` with the fetched page (`take` controls page size, default 10); it does not merge with or accumulate onto existing entries.
|
|
104
|
+
- **`markAllAsRead` flips local state immediately.** The change is kept even if the server call fails — the failure is logged only (no rollback, no error toast) and reconciled on the next `loadHistory`.
|
|
105
|
+
- **Direct store mutations can bypass invariants.** The broadcast filter only runs through `ingest({ broadcast: true })`. Pushing arrays around `history.value` directly is not supported.
|
|
106
|
+
- **`createNotificationStore({ toastHandle })` is exported.** `useNotificationStore()` always builds a default store wired to the real toast controller. For tests or a custom shell, construct a store directly with `createNotificationStore({ toastHandle })` to inject a stub toast handler.
|
|
107
|
+
|
|
108
|
+
## Related
|
|
109
|
+
|
|
110
|
+
- [useBladeNotifications](./useBladeNotifications.md) — recommended scope-aware subscription. **Start here.**
|
|
111
|
+
- [useBroadcastFilter](./useBroadcastFilter.md) — broadcast acceptance gate.
|
|
112
|
+
- [useNotificationContext](./useNotificationContext.md) — payload access inside templates.
|
|
113
|
+
- [Notifications concept page.](../../concepts/notifications.md)
|
|
114
|
+
- [Notifications plugin reference.](../../plugins/notifications.md)
|
|
@@ -51,22 +51,22 @@ Returns the shared `NotificationStore` singleton. Resolution order:
|
|
|
51
51
|
|
|
52
52
|
### `NotificationStore` Interface
|
|
53
53
|
|
|
54
|
-
| Member | Type | Description
|
|
55
|
-
| ---------------------------- | -------------------------------------------- |
|
|
56
|
-
| `registry` | `Map<string, NotificationTypeConfig>` | Registered notification type configurations
|
|
57
|
-
| `history` | `Ref<PushNotification[]>` | All notifications (loaded from API + ingested)
|
|
58
|
-
| `realtime` | `Ref<PushNotification[]>` | Session-only notifications from SignalR
|
|
59
|
-
| `unreadCount` | `ComputedRef<number>` | Count of unread notifications in history
|
|
60
|
-
| `hasUnread` | `ComputedRef<boolean>` | Whether any unread notifications exist
|
|
61
|
-
| `registerType(type, config)` | `(string, NotificationTypeConfig) => void` | Register a notification type with toast/template config
|
|
62
|
-
| `ingest(message, opts?)` | `(PushNotification, {broadcast?}?) => void` | Process an incoming notification; broadcast messages are filtered
|
|
63
|
-
| `setBroadcastFilter(fn)` | `((PushNotification) => boolean) => void` | Set filter for broadcast messages (SendSystemEvents)
|
|
64
|
-
| `clearBroadcastFilter()` | `() => void` | Remove the broadcast filter
|
|
65
|
-
| `markAsRead(message)` | `(PushNotification) => void` | Mark a single notification as read
|
|
66
|
-
| `markAllAsRead()` | `() => Promise<void>` |
|
|
67
|
-
| `loadHistory(take?)` | `(number?) => Promise<void>` | Load notification history from the API (default: 10)
|
|
68
|
-
| `subscribe(opts)` | `({types, filter?, handler?}) => () => void` | Subscribe to notification types; returns unsubscribe function
|
|
69
|
-
| `getByType(type)` | `(string) => PushNotification[]` | Filter history by `notifyType`
|
|
54
|
+
| Member | Type | Description |
|
|
55
|
+
| ---------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
56
|
+
| `registry` | `Map<string, NotificationTypeConfig>` | Registered notification type configurations |
|
|
57
|
+
| `history` | `Ref<PushNotification[]>` | All notifications (loaded from API + ingested) |
|
|
58
|
+
| `realtime` | `Ref<PushNotification[]>` | Session-only notifications from SignalR |
|
|
59
|
+
| `unreadCount` | `ComputedRef<number>` | Count of unread notifications in history |
|
|
60
|
+
| `hasUnread` | `ComputedRef<boolean>` | Whether any unread notifications exist |
|
|
61
|
+
| `registerType(type, config)` | `(string, NotificationTypeConfig) => void` | Register a notification type with toast/template config |
|
|
62
|
+
| `ingest(message, opts?)` | `(PushNotification, {broadcast?}?) => void` | Process an incoming notification; broadcast messages are filtered |
|
|
63
|
+
| `setBroadcastFilter(fn)` | `((PushNotification) => boolean) => void` | Set filter for broadcast messages (SendSystemEvents) |
|
|
64
|
+
| `clearBroadcastFilter()` | `() => void` | Remove the broadcast filter |
|
|
65
|
+
| `markAsRead(message)` | `(PushNotification) => void` | Mark a single notification as read |
|
|
66
|
+
| `markAllAsRead()` | `() => Promise<void>` | Mark-all-as-read: flips local state immediately and syncs to the server; server failure is logged only, no rollback |
|
|
67
|
+
| `loadHistory(take?)` | `(number?) => Promise<void>` | Load notification history from the API (default: 10) |
|
|
68
|
+
| `subscribe(opts)` | `({types, filter?, handler?}) => () => void` | Subscribe to notification types; returns unsubscribe function |
|
|
69
|
+
| `getByType(type)` | `(string) => PushNotification[]` | Filter history by `notifyType` |
|
|
70
70
|
|
|
71
71
|
**File:** `store.ts`
|
|
72
72
|
|
|
@@ -150,7 +150,7 @@ clearBroadcastFilter();
|
|
|
150
150
|
|
|
151
151
|
### Toast Controller
|
|
152
152
|
|
|
153
|
-
Handles toast popup display based on `NotificationTypeConfig.toast` settings. Created internally by the store.
|
|
153
|
+
Handles toast popup display based on `NotificationTypeConfig.toast` settings. Created internally by the store. `createToastController()` and `createNotificationStore(options?)` are both exported factories for custom shells and test harnesses — pass `createNotificationStore({ toastHandle })` to inject a stub toast handler.
|
|
154
154
|
|
|
155
155
|
**File:** `toast-controller.ts`
|
|
156
156
|
|
|
@@ -162,20 +162,40 @@ Handles toast popup display based on `NotificationTypeConfig.toast` settings. Cr
|
|
|
162
162
|
| `"progress"` | Persistent toast updated on each message; auto-completes when `isComplete()` returns `true` |
|
|
163
163
|
| `"silent"` | No toast displayed |
|
|
164
164
|
|
|
165
|
+
### Imperative `notification` API
|
|
166
|
+
|
|
167
|
+
Low-level toast helper exported from `index.ts` for firing toasts directly (used by the Toast Controller for progress toasts and by framework internals). Call `notification(content, options?)` for a default toast, or use the typed helpers.
|
|
168
|
+
|
|
169
|
+
**File:** `notification.ts`
|
|
170
|
+
|
|
171
|
+
| Method | Description |
|
|
172
|
+
| --------------------------------- | --------------------------------------------------------------------------- |
|
|
173
|
+
| `notification(content, opts?)` | Show a default toast; returns the notification id |
|
|
174
|
+
| `notification.error(...)` | Show an error-styled toast |
|
|
175
|
+
| `notification.warning(...)` | Show a warning-styled toast |
|
|
176
|
+
| `notification.success(...)` | Show a success-styled toast |
|
|
177
|
+
| `notification.update(id, opts)` | Update an existing toast by id (used for progress toasts) |
|
|
178
|
+
| `notification.remove(id?)` | Dismiss one toast by id, or all if id omitted |
|
|
179
|
+
| `notification.clearAll()` | Dismiss all toasts |
|
|
180
|
+
| `notification.setPosition(pos)` | Set the default toast position |
|
|
181
|
+
| `notification.clearPosition(pos)` | Dismiss all toasts at the given position |
|
|
182
|
+
| `notification.debug()` | Log active toasts and default options; returns `{ active, defaultOptions }` |
|
|
183
|
+
|
|
165
184
|
### Types
|
|
166
185
|
|
|
167
186
|
**File:** `types.ts`
|
|
168
187
|
|
|
169
|
-
| Type | Description
|
|
170
|
-
| ----------------------------- |
|
|
171
|
-
| `Severity` | `"info" \| "warning" \| "error" \| "critical"`
|
|
172
|
-
| `ToastConfig` | Toast behavior: mode, severity (static or function), timeout, isComplete, completedType
|
|
173
|
-
| `NotificationTypeConfig` | Per-type config: optional Vue `template` component, `toast` config, `groupBy` field
|
|
174
|
-
| `ModuleNotificationsConfig` | Record mapping `notifyType` strings to `NotificationTypeConfig`
|
|
175
|
-
| `NotificationAction` | Action button in notification UI: label, icon, handler, visibility
|
|
176
|
-
| `NotificationSubscription` | Internal subscriber record: id, types, filter, handler
|
|
177
|
-
| `SEVERITY_TIMEOUTS` | Default timeouts: info=5s, warning=8s, error=persistent, critical=persistent
|
|
178
|
-
| `EXCLUDED_NOTIFICATION_TYPES` | Types excluded from ingestion (e.g. `"IndexProgressPushNotification"`)
|
|
188
|
+
| Type | Description |
|
|
189
|
+
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
190
|
+
| `Severity` | `"info" \| "warning" \| "error" \| "critical"` |
|
|
191
|
+
| `ToastConfig` | Toast behavior: mode, severity (static or function), timeout, isComplete, completedType |
|
|
192
|
+
| `NotificationTypeConfig` | Per-type config: optional Vue `template` component, `toast` config, `groupBy` field |
|
|
193
|
+
| `ModuleNotificationsConfig` | Record mapping `notifyType` strings to `NotificationTypeConfig` |
|
|
194
|
+
| `NotificationAction` | Action button in notification UI: label, icon, handler, visibility |
|
|
195
|
+
| `NotificationSubscription` | Internal subscriber record: id, types, filter, handler |
|
|
196
|
+
| `SEVERITY_TIMEOUTS` | Default timeouts: info=5s, warning=8s, error=persistent, critical=persistent |
|
|
197
|
+
| `EXCLUDED_NOTIFICATION_TYPES` | Types excluded from ingestion (e.g. `"IndexProgressPushNotification"`) |
|
|
198
|
+
| `NotificationContextKey` | `InjectionKey<ComputedRef<PushNotification>>` — injection key `useNotificationContext()` reads to get the current template payload |
|
|
179
199
|
|
|
180
200
|
## Usage Examples
|
|
181
201
|
|
|
@@ -233,13 +253,13 @@ const store = useNotificationStore();
|
|
|
233
253
|
await store.loadHistory(20);
|
|
234
254
|
console.log(`${store.unreadCount.value} unread notifications`);
|
|
235
255
|
|
|
236
|
-
await store.markAllAsRead(); //
|
|
256
|
+
await store.markAllAsRead(); // flips local state immediately; server failure is logged only, no rollback
|
|
237
257
|
```
|
|
238
258
|
|
|
239
259
|
## Related
|
|
240
260
|
|
|
241
|
-
- `framework/injection-keys.ts` -- `NotificationStoreKey
|
|
242
|
-
- `framework/
|
|
261
|
+
- `framework/injection-keys.ts` -- `NotificationStoreKey`
|
|
262
|
+
- `framework/shell/components/notification-dropdown/` -- Notification dropdown UI
|
|
243
263
|
- `framework/core/api/platform.ts` -- `PushNotification`, `PushNotificationClient`
|
|
244
264
|
|
|
245
265
|
<!-- internal:start -->
|
|
@@ -49,18 +49,37 @@ app.use(aiAgentPlugin, {
|
|
|
49
49
|
|
|
50
50
|
### `IAiAgentConfig`
|
|
51
51
|
|
|
52
|
-
| Field | Type | Default | Description
|
|
53
|
-
| ---------------- | ---------- | ------------ |
|
|
54
|
-
| `url` | `string` | `""` | Chatbot iframe URL (required)
|
|
55
|
-
| `title` | `string` | `"Virto OZ"` | Panel header title
|
|
56
|
-
| `width` | `number` | `362` | Panel width in pixels
|
|
57
|
-
| `expandedWidth` | `number` | `500` | Panel width when expanded
|
|
58
|
-
| `allowedOrigins` | `string[]` | `[
|
|
52
|
+
| Field | Type | Default | Description |
|
|
53
|
+
| ---------------- | ---------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
54
|
+
| `url` | `string` | `""` | Chatbot iframe URL (required) |
|
|
55
|
+
| `title` | `string` | `"Virto OZ"` | Panel header title |
|
|
56
|
+
| `width` | `number` | `362` | Panel width in pixels |
|
|
57
|
+
| `expandedWidth` | `number` | `500` | Panel width when expanded |
|
|
58
|
+
| `allowedOrigins` | `string[]` | `[]` | Origins accepted for **incoming** postMessage; the first entry is the target origin for **outbound** messages to the chatbot iframe. Required — see below |
|
|
59
|
+
| `parentOrigin` | `string` | -- | Explicit parent origin for **outbound** embedded postMessage. Required in embedded mode — see below |
|
|
60
|
+
|
|
61
|
+
!!! danger "Origins must be configured — secure by default"
|
|
62
|
+
The bridge is locked down by default. Set both fields to explicit origins; a wildcard `"*"` or empty value is refused (the message is dropped and logged), never trusted.
|
|
63
|
+
|
|
64
|
+
- **`allowedOrigins`** governs messages the shell **accepts**, and its first entry is the target origin the shell uses to **send** `INIT_CONTEXT`/`UPDATE_CONTEXT` to the chatbot iframe. With the default `[]`, all incoming postMessages are ignored and outbound iframe messages are dropped (these carry the access token, so they are never sent to `"*"`). Set it to the chatbot's origin(s), e.g. `["https://chat.example.com"]`. A `"*"` entry is rejected outright — replace it with explicit origins.
|
|
65
|
+
- **`parentOrigin`** governs messages the shell **sends to the parent frame** in embedded mode (`AI_CONTEXT_UPDATE`, `AI_TOGGLE_PANEL`, etc.). These payloads can carry the access token, so with no explicit `parentOrigin` (or `"*"`) the outbound message is dropped. Set it to the exact host origin, e.g. `"https://host.example.com"`.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
app.use(AiAgentPlugin, {
|
|
69
|
+
config: {
|
|
70
|
+
url: "https://chat.example.com",
|
|
71
|
+
allowedOrigins: ["https://chat.example.com"], // incoming
|
|
72
|
+
parentOrigin: "https://host.example.com", // outbound (embedded mode)
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
```
|
|
59
76
|
|
|
60
77
|
### Composable: `useAiAgent()`
|
|
61
78
|
|
|
62
79
|
Access the AI agent service from any component within the app.
|
|
63
80
|
|
|
81
|
+
Returns `UseAiAgentReturn | undefined`. When `provideAiAgentService()` has not run, `useAiAgent()` logs an error and returns `undefined`, so guard the result before destructuring (e.g. `const ai = useAiAgent(); ai?.togglePanel()`).
|
|
82
|
+
|
|
64
83
|
| Return | Type | Description |
|
|
65
84
|
| ----------------- | ------------------------------------------- | ---------------------------------------------- |
|
|
66
85
|
| `panelState` | `Ref<"closed" \| "open" \| "expanded">` | Current panel state |
|
|
@@ -123,19 +142,19 @@ useAiAgentContext({ dataRef: selectedItems });
|
|
|
123
142
|
### Toggling the Panel Programmatically
|
|
124
143
|
|
|
125
144
|
```typescript
|
|
126
|
-
const
|
|
145
|
+
const ai = useAiAgent();
|
|
127
146
|
|
|
128
147
|
function onAiButtonClick() {
|
|
129
|
-
togglePanel();
|
|
148
|
+
ai?.togglePanel();
|
|
130
149
|
}
|
|
131
150
|
```
|
|
132
151
|
|
|
133
152
|
### Listening for Chatbot Messages
|
|
134
153
|
|
|
135
154
|
```typescript
|
|
136
|
-
const
|
|
155
|
+
const ai = useAiAgent();
|
|
137
156
|
|
|
138
|
-
onMessage((message) => {
|
|
157
|
+
ai?.onMessage((message) => {
|
|
139
158
|
if (message.type === "NAVIGATE_TO_APP") {
|
|
140
159
|
console.log("Chatbot wants to navigate to:", message.payload);
|
|
141
160
|
}
|
|
@@ -582,7 +582,7 @@ function defineExtensionPoint<M = Record<string, unknown>>(name: string, options
|
|
|
582
582
|
|
|
583
583
|
interface DefineExtensionPointReturn<M> {
|
|
584
584
|
/** Sorted list of registered components (by priority, ascending) */
|
|
585
|
-
components: ComputedRef<Array<ExtensionComponent & { meta?: M }>>;
|
|
585
|
+
components: ComputedRef<Array<Omit<ExtensionComponent, "meta"> & { meta?: M }>>;
|
|
586
586
|
/** True when at least one component is registered */
|
|
587
587
|
hasComponents: ComputedRef<boolean>;
|
|
588
588
|
}
|
package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md
CHANGED
|
@@ -33,7 +33,6 @@ All caught errors are parsed into human-readable messages via `parseError()` and
|
|
|
33
33
|
|
|
34
34
|
```typescript
|
|
35
35
|
// Automatic -- called by the framework during app initialization.
|
|
36
|
-
import { setupGlobalErrorHandlers } from "@vc-shell/framework";
|
|
37
36
|
setupGlobalErrorHandlers(app);
|
|
38
37
|
```
|
|
39
38
|
|
|
@@ -150,6 +149,6 @@ try {
|
|
|
150
149
|
## Related
|
|
151
150
|
|
|
152
151
|
- `framework/core/utilities/error.ts` -- `parseError()` function that extracts readable messages
|
|
153
|
-
- `framework/
|
|
152
|
+
- `framework/core/notifications/notification.ts` -- `notification.error()` toast API
|
|
154
153
|
- `framework/core/utilities/logger.ts` -- `createLogger()` for structured console logging
|
|
155
|
-
- `framework/
|
|
154
|
+
- `framework/shell/components/error-interceptor/` -- blade-level error boundary that intercepts errors before the global handler
|
|
@@ -176,12 +176,12 @@ export default defineAppModule({
|
|
|
176
176
|
|
|
177
177
|
Key differences:
|
|
178
178
|
|
|
179
|
-
| | `createAppModule`
|
|
180
|
-
| ----------------- |
|
|
181
|
-
| API style | Positional args
|
|
182
|
-
| Notifications | `notificationTemplates` (legacy)
|
|
183
|
-
| Global components | 4th arg
|
|
184
|
-
| Status | **Deprecated** -- will be removed
|
|
179
|
+
| | `createAppModule` | `defineAppModule` |
|
|
180
|
+
| ----------------- | ----------------------------------------------------------------------------------- | ---------------------------------- |
|
|
181
|
+
| API style | Positional args | Named options object |
|
|
182
|
+
| Notifications | `notificationTemplates` (legacy) | `notifications` (new typed config) |
|
|
183
|
+
| Global components | 4th arg accepted for backward compatibility but ignored (no `app.component()` call) | Not supported (use provide/inject) |
|
|
184
|
+
| Status | **Deprecated** -- will be removed | **Current** -- use this |
|
|
185
185
|
|
|
186
186
|
Migration is a one-line change:
|
|
187
187
|
|
|
@@ -278,7 +278,7 @@ defineBlade({
|
|
|
278
278
|
title: "ORDERS.MENU.TITLE", // i18n key or plain string
|
|
279
279
|
icon: "lucide-shopping-cart", // Icon name (lucide or fas)
|
|
280
280
|
priority: 1, // Lower = higher in menu
|
|
281
|
-
permissions: ["seller:orders:view"], // Optional
|
|
281
|
+
permissions: ["seller:orders:view"], // Optional fallback (used only when the blade has no permissions)
|
|
282
282
|
},
|
|
283
283
|
});
|
|
284
284
|
</script>
|
|
@@ -317,7 +317,7 @@ defineBlade({
|
|
|
317
317
|
</script>
|
|
318
318
|
```
|
|
319
319
|
|
|
320
|
-
Under the hood, `defineAppModule` calls `addMenuItem()` from `useMenuService` with:
|
|
320
|
+
Under the hood, the BladeRegistry registration function (invoked during `defineAppModule`'s install) calls `addMenuItem()` from `useMenuService` with:
|
|
321
321
|
|
|
322
322
|
```typescript
|
|
323
323
|
addMenuItem({
|
|
@@ -383,7 +383,7 @@ export default defineAppModule({
|
|
|
383
383
|
| Field | Type | Default | Description |
|
|
384
384
|
| --------------- | ---------------------------------- | ----------------- | ------------------------------------------------------------------------------------- |
|
|
385
385
|
| `mode` | `"auto" \| "progress" \| "silent"` | required | `auto` = show and auto-dismiss; `progress` = stay until complete; `silent` = no toast |
|
|
386
|
-
| `severity` | `Severity \| (msg) => Severity` | `"info"` | Toast type: `"info"`, `"
|
|
386
|
+
| `severity` | `Severity \| (msg) => Severity` | `"info"` | Toast type: `"info"`, `"warning"`, `"error"`, `"critical"` |
|
|
387
387
|
| `timeout` | `number` | varies | Auto-dismiss timeout in milliseconds |
|
|
388
388
|
| `isComplete` | `(msg) => boolean` | `msg.finished` | For `progress` mode: when to close the toast |
|
|
389
389
|
| `completedType` | `(msg) => "success" \| "error"` | `() => "success"` | For `progress` mode: final toast type |
|
|
@@ -507,7 +507,7 @@ flowchart TD
|
|
|
507
507
|
|
|
508
508
|
Non-OK manifest responses (401 / 403 / 404 / 5xx) are treated as "no plugins" — the host logs a `console.warn`, sets `modulesReady=true`, and mounts without extensions. Only network or parse failures set `modulesLoadError=true`.
|
|
509
509
|
|
|
510
|
-
See
|
|
510
|
+
See [Plugin Loading (Module Federation)](#plugin-loading-module-federation) above and the `packages/mf-host/` package for the full plugin-author + host-app walkthrough.
|
|
511
511
|
|
|
512
512
|
The host shares singleton instances of core dependencies (Vue, Vue Router, vue-i18n, @vc-shell/framework) so that remote modules use the same runtime. This is critical for reactivity, routing, and DI to work across module boundaries.
|
|
513
513
|
|
|
@@ -853,12 +853,12 @@ interface DashboardWidget {
|
|
|
853
853
|
|
|
854
854
|
**`MenuItemConfig`:**
|
|
855
855
|
|
|
856
|
-
| Field | Type | Description
|
|
857
|
-
| ------------- | ---------- |
|
|
858
|
-
| `title` | `string` | Display text or i18n key
|
|
859
|
-
| `icon` | `string` | Icon name (lucide-_ or fas fa-_)
|
|
860
|
-
| `priority` | `number` | Sort order (lower = higher in menu)
|
|
861
|
-
| `permissions` | `string[]` |
|
|
856
|
+
| Field | Type | Description |
|
|
857
|
+
| ------------- | ---------- | ---------------------------------------------------------------------------------------------------- |
|
|
858
|
+
| `title` | `string` | Display text or i18n key |
|
|
859
|
+
| `icon` | `string` | Icon name (lucide-_ or fas fa-_) |
|
|
860
|
+
| `priority` | `number` | Sort order (lower = higher in menu) |
|
|
861
|
+
| `permissions` | `string[]` | Optional fallback used only when the blade has no `permissions`; blade `permissions` take precedence |
|
|
862
862
|
|
|
863
863
|
---
|
|
864
864
|
|
|
@@ -893,13 +893,13 @@ interface ToastConfig {
|
|
|
893
893
|
|
|
894
894
|
## Related
|
|
895
895
|
|
|
896
|
-
| Resource | Path
|
|
897
|
-
| ----------------------- |
|
|
898
|
-
| Extension Points Plugin | `core/plugins/extension-points/`
|
|
899
|
-
| BladeRegistry | `core/composables/useBladeRegistry/`
|
|
900
|
-
| useMenuService | `core/composables/useMenuService/`
|
|
901
|
-
| useDashboard | `core/composables/useDashboard/`
|
|
902
|
-
| NotificationStore | `core/notifications/`
|
|
903
|
-
| i18n Plugin | `core/plugins/i18n/`
|
|
904
|
-
| mf-host | `packages/mf-host/`
|
|
905
|
-
| Blade Navigation | `
|
|
896
|
+
| Resource | Path | Description |
|
|
897
|
+
| ----------------------- | ------------------------------------ | ------------------------------------------------ |
|
|
898
|
+
| Extension Points Plugin | `core/plugins/extension-points/` | Cross-module UI extension system |
|
|
899
|
+
| BladeRegistry | `core/composables/useBladeRegistry/` | Where blades are stored and looked up |
|
|
900
|
+
| useMenuService | `core/composables/useMenuService/` | `addMenuItem()` for sidebar navigation |
|
|
901
|
+
| useDashboard | `core/composables/useDashboard/` | Dashboard widget management |
|
|
902
|
+
| NotificationStore | `core/notifications/` | Notification type registration and dispatch |
|
|
903
|
+
| i18n Plugin | `core/plugins/i18n/` | vue-i18n singleton for locale merging |
|
|
904
|
+
| mf-host | `packages/mf-host/` | Module Federation host that loads remote modules |
|
|
905
|
+
| Blade Navigation | `core/blade-navigation/` | Blade stack logic and navigation |
|
|
@@ -13,7 +13,7 @@ Permission-based access control plugin. Exposes a global `$hasAccess` helper for
|
|
|
13
13
|
|
|
14
14
|
The VirtoCommerce platform uses a role-based permission system where each user is assigned one or more roles, and each role grants a set of named permissions (e.g., `order:read`, `order:create`, `catalog:manage`). The permissions plugin bridges this system into the Vue application layer so that UI elements can be shown or hidden based on the current user's access rights.
|
|
15
15
|
|
|
16
|
-
The plugin installs the `hasAccess()` function from the `usePermissions()` composable as
|
|
16
|
+
The plugin installs the `hasAccess()` function from the `usePermissions()` composable as a Vue global property (`$hasAccess`). This means permission checks are available everywhere: in templates via `$hasAccess()` and in composition API code via `usePermissions()`.
|
|
17
17
|
|
|
18
18
|
## When to Use
|
|
19
19
|
|
|
@@ -28,14 +28,13 @@ The framework installs this plugin automatically during app setup. Module develo
|
|
|
28
28
|
```typescript
|
|
29
29
|
// Automatic -- installed by the framework during app setup.
|
|
30
30
|
// The plugin source is straightforward:
|
|
31
|
-
import { usePermissions } from "@
|
|
31
|
+
import { usePermissions } from "@vc-shell/framework";
|
|
32
32
|
import { App } from "vue";
|
|
33
33
|
|
|
34
34
|
export const permissions = {
|
|
35
35
|
install(app: App) {
|
|
36
36
|
const { hasAccess } = usePermissions();
|
|
37
37
|
app.config.globalProperties.$hasAccess = hasAccess;
|
|
38
|
-
app.provide("$hasAccess", hasAccess);
|
|
39
38
|
},
|
|
40
39
|
};
|
|
41
40
|
```
|
|
@@ -21,8 +21,8 @@ The VirtoCommerce platform uses ASP.NET SignalR to push real-time notifications
|
|
|
21
21
|
|
|
22
22
|
The SignalR plugin establishes a persistent WebSocket connection to the platform hub and listens for two event channels:
|
|
23
23
|
|
|
24
|
-
- **`Send`** --
|
|
25
|
-
- **`SendSystemEvents`** --
|
|
24
|
+
- **`Send`** -- targeted messages ingested with default routing
|
|
25
|
+
- **`SendSystemEvents`** -- ingested as broadcast (`store.ingest(message, { broadcast: true })`), no creator filtering
|
|
26
26
|
|
|
27
27
|
Incoming messages are ingested into the `NotificationStore`, which dispatches them to registered notification type handlers and triggers toast notifications based on per-type configuration.
|
|
28
28
|
|
|
@@ -32,38 +32,21 @@ The connection lifecycle is tied to the user's authentication state: it connects
|
|
|
32
32
|
|
|
33
33
|
```typescript
|
|
34
34
|
// Automatic -- installed by the framework during app setup.
|
|
35
|
-
// The
|
|
36
|
-
app.use(signalR
|
|
35
|
+
// The plugin takes no options.
|
|
36
|
+
app.use(signalR);
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Module developers do not install this plugin. It is registered once by the framework during bootstrap.
|
|
40
40
|
|
|
41
41
|
## API
|
|
42
42
|
|
|
43
|
-
### Plugin Options
|
|
44
|
-
|
|
45
|
-
| Option | Type | Description |
|
|
46
|
-
| --------- | --------------------- | -------------------------------------------------------------------------- |
|
|
47
|
-
| `creator` | `string \| undefined` | Filters `SendSystemEvents` messages to only those matching this creator ID |
|
|
48
|
-
|
|
49
43
|
### Exports
|
|
50
44
|
|
|
51
|
-
| Export
|
|
52
|
-
|
|
|
53
|
-
| `signalR`
|
|
54
|
-
| `updateSignalRCreatorSymbol` | `InjectionKey` | Injection key for the creator update function |
|
|
55
|
-
|
|
56
|
-
### Provided Injectables
|
|
57
|
-
|
|
58
|
-
| Key | Type | Description |
|
|
59
|
-
| ---------------------------- | ---------------------------------------- | --------------------------------------------- |
|
|
60
|
-
| `updateSignalRCreatorSymbol` | `(creator: string \| undefined) => void` | Updates the SignalR creator filter at runtime |
|
|
61
|
-
|
|
62
|
-
### Global Properties
|
|
45
|
+
| Export | Type | Description |
|
|
46
|
+
| --------- | -------- | ----------------------------------------- |
|
|
47
|
+
| `signalR` | `Plugin` | Vue plugin object with `install()` method |
|
|
63
48
|
|
|
64
|
-
|
|
65
|
-
| ----------------------- | ---------------------------------------- | ------------------------------------------------------------------- |
|
|
66
|
-
| `$updateSignalRCreator` | `(creator: string \| undefined) => void` | Same as the injectable, accessible via `this.$updateSignalRCreator` |
|
|
49
|
+
The plugin installs with no options: `app.use(signalR)`.
|
|
67
50
|
|
|
68
51
|
## Connection Lifecycle
|
|
69
52
|
|
|
@@ -80,7 +63,7 @@ sequenceDiagram
|
|
|
80
63
|
|
|
81
64
|
Hub-->>C: "Send" (targeted)
|
|
82
65
|
C->>Store: ingest(message)
|
|
83
|
-
Hub-->>C: "SendSystemEvents" (broadcast
|
|
66
|
+
Hub-->>C: "SendSystemEvents" (broadcast)
|
|
84
67
|
C->>Store: ingest(message, { broadcast: true })
|
|
85
68
|
|
|
86
69
|
Store->>Store: toast • subscriber callbacks • history update
|
|
@@ -98,24 +81,6 @@ sequenceDiagram
|
|
|
98
81
|
|
|
99
82
|
## Usage
|
|
100
83
|
|
|
101
|
-
### Updating the Creator Filter
|
|
102
|
-
|
|
103
|
-
After login or when switching organizations, update the creator to scope system events:
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
import { inject } from "vue";
|
|
107
|
-
import { updateSignalRCreatorSymbol } from "@vc-shell/framework";
|
|
108
|
-
|
|
109
|
-
const updateCreator = inject(updateSignalRCreatorSymbol);
|
|
110
|
-
updateCreator?.(currentUser.id);
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
Or via the global property in Options API (legacy):
|
|
114
|
-
|
|
115
|
-
```typescript
|
|
116
|
-
this.$updateSignalRCreator(currentUser.id);
|
|
117
|
-
```
|
|
118
|
-
|
|
119
84
|
### How Messages Flow
|
|
120
85
|
|
|
121
86
|
1. Platform sends a `PushNotification` via SignalR
|
|
@@ -156,13 +121,9 @@ cy.signalR("pushNotificationHub").invoke("Send", {
|
|
|
156
121
|
});
|
|
157
122
|
```
|
|
158
123
|
|
|
159
|
-
## Tip:
|
|
160
|
-
|
|
161
|
-
If your notification type should reach all connected clients regardless of who triggered it, use the `Send` channel (the platform sends it as a broadcast). For user-scoped notifications (e.g., "your export is complete"), use `SendSystemEvents` with the `creator` field set to the user's ID on the server side.
|
|
162
|
-
|
|
163
|
-
## Common Mistake
|
|
124
|
+
## Tip: Send vs. SendSystemEvents
|
|
164
125
|
|
|
165
|
-
|
|
126
|
+
Both channels ingest into the same `NotificationStore`. `Send` messages are ingested with default routing; `SendSystemEvents` messages are ingested as broadcast (`{ broadcast: true }`). The plugin does not filter either channel by a creator field -- any scoping to a specific user or organization must happen server-side before the message is pushed.
|
|
166
127
|
|
|
167
128
|
## Related
|
|
168
129
|
|