@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.
Files changed (73) hide show
  1. package/package.descriptor.mjs +14 -96
  2. package/package.json +16 -11
  3. package/src/client/account-settings/sections.js +74 -0
  4. package/src/client/composables/account-settings/accountSettingsRuntimeHelpers.js +2 -38
  5. package/src/client/composables/crud/crudLookupFieldRuntime.js +2 -2
  6. package/src/client/composables/internal/crudListParentTitleSupport.js +1 -1
  7. package/src/client/composables/internal/useOperationScope.js +12 -12
  8. package/src/client/composables/records/useAddEdit.js +2 -2
  9. package/src/client/composables/records/useList.js +3 -3
  10. package/src/client/composables/records/useView.js +2 -2
  11. package/src/client/composables/support/scopeHelpers.js +19 -19
  12. package/src/client/composables/useAccess.js +3 -3
  13. package/src/client/composables/useAccountSettingsRuntime.js +8 -156
  14. package/src/client/composables/useCommand.js +2 -2
  15. package/src/client/composables/useCrudListParentTitle.js +2 -2
  16. package/src/client/composables/usePaths.js +50 -38
  17. package/src/client/composables/useScopeRuntime.js +55 -27
  18. package/src/client/composables/useSurfaceRouteContext.js +1 -7
  19. package/src/client/index.js +0 -1
  20. package/src/client/lib/bootstrap.js +0 -63
  21. package/src/client/lib/httpClient.js +2 -59
  22. package/src/client/lib/theme.js +12 -189
  23. package/src/client/providers/UsersWebClientProvider.js +2 -25
  24. package/src/client/providers/bootUsersWebClientProvider.js +28 -0
  25. package/src/shared/toolsOutletContracts.js +1 -8
  26. package/templates/src/components/account/settings/AccountSettingsClientElement.vue +33 -21
  27. package/test/accountSettingsSections.test.js +79 -0
  28. package/test/exportsContract.test.js +2 -2
  29. package/test/scopeHelpers.test.js +6 -6
  30. package/test/settingsPlacementContract.test.js +4 -49
  31. package/test/theme.test.js +0 -56
  32. package/src/client/components/ConsoleSettingsClientElement.vue +0 -24
  33. package/src/client/components/MembersAdminClientElement.vue +0 -400
  34. package/src/client/components/UsersProfileSurfaceSwitchMenuItem.vue +0 -39
  35. package/src/client/components/UsersWorkspaceMembersMenuItem.vue +0 -36
  36. package/src/client/components/UsersWorkspacePermissionMenuItem.vue +0 -90
  37. package/src/client/components/UsersWorkspaceSelector.vue +0 -248
  38. package/src/client/components/UsersWorkspaceSettingsMenuItem.vue +0 -39
  39. package/src/client/components/UsersWorkspaceToolsWidget.vue +0 -12
  40. package/src/client/components/WorkspaceMembersClientElement.vue +0 -655
  41. package/src/client/components/WorkspaceProfileClientElement.vue +0 -116
  42. package/src/client/components/WorkspaceSettingsClientElement.vue +0 -102
  43. package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +0 -265
  44. package/src/client/components/WorkspacesClientElement.vue +0 -509
  45. package/src/client/composables/account-settings/accountSettingsInvitesRuntime.js +0 -88
  46. package/src/client/composables/useBootstrapQuery.js +0 -52
  47. package/src/client/composables/useWorkspaceRouteContext.js +0 -28
  48. package/src/client/composables/useWorkspaceSurfaceId.js +0 -43
  49. package/src/client/lib/menuIcons.js +0 -210
  50. package/src/client/lib/profileSurfaceMenuLinks.js +0 -142
  51. package/src/client/lib/surfaceAccessPolicy.js +0 -350
  52. package/src/client/lib/workspaceLinkResolver.js +0 -207
  53. package/src/client/lib/workspaceSurfaceContext.js +0 -82
  54. package/src/client/lib/workspaceSurfacePaths.js +0 -163
  55. package/src/client/providers/UsersWorkspacesClientProvider.js +0 -24
  56. package/src/client/runtime/bootstrapPlacementRouteGuards.js +0 -371
  57. package/src/client/runtime/bootstrapPlacementRuntime.js +0 -463
  58. package/src/client/runtime/bootstrapPlacementRuntimeConstants.js +0 -28
  59. package/src/client/runtime/bootstrapPlacementRuntimeHelpers.js +0 -147
  60. package/src/client/support/menuLinkTarget.js +0 -93
  61. package/src/client/support/realtimeWorkspace.js +0 -21
  62. package/src/client/support/runtimeNormalization.js +0 -27
  63. package/src/client/support/workspaceQueryKeys.js +0 -15
  64. package/templates/src/components/account/settings/AccountSettingsInvitesSection.vue +0 -77
  65. package/templates/src/pages/console/settings/index.vue +0 -8
  66. package/templates/src/pages/console/settings.vue +0 -32
  67. package/test/bootstrapPlacementRuntime.test.js +0 -1095
  68. package/test/menuIcons.test.js +0 -35
  69. package/test/menuLinkTarget.test.js +0 -116
  70. package/test/profileSurfaceMenuLinks.test.js +0 -207
  71. package/test/surfaceAccessPolicy.test.js +0 -129
  72. package/test/workspaceLinkResolver.test.js +0 -61
  73. package/test/workspaceSurfacePaths.test.js +0 -39
