@jskit-ai/users-web 0.1.36 → 0.1.38

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 (79) hide show
  1. package/package.descriptor.mjs +8 -22
  2. package/package.json +16 -11
  3. package/src/client/components/MembersAdminClientElement.vue +5 -5
  4. package/src/client/components/UsersSurfaceAwareMenuLinkItem.vue +14 -25
  5. package/src/client/components/WorkspaceMembersClientElement.vue +19 -19
  6. package/src/client/components/WorkspaceProfileClientElement.vue +1 -1
  7. package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +1 -1
  8. package/src/client/components/WorkspacesClientElement.vue +4 -4
  9. package/src/client/composables/account-settings/accountSettingsAvatarUploadRuntime.js +61 -0
  10. package/src/client/composables/{accountSettingsInvitesRuntime.js → account-settings/accountSettingsInvitesRuntime.js} +1 -1
  11. package/src/client/composables/{accountSettingsRuntimeConstants.js → account-settings/accountSettingsRuntimeConstants.js} +0 -4
  12. package/src/client/composables/{accountSettingsRuntimeHelpers.js → account-settings/accountSettingsRuntimeHelpers.js} +2 -2
  13. package/src/client/composables/crud/crudBindingSupport.js +75 -0
  14. package/src/client/composables/{crudLookupFieldLabelSupport.js → crud/crudLookupFieldLabelSupport.js} +37 -5
  15. package/src/client/composables/{crudLookupFieldRuntime.js → crud/crudLookupFieldRuntime.js} +11 -4
  16. package/src/client/composables/{crudSchemaFormHelpers.js → crud/crudSchemaFormHelpers.js} +178 -5
  17. package/src/client/composables/internal/crudListParentTitleSupport.js +168 -0
  18. package/src/client/composables/internal/useOperationScope.js +1 -1
  19. package/src/client/composables/{useAddEdit.js → records/useAddEdit.js} +18 -8
  20. package/src/client/composables/{useCrudSchemaForm.js → records/useCrudAddEdit.js} +32 -15
  21. package/src/client/composables/records/useCrudList.js +83 -0
  22. package/src/client/composables/records/useCrudView.js +35 -0
  23. package/src/client/composables/records/useList.js +482 -0
  24. package/src/client/composables/{useView.js → records/useView.js} +7 -7
  25. package/src/client/composables/{addEditUiRuntime.js → runtime/addEditUiRuntime.js} +13 -4
  26. package/src/client/composables/{listUiRuntime.js → runtime/listUiRuntime.js} +20 -8
  27. package/src/client/composables/{operationAdapters.js → runtime/operationAdapters.js} +1 -1
  28. package/src/client/composables/{useEndpointResource.js → runtime/useEndpointResource.js} +5 -5
  29. package/src/client/composables/{useListCore.js → runtime/useListCore.js} +4 -4
  30. package/src/client/composables/{useUiFeedback.js → runtime/useUiFeedback.js} +1 -1
  31. package/src/client/composables/{viewUiRuntime.js → runtime/viewUiRuntime.js} +13 -4
  32. package/src/client/composables/support/listQueryParamSupport.js +459 -0
  33. package/src/client/composables/{routeTemplateHelpers.js → support/routeTemplateHelpers.js} +122 -0
  34. package/src/client/composables/useAccess.js +2 -2
  35. package/src/client/composables/useAccountSettingsRuntime.js +6 -6
  36. package/src/client/composables/useBootstrapQuery.js +1 -1
  37. package/src/client/composables/useCommand.js +5 -5
  38. package/src/client/composables/useCrudListParentTitle.js +131 -0
  39. package/src/client/composables/usePagedCollection.js +58 -7
  40. package/src/client/composables/useScopeRuntime.js +1 -1
  41. package/src/client/lib/bootstrap.js +1 -1
  42. package/src/client/lib/menuIcons.js +27 -6
  43. package/src/client/support/menuLinkTarget.js +93 -0
  44. package/templates/src/components/WorkspaceNotFoundCard.vue +2 -1
  45. package/templates/src/components/account/settings/AccountSettingsInvitesSection.vue +1 -1
  46. package/test/addEditUiRuntime.test.js +19 -1
  47. package/test/crudBindingSupport.test.js +110 -0
  48. package/test/crudLookupFieldRuntime.test.js +52 -2
  49. package/test/errorMessageHelpers.test.js +1 -1
  50. package/test/exportsContract.test.js +10 -1
  51. package/test/listQueryParamSupport.test.js +190 -0
  52. package/test/listUiRuntime.test.js +22 -1
  53. package/test/menuIcons.test.js +2 -0
  54. package/test/menuLinkTarget.test.js +116 -0
  55. package/test/permissions.test.js +2 -2
  56. package/test/refValueHelpers.test.js +1 -1
  57. package/test/resourceLoadStateHelpers.test.js +1 -1
  58. package/test/routeTemplateHelpers.test.js +57 -1
  59. package/test/scopeHelpers.test.js +1 -1
  60. package/test/{useCrudSchemaForm.test.js → useCrudAddEdit.test.js} +81 -1
  61. package/test/useCrudListParentTitle.test.js +143 -0
  62. package/test/useListSearchSupport.test.js +1 -1
  63. package/test/usePagedCollection.test.js +53 -0
  64. package/test/viewCoreLoading.test.js +1 -1
  65. package/test/viewUiRuntime.test.js +36 -1
  66. package/src/client/composables/accountSettingsAvatarUploadRuntime.js +0 -241
  67. package/src/client/composables/useList.js +0 -268
  68. /package/src/client/composables/{modelStateHelpers.js → runtime/modelStateHelpers.js} +0 -0
  69. /package/src/client/composables/{operationUiHelpers.js → runtime/operationUiHelpers.js} +0 -0
  70. /package/src/client/composables/{operationValidationHelpers.js → runtime/operationValidationHelpers.js} +0 -0
  71. /package/src/client/composables/{useAddEditCore.js → runtime/useAddEditCore.js} +0 -0
  72. /package/src/client/composables/{useCommandCore.js → runtime/useCommandCore.js} +0 -0
  73. /package/src/client/composables/{useFieldErrorBag.js → runtime/useFieldErrorBag.js} +0 -0
  74. /package/src/client/composables/{useViewCore.js → runtime/useViewCore.js} +0 -0
  75. /package/src/client/composables/{errorMessageHelpers.js → support/errorMessageHelpers.js} +0 -0
  76. /package/src/client/composables/{listSearchSupport.js → support/listSearchSupport.js} +0 -0
  77. /package/src/client/composables/{refValueHelpers.js → support/refValueHelpers.js} +0 -0
  78. /package/src/client/composables/{resourceLoadStateHelpers.js → support/resourceLoadStateHelpers.js} +0 -0
  79. /package/src/client/composables/{scopeHelpers.js → support/scopeHelpers.js} +0 -0
