@jskit-ai/users-web 0.1.37 → 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 (71) hide show
  1. package/package.descriptor.mjs +7 -7
  2. package/package.json +16 -12
  3. package/src/client/components/UsersSurfaceAwareMenuLinkItem.vue +14 -25
  4. package/src/client/components/WorkspaceMembersClientElement.vue +3 -3
  5. package/src/client/components/WorkspaceProfileClientElement.vue +1 -1
  6. package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +1 -1
  7. package/src/client/components/WorkspacesClientElement.vue +2 -2
  8. package/src/client/composables/account-settings/accountSettingsAvatarUploadRuntime.js +61 -0
  9. package/src/client/composables/{accountSettingsInvitesRuntime.js → account-settings/accountSettingsInvitesRuntime.js} +1 -1
  10. package/src/client/composables/{accountSettingsRuntimeHelpers.js → account-settings/accountSettingsRuntimeHelpers.js} +1 -1
  11. package/src/client/composables/crud/crudBindingSupport.js +75 -0
  12. package/src/client/composables/{crudLookupFieldLabelSupport.js → crud/crudLookupFieldLabelSupport.js} +1 -1
  13. package/src/client/composables/{crudLookupFieldRuntime.js → crud/crudLookupFieldRuntime.js} +6 -2
  14. package/src/client/composables/{crudSchemaFormHelpers.js → crud/crudSchemaFormHelpers.js} +155 -2
  15. package/src/client/composables/internal/crudListParentTitleSupport.js +168 -0
  16. package/src/client/composables/internal/useOperationScope.js +1 -1
  17. package/src/client/composables/{useAddEdit.js → records/useAddEdit.js} +9 -9
  18. package/src/client/composables/{useCrudSchemaForm.js → records/useCrudAddEdit.js} +32 -15
  19. package/src/client/composables/records/useCrudList.js +83 -0
  20. package/src/client/composables/records/useCrudView.js +35 -0
  21. package/src/client/composables/{useList.js → records/useList.js} +31 -57
  22. package/src/client/composables/{useView.js → records/useView.js} +6 -9
  23. package/src/client/composables/{addEditUiRuntime.js → runtime/addEditUiRuntime.js} +2 -2
  24. package/src/client/composables/{listUiRuntime.js → runtime/listUiRuntime.js} +2 -2
  25. package/src/client/composables/{operationAdapters.js → runtime/operationAdapters.js} +1 -1
  26. package/src/client/composables/{useEndpointResource.js → runtime/useEndpointResource.js} +5 -5
  27. package/src/client/composables/{useListCore.js → runtime/useListCore.js} +4 -4
  28. package/src/client/composables/{useUiFeedback.js → runtime/useUiFeedback.js} +1 -1
  29. package/src/client/composables/{viewUiRuntime.js → runtime/viewUiRuntime.js} +2 -2
  30. package/src/client/composables/useAccess.js +2 -2
  31. package/src/client/composables/useAccountSettingsRuntime.js +6 -6
  32. package/src/client/composables/useBootstrapQuery.js +1 -1
  33. package/src/client/composables/useCommand.js +5 -5
  34. package/src/client/composables/useCrudListParentTitle.js +131 -0
  35. package/src/client/composables/usePagedCollection.js +3 -3
  36. package/src/client/composables/useScopeRuntime.js +1 -1
  37. package/src/client/support/menuLinkTarget.js +93 -0
  38. package/test/addEditUiRuntime.test.js +1 -1
  39. package/test/crudBindingSupport.test.js +110 -0
  40. package/test/crudLookupFieldRuntime.test.js +1 -1
  41. package/test/errorMessageHelpers.test.js +1 -1
  42. package/test/exportsContract.test.js +10 -1
  43. package/test/listQueryParamSupport.test.js +1 -1
  44. package/test/listUiRuntime.test.js +1 -1
  45. package/test/menuLinkTarget.test.js +116 -0
  46. package/test/permissions.test.js +2 -2
  47. package/test/refValueHelpers.test.js +1 -1
  48. package/test/resourceLoadStateHelpers.test.js +1 -1
  49. package/test/routeTemplateHelpers.test.js +1 -1
  50. package/test/scopeHelpers.test.js +1 -1
  51. package/test/{useCrudSchemaForm.test.js → useCrudAddEdit.test.js} +81 -1
  52. package/test/useCrudListParentTitle.test.js +143 -0
  53. package/test/useListSearchSupport.test.js +1 -1
  54. package/test/viewCoreLoading.test.js +1 -1
  55. package/test/viewUiRuntime.test.js +1 -1
  56. package/src/client/composables/accountSettingsAvatarUploadRuntime.js +0 -95
  57. /package/src/client/composables/{accountSettingsRuntimeConstants.js → account-settings/accountSettingsRuntimeConstants.js} +0 -0
  58. /package/src/client/composables/{modelStateHelpers.js → runtime/modelStateHelpers.js} +0 -0
  59. /package/src/client/composables/{operationUiHelpers.js → runtime/operationUiHelpers.js} +0 -0
  60. /package/src/client/composables/{operationValidationHelpers.js → runtime/operationValidationHelpers.js} +0 -0
  61. /package/src/client/composables/{useAddEditCore.js → runtime/useAddEditCore.js} +0 -0
  62. /package/src/client/composables/{useCommandCore.js → runtime/useCommandCore.js} +0 -0
  63. /package/src/client/composables/{useFieldErrorBag.js → runtime/useFieldErrorBag.js} +0 -0
  64. /package/src/client/composables/{useViewCore.js → runtime/useViewCore.js} +0 -0
  65. /package/src/client/composables/{errorMessageHelpers.js → support/errorMessageHelpers.js} +0 -0
  66. /package/src/client/composables/{listQueryParamSupport.js → support/listQueryParamSupport.js} +0 -0
  67. /package/src/client/composables/{listSearchSupport.js → support/listSearchSupport.js} +0 -0
  68. /package/src/client/composables/{refValueHelpers.js → support/refValueHelpers.js} +0 -0
  69. /package/src/client/composables/{resourceLoadStateHelpers.js → support/resourceLoadStateHelpers.js} +0 -0
  70. /package/src/client/composables/{routeTemplateHelpers.js → support/routeTemplateHelpers.js} +0 -0
  71. /package/src/client/composables/{scopeHelpers.js → support/scopeHelpers.js} +0 -0
