@headless-adminapp/app 0.0.17-alpha.5 → 0.0.17-alpha.50

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 (161) 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/board/BoardColumnDataResolver.d.ts +1 -0
  12. package/board/BoardColumnDataResolver.js +64 -0
  13. package/board/BoardColumnProvider.d.ts +7 -0
  14. package/board/BoardColumnProvider.js +36 -0
  15. package/board/context.d.ts +19 -0
  16. package/board/context.js +6 -0
  17. package/board/hooks/index.d.ts +6 -0
  18. package/board/hooks/index.js +15 -0
  19. package/board/hooks/useBoardColumnConfig.d.ts +2 -0
  20. package/board/hooks/useBoardColumnConfig.js +8 -0
  21. package/board/hooks/useBoardColumnData.d.ts +1 -0
  22. package/board/hooks/useBoardColumnData.js +9 -0
  23. package/board/hooks/useBoardColumnDataState.d.ts +5 -0
  24. package/board/hooks/useBoardColumnDataState.js +9 -0
  25. package/board/hooks/useBoardConfig.d.ts +3 -0
  26. package/board/hooks/useBoardConfig.js +8 -0
  27. package/board/hooks/useBoardSchema.d.ts +2 -0
  28. package/board/hooks/useBoardSchema.js +7 -0
  29. package/board/hooks/useSearchText.d.ts +1 -0
  30. package/board/hooks/useSearchText.js +14 -0
  31. package/board/types.d.ts +47 -0
  32. package/board/utils.d.ts +3 -0
  33. package/board/utils.js +6 -0
  34. package/builders/CommandBuilder/CommandBuilder.d.ts +10 -0
  35. package/builders/CommandBuilder/CommandBuilder.js +14 -0
  36. package/builders/CommandBuilder/DefaultCommandBuilder.d.ts +88 -0
  37. package/builders/CommandBuilder/DefaultCommandBuilder.js +191 -0
  38. package/builders/CommandBuilder/FormCommandBuilder.d.ts +46 -0
  39. package/builders/CommandBuilder/FormCommandBuilder.js +171 -0
  40. package/builders/CommandBuilder/SubgridCommandBuilder.d.ts +45 -0
  41. package/builders/CommandBuilder/SubgridCommandBuilder.js +240 -0
  42. package/builders/CommandBuilder/ViewCommandBuilder.d.ts +63 -0
  43. package/builders/CommandBuilder/ViewCommandBuilder.js +242 -0
  44. package/builders/CommandBuilder/index.d.ts +1 -0
  45. package/builders/CommandBuilder/index.js +5 -0
  46. package/builders/CommandBuilder/utils.d.ts +3 -0
  47. package/builders/CommandBuilder/utils.js +21 -0
  48. package/builders/SchemaExperienceBuilder.d.ts +5 -8
  49. package/builders/SchemaExperienceBuilder.js +4 -4
  50. package/builders/index.d.ts +1 -1
  51. package/builders/index.js +1 -2
  52. package/builders/utils.d.ts +28 -0
  53. package/builders/utils.js +185 -0
  54. package/command/hooks/useBaseCommandHandlerContext.js +22 -4
  55. package/command/hooks/useCommands.d.ts +1 -1
  56. package/command/hooks/useCommands.js +1 -1
  57. package/components/ScrollbarWithMoreDataRequest/index.d.ts +9 -0
  58. package/components/ScrollbarWithMoreDataRequest/index.js +33 -0
  59. package/dataform/DataFormProvider/DataResolver.js +6 -6
  60. package/dataform/DataFormProvider/InitialValueResolver.js +4 -2
  61. package/dataform/DataFormProvider/index.js +3 -3
  62. package/dataform/hooks/index.d.ts +1 -0
  63. package/dataform/hooks/index.js +1 -0
  64. package/dataform/hooks/useFormSave.js +9 -2
  65. package/dataform/hooks/useLoadFormGridPage.js +8 -2
  66. package/dataform/hooks/useMainFormCommands.d.ts +1 -12
  67. package/dataform/hooks/useMainFormCommands.js +9 -1
  68. package/dataform/hooks/useProcessFlowSteps.d.ts +1 -0
  69. package/dataform/hooks/useProcessFlowSteps.js +44 -0
  70. package/dataform/hooks/useRecordTitle.d.ts +1 -1
  71. package/dataform/hooks/useRecordTitle.js +9 -2
  72. package/dataform/utils/defaultParameters.d.ts +3 -0
  73. package/dataform/utils/defaultParameters.js +37 -0
  74. package/dataform/utils/index.d.ts +3 -22
  75. package/dataform/utils/index.js +88 -134
  76. package/dataform/utils/saveRecord.d.ts +25 -0
  77. package/dataform/utils/saveRecord.js +167 -0
  78. package/datagrid/DataGridProvider/DataResolver.js +25 -149
  79. package/datagrid/DataGridProvider/index.d.ts +5 -0
  80. package/datagrid/DataGridProvider/index.js +8 -0
  81. package/datagrid/DataGridProvider/transformViewColumns.js +4 -4
  82. package/datagrid/DataGridProvider/utils.d.ts +7 -2
  83. package/datagrid/DataGridProvider/utils.js +52 -2
  84. package/datagrid/column-filter/constants.js +38 -3
  85. package/datagrid/context.d.ts +9 -6
  86. package/datagrid/hooks/useGridCommands.d.ts +3 -0
  87. package/datagrid/hooks/useGridCommands.js +3 -0
  88. package/datagrid/hooks/useLoadMainGridPage.js +1 -1
  89. package/datagrid/hooks/useMainGridCommands.d.ts +1 -13
  90. package/datagrid/hooks/useMainGridCommands.js +38 -26
  91. package/datagrid/hooks/useOpenRecord.d.ts +1 -0
  92. package/datagrid/hooks/useOpenRecord.js +34 -0
  93. package/datagrid/hooks/useSubGridCommands.js +25 -65
  94. package/defaults.d.ts +2 -0
  95. package/defaults.js +5 -0
  96. package/dialog/hooks/useCloseDialog.js +17 -15
  97. package/form/FormValidationStringContext.d.ts +1 -0
  98. package/form/FormValidationStringContext.js +1 -0
  99. package/hooks/useDebouncedValue.js +0 -1
  100. package/hooks/useElementLayout.js +1 -1
  101. package/hooks/useIsMobile.js +0 -1
  102. package/hooks/useSystemColorScheme.d.ts +1 -1
  103. package/hooks/useSystemColorScheme.js +0 -1
  104. package/insights/InsightsProvider.d.ts +8 -0
  105. package/insights/InsightsProvider.js +27 -0
  106. package/locale/LocaleProvider.d.ts +2 -1
  107. package/locale/LocaleProvider.js +3 -3
  108. package/locale/index.d.ts +1 -0
  109. package/locale/index.js +1 -0
  110. package/locale/useCurrencySymbol.d.ts +1 -0
  111. package/locale/useCurrencySymbol.js +13 -0
  112. package/locale/utils.d.ts +5 -0
  113. package/locale/utils.js +7 -0
  114. package/metadata/MetadataProvider.d.ts +8 -4
  115. package/metadata/MetadataProvider.js +23 -16
  116. package/metadata/hooks/useExperienceViewCommands.js +7 -1
  117. package/metadata/hooks/useExperienceViewSubgridCommands.js +7 -1
  118. package/metadata/hooks/useMetadata.d.ts +2 -4
  119. package/metadata/hooks/useMetadata.js +2 -6
  120. package/metadata/hooks/useSchema.d.ts +1 -1
  121. package/metadata/hooks/useSchema.js +5 -2
  122. package/mutable/context.js +1 -1
  123. package/navigation/hooks/index.d.ts +1 -0
  124. package/{appearance → navigation}/hooks/index.js +1 -1
  125. package/navigation/hooks/useOpenForm.d.ts +2 -4
  126. package/navigation/hooks/useOpenForm.js +11 -3
  127. package/navigation/index.d.ts +1 -0
  128. package/{appearance → navigation}/index.js +0 -3
  129. package/package.json +5 -2
  130. package/recordset/RecordSetProvider.js +1 -1
  131. package/recordset/hooks/useRecordSetResult.js +1 -1
  132. package/route/RouteProvider.d.ts +2 -2
  133. package/route/RouteProvider.js +4 -1
  134. package/store/ComponentStore.d.ts +1 -1
  135. package/store/ComponentStore.js +5 -9
  136. package/store/SchemaExperienceStore.d.ts +3 -3
  137. package/toast-notification/hooks/useCloseToastNotification.js +17 -15
  138. package/transport/RestDataService/index.d.ts +1 -1
  139. package/transport/RestDataService/index.js +17 -16
  140. package/transport/context.d.ts +3 -1
  141. package/transport/context.js +16 -1
  142. package/transport/hooks/index.d.ts +1 -0
  143. package/transport/hooks/index.js +1 -0
  144. package/transport/hooks/useFileService.d.ts +1 -0
  145. package/transport/hooks/useFileService.js +12 -0
  146. package/transport/hooks/useRetriveRecords.d.ts +32 -0
  147. package/transport/hooks/useRetriveRecords.js +120 -0
  148. package/utils/color.d.ts +1 -0
  149. package/utils/color.js +14 -0
  150. package/utils/getAttributeFormattedValue.d.ts +3 -1
  151. package/utils/getAttributeFormattedValue.js +108 -54
  152. package/appearance/context.d.ts +0 -7
  153. package/appearance/context.js +0 -5
  154. package/appearance/hooks/index.d.ts +0 -1
  155. package/appearance/hooks/useAppearanceContext.d.ts +0 -1
  156. package/appearance/hooks/useAppearanceContext.js +0 -12
  157. package/appearance/index.d.ts +0 -2
  158. package/builders/CommandBuilder.d.ts +0 -176
  159. package/builders/CommandBuilder.js +0 -474
  160. package/locale/types.d.ts +0 -2
  161. /package/{locale → board}/types.js +0 -0
