@jskit-ai/workspaces-web 0.1.139-oldline.2 → 0.1.139
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +247 -9
- package/patterns/workspace-surfaces/PATTERN.md +63 -0
- package/src/client/account-settings/accountSettingsInvitesRuntime.js +2 -2
- package/src/client/account-settings/useAccountSettingsInvitesSectionRuntime.js +3 -3
- package/src/client/components/MembersAdminClientElement.vue +1 -1
- package/src/client/components/WorkspaceInviteLanding.vue +4 -4
- package/src/client/components/WorkspaceMembersClientElement.vue +6 -6
- package/src/client/components/{UsersWorkspaceMembersMenuItem.vue → WorkspaceMembersMenuItem.vue} +2 -2
- package/src/client/components/{UsersWorkspacePermissionMenuItem.vue → WorkspacePermissionMenuItem.vue} +3 -3
- package/src/client/components/{UsersProfileSurfaceSwitchMenuItem.vue → WorkspaceProfileSurfaceSwitchMenuItem.vue} +1 -1
- package/src/client/components/{UsersWorkspaceSelector.vue → WorkspaceSelector.vue} +1 -1
- package/src/client/components/{UsersWorkspaceSettingsMenuItem.vue → WorkspaceSettingsMenuItem.vue} +2 -2
- package/src/client/components/WorkspacesClientElement.vue +13 -13
- package/src/client/composables/useWorkspaceRouteContext.js +1 -1
- package/src/client/index.js +0 -5
- package/src/client/lib/surfaceAccessPolicy.js +4 -1
- package/src/client/providers/WorkspacesWebClientProvider.js +54 -50
- package/src/client/runtime/bootstrapPlacementRuntime.js +18 -32
- package/src/client/runtime/bootstrapPlacementRuntimeHelpers.js +4 -4
- package/test/bootstrapPlacementRuntime.test.js +40 -125
- package/test/packageMetadataOwnership.test.js +19 -0
- package/test/settingsPlacementContract.test.js +87 -389
- package/test/{usersWorkspaceSelectorContract.test.js → workspaceSelectorContract.test.js} +3 -3
- package/package.descriptor.mjs +0 -492
- package/src/client/lib/httpClient.js +0 -10
- package/src/client/lib/permissions.js +0 -27
- package/test/packageDescriptorOwnership.test.js +0 -16
- /package/{templates → patterns/workspace-surfaces/example}/packages/main/src/client/components/AccountPendingInvitesCue.vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/packages/main/src/client/components/AccountSettingsInvitesSection.vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/components/WorkspaceNotFoundCard.vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/composables/useWorkspaceNotFoundState.js +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/pages/admin/members/index.vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/pages/admin/workspace/settings/index.vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/pages/admin/workspace/settings.vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/pages/invite/[token].vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/surfaces/admin/index.vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/surfaces/admin/root.vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/surfaces/app/index.vue +0 -0
- /package/{templates → patterns/workspace-surfaces/example}/src/surfaces/app/root.vue +0 -0
- /package/src/client/components/{UsersWorkspaceToolsWidget.vue → WorkspaceToolsWidget.vue} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/workspaces-web",
|
|
3
|
-
"version": "0.1.139
|
|
3
|
+
"version": "0.1.139",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -14,19 +14,257 @@
|
|
|
14
14
|
"./client/composables/useWorkspaceRouteContext": "./src/client/composables/useWorkspaceRouteContext.js"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@
|
|
18
|
-
"@jskit-ai/
|
|
19
|
-
"@jskit-ai/
|
|
20
|
-
"@jskit-ai/
|
|
21
|
-
"@jskit-ai/
|
|
22
|
-
"@jskit-ai/users-
|
|
23
|
-
"@jskit-ai/
|
|
24
|
-
"@
|
|
17
|
+
"@jskit-ai/auth-web": "0.1.160",
|
|
18
|
+
"@jskit-ai/http-web": "0.1.5",
|
|
19
|
+
"@jskit-ai/kernel": "0.1.160",
|
|
20
|
+
"@jskit-ai/shell-web": "0.1.164",
|
|
21
|
+
"@jskit-ai/users-core": "0.1.173",
|
|
22
|
+
"@jskit-ai/users-web": "0.1.178",
|
|
23
|
+
"@jskit-ai/workspaces-core": "0.1.138",
|
|
24
|
+
"@mdi/js": "^7.4.47"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"@tanstack/vue-query": "^5.90.5",
|
|
28
28
|
"vue": "^3.5.13",
|
|
29
29
|
"vue-router": "^5.0.4",
|
|
30
30
|
"vuetify": "^4.0.0"
|
|
31
|
+
},
|
|
32
|
+
"description": "Workspace web module: workspace selector, tools widget, workspace surfaces, members UI, and settings hosts.",
|
|
33
|
+
"jskit": {
|
|
34
|
+
"kind": "runtime",
|
|
35
|
+
"capabilities": {
|
|
36
|
+
"provides": [
|
|
37
|
+
"workspaces.web"
|
|
38
|
+
],
|
|
39
|
+
"requires": [
|
|
40
|
+
"runtime.http-web",
|
|
41
|
+
"users.web",
|
|
42
|
+
"workspaces.core"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"runtime": {
|
|
46
|
+
"server": {
|
|
47
|
+
"providers": []
|
|
48
|
+
},
|
|
49
|
+
"client": {
|
|
50
|
+
"providers": [
|
|
51
|
+
{
|
|
52
|
+
"entrypoint": "src/client/providers/WorkspacesWebClientProvider.js",
|
|
53
|
+
"export": "WorkspacesWebClientProvider"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"metadata": {
|
|
59
|
+
"apiSummary": {
|
|
60
|
+
"surfaces": [
|
|
61
|
+
{
|
|
62
|
+
"subpath": "./client",
|
|
63
|
+
"summary": "Exports workspaces-web client provider registration surface."
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"subpath": "./client/components/AccountSettingsInvitesSection",
|
|
67
|
+
"summary": "Exports the default account invites section component used by multihoming installs."
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"subpath": "./client/components/WorkspaceInviteLanding",
|
|
71
|
+
"summary": "Exports the default public workspace invite landing component."
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"subpath": "./client/providers/WorkspacesWebClientProvider",
|
|
75
|
+
"summary": "Exports workspaces-web client provider class."
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"subpath": "./client/composables/useWorkspaceRouteContext",
|
|
79
|
+
"summary": "Exports workspace route context composable."
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
"ui": {
|
|
84
|
+
"placements": {
|
|
85
|
+
"outlets": [
|
|
86
|
+
{
|
|
87
|
+
"target": "admin-settings:primary-menu",
|
|
88
|
+
"surfaces": [
|
|
89
|
+
"admin"
|
|
90
|
+
],
|
|
91
|
+
"source": "patterns/workspace-surfaces/example/src/pages/admin/workspace/settings.vue"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"target": "admin-cog:primary-menu",
|
|
95
|
+
"surfaces": [
|
|
96
|
+
"admin"
|
|
97
|
+
],
|
|
98
|
+
"source": "src/client/components/WorkspaceToolsWidget.vue"
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
"topology": {
|
|
102
|
+
"placements": [
|
|
103
|
+
{
|
|
104
|
+
"id": "page.section-nav",
|
|
105
|
+
"owner": "admin-settings",
|
|
106
|
+
"description": "Navigation between workspace admin settings child pages.",
|
|
107
|
+
"surfaces": [
|
|
108
|
+
"admin"
|
|
109
|
+
],
|
|
110
|
+
"variants": {
|
|
111
|
+
"compact": {
|
|
112
|
+
"outlet": "admin-settings:primary-menu",
|
|
113
|
+
"renderers": {
|
|
114
|
+
"link": "local.main.ui.surface-aware-menu-link-item"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"medium": {
|
|
118
|
+
"outlet": "admin-settings:primary-menu",
|
|
119
|
+
"renderers": {
|
|
120
|
+
"link": "local.main.ui.surface-aware-menu-link-item"
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"expanded": {
|
|
124
|
+
"outlet": "admin-settings:primary-menu",
|
|
125
|
+
"renderers": {
|
|
126
|
+
"link": "local.main.ui.surface-aware-menu-link-item"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"id": "admin.tools-menu",
|
|
133
|
+
"description": "Admin surface tools menu actions.",
|
|
134
|
+
"surfaces": [
|
|
135
|
+
"admin"
|
|
136
|
+
],
|
|
137
|
+
"variants": {
|
|
138
|
+
"compact": {
|
|
139
|
+
"outlet": "admin-cog:primary-menu",
|
|
140
|
+
"renderers": {
|
|
141
|
+
"link": "local.main.ui.surface-aware-menu-link-item"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"medium": {
|
|
145
|
+
"outlet": "admin-cog:primary-menu",
|
|
146
|
+
"renderers": {
|
|
147
|
+
"link": "local.main.ui.surface-aware-menu-link-item"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"expanded": {
|
|
151
|
+
"outlet": "admin-cog:primary-menu",
|
|
152
|
+
"renderers": {
|
|
153
|
+
"link": "local.main.ui.surface-aware-menu-link-item"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
"contributions": [
|
|
161
|
+
{
|
|
162
|
+
"id": "workspaces.workspace.menu.app",
|
|
163
|
+
"target": "shell.primary-nav",
|
|
164
|
+
"kind": "link",
|
|
165
|
+
"surfaces": [
|
|
166
|
+
"app"
|
|
167
|
+
],
|
|
168
|
+
"order": 50,
|
|
169
|
+
"when": "auth.authenticated === true",
|
|
170
|
+
"source": "patterns/workspace-surfaces/example/src/surfaces/app/index.vue"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"id": "workspaces.workspace.menu.admin",
|
|
174
|
+
"target": "shell.primary-nav",
|
|
175
|
+
"kind": "link",
|
|
176
|
+
"surfaces": [
|
|
177
|
+
"admin"
|
|
178
|
+
],
|
|
179
|
+
"order": 60,
|
|
180
|
+
"when": "auth.authenticated === true",
|
|
181
|
+
"source": "patterns/workspace-surfaces/example/src/surfaces/admin/index.vue"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"id": "workspaces.profile.menu.surface-switch",
|
|
185
|
+
"target": "auth.profile-menu",
|
|
186
|
+
"kind": "component",
|
|
187
|
+
"surfaces": [
|
|
188
|
+
"*"
|
|
189
|
+
],
|
|
190
|
+
"order": 100,
|
|
191
|
+
"componentToken": "workspaces.web.profile.menu.surface-switch-item",
|
|
192
|
+
"when": "auth.authenticated === true",
|
|
193
|
+
"source": "src/client/components/WorkspaceProfileSurfaceSwitchMenuItem.vue"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"id": "workspaces.workspace.selector",
|
|
197
|
+
"target": "shell.identity",
|
|
198
|
+
"kind": "component",
|
|
199
|
+
"surfaces": [
|
|
200
|
+
"*"
|
|
201
|
+
],
|
|
202
|
+
"order": 200,
|
|
203
|
+
"componentToken": "workspaces.web.workspace.selector",
|
|
204
|
+
"when": "auth.authenticated === true",
|
|
205
|
+
"source": "src/client/components/WorkspaceSelector.vue"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"id": "workspaces.account.invites.cue",
|
|
209
|
+
"target": "shell.status",
|
|
210
|
+
"kind": "component",
|
|
211
|
+
"surfaces": [
|
|
212
|
+
"*"
|
|
213
|
+
],
|
|
214
|
+
"order": 850,
|
|
215
|
+
"componentToken": "local.main.account.pending-invites.cue",
|
|
216
|
+
"when": "auth.authenticated === true",
|
|
217
|
+
"source": "patterns/workspace-surfaces/example/packages/main/src/client/components/AccountPendingInvitesCue.vue"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"id": "workspaces.account.settings.invites",
|
|
221
|
+
"target": "settings.sections",
|
|
222
|
+
"owner": "account-settings",
|
|
223
|
+
"kind": "component",
|
|
224
|
+
"surfaces": [
|
|
225
|
+
"account"
|
|
226
|
+
],
|
|
227
|
+
"order": 400,
|
|
228
|
+
"componentToken": "local.main.account-settings.section.invites",
|
|
229
|
+
"when": "auth.authenticated === true && workspaceInvitesEnabled === true",
|
|
230
|
+
"source": "patterns/workspace-surfaces/example/packages/main/src/client/components/AccountSettingsInvitesSection.vue"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"id": "workspaces.workspace.tools.widget",
|
|
234
|
+
"target": "shell.status",
|
|
235
|
+
"kind": "component",
|
|
236
|
+
"surfaces": [
|
|
237
|
+
"admin"
|
|
238
|
+
],
|
|
239
|
+
"order": 900,
|
|
240
|
+
"componentToken": "workspaces.web.workspace.tools.widget",
|
|
241
|
+
"source": "src/client/components/WorkspaceToolsWidget.vue"
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"id": "workspaces.workspace.menu.workspace-settings",
|
|
245
|
+
"target": "admin.tools-menu",
|
|
246
|
+
"kind": "component",
|
|
247
|
+
"surfaces": [
|
|
248
|
+
"admin"
|
|
249
|
+
],
|
|
250
|
+
"order": 100,
|
|
251
|
+
"componentToken": "workspaces.web.workspace-settings.menu-item",
|
|
252
|
+
"source": "src/client/components/WorkspaceSettingsMenuItem.vue"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"id": "workspaces.workspace.menu.members",
|
|
256
|
+
"target": "admin.tools-menu",
|
|
257
|
+
"kind": "component",
|
|
258
|
+
"surfaces": [
|
|
259
|
+
"admin"
|
|
260
|
+
],
|
|
261
|
+
"order": 200,
|
|
262
|
+
"componentToken": "workspaces.web.workspace-members.menu-item",
|
|
263
|
+
"source": "src/client/components/WorkspaceMembersMenuItem.vue"
|
|
264
|
+
}
|
|
265
|
+
]
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
31
269
|
}
|
|
32
270
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: workspaces/workspace-surfaces
|
|
3
|
+
title: Workspace application and administration surfaces
|
|
4
|
+
summary: Compose workspace selection, invitation, member administration, settings, and responsive navigation using JSKIT workspace web APIs.
|
|
5
|
+
keywords: admin, invite, member, navigation, settings, surface, switcher, workspace
|
|
6
|
+
requires: @jskit-ai/workspaces-core, @jskit-ai/workspaces-web, @jskit-ai/shell-web
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Workspace application and administration surfaces
|
|
10
|
+
|
|
11
|
+
## Use when
|
|
12
|
+
|
|
13
|
+
Use this pattern when the product has workspace-scoped app and administration
|
|
14
|
+
surfaces, invitations, member management, or workspace switching.
|
|
15
|
+
|
|
16
|
+
## Do not use when
|
|
17
|
+
|
|
18
|
+
Do not use this pattern for a single-owner application, or copy its whole
|
|
19
|
+
surface tree when only one workspace widget is needed.
|
|
20
|
+
|
|
21
|
+
## Product decisions
|
|
22
|
+
|
|
23
|
+
Choose public invitation routes, application/admin surface ids, workspace
|
|
24
|
+
selector behavior, member-management permissions, settings sections, and the
|
|
25
|
+
empty or not-found experience.
|
|
26
|
+
|
|
27
|
+
## Framework APIs
|
|
28
|
+
|
|
29
|
+
Use the workspace client provider, components, and composables exported by
|
|
30
|
+
`@jskit-ai/workspaces-web` together with JSKIT shell placements and routes.
|
|
31
|
+
|
|
32
|
+
## Invariants
|
|
33
|
+
|
|
34
|
+
- Route workspace slug, selected workspace, and server scope stay synchronized.
|
|
35
|
+
- Invitation acceptance is public only where the server contract permits it.
|
|
36
|
+
- Administrative UI visibility never substitutes for server authorization.
|
|
37
|
+
- Query and route state hydrate immediately on warm-cache navigation.
|
|
38
|
+
- Loading uses skeletons; mutation failures use toasts without layout movement.
|
|
39
|
+
- Navigation is composed through semantic placements and registered tokens.
|
|
40
|
+
|
|
41
|
+
## Example files
|
|
42
|
+
|
|
43
|
+
`example/` contains workspace app/admin roots, starter pages, invitation route,
|
|
44
|
+
member and settings routes, not-found state, app-owned invitation widgets, and
|
|
45
|
+
the components that an application's client provider registers.
|
|
46
|
+
|
|
47
|
+
## Variation points
|
|
48
|
+
|
|
49
|
+
Change surfaces, routes, section owners, labels, icons, placement order,
|
|
50
|
+
workspace-not-found copy, member operations, and invitation presentation.
|
|
51
|
+
|
|
52
|
+
## Verification
|
|
53
|
+
|
|
54
|
+
Exercise direct workspace URLs, selection and switching, invitations, members,
|
|
55
|
+
settings, not-found state, browser back/forward, forbidden access, and all
|
|
56
|
+
responsive navigation variants.
|
|
57
|
+
|
|
58
|
+
## Avoid
|
|
59
|
+
|
|
60
|
+
- defaulting silently to another workspace after an invalid route
|
|
61
|
+
- unscoped queries
|
|
62
|
+
- inline mutation error banners
|
|
63
|
+
- generated placement or source mutation machinery
|
|
@@ -50,7 +50,7 @@ function createAccountSettingsInvitesRuntime({
|
|
|
50
50
|
message: normalizedDecision === "accept" ? "Invitation accepted." : "Invitation refused.",
|
|
51
51
|
severity: "success",
|
|
52
52
|
channel: "snackbar",
|
|
53
|
-
dedupeKey: `
|
|
53
|
+
dedupeKey: `workspaces-web.account-settings-runtime:invite-${normalizedDecision}:${token}`
|
|
54
54
|
});
|
|
55
55
|
} catch (error) {
|
|
56
56
|
const statusCode = resolveErrorStatusCode(error);
|
|
@@ -63,7 +63,7 @@ function createAccountSettingsInvitesRuntime({
|
|
|
63
63
|
: String(error?.message || fallbackMessage),
|
|
64
64
|
severity: "error",
|
|
65
65
|
channel: "banner",
|
|
66
|
-
dedupeKey: `
|
|
66
|
+
dedupeKey: `workspaces-web.account-settings-runtime:invite-${normalizedDecision}-error:${token}`
|
|
67
67
|
});
|
|
68
68
|
} finally {
|
|
69
69
|
inviteAction.value = {
|
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
} from "@jskit-ai/shell-web/client/placement";
|
|
7
7
|
import { useShellWebErrorRuntime } from "@jskit-ai/shell-web/client/error";
|
|
8
8
|
import { ROUTE_VISIBILITY_PUBLIC } from "@jskit-ai/kernel/shared/support/visibility";
|
|
9
|
-
import { useCommand } from "@jskit-ai/
|
|
10
|
-
import { usePaths } from "@jskit-ai/
|
|
11
|
-
import { useView } from "@jskit-ai/
|
|
9
|
+
import { useCommand } from "@jskit-ai/http-web/client/composables/useCommand";
|
|
10
|
+
import { usePaths } from "@jskit-ai/shell-web/client/navigation/usePaths";
|
|
11
|
+
import { useView } from "@jskit-ai/http-web/client/composables/useView";
|
|
12
12
|
import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
13
13
|
import { WORKSPACE_INVITE_REDEEM_TRANSPORT } from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
|
|
14
14
|
import { useWorkspaceSurfaceId } from "../composables/useWorkspaceSurfaceId.js";
|
|
@@ -195,7 +195,7 @@ import { computed, toRefs, unref } from "vue";
|
|
|
195
195
|
import { mdiContentCopy } from "@mdi/js";
|
|
196
196
|
import { formatDateTime as formatKernelDateTime } from "@jskit-ai/kernel/shared/support";
|
|
197
197
|
import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
198
|
-
import { requireBoolean, requireFunction, requireRecord } from "@jskit-ai/
|
|
198
|
+
import { requireBoolean, requireFunction, requireRecord } from "@jskit-ai/http-web/client/support/contractGuards";
|
|
199
199
|
|
|
200
200
|
const props = defineProps({
|
|
201
201
|
forms: {
|
|
@@ -62,12 +62,12 @@
|
|
|
62
62
|
import { computed, onMounted } from "vue";
|
|
63
63
|
import { useRoute, useRouter } from "vue-router";
|
|
64
64
|
import { useAuthStore } from "@jskit-ai/auth-web/client";
|
|
65
|
-
import { useEndpointResource } from "@jskit-ai/
|
|
65
|
+
import { useEndpointResource } from "@jskit-ai/http-web/client/composables/useEndpointResource";
|
|
66
66
|
import {
|
|
67
67
|
WORKSPACE_INVITATION_RESOLVE_TRANSPORT,
|
|
68
68
|
WORKSPACE_INVITE_REDEEM_TRANSPORT
|
|
69
69
|
} from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
|
|
70
|
-
import {
|
|
70
|
+
import { httpWebClient } from "@jskit-ai/http-web/client/lib/httpClient";
|
|
71
71
|
|
|
72
72
|
const route = useRoute();
|
|
73
73
|
const router = useRouter();
|
|
@@ -84,7 +84,7 @@ const inviteResource = useEndpointResource({
|
|
|
84
84
|
queryKey: computed(() => ["workspaces-web", "invite-landing", token.value]),
|
|
85
85
|
path: "/api/workspace/invitations/resolve",
|
|
86
86
|
enabled: computed(() => Boolean(token.value)),
|
|
87
|
-
client:
|
|
87
|
+
client: httpWebClient,
|
|
88
88
|
readQuery: inviteQuery,
|
|
89
89
|
transport: WORKSPACE_INVITATION_RESOLVE_TRANSPORT,
|
|
90
90
|
fallbackLoadError: "Unable to load invitation."
|
|
@@ -94,7 +94,7 @@ const redeemResource = useEndpointResource({
|
|
|
94
94
|
queryKey: computed(() => ["workspaces-web", "invite-landing", "redeem", token.value]),
|
|
95
95
|
path: "/api/workspace/invitations/redeem",
|
|
96
96
|
enabled: false,
|
|
97
|
-
client:
|
|
97
|
+
client: httpWebClient,
|
|
98
98
|
writeMethod: "POST",
|
|
99
99
|
transport: WORKSPACE_INVITE_REDEEM_TRANSPORT,
|
|
100
100
|
fallbackSaveError: "Unable to accept invitation."
|
|
@@ -41,12 +41,12 @@ import {
|
|
|
41
41
|
WORKSPACE_SETTINGS_TRANSPORT
|
|
42
42
|
} from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
|
|
43
43
|
import MembersAdminClientElement from "./MembersAdminClientElement.vue";
|
|
44
|
-
import { useCommand } from "@jskit-ai/
|
|
45
|
-
import { useList } from "@jskit-ai/
|
|
46
|
-
import { useView } from "@jskit-ai/
|
|
47
|
-
import { usePaths } from "@jskit-ai/
|
|
48
|
-
import { useAccess } from "@jskit-ai/
|
|
49
|
-
import { useUiFeedback } from "@jskit-ai/
|
|
44
|
+
import { useCommand } from "@jskit-ai/http-web/client/composables/useCommand";
|
|
45
|
+
import { useList } from "@jskit-ai/http-web/client/composables/useList";
|
|
46
|
+
import { useView } from "@jskit-ai/http-web/client/composables/useView";
|
|
47
|
+
import { usePaths } from "@jskit-ai/shell-web/client/navigation/usePaths";
|
|
48
|
+
import { useAccess } from "@jskit-ai/http-web/client/composables/useAccess";
|
|
49
|
+
import { useUiFeedback } from "@jskit-ai/http-web/client/composables/useUiFeedback";
|
|
50
50
|
import { useWorkspaceRouteContext } from "../composables/useWorkspaceRouteContext.js";
|
|
51
51
|
import { createWorkspaceRealtimeMatcher } from "../support/realtimeWorkspace.js";
|
|
52
52
|
import { buildWorkspaceQueryKey } from "../support/workspaceQueryKeys.js";
|
package/src/client/components/{UsersWorkspaceMembersMenuItem.vue → WorkspaceMembersMenuItem.vue}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { mdiAccountGroupOutline } from "@mdi/js";
|
|
3
|
-
import
|
|
3
|
+
import WorkspacePermissionMenuItem from "./WorkspacePermissionMenuItem.vue";
|
|
4
4
|
|
|
5
5
|
const props = defineProps({
|
|
6
6
|
label: {
|
|
@@ -25,7 +25,7 @@ const MEMBERS_MENU_PERMISSIONS = Object.freeze(["workspace.members.view", "works
|
|
|
25
25
|
</script>
|
|
26
26
|
|
|
27
27
|
<template>
|
|
28
|
-
<
|
|
28
|
+
<WorkspacePermissionMenuItem
|
|
29
29
|
:label="props.label"
|
|
30
30
|
:to="props.to"
|
|
31
31
|
:icon="props.icon"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { computed } from "vue";
|
|
3
|
-
import { useSurfaceRouteContext } from "@jskit-ai/
|
|
4
|
-
import { hasPermission, normalizePermissionList } from "@jskit-ai/
|
|
5
|
-
import { usePaths } from "@jskit-ai/
|
|
3
|
+
import { useSurfaceRouteContext } from "@jskit-ai/shell-web/client/navigation/useSurfaceRouteContext";
|
|
4
|
+
import { hasPermission, normalizePermissionList } from "@jskit-ai/http-web/client/lib/permissions";
|
|
5
|
+
import { usePaths } from "@jskit-ai/shell-web/client/navigation/usePaths";
|
|
6
6
|
|
|
7
7
|
const props = defineProps({
|
|
8
8
|
label: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { computed } from "vue";
|
|
3
|
-
import { useSurfaceRouteContext } from "@jskit-ai/
|
|
3
|
+
import { useSurfaceRouteContext } from "@jskit-ai/shell-web/client/navigation/useSurfaceRouteContext";
|
|
4
4
|
import { resolveProfileSurfaceMenuLinks } from "../lib/profileSurfaceMenuLinks.js";
|
|
5
5
|
|
|
6
6
|
const props = defineProps({
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { TENANCY_MODE_NONE } from "@jskit-ai/workspaces-core/shared/tenancyProfile";
|
|
10
10
|
import { mdiBriefcaseOutline } from "@mdi/js";
|
|
11
11
|
import { findWorkspaceBySlug, normalizeWorkspaceEntry, normalizeWorkspaceList } from "../lib/bootstrap.js";
|
|
12
|
-
import { usePaths } from "@jskit-ai/
|
|
12
|
+
import { usePaths } from "@jskit-ai/shell-web/client/navigation/usePaths";
|
|
13
13
|
import { resolveSurfaceSwitchTargetsFromPlacementContext, surfaceRequiresWorkspaceFromPlacementContext } from "../lib/workspaceSurfaceContext.js";
|
|
14
14
|
import { resolveWorkspaceSurfaceIdFromPlacementPathname, extractWorkspaceSlugFromSurfacePathname } from "../lib/workspaceSurfacePaths.js";
|
|
15
15
|
|
package/src/client/components/{UsersWorkspaceSettingsMenuItem.vue → WorkspaceSettingsMenuItem.vue}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { mdiCogOutline } from "@mdi/js";
|
|
3
|
-
import
|
|
3
|
+
import WorkspacePermissionMenuItem from "./WorkspacePermissionMenuItem.vue";
|
|
4
4
|
|
|
5
5
|
const props = defineProps({
|
|
6
6
|
label: {
|
|
@@ -28,7 +28,7 @@ const WORKSPACE_SETTINGS_MENU_PERMISSIONS = Object.freeze([
|
|
|
28
28
|
</script>
|
|
29
29
|
|
|
30
30
|
<template>
|
|
31
|
-
<
|
|
31
|
+
<WorkspacePermissionMenuItem
|
|
32
32
|
:label="props.label"
|
|
33
33
|
:to="props.to"
|
|
34
34
|
:icon="props.icon"
|
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
WORKSPACES_TRANSPORT,
|
|
13
13
|
WORKSPACE_INVITE_REDEEM_TRANSPORT
|
|
14
14
|
} from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
|
|
15
|
-
import { useCommand } from "@jskit-ai/
|
|
16
|
-
import { useView } from "@jskit-ai/
|
|
17
|
-
import { usePaths } from "@jskit-ai/
|
|
18
|
-
import { useRealtimeQueryInvalidation } from "@jskit-ai/
|
|
15
|
+
import { useCommand } from "@jskit-ai/http-web/client/composables/useCommand";
|
|
16
|
+
import { useView } from "@jskit-ai/http-web/client/composables/useView";
|
|
17
|
+
import { usePaths } from "@jskit-ai/shell-web/client/navigation/usePaths";
|
|
18
|
+
import { useRealtimeQueryInvalidation } from "@jskit-ai/http-web/client/composables/useRealtimeQueryInvalidation";
|
|
19
19
|
import { useWorkspaceSurfaceId } from "../composables/useWorkspaceSurfaceId.js";
|
|
20
20
|
import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
21
21
|
|
|
@@ -76,7 +76,7 @@ const redeemInviteModel = reactive({
|
|
|
76
76
|
token: "",
|
|
77
77
|
decision: ""
|
|
78
78
|
});
|
|
79
|
-
const bootstrapQueryKey = Object.freeze(["
|
|
79
|
+
const bootstrapQueryKey = Object.freeze(["workspaces-web", "bootstrap", "__none__"]);
|
|
80
80
|
const OWNERSHIP_PUBLIC = ROUTE_VISIBILITY_PUBLIC;
|
|
81
81
|
|
|
82
82
|
const bootstrapView = useView({
|
|
@@ -179,12 +179,12 @@ function reportFeedback({
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
errorRuntime.report({
|
|
182
|
-
source: "
|
|
182
|
+
source: "workspaces-web.workspaces-view",
|
|
183
183
|
message: normalizedMessage,
|
|
184
184
|
intent: "action-feedback",
|
|
185
185
|
severity,
|
|
186
186
|
channel,
|
|
187
|
-
dedupeKey: dedupeKey || `
|
|
187
|
+
dedupeKey: dedupeKey || `workspaces-web.workspaces-view:${severity}:${normalizedMessage}`,
|
|
188
188
|
dedupeWindowMs: 3000
|
|
189
189
|
});
|
|
190
190
|
}
|
|
@@ -235,7 +235,7 @@ async function openWorkspace(workspaceSlug) {
|
|
|
235
235
|
reportFeedback({
|
|
236
236
|
message: "Workspace surface is not configured.",
|
|
237
237
|
severity: "error",
|
|
238
|
-
dedupeKey: "
|
|
238
|
+
dedupeKey: "workspaces-web.workspaces-view:workspace-surface-missing"
|
|
239
239
|
});
|
|
240
240
|
return;
|
|
241
241
|
}
|
|
@@ -259,7 +259,7 @@ async function openWorkspace(workspaceSlug) {
|
|
|
259
259
|
reportFeedback({
|
|
260
260
|
message: String(error?.message || "Unable to open workspace."),
|
|
261
261
|
severity: "error",
|
|
262
|
-
dedupeKey: `
|
|
262
|
+
dedupeKey: `workspaces-web.workspaces-view:open-workspace:${normalizedSlug}`
|
|
263
263
|
});
|
|
264
264
|
} finally {
|
|
265
265
|
selectingWorkspaceSlug.value = "";
|
|
@@ -301,7 +301,7 @@ async function respondToInvite(invite, decision) {
|
|
|
301
301
|
reportFeedback({
|
|
302
302
|
message: "Invitation refused.",
|
|
303
303
|
severity: "success",
|
|
304
|
-
dedupeKey: `
|
|
304
|
+
dedupeKey: `workspaces-web.workspaces-view:invite-refused:${token}`
|
|
305
305
|
});
|
|
306
306
|
} catch (error) {
|
|
307
307
|
reportFeedback({
|
|
@@ -309,7 +309,7 @@ async function respondToInvite(invite, decision) {
|
|
|
309
309
|
error?.message || (normalizedDecision === "accept" ? "Unable to accept invite." : "Unable to refuse invite.")
|
|
310
310
|
),
|
|
311
311
|
severity: "error",
|
|
312
|
-
dedupeKey: `
|
|
312
|
+
dedupeKey: `workspaces-web.workspaces-view:invite-${normalizedDecision}:${token}`
|
|
313
313
|
});
|
|
314
314
|
} finally {
|
|
315
315
|
inviteAction.value = {
|
|
@@ -339,7 +339,7 @@ async function createWorkspace() {
|
|
|
339
339
|
reportFeedback({
|
|
340
340
|
message: "Workspace name is required.",
|
|
341
341
|
severity: "error",
|
|
342
|
-
dedupeKey: "
|
|
342
|
+
dedupeKey: "workspaces-web.workspaces-view:create-workspace-name-required"
|
|
343
343
|
});
|
|
344
344
|
return;
|
|
345
345
|
}
|
|
@@ -358,7 +358,7 @@ async function createWorkspace() {
|
|
|
358
358
|
reportFeedback({
|
|
359
359
|
message: String(error?.message || "Unable to create workspace."),
|
|
360
360
|
severity: "error",
|
|
361
|
-
dedupeKey: "
|
|
361
|
+
dedupeKey: "workspaces-web.workspaces-view:create-workspace-error"
|
|
362
362
|
});
|
|
363
363
|
}
|
|
364
364
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
|
-
import { useSurfaceRouteContext } from "@jskit-ai/
|
|
2
|
+
import { useSurfaceRouteContext } from "@jskit-ai/shell-web/client/navigation/useSurfaceRouteContext";
|
|
3
3
|
import { readWorkspaceRouteScope } from "../support/workspaceScopeSupport.js";
|
|
4
4
|
|
|
5
5
|
function useWorkspaceRouteContext() {
|
package/src/client/index.js
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import { WorkspacesWebClientProvider } from "./providers/WorkspacesWebClientProvider.js";
|
|
2
|
-
|
|
3
|
-
const clientProviders = Object.freeze([WorkspacesWebClientProvider]);
|
|
4
|
-
|
|
5
1
|
export { WorkspacesWebClientProvider } from "./providers/WorkspacesWebClientProvider.js";
|
|
6
2
|
export { default as WorkspaceMembersClientElement } from "./components/WorkspaceMembersClientElement.vue";
|
|
7
3
|
export { default as WorkspaceInviteLanding } from "./components/WorkspaceInviteLanding.vue";
|
|
8
|
-
export { clientProviders };
|
|
@@ -4,7 +4,10 @@ import {
|
|
|
4
4
|
normalizeRecord,
|
|
5
5
|
normalizeWorkspaceBootstrapStatusValue
|
|
6
6
|
} from "../support/runtimeNormalization.js";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
hasPermission,
|
|
9
|
+
normalizePermissionList
|
|
10
|
+
} from "@jskit-ai/http-web/client/lib/permissions";
|
|
8
11
|
|
|
9
12
|
const WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND = "not_found";
|
|
10
13
|
const WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN = "forbidden";
|