@@ -0,0 +1,168 @@
1
+ import {
2
+ normalizeCrudLookupContainerKey,
3
+ resolveCrudLookupApiPathFromNamespace,
4
+ resolveCrudLookupFieldKeyFromRouteParam
5
+ } from "@jskit-ai/kernel/shared/support/crudLookup";
6
+ import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
7
+ import { resolveLookupFieldDisplayValue, resolveRecordTitle } from "../crud/crudLookupFieldLabelSupport.js";
8
+ import { resolveRouteParamNamesInOrder, toRouteParamValue } from "../support/routeTemplateHelpers.js";
9
+
10
+ function singularizeLabel(value = "") {
11
+ const normalizedValue = normalizeText(value);
12
+ if (!normalizedValue) {
13
+ return "";
14
+ }
15
+ if (normalizedValue.endsWith("ies")) {
16
+ return `${normalizedValue.slice(0, -3)}y`;
17
+ }
18
+ if (normalizedValue.endsWith("s") && !normalizedValue.endsWith("ss")) {
19
+ return normalizedValue.slice(0, -1);
20
+ }
21
+ return normalizedValue;
22
+ }
23
+
24
+ function toTitleLabel(value = "") {
25
+ const normalizedValue = normalizeText(value)
26
+ .replace(/Id$/u, "")
27
+ .replace(/[_-]+/gu, " ")
28
+ .replace(/([a-z0-9])([A-Z])/gu, "$1 $2")
29
+ .trim();
30
+ if (!normalizedValue) {
31
+ return "";
32
+ }
33
+
34
+ return normalizedValue
35
+ .split(/\s+/u)
36
+ .filter(Boolean)
37
+ .map((entry) => entry.charAt(0).toUpperCase() + entry.slice(1))
38
+ .join(" ");
39
+ }
40
+
41
+ function resolveEntityLabel(routeParamKey = "", relationNamespace = "") {
42
+ const routeLabel = singularizeLabel(toTitleLabel(routeParamKey));
43
+ if (routeLabel) {
44
+ return routeLabel;
45
+ }
46
+
47
+ const namespaceLabel = singularizeLabel(toTitleLabel(relationNamespace));
48
+ if (namespaceLabel) {
49
+ return namespaceLabel;
50
+ }
51
+
52
+ return "Record";
53
+ }
54
+
55
+ function resolveLookupFieldMeta(resource = {}, fieldKey = "") {
56
+ const normalizedFieldKey = normalizeText(fieldKey);
57
+ if (!normalizedFieldKey) {
58
+ return null;
59
+ }
60
+
61
+ const entries = Array.isArray(resource?.fieldMeta) ? resource.fieldMeta : [];
62
+ for (const entry of entries) {
63
+ if (normalizeText(entry?.key) !== normalizedFieldKey) {
64
+ continue;
65
+ }
66
+
67
+ const relation = entry?.relation;
68
+ if (!relation || normalizeText(relation.kind).toLowerCase() !== "lookup") {
69
+ return null;
70
+ }
71
+
72
+ return entry;
73
+ }
74
+
75
+ return null;
76
+ }
77
+
78
+ function resolveCrudListParentDescriptor({ resource = {}, route = null, recordIdParam = "recordId" } = {}) {
79
+ const orderedRouteParamNames = resolveRouteParamNamesInOrder(route);
80
+ if (orderedRouteParamNames.length < 1) {
81
+ return null;
82
+ }
83
+
84
+ const normalizedRecordIdParam = normalizeText(recordIdParam) || "recordId";
85
+ for (const routeParamKey of [...orderedRouteParamNames].reverse()) {
86
+ if (routeParamKey === "workspaceSlug" || routeParamKey === normalizedRecordIdParam) {
87
+ continue;
88
+ }
89
+
90
+ const fieldKey = resolveCrudLookupFieldKeyFromRouteParam(resource, routeParamKey);
91
+ if (!fieldKey) {
92
+ continue;
93
+ }
94
+
95
+ const fieldMeta = resolveLookupFieldMeta(resource, fieldKey);
96
+ if (!fieldMeta) {
97
+ continue;
98
+ }
99
+
100
+ const relation = fieldMeta.relation || {};
101
+ const relationNamespace = normalizeText(relation.namespace);
102
+ const containerKey = normalizeCrudLookupContainerKey(relation.containerKey, {
103
+ defaultValue: resource?.contract?.lookup?.containerKey || "lookups"
104
+ });
105
+
106
+ return Object.freeze({
107
+ fieldKey,
108
+ routeParamKey,
109
+ relationNamespace,
110
+ entityLabel: resolveEntityLabel(routeParamKey, relationNamespace),
111
+ labelKey: normalizeText(relation.labelKey),
112
+ fieldDescriptor: Object.freeze({
113
+ key: fieldKey,
114
+ relation: Object.freeze({
115
+ kind: "lookup",
116
+ valueKey: normalizeText(relation.valueKey) || "id",
117
+ labelKey: normalizeText(relation.labelKey),
118
+ containerKey
119
+ })
120
+ }),
121
+ apiUrlTemplate: relationNamespace
122
+ ? `${resolveCrudLookupApiPathFromNamespace(relationNamespace)}/:${routeParamKey}`
123
+ : ""
124
+ });
125
+ }
126
+
127
+ return null;
128
+ }
129
+
130
+ function resolveCrudListParentTitleFromItems(items = [], descriptor = null) {
131
+ const sourceItems = Array.isArray(items) ? items : [];
132
+ if (!descriptor?.fieldDescriptor) {
133
+ return "";
134
+ }
135
+
136
+ for (const item of sourceItems) {
137
+ const resolvedTitle = normalizeText(resolveLookupFieldDisplayValue(item, descriptor.fieldDescriptor));
138
+ if (resolvedTitle) {
139
+ return resolvedTitle;
140
+ }
141
+ }
142
+
143
+ return "";
144
+ }
145
+
146
+ function resolveCrudListParentRecordTitle(record = {}, descriptor = null) {
147
+ const resolvedTitle = resolveRecordTitle(record, {
148
+ fallbackKey: normalizeText(descriptor?.labelKey),
149
+ defaultValue: ""
150
+ });
151
+ if (resolvedTitle && resolvedTitle !== "-") {
152
+ return resolvedTitle;
153
+ }
154
+
155
+ const entityLabel = normalizeText(descriptor?.entityLabel) || "Record";
156
+ const recordId = toRouteParamValue(record?.id);
157
+ if (recordId) {
158
+ return `${entityLabel} #${recordId}`;
159
+ }
160
+
161
+ return "";
162
+ }
163
+
164
+ export {
165
+ resolveCrudListParentDescriptor,
166
+ resolveCrudListParentRecordTitle,
167
+ resolveCrudListParentTitleFromItems
168
+ };
@@ -7,7 +7,7 @@ import {
7
7
  resolvePermissionAccess,
8
8
  resolveEnabled,
9
9
  resolveQueryKey
10
- } from "../scopeHelpers.js";
10
+ } from "../support/scopeHelpers.js";
11
11
 
