@jskit-ai/users-web 0.1.52 → 0.1.54
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 +14 -96
- package/package.json +16 -11
- package/src/client/account-settings/sections.js +74 -0
- package/src/client/composables/account-settings/accountSettingsRuntimeHelpers.js +2 -38
- package/src/client/composables/crud/crudLookupFieldRuntime.js +2 -2
- package/src/client/composables/internal/crudListParentTitleSupport.js +1 -1
- package/src/client/composables/internal/useOperationScope.js +12 -12
- package/src/client/composables/records/useAddEdit.js +2 -2
- package/src/client/composables/records/useList.js +3 -3
- package/src/client/composables/records/useView.js +2 -2
- package/src/client/composables/support/scopeHelpers.js +19 -19
- package/src/client/composables/useAccess.js +3 -3
- package/src/client/composables/useAccountSettingsRuntime.js +8 -156
- package/src/client/composables/useCommand.js +2 -2
- package/src/client/composables/useCrudListParentTitle.js +2 -2
- package/src/client/composables/usePaths.js +50 -38
- package/src/client/composables/useScopeRuntime.js +55 -27
- package/src/client/composables/useSurfaceRouteContext.js +1 -7
- package/src/client/index.js +0 -1
- package/src/client/lib/bootstrap.js +0 -63
- package/src/client/lib/httpClient.js +2 -59
- package/src/client/lib/theme.js +12 -189
- package/src/client/providers/UsersWebClientProvider.js +2 -25
- package/src/client/providers/bootUsersWebClientProvider.js +28 -0
- package/src/shared/toolsOutletContracts.js +1 -8
- package/templates/src/components/account/settings/AccountSettingsClientElement.vue +33 -21
- package/test/accountSettingsSections.test.js +79 -0
- package/test/exportsContract.test.js +2 -2
- package/test/scopeHelpers.test.js +6 -6
- package/test/settingsPlacementContract.test.js +4 -49
- package/test/theme.test.js +0 -56
- package/src/client/components/ConsoleSettingsClientElement.vue +0 -24
- package/src/client/components/MembersAdminClientElement.vue +0 -400
- package/src/client/components/UsersProfileSurfaceSwitchMenuItem.vue +0 -39
- package/src/client/components/UsersWorkspaceMembersMenuItem.vue +0 -36
- package/src/client/components/UsersWorkspacePermissionMenuItem.vue +0 -90
- package/src/client/components/UsersWorkspaceSelector.vue +0 -248
- package/src/client/components/UsersWorkspaceSettingsMenuItem.vue +0 -39
- package/src/client/components/UsersWorkspaceToolsWidget.vue +0 -12
- package/src/client/components/WorkspaceMembersClientElement.vue +0 -655
- package/src/client/components/WorkspaceProfileClientElement.vue +0 -116
- package/src/client/components/WorkspaceSettingsClientElement.vue +0 -102
- package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +0 -265
- package/src/client/components/WorkspacesClientElement.vue +0 -509
- package/src/client/composables/account-settings/accountSettingsInvitesRuntime.js +0 -88
- package/src/client/composables/useBootstrapQuery.js +0 -52
- package/src/client/composables/useWorkspaceRouteContext.js +0 -28
- package/src/client/composables/useWorkspaceSurfaceId.js +0 -43
- package/src/client/lib/menuIcons.js +0 -210
- package/src/client/lib/profileSurfaceMenuLinks.js +0 -142
- package/src/client/lib/surfaceAccessPolicy.js +0 -350
- package/src/client/lib/workspaceLinkResolver.js +0 -207
- package/src/client/lib/workspaceSurfaceContext.js +0 -82
- package/src/client/lib/workspaceSurfacePaths.js +0 -163
- package/src/client/providers/UsersWorkspacesClientProvider.js +0 -24
- package/src/client/runtime/bootstrapPlacementRouteGuards.js +0 -371
- package/src/client/runtime/bootstrapPlacementRuntime.js +0 -463
- package/src/client/runtime/bootstrapPlacementRuntimeConstants.js +0 -28
- package/src/client/runtime/bootstrapPlacementRuntimeHelpers.js +0 -147
- package/src/client/support/menuLinkTarget.js +0 -93
- package/src/client/support/realtimeWorkspace.js +0 -21
- package/src/client/support/runtimeNormalization.js +0 -27
- package/src/client/support/workspaceQueryKeys.js +0 -15
- package/templates/src/components/account/settings/AccountSettingsInvitesSection.vue +0 -77
- package/templates/src/pages/console/settings/index.vue +0 -8
- package/templates/src/pages/console/settings.vue +0 -32
- package/test/bootstrapPlacementRuntime.test.js +0 -1095
- package/test/menuIcons.test.js +0 -35
- package/test/menuLinkTarget.test.js +0 -116
- package/test/profileSurfaceMenuLinks.test.js +0 -207
- package/test/surfaceAccessPolicy.test.js +0 -129
- package/test/workspaceLinkResolver.test.js +0 -61
- package/test/workspaceSurfacePaths.test.js +0 -39
package/package.descriptor.mjs
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
HOME_TOOLS_OUTLET,
|
|
3
|
-
WORKSPACE_TOOLS_OUTLET
|
|
4
|
-
} from "./src/shared/toolsOutletContracts.js";
|
|
1
|
+
import { HOME_TOOLS_OUTLET } from "./src/shared/toolsOutletContracts.js";
|
|
5
2
|
|
|
6
3
|
export default Object.freeze({
|
|
7
4
|
packageVersion: 1,
|
|
8
5
|
packageId: "@jskit-ai/users-web",
|
|
9
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.54",
|
|
10
7
|
kind: "runtime",
|
|
11
8
|
description: "Users web module: account/profile UI plus shared users web widgets.",
|
|
12
9
|
dependsOn: [
|
|
13
10
|
"@jskit-ai/auth-web",
|
|
14
|
-
"@jskit-ai/console-web",
|
|
15
11
|
"@jskit-ai/http-runtime",
|
|
16
12
|
"@jskit-ai/shell-web",
|
|
17
13
|
"@jskit-ai/uploads-image-web",
|
|
@@ -80,24 +76,22 @@ export default Object.freeze({
|
|
|
80
76
|
},
|
|
81
77
|
{
|
|
82
78
|
subpath: "./client/composables/usePaths",
|
|
83
|
-
summary: "Exports surface
|
|
79
|
+
summary: "Exports surface route path resolver composable."
|
|
84
80
|
},
|
|
85
81
|
{
|
|
86
82
|
subpath: "./client/composables/useAccountSettingsRuntime",
|
|
87
83
|
summary: "Exports account settings runtime composable for app-owned settings UI."
|
|
88
84
|
},
|
|
89
85
|
{
|
|
90
|
-
subpath: "./client/
|
|
91
|
-
summary: "Exports
|
|
92
|
-
}
|
|
86
|
+
subpath: "./client/account-settings/sections",
|
|
87
|
+
summary: "Exports account settings section extension seam helpers."
|
|
88
|
+
}
|
|
93
89
|
],
|
|
94
90
|
containerTokens: {
|
|
95
91
|
server: [],
|
|
96
92
|
client: [
|
|
97
|
-
"users.web.profile.menu.surface-switch-item",
|
|
98
93
|
"users.web.home.tools.widget",
|
|
99
|
-
"users.web.profile.element"
|
|
100
|
-
"users.web.bootstrap-placement.runtime"
|
|
94
|
+
"users.web.profile.element"
|
|
101
95
|
]
|
|
102
96
|
}
|
|
103
97
|
},
|
|
@@ -109,30 +103,9 @@ export default Object.freeze({
|
|
|
109
103
|
defaultLinkComponentToken: HOME_TOOLS_OUTLET.defaultLinkComponentToken,
|
|
110
104
|
surfaces: ["home"],
|
|
111
105
|
source: "src/client/components/UsersHomeToolsWidget.vue"
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
target: WORKSPACE_TOOLS_OUTLET.target,
|
|
115
|
-
defaultLinkComponentToken: WORKSPACE_TOOLS_OUTLET.defaultLinkComponentToken,
|
|
116
|
-
surfaces: ["admin"],
|
|
117
|
-
source: "src/client/components/UsersWorkspaceToolsWidget.vue"
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
target: "console-settings:primary-menu",
|
|
121
|
-
defaultLinkComponentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
122
|
-
surfaces: ["console"],
|
|
123
|
-
source: "templates/src/pages/console/settings.vue"
|
|
124
106
|
}
|
|
125
107
|
],
|
|
126
108
|
contributions: [
|
|
127
|
-
{
|
|
128
|
-
id: "users.profile.menu.surface-switch",
|
|
129
|
-
target: "auth-profile-menu:primary-menu",
|
|
130
|
-
surfaces: ["*"],
|
|
131
|
-
order: 100,
|
|
132
|
-
componentToken: "users.web.profile.menu.surface-switch-item",
|
|
133
|
-
when: "auth.authenticated === true",
|
|
134
|
-
source: "mutations.text#users-web-profile-surface-switch-placement"
|
|
135
|
-
},
|
|
136
109
|
{
|
|
137
110
|
id: "users.profile.menu.settings",
|
|
138
111
|
target: "auth-profile-menu:primary-menu",
|
|
@@ -142,15 +115,6 @@ export default Object.freeze({
|
|
|
142
115
|
when: "auth.authenticated === true",
|
|
143
116
|
source: "mutations.text#users-web-profile-settings-placement"
|
|
144
117
|
},
|
|
145
|
-
{
|
|
146
|
-
id: "users.console.menu.settings",
|
|
147
|
-
target: "shell-layout:primary-menu",
|
|
148
|
-
surfaces: ["console"],
|
|
149
|
-
order: 100,
|
|
150
|
-
componentToken: "local.main.ui.menu-link-item",
|
|
151
|
-
when: "auth.authenticated === true",
|
|
152
|
-
source: "mutations.text#users-web-console-settings-placement"
|
|
153
|
-
},
|
|
154
118
|
{
|
|
155
119
|
id: "users.home.tools.widget",
|
|
156
120
|
target: "shell-layout:top-right",
|
|
@@ -178,13 +142,12 @@ export default Object.freeze({
|
|
|
178
142
|
runtime: {
|
|
179
143
|
"@tanstack/vue-query": "5.92.12",
|
|
180
144
|
"@mdi/js": "^7.4.47",
|
|
181
|
-
"@jskit-ai/
|
|
182
|
-
"@jskit-ai/
|
|
183
|
-
"@jskit-ai/
|
|
184
|
-
"@jskit-ai/
|
|
185
|
-
"@jskit-ai/
|
|
186
|
-
"@jskit-ai/
|
|
187
|
-
"@jskit-ai/users-core": "0.1.47",
|
|
145
|
+
"@jskit-ai/http-runtime": "0.1.38",
|
|
146
|
+
"@jskit-ai/realtime": "0.1.38",
|
|
147
|
+
"@jskit-ai/kernel": "0.1.39",
|
|
148
|
+
"@jskit-ai/shell-web": "0.1.38",
|
|
149
|
+
"@jskit-ai/uploads-image-web": "0.1.17",
|
|
150
|
+
"@jskit-ai/users-core": "0.1.49",
|
|
188
151
|
vuetify: "^4.0.0"
|
|
189
152
|
},
|
|
190
153
|
dev: {}
|
|
@@ -232,29 +195,6 @@ export default Object.freeze({
|
|
|
232
195
|
reason: "Install app-owned account settings notifications section scaffold.",
|
|
233
196
|
category: "users-web",
|
|
234
197
|
id: "users-web-component-account-settings-notifications"
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
from: "templates/src/components/account/settings/AccountSettingsInvitesSection.vue",
|
|
238
|
-
to: "src/components/account/settings/AccountSettingsInvitesSection.vue",
|
|
239
|
-
reason: "Install app-owned account settings invites section scaffold.",
|
|
240
|
-
category: "users-web",
|
|
241
|
-
id: "users-web-component-account-settings-invites"
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
from: "templates/src/pages/console/settings.vue",
|
|
245
|
-
toSurface: "console",
|
|
246
|
-
toSurfacePath: "settings.vue",
|
|
247
|
-
reason: "Install console settings shell route scaffold for users-web console UI.",
|
|
248
|
-
category: "users-web",
|
|
249
|
-
id: "users-web-page-console-settings-shell"
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
from: "templates/src/pages/console/settings/index.vue",
|
|
253
|
-
toSurface: "console",
|
|
254
|
-
toSurfacePath: "settings/index.vue",
|
|
255
|
-
reason: "Install console settings index stub scaffold for app-owned landing or redirect behavior.",
|
|
256
|
-
category: "users-web",
|
|
257
|
-
id: "users-web-page-console-settings"
|
|
258
198
|
}
|
|
259
199
|
],
|
|
260
200
|
text: [
|
|
@@ -269,17 +209,6 @@ export default Object.freeze({
|
|
|
269
209
|
category: "users-web",
|
|
270
210
|
id: "users-web-surface-config-account"
|
|
271
211
|
},
|
|
272
|
-
{
|
|
273
|
-
op: "append-text",
|
|
274
|
-
file: "src/placement.js",
|
|
275
|
-
position: "bottom",
|
|
276
|
-
skipIfContains: "id: \"users.profile.menu.surface-switch\"",
|
|
277
|
-
value:
|
|
278
|
-
"\naddPlacement({\n id: \"users.profile.menu.surface-switch\",\n target: \"auth-profile-menu:primary-menu\",\n surfaces: [\"*\"],\n order: 100,\n componentToken: \"users.web.profile.menu.surface-switch-item\",\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
|
|
279
|
-
reason: "Append users-web profile surface switch placement into app-owned placement registry.",
|
|
280
|
-
category: "users-web",
|
|
281
|
-
id: "users-web-profile-surface-switch-placement"
|
|
282
|
-
},
|
|
283
212
|
{
|
|
284
213
|
op: "append-text",
|
|
285
214
|
file: "src/placement.js",
|
|
@@ -291,24 +220,13 @@ export default Object.freeze({
|
|
|
291
220
|
category: "users-web",
|
|
292
221
|
id: "users-web-profile-settings-placement"
|
|
293
222
|
},
|
|
294
|
-
{
|
|
295
|
-
op: "append-text",
|
|
296
|
-
file: "src/placement.js",
|
|
297
|
-
position: "bottom",
|
|
298
|
-
skipIfContains: "id: \"users.console.menu.settings\"",
|
|
299
|
-
value:
|
|
300
|
-
"\naddPlacement({\n id: \"users.console.menu.settings\",\n target: \"shell-layout:primary-menu\",\n surfaces: [\"console\"],\n order: 100,\n componentToken: \"local.main.ui.menu-link-item\",\n props: {\n label: \"Settings\",\n to: \"/console/settings\",\n icon: \"mdi-cog-outline\"\n },\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
|
|
301
|
-
reason: "Append users-web console settings menu placement into app-owned placement registry.",
|
|
302
|
-
category: "users-web",
|
|
303
|
-
id: "users-web-console-settings-placement"
|
|
304
|
-
},
|
|
305
223
|
{
|
|
306
224
|
op: "append-text",
|
|
307
225
|
file: "src/placement.js",
|
|
308
226
|
position: "bottom",
|
|
309
227
|
skipIfContains: "id: \"users.home.tools.widget\"",
|
|
310
228
|
value:
|
|
311
|
-
"\naddPlacement({\n id: \"users.home.tools.widget\",\n target: \"shell-layout:top-right\",\n surfaces: [\"home\"],\n order: 900,\n componentToken: \"users.web.home.tools.widget\",\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n\naddPlacement({\n id: \"users.home.menu.settings\",\n target: \"home-tools:primary-menu\",\n surfaces: [\"home\"],\n order: 100,\n componentToken: \"local.main.ui.surface-aware-menu-link-item\",\n props: {\n label: \"Settings\",\n surface: \"home\",\n
|
|
229
|
+
"\naddPlacement({\n id: \"users.home.tools.widget\",\n target: \"shell-layout:top-right\",\n surfaces: [\"home\"],\n order: 900,\n componentToken: \"users.web.home.tools.widget\",\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n\naddPlacement({\n id: \"users.home.menu.settings\",\n target: \"home-tools:primary-menu\",\n surfaces: [\"home\"],\n order: 100,\n componentToken: \"local.main.ui.surface-aware-menu-link-item\",\n props: {\n label: \"Settings\",\n surface: \"home\",\n scopedSuffix: \"/settings\",\n unscopedSuffix: \"/settings\"\n },\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
|
|
312
230
|
reason: "Append users-web home tools widget and settings menu placements into app-owned placement registry.",
|
|
313
231
|
category: "users-web",
|
|
314
232
|
id: "users-web-home-tools-placement"
|
package/package.json
CHANGED
|
@@ -1,37 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/users-web",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.54",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
7
7
|
},
|
|
8
8
|
"exports": {
|
|
9
9
|
"./client": "./src/client/index.js",
|
|
10
|
-
"./client/
|
|
11
|
-
"./client/components/WorkspaceMembersClientElement": "./src/client/components/WorkspaceMembersClientElement.vue",
|
|
10
|
+
"./client/account-settings/sections": "./src/client/account-settings/sections.js",
|
|
12
11
|
"./client/composables/useAddEdit": "./src/client/composables/records/useAddEdit.js",
|
|
12
|
+
"./client/composables/useAccess": "./src/client/composables/useAccess.js",
|
|
13
|
+
"./client/composables/useCommand": "./src/client/composables/useCommand.js",
|
|
13
14
|
"./client/composables/useCrudAddEdit": "./src/client/composables/records/useCrudAddEdit.js",
|
|
14
15
|
"./client/composables/crudLookupFieldRuntime": "./src/client/composables/crud/crudLookupFieldRuntime.js",
|
|
15
16
|
"./client/composables/useList": "./src/client/composables/records/useList.js",
|
|
16
17
|
"./client/composables/useCrudList": "./src/client/composables/records/useCrudList.js",
|
|
17
18
|
"./client/composables/useCrudListParentTitle": "./src/client/composables/useCrudListParentTitle.js",
|
|
19
|
+
"./client/composables/useRealtimeQueryInvalidation": "./src/client/composables/useRealtimeQueryInvalidation.js",
|
|
20
|
+
"./client/composables/useSurfaceRouteContext": "./src/client/composables/useSurfaceRouteContext.js",
|
|
18
21
|
"./client/composables/useView": "./src/client/composables/records/useView.js",
|
|
19
22
|
"./client/composables/useCrudView": "./src/client/composables/records/useCrudView.js",
|
|
20
23
|
"./client/composables/usePagedCollection": "./src/client/composables/usePagedCollection.js",
|
|
21
24
|
"./client/composables/useAccountSettingsRuntime": "./src/client/composables/useAccountSettingsRuntime.js",
|
|
22
25
|
"./client/composables/usePaths": "./src/client/composables/usePaths.js",
|
|
23
|
-
"./client/composables/
|
|
24
|
-
"./client/
|
|
26
|
+
"./client/composables/runtime/useUiFeedback": "./src/client/composables/runtime/useUiFeedback.js",
|
|
27
|
+
"./client/lib/bootstrap": "./src/client/lib/bootstrap.js",
|
|
28
|
+
"./client/lib/permissions": "./src/client/lib/permissions.js",
|
|
29
|
+
"./client/support/contractGuards": "./src/client/support/contractGuards.js"
|
|
25
30
|
},
|
|
26
31
|
"dependencies": {
|
|
27
32
|
"@tanstack/vue-query": "5.92.12",
|
|
28
33
|
"@mdi/js": "^7.4.47",
|
|
29
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
30
|
-
"@jskit-ai/kernel": "0.1.
|
|
31
|
-
"@jskit-ai/realtime": "0.1.
|
|
32
|
-
"@jskit-ai/shell-web": "0.1.
|
|
33
|
-
"@jskit-ai/uploads-image-web": "0.1.
|
|
34
|
-
"@jskit-ai/users-core": "0.1.
|
|
34
|
+
"@jskit-ai/http-runtime": "0.1.38",
|
|
35
|
+
"@jskit-ai/kernel": "0.1.39",
|
|
36
|
+
"@jskit-ai/realtime": "0.1.38",
|
|
37
|
+
"@jskit-ai/shell-web": "0.1.38",
|
|
38
|
+
"@jskit-ai/uploads-image-web": "0.1.17",
|
|
39
|
+
"@jskit-ai/users-core": "0.1.49",
|
|
35
40
|
"vuetify": "^4.0.0"
|
|
36
41
|
}
|
|
37
42
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { inject } from "vue";
|
|
2
|
+
|
|
3
|
+
const ACCOUNT_SETTINGS_SECTIONS_INJECTION_KEY = Symbol("users-web.account-settings.sections");
|
|
4
|
+
const ACCOUNT_SETTINGS_SECTION_REGISTRY_TAG = "users.web.account-settings.sections";
|
|
5
|
+
const EMPTY_ACCOUNT_SETTINGS_SECTIONS = Object.freeze([]);
|
|
6
|
+
const RESERVED_ACCOUNT_SETTINGS_SECTION_VALUES = Object.freeze([
|
|
7
|
+
"profile",
|
|
8
|
+
"preferences",
|
|
9
|
+
"notifications"
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
function normalizeAccountSettingsSectionEntry(entry = null) {
|
|
13
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const value = String(entry.value || "").trim().toLowerCase();
|
|
18
|
+
const title = String(entry.title || "").trim();
|
|
19
|
+
const component = entry.component;
|
|
20
|
+
if (!value || !title || !component) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return Object.freeze({
|
|
25
|
+
value,
|
|
26
|
+
title,
|
|
27
|
+
component,
|
|
28
|
+
order: Number.isFinite(Number(entry.order)) ? Number(entry.order) : 500,
|
|
29
|
+
usesSharedRuntime: entry.usesSharedRuntime === true
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function sortAccountSettingsSections(entries = []) {
|
|
34
|
+
return Object.freeze(
|
|
35
|
+
[...entries].sort((left, right) => {
|
|
36
|
+
const orderDelta = left.order - right.order;
|
|
37
|
+
if (orderDelta !== 0) {
|
|
38
|
+
return orderDelta;
|
|
39
|
+
}
|
|
40
|
+
return left.value.localeCompare(right.value);
|
|
41
|
+
})
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function resolveAccountSettingsSections(entries = []) {
|
|
46
|
+
const seen = new Set(RESERVED_ACCOUNT_SETTINGS_SECTION_VALUES);
|
|
47
|
+
const normalized = [];
|
|
48
|
+
|
|
49
|
+
for (const entry of Array.isArray(entries) ? entries : []) {
|
|
50
|
+
const resolved = normalizeAccountSettingsSectionEntry(entry);
|
|
51
|
+
if (!resolved || seen.has(resolved.value)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
seen.add(resolved.value);
|
|
55
|
+
normalized.push(resolved);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return sortAccountSettingsSections(normalized);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function useAccountSettingsSections() {
|
|
62
|
+
return inject(ACCOUNT_SETTINGS_SECTIONS_INJECTION_KEY, EMPTY_ACCOUNT_SETTINGS_SECTIONS);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
ACCOUNT_SETTINGS_SECTIONS_INJECTION_KEY,
|
|
67
|
+
ACCOUNT_SETTINGS_SECTION_REGISTRY_TAG,
|
|
68
|
+
EMPTY_ACCOUNT_SETTINGS_SECTIONS,
|
|
69
|
+
RESERVED_ACCOUNT_SETTINGS_SECTION_VALUES,
|
|
70
|
+
normalizeAccountSettingsSectionEntry,
|
|
71
|
+
resolveAccountSettingsSections,
|
|
72
|
+
sortAccountSettingsSections,
|
|
73
|
+
useAccountSettingsSections
|
|
74
|
+
};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { ACCOUNT_SETTINGS_DEFAULTS } from "./accountSettingsRuntimeConstants.js";
|
|
2
2
|
import {
|
|
3
|
+
isRecord,
|
|
3
4
|
normalizeReturnToPath as normalizeSharedReturnToPath,
|
|
4
5
|
resolveAllowedOriginsFromPlacementContext
|
|
5
6
|
} from "@jskit-ai/kernel/shared/support";
|
|
6
|
-
import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
7
|
-
import { normalizeRecord } from "../../support/runtimeNormalization.js";
|
|
8
7
|
|
|
9
8
|
function normalizeReturnToPath(value, { fallback = "/", accountSettingsPath = "/account", allowedOrigins = [] } = {}) {
|
|
10
9
|
return normalizeSharedReturnToPath(value, {
|
|
@@ -20,41 +19,7 @@ function resolveAllowedReturnToOrigins(contextValue = null) {
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
function normalizeSettingsPayload(value) {
|
|
23
|
-
return
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function normalizePendingInvite(entry) {
|
|
27
|
-
if (!entry || typeof entry !== "object") {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const id = normalizeRecordId(entry.id, { fallback: null });
|
|
32
|
-
const workspaceId = normalizeRecordId(entry.workspaceId, { fallback: null });
|
|
33
|
-
if (!id || !workspaceId) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const workspaceSlug = String(entry.workspaceSlug || "").trim();
|
|
38
|
-
if (!workspaceSlug) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const token = String(entry.token || "").trim();
|
|
43
|
-
if (!token) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
id,
|
|
49
|
-
token,
|
|
50
|
-
workspaceId,
|
|
51
|
-
workspaceSlug,
|
|
52
|
-
workspaceName: String(entry.workspaceName || workspaceSlug).trim() || workspaceSlug,
|
|
53
|
-
workspaceAvatarUrl: String(entry.workspaceAvatarUrl || "").trim(),
|
|
54
|
-
roleSid: String(entry.roleSid || "member").trim().toLowerCase() || "member",
|
|
55
|
-
status: String(entry.status || "pending").trim().toLowerCase() || "pending",
|
|
56
|
-
expiresAt: String(entry.expiresAt || "").trim()
|
|
57
|
-
};
|
|
22
|
+
return isRecord(value) ? value : {};
|
|
58
23
|
}
|
|
59
24
|
|
|
60
25
|
function normalizeAvatarSize(value) {
|
|
@@ -70,7 +35,6 @@ function normalizeAvatarSize(value) {
|
|
|
70
35
|
export {
|
|
71
36
|
resolveAllowedReturnToOrigins,
|
|
72
37
|
normalizeAvatarSize,
|
|
73
|
-
normalizePendingInvite,
|
|
74
38
|
normalizeReturnToPath,
|
|
75
39
|
normalizeSettingsPayload
|
|
76
40
|
};
|
|
@@ -119,11 +119,11 @@ function createCrudLookupFieldRuntime({
|
|
|
119
119
|
adapter: adapter || undefined,
|
|
120
120
|
...(relationSurfaceId ? { surfaceId: relationSurfaceId } : {}),
|
|
121
121
|
apiSuffix: apiPath,
|
|
122
|
-
queryKeyFactory: (surfaceId = "",
|
|
122
|
+
queryKeyFactory: (surfaceId = "", scopeParamValue = "") => [
|
|
123
123
|
...normalizedQueryKeyPrefix,
|
|
124
124
|
key,
|
|
125
125
|
String(surfaceId || ""),
|
|
126
|
-
String(
|
|
126
|
+
String(scopeParamValue || "")
|
|
127
127
|
],
|
|
128
128
|
search: {
|
|
129
129
|
enabled: true,
|
|
@@ -83,7 +83,7 @@ function resolveCrudListParentDescriptor({ resource = {}, route = null, recordId
|
|
|
83
83
|
|
|
84
84
|
const normalizedRecordIdParam = normalizeText(recordIdParam) || "recordId";
|
|
85
85
|
for (const routeParamKey of [...orderedRouteParamNames].reverse()) {
|
|
86
|
-
if (routeParamKey ===
|
|
86
|
+
if (routeParamKey === normalizedRecordIdParam) {
|
|
87
87
|
continue;
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { computed, unref } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
|
|
3
3
|
import { useScopeRuntime } from "../useScopeRuntime.js";
|
|
4
4
|
import { useOperationRealtime } from "../useRealtimeQueryInvalidation.js";
|
|
5
5
|
import {
|
|
@@ -33,7 +33,7 @@ function hasAnyPermissions(permissionSets = {}) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function useOperationScope({
|
|
36
|
-
ownershipFilter =
|
|
36
|
+
ownershipFilter = ROUTE_VISIBILITY_WORKSPACE,
|
|
37
37
|
surfaceId = "",
|
|
38
38
|
access = "auto",
|
|
39
39
|
placementSource = "users-web.operation",
|
|
@@ -54,8 +54,8 @@ function useOperationScope({
|
|
|
54
54
|
});
|
|
55
55
|
const normalizedOwnershipFilter = scopeRuntime.normalizedOwnershipFilter;
|
|
56
56
|
const routeContext = scopeRuntime.routeContext;
|
|
57
|
-
const
|
|
58
|
-
const
|
|
57
|
+
const scopeParamValue = scopeRuntime.scopeParamValue;
|
|
58
|
+
const hasRequiredRouteScope = scopeRuntime.hasRequiredRouteScope;
|
|
59
59
|
const accessRuntime = scopeRuntime.access;
|
|
60
60
|
|
|
61
61
|
const apiPath = computed(() =>
|
|
@@ -67,7 +67,7 @@ function useOperationScope({
|
|
|
67
67
|
const queryEnabled = computed(() =>
|
|
68
68
|
resolveEnabled(readEnabled, {
|
|
69
69
|
surfaceId: routeContext.currentSurfaceId.value,
|
|
70
|
-
|
|
70
|
+
scopeParamValue: scopeParamValue.value,
|
|
71
71
|
ownershipFilter: normalizedOwnershipFilter,
|
|
72
72
|
model
|
|
73
73
|
})
|
|
@@ -76,20 +76,20 @@ function useOperationScope({
|
|
|
76
76
|
const queryKey = computed(() =>
|
|
77
77
|
resolveQueryKey(queryKeyFactory, {
|
|
78
78
|
surfaceId: routeContext.currentSurfaceId.value,
|
|
79
|
-
|
|
79
|
+
scopeParamValue: scopeParamValue.value,
|
|
80
80
|
ownershipFilter: normalizedOwnershipFilter
|
|
81
81
|
})
|
|
82
82
|
);
|
|
83
83
|
const realtimeBinding = useOperationRealtime({
|
|
84
84
|
realtime,
|
|
85
85
|
queryKey: typeof queryKeyFactory === "function" ? queryKey : null,
|
|
86
|
-
enabled: computed(() =>
|
|
86
|
+
enabled: computed(() => hasRequiredRouteScope.value && Boolean(apiPath.value))
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
function queryCanRun(accessGate = true) {
|
|
90
90
|
return computed(() =>
|
|
91
91
|
queryEnabled.value &&
|
|
92
|
-
|
|
92
|
+
hasRequiredRouteScope.value &&
|
|
93
93
|
Boolean(apiPath.value) &&
|
|
94
94
|
Boolean(unref(accessGate))
|
|
95
95
|
);
|
|
@@ -102,8 +102,8 @@ function useOperationScope({
|
|
|
102
102
|
|
|
103
103
|
function loadError(baseError = "") {
|
|
104
104
|
return computed(() => {
|
|
105
|
-
if (scopeRuntime.
|
|
106
|
-
return scopeRuntime.
|
|
105
|
+
if (scopeRuntime.routeScopeError.value) {
|
|
106
|
+
return scopeRuntime.routeScopeError.value;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
const bootstrapError = String(accessRuntime.bootstrapError.value || "").trim();
|
|
@@ -127,8 +127,8 @@ function useOperationScope({
|
|
|
127
127
|
scopeRuntime,
|
|
128
128
|
routeContext,
|
|
129
129
|
normalizedOwnershipFilter,
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
scopeParamValue,
|
|
131
|
+
hasRequiredRouteScope,
|
|
132
132
|
access: accessRuntime,
|
|
133
133
|
apiPath,
|
|
134
134
|
queryEnabled,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, proxyRefs } from "vue";
|
|
2
2
|
import { useRoute } from "vue-router";
|
|
3
|
-
import {
|
|
3
|
+
import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
|
|
4
4
|
import { useAddEditCore } from "../runtime/useAddEditCore.js";
|
|
5
5
|
import { useEndpointResource } from "../runtime/useEndpointResource.js";
|
|
6
6
|
import { resolveOperationAdapter } from "../runtime/operationAdapters.js";
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import { resolveRouteParamNamesInOrder } from "../support/routeTemplateHelpers.js";
|
|
18
18
|
|
|
19
19
|
function useAddEdit({
|
|
20
|
-
ownershipFilter =
|
|
20
|
+
ownershipFilter = ROUTE_VISIBILITY_WORKSPACE,
|
|
21
21
|
surfaceId = "",
|
|
22
22
|
access = "auto",
|
|
23
23
|
resource = null,
|
|
@@ -2,7 +2,7 @@ import { computed, onScopeDispose, proxyRefs, ref, watch } from "vue";
|
|
|
2
2
|
import { useRouter } from "vue-router";
|
|
3
3
|
import { appendQueryString } from "@jskit-ai/kernel/shared/support";
|
|
4
4
|
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
5
|
-
import {
|
|
5
|
+
import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
|
|
6
6
|
import { useListCore } from "../runtime/useListCore.js";
|
|
7
7
|
import { resolveOperationAdapter } from "../runtime/operationAdapters.js";
|
|
8
8
|
import { setupOperationErrorReporting } from "../runtime/operationUiHelpers.js";
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
const EMPTY_ROUTE_SYNC_QUERY_PARAM_BLACKLIST = Object.freeze([]);
|
|
32
32
|
|
|
33
33
|
function useList({
|
|
34
|
-
ownershipFilter =
|
|
34
|
+
ownershipFilter = ROUTE_VISIBILITY_WORKSPACE,
|
|
35
35
|
surfaceId = "",
|
|
36
36
|
access = "auto",
|
|
37
37
|
apiSuffix = "",
|
|
@@ -131,7 +131,7 @@ function useList({
|
|
|
131
131
|
const queryParamsContext = computed(() => {
|
|
132
132
|
return Object.freeze({
|
|
133
133
|
surfaceId: operationScope.routeContext.currentSurfaceId.value,
|
|
134
|
-
|
|
134
|
+
scopeParamValue: operationScope.scopeParamValue.value,
|
|
135
135
|
ownershipFilter: operationScope.normalizedOwnershipFilter
|
|
136
136
|
});
|
|
137
137
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, proxyRefs } from "vue";
|
|
2
2
|
import { useRoute } from "vue-router";
|
|
3
|
-
import {
|
|
3
|
+
import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
|
|
4
4
|
import { useViewCore } from "../runtime/useViewCore.js";
|
|
5
5
|
import { useEndpointResource } from "../runtime/useEndpointResource.js";
|
|
6
6
|
import { resolveOperationAdapter } from "../runtime/operationAdapters.js";
|
|
@@ -9,7 +9,7 @@ import { createViewUiRuntime } from "../runtime/viewUiRuntime.js";
|
|
|
9
9
|
import { resolveRouteParamNamesInOrder } from "../support/routeTemplateHelpers.js";
|
|
10
10
|
|
|
11
11
|
function useView({
|
|
12
|
-
ownershipFilter =
|
|
12
|
+
ownershipFilter = ROUTE_VISIBILITY_WORKSPACE,
|
|
13
13
|
surfaceId = "",
|
|
14
14
|
access = "auto",
|
|
15
15
|
apiSuffix = "",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { resolveEnabledRef, resolveTextRef } from "./refValueHelpers.js";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "@jskit-ai/
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
ROUTE_VISIBILITY_TOKENS,
|
|
4
|
+
ROUTE_VISIBILITY_WORKSPACE,
|
|
5
|
+
ROUTE_VISIBILITY_WORKSPACE_USER
|
|
6
|
+
} from "@jskit-ai/kernel/shared/support/visibility";
|
|
7
|
+
|
|
8
|
+
const OWNERSHIP_FILTER_VALUES = ROUTE_VISIBILITY_TOKENS;
|
|
9
|
+
const SCOPED_OWNERSHIP_FILTER_SET = new Set([
|
|
10
|
+
ROUTE_VISIBILITY_WORKSPACE,
|
|
11
|
+
ROUTE_VISIBILITY_WORKSPACE_USER
|
|
12
12
|
]);
|
|
13
13
|
const ACCESS_MODE_VALUES = Object.freeze(["auto", "always", "never"]);
|
|
14
14
|
|
|
@@ -89,31 +89,31 @@ function resolveEnabled(value, context = {}) {
|
|
|
89
89
|
return resolveEnabledRef(value);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
function normalizeOwnershipFilter(value =
|
|
93
|
-
const normalized = String(value ||
|
|
94
|
-
if (
|
|
92
|
+
function normalizeOwnershipFilter(value = ROUTE_VISIBILITY_WORKSPACE) {
|
|
93
|
+
const normalized = String(value || ROUTE_VISIBILITY_WORKSPACE).trim().toLowerCase();
|
|
94
|
+
if (OWNERSHIP_FILTER_VALUES.includes(normalized)) {
|
|
95
95
|
return normalized;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
throw new TypeError(
|
|
99
|
-
`ownershipFilter must be one of: ${
|
|
99
|
+
`ownershipFilter must be one of: ${OWNERSHIP_FILTER_VALUES.join(", ")}. Received: ${String(value || "") || "(empty)"}`
|
|
100
100
|
);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
function
|
|
104
|
-
return
|
|
103
|
+
function isScopedOwnershipFilter(ownershipFilter) {
|
|
104
|
+
return SCOPED_OWNERSHIP_FILTER_SET.has(ownershipFilter);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
function resolveQueryKey(
|
|
108
108
|
queryKeyFactory,
|
|
109
|
-
{ surfaceId = "",
|
|
109
|
+
{ surfaceId = "", scopeParamValue = "", ownershipFilter = ROUTE_VISIBILITY_WORKSPACE } = {}
|
|
110
110
|
) {
|
|
111
111
|
if (typeof queryKeyFactory !== "function") {
|
|
112
112
|
throw new TypeError("queryKeyFactory is required.");
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
if (
|
|
116
|
-
return queryKeyFactory(surfaceId,
|
|
115
|
+
if (isScopedOwnershipFilter(ownershipFilter)) {
|
|
116
|
+
return queryKeyFactory(surfaceId, scopeParamValue, ownershipFilter);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
return queryKeyFactory(surfaceId, ownershipFilter);
|
|
@@ -139,7 +139,7 @@ export {
|
|
|
139
139
|
resolveApiSuffix,
|
|
140
140
|
resolveEnabled,
|
|
141
141
|
normalizeOwnershipFilter,
|
|
142
|
-
|
|
142
|
+
isScopedOwnershipFilter,
|
|
143
143
|
resolveQueryKey,
|
|
144
144
|
resolveResourceMessages
|
|
145
145
|
};
|
|
@@ -20,7 +20,7 @@ function asPermissionList(value) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function useAccess({
|
|
23
|
-
|
|
23
|
+
scopeParamValue = "",
|
|
24
24
|
enabled = true,
|
|
25
25
|
access = "always",
|
|
26
26
|
hasPermissionRequirements = false
|
|
@@ -30,7 +30,7 @@ function useAccess({
|
|
|
30
30
|
hasPermissionRequirements: hasPermissionRequirements === true
|
|
31
31
|
});
|
|
32
32
|
const { context: placementContext } = useWebPlacementContext();
|
|
33
|
-
const
|
|
33
|
+
const normalizedScopeParamValue = computed(() => resolveTextRef(scopeParamValue));
|
|
34
34
|
const queryEnabled = computed(() => resolveEnabledRef(enabled) && accessRequired);
|
|
35
35
|
const hasPlacementBootstrapPermissions = computed(() => {
|
|
36
36
|
const source = placementContext.value;
|
|
@@ -95,7 +95,7 @@ function useAccess({
|
|
|
95
95
|
return Object.freeze({
|
|
96
96
|
accessMode: normalizedAccessMode,
|
|
97
97
|
accessRequired,
|
|
98
|
-
|
|
98
|
+
scopeParamValue: normalizedScopeParamValue,
|
|
99
99
|
permissions,
|
|
100
100
|
bootstrapError,
|
|
101
101
|
isBootstrapping,
|