@@ -0,0 +1,3 @@
1
+ import { Schema } from '@headless-adminapp/core/schema';
2
+ export declare function getFormDefaultParameters(schema: Schema): Record<string, any>;
3
+ export declare function setFormDefaultParameters(logicalName: string, values: Record<string, any>): void;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFormDefaultParameters = getFormDefaultParameters;
4
+ exports.setFormDefaultParameters = setFormDefaultParameters;
5
+ let formDefaultParameters = null;
6
+ function getFormDefaultParameters(schema) {
7
+ const _values = formDefaultParameters === null || formDefaultParameters === void 0 ? void 0 : formDefaultParameters.values;
8
+ const _logicalName = formDefaultParameters === null || formDefaultParameters === void 0 ? void 0 : formDefaultParameters.logicalName;
9
+ const schemaDefaultValues = Object.keys(schema.attributes).reduce((acc, key) => {
10
+ const attribute = schema.attributes[key];
11
+ let defaultValue = attribute.default;
12
+ if (typeof defaultValue === 'function') {
13
+ defaultValue = defaultValue();
14
+ }
15
+ if (defaultValue instanceof Date) {
16
+ defaultValue = defaultValue.toISOString();
17
+ }
18
+ return Object.assign(Object.assign({}, acc), { [key]: defaultValue });
19
+ }, {});
20
+ if (_logicalName === schema.logicalName) {
21
+ return Object.assign(Object.assign({}, schemaDefaultValues), _values);
22
+ }
23
+ return schemaDefaultValues;
24
+ }
25
+ let defaultParamsTimeout = null;
26
+ function setFormDefaultParameters(logicalName, values) {
27
+ formDefaultParameters = {
28
+ logicalName,
29
+ values,
30
+ };
31
+ if (defaultParamsTimeout) {
32
+ clearTimeout(defaultParamsTimeout);
33
+ }
34
+ defaultParamsTimeout = setTimeout(() => {
35
+ formDefaultParameters = null;
36
+ }, 5000);
37
+ }
@@ -1,31 +1,13 @@
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 { IDataService } from '@headless-adminapp/core/transport';
4
+ import { ISchemaStore } from '@headless-adminapp/core/store';
5
5
  import { Nullable } from '@headless-adminapp/core/types';