12
12
  function normalizePermissionSets(permissionSets = {}) {
13
13
  const source = permissionSets && typeof permissionSets === "object" && !Array.isArray(permissionSets)
@@ -1,20 +1,20 @@
1
1
  import { computed, proxyRefs } from "vue";
2
2
  import { useRoute } from "vue-router";
3
3
  import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
4
- import { useAddEditCore } from "./useAddEditCore.js";
5
- import { useEndpointResource } from "./useEndpointResource.js";
6
- import { resolveOperationAdapter } from "./operationAdapters.js";
7
- import { createAddEditUiRuntime } from "./addEditUiRuntime.js";
8
- import { useUiFeedback } from "./useUiFeedback.js";
9
- import { useFieldErrorBag } from "./useFieldErrorBag.js";
4
+ import { useAddEditCore } from "../runtime/useAddEditCore.js";
5
+ import { useEndpointResource } from "../runtime/useEndpointResource.js";
6
+ import { resolveOperationAdapter } from "../runtime/operationAdapters.js";
7
+ import { createAddEditUiRuntime } from "../runtime/addEditUiRuntime.js";
8
+ import { useUiFeedback } from "../runtime/useUiFeedback.js";
9
+ import { useFieldErrorBag } from "../runtime/useFieldErrorBag.js";
10
10
  import {
11
11
  setupRouteChangeCleanup,
12
12
  setupOperationErrorReporting
13
- } from "./operationUiHelpers.js";
13
+ } from "../runtime/operationUiHelpers.js";
14
14
  import {
15
15
  resolveResourceMessages
16
- } from "./scopeHelpers.js";
17
- import { resolveRouteParamNamesInOrder } from "./routeTemplateHelpers.js";
16
+ } from "../support/scopeHelpers.js";
17
+ import { resolveRouteParamNamesInOrder } from "../support/routeTemplateHelpers.js";
18
18
 