@@ -1,268 +0,0 @@
1
- import { computed, onScopeDispose, proxyRefs, ref, watch } from "vue";
2
- import { appendQueryString } from "@jskit-ai/kernel/shared/support";
3
- import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
4
- import { resolveCrudLookupFieldKeys } from "@jskit-ai/kernel/shared/support/crudLookup";
5
- import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
6
- import { useListCore } from "./useListCore.js";
7
- import { resolveOperationAdapter } from "./operationAdapters.js";
8
- import { setupOperationErrorReporting } from "./operationUiHelpers.js";
9
- import { createListUiRuntime } from "./listUiRuntime.js";
10
- import {
11
- normalizeListSearchConfig,
12
- matchesLocalSearch
13
- } from "./listSearchSupport.js";
14
- import { resolveLookupFieldDisplayValue } from "./crudLookupFieldLabelSupport.js";
15
- import {
16
- resolveRouteParamNamesInOrder,
17
- resolveRouteParamsSource,
18
- toRouteParamValue
19
- } from "./routeTemplateHelpers.js";
20
-
21
- function useList({
22
- ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE,
23
- surfaceId = "",
24
- access = "auto",
25
- apiSuffix = "",
26
- queryKeyFactory = null,
27
- viewPermissions = [],
28
- readEnabled = true,
29
- placementSource = "users-web.list",
30
- fallbackLoadError = "Unable to load list.",
31
- initialPageParam = null,
32
- getNextPageParam,
33
- selectItems,
34
- requestOptions,
35
- queryOptions,
36
- realtime = null,
37
- adapter = null,
38
- resource = null,
39
- recordIdParam = "recordId",
40
- recordIdSelector = null,
41
- viewUrlTemplate = "",
42
- editUrlTemplate = "",
43
- search = null
44
- } = {}) {
45
- const searchConfig = normalizeListSearchConfig(search);
46
- const searchQuery = ref(searchConfig.initialQuery);
47
- const debouncedSearchQuery = ref(searchConfig.initialQuery);
48
- let searchDebounceTimer = null;
49
- const isSearchDebouncing = ref(false);
50
-
51
- watch(searchQuery, (value) => {
52
- const normalizedValue = normalizeText(value);
53
- if (searchDebounceTimer) {
54
- clearTimeout(searchDebounceTimer);
55
- }
56
- if (searchConfig.enabled !== true) {
57
- debouncedSearchQuery.value = normalizedValue;
58
- isSearchDebouncing.value = false;
59
- return;
60
- }
61
- isSearchDebouncing.value = true;
62
- searchDebounceTimer = setTimeout(() => {
63
- debouncedSearchQuery.value = normalizedValue;
64
- isSearchDebouncing.value = false;
65
- searchDebounceTimer = null;
66
- }, searchConfig.debounceMs);
67
- }, { immediate: true });
68
-
69
- onScopeDispose(() => {
70
- if (!searchDebounceTimer) {
71
- return;
72
- }
73
- clearTimeout(searchDebounceTimer);
74
- searchDebounceTimer = null;
75
- });
76
-
77
- const operationAdapter = resolveOperationAdapter(adapter, {
78
- context: "useList adapter"
79
- });
80
- const operationScope = operationAdapter.useOperationScope({
81
- ownershipFilter,
82
- surfaceId,
83
- access,
84
- placementSource,
85
- apiSuffix,
86
- readEnabled,
87
- queryKeyFactory,
88
- permissionSets: {
89
- view: viewPermissions
90
- },
91
- realtime
92
- });
93
- const canView = operationScope.permissionGate("view");
94
- const parentRouteFilter = computed(() => {
95
- const lookupFieldKeys = resolveCrudLookupFieldKeys(resource);
96
- if (lookupFieldKeys.length < 1) {
97
- return null;
98
- }
99
-
100
- const lookupFieldKeySet = new Set(lookupFieldKeys);
101
- const sourceRoute = operationScope.routeContext.route;
102
- const orderedRouteParamNames = resolveRouteParamNamesInOrder(sourceRoute);
103
- if (orderedRouteParamNames.length < 1) {
104
- return null;
105
- }
106
-
107
- const normalizedRecordIdParam = normalizeText(recordIdParam) || "recordId";
108
- const parentParamName = [...orderedRouteParamNames]
109
- .reverse()
110
- .find((name) => (
111
- name !== "workspaceSlug" &&
112
- name !== normalizedRecordIdParam &&
113
- lookupFieldKeySet.has(name)
114
- )) || "";
115
- if (!parentParamName) {
116
- return null;
117
- }
118
-
119
- const routeParams = resolveRouteParamsSource(sourceRoute?.params || {});
120
- const parentParamValue = toRouteParamValue(routeParams[parentParamName]);
121
- if (!parentParamValue) {
122
- return null;
123
- }
124
-
125
- return Object.freeze({
126
- key: parentParamName,
127
- value: parentParamValue
128
- });
129
- });
130
- const activeSearchQuery = computed(() => {
131
- if (searchConfig.enabled !== true) {
132
- return "";
133
- }
134
- const normalized = normalizeText(debouncedSearchQuery.value);
135
- if (!normalized || normalized.length < searchConfig.minLength) {
136
- return "";
137
- }
138
- return normalized;
139
- });
140
- const querySearchEnabled = computed(() => searchConfig.enabled === true && searchConfig.mode === "query");
141
- const listPath = computed(() => {
142
- const basePath = normalizeText(operationScope.apiPath.value);
143
- if (!basePath) {
144
- return "";
145
- }
146
-
147
- const searchParams = new URLSearchParams();
148
- if (querySearchEnabled.value) {
149
- const queryValue = activeSearchQuery.value;
150
- if (queryValue) {
151
- searchParams.set(searchConfig.queryParam, queryValue);
152
- }
153
- }
154
-
155
- const parentFilter = parentRouteFilter.value;
156
- if (parentFilter) {
157
- searchParams.set(parentFilter.key, parentFilter.value);
158
- }
159
-
160
- const serializedSearch = searchParams.toString();
161
- if (!serializedSearch) {
162
- return basePath;
163
- }
164
-
165
- return appendQueryString(basePath, serializedSearch);
166
- });
167
- const listQueryKey = computed(() => {
168
- const sourceQueryKey = operationScope.queryKey.value;
169
- const baseQueryKey = Array.isArray(sourceQueryKey)
170
- ? [...sourceQueryKey]
171
- : sourceQueryKey == null
172
- ? []
173
- : [sourceQueryKey];
174
- const parentFilter = parentRouteFilter.value;
175
- if (parentFilter) {
176
- baseQueryKey.push("__parent__", parentFilter.key, parentFilter.value);
177
- }
178
- if (querySearchEnabled.value) {
179
- baseQueryKey.push("__search__", searchConfig.queryParam, activeSearchQuery.value);
180
- }
181
- return baseQueryKey;
182
- });
183
-
184
- const list = useListCore({
185
- queryKey: listQueryKey,
186
- path: listPath,
187
- enabled: operationScope.queryCanRun(canView),
188
- initialPageParam,
189
- getNextPageParam,
190
- selectItems,
191
- requestOptions,
192
- queryOptions,
193
- fallbackLoadError
194
- });
195
- const filteredItems = computed(() => {
196
- const sourceItems = Array.isArray(list.items.value) ? list.items.value : [];
197
- if (searchConfig.enabled !== true || searchConfig.mode !== "local") {
198
- return sourceItems;
199
- }
200
-
201
- const queryValue = activeSearchQuery.value;
202
- if (!queryValue) {
203
- return sourceItems;
204
- }
205
-
206
- return sourceItems.filter((item) => matchesLocalSearch(item, queryValue, searchConfig.fields));
207
- });
208
-
209
- const isInitialLoading = operationScope.isLoading(list.isInitialLoading);
210
- const isFetching = operationScope.isLoading(list.isFetching);
211
- const isRefetching = computed(() => Boolean(isFetching.value && !isInitialLoading.value));
212
- const loadError = operationScope.loadError(list.loadError);
213
- const isLoading = operationScope.isLoading(list.isLoading);
214
- const listUiRuntime = createListUiRuntime({
215
- items: filteredItems,
216
- isInitialLoading,
217
- recordIdParam,
218
- recordIdSelector,
219
- routeParams: computed(() => operationScope.routeContext.route?.params || {}),
220
- routePath: computed(() => operationScope.routeContext.route?.path || ""),
221
- viewUrlTemplate,
222
- editUrlTemplate
223
- });
224
- setupOperationErrorReporting({
225
- source: `${placementSource}.load`,
226
- loadError,
227
- dedupeWindowMs: 0,
228
- loadActionFactory: () => ({
229
- label: "Retry",
230
- dismissOnRun: true,
231
- handler() {
232
- void list.reload();
233
- }
234
- })
235
- });
236
-
237
- return proxyRefs({
238
- canView,
239
- isInitialLoading,
240
- isFetching,
241
- isRefetching,
242
- isLoading,
243
- isLoadingMore: list.isLoadingMore,
244
- hasMore: list.hasMore,
245
- loadError,
246
- pages: list.pages,
247
- items: filteredItems,
248
- reload: list.reload,
249
- loadMore: list.loadMore,
250
- hasViewUrl: listUiRuntime.hasViewUrl,
251
- hasEditUrl: listUiRuntime.hasEditUrl,
252
- actionColumnCount: listUiRuntime.actionColumnCount,
253
- showListSkeleton: listUiRuntime.showListSkeleton,
254
- resolveRowKey: listUiRuntime.resolveRowKey,
255
- resolveParams: listUiRuntime.resolveParams,
256
- resolveViewUrl: listUiRuntime.resolveViewUrl,
257
- resolveEditUrl: listUiRuntime.resolveEditUrl,
258
- resolveFieldDisplay: resolveLookupFieldDisplayValue,
259
- searchEnabled: searchConfig.enabled,
260
- searchMode: searchConfig.mode,
261
- searchQuery,
262
- searchLabel: searchConfig.label,
263
- searchPlaceholder: searchConfig.placeholder,
264
- isSearchDebouncing
265
- });
266
- }
267
-
268
- export { useList };