@vc-shell/vc-app-skill 2.1.0 → 2.2.0-pr260.a8bd3a7
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/VERSION +1 -1
- package/runtime/agents/migration-agent.md +4 -2
- package/runtime/knowledge/docs/_BUILD_HASH.md +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/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 +1 -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 +1 -2
- package/runtime/knowledge/docs/core/notifications/composables/useBroadcastFilter.docs.md +3 -3
- package/runtime/knowledge/docs/core/notifications/composables/useNotificationStore.docs.md +19 -18
- 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 +7 -7
- 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/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} +24 -27
- 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 +509 -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 +3 -3
- package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +4 -4
- package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +2 -3
- package/runtime/knowledge/migration-prompts/table-url-state-migration.md +221 -0
- package/runtime/vc-app.md +1 -0
|
@@ -25,7 +25,7 @@ Unlike a standalone loading component, `v-loading` scopes the overlay to the ele
|
|
|
25
25
|
| ----------------------- | ---------------- | ------------------------------------ |
|
|
26
26
|
| `v-loading="true"` | `boolean` | Show/hide the loading overlay |
|
|
27
27
|
| `v-loading="options"` | `LoadingOptions` | Show with configuration (see below) |
|
|
28
|
-
| `v-loading:1000="true"` | `arg: string` | Set custom z-index (default: `
|
|
28
|
+
| `v-loading:1000="true"` | `arg: string` | Set custom z-index (default: `9000`) |
|
|
29
29
|
|
|
30
30
|
### LoadingOptions
|
|
31
31
|
|
|
@@ -108,7 +108,7 @@ async function loadOrder() {
|
|
|
108
108
|
<!-- Use a lower z-index so popups can render above the spinner -->
|
|
109
109
|
<div v-loading:500="isLoading">Content</div>
|
|
110
110
|
|
|
111
|
-
<!-- Default z-index is
|
|
111
|
+
<!-- Default z-index is 9000 -->
|
|
112
112
|
<div v-loading="isLoading">Content</div>
|
|
113
113
|
</template>
|
|
114
114
|
```
|
|
@@ -180,5 +180,4 @@ If you call the composable from a manually managed `effectScope()`, the cleanup
|
|
|
180
180
|
- [useNotificationStore](./useNotificationStore.md) — direct store access for app-shell features (dropdown, badge).
|
|
181
181
|
- [useNotificationContext](./useNotificationContext.md) — read the current notification inside a custom template.
|
|
182
182
|
- [useBroadcastFilter](./useBroadcastFilter.md) — control which `SendSystemEvents` broadcasts reach the store.
|
|
183
|
-
- [Notifications
|
|
184
|
-
- [Notifications plugin reference.](../../plugins/notifications.md)
|
|
183
|
+
- [Notifications overview.](../notifications.md)
|
|
@@ -13,7 +13,7 @@ This is the standard mechanism for scoping a multi-tenant app — show a seller
|
|
|
13
13
|
## When to use
|
|
14
14
|
|
|
15
15
|
- Multi-tenant apps where the same broadcast topic carries events for different tenants (sellers, organizations, departments) and each user should only see their slice.
|
|
16
|
-
- Apps that want to drop noisy
|
|
16
|
+
- Apps that want to drop noisy maintenance broadcasts for non-admin roles. (Note: `IndexProgressPushNotification` is already globally dropped via `EXCLUDED_NOTIFICATION_TYPES` and needs no filter.)
|
|
17
17
|
- When NOT to use: filtering targeted notifications. The platform already delivers `Send` messages only to the addressed user; `useBroadcastFilter` does not see them.
|
|
18
18
|
|
|
19
19
|
## Quick Start
|
|
@@ -92,7 +92,7 @@ If the app supports user switching without a full reload (impersonation, multi-a
|
|
|
92
92
|
### Drop a noisy type entirely
|
|
93
93
|
|
|
94
94
|
```ts
|
|
95
|
-
setBroadcastFilter((msg) => msg.notifyType !== "
|
|
95
|
+
setBroadcastFilter((msg) => msg.notifyType !== "BulkActionPushNotification");
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
Broadcast-only suppression. To suppress targeted messages too, set `toast: false` or `toast: { mode: "silent" }` on the type's `defineAppModule({ notifications })` config — that controls the toast surface; the history still records the event.
|
|
@@ -107,7 +107,7 @@ Broadcast-only suppression. To suppress targeted messages too, set `toast: false
|
|
|
107
107
|
## Tips
|
|
108
108
|
|
|
109
109
|
- **Install once, early.** Setting the filter in `App.vue` `onMounted` (after authentication) is the canonical placement, so messages arriving before the first blade mounts are already scoped.
|
|
110
|
-
- **
|
|
110
|
+
- **A throwing predicate is not caught.** `ingest` calls the filter without a try/catch, so an exception propagates up through ingestion — it is not logged and the message is not silently dropped. Guard field access inside the predicate (e.g. optional chaining) when reading potentially missing fields.
|
|
111
111
|
- **Do not query the store from inside the filter.** The store is `useBroadcastFilter`'s parent — calling back into it during ingestion causes re-entrancy.
|
|
112
112
|
|
|
113
113
|
## Related
|
|
@@ -34,22 +34,22 @@ await store.loadHistory(50);
|
|
|
34
34
|
|
|
35
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
36
|
|
|
37
|
-
| Member | Type | Description
|
|
38
|
-
| ------------------------ | ------------------------------------------------------ |
|
|
39
|
-
| `registry` | `Map<string, NotificationTypeConfig>` | Notification types registered through `defineAppModule({ notifications })`.
|
|
40
|
-
| `history` | `Ref<PushNotification[]>` | Full history
|
|
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
|
|
49
|
-
| `markAllAsRead()` | `() => Promise<void>` |
|
|
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`.
|
|
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
53
|
|
|
54
54
|
## Escape-hatch patterns
|
|
55
55
|
|
|
@@ -100,9 +100,10 @@ The fallback exists so module-federation remotes and standalone scripts see the
|
|
|
100
100
|
|
|
101
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
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
|
|
104
|
-
- **`markAllAsRead`
|
|
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
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.
|
|
106
107
|
|
|
107
108
|
## Related
|
|
108
109
|
|
|
@@ -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
|
|