@headless-adminapp/app 0.0.17-alpha.4 → 0.0.17-alpha.41

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 (115) hide show
  1. package/app/AppProvider.js +2 -1
  2. package/app/AuthWrapper.d.ts +1 -1
  3. package/app/AuthWrapper.js +4 -1
  4. package/app/LayoutProvider.d.ts +8 -7
  5. package/app/LayoutProvider.js +37 -2
  6. package/auth/AuthProvider.d.ts +1 -1
  7. package/auth/AuthProvider.js +23 -3
  8. package/auth/context.d.ts +1 -0
  9. package/auth/hooks/useIsSkipAuthCheck.d.ts +1 -0
  10. package/auth/hooks/useIsSkipAuthCheck.js +8 -0
  11. package/builders/CommandBuilder/CommandBuilder.d.ts +10 -0
  12. package/builders/CommandBuilder/CommandBuilder.js +14 -0
  13. package/builders/CommandBuilder/DefaultCommandBuilder.d.ts +88 -0
  14. package/builders/CommandBuilder/DefaultCommandBuilder.js +191 -0
  15. package/builders/CommandBuilder/FormCommandBuilder.d.ts +46 -0
  16. package/builders/CommandBuilder/FormCommandBuilder.js +171 -0
  17. package/builders/CommandBuilder/SubgridCommandBuilder.d.ts +45 -0
  18. package/builders/CommandBuilder/SubgridCommandBuilder.js +240 -0
  19. package/builders/CommandBuilder/ViewCommandBuilder.d.ts +63 -0
  20. package/builders/CommandBuilder/ViewCommandBuilder.js +242 -0
  21. package/builders/CommandBuilder/index.d.ts +1 -0
  22. package/builders/CommandBuilder/index.js +5 -0
  23. package/builders/CommandBuilder/utils.d.ts +3 -0
  24. package/builders/CommandBuilder/utils.js +21 -0
  25. package/builders/SchemaExperienceBuilder.d.ts +5 -8
  26. package/builders/SchemaExperienceBuilder.js +4 -4
  27. package/builders/index.d.ts +1 -1
  28. package/builders/index.js +1 -2
  29. package/builders/utils.d.ts +28 -0
  30. package/builders/utils.js +185 -0
  31. package/command/hooks/useBaseCommandHandlerContext.js +22 -4
  32. package/command/hooks/useCommands.d.ts +1 -1
  33. package/command/hooks/useCommands.js +1 -1
  34. package/dataform/DataFormProvider/DataResolver.js +6 -6
  35. package/dataform/DataFormProvider/index.js +3 -3
  36. package/dataform/hooks/useFormSave.js +9 -2
  37. package/dataform/hooks/useLoadFormGridPage.js +8 -2
  38. package/dataform/hooks/useMainFormCommands.d.ts +1 -12
  39. package/dataform/hooks/useMainFormCommands.js +9 -1
  40. package/dataform/utils/index.d.ts +4 -3
  41. package/dataform/utils/index.js +24 -6
  42. package/datagrid/DataGridProvider/DataResolver.js +9 -49
  43. package/datagrid/DataGridProvider/index.d.ts +5 -0
  44. package/datagrid/DataGridProvider/index.js +8 -0
  45. package/datagrid/DataGridProvider/transformViewColumns.js +4 -4
  46. package/datagrid/DataGridProvider/utils.d.ts +7 -2
  47. package/datagrid/DataGridProvider/utils.js +52 -2
  48. package/datagrid/column-filter/constants.js +38 -3
  49. package/datagrid/context.d.ts +9 -6
  50. package/datagrid/hooks/useGridCommands.d.ts +3 -0
  51. package/datagrid/hooks/useGridCommands.js +3 -0
  52. package/datagrid/hooks/useLoadMainGridPage.js +1 -1
  53. package/datagrid/hooks/useMainGridCommands.d.ts +1 -13
  54. package/datagrid/hooks/useMainGridCommands.js +38 -26
  55. package/datagrid/hooks/useOpenRecord.d.ts +1 -0
  56. package/datagrid/hooks/useOpenRecord.js +34 -0
  57. package/datagrid/hooks/useSubGridCommands.js +25 -65
  58. package/defaults.d.ts +2 -0
  59. package/defaults.js +5 -0
  60. package/form/FormValidationStringContext.d.ts +1 -0
  61. package/form/FormValidationStringContext.js +1 -0
  62. package/hooks/useSystemColorScheme.d.ts +1 -1
  63. package/insights/InsightsProvider.d.ts +8 -0
  64. package/insights/InsightsProvider.js +27 -0
  65. package/locale/LocaleProvider.d.ts +2 -1
  66. package/locale/LocaleProvider.js +3 -3
  67. package/locale/index.d.ts +1 -0
  68. package/locale/index.js +1 -0
  69. package/locale/useCurrencySymbol.d.ts +1 -0
  70. package/locale/useCurrencySymbol.js +13 -0
  71. package/locale/utils.d.ts +5 -0
  72. package/locale/utils.js +7 -0
  73. package/metadata/MetadataProvider.d.ts +8 -4
  74. package/metadata/MetadataProvider.js +23 -16
  75. package/metadata/hooks/useExperienceViewCommands.js +7 -1
  76. package/metadata/hooks/useExperienceViewSubgridCommands.js +7 -1
  77. package/metadata/hooks/useMetadata.d.ts +2 -4
  78. package/metadata/hooks/useMetadata.js +2 -6
  79. package/metadata/hooks/useSchema.d.ts +1 -1
  80. package/metadata/hooks/useSchema.js +5 -2
  81. package/mutable/context.js +1 -1
  82. package/navigation/hooks/index.d.ts +1 -0
  83. package/{appearance → navigation}/hooks/index.js +1 -1
  84. package/navigation/hooks/useOpenForm.d.ts +2 -4
  85. package/navigation/hooks/useOpenForm.js +7 -3
  86. package/navigation/index.d.ts +1 -0
  87. package/{appearance → navigation}/index.js +0 -3
  88. package/package.json +12 -3
  89. package/recordset/RecordSetProvider.js +1 -1
  90. package/recordset/hooks/useRecordSetResult.js +1 -1
  91. package/route/RouteProvider.d.ts +2 -2
  92. package/route/RouteProvider.js +4 -1
  93. package/store/ComponentStore.d.ts +1 -1
  94. package/store/ComponentStore.js +5 -9
  95. package/store/SchemaExperienceStore.d.ts +3 -3
  96. package/transport/RestDataService/index.d.ts +1 -1
  97. package/transport/RestDataService/index.js +17 -16
  98. package/transport/context.d.ts +3 -1
  99. package/transport/context.js +16 -1
  100. package/transport/hooks/index.d.ts +1 -0
  101. package/transport/hooks/index.js +1 -0
  102. package/transport/hooks/useFileService.d.ts +1 -0
  103. package/transport/hooks/useFileService.js +12 -0
  104. package/utils/getAttributeFormattedValue.d.ts +2 -0
  105. package/utils/getAttributeFormattedValue.js +31 -12
  106. package/appearance/context.d.ts +0 -7
  107. package/appearance/context.js +0 -5
  108. package/appearance/hooks/index.d.ts +0 -1
  109. package/appearance/hooks/useAppearanceContext.d.ts +0 -1
  110. package/appearance/hooks/useAppearanceContext.js +0 -12
  111. package/appearance/index.d.ts +0 -2
  112. package/builders/CommandBuilder.d.ts +0 -176
  113. package/builders/CommandBuilder.js +0 -474
  114. package/locale/types.d.ts +0 -2
  115. package/locale/types.js +0 -2