6
6
  import { MemoizedFunction } from 'lodash';
7
7
  import { ResolverResult } from 'react-hook-form';
8
8
  import * as yup from 'yup';
9
9
  import { FormValidationStringSet } from '../../form/FormValidationStringContext';
10
- export declare function getModifiedValues(initialValues: any, values: any, exclude?: string[]): Record<string, any>;
11
- type SaveRecordResult = {
12
- success: true;
13
- recordId: string;
14
- } | {
15
- success: false;
16
- title?: string;
17
- message: string;
18
- isError: boolean;
19
- };
20
- export declare function saveRecord({ values, form, schema, dataService, initialValues, record, getSchema, }: {
21
- values: any;
22
- form: Form<SchemaAttributes>;
23
- record: InferredSchemaType<SchemaAttributes> | undefined;
24
- initialValues: Nullable<InferredSchemaType<SchemaAttributes>>;
25
- schema: Schema<SchemaAttributes>;
26
- dataService: IDataService;
27
- getSchema: (logicalName: string) => Schema<SchemaAttributes>;
28
- }): Promise<SaveRecordResult>;
10
+ export { saveRecord } from './saveRecord';
29
11
  export declare function getInitialValues({ cloneRecord, form, record, recordId, defaultParameters, }: {
30
12
  cloneRecord: InferredSchemaType<SchemaAttributes> | undefined;
31
13
  form: Form<SchemaAttributes>;
@@ -41,7 +23,7 @@ interface FormValidatorOptions<A extends SchemaAttributes = SchemaAttributes> {
41
23
  formReadOnly?: boolean;
42
24
  readonlyAttributes?: string[];
43
25
  strings: FormValidationStringSet;
44
- getSchema: (logicalName: string) => Schema;
26
+ schemaStore: ISchemaStore;
45
27
  }
46
28
  type FormValidator = (<A extends SchemaAttributes = SchemaAttributes>(options: FormValidatorOptions<A>) => (values: Record<string, any>, context: any, options: any) => Promise<ResolverResult<{}>>) & MemoizedFunction;
47
29
  export declare const formValidator: FormValidator;
@@ -63,4 +45,3 @@ export declare const generateValidationSchema: (<A extends SchemaAttributes = Sc
63
45
  [x: string]: any;
64
46
  }, "">) & MemoizedFunction;
65
47
  export declare const generateAttributeValidationSchema: ((attribute: Attribute, language: string, strings: FormValidationStringSet) => yup.Schema<any, any, any, "">) & MemoizedFunction;
66
- export {};
@@ -32,126 +32,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
32
32
  });