19
19
  function useAddEdit({
20
20
  ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE,
@@ -1,17 +1,20 @@
1
1
  import { computed, proxyRefs, reactive, watch } from "vue";
2
2
  import { useRoute, useRouter } from "vue-router";
3
- import { asPlainObject } from "./scopeHelpers.js";
3
+ import { asPlainObject } from "../support/scopeHelpers.js";
4
4
  import { useAddEdit } from "./useAddEdit.js";
5
+ import {
6
+ resolveCrudBoundValues,
7
+ } from "../crud/crudBindingSupport.js";
5
8
  import {
6
9
  normalizeCrudFormFields,
7
10
  createCrudFormModel,
8
11
  buildCrudFormPayload,
9
12
  applyCrudPayloadToForm,
10
- applyCrudRouteBoundFieldValues,
13
+ resolveCrudRouteBoundFieldValues,
11
14
  resolveCrudFieldErrors,
12
15
  parseCrudResourceOperationInput
13
- } from "./crudSchemaFormHelpers.js";
14
- import { hasResolvedQueryData } from "./resourceLoadStateHelpers.js";
16
+ } from "../crud/crudSchemaFormHelpers.js";
17
+ import { hasResolvedQueryData } from "../support/resourceLoadStateHelpers.js";
15
18
 
16
19
  function normalizeFieldErrorKeys(keys = []) {
17
20
  return Array.isArray(keys)
@@ -36,12 +39,13 @@ function normalizeSaveSuccessOptions(options = {}) {
36
39
  });
37
40
  }
38
41
 
