@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
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
2
|
-
import { surfaceRequiresWorkspaceFromPlacementContext } from "../lib/workspaceSurfaceContext.js";
|
|
3
|
-
|
|
4
|
-
function normalizeMenuLinkPathname(pathname = "") {
|
|
5
|
-
const source = String(pathname || "").trim();
|
|
6
|
-
if (!source) {
|
|
7
|
-
return "";
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const queryIndex = source.indexOf("?");
|
|
11
|
-
const hashIndex = source.indexOf("#");
|
|
12
|
-
const cutoff =
|
|
13
|
-
queryIndex < 0
|
|
14
|
-
? hashIndex
|
|
15
|
-
: hashIndex < 0
|
|
16
|
-
? queryIndex
|
|
17
|
-
: Math.min(queryIndex, hashIndex);
|
|
18
|
-
|
|
19
|
-
return cutoff < 0 ? source : source.slice(0, cutoff);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function resolveMenuLinkSurfaceId(surface = "", fallbackSurfaceId = "") {
|
|
23
|
-
const explicitSurface = normalizeText(surface).toLowerCase();
|
|
24
|
-
if (explicitSurface && explicitSurface !== "*") {
|
|
25
|
-
return explicitSurface;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return normalizeText(fallbackSurfaceId).toLowerCase();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function interpolateBracketParams(pathTemplate = "", params = {}) {
|
|
32
|
-
const source = String(pathTemplate || "").trim();
|
|
33
|
-
if (!source) {
|
|
34
|
-
return "";
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return source.replace(/\[([^\]]+)\]/g, (_match, rawKey) => {
|
|
38
|
-
const key = String(rawKey || "").trim();
|
|
39
|
-
if (!key) {
|
|
40
|
-
return "";
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const value = params?.[key];
|
|
44
|
-
return value == null ? `[${key}]` : encodeURIComponent(String(value));
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function isRelativeMenuLinkTarget(target = "") {
|
|
49
|
-
const normalizedTarget = normalizeText(target);
|
|
50
|
-
return normalizedTarget.startsWith("./") || normalizedTarget.startsWith("../");
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function resolveMenuLinkTarget({
|
|
54
|
-
to = "",
|
|
55
|
-
surface = "",
|
|
56
|
-
currentSurfaceId = "",
|
|
57
|
-
placementContext = null,
|
|
58
|
-
workspaceSuffix = "/",
|
|
59
|
-
nonWorkspaceSuffix = "/",
|
|
60
|
-
routeParams = {},
|
|
61
|
-
resolvePagePath = null
|
|
62
|
-
} = {}) {
|
|
63
|
-
const explicitTarget = normalizeText(to);
|
|
64
|
-
const targetSurfaceId = resolveMenuLinkSurfaceId(surface, currentSurfaceId);
|
|
65
|
-
const workspaceRequired = surfaceRequiresWorkspaceFromPlacementContext(placementContext, targetSurfaceId);
|
|
66
|
-
const suffixTemplate = normalizeText(workspaceRequired ? workspaceSuffix : nonWorkspaceSuffix) || "/";
|
|
67
|
-
const interpolatedSuffix = interpolateBracketParams(suffixTemplate, routeParams);
|
|
68
|
-
const resolvedSuffixTarget =
|
|
69
|
-
typeof resolvePagePath === "function" &&
|
|
70
|
-
targetSurfaceId &&
|
|
71
|
-
interpolatedSuffix &&
|
|
72
|
-
!interpolatedSuffix.includes("[")
|
|
73
|
-
? normalizeText(resolvePagePath(interpolatedSuffix, {
|
|
74
|
-
surface: targetSurfaceId,
|
|
75
|
-
mode: "auto"
|
|
76
|
-
}))
|
|
77
|
-
: "";
|
|
78
|
-
|
|
79
|
-
if (!explicitTarget) {
|
|
80
|
-
return resolvedSuffixTarget;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (isRelativeMenuLinkTarget(explicitTarget)) {
|
|
84
|
-
return resolvedSuffixTarget;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return explicitTarget;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export {
|
|
91
|
-
normalizeMenuLinkPathname,
|
|
92
|
-
resolveMenuLinkTarget
|
|
93
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { unref } from "vue";
|
|
2
|
-
|
|
3
|
-
function matchesCurrentWorkspaceEvent(payload = {}, workspaceSlug = "") {
|
|
4
|
-
const payloadWorkspaceSlug = String(payload?.workspaceSlug || "").trim();
|
|
5
|
-
if (!payloadWorkspaceSlug) {
|
|
6
|
-
return true;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
return payloadWorkspaceSlug === String(workspaceSlug || "").trim();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function createWorkspaceRealtimeMatcher(workspaceSlugRef) {
|
|
13
|
-
return function matchesWorkspaceRealtimeEvent({ payload = {} } = {}) {
|
|
14
|
-
return matchesCurrentWorkspaceEvent(payload, unref(workspaceSlugRef));
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export {
|
|
19
|
-
matchesCurrentWorkspaceEvent,
|
|
20
|
-
createWorkspaceRealtimeMatcher
|
|
21
|
-
};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
function normalizeRecord(value) {
|
|
2
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3
|
-
return {};
|
|
4
|
-
}
|
|
5
|
-
return value;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function resolveErrorStatusCode(error) {
|
|
9
|
-
const statusCode = Number(error?.statusCode || error?.status || 0);
|
|
10
|
-
return Number.isInteger(statusCode) && statusCode > 0 ? statusCode : 0;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function normalizeWorkspaceBootstrapStatusValue(status = "", allowedStatuses = null) {
|
|
14
|
-
const normalizedStatus = String(status || "")
|
|
15
|
-
.trim()
|
|
16
|
-
.toLowerCase();
|
|
17
|
-
if (!normalizedStatus || !(allowedStatuses instanceof Set)) {
|
|
18
|
-
return "";
|
|
19
|
-
}
|
|
20
|
-
return allowedStatuses.has(normalizedStatus) ? normalizedStatus : "";
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export {
|
|
24
|
-
normalizeRecord,
|
|
25
|
-
normalizeWorkspaceBootstrapStatusValue,
|
|
26
|
-
resolveErrorStatusCode
|
|
27
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { normalizeQueryToken } from "@jskit-ai/kernel/shared/support/normalize";
|
|
2
|
-
|
|
3
|
-
function buildWorkspaceQueryKey(kind = "", surfaceId = "", workspaceSlug = "") {
|
|
4
|
-
return [
|
|
5
|
-
"users-web",
|
|
6
|
-
"workspace",
|
|
7
|
-
String(kind || ""),
|
|
8
|
-
normalizeQueryToken(surfaceId),
|
|
9
|
-
normalizeQueryToken(workspaceSlug)
|
|
10
|
-
];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export {
|
|
14
|
-
buildWorkspaceQueryKey
|
|
15
|
-
};
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
const props = defineProps({
|
|
3
|
-
runtime: {
|
|
4
|
-
type: Object,
|
|
5
|
-
required: true
|
|
6
|
-
}
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
const invites = props.runtime.invites;
|
|
10
|
-
</script>
|
|
11
|
-
|
|
12
|
-
<template>
|
|
13
|
-
<v-card rounded="lg" elevation="0" border>
|
|
14
|
-
<v-card-item>
|
|
15
|
-
<v-card-title class="text-subtitle-1">Invitations</v-card-title>
|
|
16
|
-
<v-card-subtitle>Accept or refuse workspace invitations.</v-card-subtitle>
|
|
17
|
-
</v-card-item>
|
|
18
|
-
<v-divider />
|
|
19
|
-
<v-card-text>
|
|
20
|
-
<template v-if="invites.isLoading.value">
|
|
21
|
-
<v-skeleton-loader type="text@2, list-item-two-line@3" />
|
|
22
|
-
</template>
|
|
23
|
-
|
|
24
|
-
<template v-else-if="invites.items.value.length < 1">
|
|
25
|
-
<v-progress-linear v-if="invites.isRefetching.value" indeterminate class="mb-4" />
|
|
26
|
-
<p class="text-body-2 text-medium-emphasis mb-0">No pending invitations.</p>
|
|
27
|
-
</template>
|
|
28
|
-
|
|
29
|
-
<template v-else>
|
|
30
|
-
<v-progress-linear v-if="invites.isRefetching.value" indeterminate class="mb-4" />
|
|
31
|
-
<v-list density="comfortable" class="pa-0">
|
|
32
|
-
<v-list-item
|
|
33
|
-
v-for="invite in invites.items.value"
|
|
34
|
-
:key="invite.id"
|
|
35
|
-
:title="invite.workspaceName"
|
|
36
|
-
:subtitle="`/${invite.workspaceSlug} • role: ${invite.roleSid}`"
|
|
37
|
-
class="px-0"
|
|
38
|
-
>
|
|
39
|
-
<template #prepend>
|
|
40
|
-
<v-avatar color="warning" size="28">
|
|
41
|
-
<span class="text-caption font-weight-bold">?</span>
|
|
42
|
-
</v-avatar>
|
|
43
|
-
</template>
|
|
44
|
-
<template #append>
|
|
45
|
-
<div class="d-flex ga-2">
|
|
46
|
-
<v-btn
|
|
47
|
-
size="small"
|
|
48
|
-
variant="text"
|
|
49
|
-
color="error"
|
|
50
|
-
:loading="invites.action.value.token === invite.token && invites.action.value.decision === 'refuse'"
|
|
51
|
-
:disabled="
|
|
52
|
-
invites.isRefetching.value || (invites.isResolving.value && invites.action.value.token !== invite.token)
|
|
53
|
-
"
|
|
54
|
-
@click="invites.refuse(invite)"
|
|
55
|
-
>
|
|
56
|
-
Refuse
|
|
57
|
-
</v-btn>
|
|
58
|
-
<v-btn
|
|
59
|
-
size="small"
|
|
60
|
-
variant="tonal"
|
|
61
|
-
color="primary"
|
|
62
|
-
:loading="invites.action.value.token === invite.token && invites.action.value.decision === 'accept'"
|
|
63
|
-
:disabled="
|
|
64
|
-
invites.isRefetching.value || (invites.isResolving.value && invites.action.value.token !== invite.token)
|
|
65
|
-
"
|
|
66
|
-
@click="invites.accept(invite)"
|
|
67
|
-
>
|
|
68
|
-
Join
|
|
69
|
-
</v-btn>
|
|
70
|
-
</div>
|
|
71
|
-
</template>
|
|
72
|
-
</v-list-item>
|
|
73
|
-
</v-list>
|
|
74
|
-
</template>
|
|
75
|
-
</v-card-text>
|
|
76
|
-
</v-card>
|
|
77
|
-
</template>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import ShellOutlet from "@jskit-ai/shell-web/client/components/ShellOutlet";
|
|
3
|
-
import { RouterView } from "vue-router";
|
|
4
|
-
</script>
|
|
5
|
-
|
|
6
|
-
<template>
|
|
7
|
-
<section class="settings-shell d-flex flex-column ga-4">
|
|
8
|
-
<v-card rounded="lg" elevation="1" border>
|
|
9
|
-
<v-card-item>
|
|
10
|
-
<v-card-title>Console settings</v-card-title>
|
|
11
|
-
<v-card-subtitle>Global configuration and reference data for the whole app.</v-card-subtitle>
|
|
12
|
-
</v-card-item>
|
|
13
|
-
<v-divider />
|
|
14
|
-
<v-card-text class="pt-4">
|
|
15
|
-
<v-row no-gutters>
|
|
16
|
-
<v-col cols="12" md="3" lg="2" class="pr-md-4 mb-4 mb-md-0">
|
|
17
|
-
<v-list nav density="comfortable" rounded="lg" border>
|
|
18
|
-
<ShellOutlet
|
|
19
|
-
target="console-settings:primary-menu"
|
|
20
|
-
default-link-component-token="local.main.ui.surface-aware-menu-link-item"
|
|
21
|
-
/>
|
|
22
|
-
</v-list>
|
|
23
|
-
</v-col>
|
|
24
|
-
|
|
25
|
-
<v-col cols="12" md="9" lg="10">
|
|
26
|
-
<RouterView />
|
|
27
|
-
</v-col>
|
|
28
|
-
</v-row>
|
|
29
|
-
</v-card-text>
|
|
30
|
-
</v-card>
|
|
31
|
-
</section>
|
|
32
|
-
</template>
|