@jskit-ai/workspaces-web 0.1.19 → 0.1.21
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.descriptor.mjs +4 -3
- package/package.json +7 -7
- package/src/client/composables/useWorkspaceRouteContext.js +4 -15
- package/src/client/providers/WorkspacesWebClientProvider.js +19 -0
- package/src/client/support/workspaceScopeSupport.js +48 -0
- package/test/workspaceScopeSupport.test.js +74 -0
package/package.descriptor.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
packageVersion: 1,
|
|
3
3
|
packageId: "@jskit-ai/workspaces-web",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.21",
|
|
5
5
|
kind: "runtime",
|
|
6
6
|
description: "Workspace web module: workspace selector, tools widget, workspace surfaces, and members/settings UI.",
|
|
7
7
|
dependsOn: [
|
|
@@ -56,6 +56,7 @@ export default Object.freeze({
|
|
|
56
56
|
"workspaces.web.workspace-members.menu-item",
|
|
57
57
|
"workspaces.web.members-admin.element",
|
|
58
58
|
"workspaces.web.bootstrap-placement.runtime",
|
|
59
|
+
"workspaces.web.scope-support",
|
|
59
60
|
"workspaces.web.account-settings.section.invites"
|
|
60
61
|
]
|
|
61
62
|
}
|
|
@@ -147,8 +148,8 @@ export default Object.freeze({
|
|
|
147
148
|
mutations: {
|
|
148
149
|
dependencies: {
|
|
149
150
|
runtime: {
|
|
150
|
-
"@jskit-ai/workspaces-core": "0.1.
|
|
151
|
-
"@jskit-ai/users-web": "0.1.
|
|
151
|
+
"@jskit-ai/workspaces-core": "0.1.21",
|
|
152
|
+
"@jskit-ai/users-web": "0.1.60",
|
|
152
153
|
"vuetify": "^4.0.0"
|
|
153
154
|
},
|
|
154
155
|
dev: {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/workspaces-web",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@tanstack/vue-query": "5.92.12",
|
|
16
16
|
"@mdi/js": "^7.4.47",
|
|
17
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
18
|
-
"@jskit-ai/kernel": "0.1.
|
|
19
|
-
"@jskit-ai/shell-web": "0.1.
|
|
20
|
-
"@jskit-ai/users-core": "0.1.
|
|
21
|
-
"@jskit-ai/users-web": "0.1.
|
|
22
|
-
"@jskit-ai/workspaces-core": "0.1.
|
|
17
|
+
"@jskit-ai/http-runtime": "0.1.44",
|
|
18
|
+
"@jskit-ai/kernel": "0.1.45",
|
|
19
|
+
"@jskit-ai/shell-web": "0.1.44",
|
|
20
|
+
"@jskit-ai/users-core": "0.1.55",
|
|
21
|
+
"@jskit-ai/users-web": "0.1.60",
|
|
22
|
+
"@jskit-ai/workspaces-core": "0.1.21",
|
|
23
23
|
"vuetify": "^4.0.0"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -1,26 +1,15 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
|
-
import {
|
|
3
|
-
extractWorkspaceSlugFromSurfacePathname
|
|
4
|
-
} from "../lib/workspaceSurfacePaths.js";
|
|
5
2
|
import { useSurfaceRouteContext } from "@jskit-ai/users-web/client/composables/useSurfaceRouteContext";
|
|
3
|
+
import { readWorkspaceRouteScope } from "../support/workspaceScopeSupport.js";
|
|
6
4
|
|
|
7
5
|
function useWorkspaceRouteContext() {
|
|
8
|
-
const
|
|
6
|
+
const routeContext = useSurfaceRouteContext();
|
|
9
7
|
const workspaceSlugFromRoute = computed(() => {
|
|
10
|
-
|
|
11
|
-
placementContext.value,
|
|
12
|
-
currentSurfaceId.value,
|
|
13
|
-
routePath.value
|
|
14
|
-
);
|
|
15
|
-
return String(workspaceSlug || "").trim();
|
|
8
|
+
return readWorkspaceRouteScope(routeContext).workspaceSlug;
|
|
16
9
|
});
|
|
17
10
|
|
|
18
11
|
return Object.freeze({
|
|
19
|
-
|
|
20
|
-
routePath,
|
|
21
|
-
placementContext,
|
|
22
|
-
mergePlacementContext,
|
|
23
|
-
currentSurfaceId,
|
|
12
|
+
...routeContext,
|
|
24
13
|
workspaceSlugFromRoute
|
|
25
14
|
});
|
|
26
15
|
}
|
|
@@ -7,6 +7,10 @@ import UsersWorkspaceSettingsMenuItem from "../components/UsersWorkspaceSettings
|
|
|
7
7
|
import UsersWorkspaceMembersMenuItem from "../components/UsersWorkspaceMembersMenuItem.vue";
|
|
8
8
|
import MembersAdminClientElement from "../components/MembersAdminClientElement.vue";
|
|
9
9
|
import { createBootstrapPlacementRuntime } from "../runtime/bootstrapPlacementRuntime.js";
|
|
10
|
+
import {
|
|
11
|
+
WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY,
|
|
12
|
+
createWorkspaceScopeSupport
|
|
13
|
+
} from "../support/workspaceScopeSupport.js";
|
|
10
14
|
|
|
11
15
|
class WorkspacesWebClientProvider {
|
|
12
16
|
static id = "workspaces.web.client";
|
|
@@ -24,6 +28,7 @@ class WorkspacesWebClientProvider {
|
|
|
24
28
|
app.singleton("workspaces.web.workspace-members.menu-item", () => UsersWorkspaceMembersMenuItem);
|
|
25
29
|
app.singleton("workspaces.web.members-admin.element", () => MembersAdminClientElement);
|
|
26
30
|
app.singleton("workspaces.web.bootstrap-placement.runtime", (scope) => createBootstrapPlacementRuntime({ app: scope }));
|
|
31
|
+
app.singleton("workspaces.web.scope-support", () => createWorkspaceScopeSupport());
|
|
27
32
|
app.singleton("workspaces.web.account-settings.section.invites", () =>
|
|
28
33
|
Object.freeze({
|
|
29
34
|
title: "Invites",
|
|
@@ -45,6 +50,20 @@ class WorkspacesWebClientProvider {
|
|
|
45
50
|
if (runtime && typeof runtime.initialize === "function") {
|
|
46
51
|
await runtime.initialize();
|
|
47
52
|
}
|
|
53
|
+
|
|
54
|
+
if (!app.has("jskit.client.vue.app")) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const vueApp = app.make("jskit.client.vue.app");
|
|
59
|
+
if (!vueApp || typeof vueApp.provide !== "function") {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
vueApp.provide(
|
|
64
|
+
WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY,
|
|
65
|
+
app.make("workspaces.web.scope-support")
|
|
66
|
+
);
|
|
48
67
|
}
|
|
49
68
|
|
|
50
69
|
shutdown(app) {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getClientAppConfig } from "@jskit-ai/kernel/client";
|
|
2
|
+
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
3
|
+
import {
|
|
4
|
+
extractWorkspaceSlugFromSurfacePathname
|
|
5
|
+
} from "../lib/workspaceSurfacePaths.js";
|
|
6
|
+
|
|
7
|
+
const WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY = "jskit.workspaces.web.scope-support";
|
|
8
|
+
|
|
9
|
+
function unwrapRefValue(value) {
|
|
10
|
+
if (value && typeof value === "object" && Object.hasOwn(value, "value")) {
|
|
11
|
+
return value.value;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function readWorkspaceRouteScope(routeContext = {}) {
|
|
18
|
+
const placementContext = unwrapRefValue(routeContext?.placementContext);
|
|
19
|
+
const currentSurfaceId = normalizeText(unwrapRefValue(routeContext?.currentSurfaceId)).toLowerCase();
|
|
20
|
+
const routePath = normalizeText(unwrapRefValue(routeContext?.routePath));
|
|
21
|
+
const workspaceSlug = extractWorkspaceSlugFromSurfacePathname(
|
|
22
|
+
placementContext,
|
|
23
|
+
currentSurfaceId,
|
|
24
|
+
routePath
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
return Object.freeze({
|
|
28
|
+
workspaceSlug: String(workspaceSlug || "").trim()
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function createWorkspaceScopeSupport() {
|
|
33
|
+
const appConfig = getClientAppConfig();
|
|
34
|
+
const tenancyMode = normalizeText(appConfig?.tenancyMode).toLowerCase();
|
|
35
|
+
|
|
36
|
+
return Object.freeze({
|
|
37
|
+
available: tenancyMode === "personal" || tenancyMode === "workspaces",
|
|
38
|
+
readRouteScope(routeContext = {}) {
|
|
39
|
+
return readWorkspaceRouteScope(routeContext);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY,
|
|
46
|
+
createWorkspaceScopeSupport,
|
|
47
|
+
readWorkspaceRouteScope
|
|
48
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import {
|
|
4
|
+
createWorkspaceScopeSupport,
|
|
5
|
+
readWorkspaceRouteScope
|
|
6
|
+
} from "../src/client/support/workspaceScopeSupport.js";
|
|
7
|
+
|
|
8
|
+
test("readWorkspaceRouteScope extracts workspace slug from the current dynamic surface path", () => {
|
|
9
|
+
const scope = readWorkspaceRouteScope({
|
|
10
|
+
placementContext: {
|
|
11
|
+
value: {
|
|
12
|
+
surfaceConfig: {
|
|
13
|
+
defaultSurfaceId: "app",
|
|
14
|
+
surfacesById: {
|
|
15
|
+
app: {
|
|
16
|
+
id: "app",
|
|
17
|
+
routeBase: "w/[workspaceSlug]",
|
|
18
|
+
requiresWorkspace: true
|
|
19
|
+
},
|
|
20
|
+
admin: {
|
|
21
|
+
id: "admin",
|
|
22
|
+
routeBase: "w/[workspaceSlug]/admin",
|
|
23
|
+
requiresWorkspace: true
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
currentSurfaceId: {
|
|
30
|
+
value: "admin"
|
|
31
|
+
},
|
|
32
|
+
routePath: {
|
|
33
|
+
value: "/w/acme/admin/settings"
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
assert.deepEqual(scope, {
|
|
38
|
+
workspaceSlug: "acme"
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("workspace scope support exposes the shared route-scope reader", () => {
|
|
43
|
+
const support = createWorkspaceScopeSupport();
|
|
44
|
+
|
|
45
|
+
assert.equal(typeof support.available, "boolean");
|
|
46
|
+
assert.equal(typeof support.readRouteScope, "function");
|
|
47
|
+
assert.deepEqual(
|
|
48
|
+
support.readRouteScope({
|
|
49
|
+
placementContext: {
|
|
50
|
+
value: {
|
|
51
|
+
surfaceConfig: {
|
|
52
|
+
defaultSurfaceId: "app",
|
|
53
|
+
surfacesById: {
|
|
54
|
+
app: {
|
|
55
|
+
id: "app",
|
|
56
|
+
routeBase: "w/[workspaceSlug]",
|
|
57
|
+
requiresWorkspace: true
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
currentSurfaceId: {
|
|
64
|
+
value: "app"
|
|
65
|
+
},
|
|
66
|
+
routePath: {
|
|
67
|
+
value: "/w/dogandgroom"
|
|
68
|
+
}
|
|
69
|
+
}),
|
|
70
|
+
{
|
|
71
|
+
workspaceSlug: "dogandgroom"
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
});
|