39
- function useCrudSchemaForm({
42
+ function useCrudAddEdit({
40
43
  resource = null,
41
44
  operationName = "",
42
45
  formFields = [],
43
46
  addEditOptions = {},
44
47
  saveSuccess = {},
48
+ fieldBinding = null,
45
49
  createModel = null,
46
50
  buildPayload = null,
47
51
  mapPayloadToModel = null,
@@ -61,18 +65,31 @@ function useCrudSchemaForm({
61
65
  ? asPlainObject(createModel(normalizedFields))
62
66
  : createCrudFormModel(normalizedFields);
63
67
  const form = hasProvidedModel ? providedModel : reactive(defaultModel);
68
+ const boundFieldValues = computed(() => {
69
+ return resolveCrudBoundValues({
70
+ binding: fieldBinding,
71
+ routeValues: resolveCrudRouteBoundFieldValues(normalizedFields, route?.params || {}),
72
+ context: Object.freeze({
73
+ route,
74
+ fields: normalizedFields
75
+ })
76
+ });
77
+ });
64
78
 
65
- function applyRouteBoundValues(target = {}) {
66
- return applyCrudRouteBoundFieldValues(normalizedFields, target, route?.params || {});
79
+ function applyBoundFieldValues(target = {}) {
80
+ Object.assign(target, boundFieldValues.value);
81
+ return target;
67
82
  }
68
83
 
69
- applyRouteBoundValues(form);
70
84
  watch(
71
- () => route?.params,
85
+ boundFieldValues,
72
86
  () => {
73
- applyRouteBoundValues(form);
87
+ applyBoundFieldValues(form);
74
88
  },
75
- { deep: true }
89
+ {
90
+ immediate: true,
91
+ deep: true
92
+ }
76
93
  );
77
94
  const parseInputOverride = typeof parseInput === "function"
78
95
  ? parseInput
@@ -109,7 +126,7 @@ function useCrudSchemaForm({
109
126
  fields: normalizedFields
110
127
  })
111
128
  : buildCrudFormPayload(normalizedFields, model);
112
- applyRouteBoundValues(payload);
129
+ applyBoundFieldValues(payload);
113
130
 
114
131
  return payload;
115
132
  }
@@ -120,12 +137,12 @@ function useCrudSchemaForm({
120
137
  ...context,
121
138
  fields: normalizedFields
122
139
  });
123
- applyRouteBoundValues(model);
140
+ applyBoundFieldValues(model);
124
141
  }
125
142
  : (shouldApplyDefaultMapPayload
126
143
  ? (model = {}, payload = {}) => {
127
144
  applyCrudPayloadToForm(normalizedFields, model, payload);
128
- applyRouteBoundValues(model);
145
+ applyBoundFieldValues(model);
129
146
  }
130
147
  : undefined);
131
148
 
@@ -200,4 +217,4 @@ function useCrudSchemaForm({
200
217
  });
201
218
  }
202
219
 
203
- export { useCrudSchemaForm };
220
+ export { useCrudAddEdit };
@@ -0,0 +1,83 @@
1
+ import { computed, unref } from "vue";
2
+ import { useRoute } from "vue-router";
3
+ import { resolveLookupFieldDisplayValue } from "../crud/crudLookupFieldLabelSupport.js";
4
+ import { resolveCrudBoundValues } from "../crud/crudBindingSupport.js";
5
+ import { resolveCrudListParentDescriptor } from "../internal/crudListParentTitleSupport.js";
6
+ import {
7
+ resolveRouteParamsSource,
8
+ toRouteParamValue
9
+ } from "../support/routeTemplateHelpers.js";
10
+ import { asPlainObject } from "../support/scopeHelpers.js";
11
+ import { useList } from "./useList.js";
12
+
13
+ function resolveRequestQueryParamsInput(requestQueryParams, context = {}) {
14
+ if (typeof requestQueryParams === "function") {
15
+ return asPlainObject(requestQueryParams(context));
16
+ }
17
+
18
+ return asPlainObject(unref(requestQueryParams));
19
+ }
20
+
21
+ function resolveCrudParentRequestQueryParams({ resource = {}, route = null, recordIdParam = "recordId" } = {}) {
22
+ const descriptor = resolveCrudListParentDescriptor({
23
+ resource,
24
+ route,
25
+ recordIdParam
26
+ });
27
+ if (!descriptor?.fieldKey || !descriptor?.routeParamKey) {
28
+ return {};
29
+ }
30
+
31
+ const routeParams = resolveRouteParamsSource(route?.params || {});
32
+ const routeParamValue = toRouteParamValue(routeParams[descriptor.routeParamKey]);
33
+ if (!routeParamValue) {
34
+ return {};
35
+ }
36
+
37
+ return {
38
+ [descriptor.fieldKey]: routeParamValue
39
+ };
40
+ }
41
+
42
+ function useCrudList({
43
+ resource = null,
44
+ requestQueryParams = null,
45
+ parentBinding = null,
46
+ recordIdParam = "recordId",
47
+ route = null,
48
+ ...listOptions
49
+ } = {}) {
50
+ const sourceRoute = route && typeof route === "object" ? route : useRoute();
51
+ const boundParentRequestQueryParams = computed(() => {
52
+ return resolveCrudBoundValues({
53
+ binding: parentBinding,
54
+ routeValues: resolveCrudParentRequestQueryParams({
55
+ resource,
56
+ route: sourceRoute,
57
+ recordIdParam
58
+ }),
59
+ context: Object.freeze({
60
+ route: sourceRoute,
61
+ resource,
62
+ recordIdParam
63
+ })
64
+ });
65
+ });
66
+ const records = useList({
67
+ ...listOptions,
68
+ recordIdParam,
69
+ requestQueryParams(context = {}) {
70
+ const baseRequestQueryParams = resolveRequestQueryParamsInput(requestQueryParams, context);
71
+
72
+ return {
73
+ ...baseRequestQueryParams,
74
+ ...boundParentRequestQueryParams.value
75
+ };
76
+ }
77
+ });
78
+
79
+ records.resolveFieldDisplay = resolveLookupFieldDisplayValue;
80
+ return records;
81
+ }
82
+
83
+ export { useCrudList };
@@ -0,0 +1,35 @@
1
+ import { computed } from "vue";
2
+ import { useRoute } from "vue-router";
3
+ import {
4
+ resolveLookupFieldDisplayValue,
5
+ resolveRecordTitle
6
+ } from "../crud/crudLookupFieldLabelSupport.js";
7
+ import { resolveCrudBoundValues } from "../crud/crudBindingSupport.js";
8
+ import { asPlainObject } from "../support/scopeHelpers.js";
9
+ import { useView } from "./useView.js";
10
+
11
+ function useCrudView({
12
+ paramBinding = null,
13
+ route = null,
14
+ ...viewOptions
15
+ } = {}) {
16
+ const sourceRoute = route && typeof route === "object" ? route : useRoute();
17
+ const boundRouteParams = computed(() => {
18
+ return resolveCrudBoundValues({
19
+ binding: paramBinding,
20
+ routeValues: asPlainObject(sourceRoute?.params || {}),
21
+ context: Object.freeze({
22
+ route: sourceRoute
23
+ })
24
+ });
25
+ });
26
+ const view = useView({
27
+ ...viewOptions,
28
+ routeParams: boundRouteParams
29
+ });
30
+ view.resolveFieldDisplay = resolveLookupFieldDisplayValue;
31
+ view.resolveRecordTitle = resolveRecordTitle;
32
+ return view;
33
+ }
34
+
35
+ export { useCrudView };
@@ -2,17 +2,16 @@ 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 { resolveCrudLookupFieldKeys } from "@jskit-ai/kernel/shared/support/crudLookup";
6
5
  import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
7
- import { useListCore } from "./useListCore.js";
8
- import { resolveOperationAdapter } from "./operationAdapters.js";
9
- import { setupOperationErrorReporting } from "./operationUiHelpers.js";
10
- import { createListUiRuntime } from "./listUiRuntime.js";
11
- import { asPlainObject } from "./scopeHelpers.js";
6
+ import { useListCore } from "../runtime/useListCore.js";
7
+ import { resolveOperationAdapter } from "../runtime/operationAdapters.js";
8
+ import { setupOperationErrorReporting } from "../runtime/operationUiHelpers.js";
9
+ import { createListUiRuntime } from "../runtime/listUiRuntime.js";
10
+ import { asPlainObject } from "../support/scopeHelpers.js";
12
11
  import {
13
12
  normalizeListSearchConfig,
14
13
  matchesLocalSearch
15
- } from "./listSearchSupport.js";
14
+ } from "../support/listSearchSupport.js";
16
15
  import {
17
16
  normalizeListSyncToRouteConfig,
18
17
  resolveQueryParamDescriptors,
@@ -24,13 +23,10 @@ import {
24
23
  buildRouteQueryCompareToken,
25
24
  mergeManagedQueryParamKeyHistory,
26
25
  resolveRouteSyncManagedKeys
27
- } from "./listQueryParamSupport.js";
28
- import { resolveLookupFieldDisplayValue } from "./crudLookupFieldLabelSupport.js";
26
+ } from "../support/listQueryParamSupport.js";
29
27
  import {
30
28
  resolveRouteParamNamesInOrder,
31
- resolveRouteParamsSource,
32
- toRouteParamValue
33
- } from "./routeTemplateHelpers.js";
29
+ } from "../support/routeTemplateHelpers.js";
34
30
 
35
31
  const EMPTY_ROUTE_SYNC_QUERY_PARAM_BLACKLIST = Object.freeze([]);
36
32
 
@@ -51,13 +47,13 @@ function useList({
51
47
  queryOptions,
52
48
  realtime = null,
53
49
  adapter = null,
54
- resource = null,
55
50
  recordIdParam = "recordId",
56
51
  recordIdSelector = null,
57
52
  viewUrlTemplate = "",
58
53
  editUrlTemplate = "",
59
54
  search = null,
60
55
  queryParams = null,
56
+ requestQueryParams = null,
61
57
  syncToRoute = false
62
58
  } = {}) {
63
59
  const searchConfig = normalizeListSearchConfig(search);
@@ -142,52 +138,25 @@ function useList({
142
138
  const queryParamDescriptors = computed(() => {
143
139
  return resolveQueryParamDescriptors(queryParams, queryParamsContext.value);
144
140
  });
141
+ const requestQueryParamDescriptors = computed(() => {
142
+ return resolveQueryParamDescriptors(requestQueryParams, queryParamsContext.value);
143
+ });
145
144
  const declaredQueryParamKeys = computed(() => {
146
145
  return queryParamDescriptors.value.map((descriptor) => descriptor.key);
147
146
  });
148
147
  const activeQueryParamEntries = computed(() => {
149
148
  return resolveActiveQueryParamEntries(queryParamDescriptors.value);
150
149
  });
150
+ const activeRequestQueryParamEntries = computed(() => {
151
+ return resolveActiveQueryParamEntries(requestQueryParamDescriptors.value);
152
+ });
151
153
  const activeQueryParamsToken = computed(() => buildQueryParamEntriesToken(activeQueryParamEntries.value));
154
+ const activeRequestQueryParamsToken = computed(() => {
155
+ return buildQueryParamEntriesToken(activeRequestQueryParamEntries.value);
156
+ });
152
157
  const writableQueryParamBindings = computed(() => {
153
158
  return resolveWritableQueryParamBindings(queryParamDescriptors.value);
154
159
  });
155
- const parentRouteFilter = computed(() => {
156
- const lookupFieldKeys = resolveCrudLookupFieldKeys(resource);
157
- if (lookupFieldKeys.length < 1) {
158
- return null;
159
- }
160
-
161
- const lookupFieldKeySet = new Set(lookupFieldKeys);
162
- const sourceRoute = operationScope.routeContext.route;
163
- const orderedRouteParamNames = resolveRouteParamNamesInOrder(sourceRoute);
164
- if (orderedRouteParamNames.length < 1) {
165
- return null;
166
- }
167
-
168
- const normalizedRecordIdParam = normalizeText(recordIdParam) || "recordId";
169
- const parentParamName = [...orderedRouteParamNames]
170
- .reverse()
171
- .find((name) => (
172
- name !== "workspaceSlug" &&
173
- name !== normalizedRecordIdParam &&
174
- lookupFieldKeySet.has(name)
175
- )) || "";
176
- if (!parentParamName) {
177
- return null;
178
- }
179
-
180
- const routeParams = resolveRouteParamsSource(sourceRoute?.params || {});
181
- const parentParamValue = toRouteParamValue(routeParams[parentParamName]);
182
- if (!parentParamValue) {
183
- return null;
184
- }
185
-
186
- return Object.freeze({
187
- key: parentParamName,
188
- value: parentParamValue
189
- });
190
- });
191
160
  const activeSearchQuery = computed(() => {
192
161
  if (searchConfig.enabled !== true) {
193
162
  return "";
@@ -213,11 +182,11 @@ function useList({
213
182
  }
214
183
  }
215
184
 
216
- const parentFilter = parentRouteFilter.value;
217
- if (parentFilter) {
218
- searchParams.set(parentFilter.key, parentFilter.value);
185
+ for (const entry of activeRequestQueryParamEntries.value) {
186
+ for (const value of entry.values) {
187
+ searchParams.append(entry.key, value);
188
+ }
219
189
  }
220
-
221
190
  for (const entry of activeQueryParamEntries.value) {
222
191
  for (const value of entry.values) {
223
192
  searchParams.append(entry.key, value);
@@ -238,9 +207,8 @@ function useList({
238
207
  : sourceQueryKey == null
239
208
  ? []
240
209
  : [sourceQueryKey];
241
- const parentFilter = parentRouteFilter.value;
242
- if (parentFilter) {
243
- baseQueryKey.push("__parent__", parentFilter.key, parentFilter.value);
210
+ if (activeRequestQueryParamsToken.value) {
211
+ baseQueryKey.push("__request_query__", activeRequestQueryParamsToken.value);
244
212
  }
245
213
  if (querySearchEnabled.value) {
246
214
  baseQueryKey.push("__search__", searchConfig.queryParam, activeSearchQuery.value);
@@ -430,6 +398,13 @@ function useList({
430
398
 
431
399
  list.trimToFirstPage();
432
400
  });
401
+ watch(activeRequestQueryParamsToken, (nextValue, previousValue) => {
402
+ if (nextValue === previousValue) {
403
+ return;
404
+ }
405
+
406
+ list.trimToFirstPage();
407
+ });
433
408
  const filteredItems = computed(() => {
434
409
  const sourceItems = Array.isArray(list.items.value) ? list.items.value : [];
435
410
  if (searchConfig.enabled !== true || searchConfig.mode !== "local") {
@@ -494,7 +469,6 @@ function useList({
494
469
  resolveParams: listUiRuntime.resolveParams,
495
470
  resolveViewUrl: listUiRuntime.resolveViewUrl,
496
471
  resolveEditUrl: listUiRuntime.resolveEditUrl,
497
- resolveFieldDisplay: resolveLookupFieldDisplayValue,
498
472
  searchEnabled: searchConfig.enabled,
499
473
  searchMode: searchConfig.mode,
500
474
  searchQuery,
@@ -1,13 +1,12 @@
1
1
  import { computed, proxyRefs } from "vue";
2
2
  import { useRoute } from "vue-router";
3
3
  import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
4
- import { useViewCore } from "./useViewCore.js";
5
- import { useEndpointResource } from "./useEndpointResource.js";
6
- import { resolveOperationAdapter } from "./operationAdapters.js";
7
- import { setupOperationErrorReporting } from "./operationUiHelpers.js";
8
- import { createViewUiRuntime } from "./viewUiRuntime.js";
9
- import { resolveLookupFieldDisplayValue, resolveRecordTitle } from "./crudLookupFieldLabelSupport.js";
10
- import { resolveRouteParamNamesInOrder } from "./routeTemplateHelpers.js";
4
+ import { useViewCore } from "../runtime/useViewCore.js";
5
+ import { useEndpointResource } from "../runtime/useEndpointResource.js";
6
+ import { resolveOperationAdapter } from "../runtime/operationAdapters.js";
7
+ import { setupOperationErrorReporting } from "../runtime/operationUiHelpers.js";
8
+ import { createViewUiRuntime } from "../runtime/viewUiRuntime.js";
9
+ import { resolveRouteParamNamesInOrder } from "../support/routeTemplateHelpers.js";
11
10
 
12
11
  function useView({
13
12
  ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE,
@@ -115,8 +114,6 @@ function useView({
115
114
  listUrl: viewUiRuntime.listUrl,
116
115
  editUrl: viewUiRuntime.editUrl,
117
116
  resolveParams: viewUiRuntime.resolveParams,
118
- resolveFieldDisplay: resolveLookupFieldDisplayValue,
119
- resolveRecordTitle,
120
117
  canView,
121
118
  isLoading,
122
119
  isFetching,
@@ -1,12 +1,12 @@
1
1
  import { computed, unref } from "vue";
2
- import { asPlainObject } from "./scopeHelpers.js";
2
+ import { asPlainObject } from "../support/scopeHelpers.js";
3
3
  import {
4
4
  normalizeRouteParamName,
5
5
  resolveRouteParamsSource,
6
6
  resolveScopedRoutePathname,
7
7
  resolveRouteTemplateLocation,
8
8
  toRouteParamValue
9
- } from "./routeTemplateHelpers.js";
9
+ } from "../support/routeTemplateHelpers.js";
10
10
 
11
11
  function toResolvedRecordId({ routeParams, recordIdParam, routeRecordId }) {
12
12
  const explicitRecordId = toRouteParamValue(
@@ -1,12 +1,12 @@
1
1
  import { computed } from "vue";
2
- import { asPlainObject } from "./scopeHelpers.js";
2
+ import { asPlainObject } from "../support/scopeHelpers.js";
3
3
  import {
4
4
  normalizeRouteParamName,
5
5
  toRouteParamValue,
6
6
  resolveRouteParamsSource,
7
7
  resolveScopedRoutePathname,
8
8
  resolveRouteTemplateLocation
9
- } from "./routeTemplateHelpers.js";
9
+ } from "../support/routeTemplateHelpers.js";
10
10
 
11
11
  function resolveRecordId(record, recordIdSelector) {
12
12
  const item = asPlainObject(record);
@@ -1,4 +1,4 @@
1
- import { useOperationScope } from "./internal/useOperationScope.js";
1
+ import { useOperationScope } from "../internal/useOperationScope.js";
2
2
 
3
3
  const USERS_OPERATION_ADAPTER_ID = "users-default";
4
4