33
33
  };
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.generateAttributeValidationSchema = exports.generateValidationSchema = exports.formValidator = void 0;
36
- exports.getModifiedValues = getModifiedValues;
37
- exports.saveRecord = saveRecord;
35
+ exports.generateAttributeValidationSchema = exports.generateValidationSchema = exports.formValidator = exports.saveRecord = void 0;
38
36
  exports.getInitialValues = getInitialValues;
39
37
  const yup_1 = require("@hookform/resolvers/yup");
40
38
  const lodash_1 = require("lodash");
41
39
  const yup = __importStar(require("yup"));
42
- const CommandBuilder_1 = require("../../builders/CommandBuilder");
43
40
  const DataResolver_1 = require("../../dataform/DataFormProvider/DataResolver");
44
- function getModifiedValues(initialValues, values, exclude) {
45
- const keys = Object.keys(values);
46
- return keys.reduce((p, c) => {
47
- if (c === '_id') {
48
- return p;
49
- }
50
- if (exclude && exclude.includes(c)) {
51
- return p;
52
- }
53
- if (JSON.stringify(values[c]) !== JSON.stringify(initialValues[c])) {
54
- p[c] = values[c];
55
- }
56
- return p;
57
- }, {});
58
- }
59
- function saveRecord(_a) {
60
- return __awaiter(this, arguments, void 0, function* ({ values, form, schema, dataService, initialValues, record, getSchema, }) {
61
- const controls = (0, DataResolver_1.getControls)(form);
62
- const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
63
- const modifiedValues = getModifiedValues(initialValues, values, editableGridControls.map((x) => x.attributeName));
64
- let recordId;
65
- if (record) {
66
- recordId = record[schema.idAttribute];
67
- const operations = [];
68
- if (Object.keys(modifiedValues).length) {
69
- operations.push({
70
- type: 'update',
71
- logicalName: schema.logicalName,
72
- data: modifiedValues,
73
- id: recordId,
74
- });
75
- }
76
- for (const control of editableGridControls) {
77
- const gridSchema = getSchema(control.logicalName);
78
- const gridRows = values[control.attributeName];
79
- const initialGridRows = initialValues[control.attributeName];
80
- const newRows = gridRows.filter((x) => !x[gridSchema.idAttribute]);
81
- const updatedRows = gridRows.filter((x) => x[gridSchema.idAttribute]);
82
- const deletedIds = initialGridRows === null || initialGridRows === void 0 ? void 0 : initialGridRows.map((x) => x[gridSchema.idAttribute]).filter((id) => !gridRows.find((x) => x[gridSchema.idAttribute] === id));
83
- for (const row of newRows) {
84
- operations.push({
85
- type: 'create',
86
- logicalName: control.logicalName,
87
- data: Object.assign(Object.assign({}, row), { [control.referenceAttribute]: {
88
- id: recordId,
89
- } }),
90
- });
91
- }
92
- for (const row of updatedRows) {
93
- const initialRow = initialGridRows.find((x) => x[gridSchema.idAttribute] === row[gridSchema.idAttribute]);
94
- if (!initialRow) {
95
- throw new Error('Initial row not found');
96
- }
97
- const modifiedRow = getModifiedValues(initialRow, row);
98
- if (!Object.keys(modifiedRow).length) {
99
- continue;
100
- }
101
- operations.push({
102
- type: 'update',
103
- logicalName: control.logicalName,
104
- data: modifiedRow,
105
- id: row[gridSchema.idAttribute],
106
- });
107
- }
108
- for (const id of deletedIds) {
109
- operations.push({
110
- type: 'delete',
111
- logicalName: control.logicalName,
112
- id,
113
- });
114
- }
115
- }
116
- if (!operations.length) {
117
- return {
118
- success: false,
119
- title: 'No changes',
120
- message: 'No changes made to the record',
121
- isError: false,
122
- };
123
- }
124
- for (const operation of operations) {
125
- switch (operation.type) {
126
- case 'create':
127
- yield dataService.createRecord(operation.logicalName, operation.data);
128
- break;
129
- case 'update':
130
- yield dataService.updateRecord(operation.logicalName, operation.id, operation.data);
131
- break;
132
- case 'delete':
133
- yield dataService.deleteRecord(operation.logicalName, operation.id);
134
- }
135
- }
136
- }
137
- else {
138
- const result = yield dataService.createRecord(schema.logicalName, values);
139
- recordId = result[schema.idAttribute];
140
- for (const control of editableGridControls) {
141
- const gridRows = values[control.attributeName];
142
- for (const row of gridRows) {
143
- yield dataService.createRecord(control.logicalName, Object.assign(Object.assign({}, row), { [control.referenceAttribute]: {
144
- id: recordId,
145
- } }));
146
- }
147
- }
148
- }
149
- return {
150
- success: true,
151
- recordId,
152
- };
153
- });
154
- }
41
+ const utils_1 = require("../../locale/utils");
42
+ var saveRecord_1 = require("./saveRecord");
43
+ Object.defineProperty(exports, "saveRecord", { enumerable: true, get: function () { return saveRecord_1.saveRecord; } });
155
44
  function getInitialValues({ cloneRecord, form, record, recordId, defaultParameters, }) {
156
45
  const formColumns = (0, DataResolver_1.getColumns)(form);
157
46
  const editableGridControls = (0, DataResolver_1.getControls)(form).filter((control) => control.type === 'editablegrid');
@@ -212,7 +101,7 @@ function getInitialValues({ cloneRecord, form, record, recordId, defaultParamete
212
101
  return Object.assign(Object.assign({}, acc), { [column]: value });
213
102
  }, {});
214
103
  }
