@jskit-ai/workspaces-web 0.1.30 → 0.1.32
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 +3 -3
- package/package.json +11 -7
- package/src/client/account-settings/useAccountSettingsInvitesSectionRuntime.js +2 -0
- package/src/client/components/WorkspaceMembersClientElement.vue +16 -0
- package/src/client/components/WorkspaceProfileClientElement.vue +3 -7
- package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +3 -7
- package/src/client/components/WorkspacesClientElement.vue +6 -0
- package/src/client/providers/WorkspacesWebClientProvider.js +19 -2
- package/src/client/runtime/bootstrapPlacementRuntime.js +191 -136
- package/src/client/support/workspaceScopeSupport.js +4 -11
- package/test/bootstrapPlacementRuntime.test.js +340 -440
- package/test/profileSurfaceMenuLinks.test.js +34 -0
- package/test/workspaceScopeSupport.test.js +28 -39
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.32",
|
|
5
5
|
kind: "runtime",
|
|
6
6
|
description: "Workspace web module: workspace selector, tools widget, workspace surfaces, and members/settings UI.",
|
|
7
7
|
dependsOn: [
|
|
@@ -166,8 +166,8 @@ export default Object.freeze({
|
|
|
166
166
|
mutations: {
|
|
167
167
|
dependencies: {
|
|
168
168
|
runtime: {
|
|
169
|
-
"@jskit-ai/workspaces-core": "0.1.
|
|
170
|
-
"@jskit-ai/users-web": "0.1.
|
|
169
|
+
"@jskit-ai/workspaces-core": "0.1.32",
|
|
170
|
+
"@jskit-ai/users-web": "0.1.71",
|
|
171
171
|
"vuetify": "^4.0.0"
|
|
172
172
|
},
|
|
173
173
|
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.32",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -15,12 +15,16 @@
|
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@tanstack/vue-query": "5.92.12",
|
|
17
17
|
"@mdi/js": "^7.4.47",
|
|
18
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
19
|
-
"@jskit-ai/kernel": "0.1.
|
|
20
|
-
"@jskit-ai/shell-web": "0.1.
|
|
21
|
-
"@jskit-ai/users-core": "0.1.
|
|
22
|
-
"@jskit-ai/users-web": "0.1.
|
|
23
|
-
"@jskit-ai/workspaces-core": "0.1.
|
|
18
|
+
"@jskit-ai/http-runtime": "0.1.55",
|
|
19
|
+
"@jskit-ai/kernel": "0.1.56",
|
|
20
|
+
"@jskit-ai/shell-web": "0.1.55",
|
|
21
|
+
"@jskit-ai/users-core": "0.1.66",
|
|
22
|
+
"@jskit-ai/users-web": "0.1.71",
|
|
23
|
+
"@jskit-ai/workspaces-core": "0.1.32",
|
|
24
24
|
"vuetify": "^4.0.0"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"vue": "^3.5.13",
|
|
28
|
+
"vue-router": "^5.0.4"
|
|
25
29
|
}
|
|
26
30
|
}
|
|
@@ -10,6 +10,7 @@ import { useCommand } from "@jskit-ai/users-web/client/composables/useCommand";
|
|
|
10
10
|
import { usePaths } from "@jskit-ai/users-web/client/composables/usePaths";
|
|
11
11
|
import { useView } from "@jskit-ai/users-web/client/composables/useView";
|
|
12
12
|
import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
13
|
+
import { WORKSPACE_INVITE_REDEEM_TRANSPORT } from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
|
|
13
14
|
import { useWorkspaceSurfaceId } from "../composables/useWorkspaceSurfaceId.js";
|
|
14
15
|
import { createAccountSettingsInvitesRuntime } from "./accountSettingsInvitesRuntime.js";
|
|
15
16
|
|
|
@@ -112,6 +113,7 @@ function useAccountSettingsInvitesSectionRuntime() {
|
|
|
112
113
|
ownershipFilter: ROUTE_VISIBILITY_PUBLIC,
|
|
113
114
|
apiSuffix: "/workspace/invitations/redeem",
|
|
114
115
|
writeMethod: "POST",
|
|
116
|
+
transport: WORKSPACE_INVITE_REDEEM_TRANSPORT,
|
|
115
117
|
fallbackRunError: "Unable to respond to invitation.",
|
|
116
118
|
suppressSuccessMessage: true,
|
|
117
119
|
model: redeemInviteModel,
|
|
@@ -23,6 +23,14 @@ import { computed, reactive, ref, watch } from "vue";
|
|
|
23
23
|
import { formatDateTime } from "@jskit-ai/kernel/shared/support";
|
|
24
24
|
import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
25
25
|
import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
|
|
26
|
+
import {
|
|
27
|
+
WORKSPACE_INVITES_TRANSPORT,
|
|
28
|
+
WORKSPACE_INVITE_CREATE_TRANSPORT,
|
|
29
|
+
WORKSPACE_MEMBER_ROLE_UPDATE_TRANSPORT,
|
|
30
|
+
WORKSPACE_MEMBERS_TRANSPORT,
|
|
31
|
+
WORKSPACE_ROLE_CATALOG_TRANSPORT,
|
|
32
|
+
WORKSPACE_SETTINGS_TRANSPORT
|
|
33
|
+
} from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
|
|
26
34
|
import MembersAdminClientElement from "./MembersAdminClientElement.vue";
|
|
27
35
|
import { useCommand } from "@jskit-ai/users-web/client/composables/useCommand";
|
|
28
36
|
import { useList } from "@jskit-ai/users-web/client/composables/useList";
|
|
@@ -276,6 +284,7 @@ const workspaceSettingsView = useView({
|
|
|
276
284
|
event: "workspace.settings.changed",
|
|
277
285
|
matches: matchesWorkspaceRealtime
|
|
278
286
|
},
|
|
287
|
+
transport: WORKSPACE_SETTINGS_TRANSPORT,
|
|
279
288
|
fallbackLoadError: "Unable to load workspace settings."
|
|
280
289
|
});
|
|
281
290
|
|
|
@@ -284,6 +293,7 @@ const workspaceRolesView = useView({
|
|
|
284
293
|
apiSuffix: "/roles",
|
|
285
294
|
queryKeyFactory: (surfaceId = "", workspaceSlug = "") => buildWorkspaceQueryKey("roles", surfaceId, workspaceSlug),
|
|
286
295
|
viewPermissions: ["workspace.members.view", "workspace.members.invite", "workspace.members.manage"],
|
|
296
|
+
transport: WORKSPACE_ROLE_CATALOG_TRANSPORT,
|
|
287
297
|
fallbackLoadError: "Unable to load workspace roles."
|
|
288
298
|
});
|
|
289
299
|
|
|
@@ -297,6 +307,7 @@ const workspaceMembersList = useList({
|
|
|
297
307
|
event: "workspace.members.changed",
|
|
298
308
|
matches: matchesWorkspaceRealtime
|
|
299
309
|
},
|
|
310
|
+
transport: WORKSPACE_MEMBERS_TRANSPORT,
|
|
300
311
|
selectItems: (payload) => normalizeMembers(payload?.members),
|
|
301
312
|
fallbackLoadError: "Unable to load workspace members."
|
|
302
313
|
});
|
|
@@ -311,6 +322,7 @@ const workspaceInvitesList = useList({
|
|
|
311
322
|
event: "workspace.invites.changed",
|
|
312
323
|
matches: matchesWorkspaceRealtime
|
|
313
324
|
},
|
|
325
|
+
transport: WORKSPACE_INVITES_TRANSPORT,
|
|
314
326
|
selectItems: (payload) => normalizeInvites(payload?.invites),
|
|
315
327
|
fallbackLoadError: "Unable to load workspace invites."
|
|
316
328
|
});
|
|
@@ -320,6 +332,7 @@ const inviteCreateCommand = useCommand({
|
|
|
320
332
|
apiSuffix: "/invites",
|
|
321
333
|
runPermissions: ["workspace.members.invite"],
|
|
322
334
|
writeMethod: "POST",
|
|
335
|
+
transport: WORKSPACE_INVITE_CREATE_TRANSPORT,
|
|
323
336
|
fallbackRunError: "Unable to send invite.",
|
|
324
337
|
buildRawPayload: () => ({
|
|
325
338
|
email: forms.invite.email,
|
|
@@ -336,6 +349,7 @@ const revokeInviteCommand = useCommand({
|
|
|
336
349
|
apiSuffix: "/invites",
|
|
337
350
|
runPermissions: ["workspace.invites.revoke"],
|
|
338
351
|
writeMethod: "DELETE",
|
|
352
|
+
transport: WORKSPACE_INVITES_TRANSPORT,
|
|
339
353
|
fallbackRunError: "Unable to revoke invite.",
|
|
340
354
|
buildCommandOptions: (_parsed, { context }) => {
|
|
341
355
|
return {
|
|
@@ -354,6 +368,7 @@ const memberRoleCommand = useCommand({
|
|
|
354
368
|
apiSuffix: "/members",
|
|
355
369
|
runPermissions: ["workspace.members.manage"],
|
|
356
370
|
writeMethod: "PATCH",
|
|
371
|
+
transport: WORKSPACE_MEMBER_ROLE_UPDATE_TRANSPORT,
|
|
357
372
|
fallbackRunError: "Unable to update member role.",
|
|
358
373
|
buildRawPayload: (_model, { context }) => ({
|
|
359
374
|
roleSid: String(context?.roleSid || "").trim().toLowerCase()
|
|
@@ -375,6 +390,7 @@ const memberRemoveCommand = useCommand({
|
|
|
375
390
|
apiSuffix: "/members",
|
|
376
391
|
runPermissions: ["workspace.members.manage"],
|
|
377
392
|
writeMethod: "DELETE",
|
|
393
|
+
transport: WORKSPACE_MEMBERS_TRANSPORT,
|
|
378
394
|
fallbackRunError: "Unable to remove member.",
|
|
379
395
|
buildCommandOptions: (_parsed, { context }) => {
|
|
380
396
|
return {
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
|
|
69
69
|
<script setup>
|
|
70
70
|
import { computed, reactive } from "vue";
|
|
71
|
-
import { validateOperationSection } from "@jskit-ai/http-runtime/shared/validators/operationValidation";
|
|
72
71
|
import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
|
|
72
|
+
import { WORKSPACES_TRANSPORT } from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
|
|
73
73
|
import { workspaceResource } from "@jskit-ai/workspaces-core/shared/resources/workspaceResource";
|
|
74
74
|
import { useAddEdit } from "@jskit-ai/users-web/client/composables/useAddEdit";
|
|
75
75
|
import { buildWorkspaceQueryKey } from "../support/workspaceQueryKeys.js";
|
|
@@ -89,16 +89,12 @@ const addEdit = useAddEdit({
|
|
|
89
89
|
buildWorkspaceQueryKey("profile", surfaceId, scopeParamValue),
|
|
90
90
|
viewPermissions: ["workspace.settings.view", "workspace.settings.update"],
|
|
91
91
|
savePermissions: ["workspace.settings.update"],
|
|
92
|
+
transport: WORKSPACES_TRANSPORT,
|
|
92
93
|
placementSource: "workspaces-web.workspace-profile-view",
|
|
93
94
|
fallbackLoadError: "Unable to load workspace profile.",
|
|
94
95
|
fieldErrorKeys: ["name", "avatarUrl"],
|
|
95
96
|
model: workspaceProfileForm,
|
|
96
|
-
|
|
97
|
-
validateOperationSection({
|
|
98
|
-
operation: workspaceResource.operations.patch,
|
|
99
|
-
section: "bodyValidator",
|
|
100
|
-
value: rawPayload
|
|
101
|
-
}),
|
|
97
|
+
input: workspaceResource.operations.patch.body,
|
|
102
98
|
mapLoadedToModel: (model, payload = {}) => {
|
|
103
99
|
model.name = String(payload?.name || "");
|
|
104
100
|
model.avatarUrl = String(payload?.avatarUrl || "");
|
|
@@ -168,8 +168,8 @@
|
|
|
168
168
|
|
|
169
169
|
<script setup>
|
|
170
170
|
import { computed, reactive } from "vue";
|
|
171
|
-
import { validateOperationSection } from "@jskit-ai/http-runtime/shared/validators/operationValidation";
|
|
172
171
|
import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
|
|
172
|
+
import { WORKSPACE_SETTINGS_TRANSPORT } from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
|
|
173
173
|
import { workspaceSettingsResource } from "@jskit-ai/workspaces-core/shared/resources/workspaceSettingsResource";
|
|
174
174
|
import {
|
|
175
175
|
DEFAULT_WORKSPACE_DARK_PALETTE,
|
|
@@ -207,6 +207,7 @@ const addEdit = useAddEdit({
|
|
|
207
207
|
buildWorkspaceQueryKey("settings", surfaceId, scopeParamValue),
|
|
208
208
|
viewPermissions: ["workspace.settings.view", "workspace.settings.update"],
|
|
209
209
|
savePermissions: ["workspace.settings.update"],
|
|
210
|
+
transport: WORKSPACE_SETTINGS_TRANSPORT,
|
|
210
211
|
placementSource: "workspaces-web.workspace-settings-view",
|
|
211
212
|
fallbackLoadError: "Unable to load workspace settings.",
|
|
212
213
|
fieldErrorKeys: [
|
|
@@ -224,12 +225,7 @@ const addEdit = useAddEdit({
|
|
|
224
225
|
matches: matchesWorkspaceRealtime
|
|
225
226
|
},
|
|
226
227
|
model: workspaceSettingsForm,
|
|
227
|
-
|
|
228
|
-
validateOperationSection({
|
|
229
|
-
operation: workspaceSettingsResource.operations.patch,
|
|
230
|
-
section: "bodyValidator",
|
|
231
|
-
value: rawPayload
|
|
232
|
-
}),
|
|
228
|
+
input: workspaceSettingsResource.operations.patch.body,
|
|
233
229
|
mapLoadedToModel: (model, payload = {}) => {
|
|
234
230
|
const settings = payload?.settings && typeof payload.settings === "object" ? payload.settings : {};
|
|
235
231
|
const normalizedTheme = resolveWorkspaceThemePalettes(settings);
|
|
@@ -8,6 +8,10 @@ import {
|
|
|
8
8
|
import { useShellWebErrorRuntime } from "@jskit-ai/shell-web/client/error";
|
|
9
9
|
import { normalizeWorkspaceList } from "../lib/bootstrap.js";
|
|
10
10
|
import { ROUTE_VISIBILITY_PUBLIC } from "@jskit-ai/kernel/shared/support/visibility";
|
|
11
|
+
import {
|
|
12
|
+
WORKSPACES_TRANSPORT,
|
|
13
|
+
WORKSPACE_INVITE_REDEEM_TRANSPORT
|
|
14
|
+
} from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
|
|
11
15
|
import { useCommand } from "@jskit-ai/users-web/client/composables/useCommand";
|
|
12
16
|
import { useView } from "@jskit-ai/users-web/client/composables/useView";
|
|
13
17
|
import { usePaths } from "@jskit-ai/users-web/client/composables/usePaths";
|
|
@@ -102,6 +106,7 @@ const redeemInviteCommand = useCommand({
|
|
|
102
106
|
ownershipFilter: OWNERSHIP_PUBLIC,
|
|
103
107
|
apiSuffix: "/workspace/invitations/redeem",
|
|
104
108
|
writeMethod: "POST",
|
|
109
|
+
transport: WORKSPACE_INVITE_REDEEM_TRANSPORT,
|
|
105
110
|
fallbackRunError: "Unable to respond to invitation.",
|
|
106
111
|
suppressSuccessMessage: true,
|
|
107
112
|
model: redeemInviteModel,
|
|
@@ -118,6 +123,7 @@ const createWorkspaceCommand = useCommand({
|
|
|
118
123
|
ownershipFilter: OWNERSHIP_PUBLIC,
|
|
119
124
|
apiSuffix: "/workspaces",
|
|
120
125
|
writeMethod: "POST",
|
|
126
|
+
transport: WORKSPACES_TRANSPORT,
|
|
121
127
|
fallbackRunError: "Unable to create workspace.",
|
|
122
128
|
suppressSuccessMessage: true,
|
|
123
129
|
model: createWorkspaceModel,
|
|
@@ -4,6 +4,7 @@ import UsersWorkspaceToolsWidget from "../components/UsersWorkspaceToolsWidget.v
|
|
|
4
4
|
import UsersWorkspaceSettingsMenuItem from "../components/UsersWorkspaceSettingsMenuItem.vue";
|
|
5
5
|
import UsersWorkspaceMembersMenuItem from "../components/UsersWorkspaceMembersMenuItem.vue";
|
|
6
6
|
import MembersAdminClientElement from "../components/MembersAdminClientElement.vue";
|
|
7
|
+
import { registerBootstrapPayloadHandler } from "@jskit-ai/shell-web/client/bootstrap";
|
|
7
8
|
import { createBootstrapPlacementRuntime } from "../runtime/bootstrapPlacementRuntime.js";
|
|
8
9
|
import {
|
|
9
10
|
WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY,
|
|
@@ -15,8 +16,8 @@ class WorkspacesWebClientProvider {
|
|
|
15
16
|
static dependsOn = ["users.web.client"];
|
|
16
17
|
|
|
17
18
|
register(app) {
|
|
18
|
-
if (!app || typeof app.singleton !== "function") {
|
|
19
|
-
throw new Error("WorkspacesWebClientProvider requires application singleton().");
|
|
19
|
+
if (!app || typeof app.singleton !== "function" || typeof app.tag !== "function") {
|
|
20
|
+
throw new Error("WorkspacesWebClientProvider requires application singleton()/tag().");
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
app.singleton("workspaces.web.profile.menu.surface-switch-item", () => UsersProfileSurfaceSwitchMenuItem);
|
|
@@ -26,6 +27,22 @@ class WorkspacesWebClientProvider {
|
|
|
26
27
|
app.singleton("workspaces.web.workspace-members.menu-item", () => UsersWorkspaceMembersMenuItem);
|
|
27
28
|
app.singleton("workspaces.web.members-admin.element", () => MembersAdminClientElement);
|
|
28
29
|
app.singleton("workspaces.web.bootstrap-placement.runtime", (scope) => createBootstrapPlacementRuntime({ app: scope }));
|
|
30
|
+
registerBootstrapPayloadHandler(app, "workspaces.web.bootstrap.handler", (scope) => {
|
|
31
|
+
const runtime = scope.make("workspaces.web.bootstrap-placement.runtime");
|
|
32
|
+
return Object.freeze({
|
|
33
|
+
handlerId: "workspaces.web.bootstrap",
|
|
34
|
+
order: 100,
|
|
35
|
+
resolveBootstrapRequest(input = {}) {
|
|
36
|
+
return runtime.resolveBootstrapRequest(input);
|
|
37
|
+
},
|
|
38
|
+
applyBootstrapPayload(input = {}) {
|
|
39
|
+
return runtime.applyBootstrapPayload(input);
|
|
40
|
+
},
|
|
41
|
+
handleBootstrapError(input = {}) {
|
|
42
|
+
return runtime.handleBootstrapError(input);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
29
46
|
app.singleton("workspaces.web.scope-support", () => createWorkspaceScopeSupport());
|
|
30
47
|
}
|
|
31
48
|
|