@jskit-ai/users-web 0.1.53 → 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 +15 -53
- 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 -11
- package/test/theme.test.js +0 -56
- 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 -201
- 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/test/bootstrapPlacementRuntime.test.js +0 -1095
- package/test/menuIcons.test.js +0 -34
- package/test/menuLinkTarget.test.js +0 -116
- package/test/profileSurfaceMenuLinks.test.js +0 -208
- 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,12 +1,9 @@
|
|
|
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: [
|
|
@@ -79,24 +76,22 @@ export default Object.freeze({
|
|
|
79
76
|
},
|
|
80
77
|
{
|
|
81
78
|
subpath: "./client/composables/usePaths",
|
|
82
|
-
summary: "Exports surface
|
|
79
|
+
summary: "Exports surface route path resolver composable."
|
|
83
80
|
},
|
|
84
81
|
{
|
|
85
82
|
subpath: "./client/composables/useAccountSettingsRuntime",
|
|
86
83
|
summary: "Exports account settings runtime composable for app-owned settings UI."
|
|
87
84
|
},
|
|
88
85
|
{
|
|
89
|
-
subpath: "./client/
|
|
90
|
-
summary: "Exports
|
|
91
|
-
}
|
|
86
|
+
subpath: "./client/account-settings/sections",
|
|
87
|
+
summary: "Exports account settings section extension seam helpers."
|
|
88
|
+
}
|
|
92
89
|
],
|
|
93
90
|
containerTokens: {
|
|
94
91
|
server: [],
|
|
95
92
|
client: [
|
|
96
|
-
"users.web.profile.menu.surface-switch-item",
|
|
97
93
|
"users.web.home.tools.widget",
|
|
98
|
-
"users.web.profile.element"
|
|
99
|
-
"users.web.bootstrap-placement.runtime"
|
|
94
|
+
"users.web.profile.element"
|
|
100
95
|
]
|
|
101
96
|
}
|
|
102
97
|
},
|
|
@@ -108,24 +103,9 @@ export default Object.freeze({
|
|
|
108
103
|
defaultLinkComponentToken: HOME_TOOLS_OUTLET.defaultLinkComponentToken,
|
|
109
104
|
surfaces: ["home"],
|
|
110
105
|
source: "src/client/components/UsersHomeToolsWidget.vue"
|
|
111
|
-
}
|
|
112
|
-
{
|
|
113
|
-
target: WORKSPACE_TOOLS_OUTLET.target,
|
|
114
|
-
defaultLinkComponentToken: WORKSPACE_TOOLS_OUTLET.defaultLinkComponentToken,
|
|
115
|
-
surfaces: ["admin"],
|
|
116
|
-
source: "src/client/components/UsersWorkspaceToolsWidget.vue"
|
|
117
|
-
},
|
|
106
|
+
}
|
|
118
107
|
],
|
|
119
108
|
contributions: [
|
|
120
|
-
{
|
|
121
|
-
id: "users.profile.menu.surface-switch",
|
|
122
|
-
target: "auth-profile-menu:primary-menu",
|
|
123
|
-
surfaces: ["*"],
|
|
124
|
-
order: 100,
|
|
125
|
-
componentToken: "users.web.profile.menu.surface-switch-item",
|
|
126
|
-
when: "auth.authenticated === true",
|
|
127
|
-
source: "mutations.text#users-web-profile-surface-switch-placement"
|
|
128
|
-
},
|
|
129
109
|
{
|
|
130
110
|
id: "users.profile.menu.settings",
|
|
131
111
|
target: "auth-profile-menu:primary-menu",
|
|
@@ -162,12 +142,12 @@ export default Object.freeze({
|
|
|
162
142
|
runtime: {
|
|
163
143
|
"@tanstack/vue-query": "5.92.12",
|
|
164
144
|
"@mdi/js": "^7.4.47",
|
|
165
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
166
|
-
"@jskit-ai/realtime": "0.1.
|
|
167
|
-
"@jskit-ai/kernel": "0.1.
|
|
168
|
-
"@jskit-ai/shell-web": "0.1.
|
|
169
|
-
"@jskit-ai/uploads-image-web": "0.1.
|
|
170
|
-
"@jskit-ai/users-core": "0.1.
|
|
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",
|
|
171
151
|
vuetify: "^4.0.0"
|
|
172
152
|
},
|
|
173
153
|
dev: {}
|
|
@@ -215,13 +195,6 @@ export default Object.freeze({
|
|
|
215
195
|
reason: "Install app-owned account settings notifications section scaffold.",
|
|
216
196
|
category: "users-web",
|
|
217
197
|
id: "users-web-component-account-settings-notifications"
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
from: "templates/src/components/account/settings/AccountSettingsInvitesSection.vue",
|
|
221
|
-
to: "src/components/account/settings/AccountSettingsInvitesSection.vue",
|
|
222
|
-
reason: "Install app-owned account settings invites section scaffold.",
|
|
223
|
-
category: "users-web",
|
|
224
|
-
id: "users-web-component-account-settings-invites"
|
|
225
198
|
}
|
|
226
199
|
],
|
|
227
200
|
text: [
|
|
@@ -236,17 +209,6 @@ export default Object.freeze({
|
|
|
236
209
|
category: "users-web",
|
|
237
210
|
id: "users-web-surface-config-account"
|
|
238
211
|
},
|
|
239
|
-
{
|
|
240
|
-
op: "append-text",
|
|
241
|
-
file: "src/placement.js",
|
|
242
|
-
position: "bottom",
|
|
243
|
-
skipIfContains: "id: \"users.profile.menu.surface-switch\"",
|
|
244
|
-
value:
|
|
245
|
-
"\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",
|
|
246
|
-
reason: "Append users-web profile surface switch placement into app-owned placement registry.",
|
|
247
|
-
category: "users-web",
|
|
248
|
-
id: "users-web-profile-surface-switch-placement"
|
|
249
|
-
},
|
|
250
212
|
{
|
|
251
213
|
op: "append-text",
|
|
252
214
|
file: "src/placement.js",
|
|
@@ -264,7 +226,7 @@ export default Object.freeze({
|
|
|
264
226
|
position: "bottom",
|
|
265
227
|
skipIfContains: "id: \"users.home.tools.widget\"",
|
|
266
228
|
value:
|
|
267
|
-
"\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",
|
|
268
230
|
reason: "Append users-web home tools widget and settings menu placements into app-owned placement registry.",
|
|
269
231
|
category: "users-web",
|
|
270
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,
|