@vc-shell/framework 1.0.190 → 1.0.192
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 +23 -0
- package/core/plugins/modularity/index.ts +9 -2
- package/dist/core/plugins/modularity/index.d.ts.map +1 -1
- package/dist/framework.js +11960 -11881
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts +5 -2
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/types/index.d.ts +0 -1
- package/dist/shared/components/blade-navigation/types/index.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/composables/useFilterBuilder/index.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 +8 -9
- package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts +1 -0
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
- package/package.json +4 -4
- package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +235 -191
- package/shared/components/blade-navigation/plugin.ts +1 -1
- package/shared/components/blade-navigation/types/index.ts +0 -1
- package/shared/modules/dynamic/composables/useFilterBuilder/index.ts +6 -3
- package/shared/modules/dynamic/index.ts +5 -0
- package/shared/modules/dynamic/pages/dynamic-blade-form.vue +4 -1
- package/shared/modules/dynamic/pages/dynamic-blade-list.vue +5 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue +4 -15
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue +2 -0
- package/ui/components/organisms/vc-app/vc-app.vue +8 -1
- package/ui/components/organisms/vc-table/vc-table.vue +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vc-app-menu-link.vue.d.ts","sourceRoot":"","sources":["../../../../../../../../../../ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AAIjE,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"vc-app-menu-link.vue.d.ts","sourceRoot":"","sources":["../../../../../../../../../../ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AAIjE,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;CAC3C;;;;;;;;;;;;AAyND,wBAOG;AACH,KAAK,sBAAsB,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;AACjE,KAAK,6BAA6B,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE;CAAE,CAAC;AAC9M,KAAK,kBAAkB,CAAC,CAAC,EAAE,CAAC,IAAI;KAE1B,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;QACxE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;KACb,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACT,CAAC;AACN,KAAK,cAAc,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vc-app-menu-item.vue.d.ts","sourceRoot":"","sources":["../../../../../../../../../ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAE9D,MAAM,WAAW,KAAK;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;CACzC;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"vc-app-menu-item.vue.d.ts","sourceRoot":"","sources":["../../../../../../../../../ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAE9D,MAAM,WAAW,KAAK;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;CACzC;;;;;;;;;;;;;;;;;AA8HD,wBAOG;AACH,KAAK,sBAAsB,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;AACjE,KAAK,6BAA6B,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE;CAAE,CAAC;AAC9M,KAAK,kBAAkB,CAAC,CAAC,EAAE,CAAC,IAAI;KAE1B,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;QACxE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;KACb,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACT,CAAC;AACN,KAAK,cAAc,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vc-app.vue.d.ts","sourceRoot":"","sources":["../../../../../ui/components/organisms/vc-app/vc-app.vue.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"vc-app.vue.d.ts","sourceRoot":"","sources":["../../../../../ui/components/organisms/vc-app/vc-app.vue.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0cD,wBAAwG;AACxG,KAAK,sBAAsB,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;AACjE,KAAK,6BAA6B,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE;CAAE,CAAC;AAC9M,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAAE,QAAO;QAClD,MAAM,EAAE,CAAC,CAAC;KACT,CAAA;CAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vc-shell/framework",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.192",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/framework.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -59,9 +59,9 @@
|
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@types/dompurify": "^3.0.5",
|
|
61
61
|
"@types/quill": "^2.0.14",
|
|
62
|
-
"@vc-shell/api-client-generator": "^1.0.
|
|
63
|
-
"@vc-shell/config-generator": "^1.0.
|
|
64
|
-
"@vc-shell/ts-config": "^1.0.
|
|
62
|
+
"@vc-shell/api-client-generator": "^1.0.192",
|
|
63
|
+
"@vc-shell/config-generator": "^1.0.192",
|
|
64
|
+
"@vc-shell/ts-config": "^1.0.192",
|
|
65
65
|
"@vitejs/plugin-vue": "^5.0.3",
|
|
66
66
|
"sass": "^1.69.6",
|
|
67
67
|
"shx": "^0.3.4",
|
|
@@ -10,11 +10,12 @@ import {
|
|
|
10
10
|
h,
|
|
11
11
|
shallowRef,
|
|
12
12
|
ComputedRef,
|
|
13
|
+
mergeProps,
|
|
13
14
|
} from "vue";
|
|
14
15
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
15
|
-
import { createSharedComposable, reactiveComputed } from "@vueuse/core";
|
|
16
|
+
import { createSharedComposable, reactiveComputed, toValue, watchDebounced } from "@vueuse/core";
|
|
16
17
|
import * as _ from "lodash-es";
|
|
17
|
-
import { RouteLocationNormalized, useRoute, NavigationFailure } from "vue-router";
|
|
18
|
+
import { RouteLocationNormalized, useRoute, NavigationFailure, RouteRecordName, RouteParams, Router } from "vue-router";
|
|
18
19
|
import { bladeNavigationInstance } from "../../plugin";
|
|
19
20
|
import {
|
|
20
21
|
BladeComponentInternalInstance,
|
|
@@ -24,6 +25,7 @@ import {
|
|
|
24
25
|
IParentCallArgs,
|
|
25
26
|
BladeInstanceConstructor,
|
|
26
27
|
BladeRoutesRecord,
|
|
28
|
+
ExtractedBladeOptions,
|
|
27
29
|
} from "../../types";
|
|
28
30
|
import { navigationViewLocation } from "../../injectionKeys";
|
|
29
31
|
import { usePermissions } from "../../../../../core/composables";
|
|
@@ -43,30 +45,66 @@ interface IUseBladeNavigation {
|
|
|
43
45
|
onParentCall: (parentExposedMethods: Record<string, any>, args: IParentCallArgs) => void;
|
|
44
46
|
onBeforeClose: (cb: () => Promise<boolean | undefined>) => void;
|
|
45
47
|
resolveBladeByName: (name: string) => BladeInstanceConstructor;
|
|
46
|
-
routeResolver: (to: RouteLocationNormalized) =>
|
|
48
|
+
routeResolver: (to: RouteLocationNormalized) =>
|
|
49
|
+
| Promise<
|
|
50
|
+
| {
|
|
51
|
+
name: RouteRecordName | undefined;
|
|
52
|
+
params: RouteParams;
|
|
53
|
+
}
|
|
54
|
+
| undefined
|
|
55
|
+
>
|
|
56
|
+
| undefined;
|
|
47
57
|
getCurrentBlade: () => BladeVNode;
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
const activeWorkspace = shallowRef<BladeVNode>();
|
|
51
61
|
const mainRouteBaseParamURL = shallowRef<string>();
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
63
|
+
const utils = (router: Router) => {
|
|
64
|
+
const route = useRoute();
|
|
65
|
+
|
|
66
|
+
function parseUrl(url: string) {
|
|
67
|
+
// remove parts of url that does not contain workspace, blade or param - everything before workspace
|
|
68
|
+
const parts = url.split("/");
|
|
69
|
+
const workspaceIndex = parts.findIndex((part) => {
|
|
70
|
+
const route = router
|
|
71
|
+
.getRoutes()
|
|
72
|
+
.find((r) => r.path.endsWith("/" + part) && (r.components?.default as BladeVNode).type.isWorkspace);
|
|
73
|
+
|
|
74
|
+
return route !== undefined;
|
|
75
|
+
});
|
|
76
|
+
const cleanUrl = "/" + parts.slice(workspaceIndex).join("/");
|
|
77
|
+
|
|
78
|
+
const urlRegex = /^\/([a-zA-Z0-9_-]+)(?:\/([a-zA-Z0-9_-]+))?(?:\/([a-zA-Z0-9_-]+))?$/;
|
|
79
|
+
const match = cleanUrl.match(urlRegex);
|
|
56
80
|
|
|
57
|
-
|
|
58
|
-
|
|
81
|
+
if (!match) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
86
|
+
const [_, workspace, blade, param] = match;
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
workspace,
|
|
90
|
+
blade: blade || undefined,
|
|
91
|
+
param: param || undefined,
|
|
92
|
+
};
|
|
59
93
|
}
|
|
60
94
|
|
|
61
|
-
|
|
62
|
-
|
|
95
|
+
function parseWorkspaceUrl(path: string): string {
|
|
96
|
+
const basePath = "/" + (Object.values(route.params)?.[0] ?? "");
|
|
97
|
+
const pathWithoutBase = path.startsWith(basePath) ? path.slice(basePath.length) : path;
|
|
98
|
+
const segments = pathWithoutBase.split("/").filter(Boolean);
|
|
99
|
+
const workspaceUrl = segments.slice(0, 1).join("/");
|
|
100
|
+
return "/" + workspaceUrl;
|
|
101
|
+
}
|
|
63
102
|
|
|
64
103
|
return {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
param: param || undefined,
|
|
104
|
+
parseUrl,
|
|
105
|
+
parseWorkspaceUrl,
|
|
68
106
|
};
|
|
69
|
-
}
|
|
107
|
+
};
|
|
70
108
|
|
|
71
109
|
const useBladeNavigationSingleton = createSharedComposable(() => {
|
|
72
110
|
const route = useRoute();
|
|
@@ -76,94 +114,100 @@ const useBladeNavigationSingleton = createSharedComposable(() => {
|
|
|
76
114
|
(instance !== null && inject<BladeNavigationPlugin>("bladeNavigationPlugin")) || bladeNavigationInstance;
|
|
77
115
|
const router = navigationInstance?.router;
|
|
78
116
|
|
|
79
|
-
|
|
80
|
-
// Object.values(route.params)[0] will always be base path of the app
|
|
81
|
-
if (!mainRouteBaseParamURL.value) {
|
|
82
|
-
mainRouteBaseParamURL.value = "/" + (Object.values(route.params)?.[0] ?? "");
|
|
83
|
-
}
|
|
84
|
-
const pathWithoutBase = path.startsWith(mainRouteBaseParamURL.value)
|
|
85
|
-
? path.slice(mainRouteBaseParamURL.value.length)
|
|
86
|
-
: path;
|
|
87
|
-
const segments = pathWithoutBase.split("/").filter(Boolean);
|
|
88
|
-
const workspaceUrl = segments.slice(0, 1).join("/");
|
|
89
|
-
return "/" + workspaceUrl;
|
|
90
|
-
}
|
|
117
|
+
const { parseUrl, parseWorkspaceUrl } = utils(router);
|
|
91
118
|
|
|
92
|
-
|
|
119
|
+
watchDebounced(
|
|
93
120
|
() => route.path,
|
|
94
121
|
async (newVal, oldVal) => {
|
|
95
122
|
const workspaceUrl = parseWorkspaceUrl(newVal);
|
|
96
123
|
|
|
97
|
-
const wsRouteComponent =
|
|
98
|
-
(route?.matched?.[1]?.components?.default as BladeVNode) ??
|
|
99
|
-
(router.resolve({ path: workspaceUrl })?.matched?.[1]?.components?.default as BladeVNode);
|
|
124
|
+
const wsRouteComponent = getWorkspaceRouteComponent(workspaceUrl);
|
|
100
125
|
|
|
101
126
|
if (wsRouteComponent !== undefined) {
|
|
102
127
|
if (isVNode(wsRouteComponent) && wsRouteComponent.type.isBlade) {
|
|
103
|
-
|
|
104
|
-
navigationInstance.blades.value[0] = markRaw(wsRouteComponent);
|
|
105
|
-
activeWorkspace.value = wsRouteComponent;
|
|
128
|
+
updateActiveWorkspace(wsRouteComponent);
|
|
106
129
|
} else {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (!isPrevented) {
|
|
110
|
-
// add not blade page to blades array to show simple routes as
|
|
111
|
-
// we use only one router-view for all routes
|
|
112
|
-
navigationInstance.blades.value = [];
|
|
113
|
-
} else {
|
|
114
|
-
if (oldVal) router.replace({ path: oldVal });
|
|
115
|
-
}
|
|
130
|
+
await handleNonBladePage(oldVal);
|
|
116
131
|
}
|
|
117
132
|
}
|
|
118
133
|
},
|
|
119
134
|
{ immediate: true },
|
|
120
135
|
);
|
|
121
136
|
|
|
122
|
-
|
|
137
|
+
async function handleNonBladePage(oldVal?: string) {
|
|
138
|
+
const isPrevented = await closeBlade(0);
|
|
139
|
+
if (!isPrevented) {
|
|
140
|
+
navigationInstance.blades.value = [];
|
|
141
|
+
activeWorkspace.value = undefined;
|
|
142
|
+
} else {
|
|
143
|
+
if (oldVal) router.replace({ path: oldVal });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function updateActiveWorkspace(wsRouteComponent: BladeVNode) {
|
|
148
|
+
navigationInstance.blades.value[0] = markRaw(
|
|
149
|
+
Object.assign(wsRouteComponent, {
|
|
150
|
+
props: mergeProps(wsRouteComponent.props, {
|
|
151
|
+
navigation: {
|
|
152
|
+
idx: 0,
|
|
153
|
+
},
|
|
154
|
+
}),
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
activeWorkspace.value = wsRouteComponent;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function getWorkspaceRouteComponent(workspaceUrl: string) {
|
|
161
|
+
return (
|
|
162
|
+
(route?.matched?.[1]?.components?.default as BladeVNode) ??
|
|
163
|
+
(router.resolve({ path: workspaceUrl })?.matched?.[1]?.components?.default as BladeVNode)
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
watchDebounced(
|
|
123
168
|
navigationInstance.blades,
|
|
124
|
-
(newVal) => {
|
|
169
|
+
async (newVal) => {
|
|
125
170
|
const workspace = navigationInstance.blades.value[0];
|
|
126
|
-
|
|
127
|
-
// method that checks if last item in newVal array has url and returns item. If it has no url - it returns previous item with url, but not first item from array as it's workspace
|
|
128
|
-
const getLastItemWithUrl = () => {
|
|
129
|
-
// Find the previous item with a URL
|
|
130
|
-
for (let i = newVal.length - 1; i > 0; i--) {
|
|
131
|
-
if (newVal[i].type.url) {
|
|
132
|
-
return newVal[i]; // return the previous item with a URL
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return;
|
|
136
|
-
};
|
|
171
|
+
const lastBlade = getLastItemWithUrl(newVal);
|
|
137
172
|
|
|
138
173
|
if (workspace?.type?.url) {
|
|
139
|
-
|
|
140
|
-
// when restoring blades we need to use full path of the blade to show last blade from the url as workspace.
|
|
141
|
-
// fullPath is provided by generateRoute function
|
|
142
|
-
const wsBladeUrl = workspace?.props?.navigation?.fullPath || workspace?.type.url;
|
|
143
|
-
|
|
144
|
-
const lastBlade = getLastItemWithUrl();
|
|
145
|
-
if (getLastItemWithUrl()) {
|
|
146
|
-
url =
|
|
147
|
-
"/" +
|
|
148
|
-
parseUrl(wsBladeUrl)?.workspace +
|
|
149
|
-
lastBlade?.type.url +
|
|
150
|
-
(lastBlade?.props?.param ? "/" + lastBlade?.props.param : "");
|
|
151
|
-
} else {
|
|
152
|
-
url = wsBladeUrl;
|
|
153
|
-
}
|
|
154
|
-
|
|
174
|
+
const url = constructUrl(workspace, lastBlade);
|
|
155
175
|
if (url) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
? mainRouteBaseParamURL.value
|
|
159
|
-
: "") + url,
|
|
160
|
-
);
|
|
176
|
+
const query = window.location.search;
|
|
177
|
+
updateRouterHistory(url, query);
|
|
161
178
|
}
|
|
162
179
|
}
|
|
163
180
|
},
|
|
164
|
-
{ deep: true },
|
|
181
|
+
{ deep: true, debounce: 1 },
|
|
165
182
|
);
|
|
166
183
|
|
|
184
|
+
function getLastItemWithUrl(newVal: BladeVNode[]) {
|
|
185
|
+
for (let i = newVal.length - 1; i > 0; i--) {
|
|
186
|
+
if (newVal[i].type.url) {
|
|
187
|
+
return newVal[i];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function constructUrl(workspace: BladeVNode, lastBlade?: BladeVNode) {
|
|
193
|
+
const wsBladeUrl = workspace?.type.url;
|
|
194
|
+
const lastBladeUrl = lastBlade?.type.url;
|
|
195
|
+
const param = lastBlade?.props?.param;
|
|
196
|
+
if (lastBlade && wsBladeUrl) {
|
|
197
|
+
return "/" + parseUrl(wsBladeUrl)?.workspace + lastBladeUrl + (param ? "/" + param : "");
|
|
198
|
+
} else {
|
|
199
|
+
return wsBladeUrl;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function updateRouterHistory(url: string, query: string) {
|
|
204
|
+
router.options.history.replace(
|
|
205
|
+
(mainRouteBaseParamURL.value && !url.startsWith(mainRouteBaseParamURL.value) ? mainRouteBaseParamURL.value : "") +
|
|
206
|
+
url +
|
|
207
|
+
(query ? "?" + query : ""),
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
167
211
|
async function closeBlade(index: number) {
|
|
168
212
|
console.debug(`[@vc-shell/framework#useBladeNavigation] - closeBlade called.`);
|
|
169
213
|
|
|
@@ -215,8 +259,9 @@ export function useBladeNavigation(): IUseBladeNavigation {
|
|
|
215
259
|
const instance: BladeComponentInternalInstance = getCurrentInstance() as BladeComponentInternalInstance;
|
|
216
260
|
|
|
217
261
|
const { router, route, navigationInstance, closeBlade } = useBladeNavigationSingleton();
|
|
218
|
-
|
|
219
|
-
const
|
|
262
|
+
const { parseUrl } = utils(router);
|
|
263
|
+
const routerRoutes = router.getRoutes();
|
|
264
|
+
const mainRoute = routerRoutes.find((r) => r.meta?.root)!;
|
|
220
265
|
|
|
221
266
|
async function openWorkspace<Blade extends Component>({ blade, param, options }: IBladeEvent<Blade>) {
|
|
222
267
|
const createdComponent = h(blade, {
|
|
@@ -228,26 +273,26 @@ export function useBladeNavigation(): IUseBladeNavigation {
|
|
|
228
273
|
}) as BladeVNode;
|
|
229
274
|
|
|
230
275
|
try {
|
|
231
|
-
|
|
276
|
+
// Close all blades except the first one cause it will be overwritten
|
|
277
|
+
const isPrevented = await closeBlade(1);
|
|
232
278
|
|
|
233
279
|
if (!isPrevented && createdComponent.type?.url) {
|
|
234
280
|
if (hasAccess(blade.permissions)) {
|
|
235
281
|
navigationInstance.blades.value = [createdComponent];
|
|
236
|
-
|
|
237
282
|
// Find the route with the matching URL and update the components.default property with the new component
|
|
238
|
-
const
|
|
239
|
-
if (
|
|
240
|
-
|
|
283
|
+
const wsroute = routerRoutes.find((r) => r.path.endsWith(createdComponent.type?.url as string));
|
|
284
|
+
if (wsroute && wsroute.components) {
|
|
285
|
+
wsroute.components.default = createdComponent;
|
|
241
286
|
}
|
|
242
287
|
|
|
243
|
-
return await router.replace({
|
|
288
|
+
return await router.replace({ name: wsroute?.name, params: { ...route.params } });
|
|
244
289
|
} else
|
|
245
290
|
notification.error(i18n.global.t("PERMISSION_MESSAGES.ACCESS_RESTRICTED"), {
|
|
246
291
|
timeout: 3000,
|
|
247
292
|
});
|
|
248
293
|
}
|
|
249
294
|
} catch (e) {
|
|
250
|
-
console.
|
|
295
|
+
console.error(e);
|
|
251
296
|
throw new Error(`Opening workspace '${blade.type.name}' is prevented`);
|
|
252
297
|
}
|
|
253
298
|
}
|
|
@@ -267,52 +312,64 @@ export function useBladeNavigation(): IUseBladeNavigation {
|
|
|
267
312
|
try {
|
|
268
313
|
const instanceComponent = navigationView || activeWorkspace.value;
|
|
269
314
|
|
|
270
|
-
if (
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
315
|
+
if (!instanceComponent) {
|
|
316
|
+
throw new Error("No workspace found");
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const instanceComponentIndex = findInstanceComponentIndex(instanceComponent);
|
|
320
|
+
const instanceComponentChild = navigationInstance.blades.value[instanceComponentIndex + 1];
|
|
274
321
|
|
|
275
|
-
|
|
276
|
-
instanceComponentIndex >= 0 ? navigationInstance.blades.value[instanceComponentIndex + 1] : undefined;
|
|
322
|
+
let isPrevented = false;
|
|
277
323
|
|
|
278
|
-
|
|
324
|
+
if (instanceComponentChild) {
|
|
325
|
+
isPrevented = await closeBlade(instanceComponentChild.props?.navigation?.idx);
|
|
326
|
+
}
|
|
279
327
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
328
|
+
const currentBladeIdx = instanceComponent.props?.navigation?.idx ?? 0;
|
|
329
|
+
|
|
330
|
+
const bladeNode = createBladeNode<Blade>({ blade, currentBladeIdx, options, param, onClose, onOpen });
|
|
283
331
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
{},
|
|
290
|
-
reactiveComputed(() => ({ options, param })),
|
|
291
|
-
{
|
|
292
|
-
navigation: {
|
|
293
|
-
onClose,
|
|
294
|
-
onOpen,
|
|
295
|
-
idx: currentBladeIdx + 1,
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
),
|
|
299
|
-
) as BladeVNode;
|
|
300
|
-
|
|
301
|
-
if (!isPrevented) {
|
|
302
|
-
if (hasAccess(blade.permissions)) navigationInstance.blades.value.push(bladeNode);
|
|
303
|
-
else
|
|
304
|
-
notification.error(i18n.global.t("PERMISSION_MESSAGES.ACCESS_RESTRICTED"), {
|
|
305
|
-
timeout: 3000,
|
|
306
|
-
});
|
|
332
|
+
if (!isPrevented) {
|
|
333
|
+
if (hasAccess(blade.permissions)) {
|
|
334
|
+
navigationInstance.blades.value.push(bladeNode);
|
|
335
|
+
} else {
|
|
336
|
+
notification.error(i18n.global.t("PERMISSION_MESSAGES.ACCESS_RESTRICTED"), { timeout: 3000 });
|
|
307
337
|
}
|
|
308
|
-
} else {
|
|
309
|
-
throw new Error("No workspace found");
|
|
310
338
|
}
|
|
311
339
|
} catch (e) {
|
|
312
340
|
console.error(e);
|
|
313
341
|
}
|
|
314
342
|
}
|
|
315
343
|
|
|
344
|
+
function findInstanceComponentIndex(instanceComponent: BladeVNode) {
|
|
345
|
+
return navigationInstance.blades.value.findIndex((x) => _.isEqual(x.type, instanceComponent.type));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function createBladeNode<Blade extends Component>(args: {
|
|
349
|
+
blade: BladeInstanceConstructor<Blade>;
|
|
350
|
+
currentBladeIdx: number;
|
|
351
|
+
options: ExtractedBladeOptions<InstanceType<BladeInstanceConstructor<Blade>>["$props"], "options"> | undefined;
|
|
352
|
+
param?: string;
|
|
353
|
+
onClose?: () => void;
|
|
354
|
+
onOpen?: () => void;
|
|
355
|
+
}) {
|
|
356
|
+
const { blade, currentBladeIdx, options, param, onClose, onOpen } = args;
|
|
357
|
+
return h(
|
|
358
|
+
blade,
|
|
359
|
+
Object.assign(
|
|
360
|
+
{},
|
|
361
|
+
reactiveComputed(() => ({ options, param })),
|
|
362
|
+
{
|
|
363
|
+
navigation: {
|
|
364
|
+
onClose,
|
|
365
|
+
onOpen,
|
|
366
|
+
idx: currentBladeIdx + 1,
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
),
|
|
370
|
+
) as BladeVNode;
|
|
371
|
+
}
|
|
372
|
+
|
|
316
373
|
async function onParentCall(parentExposedMethods: Record<string, any>, args: IParentCallArgs) {
|
|
317
374
|
console.debug(`vc-app#onParentCall({ method: ${args.method} }) called.`);
|
|
318
375
|
|
|
@@ -355,7 +412,7 @@ export function useBladeNavigation(): IUseBladeNavigation {
|
|
|
355
412
|
}
|
|
356
413
|
|
|
357
414
|
function hasNecessaryRoute(to: RouteLocationNormalized) {
|
|
358
|
-
return
|
|
415
|
+
return routerRoutes.find((route) => route.path === to.path);
|
|
359
416
|
}
|
|
360
417
|
|
|
361
418
|
/**
|
|
@@ -369,92 +426,79 @@ export function useBladeNavigation(): IUseBladeNavigation {
|
|
|
369
426
|
*/
|
|
370
427
|
async function generateRoute(to: RouteLocationNormalized, routes: BladeRoutesRecord[]) {
|
|
371
428
|
// Extract parameters excluding "pathMatch". This is necessary if a variable is used as the App component URL, for example, /:userId?
|
|
372
|
-
const params = Object.entries(to.params)
|
|
373
|
-
.filter(([key]) => key !== "pathMatch")
|
|
374
|
-
.reduce(
|
|
375
|
-
(acc, [key, value]) => {
|
|
376
|
-
acc[key] = value;
|
|
377
|
-
return acc;
|
|
378
|
-
},
|
|
379
|
-
{} as Record<string, string | string[]>,
|
|
380
|
-
);
|
|
429
|
+
const params = Object.fromEntries(Object.entries(to.params).filter(([key]) => key !== "pathMatch"));
|
|
381
430
|
|
|
382
431
|
// Get the raw path of the main route.
|
|
383
|
-
const parentRawPath =
|
|
432
|
+
const parentRawPath = routerRoutes.find((route) => route.name === mainRoute.name)?.path;
|
|
384
433
|
|
|
385
434
|
// Determine the parent path based on the parameters.
|
|
386
|
-
const parentPath =
|
|
387
|
-
|
|
388
|
-
: "";
|
|
435
|
+
const parentPath =
|
|
436
|
+
parentRawPath && parentRawPath.includes(Object.keys(params)[0]) ? `/${Object.values(params)[0]}` : "";
|
|
389
437
|
|
|
390
438
|
// Set the base param value.
|
|
391
439
|
mainRouteBaseParamURL.value = parentPath;
|
|
392
440
|
|
|
393
|
-
// Check if the current path matches the parent path.
|
|
394
|
-
const isCorrectParentPath = parentRawPath !== "/" && to.path.startsWith(parentPath);
|
|
395
|
-
|
|
396
|
-
// Check if the current route is a parent route.
|
|
397
|
-
const isRouteParent = router.getRoutes().find((x) => x.path.endsWith(parentPath));
|
|
398
|
-
|
|
399
441
|
// Parse the URL to extract relevant route information.
|
|
400
|
-
const parsedRoutes = parseUrl(
|
|
442
|
+
const parsedRoutes = parseUrl(parentPath !== "/" ? to.path.slice(parentPath.length) : to.path);
|
|
443
|
+
|
|
444
|
+
if (parsedRoutes !== undefined) {
|
|
445
|
+
const { workspace, blade, param } = parsedRoutes;
|
|
401
446
|
|
|
402
|
-
if (parsedRoutes) {
|
|
403
447
|
// Find the registered route component.
|
|
404
|
-
const
|
|
448
|
+
const registeredWorkspaceComponent = routes.find((route) => route.route === `/${workspace}`)?.component;
|
|
449
|
+
const registeredRouteComponent = routes.find((route) => route.route === `/${blade}`)?.component;
|
|
405
450
|
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
// If the route is not routable, redirect to the workspace.
|
|
421
|
-
if (!parsedRoutes.param && !registeredRouteComponent.type?.routable) {
|
|
422
|
-
return router.replace("/" + parsedRoutes?.workspace);
|
|
423
|
-
} else {
|
|
424
|
-
// Add the route to the router.
|
|
425
|
-
router.addRoute(mainRoute.name as string, {
|
|
426
|
-
name: url,
|
|
427
|
-
path: parentRawPath !== "/" ? parentRawPath + url : "" + url,
|
|
428
|
-
components: {
|
|
429
|
-
default: _.merge({}, registeredRouteComponent, {
|
|
430
|
-
props: {
|
|
431
|
-
param: parsedRoutes.param,
|
|
432
|
-
navigation: {
|
|
433
|
-
fullPath: url,
|
|
434
|
-
idx: 0,
|
|
435
|
-
},
|
|
436
|
-
},
|
|
437
|
-
}),
|
|
438
|
-
},
|
|
439
|
-
meta: {
|
|
440
|
-
permissions: registeredRouteComponent.type?.permissions,
|
|
441
|
-
},
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
// Navigate to the newly added route.
|
|
445
|
-
return router.replace({ name: url, params: isCorrectParentPath ? params : {} });
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
} else {
|
|
449
|
-
// If the registered route component is not found, navigate to the main route.
|
|
450
|
-
const mainRoute = router.getRoutes().find((route) => route.meta?.root);
|
|
451
|
-
const mainRouteAlias = router.getRoutes().find((route) => route.aliasOf?.path === mainRoute?.path) ?? mainRoute;
|
|
451
|
+
if (!registeredWorkspaceComponent) {
|
|
452
|
+
return goToRoot();
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Open the workspace component or workspace route.
|
|
456
|
+
if (registeredRouteComponent?.type.isWorkspace) {
|
|
457
|
+
await openBlade(
|
|
458
|
+
{
|
|
459
|
+
blade: registeredRouteComponent as unknown as BladeInstanceConstructor,
|
|
460
|
+
},
|
|
461
|
+
true,
|
|
462
|
+
);
|
|
463
|
+
return { name: registeredRouteComponent?.type.name, params };
|
|
464
|
+
}
|
|
452
465
|
|
|
453
|
-
|
|
466
|
+
// Open the workspace component with param or workspace route.
|
|
467
|
+
if (registeredWorkspaceComponent) {
|
|
468
|
+
await openBlade(
|
|
469
|
+
{
|
|
470
|
+
blade: registeredWorkspaceComponent as unknown as BladeInstanceConstructor,
|
|
471
|
+
param:
|
|
472
|
+
registeredRouteComponent?.type.moduleUid === registeredWorkspaceComponent.type.moduleUid
|
|
473
|
+
? param
|
|
474
|
+
: undefined,
|
|
475
|
+
},
|
|
476
|
+
true,
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
// Open the route if it's not from the workspace module.
|
|
480
|
+
if (
|
|
481
|
+
registeredRouteComponent?.type.moduleUid !== registeredWorkspaceComponent.type.moduleUid &&
|
|
482
|
+
registeredRouteComponent?.type.routable
|
|
483
|
+
) {
|
|
484
|
+
await openBlade({
|
|
485
|
+
blade: registeredRouteComponent as unknown as BladeInstanceConstructor,
|
|
486
|
+
param: param,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
return { name: registeredWorkspaceComponent?.type.name, params };
|
|
454
490
|
}
|
|
491
|
+
} else {
|
|
492
|
+
return goToRoot();
|
|
455
493
|
}
|
|
456
494
|
}
|
|
457
495
|
|
|
496
|
+
function goToRoot() {
|
|
497
|
+
const mainRoute = routerRoutes.find((route) => route.meta?.root);
|
|
498
|
+
const mainRouteAlias = routerRoutes.find((route) => route.aliasOf?.path === mainRoute?.path) || mainRoute;
|
|
499
|
+
return { name: mainRouteAlias?.name, params: route.params };
|
|
500
|
+
}
|
|
501
|
+
|
|
458
502
|
/**
|
|
459
503
|
* The function getCurrentBlade returns the current BladeVNode instance's vnode.
|
|
460
504
|
* @returns the `vnode` property of the `instance` object, which is of type `BladeVNode`.
|
|
@@ -29,7 +29,7 @@ export const VcBladeNavigationComponent = {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
app.config.globalProperties.$bladeNavigationPlugin = bladeNavigationPlugin;
|
|
32
|
-
app.provide("bladeNavigationPlugin", bladeNavigationPlugin);
|
|
33
32
|
bladeNavigationInstance = bladeNavigationPlugin;
|
|
33
|
+
app.provide("bladeNavigationPlugin", bladeNavigationPlugin);
|
|
34
34
|
},
|
|
35
35
|
};
|
|
@@ -95,7 +95,6 @@ export interface BladeVNode extends VNode {
|
|
|
95
95
|
onClose?: () => void;
|
|
96
96
|
onBeforeClose?: () => Promise<boolean | undefined>;
|
|
97
97
|
instance: Ref<CoreBladeExposed | undefined | null>;
|
|
98
|
-
fullPath: string;
|
|
99
98
|
idx: number;
|
|
100
99
|
};
|
|
101
100
|
onVnodeUnmounted?: VNodeMountHook | VNodeMountHook[];
|