@@ -28,10 +28,10 @@ function getControls(form) {
28
28
  return controls;
29
29
  }
30
30
  function getColumns(form) {
31
- var _a;
31
+ var _a, _b;
32
32
  const columns = Array.from(new Set([
33
33
  ...((_a = form.experience.includeAttributes) !== null && _a !== void 0 ? _a : []),
34
- ...form.experience.headerControls,
34
+ ...((_b = form.experience.headerControls) !== null && _b !== void 0 ? _b : []),
35
35
  ...getControls(form)
36
36
  .filter((control) => control.type === 'standard')
37
37
  .map((control) => control.attributeName),
@@ -39,7 +39,7 @@ function getColumns(form) {
39
39
  return columns;
40
40
  }
41
41
  function getRecord(_a) {
42
- return __awaiter(this, arguments, void 0, function* ({ recordId, dataService, form, schema, columns, getSchema, }) {
42
+ return __awaiter(this, arguments, void 0, function* ({ recordId, dataService, form, schema, columns, schemaStore, }) {
43
43
  var _b;
44
44
  let record = null;
45
45
  try {
@@ -60,7 +60,7 @@ function getRecord(_a) {
60
60
  if (control.type !== 'editablegrid') {
61
61
  continue;
62
62
  }
63
- const controlSchema = getSchema(control.logicalName);
63
+ const controlSchema = schemaStore.getSchema(control.logicalName);
64
64
  const records = yield dataService.retriveRecords({
65
65
  logicalName: controlSchema.logicalName,
66
66
  filter: {
@@ -97,7 +97,7 @@ function DataResolver() {
97
97
  const form = (0, hooks_2.useSelectedForm)();
98
98
  const dataService = (0, transport_2.useDataService)();
99
99
  const recordId = (0, hooks_2.useRecordId)();
100
- const { getSchema } = (0, hooks_1.useMetadata)();
100
+ const { schemaStore } = (0, hooks_1.useMetadata)();
101
101
  const setState = (0, mutable_1.useContextSetValue)(context_1.DataFormContext);
102
102
  const columns = (0, react_1.useMemo)(() => getColumns(form), [form]);
103
103
  const queryKey = (0, react_1.useMemo)(() => ['data', 'retriveRecord', schema.logicalName, recordId, columns], [columns, recordId, schema.logicalName]);
@@ -113,7 +113,7 @@ function DataResolver() {
113
113
  form,
114
114
  recordId,
115
115
  schema,
116
- getSchema,
116
+ schemaStore,
117
117
  });
118
118
  return record;
119
119
  }),
@@ -23,7 +23,7 @@ const DataResolver_1 = require("./DataResolver");
23
23
  const InitialValueResolver_1 = require("./InitialValueResolver");
24
24
  const ReadonlyInfoResolver_1 = require("./ReadonlyInfoResolver");
25
25
  function DataFormProvider(props) {
26
- const { getSchema } = (0, useMetadata_1.useMetadata)();
26
+ const { schemaStore } = (0, useMetadata_1.useMetadata)();
27
27
  const { language } = (0, useLocale_1.useLocale)();
28
28
  const formValidationStrings = (0, FormValidationStringContext_1.useFormValidationStrings)();
29
29
  const [formReadOnly, setFormReadOnly] = (0, react_1.useState)(false); // A trick to provide readOnly info to formInstance
@@ -32,7 +32,7 @@ function DataFormProvider(props) {
32
32
  defaultValues: {},
33
33
  resolver: (0, utils_1.formValidator)({
34
34
  form: props.form,
35
- getSchema,
35
+ schemaStore,
36
36
  language,
37
37
  schema: props.schema,
38
38
  strings: formValidationStrings,
@@ -65,7 +65,7 @@ function DataFormProvider(props) {
65
65
  props.schema,
66
66
  props.recordId,
67
67
  contextValue,
68
- getSchema,
68
+ schemaStore,
69
69
  props.commands,
70
70
  ]);
71
71
  return ((0, jsx_runtime_1.jsx)(context_1.DataFormContext.Provider, { value: contextValue, children: (0, jsx_runtime_1.jsxs)(react_hook_form_1.FormProvider, Object.assign({}, formInstance, { children: [(0, jsx_runtime_1.jsx)(DataResolver_1.DataResolver, {}), (0, jsx_runtime_1.jsx)(InitialValueResolver_1.InitialValueResolver, {}), (0, jsx_runtime_1.jsx)(ReadonlyInfoResolver_1.ReadonlyInfoResolver, { setFormReadOnly: setFormReadOnly }), props.children] })) }));
@@ -17,6 +17,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
17
17
  };
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.useFormSave = useFormSave;
20
+ // Wrapper - Loader, response message
21
+ // Core - Extract modified fields, prepare operations, perform operations
22
+ const route_1 = require("@headless-adminapp/app/route");
20
23
  const react_query_1 = require("@tanstack/react-query");
21
24
  const react_1 = require("react");
22
25
  const react_hook_form_1 = require("react-hook-form");
@@ -34,7 +37,7 @@ function useFormSave() {
34
37
  const form = (0, useSelectedForm_1.useSelectedForm)();
35
38
  const formInstance = (0, react_hook_form_1.useFormContext)();
36
39
  const record = (0, useFormRecord_1.useFormRecord)();
37
- const { getSchema } = (0, useMetadata_1.useMetadata)();
40
+ const { schemaStore } = (0, useMetadata_1.useMetadata)();
38
41
  const schema = (0, useFormSchema_1.useDataFormSchema)();
39
42
  const initialValues = (0, context_1.useContextSelector)(context_2.DataFormContext, (state) => state.initialValues);
40
43
  const refresh = (0, context_1.useContextSelector)(context_2.DataFormContext, (state) => state.refresh);
@@ -42,6 +45,7 @@ function useFormSave() {
42
45
  const { showProgressIndicator, hideProgressIndicator } = (0, useProgressIndicator_1.useProgressIndicator)();
43
46
  const openToastNotification = (0, useOpenToastNotification_1.useOpenToastNotification)();
44
47
  const client = (0, react_query_1.useQueryClient)();
48
+ const router = (0, route_1.useRouter)();
45
49
  function showMessageAfterSave({ isCreatedMode }) {
46
50
  // Show notification
47
51
  if (!isCreatedMode) {
@@ -76,7 +80,7 @@ function useFormSave() {
76
80
  initialValues: initialValues,
77
81
  dataService,
78
82
  schema: schema,
79
- getSchema,
83
+ schemaStore,
80
84
  });
81
85
  if (!result.success) {
82
86
  openToastNotification({
@@ -97,6 +101,9 @@ function useFormSave() {
97
101
  yield client.invalidateQueries({
98
102
  queryKey: ['data', 'retriveRecord'],
99
103
  });
104
+ if (mode === 'saveandclose') {
105
+ router.back();
106
+ }
100
107
  }
101
108
  yield client.invalidateQueries({
102
109
  queryKey: ['data', 'retriveRecords'],
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.useLoadFormGridPage = useLoadFormGridPage;
13
+ const app_1 = require("@headless-adminapp/app/app");
13
14
  const react_query_1 = require("@tanstack/react-query");
14
15
  const hooks_1 = require("../../metadata/hooks");
15
16
  function useLoadFormGridPage(logicalName, formId) {
@@ -22,10 +23,15 @@ function useLoadFormGridPage(logicalName, formId) {
22
23
  }),
23
24
  placeholderData: react_query_1.keepPreviousData,
24
25
  });
26
+ const { app: { formCommands }, } = (0, app_1.useAppContext)();
25
27
  const { data: commands } = (0, react_query_1.useQuery)({
26
28
  queryKey: ['experience-schema-form-commands', logicalName],
27
29
  queryFn: () => __awaiter(this, void 0, void 0, function* () {
28
- return experienceStore.getFormCommands(logicalName);
30
+ let commands = yield experienceStore.getFormCommands(logicalName);
31
+ if (!commands) {
32
+ commands = formCommands;
33
+ }
34
+ return commands !== null && commands !== void 0 ? commands : [];
29
35
  }),
30
36
  initialData: [],
31
37
  });
@@ -34,7 +40,7 @@ function useLoadFormGridPage(logicalName, formId) {
34
40
  loading: false,
35
41
  error: true,
36
42
  title: 'Schema not found',
37
- message: 'The schema was not found',
43
+ message: `The schema "${logicalName}" was not found`,
38
44
  };
39
45
  }
40
46
  if (!form) {
@@ -1,16 +1,5 @@
1
1
  import { EntityFormCommandContext } from '@headless-adminapp/core/experience/form';
2
2
  import { CommandItemState } from '../../command';
3
- export declare function useFormControlContext(): {
4
- data: any;
5
- logicalName: string;
6
- schema: import("@headless-adminapp/core/schema").Schema<import("@headless-adminapp/core/schema").SchemaAttributes>;
7
- form: import("@headless-adminapp/core/experience/form").Form<import("@headless-adminapp/core/schema").SchemaAttributes>;
8
- formId: string;
9
- originalData: import("@headless-adminapp/core/transport").Data<import("@headless-adminapp/core/schema").InferredSchemaType<import("@headless-adminapp/core/schema").SchemaAttributes>> | null;
10
- recordId: string | number;
11
- refresh: () => Promise<void>;
12
- save: (mode?: import("@headless-adminapp/core/experience/form").SaveMode) => Promise<void>;
13
- readonly: boolean | undefined;
14
- };
3
+ export declare function useFormControlContext(): EntityFormCommandContext['primaryControl'];
15
4
  export declare function useMainFormCommandHandlerContext(): EntityFormCommandContext;
16
5
  export declare function useMainFormCommands(): CommandItemState[][];
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useFormControlContext = useFormControlContext;
4
4
  exports.useMainFormCommandHandlerContext = useMainFormCommandHandlerContext;
5
5
  exports.useMainFormCommands = useMainFormCommands;
6
+ const route_1 = require("@headless-adminapp/app/route");
7
+ const react_1 = require("react");
6
8
  const command_1 = require("../../command");
7
9
  const context_1 = require("../../mutable/context");
8
10
  const context_2 = require("../context");
@@ -13,6 +15,7 @@ const useFormSave_1 = require("./useFormSave");
13
15
  const useFormSchema_1 = require("./useFormSchema");
14
16
  const useRecordId_1 = require("./useRecordId");
15
17
  function useFormControlContext() {
18
+ var _a;
16
19
  const schema = (0, useFormSchema_1.useDataFormSchema)();
17
20
  const form = (0, context_1.useContextSelector)(context_2.DataFormContext, (state) => state.form);
18
21
  const originalData = (0, useFormRecord_1.useFormRecord)();
@@ -20,8 +23,12 @@ function useFormControlContext() {
20
23
  const save = (0, useFormSave_1.useFormSave)();
21
24
  const refresh = (0, context_1.useContextSelector)(context_2.DataFormContext, (state) => state.refresh);
22
25
  const formInstance = (0, useFormInstance_1.useFormInstance)();
23
- const readonly = (0, useFormIsReadonly_1.useFormIsReadonly)();
26
+ const readonly = (_a = (0, useFormIsReadonly_1.useFormIsReadonly)()) !== null && _a !== void 0 ? _a : false;
24
27
  const data = formInstance.watch();
28
+ const router = (0, route_1.useRouter)();
29
+ const close = (0, react_1.useCallback)(() => {
30
+ router.back();
31
+ }, [router]);
25
32
  return {
26
33
  data,
27
34
  logicalName: schema.logicalName,
@@ -33,6 +40,7 @@ function useFormControlContext() {
33
40
  refresh,
34
41
  save,
35
42
  readonly,
43
+ close,
36
44
  };
37
45
  }
38
46
  function useMainFormCommandHandlerContext() {
@@ -1,6 +1,7 @@
1
1
  import type { Attribute } from '@headless-adminapp/core/attributes';
2
2
  import { Form } from '@headless-adminapp/core/experience/form';
3
3
  import { InferredSchemaType, Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
4
+ import { ISchemaStore } from '@headless-adminapp/core/store';
4
5
  import { IDataService } from '@headless-adminapp/core/transport';
5
6
  import { Nullable } from '@headless-adminapp/core/types';
6
7
  import { MemoizedFunction } from 'lodash';
@@ -17,14 +18,14 @@ type SaveRecordResult = {
17
18
  message: string;
18
19
  isError: boolean;
19
20
  };
20
- export declare function saveRecord({ values, form, schema, dataService, initialValues, record, getSchema, }: {
21
+ export declare function saveRecord({ values, form, schema, dataService, initialValues, record, schemaStore, }: {
21
22
  values: any;
22
23
  form: Form<SchemaAttributes>;
23
24
  record: InferredSchemaType<SchemaAttributes> | undefined;
24
25
  initialValues: Nullable<InferredSchemaType<SchemaAttributes>>;
25
26
  schema: Schema<SchemaAttributes>;
26
27
  dataService: IDataService;
27
- getSchema: (logicalName: string) => Schema<SchemaAttributes>;
28
+ schemaStore: ISchemaStore;
28
29
  }): Promise<SaveRecordResult>;
29
30
  export declare function getInitialValues({ cloneRecord, form, record, recordId, defaultParameters, }: {
30
31
  cloneRecord: InferredSchemaType<SchemaAttributes> | undefined;
@@ -41,7 +42,7 @@ interface FormValidatorOptions<A extends SchemaAttributes = SchemaAttributes> {
41
42
  formReadOnly?: boolean;
42
43
  readonlyAttributes?: string[];
43
44
  strings: FormValidationStringSet;
44
- getSchema: (logicalName: string) => Schema;
45
+ schemaStore: ISchemaStore;
45
46
  }
46
47
  type FormValidator = (<A extends SchemaAttributes = SchemaAttributes>(options: FormValidatorOptions<A>) => (values: Record<string, any>, context: any, options: any) => Promise<ResolverResult<{}>>) & MemoizedFunction;
47
48
  export declare const formValidator: FormValidator;
@@ -39,8 +39,8 @@ exports.getInitialValues = getInitialValues;
39
39
  const yup_1 = require("@hookform/resolvers/yup");
40
40
  const lodash_1 = require("lodash");
41
41
  const yup = __importStar(require("yup"));
42
- const CommandBuilder_1 = require("../../builders/CommandBuilder");
43
42
  const DataResolver_1 = require("../../dataform/DataFormProvider/DataResolver");
43
+ const utils_1 = require("../../locale/utils");
44
44
  function getModifiedValues(initialValues, values, exclude) {
45
45
  const keys = Object.keys(values);
46
46
  return keys.reduce((p, c) => {
@@ -57,7 +57,7 @@ function getModifiedValues(initialValues, values, exclude) {
57
57
  }, {});
58
58
  }
59
59
  function saveRecord(_a) {
60
- return __awaiter(this, arguments, void 0, function* ({ values, form, schema, dataService, initialValues, record, getSchema, }) {
60
+ return __awaiter(this, arguments, void 0, function* ({ values, form, schema, dataService, initialValues, record, schemaStore, }) {
61
61
  const controls = (0, DataResolver_1.getControls)(form);
62
62
  const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
63
63
  const modifiedValues = getModifiedValues(initialValues, values, editableGridControls.map((x) => x.attributeName));
@@ -74,7 +74,7 @@ function saveRecord(_a) {
74
74
  });
75
75
  }
76
76
  for (const control of editableGridControls) {
77
- const gridSchema = getSchema(control.logicalName);
77
+ const gridSchema = schemaStore.getSchema(control.logicalName);
78
78
  const gridRows = values[control.attributeName];
79
79
  const initialGridRows = initialValues[control.attributeName];
80
80
  const newRows = gridRows.filter((x) => !x[gridSchema.idAttribute]);
@@ -212,7 +212,7 @@ function getInitialValues({ cloneRecord, form, record, recordId, defaultParamete
212
212
  return Object.assign(Object.assign({}, acc), { [column]: value });
213
213
  }, {});
214
214
  }
215
- exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, schema, readonlyAttributes, formReadOnly, getSchema, language, strings, }) {
215
+ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, schema, readonlyAttributes, formReadOnly, schemaStore, language, strings, }) {
216
216
  return (values, context, options) => __awaiter(this, void 0, void 0, function* () {
217
217
  let validator = yup.object().shape({});
218
218
  if (!formReadOnly) {
@@ -243,7 +243,7 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
243
243
  if (control.type !== 'editablegrid') {
244
244
  throw new Error('Invalid control type');
245
245
  }
246
- const schema = getSchema(control.logicalName);
246
+ const schema = schemaStore.getSchema(control.logicalName);
247
247
  return {
248
248
  columns: control.attributes,
249
249
  schema: schema,
@@ -312,11 +312,16 @@ exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function gener
312
312
  case 'number':
313
313
  validationSchema = yup.number().nullable();
314
314
  break;
315
+ case 'attachments':
316
+ case 'choices':
317
+ case 'lookups':
318
+ validationSchema = yup.array().nullable();
319
+ break;
315
320
  default:
316
321
  validationSchema = yup.mixed().nullable();
317
322
  break;
318
323
  }
319
- const label = (0, CommandBuilder_1.localizedLabel)(language, attribute);
324
+ const label = (0, utils_1.localizedLabel)(language, attribute);
320
325
  if (attribute.required) {
321
326
  validationSchema = validationSchema.required(`${label}: ${strings.required}`);
322
327
  }
@@ -338,6 +343,19 @@ exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function gener
338
343
  validationSchema = validationSchema.matches(/^(\+\d{1,2}\s?)?\d{10}$/, `${label}: ${strings.invalidPhoneNumber}`);
339
344
  }
340
345
  break;
346
+ case 'attachments':
347
+ if (attribute.required) {
348
+ validationSchema = validationSchema.min(1, `${label}: ${strings.required}`);
349
+ }
350
+ if (attribute.maxSize) {
351
+ validationSchema = validationSchema.test('fileSize', `${label}: ${strings.fileSizeExceeded}`, (value) => {
352
+ if (!value) {
353
+ return true;
354
+ }
355
+ return value.every((file) => (file === null || file === void 0 ? void 0 : file.size) && file.size <= attribute.maxSize);
356
+ });
357
+ }
358
+ break;
341
359
  default:
342
360
  break;
343
361
  }
@@ -21,41 +21,6 @@ const hooks_1 = require("../hooks");
21
21
  const utils_1 = require("./utils");
22
22
  const ROWS_PER_PAGE = 100;
23
23
  const MAX_RECORDS = 10000;
24
- function mergeConditions(schema, filter, extraFilter, columnFilters, getSchema) {
25
- const conditions = [];
26
- if (filter) {
27
- conditions.push(filter);
28
- }
29
- if (extraFilter) {
30
- conditions.push(extraFilter);
31
- }
32
- if (columnFilters) {
33
- const transformedColumnFilters = (0, utils_1.transformColumnFilter)(columnFilters, schema, getSchema);
34
- if (transformedColumnFilters) {
35
- conditions.push({
36
- type: 'and',
37
- conditions: Object.entries(transformedColumnFilters).map(([field, condition]) => {
38
- return {
39
- field,
40
- operator: condition.operator,
41
- value: condition.value,
42
- extendedKey: condition.extendedKey,
43
- };
44
- }),
45
- });
46
- }
47
- }
48
- if (conditions.length === 0) {
49
- return null;
50
- }
51
- if (conditions.length === 1) {
52
- return conditions[0];
53
- }
54
- return {
55
- type: 'and',
56
- conditions,
57
- };
58
- }
59
24
  function DataResolver() {
60
25
  var _a;
61
26
  const schema = (0, hooks_1.useDataGridSchema)();
@@ -67,24 +32,17 @@ function DataResolver() {
67
32
  const [columnFilters] = (0, hooks_1.useGridColumnFilter)();
68
33
  const gridColumns = (0, hooks_1.useGridColumns)();
69
34
  const maxRecords = (_a = (0, hooks_1.useMaxRecords)()) !== null && _a !== void 0 ? _a : MAX_RECORDS;
70
- const { getSchema } = (0, useMetadata_1.useMetadata)();
35
+ const [selectedIds] = (0, hooks_1.useGridSelection)();
36
+ const { schemaStore } = (0, useMetadata_1.useMetadata)();
37
+ const selectedIdsRef = (0, react_1.useRef)(selectedIds);
38
+ selectedIdsRef.current = selectedIds;
71
39
  const setState = (0, context_1.useContextSetValue)(context_2.GridContext);
72
40
  const [search] = (0, useDebouncedValue_1.useDebouncedValue)(searchText, 500);
73
41
  const columns = (0, react_1.useMemo)(() => Array.from(new Set([
74
42
  ...gridColumns.filter((x) => !x.expandedKey).map((x) => x.name),
75
43
  schema.primaryAttribute,
76
44
  ])), [gridColumns, schema.primaryAttribute]);
77
- const expand = (0, react_1.useMemo)(() => gridColumns
78
- .filter((x) => x.expandedKey)
79
- .reduce((acc, x) => {
80
- if (!acc[x.name]) {
81
- acc[x.name] = [];
82
- }
83
- if (!acc[x.name].includes(x.expandedKey)) {
84
- acc[x.name].push(x.expandedKey);
85
- }
86
- return acc;
87
- }, {}), [gridColumns]);
45
+ const expand = (0, react_1.useMemo)(() => (0, utils_1.collectExpandedKeys)(gridColumns), [gridColumns]);
88
46
  const queryKey = (0, react_1.useMemo)(() => [
89
47
  'data',
90
48
  'retriveRecords',
@@ -150,7 +108,7 @@ function DataResolver() {
150
108
  search,
151
109
  columns: columns,
152
110
  expand,
153
- filter: mergeConditions(schema, view.experience.filter, extraFilter, columnFilters, getSchema),
111
+ filter: (0, utils_1.mergeConditions)(schema, view.experience.filter, extraFilter, columnFilters, schemaStore),
154
112
  skip,
155
113
  limit,
156
114
  sort: sorting,
@@ -191,10 +149,12 @@ function DataResolver() {
191
149
  count: (_c = (_b = data === null || data === void 0 ? void 0 : data.pages) === null || _b === void 0 ? void 0 : _b[0].data.count) !== null && _c !== void 0 ? _c : 0,
192
150
  records: (_d = data === null || data === void 0 ? void 0 : data.pages.map((x) => x.data.records).flat()) !== null && _d !== void 0 ? _d : [],
193
151
  };
152
+ const selectedIds = selectedIdsRef.current.filter((x) => finalData.records.some((y) => y[schema.idAttribute] === x));
194
153
  setState({
195
154
  data: finalData,
155
+ selectedIds,
196
156
  });
197
- }, [data, setState]);
157
+ }, [data, setState, schema.idAttribute]);
198
158
  (0, react_1.useEffect)(() => {
199
159
  setState({
200
160
  dataState: {
@@ -12,6 +12,11 @@ export interface DataGridProviderProps<S extends SchemaAttributes = SchemaAttrib
12
12
  commands: CommandItemExperience<CommandContext>[][];
13
13
  onChangeView?: (viewId: string) => void;
14
14
  isSubGrid?: boolean;
15
+ associated?: false | {
16
+ logicalName: string;
17
+ id: string;
18
+ refAttributeName: string;
19
+ };
15
20
  allowViewSelection?: boolean;
16
21
  maxRecords?: number;
17
22
  }
@@ -45,6 +45,7 @@ function DataGridProvider(props) {
45
45
  isSubGrid: (_b = props.isSubGrid) !== null && _b !== void 0 ? _b : false,
46
46
  allowViewSelection: (_c = props.allowViewSelection) !== null && _c !== void 0 ? _c : false,
47
47
  maxRecords: props.maxRecords,
48
+ associated: props.associated,
48
49
  });
49
50
  (0, react_1.useEffect)(() => {
50
51
  var _a;
@@ -74,5 +75,12 @@ function DataGridProvider(props) {
74
75
  commands: props.commands,
75
76
  });
76
77
  }, [props.commands, contextValue]);
78
+ (0, react_1.useEffect)(() => {
79
+ var _a;
80
+ contextValue.setValue({
81
+ isSubGrid: (_a = props.isSubGrid) !== null && _a !== void 0 ? _a : false,
82
+ associated: props.associated,
83
+ });
84
+ }, [props.isSubGrid, props.associated, contextValue]);
77
85
  return ((0, jsx_runtime_1.jsxs)(context_2.GridContext.Provider, { value: contextValue, children: [(0, jsx_runtime_1.jsx)(DataResolver_1.DataResolver, {}), props.children] }));
78
86
  }
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.transformViewColumns = transformViewColumns;
4
- const CommandBuilder_1 = require("../../builders/CommandBuilder");
4
+ const utils_1 = require("../../locale/utils");
5
5
  function transformViewColumns(logicalName, columns, schemaStore, language) {
6
6
  const schema = schemaStore.getSchema(logicalName);
7
7
  return columns
8
- .map((column) => {
8
+ .map(column => {
9
9
  const attribute = schema.attributes[column.name];
10
10
  if (!attribute) {
11
11
  return null;
12
12
  }
13
- const label = (0, CommandBuilder_1.localizedLabel)(language, attribute);
13
+ const label = (0, utils_1.localizedLabel)(language, attribute);
14
14
  if (column.expandedKey) {
15
15
  if (attribute.type !== 'lookup') {
16
16
  return null;
@@ -20,7 +20,7 @@ function transformViewColumns(logicalName, columns, schemaStore, language) {
20
20
  if (!lookupAttribute) {
21
21
  return null;
22
22
  }
23
- const lookupLabel = (0, CommandBuilder_1.localizedLabel)(language, lookupAttribute);
23
+ const lookupLabel = (0, utils_1.localizedLabel)(language, lookupAttribute);
24
24
  return Object.assign(Object.assign({}, column), { id: `${column.name}.${column.expandedKey}`, label: `${lookupLabel} (${label})` });
25
25
  }
26
26
  return Object.assign(Object.assign({}, column), { id: column.name, label: label });
@@ -1,3 +1,8 @@
1
1
  import { ColumnCondition } from '@headless-adminapp/core/experience/view';
2
- import { Schema } from '@headless-adminapp/core/schema';
3
- export declare function transformColumnFilter(filter: Partial<Record<string, ColumnCondition>>, schema: Schema, getSchema: (logicalName: string) => Schema): Record<string, ColumnCondition> | null;
2
+ import { Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
3
+ import { ISchemaStore } from '@headless-adminapp/core/store';
4
+ import { Filter } from '@headless-adminapp/core/transport';
5
+ import { TransformedViewColumn } from '../context';
6
+ export declare function transformColumnFilter<S extends SchemaAttributes = SchemaAttributes>(filter: Partial<Record<string, ColumnCondition>>, schema: Schema<S>, schemaStore: ISchemaStore): Record<string, ColumnCondition> | null;
7
+ export declare function mergeConditions<S extends SchemaAttributes = SchemaAttributes>(schema: Schema<S>, filter: Filter | null | undefined, extraFilter: Filter | null | undefined, columnFilters: Partial<Record<string, ColumnCondition>> | undefined, schemaStore: ISchemaStore): Filter | null;
8
+ export declare function collectExpandedKeys(columns: TransformedViewColumn<SchemaAttributes>[]): Record<string, string[]>;
@@ -4,8 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.transformColumnFilter = transformColumnFilter;
7
+ exports.mergeConditions = mergeConditions;
8
+ exports.collectExpandedKeys = collectExpandedKeys;
7
9
  const dayjs_1 = __importDefault(require("dayjs"));
8
- function transformColumnFilter(filter, schema, getSchema) {
10
+ function transformColumnFilter(filter, schema, schemaStore) {
9
11
  const transformedResult = Object.entries(filter).reduce((acc, [id, value]) => {
10
12
  const [key, extendedKey] = id.split('.');
11
13
  let attribute = schema.attributes[key];
@@ -16,7 +18,7 @@ function transformColumnFilter(filter, schema, getSchema) {
16
18
  if (attribute.type !== 'lookup') {
17
19
  throw new Error(`Invalid column filter key: ${id}. Key ${key} is not a lookup column.`);
18
20
  }
19
- const lookupSchema = getSchema(attribute.entity);
21
+ const lookupSchema = schemaStore.getSchema(attribute.entity);
20
22
  attribute = lookupSchema.attributes[extendedKey];
21
23
  }
22
24
  if (!attribute) {
@@ -72,3 +74,51 @@ function transformColumnFilter(filter, schema, getSchema) {
72
74
  }
73
75
  return transformedResult;
74
76
  }
77
+ function mergeConditions(schema, filter, extraFilter, columnFilters, schemaStore) {
78
+ const filters = [];
79
+ if (filter) {
80
+ filters.push(filter);
81
+ }
82
+ if (extraFilter) {
83
+ filters.push(extraFilter);
84
+ }
85
+ if (columnFilters) {
86
+ const transformedColumnFilters = transformColumnFilter(columnFilters, schema, schemaStore);
87
+ if (transformedColumnFilters) {
88
+ filters.push({
89
+ type: 'and',
90
+ conditions: Object.entries(transformedColumnFilters).map(([field, condition]) => {
91
+ return {
92
+ field,
93
+ operator: condition.operator,
94
+ value: condition.value,
95
+ extendedKey: condition.extendedKey,
96
+ };
97
+ }),
98
+ });
99
+ }
100
+ }
101
+ if (filters.length === 0) {
102
+ return null;
103
+ }
104
+ if (filters.length === 1) {
105
+ return filters[0];
106
+ }
107
+ return {
108
+ type: 'and',
109
+ filters: filters,
110
+ };
111
+ }
112
+ function collectExpandedKeys(columns) {
113
+ return columns
114
+ .filter((x) => x.expandedKey)
115
+ .reduce((acc, x) => {
116
+ if (!acc[x.name]) {
117
+ acc[x.name] = [];
118
+ }
119
+ if (!acc[x.name].includes(x.expandedKey)) {
120
+ acc[x.name].push(x.expandedKey);
121
+ }
122
+ return acc;
123
+ }, {});
124
+ }
@@ -463,8 +463,42 @@ const booleanOperatorOptions = [
463
463
  controls: [],
464
464
  },
465
465
  ];
466
- const idOperatorOptions = [];
467
- const attachmentOperatorOptions = [];
466
+ const idOperatorOptions = [
467
+ {
468
+ value: 'not-null',
469
+ labelKey: 'containsData',
470
+ controls: [],
471
+ },
472
+ {
473
+ value: 'null',
474
+ labelKey: 'doesNotContainData',
475
+ controls: [],
476
+ },
477
+ ];
478
+ const attachmentOperatorOptions = [
479
+ {
480
+ value: 'not-null',
481
+ labelKey: 'containsData',
482
+ controls: [],
483
+ },
484
+ {
485
+ value: 'null',
486
+ labelKey: 'doesNotContainData',
487
+ controls: [],
488
+ },
489
+ ];
490
+ const mixedOperatorOptions = [
491
+ {
492
+ value: 'not-null',
493
+ labelKey: 'containsData',
494
+ controls: [],
495
+ },
496
+ {
497
+ value: 'null',
498
+ labelKey: 'doesNotContainData',
499
+ controls: [],
500
+ },
501
+ ];
468
502
  exports.operatorOptions = {
469
503
  id: idOperatorOptions,
470
504
  boolean: booleanOperatorOptions,
@@ -476,7 +510,8 @@ exports.operatorOptions = {
476
510
  number: numberOperatorOptions,
477
511
  string: stringOperatorOptions,
478
512
  attachment: attachmentOperatorOptions,
479
- mixed: [],
513
+ attachments: [],
514
+ mixed: mixedOperatorOptions,
480
515
  daterange: [],
481
516
  lookups: [],
482
517
  };
@@ -1,20 +1,23 @@
1
1
  import { LocalizedDataLookup } from '@headless-adminapp/core/attributes';
2
2
  import { CommandItemExperience } from '@headless-adminapp/core/experience/command';
3
- import { ColumnCondition, EntityMainGridCommandContext, EntitySubGridCommandContext, SortingState, View, ViewColumn } from '@headless-adminapp/core/experience/view';
3
+ import { ColumnCondition, EntityMainGridCommandContext, EntitySubGridCommandContext, SortingState, View } from '@headless-adminapp/core/experience/view';
4
+ import { type TransformedViewColumn } from '@headless-adminapp/core/experience/view/ViewColumn';
4
5
  import { InferredSchemaType, Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
5
6
  import { Filter, RetriveRecordsResult } from '@headless-adminapp/core/transport';
6
- export interface TransformedViewColumn<S extends SchemaAttributes = SchemaAttributes> extends ViewColumn<S> {
7
- id: string;
8
- label: string;
9
- }
7
+ export { type TransformedViewColumn } from '@headless-adminapp/core/experience/view/ViewColumn';
10
8
  export interface GridContextState<S extends SchemaAttributes = SchemaAttributes, CommandContext extends EntityMainGridCommandContext | EntitySubGridCommandContext = EntityMainGridCommandContext> {
11
9
  schema: Schema<S>;
12
10
  view: View<S>;
13
11
  viewLookup: LocalizedDataLookup[];
14
12
  onChangeView?: (viewId: string) => void;
15
13
  extraFilter?: Filter;
16
- commands: CommandItemExperience<CommandContext>[][];
14
+ commands?: CommandItemExperience<CommandContext>[][];
17
15
  maxRecords?: number;
16
+ associated?: false | {
17
+ logicalName: string;
18
+ id: string;
19
+ refAttributeName: string;
20
+ };
18
21
  columns: TransformedViewColumn<S>[];
19
22
  searchText: string;
20
23
  columnFilters: Partial<Record<keyof S, ColumnCondition>>;