@vc-shell/framework 1.1.22 → 1.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/core/composables/useAppInsights/index.ts +11 -1
- package/core/composables/useBladeRegistry/index.ts +176 -0
- package/core/composables/useDynamicProperties/index.ts +380 -255
- package/core/composables/useErrorHandler/index.ts +2 -3
- package/core/composables/useLanguages/index.ts +78 -78
- package/core/plugins/modularity/index.ts +17 -6
- package/core/services/global-search-service/index.ts +36 -0
- package/dist/core/composables/useAppInsights/index.d.ts +5 -2
- package/dist/core/composables/useAppInsights/index.d.ts.map +1 -1
- package/dist/core/composables/useBladeRegistry/index.d.ts +48 -0
- package/dist/core/composables/useBladeRegistry/index.d.ts.map +1 -0
- package/dist/core/composables/useDynamicProperties/index.d.ts +11 -9
- package/dist/core/composables/useDynamicProperties/index.d.ts.map +1 -1
- package/dist/core/composables/useErrorHandler/index.d.ts.map +1 -1
- package/dist/core/plugins/modularity/index.d.ts.map +1 -1
- package/dist/core/services/global-search-service/index.d.ts +10 -0
- package/dist/core/services/global-search-service/index.d.ts.map +1 -0
- package/dist/framework.js +1 -1
- package/dist/{index-BQtOyLub.js → index-BLmjssqE.js} +1 -1
- package/dist/{index-C_zSZ2pX.js → index-BYcoxn-f.js} +1 -1
- package/dist/{index-wjw1DwqR.js → index-BbuBDu8A.js} +1 -1
- package/dist/{index-DqDgL4W3.js → index-BnqqEJTE.js} +1 -1
- package/dist/{index--KQZx7Nr.js → index-Br7ZwtRW.js} +1 -1
- package/dist/{index-DwjKpYAo.js → index-CGL9e-cM.js} +1 -1
- package/dist/{index-DoHQrH4a.js → index-CIzLBvgg.js} +1 -1
- package/dist/{index-DFdFt54f.js → index-CLAYu8Qj.js} +1 -1
- package/dist/{index-BxrA7EzT.js → index-CRwMOCjN.js} +1 -1
- package/dist/{index-DL0-yUXC.js → index-Cmbxdwnl.js} +1 -1
- package/dist/{index-Bf4s6An9.js → index-Cxkjjuah.js} +1 -1
- package/dist/{index-xCbUzsUb.js → index-DAnceKLv.js} +1 -1
- package/dist/{index-BAngL0ix.js → index-Dk1K3-27.js} +1 -1
- package/dist/{index-d16x5dY_.js → index-DoArZBIw.js} +1 -1
- package/dist/{index-C-y5H4_R.js → index-DvenBxy6.js} +45753 -45502
- package/dist/{index-DI3UVoln.js → index-cuex9jil.js} +1 -1
- package/dist/{index--F0eI_oT.js → index-eOG-NNYN.js} +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts +7 -12
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.d.ts +15 -0
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.d.ts.map +1 -0
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.d.ts +11 -0
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.d.ts.map +1 -0
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeState.d.ts +15 -0
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeState.d.ts.map +1 -0
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeWatchers.d.ts +6 -0
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeWatchers.d.ts.map +1 -0
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.d.ts +28 -0
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.d.ts.map +1 -0
- package/dist/shared/components/blade-navigation/plugin.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/types/index.d.ts +5 -5
- package/dist/shared/components/blade-navigation/types/index.d.ts.map +1 -1
- package/dist/shared/components/notification-template/notification-template.vue.d.ts +2 -2
- package/dist/shared/components/notification-template/notification-template.vue.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.d.ts +1 -9
- package/dist/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/index.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts +2 -18
- package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.vue.d.ts +2 -0
- package/dist/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue.d.ts.map +1 -1
- package/package.json +4 -4
- package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +199 -597
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.ts +151 -0
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.ts +243 -0
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeState.ts +93 -0
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeWatchers.ts +90 -0
- package/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.ts +150 -0
- package/shared/components/blade-navigation/plugin.ts +17 -12
- package/shared/components/blade-navigation/types/index.ts +2 -4
- package/shared/components/notification-template/notification-template.vue +2 -2
- package/shared/modules/dynamic/index.ts +2 -8
- package/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.vue +4 -0
- package/ui/components/organisms/vc-app/vc-app.vue +11 -6
- package/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue +10 -1
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
import { computed, getCurrentInstance, inject, warn, Component,
|
|
1
|
+
import { computed, getCurrentInstance, inject, warn, Component, ComputedRef } from "vue";
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
import { createSharedComposable
|
|
3
|
+
import { createSharedComposable } from "@vueuse/core";
|
|
4
4
|
import * as _ from "lodash-es";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
NavigationFailure,
|
|
9
|
-
RouteRecordName,
|
|
10
|
-
RouteParams,
|
|
11
|
-
Router,
|
|
12
|
-
LocationQuery,
|
|
13
|
-
RouteParamsGeneric,
|
|
14
|
-
RouteRecordNameGeneric,
|
|
15
|
-
} from "vue-router";
|
|
16
|
-
import { bladeNavigationInstance } from "../../plugin";
|
|
5
|
+
import { RouteLocationNormalized, useRoute, NavigationFailure, RouteLocationRaw } from "vue-router";
|
|
6
|
+
import { bladeNavigationInstance as globalBladeNavigationPluginInstanceFallback } from "../../plugin";
|
|
7
|
+
import { useBladeRegistry, IBladeRegistry } from "../../../../../core/composables/useBladeRegistry";
|
|
17
8
|
import {
|
|
18
9
|
BladeComponentInternalInstance,
|
|
19
10
|
BladeNavigationPlugin,
|
|
@@ -21,646 +12,257 @@ import {
|
|
|
21
12
|
IBladeEvent,
|
|
22
13
|
IParentCallArgs,
|
|
23
14
|
BladeInstanceConstructor,
|
|
24
|
-
|
|
25
|
-
ExtractedBladeOptions,
|
|
15
|
+
CoreBladeAdditionalSettings,
|
|
26
16
|
} from "../../types";
|
|
27
17
|
import { navigationViewLocation } from "../../../../../injection-keys";
|
|
28
18
|
import { useAppInsights, usePermissions } from "../../../../../core/composables";
|
|
29
|
-
import { notification } from "./../../../notifications";
|
|
19
|
+
import { notification as notificationService } from "./../../../notifications";
|
|
30
20
|
import "core-js/actual/array/find-last";
|
|
31
21
|
import "core-js/actual/array/find-last-index";
|
|
32
22
|
import { i18n } from "../../../../../core/plugins/i18n";
|
|
33
23
|
|
|
24
|
+
// Internal modules
|
|
25
|
+
import { _createBladeStateManagement } from "./internal/bladeState";
|
|
26
|
+
import { _createRouterUtils } from "./internal/routerUtils";
|
|
27
|
+
import { _createBladeActions } from "./internal/bladeActions";
|
|
28
|
+
import { _createBladeRouteResolver } from "./internal/bladeRouteResolver";
|
|
29
|
+
import { _createBladeWatchers } from "./internal/bladeWatchers";
|
|
30
|
+
|
|
34
31
|
interface IUseBladeNavigation {
|
|
35
32
|
readonly blades: ComputedRef<BladeVNode[]>;
|
|
36
|
-
readonly
|
|
33
|
+
readonly activeWorkspace: ComputedRef<BladeVNode | undefined>;
|
|
34
|
+
readonly currentBladeNavigationData: ComputedRef<BladeVNode["props"]["navigation"] | undefined>;
|
|
37
35
|
openBlade: <Blade extends Component>(
|
|
38
|
-
|
|
36
|
+
args: IBladeEvent<Blade>,
|
|
39
37
|
isWorkspace?: boolean,
|
|
40
38
|
) => Promise<void | NavigationFailure>;
|
|
41
39
|
closeBlade: (index: number) => Promise<boolean>;
|
|
42
|
-
goToRoot: () =>
|
|
43
|
-
name: RouteRecordNameGeneric;
|
|
44
|
-
params: RouteParamsGeneric;
|
|
45
|
-
};
|
|
40
|
+
goToRoot: () => RouteLocationRaw;
|
|
46
41
|
onParentCall: (parentExposedMethods: Record<string, any>, args: IParentCallArgs) => void;
|
|
47
42
|
onBeforeClose: (cb: () => Promise<boolean | undefined>) => void;
|
|
48
|
-
resolveBladeByName: (name: string) => BladeInstanceConstructor;
|
|
49
|
-
routeResolver: (to: RouteLocationNormalized) =>
|
|
50
|
-
| Promise<
|
|
51
|
-
| {
|
|
52
|
-
name: RouteRecordName | undefined;
|
|
53
|
-
params: RouteParams;
|
|
54
|
-
}
|
|
55
|
-
| undefined
|
|
56
|
-
>
|
|
57
|
-
| undefined;
|
|
43
|
+
resolveBladeByName: (name: string) => BladeInstanceConstructor | undefined;
|
|
44
|
+
routeResolver: (to: RouteLocationNormalized) => Promise<RouteLocationRaw | undefined> | RouteLocationRaw | undefined;
|
|
58
45
|
setNavigationQuery: (query: Record<string, string | number>) => void;
|
|
59
46
|
getNavigationQuery: () => Record<string, string | number> | undefined;
|
|
60
47
|
}
|
|
61
48
|
|
|
62
|
-
|
|
63
|
-
const mainRouteBaseParamURL = shallowRef<string>();
|
|
64
|
-
|
|
65
|
-
const utils = (router: Router) => {
|
|
66
|
-
const route = useRoute();
|
|
67
|
-
const routes = router.getRoutes();
|
|
68
|
-
|
|
69
|
-
function parseUrl(url: string) {
|
|
70
|
-
// remove parts of url that does not contain workspace, blade or param - everything before workspace
|
|
71
|
-
const parts = url.split("/");
|
|
72
|
-
const workspaceIndex = parts.findIndex((part) => {
|
|
73
|
-
const route = routes.find(
|
|
74
|
-
(r) => r.path.endsWith("/" + part) && (r.components?.default as BladeVNode)?.type?.isWorkspace,
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
return route !== undefined;
|
|
78
|
-
});
|
|
79
|
-
const cleanUrl = "/" + parts.slice(workspaceIndex).join("/");
|
|
80
|
-
|
|
81
|
-
const urlRegex = /^\/([a-zA-Z0-9_-]+)(?:\/([a-zA-Z0-9_-]+))?(?:\/([a-zA-Z0-9_-]+))?$/;
|
|
82
|
-
const match = cleanUrl.match(urlRegex);
|
|
83
|
-
|
|
84
|
-
if (!match) {
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
89
|
-
const [_, workspace, blade, param] = match;
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
workspace,
|
|
93
|
-
blade: blade || undefined,
|
|
94
|
-
param: param || undefined,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function parseWorkspaceUrl(path: string): string {
|
|
99
|
-
// Object.values(route.params)[0] will always be base path of the app
|
|
100
|
-
mainRouteBaseParamURL.value = "/" + (Object.values(route.params)?.[0] ?? "");
|
|
101
|
-
|
|
102
|
-
const pathWithoutBase = path.startsWith(mainRouteBaseParamURL.value)
|
|
103
|
-
? path.slice(mainRouteBaseParamURL.value.length)
|
|
104
|
-
: path;
|
|
105
|
-
const segments = pathWithoutBase.split("/").filter(Boolean);
|
|
106
|
-
const workspaceUrl = segments.slice(0, 1).join("/");
|
|
107
|
-
return "/" + workspaceUrl;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function getURLQuery() {
|
|
111
|
-
if (route.query && Object.keys(route.query).length) {
|
|
112
|
-
return {
|
|
113
|
-
params: new URLSearchParams(route.query as Record<string, string>).toString(),
|
|
114
|
-
obj: route.query,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const [, query] = window.location.href.split("#")[1].split("?");
|
|
119
|
-
const params = new URLSearchParams(query).toString();
|
|
120
|
-
|
|
121
|
-
return { params, obj: Object.fromEntries(new URLSearchParams(query)) };
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
parseUrl,
|
|
126
|
-
parseWorkspaceUrl,
|
|
127
|
-
getURLQuery,
|
|
128
|
-
routes,
|
|
129
|
-
};
|
|
130
|
-
};
|
|
131
|
-
|
|
49
|
+
// --- Singleton for useBladeNavigation ---
|
|
132
50
|
const useBladeNavigationSingleton = createSharedComposable(() => {
|
|
133
51
|
const route = useRoute();
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
const instance = getCurrentInstance() as BladeComponentInternalInstance;
|
|
137
|
-
const navigationInstance =
|
|
138
|
-
(instance !== null && inject<BladeNavigationPlugin>("bladeNavigationPlugin")) || bladeNavigationInstance;
|
|
139
|
-
const router = navigationInstance?.router;
|
|
140
|
-
|
|
141
|
-
const { parseUrl, parseWorkspaceUrl, getURLQuery } = utils(router);
|
|
142
|
-
|
|
143
|
-
watch(
|
|
144
|
-
() => route.path,
|
|
145
|
-
async (newVal, oldVal) => {
|
|
146
|
-
const workspaceUrl = parseWorkspaceUrl(newVal);
|
|
147
|
-
|
|
148
|
-
const wsRouteComponent = getWorkspaceRouteComponent(workspaceUrl);
|
|
149
|
-
|
|
150
|
-
if (wsRouteComponent !== undefined) {
|
|
151
|
-
if (isVNode(wsRouteComponent) && wsRouteComponent.type.isBlade) {
|
|
152
|
-
updateActiveWorkspace(wsRouteComponent);
|
|
153
|
-
} else {
|
|
154
|
-
await handleNonBladePage(oldVal);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
{ immediate: true },
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
async function handleNonBladePage(oldVal?: string) {
|
|
162
|
-
const isPrevented = await closeBlade(0);
|
|
163
|
-
if (!isPrevented) {
|
|
164
|
-
navigationInstance.blades.value = [];
|
|
165
|
-
activeWorkspace.value = undefined;
|
|
166
|
-
} else {
|
|
167
|
-
if (oldVal) router.push({ path: oldVal });
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function updateActiveWorkspace(wsRouteComponent: BladeVNode) {
|
|
172
|
-
if (wsRouteComponent.props?.navigation) {
|
|
173
|
-
wsRouteComponent.props.navigation.idx = 0;
|
|
174
|
-
}
|
|
175
|
-
navigationInstance.blades.value[0] = wsRouteComponent;
|
|
176
|
-
activeWorkspace.value = wsRouteComponent;
|
|
177
|
-
closeBlade(1);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function getWorkspaceRouteComponent(workspaceUrl: string) {
|
|
181
|
-
return (
|
|
182
|
-
(route?.matched?.[1]?.components?.default as BladeVNode) ??
|
|
183
|
-
(router.resolve({ path: workspaceUrl })?.matched?.[1]?.components?.default as BladeVNode)
|
|
184
|
-
);
|
|
185
|
-
}
|
|
52
|
+
const injectedPlugin = inject<BladeNavigationPlugin>("bladeNavigationPlugin");
|
|
53
|
+
const router = injectedPlugin?.router || globalBladeNavigationPluginInstanceFallback.router;
|
|
186
54
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
async (newVal) => {
|
|
190
|
-
const workspace = navigationInstance.blades.value[0];
|
|
191
|
-
const lastBlade = getLastItemWithUrl(newVal);
|
|
192
|
-
|
|
193
|
-
if (workspace?.type?.url) {
|
|
194
|
-
const url = constructUrl(workspace, lastBlade);
|
|
195
|
-
if (url) {
|
|
196
|
-
updateRouterHistory(url, lastBlade?.type.name);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
},
|
|
200
|
-
{ deep: true, debounce: 1 },
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
function getLastItemWithUrl(newVal: BladeVNode[]) {
|
|
204
|
-
for (let i = newVal.length - 1; i > 0; i--) {
|
|
205
|
-
if (newVal[i].type.url) {
|
|
206
|
-
return newVal[i];
|
|
207
|
-
}
|
|
208
|
-
}
|
|
55
|
+
if (!router) {
|
|
56
|
+
throw new Error("[@vc-shell/framework#useBladeNavigation] Vue Router instance is not available.");
|
|
209
57
|
}
|
|
210
58
|
|
|
211
|
-
|
|
212
|
-
const wsBladeUrl = workspace?.type.url;
|
|
213
|
-
const lastBladeUrl = lastBlade?.type.url;
|
|
214
|
-
const param = lastBlade?.props?.param;
|
|
215
|
-
const parsedWorkspaceUrl = parseUrl(wsBladeUrl || "")?.workspace;
|
|
216
|
-
|
|
217
|
-
if (lastBlade && wsBladeUrl && parsedWorkspaceUrl) {
|
|
218
|
-
return "/" + parsedWorkspaceUrl + lastBladeUrl + (param ? "/" + param : "");
|
|
219
|
-
} else {
|
|
220
|
-
return wsBladeUrl;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
59
|
+
const bladeRegistry: IBladeRegistry = useBladeRegistry();
|
|
223
60
|
|
|
224
|
-
|
|
225
|
-
|
|
61
|
+
// Base modules initialization
|
|
62
|
+
const bladeState = _createBladeStateManagement(router);
|
|
63
|
+
const routerUtils = _createRouterUtils(router, route);
|
|
226
64
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
(params ? "?" + params : "");
|
|
231
|
-
|
|
232
|
-
router.options.history.replace(fullUrl);
|
|
233
|
-
|
|
234
|
-
if (name) {
|
|
235
|
-
setupPageTracking.afterEach({ name: name, fullPath: fullUrl });
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
async function closeBlade(index: number) {
|
|
240
|
-
console.debug(`[@vc-shell/framework#useBladeNavigation] - closeBlade called.`);
|
|
65
|
+
const { setupPageTracking } = useAppInsights();
|
|
66
|
+
const { hasAccess } = usePermissions();
|
|
67
|
+
const currentInstance = getCurrentInstance() as BladeComponentInternalInstance | null;
|
|
241
68
|
|
|
242
|
-
|
|
243
|
-
|
|
69
|
+
function ensureBladeComponent<Blade extends Component>(
|
|
70
|
+
bladeInput: BladeInstanceConstructor<Blade> | { name: string } | null | undefined,
|
|
71
|
+
): BladeInstanceConstructor<Blade> {
|
|
72
|
+
if (!bladeInput) {
|
|
73
|
+
throw new Error("ensureBladeComponent: bladeInput cannot be null or undefined.");
|
|
244
74
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
let isPrevented = false;
|
|
249
|
-
for (let i = 0; i < children.length; i++) {
|
|
250
|
-
const element = children[i];
|
|
251
|
-
|
|
252
|
-
if (element.props?.navigation?.onBeforeClose) {
|
|
253
|
-
const result = await element.props.navigation.onBeforeClose();
|
|
254
|
-
|
|
255
|
-
if (result === false) {
|
|
256
|
-
isPrevented = true;
|
|
257
|
-
console.debug(`[@vc-shell/framework#useBladeNavigation] - Navigation is prevented`);
|
|
258
|
-
}
|
|
259
|
-
// we use break here to prevent running onBeforeClose for all children, cause it can be prevented by first child
|
|
260
|
-
break;
|
|
261
|
-
}
|
|
75
|
+
if (typeof bladeInput === "object" && "name" in bladeInput) {
|
|
76
|
+
if (!bladeInput.name) {
|
|
77
|
+
throw new Error("ensureBladeComponent: bladeInput.name cannot be empty when resolving by name.");
|
|
262
78
|
}
|
|
263
|
-
|
|
264
|
-
if (!
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
prevBlade.props.navigation.isVisible = true;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Clear param of table blade when closing child blade to prevent table row selection from being preserved
|
|
272
|
-
if (
|
|
273
|
-
prevBlade &&
|
|
274
|
-
prevBlade.props.navigation.idx === 0 &&
|
|
275
|
-
toValue(prevBlade.props?.param) === toValue(navigationInstance.blades.value[index]?.props?.param)
|
|
276
|
-
) {
|
|
277
|
-
prevBlade.props.param = undefined;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
navigationInstance.blades.value.splice(index);
|
|
79
|
+
const resolvedComponent = bladeRegistry.getBladeComponent(bladeInput.name);
|
|
80
|
+
if (!resolvedComponent) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`ensureBladeComponent: Failed to resolve blade by name '${bladeInput.name}' via BladeRegistry. Blade component not registered or plugin issue.`,
|
|
83
|
+
);
|
|
281
84
|
}
|
|
282
|
-
|
|
283
|
-
return isPrevented;
|
|
284
|
-
} finally {
|
|
285
|
-
console.debug(`[@vc-shell/framework#useBladeNavigation] - closeBlade finished.`);
|
|
85
|
+
return resolvedComponent as BladeInstanceConstructor<Blade>;
|
|
286
86
|
}
|
|
87
|
+
return bladeInput as BladeInstanceConstructor<Blade>;
|
|
287
88
|
}
|
|
288
89
|
|
|
289
|
-
|
|
290
|
-
navigationInstance,
|
|
90
|
+
const bladeActions = _createBladeActions(
|
|
291
91
|
router,
|
|
292
92
|
route,
|
|
293
|
-
|
|
93
|
+
bladeState,
|
|
94
|
+
routerUtils,
|
|
95
|
+
ensureBladeComponent,
|
|
96
|
+
hasAccess,
|
|
97
|
+
notificationService,
|
|
98
|
+
i18n,
|
|
294
99
|
setupPageTracking,
|
|
295
|
-
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
export function useBladeNavigation(): IUseBladeNavigation {
|
|
299
|
-
const navigationView = inject(navigationViewLocation, undefined) as BladeVNode;
|
|
300
|
-
|
|
301
|
-
const { hasAccess } = usePermissions();
|
|
302
|
-
|
|
303
|
-
const instance = getCurrentInstance() as BladeComponentInternalInstance;
|
|
304
|
-
|
|
305
|
-
const { router, route, navigationInstance, closeBlade, setupPageTracking } = useBladeNavigationSingleton();
|
|
306
|
-
|
|
307
|
-
const { parseUrl, getURLQuery, routes: routerRoutes } = utils(router);
|
|
308
|
-
const mainRoute = routerRoutes.find((r) => r.meta?.root);
|
|
309
|
-
if (!mainRoute) {
|
|
310
|
-
throw new Error("Main route not found");
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
async function openWorkspace<Blade extends Component>(
|
|
314
|
-
{ blade, param, options }: IBladeEvent<Blade>,
|
|
315
|
-
query: LocationQuery | undefined = undefined,
|
|
316
|
-
params: RouteParams = {},
|
|
317
|
-
replace = false,
|
|
318
|
-
) {
|
|
319
|
-
const createdComponent = h(
|
|
320
|
-
blade,
|
|
321
|
-
reactifyObject({
|
|
322
|
-
// param: computed(() => {
|
|
323
|
-
// const isChildWithSameParamOpened = navigationInstance.blades.value.some(
|
|
324
|
-
// (x) => x.props?.param === toValue(param),
|
|
325
|
-
// );
|
|
326
|
-
// if (isChildWithSameParamOpened) {
|
|
327
|
-
// return toValue(param);
|
|
328
|
-
// }
|
|
329
|
-
// return undefined;
|
|
330
|
-
// }) as unknown as string,
|
|
331
|
-
param,
|
|
332
|
-
options,
|
|
333
|
-
navigation: {
|
|
334
|
-
idx: 0,
|
|
335
|
-
},
|
|
336
|
-
}),
|
|
337
|
-
) as BladeVNode;
|
|
100
|
+
);
|
|
338
101
|
|
|
339
|
-
|
|
340
|
-
|
|
102
|
+
const routeResolverInstance = _createBladeRouteResolver(
|
|
103
|
+
router,
|
|
104
|
+
route,
|
|
105
|
+
bladeRegistry,
|
|
106
|
+
routerUtils,
|
|
107
|
+
bladeActions,
|
|
108
|
+
bladeState,
|
|
109
|
+
ensureBladeComponent,
|
|
110
|
+
hasAccess,
|
|
111
|
+
);
|
|
341
112
|
|
|
342
|
-
|
|
343
|
-
if (hasAccess(blade.permissions)) {
|
|
344
|
-
if (
|
|
345
|
-
hasAccess(blade.permissions) &&
|
|
346
|
-
navigationInstance.blades.value.length > 0 &&
|
|
347
|
-
navigationInstance.blades.value[0].type.url === createdComponent.type.url
|
|
348
|
-
) {
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
navigationInstance.blades.value = [createdComponent];
|
|
352
|
-
// Find the route with the matching URL and update the components.default property with the new component
|
|
353
|
-
const wsroute = routerRoutes.find((r) => r.path.endsWith(createdComponent.type?.url as string));
|
|
354
|
-
if (wsroute && wsroute.components) {
|
|
355
|
-
wsroute.components.default = createdComponent;
|
|
356
|
-
}
|
|
113
|
+
_createBladeWatchers(router, route, bladeState, routerUtils, setupPageTracking);
|
|
357
114
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
115
|
+
return {
|
|
116
|
+
blades: bladeState.blades,
|
|
117
|
+
activeWorkspace: bladeState.activeWorkspace,
|
|
118
|
+
_internal_openBlade: bladeActions.openBlade,
|
|
119
|
+
closeBlade: bladeState.removeBladesStartingFrom,
|
|
120
|
+
goToRoot: routerUtils.goToRoot,
|
|
121
|
+
routeResolver: routeResolverInstance,
|
|
122
|
+
onParentCall: async (parentExposedMethods: Record<string, any>, args: IParentCallArgs) => {
|
|
123
|
+
if (args.method && parentExposedMethods && typeof parentExposedMethods[args.method] === "function") {
|
|
124
|
+
const method = parentExposedMethods[args.method];
|
|
125
|
+
const result = await method(args.args);
|
|
126
|
+
if (typeof args.callback === "function") args.callback(result);
|
|
127
|
+
} else {
|
|
128
|
+
console.error(
|
|
129
|
+
`No such method: ${args.method}. Please, add method with name ${args.method} and use defineExpose to expose it in parent blade`,
|
|
130
|
+
);
|
|
369
131
|
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
{ blade, param, options, onOpen, onClose, replaceCurrentBlade = false }: IBladeEvent<Blade>,
|
|
378
|
-
isWorkspace = false,
|
|
379
|
-
) {
|
|
380
|
-
if (!blade) {
|
|
381
|
-
throw new Error("You should pass blade component as openBlade argument");
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
if (isWorkspace) {
|
|
385
|
-
return await openWorkspace({ blade, param, options });
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
try {
|
|
389
|
-
const instanceComponent = navigationView || activeWorkspace.value;
|
|
390
|
-
|
|
391
|
-
if (!(isVNode(instanceComponent) || activeWorkspace.value)) {
|
|
392
|
-
throw new Error("No workspace found");
|
|
132
|
+
},
|
|
133
|
+
onBeforeClose: (cb: () => Promise<boolean | undefined>) => {
|
|
134
|
+
const targetBlade = bladeState.activeWorkspace.value;
|
|
135
|
+
if (targetBlade && targetBlade.props.navigation) {
|
|
136
|
+
targetBlade.props.navigation.onBeforeClose = cb;
|
|
137
|
+
} else {
|
|
138
|
+
warn("Singleton onBeforeClose: Could not identify a target blade (e.g., active workspace).");
|
|
393
139
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
let isPrevented = false;
|
|
400
|
-
|
|
401
|
-
if (instanceComponentChild) {
|
|
402
|
-
isPrevented = await closeBlade(instanceComponentChild.props?.navigation?.idx);
|
|
140
|
+
},
|
|
141
|
+
setNavigationQuery: (query: Record<string, string | number>) => {
|
|
142
|
+
if (!currentInstance) {
|
|
143
|
+
warn("Singleton's setNavigationQuery called in a context without a component instance.");
|
|
144
|
+
return;
|
|
403
145
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
if (hasAccess(blade.permissions)) {
|
|
418
|
-
if (replaceCurrentBlade) {
|
|
419
|
-
navigationInstance.blades.value[currentBladeIdx].props.navigation.isVisible = false;
|
|
420
|
-
}
|
|
421
|
-
setupPageTracking.beforeEach({ name: bladeNode.type.name! });
|
|
422
|
-
navigationInstance.blades.value.push(bladeNode);
|
|
423
|
-
} else {
|
|
424
|
-
notification.error(i18n.global.t("PERMISSION_MESSAGES.ACCESS_RESTRICTED"), { timeout: 3000 });
|
|
425
|
-
}
|
|
146
|
+
const typeName = (currentInstance.vnode.type as CoreBladeAdditionalSettings).name?.toLowerCase();
|
|
147
|
+
if (
|
|
148
|
+
typeName &&
|
|
149
|
+
bladeState.activeWorkspace.value &&
|
|
150
|
+
bladeState.activeWorkspace.value.props.navigation?.idx === 0
|
|
151
|
+
) {
|
|
152
|
+
const namedQuery = _.mapKeys(_.mapValues(query, String), (v, k) => `${typeName}_${k}`);
|
|
153
|
+
const cleanQuery = _.omitBy(namedQuery, _.isNil);
|
|
154
|
+
router.options.history.replace(
|
|
155
|
+
decodeURIComponent(
|
|
156
|
+
`${window.location.hash.substring(1).split("?")[0]}?${new URLSearchParams(cleanQuery).toString()}`,
|
|
157
|
+
),
|
|
158
|
+
);
|
|
426
159
|
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
function findInstanceComponentIndex(instanceComponent: BladeVNode) {
|
|
433
|
-
return _.findLastIndex(navigationInstance.blades.value, (x) => _.isEqual(x.type, instanceComponent.type));
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
function createBladeNode<Blade extends Component>(args: {
|
|
437
|
-
blade: BladeInstanceConstructor<Blade>;
|
|
438
|
-
currentBladeIdx: number;
|
|
439
|
-
options: ExtractedBladeOptions<InstanceType<BladeInstanceConstructor<Blade>>["$props"], "options"> | undefined;
|
|
440
|
-
param?: string;
|
|
441
|
-
onClose?: () => void;
|
|
442
|
-
onOpen?: () => void;
|
|
443
|
-
}) {
|
|
444
|
-
const { blade, currentBladeIdx, options, param, onClose, onOpen } = args;
|
|
445
|
-
return h(
|
|
446
|
-
blade,
|
|
447
|
-
Object.assign(
|
|
448
|
-
{},
|
|
449
|
-
reactiveComputed(() => ({ options, param })),
|
|
450
|
-
{
|
|
451
|
-
navigation: {
|
|
452
|
-
onClose,
|
|
453
|
-
onOpen,
|
|
454
|
-
idx: currentBladeIdx + 1,
|
|
455
|
-
},
|
|
456
|
-
},
|
|
457
|
-
),
|
|
458
|
-
) as BladeVNode;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
async function onParentCall(parentExposedMethods: Record<string, any>, args: IParentCallArgs) {
|
|
462
|
-
console.debug(`vc-app#onParentCall({ method: ${args.method} }) called.`);
|
|
463
|
-
|
|
464
|
-
if (args.method && parentExposedMethods && typeof parentExposedMethods[args.method] === "function") {
|
|
465
|
-
const method = parentExposedMethods[args.method];
|
|
466
|
-
const result = await method(args.args);
|
|
467
|
-
|
|
468
|
-
if (typeof args.callback === "function") {
|
|
469
|
-
args.callback(result);
|
|
160
|
+
},
|
|
161
|
+
getNavigationQuery: () => {
|
|
162
|
+
if (!currentInstance) {
|
|
163
|
+
warn("Singleton's getNavigationQuery called in a context without a component instance.");
|
|
164
|
+
return undefined;
|
|
470
165
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
166
|
+
const typeName = (currentInstance.vnode.type as CoreBladeAdditionalSettings).name?.toLowerCase();
|
|
167
|
+
if (
|
|
168
|
+
typeName &&
|
|
169
|
+
bladeState.activeWorkspace.value &&
|
|
170
|
+
bladeState.activeWorkspace.value.props.navigation?.idx === 0
|
|
171
|
+
) {
|
|
172
|
+
const queryKeys = Object.keys(route.query);
|
|
173
|
+
const bladeQueryKeys = queryKeys.filter((key) => key.startsWith(typeName));
|
|
174
|
+
const namedQuery = _.mapKeys(_.pick(route.query, bladeQueryKeys), (v, k) => k.replace(`${typeName}_`, ""));
|
|
175
|
+
|
|
176
|
+
const result: Record<string, string | number> = {};
|
|
177
|
+
for (const [key, value] of Object.entries(namedQuery)) {
|
|
178
|
+
const numValue = Number(value);
|
|
179
|
+
result[key] = isNaN(numValue) ? (value as string) : numValue;
|
|
180
|
+
}
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
},
|
|
185
|
+
currentBladeNavigationData: computed(() => {
|
|
186
|
+
return bladeState.activeWorkspace.value?.props?.navigation ?? undefined;
|
|
187
|
+
}),
|
|
188
|
+
};
|
|
189
|
+
});
|
|
481
190
|
|
|
482
|
-
|
|
191
|
+
export function useBladeNavigation(): IUseBladeNavigation {
|
|
192
|
+
const singleton = useBladeNavigationSingleton() as typeof useBladeNavigationSingleton extends () => infer R
|
|
193
|
+
? R
|
|
194
|
+
: never;
|
|
195
|
+
const currentCallingInstance = getCurrentInstance() as BladeComponentInternalInstance | null;
|
|
196
|
+
const bladeRegistry = useBladeRegistry();
|
|
197
|
+
|
|
198
|
+
const currentBladeNavigationData = computed(() => {
|
|
199
|
+
if (!currentCallingInstance) return undefined;
|
|
200
|
+
const viewNode = (currentCallingInstance as any).provides[navigationViewLocation as any] as BladeVNode | undefined;
|
|
201
|
+
if (
|
|
202
|
+
!viewNode &&
|
|
203
|
+
singleton.activeWorkspace.value &&
|
|
204
|
+
currentCallingInstance.vnode &&
|
|
205
|
+
_.isEqual(currentCallingInstance.vnode.type, singleton.activeWorkspace.value.type)
|
|
206
|
+
) {
|
|
207
|
+
return singleton.activeWorkspace.value.props?.navigation;
|
|
483
208
|
}
|
|
209
|
+
return viewNode?.props?.navigation;
|
|
210
|
+
});
|
|
484
211
|
|
|
485
|
-
|
|
486
|
-
|
|
212
|
+
const onBeforeClose = (cb: () => Promise<boolean | undefined>) => {
|
|
213
|
+
if (!currentCallingInstance) {
|
|
214
|
+
warn("onBeforeClose called outside of a component setup context.");
|
|
215
|
+
return;
|
|
487
216
|
}
|
|
488
|
-
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
217
|
+
const viewNode = (currentCallingInstance as any).provides[navigationViewLocation as any] as BladeVNode | undefined;
|
|
218
|
+
const targetBlade = singleton.blades.value.find(
|
|
219
|
+
(b) =>
|
|
220
|
+
(b && viewNode && _.isEqual(b, viewNode)) ||
|
|
221
|
+
(b &&
|
|
222
|
+
b.props?.navigation?.idx === 0 &&
|
|
223
|
+
currentCallingInstance.vnode &&
|
|
224
|
+
_.isEqual(b.type, currentCallingInstance.vnode.type)),
|
|
225
|
+
);
|
|
226
|
+
if (targetBlade && targetBlade.props.navigation) {
|
|
227
|
+
targetBlade.props.navigation.onBeforeClose = cb;
|
|
492
228
|
} else {
|
|
493
|
-
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
function routeResolver(to: RouteLocationNormalized) {
|
|
498
|
-
if (!hasNecessaryRoute(to)) {
|
|
499
|
-
return generateRoute(to, navigationInstance.internalRoutes);
|
|
229
|
+
warn("Context-specific onBeforeClose: Could not identify the target blade in the global list.");
|
|
500
230
|
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
function hasNecessaryRoute(to: RouteLocationNormalized) {
|
|
504
|
-
return routerRoutes.find((route) => route.path === to.path);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
/**
|
|
508
|
-
* Generates and handles navigation for dynamic routes based on the provided route information.
|
|
509
|
-
*
|
|
510
|
-
* Supports App component URLs with variable like '/:userId?'.
|
|
511
|
-
* @link https://router.vuejs.org/guide/essentials/dynamic-matching.html
|
|
512
|
-
*
|
|
513
|
-
* @param to - The target route.
|
|
514
|
-
* @param routes - The array of BladeRoutesRecord containing the registered routes.
|
|
515
|
-
*/
|
|
516
|
-
async function generateRoute(to: RouteLocationNormalized, routes: BladeRoutesRecord[]) {
|
|
517
|
-
// Extract parameters excluding "pathMatch". This is necessary if a variable is used as the App component URL, for example, /:userId?
|
|
518
|
-
const params = Object.fromEntries(Object.entries(to.params).filter(([key]) => key !== "pathMatch"));
|
|
519
|
-
|
|
520
|
-
// Get the raw path of the main route.
|
|
521
|
-
const parentRawPath = routerRoutes.find((route) => route.name === mainRoute?.name)?.path;
|
|
522
|
-
|
|
523
|
-
// Determine the parent path based on the parameters.
|
|
524
|
-
const parentPath =
|
|
525
|
-
parentRawPath && parentRawPath.includes(Object.keys(params)[0]) ? `/${Object.values(params)[0]}` : "";
|
|
526
|
-
|
|
527
|
-
// Set the base param value.
|
|
528
|
-
mainRouteBaseParamURL.value = parentPath;
|
|
529
|
-
|
|
530
|
-
// Parse the URL to extract relevant route information.
|
|
531
|
-
const parsedRoutes = parseUrl(parentPath !== "/" ? to.path.slice(parentPath.length) : to.path);
|
|
532
|
-
|
|
533
|
-
if (parsedRoutes !== undefined) {
|
|
534
|
-
const { workspace, blade, param } = parsedRoutes;
|
|
535
|
-
|
|
536
|
-
// Find the registered route component.
|
|
537
|
-
const registeredWorkspaceComponent = routes.find((route) => route.route === `/${workspace}`)?.component;
|
|
538
|
-
const registeredRouteComponent = routes.find((route) => route.route === `/${blade}`)?.component;
|
|
231
|
+
};
|
|
539
232
|
|
|
540
|
-
|
|
541
|
-
|
|
233
|
+
return {
|
|
234
|
+
blades: singleton.blades,
|
|
235
|
+
activeWorkspace: singleton.activeWorkspace,
|
|
236
|
+
openBlade: <Blade extends Component>(
|
|
237
|
+
args: IBladeEvent<Blade>,
|
|
238
|
+
isWorkspace?: boolean,
|
|
239
|
+
): Promise<void | NavigationFailure> => {
|
|
240
|
+
let sourceBladeInstanceForOpening: BladeVNode | undefined = undefined;
|
|
241
|
+
if (currentCallingInstance) {
|
|
242
|
+
sourceBladeInstanceForOpening = (currentCallingInstance as any).provides[navigationViewLocation as any] as
|
|
243
|
+
| BladeVNode
|
|
244
|
+
| undefined;
|
|
542
245
|
}
|
|
543
246
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
await openWorkspace(
|
|
547
|
-
{
|
|
548
|
-
blade: registeredRouteComponent as unknown as BladeInstanceConstructor,
|
|
549
|
-
},
|
|
550
|
-
undefined,
|
|
551
|
-
undefined,
|
|
552
|
-
true,
|
|
553
|
-
);
|
|
554
|
-
return { name: registeredRouteComponent?.type.name, params };
|
|
247
|
+
if (!sourceBladeInstanceForOpening) {
|
|
248
|
+
sourceBladeInstanceForOpening = singleton.activeWorkspace.value;
|
|
555
249
|
}
|
|
556
250
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
param: computed(() => {
|
|
563
|
-
if (registeredRouteComponent?.type.moduleUid === registeredWorkspaceComponent.type.moduleUid) {
|
|
564
|
-
return param;
|
|
565
|
-
}
|
|
566
|
-
return undefined;
|
|
567
|
-
}) as unknown as string,
|
|
568
|
-
}),
|
|
569
|
-
getURLQuery().obj,
|
|
570
|
-
params,
|
|
571
|
-
true,
|
|
572
|
-
);
|
|
573
|
-
|
|
574
|
-
// Open the route if it's routable.
|
|
575
|
-
if (
|
|
576
|
-
registeredRouteComponent?.type.routable &&
|
|
577
|
-
registeredWorkspaceComponent.type.moduleUid === registeredRouteComponent.type.moduleUid
|
|
578
|
-
) {
|
|
579
|
-
await openBlade({
|
|
580
|
-
blade: registeredRouteComponent as unknown as BladeInstanceConstructor,
|
|
581
|
-
param: param,
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
return { name: registeredWorkspaceComponent?.type.name, params, query: to.query };
|
|
586
|
-
}
|
|
587
|
-
} else {
|
|
588
|
-
return goToRoot();
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
function goToRoot() {
|
|
593
|
-
const mainRoute = routerRoutes.find((route) => route.meta?.root);
|
|
594
|
-
const mainRouteAlias = routerRoutes.find((route) => route.aliasOf?.path === mainRoute?.path) || mainRoute;
|
|
595
|
-
return { name: mainRouteAlias?.name, params: route.params };
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
const currentBladeNavigationData = computed(() => navigationView?.props?.navigation ?? undefined);
|
|
599
|
-
|
|
600
|
-
function onBeforeClose(cb: () => Promise<boolean | undefined>) {
|
|
601
|
-
const instanceComponent = navigationView;
|
|
602
|
-
|
|
603
|
-
const currentBlade = navigationInstance.blades.value.find((x: any) => _.isEqual(x, instanceComponent));
|
|
604
|
-
|
|
605
|
-
if (currentBlade) {
|
|
606
|
-
currentBlade.props.navigation.onBeforeClose = cb;
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
function setNavigationQuery(query: Record<string, string | number>) {
|
|
611
|
-
const typeName = instance.vnode.type.name?.toLowerCase();
|
|
612
|
-
if (typeName && instance.vnode.props.navigation.idx === 0) {
|
|
613
|
-
// add blade name to query keys
|
|
614
|
-
const namedQuery = _.mapKeys(
|
|
615
|
-
_.mapValues(query, (value) => value?.toString()),
|
|
616
|
-
(value, key) => typeName + "_" + key,
|
|
617
|
-
);
|
|
618
|
-
const cleanQuery = _.omitBy(namedQuery, _.isNil);
|
|
619
|
-
|
|
620
|
-
router.options.history.replace(
|
|
621
|
-
decodeURIComponent(
|
|
622
|
-
`${window.location.hash.substring(1).split("?")[0]}?${new URLSearchParams(cleanQuery).toString()}`,
|
|
623
|
-
),
|
|
624
|
-
);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
function getNavigationQuery() {
|
|
629
|
-
const typeName = instance.vnode.type.name?.toLowerCase();
|
|
630
|
-
if (typeName && instance.vnode.props.navigation.idx === 0) {
|
|
631
|
-
const queryKeys = Array.from(Object.keys(route.query));
|
|
632
|
-
const bladeQueryKeys = queryKeys.filter((key) => key.startsWith(typeName));
|
|
633
|
-
|
|
634
|
-
const namedQuery = _.mapKeys(_.pick(route.query, bladeQueryKeys), (value, key) =>
|
|
635
|
-
key.replace(typeName + "_", ""),
|
|
636
|
-
) as Record<string, string | number>;
|
|
637
|
-
|
|
638
|
-
const obj: typeof namedQuery = {};
|
|
639
|
-
for (const [key, value] of Object.entries(namedQuery)) {
|
|
640
|
-
const numValue = Number(value);
|
|
641
|
-
|
|
642
|
-
if (!isNaN(numValue)) {
|
|
643
|
-
obj[key] = numValue;
|
|
644
|
-
} else {
|
|
645
|
-
obj[key] = value;
|
|
646
|
-
}
|
|
251
|
+
if (typeof singleton._internal_openBlade === "function") {
|
|
252
|
+
return singleton._internal_openBlade(args, isWorkspace, sourceBladeInstanceForOpening);
|
|
253
|
+
} else {
|
|
254
|
+
console.error("Internal _internal_openBlade method not found on singleton.");
|
|
255
|
+
return Promise.reject(new Error("Blade navigation internal error."));
|
|
647
256
|
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
blades: computed(() => navigationInstance.blades.value),
|
|
655
|
-
openBlade,
|
|
656
|
-
closeBlade,
|
|
657
|
-
goToRoot,
|
|
658
|
-
onParentCall,
|
|
659
|
-
resolveBladeByName,
|
|
660
|
-
routeResolver,
|
|
257
|
+
},
|
|
258
|
+
closeBlade: singleton.closeBlade,
|
|
259
|
+
goToRoot: singleton.goToRoot,
|
|
260
|
+
onParentCall: singleton.onParentCall,
|
|
261
|
+
resolveBladeByName: (name: string) => bladeRegistry.getBladeComponent(name),
|
|
262
|
+
routeResolver: singleton.routeResolver,
|
|
661
263
|
currentBladeNavigationData,
|
|
662
264
|
onBeforeClose,
|
|
663
|
-
setNavigationQuery,
|
|
664
|
-
getNavigationQuery,
|
|
265
|
+
setNavigationQuery: singleton.setNavigationQuery,
|
|
266
|
+
getNavigationQuery: singleton.getNavigationQuery,
|
|
665
267
|
};
|
|
666
268
|
}
|