215
- exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, schema, readonlyAttributes, formReadOnly, getSchema, language, strings, }) {
104
+ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, schema, readonlyAttributes, formReadOnly, schemaStore, language, strings, }) {
216
105
  return (values, context, options) => __awaiter(this, void 0, void 0, function* () {
217
106
  let validator = yup.object().shape({});
218
107
  if (!formReadOnly) {
@@ -243,7 +132,7 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
243
132
  if (control.type !== 'editablegrid') {
244
133
  throw new Error('Invalid control type');
245
134
  }
246
- const schema = getSchema(control.logicalName);
135
+ const schema = schemaStore.getSchema(control.logicalName);
247
136
  return {
248
137
  columns: control.attributes,
249
138
  schema: schema,
@@ -303,7 +192,7 @@ exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValida
303
192
  strings,
304
193
  readonlyAttributes,
305
194
  }));
306
- exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function generateAttributeValidationSchema(attribute, language, strings) {
195
+ function createAttributeValidationSchema(attribute) {
307
196
  let validationSchema;
308
197
  switch (attribute.type) {
309
198
  case 'string':
@@ -312,35 +201,100 @@ exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function gener
312
201
  case 'number':
313
202
  validationSchema = yup.number().nullable();
314
203
  break;
204
+ case 'attachments':
205
+ case 'choices':
206
+ case 'lookups':
207
+ validationSchema = yup.array().nullable();
208
+ break;
315
209
  default:
316
210
  validationSchema = yup.mixed().nullable();
317
211
  break;
318
212
  }
319
- const label = (0, CommandBuilder_1.localizedLabel)(language, attribute);
213
+ return validationSchema;
214
+ }
215
+ function extendAttributeRequiredValidationSchema({ attribute, validationSchema, label, strings, }) {
320
216
  if (attribute.required) {
321
217
  validationSchema = validationSchema.required(`${label}: ${strings.required}`);
322
218
  }
219
+ return validationSchema;
220
+ }
221
+ function extendAttributeValidationSchema({ attribute, validationSchema, label, strings, }) {
323
222
  switch (attribute.type) {
324
223
  case 'string':
325
- if (attribute.maxLength) {
326
- validationSchema = validationSchema.max(attribute.maxLength, `${label}: ${strings.maxLength}`);
327
- }
328
- if (attribute.minLength) {
329
- validationSchema = validationSchema.min(attribute.minLength, `${label}: ${strings.minLength}`);
330
- }
331
- if (attribute.pattern) {
332
- validationSchema = validationSchema.matches(new RegExp(attribute.pattern), `${label}: ${strings.invalidFormat}`);
333
- }
334
- if (attribute.format === 'email') {
335
- validationSchema = validationSchema.email(`${label}: ${strings.invalidEmail}`);
336
- }
337
- else if (attribute.format === 'phone') {
338
- validationSchema = validationSchema.matches(/^(\+\d{1,2}\s?)?\d{10}$/, `${label}: ${strings.invalidPhoneNumber}`);
339
- }
224
+ validationSchema = extendAttributeStringValidationSchema({
225
+ attribute,
226
+ validationSchema: validationSchema,
227
+ label,
228
+ strings,
229
+ });
230
+ break;
231
+ case 'attachments':
232
+ validationSchema = extendAttributeAttachmentsValidationSchema({
233
+ attribute,
234
+ validationSchema: validationSchema,
235
+ label,
236
+ strings,
237
+ });
340
238
  break;
341
239
  default:
342
240
  break;
343
241
  }
242
+ return validationSchema;
243
+ }
244
+ function extendAttributeStringValidationSchema({ attribute, validationSchema, label, strings, }) {
245
+ if (attribute.maxLength) {
246
+ // extend the validation schema with the max length
247
+ validationSchema = validationSchema.max(attribute.maxLength, `${label}: ${strings.maxLength}`);
248
+ }
249
+ if (attribute.minLength) {
250
+ // extend the validation schema with the min length
251
+ validationSchema = validationSchema.min(attribute.minLength, `${label}: ${strings.minLength}`);
252
+ }
253
+ if (attribute.pattern) {
254
+ // extend the validation schema with the pattern
255
+ validationSchema = validationSchema.matches(new RegExp(attribute.pattern), `${label}: ${strings.invalidFormat}`);
256
+ }
257
+ if (attribute.format === 'email') {
258
+ // extend the validation schema with the email format
259
+ validationSchema = validationSchema.email(`${label}: ${strings.invalidEmail}`);
260
+ }
261
+ else if (attribute.format === 'phone') {
262
+ // extend the validation schema with the phone format
263
+ validationSchema = validationSchema.matches(/^(\+\d{1,2}\s?)?\d{10}$/, `${label}: ${strings.invalidPhoneNumber}`);
264
+ }
265
+ return validationSchema;
266
+ }
267
+ function extendAttributeAttachmentsValidationSchema({ attribute, validationSchema, label, strings, }) {
268
+ if (attribute.required) {
269
+ // extend the validation schema with the min length
270
+ validationSchema = validationSchema.min(1, `${label}: ${strings.required}`);
271
+ }
272
+ if (attribute.maxSize) {
273
+ // extend the validation schema with the max size
274
+ validationSchema = validationSchema.test('fileSize', `${label}: ${strings.fileSizeExceeded}`, (value) => {
275
+ if (!value) {
276
+ return true;
277
+ }
278
+ return value.every((file) => (file === null || file === void 0 ? void 0 : file.size) && file.size <= attribute.maxSize);
279
+ });
280
+ }
281
+ return validationSchema;
282
+ }
283
+ exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function generateAttributeValidationSchema(attribute, language, strings) {
284
+ let validationSchema = createAttributeValidationSchema(attribute);
285
+ const label = (0, utils_1.localizedLabel)(language, attribute);
286
+ validationSchema = extendAttributeRequiredValidationSchema({
287
+ attribute,
288
+ validationSchema,
289
+ label,
290
+ strings,
291
+ });
292
+ validationSchema = extendAttributeValidationSchema({
293
+ attribute,
294
+ validationSchema,
295
+ label,
296
+ strings,
297
+ });
344
298
  validationSchema = validationSchema.transform((value) => {
345
299
  if (value === '') {
346
300
  return null;
@@ -0,0 +1,25 @@
1
+ import { Form } from '@headless-adminapp/core/experience/form';
2
+ import { InferredSchemaType, Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
3
+ import { ISchemaStore } from '@headless-adminapp/core/store';
4
+ import { IDataService } from '@headless-adminapp/core/transport';
5
+ import { Nullable } from '@headless-adminapp/core/types';
6
+ export declare function getModifiedValues(initialValues: any, values: any, exclude?: string[]): Record<string, any>;
7
+ type SaveRecordResult = {
8
+ success: true;
9
+ recordId: string;
10
+ } | {
11
+ success: false;
12
+ title?: string;
13
+ message: string;
14
+ isError: boolean;
15
+ };
16
+ export declare function saveRecord({ values, form, schema, dataService, initialValues, record, schemaStore, }: {
17
+ values: any;
18
+ form: Form<SchemaAttributes>;
19
+ record: InferredSchemaType<SchemaAttributes> | undefined;
20
+ initialValues: Nullable<InferredSchemaType<SchemaAttributes>>;
21
+ schema: Schema<SchemaAttributes>;
22
+ dataService: IDataService;
23
+ schemaStore: ISchemaStore;
24
+ }): Promise<SaveRecordResult>;
25
+ export {};
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getModifiedValues = getModifiedValues;
13
+ exports.saveRecord = saveRecord;
14
+ const DataResolver_1 = require("../../dataform/DataFormProvider/DataResolver");
15
+ function getModifiedValues(initialValues, values, exclude) {
16
+ const keys = Object.keys(values);
17
+ return keys.reduce((p, c) => {
18
+ if (c === '_id') {
19
+ return p;
20
+ }
21
+ if (exclude === null || exclude === void 0 ? void 0 : exclude.includes(c)) {
22
+ return p;
23
+ }
24
+ if (JSON.stringify(values[c]) !== JSON.stringify(initialValues[c])) {
25
+ p[c] = values[c];
26
+ }
27
+ return p;
28
+ }, {});
29
+ }
30
+ function executeOperation(operation, dataService) {
31
+ return __awaiter(this, void 0, void 0, function* () {
32
+ switch (operation.type) {
33
+ case 'create':
34
+ yield dataService.createRecord(operation.logicalName, operation.data);
35
+ break;
36
+ case 'update':
37
+ yield dataService.updateRecord(operation.logicalName, operation.id, operation.data);
38
+ break;
39
+ case 'delete':
40
+ yield dataService.deleteRecord(operation.logicalName, operation.id);
41
+ }
42
+ });
43
+ }
44
+ function generateSubgridUpdateOperation({ recordId, control, schemaStore, values, initialValues, }) {
45
+ const operations = [];
46
+ const gridSchema = schemaStore.getSchema(control.logicalName);
47
+ const gridRows = values[control.attributeName];
48
+ const initialGridRows = initialValues[control.attributeName];
49
+ const newRows = gridRows.filter((x) => !x[gridSchema.idAttribute]);
50
+ const updatedRows = gridRows.filter((x) => x[gridSchema.idAttribute]);
51
+ const deletedIds = initialGridRows === null || initialGridRows === void 0 ? void 0 : initialGridRows.map((x) => x[gridSchema.idAttribute]).filter((id) => !gridRows.find((x) => x[gridSchema.idAttribute] === id));
52
+ for (const row of newRows) {
53
+ operations.push({
54
+ type: 'create',
55
+ logicalName: control.logicalName,
56
+ data: Object.assign(Object.assign({}, row), { [control.referenceAttribute]: {
57
+ id: recordId,
58
+ } }),
59
+ });
60
+ }
61
+ for (const row of updatedRows) {
62
+ const initialRow = initialGridRows.find((x) => x[gridSchema.idAttribute] === row[gridSchema.idAttribute]);
63
+ if (!initialRow) {
64
+ throw new Error('Initial row not found');
65
+ }
66
+ const modifiedRow = getModifiedValues(initialRow, row);
67
+ if (!Object.keys(modifiedRow).length) {
68
+ continue;
69
+ }
70
+ operations.push({
71
+ type: 'update',
72
+ logicalName: control.logicalName,
73
+ data: modifiedRow,
74
+ id: row[gridSchema.idAttribute],
75
+ });
76
+ }
77
+ for (const id of deletedIds) {
78
+ operations.push({
79
+ type: 'delete',
80
+ logicalName: control.logicalName,
81
+ id,
82
+ });
83
+ }
84
+ return operations;
85
+ }
86
+ function createRecord(_a) {
87
+ return __awaiter(this, arguments, void 0, function* ({ values, form, schema, dataService, }) {
88
+ const controls = (0, DataResolver_1.getControls)(form);
89
+ const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
90
+ const result = yield dataService.createRecord(schema.logicalName, values);
91
+ const recordId = result[schema.idAttribute];
92
+ for (const control of editableGridControls) {
93
+ const gridRows = values[control.attributeName];
94
+ for (const row of gridRows) {
95
+ yield dataService.createRecord(control.logicalName, Object.assign(Object.assign({}, row), { [control.referenceAttribute]: {
96
+ id: recordId,
97
+ } }));
98
+ }
99
+ }
100
+ return recordId;
101
+ });
102
+ }
103
+ function updateRecord(_a) {
104
+ return __awaiter(this, arguments, void 0, function* ({ recordId, values, form, schema, dataService, initialValues, schemaStore, }) {
105
+ const controls = (0, DataResolver_1.getControls)(form);
106
+ const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
107
+ const modifiedValues = getModifiedValues(initialValues, values, editableGridControls.map((x) => x.attributeName));
108
+ const operations = [];
109
+ if (Object.keys(modifiedValues).length) {
110
+ operations.push({
111
+ type: 'update',
112
+ logicalName: schema.logicalName,
113
+ data: modifiedValues,
114
+ id: recordId,
115
+ });
116
+ }
117
+ for (const control of editableGridControls) {
118
+ operations.push(...generateSubgridUpdateOperation({
119
+ recordId,
120
+ control,
121
+ schemaStore,
122
+ initialValues,
123
+ values,
124
+ }));
125
+ }
126
+ if (!operations.length) {
127
+ return {
128
+ success: false,
129
+ title: 'No changes',
130
+ message: 'No changes made to the record',
131
+ isError: false,
132
+ };
133
+ }
134
+ for (const operation of operations) {
135
+ yield executeOperation(operation, dataService);
136
+ }
137
+ });
138
+ }
139
+ function saveRecord(_a) {
140
+ return __awaiter(this, arguments, void 0, function* ({ values, form, schema, dataService, initialValues, record, schemaStore, }) {
141
+ let recordId;
142
+ if (record) {
143
+ recordId = record[schema.idAttribute];
144
+ yield updateRecord({
145
+ recordId,
146
+ values,
147
+ form,
148
+ schema,
149
+ dataService,
150
+ initialValues,
151
+ schemaStore,
152
+ });
153
+ }
154
+ else {
155
+ recordId = yield createRecord({
156
+ dataService,
157
+ form,
158
+ schema,
159
+ values,
160
+ });
161
+ }
162
+ return {
163
+ success: true,
164
+ recordId,
165
+ };
166
+ });
167
+ }