@@ -1,116 +0,0 @@
1
- <template>
2
- <v-card class="mb-4" rounded="lg" elevation="1" border>
3
- <v-card-item>
4
- <v-card-title class="text-h6">Workspace profile</v-card-title>
5
- <v-card-subtitle>Name and avatar used across the workspace.</v-card-subtitle>
6
- </v-card-item>
7
- <v-divider />
8
- <v-card-text class="pt-4">
9
- <template v-if="showSkeleton">
10
- <v-skeleton-loader type="text@2, list-item-two-line@3, button" />
11
- </template>
12
-
13
- <p v-else-if="addEdit.loadError" class="text-body-2 text-medium-emphasis mb-4">
14
- {{ addEdit.loadError }}
15
- </p>
16
-
17
- <p v-else-if="!addEdit.canView" class="text-body-2 text-medium-emphasis mb-4">
18
- You do not have permission to view workspace profile.
19
- </p>
20
-
21
- <template v-else>
22
- <v-form @submit.prevent="addEdit.submit" novalidate>
23
- <v-progress-linear v-if="addEdit.isRefetching" indeterminate class="mb-4" />
24
- <v-row>
25
- <v-col cols="12" md="6">
26
- <v-text-field
27
- v-model="workspaceProfileForm.name"
28
- label="Workspace name"
29
- variant="outlined"
30
- density="comfortable"
31
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
32
- :error-messages="addEdit.fieldErrors.name ? [addEdit.fieldErrors.name] : []"
33
- />
34
- </v-col>
35
-
36
- <v-col cols="12" md="6">
37
- <v-text-field
38
- v-model="workspaceProfileForm.avatarUrl"
39
- label="Workspace avatar URL"
40
- variant="outlined"
41
- density="comfortable"
42
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
43
- placeholder="https://..."
44
- hint="Optional"
45
- persistent-hint
46
- :error-messages="addEdit.fieldErrors.avatarUrl ? [addEdit.fieldErrors.avatarUrl] : []"
47
- />
48
- </v-col>
49
-
50
- <v-col cols="12" class="d-flex align-center justify-end ga-3">
51
- <v-btn
52
- v-if="addEdit.canSave"
53
- type="submit"
54
- color="primary"
55
- :loading="addEdit.isSaving"
56
- :disabled="addEdit.isInitialLoading || addEdit.isRefetching"
57
- >
58
- Save workspace profile
59
- </v-btn>
60
- <v-chip v-else color="secondary" label>Read-only</v-chip>
61
- </v-col>
62
- </v-row>
63
- </v-form>
64
- </template>
65
- </v-card-text>
66
- </v-card>
67
- </template>
68
-
69
- <script setup>
70
- import { computed, reactive } from "vue";
71
- import { validateOperationSection } from "@jskit-ai/http-runtime/shared/validators/operationValidation";
72
- import { workspaceResource } from "@jskit-ai/users-core/shared/resources/workspaceResource";
73
- import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
74
- import { useAddEdit } from "../composables/records/useAddEdit.js";
75
- import { buildWorkspaceQueryKey } from "../support/workspaceQueryKeys.js";
76
-
77
- const emit = defineEmits(["saved"]);
78
-
79
- const workspaceProfileForm = reactive({
80
- name: "",
81
- avatarUrl: ""
82
- });
83
-
84
- const addEdit = useAddEdit({
85
- ownershipFilter: USERS_ROUTE_VISIBILITY_WORKSPACE,
86
- resource: workspaceResource,
87
- apiSuffix: "/",
88
- queryKeyFactory: (surfaceId = "", workspaceSlug = "") =>
89
- buildWorkspaceQueryKey("profile", surfaceId, workspaceSlug),
90
- viewPermissions: ["workspace.settings.view", "workspace.settings.update"],
91
- savePermissions: ["workspace.settings.update"],
92
- placementSource: "users-web.workspace-profile-view",
93
- fallbackLoadError: "Unable to load workspace profile.",
94
- fieldErrorKeys: ["name", "avatarUrl"],
95
- model: workspaceProfileForm,
96
- parseInput: (rawPayload) =>
97
- validateOperationSection({
98
- operation: workspaceResource.operations.patch,
99
- section: "bodyValidator",
100
- value: rawPayload
101
- }),
102
- mapLoadedToModel: (model, payload = {}) => {
103
- model.name = String(payload?.name || "");
104
- model.avatarUrl = String(payload?.avatarUrl || "");
105
- },
106
- buildRawPayload: (model) => ({
107
- name: model.name,
108
- avatarUrl: model.avatarUrl
109
- }),
110
- onSaveSuccess: async () => {
111
- emit("saved");
112
- }
113
- });
114
-
115
- const showSkeleton = computed(() => Boolean(addEdit.isInitialLoading));
116
- </script>
@@ -1,102 +0,0 @@
1
- <template>
2
- <section class="workspace-settings-client-element">
3
- <WorkspaceProfileClientElement @saved="handleFormSaved" />
4
- <WorkspaceSettingsFieldsClientElement @saved="handleFormSaved" />
5
- </section>
6
- </template>
7
-
8
- <script setup>
9
- import { computed, watch } from "vue";
10
- import { useWebPlacementContext } from "@jskit-ai/shell-web/client/placement";
11
- import { useBootstrapQuery } from "../composables/useBootstrapQuery.js";
12
- import { useWorkspaceRouteContext } from "../composables/useWorkspaceRouteContext.js";
13
- import { findWorkspaceBySlug, normalizeWorkspaceList } from "../lib/bootstrap.js";
14
- import { arePermissionListsEqual, normalizePermissionList } from "../lib/permissions.js";
15
- import WorkspaceProfileClientElement from "./WorkspaceProfileClientElement.vue";
16
- import WorkspaceSettingsFieldsClientElement from "./WorkspaceSettingsFieldsClientElement.vue";
17
-
18
- const routeContext = useWorkspaceRouteContext();
19
- const { context: placementContext, mergeContext: mergePlacementContext } = useWebPlacementContext();
20
- const bootstrapQuery = useBootstrapQuery({
21
- workspaceSlug: routeContext.workspaceSlugFromRoute,
22
- enabled: computed(() => Boolean(routeContext.workspaceSlugFromRoute.value))
23
- });
24
-
25
- function toWorkspaceEntrySnapshot(entry = null) {
26
- if (!entry || typeof entry !== "object") {
27
- return "";
28
- }
29
-
30
- const normalizedEntry = normalizeWorkspaceList([entry])[0] || null;
31
- if (!normalizedEntry) {
32
- return "";
33
- }
34
-
35
- return JSON.stringify(normalizedEntry);
36
- }
37
-
38
- function toWorkspaceListSnapshot(list = []) {
39
- return JSON.stringify(normalizeWorkspaceList(list));
40
- }
41
-
42
- function toWorkspaceSettingsSnapshot(settings = null) {
43
- if (!settings || typeof settings !== "object") {
44
- return "";
45
- }
46
-
47
- return JSON.stringify(settings);
48
- }
49
-
50
- function applyShellWorkspaceContext(payload = {}) {
51
- const availableWorkspaces = normalizeWorkspaceList(payload?.workspaces);
52
- const currentWorkspace = findWorkspaceBySlug(
53
- availableWorkspaces,
54
- routeContext.workspaceSlugFromRoute.value
55
- );
56
- const permissions = normalizePermissionList(payload?.permissions);
57
- const currentContext =
58
- placementContext.value && typeof placementContext.value === "object"
59
- ? placementContext.value
60
- : {};
61
- const currentPermissions = normalizePermissionList(currentContext.permissions);
62
- const samePermissions = arePermissionListsEqual(permissions, currentPermissions);
63
- const sameWorkspace = toWorkspaceEntrySnapshot(currentContext.workspace) === toWorkspaceEntrySnapshot(currentWorkspace);
64
- const sameWorkspaces =
65
- toWorkspaceListSnapshot(currentContext.workspaces) === toWorkspaceListSnapshot(availableWorkspaces);
66
- const sameWorkspaceSettings =
67
- toWorkspaceSettingsSnapshot(currentContext.workspaceSettings) ===
68
- toWorkspaceSettingsSnapshot(payload?.workspaceSettings);
69
-
70
- if (samePermissions && sameWorkspace && sameWorkspaces && sameWorkspaceSettings) {
71
- return;
72
- }
73
-
74
- mergePlacementContext(
75
- {
76
- workspace: currentWorkspace,
77
- workspaceSettings:
78
- payload?.workspaceSettings && typeof payload.workspaceSettings === "object"
79
- ? payload.workspaceSettings
80
- : null,
81
- workspaces: availableWorkspaces,
82
- permissions
83
- },
84
- "users-web.workspace-settings-view"
85
- );
86
- }
87
-
88
- watch(
89
- () => bootstrapQuery.query.data.value,
90
- (payload) => {
91
- if (!payload || typeof payload !== "object") {
92
- return;
93
- }
94
- applyShellWorkspaceContext(payload);
95
- },
96
- { immediate: true }
97
- );
98
-
99
- async function handleFormSaved() {
100
- await bootstrapQuery.query.refetch();
101
- }
102
- </script>
@@ -1,265 +0,0 @@
1
- <template>
2
- <v-card rounded="lg" elevation="1" border>
3
- <v-card-item>
4
- <v-card-title class="text-h6">Workspace settings</v-card-title>
5
- <v-card-subtitle>These values apply to everyone in this workspace.</v-card-subtitle>
6
- </v-card-item>
7
- <v-divider />
8
- <v-card-text class="pt-4">
9
- <template v-if="showSkeleton">
10
- <v-skeleton-loader type="text@2, list-item-two-line@4, button" />
11
- </template>
12
-
13
- <p v-else-if="addEdit.loadError" class="text-body-2 text-medium-emphasis mb-4">
14
- {{ addEdit.loadError }}
15
- </p>
16
-
17
- <p v-else-if="!addEdit.canView" class="text-body-2 text-medium-emphasis mb-4">
18
- You do not have permission to view workspace settings.
19
- </p>
20
-
21
- <template v-else>
22
- <v-form @submit.prevent="addEdit.submit" novalidate>
23
- <v-progress-linear v-if="addEdit.isRefetching" indeterminate class="mb-4" />
24
- <v-row>
25
- <v-col cols="12">
26
- <div class="text-subtitle-2 mb-2">Theme colors</div>
27
- <v-row dense class="mb-2">
28
- <v-col cols="12">
29
- <div class="text-caption text-medium-emphasis mb-2">Light palette</div>
30
- </v-col>
31
- <v-col cols="12" md="3">
32
- <v-text-field
33
- v-model="workspaceSettingsForm.lightPrimaryColor"
34
- label="Primary"
35
- type="color"
36
- variant="outlined"
37
- density="comfortable"
38
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
39
- :error-messages="addEdit.fieldErrors.lightPrimaryColor ? [addEdit.fieldErrors.lightPrimaryColor] : []"
40
- />
41
- </v-col>
42
-
43
- <v-col cols="12" md="3">
44
- <v-text-field
45
- v-model="workspaceSettingsForm.lightSecondaryColor"
46
- label="Secondary"
47
- type="color"
48
- variant="outlined"
49
- density="comfortable"
50
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
51
- :error-messages="
52
- addEdit.fieldErrors.lightSecondaryColor ? [addEdit.fieldErrors.lightSecondaryColor] : []
53
- "
54
- />
55
- </v-col>
56
-
57
- <v-col cols="12" md="3">
58
- <v-text-field
59
- v-model="workspaceSettingsForm.lightSurfaceColor"
60
- label="Surface"
61
- type="color"
62
- variant="outlined"
63
- density="comfortable"
64
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
65
- :error-messages="addEdit.fieldErrors.lightSurfaceColor ? [addEdit.fieldErrors.lightSurfaceColor] : []"
66
- />
67
- </v-col>
68
-
69
- <v-col cols="12" md="3">
70
- <v-text-field
71
- v-model="workspaceSettingsForm.lightSurfaceVariantColor"
72
- label="Surface variant"
73
- type="color"
74
- variant="outlined"
75
- density="comfortable"
76
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
77
- :error-messages="
78
- addEdit.fieldErrors.lightSurfaceVariantColor ? [addEdit.fieldErrors.lightSurfaceVariantColor] : []
79
- "
80
- />
81
- </v-col>
82
- </v-row>
83
-
84
- <v-row dense>
85
- <v-col cols="12">
86
- <div class="text-caption text-medium-emphasis mb-2">Dark palette</div>
87
- </v-col>
88
- <v-col cols="12" md="3">
89
- <v-text-field
90
- v-model="workspaceSettingsForm.darkPrimaryColor"
91
- label="Primary"
92
- type="color"
93
- variant="outlined"
94
- density="comfortable"
95
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
96
- :error-messages="addEdit.fieldErrors.darkPrimaryColor ? [addEdit.fieldErrors.darkPrimaryColor] : []"
97
- />
98
- </v-col>
99
-
100
- <v-col cols="12" md="3">
101
- <v-text-field
102
- v-model="workspaceSettingsForm.darkSecondaryColor"
103
- label="Secondary"
104
- type="color"
105
- variant="outlined"
106
- density="comfortable"
107
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
108
- :error-messages="addEdit.fieldErrors.darkSecondaryColor ? [addEdit.fieldErrors.darkSecondaryColor] : []"
109
- />
110
- </v-col>
111
-
112
- <v-col cols="12" md="3">
113
- <v-text-field
114
- v-model="workspaceSettingsForm.darkSurfaceColor"
115
- label="Surface"
116
- type="color"
117
- variant="outlined"
118
- density="comfortable"
119
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
120
- :error-messages="addEdit.fieldErrors.darkSurfaceColor ? [addEdit.fieldErrors.darkSurfaceColor] : []"
121
- />
122
- </v-col>
123
-
124
- <v-col cols="12" md="3">
125
- <v-text-field
126
- v-model="workspaceSettingsForm.darkSurfaceVariantColor"
127
- label="Surface variant"
128
- type="color"
129
- variant="outlined"
130
- density="comfortable"
131
- :readonly="!addEdit.canSave || addEdit.isSaving || addEdit.isRefetching"
132
- :error-messages="
133
- addEdit.fieldErrors.darkSurfaceVariantColor ? [addEdit.fieldErrors.darkSurfaceVariantColor] : []
134
- "
135
- />
136
- </v-col>
137
- </v-row>
138
- </v-col>
139
-
140
- <v-col cols="12" md="6" class="d-flex align-center">
141
- <v-switch
142
- v-model="workspaceSettingsForm.invitesEnabled"
143
- color="primary"
144
- hide-details
145
- label="Enable invites"
146
- :disabled="!addEdit.canSave || !workspaceSettingsForm.invitesAvailable || addEdit.isSaving || addEdit.isRefetching"
147
- />
148
- </v-col>
149
-
150
- <v-col cols="12" class="d-flex align-center justify-end ga-3">
151
- <v-btn
152
- v-if="addEdit.canSave"
153
- type="submit"
154
- color="primary"
155
- :loading="addEdit.isSaving"
156
- :disabled="addEdit.isInitialLoading || addEdit.isRefetching"
157
- >
158
- Save workspace settings
159
- </v-btn>
160
- <v-chip v-else color="secondary" label>Read-only</v-chip>
161
- </v-col>
162
- </v-row>
163
- </v-form>
164
- </template>
165
- </v-card-text>
166
- </v-card>
167
- </template>
168
-
169
- <script setup>
170
- import { computed, reactive } from "vue";
171
- import { validateOperationSection } from "@jskit-ai/http-runtime/shared/validators/operationValidation";
172
- import { workspaceSettingsResource } from "@jskit-ai/users-core/shared/resources/workspaceSettingsResource";
173
- import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
174
- import {
175
- DEFAULT_WORKSPACE_DARK_PALETTE,
176
- DEFAULT_WORKSPACE_LIGHT_PALETTE,
177
- resolveWorkspaceThemePalettes
178
- } from "@jskit-ai/users-core/shared/settings";
179
- import { useAddEdit } from "../composables/records/useAddEdit.js";
180
- import { useWorkspaceRouteContext } from "../composables/useWorkspaceRouteContext.js";
181
- import { createWorkspaceRealtimeMatcher } from "../support/realtimeWorkspace.js";
182
- import { buildWorkspaceQueryKey } from "../support/workspaceQueryKeys.js";
183
-
184
- const emit = defineEmits(["saved"]);
185
-
186
- const workspaceSettingsForm = reactive({
187
- lightPrimaryColor: DEFAULT_WORKSPACE_LIGHT_PALETTE.color,
188
- lightSecondaryColor: DEFAULT_WORKSPACE_LIGHT_PALETTE.secondaryColor,
189
- lightSurfaceColor: DEFAULT_WORKSPACE_LIGHT_PALETTE.surfaceColor,
190
- lightSurfaceVariantColor: DEFAULT_WORKSPACE_LIGHT_PALETTE.surfaceVariantColor,
191
- darkPrimaryColor: DEFAULT_WORKSPACE_DARK_PALETTE.color,
192
- darkSecondaryColor: DEFAULT_WORKSPACE_DARK_PALETTE.secondaryColor,
193
- darkSurfaceColor: DEFAULT_WORKSPACE_DARK_PALETTE.surfaceColor,
194
- darkSurfaceVariantColor: DEFAULT_WORKSPACE_DARK_PALETTE.surfaceVariantColor,
195
- invitesEnabled: false,
196
- invitesAvailable: false
197
- });
198
-
199
- const routeContext = useWorkspaceRouteContext();
200
- const matchesWorkspaceRealtime = createWorkspaceRealtimeMatcher(routeContext.workspaceSlugFromRoute);
201
-
202
- const addEdit = useAddEdit({
203
- ownershipFilter: USERS_ROUTE_VISIBILITY_WORKSPACE,
204
- resource: workspaceSettingsResource,
205
- apiSuffix: "/settings",
206
- queryKeyFactory: (surfaceId = "", workspaceSlug = "") =>
207
- buildWorkspaceQueryKey("settings", surfaceId, workspaceSlug),
208
- viewPermissions: ["workspace.settings.view", "workspace.settings.update"],
209
- savePermissions: ["workspace.settings.update"],
210
- placementSource: "users-web.workspace-settings-view",
211
- fallbackLoadError: "Unable to load workspace settings.",
212
- fieldErrorKeys: [
213
- "lightPrimaryColor",
214
- "lightSecondaryColor",
215
- "lightSurfaceColor",
216
- "lightSurfaceVariantColor",
217
- "darkPrimaryColor",
218
- "darkSecondaryColor",
219
- "darkSurfaceColor",
220
- "darkSurfaceVariantColor"
221
- ],
222
- realtime: {
223
- event: "workspace.settings.changed",
224
- matches: matchesWorkspaceRealtime
225
- },
226
- model: workspaceSettingsForm,
227
- parseInput: (rawPayload) =>
228
- validateOperationSection({
229
- operation: workspaceSettingsResource.operations.patch,
230
- section: "bodyValidator",
231
- value: rawPayload
232
- }),
233
- mapLoadedToModel: (model, payload = {}) => {
234
- const settings = payload?.settings && typeof payload.settings === "object" ? payload.settings : {};
235
- const normalizedTheme = resolveWorkspaceThemePalettes(settings);
236
-
237
- model.lightPrimaryColor = normalizedTheme.light.color;
238
- model.lightSecondaryColor = normalizedTheme.light.secondaryColor;
239
- model.lightSurfaceColor = normalizedTheme.light.surfaceColor;
240
- model.lightSurfaceVariantColor = normalizedTheme.light.surfaceVariantColor;
241
- model.darkPrimaryColor = normalizedTheme.dark.color;
242
- model.darkSecondaryColor = normalizedTheme.dark.secondaryColor;
243
- model.darkSurfaceColor = normalizedTheme.dark.surfaceColor;
244
- model.darkSurfaceVariantColor = normalizedTheme.dark.surfaceVariantColor;
245
- model.invitesEnabled = settings.invitesEnabled !== false;
246
- model.invitesAvailable = settings.invitesAvailable !== false;
247
- },
248
- buildRawPayload: (model) => ({
249
- lightPrimaryColor: model.lightPrimaryColor,
250
- lightSecondaryColor: model.lightSecondaryColor,
251
- lightSurfaceColor: model.lightSurfaceColor,
252
- lightSurfaceVariantColor: model.lightSurfaceVariantColor,
253
- darkPrimaryColor: model.darkPrimaryColor,
254
- darkSecondaryColor: model.darkSecondaryColor,
255
- darkSurfaceColor: model.darkSurfaceColor,
256
- darkSurfaceVariantColor: model.darkSurfaceVariantColor,
257
- invitesEnabled: model.invitesEnabled
258
- }),
259
- onSaveSuccess: async () => {
260
- emit("saved");
261
- }
262
- });
263
-
264
- const showSkeleton = computed(() => Boolean(addEdit.isInitialLoading));
265
- </script>