@headless-adminapp/app 0.0.17-alpha.8 → 1.0.0

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 (243) hide show
  1. package/app/AppProvider.d.ts +0 -3
  2. package/app/AppProvider.js +10 -33
  3. package/app/AuthWrapper.d.ts +1 -1
  4. package/app/AuthWrapper.js +4 -1
  5. package/app/LayoutProvider.d.ts +8 -7
  6. package/app/LayoutProvider.js +28 -2
  7. package/app/context.d.ts +1 -1
  8. package/auth/AuthProvider.d.ts +1 -1
  9. package/auth/AuthProvider.js +30 -23
  10. package/auth/context.d.ts +2 -0
  11. package/auth/hooks/useIsSkipAuthCheck.d.ts +1 -0
  12. package/auth/hooks/useIsSkipAuthCheck.js +8 -0
  13. package/auth/hooks/useLogout.js +1 -1
  14. package/board/BoardColumnDataResolver.d.ts +1 -0
  15. package/board/BoardColumnDataResolver.js +64 -0
  16. package/board/BoardColumnProvider.d.ts +7 -0
  17. package/board/BoardColumnProvider.js +36 -0
  18. package/board/context.d.ts +19 -0
  19. package/board/context.js +6 -0
  20. package/board/hooks/index.d.ts +6 -0
  21. package/board/hooks/index.js +15 -0
  22. package/board/hooks/useBoardColumnConfig.d.ts +2 -0
  23. package/board/hooks/useBoardColumnConfig.js +8 -0
  24. package/board/hooks/useBoardColumnData.d.ts +3 -0
  25. package/board/hooks/useBoardColumnData.js +9 -0
  26. package/board/hooks/useBoardColumnDataState.d.ts +5 -0
  27. package/board/hooks/useBoardColumnDataState.js +9 -0
  28. package/board/hooks/useBoardConfig.d.ts +3 -0
  29. package/board/hooks/useBoardConfig.js +8 -0
  30. package/board/hooks/useBoardSchema.d.ts +2 -0
  31. package/board/hooks/useBoardSchema.js +7 -0
  32. package/board/hooks/useSearchText.d.ts +1 -0
  33. package/board/hooks/useSearchText.js +14 -0
  34. package/board/types.d.ts +47 -0
  35. package/board/utils.d.ts +3 -0
  36. package/board/utils.js +6 -0
  37. package/builders/CommandBuilder/DefaultCommandBuilder.d.ts +15 -6
  38. package/builders/CommandBuilder/DefaultCommandBuilder.js +42 -20
  39. package/builders/CommandBuilder/FormCommandBuilder.d.ts +14 -13
  40. package/builders/CommandBuilder/FormCommandBuilder.js +66 -52
  41. package/builders/CommandBuilder/SubgridCommandBuilder.d.ts +8 -27
  42. package/builders/CommandBuilder/SubgridCommandBuilder.js +115 -57
  43. package/builders/CommandBuilder/ViewCommandBuilder.js +32 -52
  44. package/builders/CommandBuilder/utils.js +1 -1
  45. package/builders/DefineFormExperience.d.ts +27 -0
  46. package/builders/DefineFormExperience.js +99 -0
  47. package/builders/DefineViewExperience.d.ts +13 -0
  48. package/builders/DefineViewExperience.js +33 -0
  49. package/builders/SchemaExperienceBuilder.d.ts +9 -7
  50. package/builders/SchemaExperienceBuilder.js +62 -40
  51. package/builders/utils.js +30 -44
  52. package/calendar/baseEventAttributes.d.ts +35 -0
  53. package/calendar/baseEventAttributes.js +38 -0
  54. package/calendar/context.d.ts +6 -0
  55. package/calendar/context.js +5 -0
  56. package/calendar/hooks/index.d.ts +1 -0
  57. package/{appearance → calendar}/hooks/index.js +1 -1
  58. package/calendar/hooks/useConfig.d.ts +3 -0
  59. package/calendar/hooks/useConfig.js +8 -0
  60. package/calendar/types.d.ts +41 -0
  61. package/calendar/types.js +2 -0
  62. package/calendar/utils.d.ts +3 -0
  63. package/calendar/utils.js +6 -0
  64. package/command/hooks/useBaseCommandHandlerContext.js +15 -6
  65. package/command/hooks/useCommands.js +1 -1
  66. package/command/utils/index.js +34 -9
  67. package/components/ScrollView/index.d.ts +1 -1
  68. package/components/ScrollView/index.js +2 -2
  69. package/components/ScrollbarWithMoreDataRequest/index.d.ts +9 -0
  70. package/components/ScrollbarWithMoreDataRequest/index.js +32 -0
  71. package/dataform/DataFormProvider/CustomHookExecuter.d.ts +5 -0
  72. package/dataform/DataFormProvider/CustomHookExecuter.js +14 -0
  73. package/dataform/DataFormProvider/DataResolver.d.ts +6 -4
  74. package/dataform/DataFormProvider/DataResolver.js +11 -94
  75. package/dataform/DataFormProvider/InitialValueResolver.js +3 -2
  76. package/dataform/DataFormProvider/ReadonlyInfoResolver.js +2 -3
  77. package/dataform/DataFormProvider/getRecord.d.ts +3 -0
  78. package/dataform/DataFormProvider/getRecord.js +56 -0
  79. package/dataform/DataFormProvider/index.d.ts +4 -0
  80. package/dataform/DataFormProvider/index.js +34 -12
  81. package/dataform/DataFormProvider/types.d.ts +13 -0
  82. package/dataform/DataFormProvider/types.js +2 -0
  83. package/dataform/DataFormProvider/utils.d.ts +23 -0
  84. package/dataform/DataFormProvider/utils.js +105 -0
  85. package/dataform/FormManager.d.ts +57 -0
  86. package/dataform/FormManager.js +247 -0
  87. package/dataform/constants.d.ts +1 -0
  88. package/dataform/constants.js +4 -0
  89. package/dataform/context.d.ts +26 -1
  90. package/dataform/hooks/index.d.ts +11 -0
  91. package/dataform/hooks/index.js +11 -0
  92. package/dataform/hooks/useContextKey.d.ts +1 -0
  93. package/dataform/hooks/useContextKey.js +8 -0
  94. package/dataform/hooks/useDisabledControlsManager.d.ts +6 -0
  95. package/dataform/hooks/useDisabledControlsManager.js +46 -0
  96. package/dataform/hooks/useEventManager.d.ts +1 -0
  97. package/dataform/hooks/useEventManager.js +8 -0
  98. package/dataform/hooks/useFormManager.d.ts +2 -0
  99. package/dataform/hooks/useFormManager.js +13 -0
  100. package/dataform/hooks/useFormNotifications.js +2 -2
  101. package/dataform/hooks/useFormSave.js +28 -31
  102. package/dataform/hooks/useHiddenControlsManager.d.ts +7 -0
  103. package/dataform/hooks/useHiddenControlsManager.js +50 -0
  104. package/dataform/hooks/useIsControlDisabled.d.ts +1 -0
  105. package/dataform/hooks/useIsControlDisabled.js +27 -0
  106. package/dataform/hooks/useIsControlHiddenByAttributeName.d.ts +1 -0
  107. package/dataform/hooks/useIsControlHiddenByAttributeName.js +17 -0
  108. package/dataform/hooks/useIsControlHiddenByKey.d.ts +1 -0
  109. package/dataform/hooks/useIsControlHiddenByKey.js +17 -0
  110. package/dataform/hooks/useIsFieldRequired.d.ts +1 -0
  111. package/dataform/hooks/useIsFieldRequired.js +25 -0
  112. package/dataform/hooks/useLoadFormGridPage.js +8 -17
  113. package/dataform/hooks/useMainFormCommands.d.ts +1 -12
  114. package/dataform/hooks/useMainFormCommands.js +13 -3
  115. package/dataform/hooks/useOnFieldValueChangeListener.d.ts +1 -0
  116. package/dataform/hooks/useOnFieldValueChangeListener.js +30 -0
  117. package/dataform/hooks/useProcessFlowSteps.d.ts +1 -0
  118. package/dataform/hooks/useProcessFlowSteps.js +45 -0
  119. package/dataform/hooks/useRecordTitle.d.ts +3 -1
  120. package/dataform/hooks/useRecordTitle.js +12 -5
  121. package/dataform/hooks/useRequiredFieldManager.d.ts +6 -0
  122. package/dataform/hooks/useRequiredFieldManager.js +49 -0
  123. package/dataform/test.d.ts +57 -0
  124. package/dataform/test.js +247 -0
  125. package/dataform/utils/defaultParameters.d.ts +6 -0
  126. package/dataform/utils/defaultParameters.js +54 -0
  127. package/dataform/utils/index.d.ts +6 -24
  128. package/dataform/utils/index.js +164 -190
  129. package/dataform/utils/saveRecord.d.ts +27 -0
  130. package/dataform/utils/saveRecord.js +163 -0
  131. package/datagrid/DataGridProvider/DataResolver.js +38 -109
  132. package/datagrid/DataGridProvider/index.d.ts +6 -0
  133. package/datagrid/DataGridProvider/index.js +18 -8
  134. package/datagrid/DataGridProvider/transformViewColumns.js +10 -2
  135. package/datagrid/DataGridProvider/utils.js +8 -8
  136. package/datagrid/column-filter/constants.js +38 -3
  137. package/datagrid/column-filter/utils.js +7 -1
  138. package/datagrid/context.d.ts +6 -0
  139. package/datagrid/hooks/useChangeView.js +1 -1
  140. package/datagrid/hooks/useGridColumnFilter.js +4 -1
  141. package/datagrid/hooks/useGridDisabled.d.ts +1 -0
  142. package/datagrid/hooks/useGridDisabled.js +8 -0
  143. package/datagrid/hooks/useLoadMainGridPage.js +1 -1
  144. package/datagrid/hooks/useMainGridCommands.js +23 -9
  145. package/datagrid/hooks/useOpenRecord.js +2 -2
  146. package/datagrid/hooks/useSubGridCommands.js +23 -45
  147. package/defaults.d.ts +2 -0
  148. package/defaults.js +5 -0
  149. package/dialog/hooks/useCloseDialog.js +17 -15
  150. package/dialog/hooks/useOpenAlertDialog.js +8 -3
  151. package/dialog/hooks/useOpenConfirmDialog.js +10 -4
  152. package/dialog/hooks/useOpenDialog.js +7 -5
  153. package/dialog/hooks/useOpenErrorDialog.js +8 -3
  154. package/dialog/hooks/useOpenPromptDialog.js +10 -4
  155. package/form/FormValidationStringContext.d.ts +1 -0
  156. package/form/FormValidationStringContext.js +1 -0
  157. package/hooks/index.d.ts +1 -0
  158. package/hooks/index.js +3 -0
  159. package/hooks/useDebouncedValue.js +0 -1
  160. package/hooks/useElementLayout.js +1 -1
  161. package/hooks/useIsMobile.js +0 -1
  162. package/hooks/useItemsWithKey.d.ts +7 -0
  163. package/hooks/useItemsWithKey.js +13 -0
  164. package/hooks/useStorageState.js +1 -2
  165. package/hooks/useSystemColorScheme.d.ts +1 -1
  166. package/hooks/useSystemColorScheme.js +0 -1
  167. package/insights/InsightsProvider.d.ts +8 -0
  168. package/insights/InsightsProvider.js +27 -0
  169. package/locale/LocaleProvider.d.ts +2 -1
  170. package/locale/LocaleProvider.js +3 -3
  171. package/locale/index.d.ts +1 -0
  172. package/locale/index.js +1 -0
  173. package/locale/useCurrencySymbol.d.ts +1 -0
  174. package/locale/useCurrencySymbol.js +12 -0
  175. package/locale/utils.js +4 -2
  176. package/metadata/MetadataProvider.d.ts +8 -4
  177. package/metadata/MetadataProvider.js +23 -17
  178. package/metadata/context.d.ts +3 -2
  179. package/metadata/hooks/index.d.ts +1 -1
  180. package/metadata/hooks/index.js +1 -1
  181. package/metadata/hooks/useAppExperience.d.ts +1 -0
  182. package/metadata/hooks/useAppExperience.js +8 -0
  183. package/metadata/hooks/useAppStore.d.ts +1 -1
  184. package/metadata/hooks/useAppStore.js +3 -3
  185. package/metadata/hooks/useExperienceView.js +2 -11
  186. package/metadata/hooks/useExperienceViewCommands.d.ts +1 -1
  187. package/metadata/hooks/useExperienceViewCommands.js +5 -14
  188. package/metadata/hooks/useExperienceViewLookup.js +2 -11
  189. package/metadata/hooks/useExperienceViewSubgridCommands.d.ts +1 -1
  190. package/metadata/hooks/useExperienceViewSubgridCommands.js +5 -14
  191. package/metadata/hooks/useMetadata.d.ts +11 -10
  192. package/metadata/hooks/useMetadata.js +4 -16
  193. package/metadata/hooks/useSchema.d.ts +1 -1
  194. package/metadata/hooks/useSchema.js +3 -0
  195. package/mutable/context.d.ts +3 -0
  196. package/mutable/context.js +8 -0
  197. package/mutable/utils.js +5 -12
  198. package/navigation/hooks/useOpenForm.js +4 -0
  199. package/package.json +6 -10
  200. package/providers/PageEntityFormProvider/index.d.ts +5 -1
  201. package/providers/PageEntityFormProvider/index.js +2 -2
  202. package/recordset/hooks/useRecordSetResult.js +4 -14
  203. package/route/RouteProvider.d.ts +2 -2
  204. package/route/RouteProvider.js +4 -1
  205. package/store/ClientAppStore.js +7 -20
  206. package/store/ComponentStore.d.ts +1 -1
  207. package/store/ComponentStore.js +6 -12
  208. package/store/EventManager.d.ts +2 -2
  209. package/store/EventManager.js +13 -29
  210. package/store/SchemaExperienceStore.js +179 -215
  211. package/store/index.d.ts +0 -1
  212. package/store/index.js +0 -1
  213. package/toast-notification/hooks/useCloseToastNotification.js +17 -15
  214. package/toast-notification/hooks/useOpenToastNotification.js +7 -5
  215. package/transport/InMemoryDataService/index.js +54 -77
  216. package/transport/RestDataService/index.d.ts +3 -3
  217. package/transport/RestDataService/index.js +68 -91
  218. package/transport/context.d.ts +2 -1
  219. package/transport/context.js +7 -1
  220. package/transport/hooks/index.d.ts +1 -0
  221. package/transport/hooks/index.js +1 -0
  222. package/transport/hooks/useFileService.d.ts +1 -0
  223. package/transport/hooks/useFileService.js +9 -0
  224. package/transport/hooks/useRetriveRecords.d.ts +33 -0
  225. package/transport/hooks/useRetriveRecords.js +110 -0
  226. package/utils/calculateColumnWidths.js +1 -1
  227. package/utils/color.d.ts +1 -0
  228. package/utils/color.js +14 -0
  229. package/utils/getAttributeFormattedValue.d.ts +4 -1
  230. package/utils/getAttributeFormattedValue.js +109 -54
  231. package/utils/phone.d.ts +13 -0
  232. package/utils/phone.js +33 -0
  233. package/appearance/context.d.ts +0 -7
  234. package/appearance/context.js +0 -5
  235. package/appearance/hooks/index.d.ts +0 -1
  236. package/appearance/hooks/useAppearanceContext.d.ts +0 -1
  237. package/appearance/hooks/useAppearanceContext.js +0 -12
  238. package/appearance/index.d.ts +0 -2
  239. package/appearance/index.js +0 -20
  240. package/builders/CommandBuilder.d.ts +0 -176
  241. package/builders/CommandBuilder.js +0 -567
  242. package/locale/types.d.ts +0 -2
  243. /package/{locale → board}/types.js +0 -0
@@ -22,142 +22,23 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
25
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.generateAttributeValidationSchema = exports.generateValidationSchema = exports.formValidator = void 0;
36
- exports.getModifiedValues = getModifiedValues;
37
- exports.saveRecord = saveRecord;
26
+ exports.generateAttributeValidationSchema = exports.generateValidationSchema = exports.formValidator = exports.saveRecord = void 0;
38
27
  exports.getInitialValues = getInitialValues;
28
+ const phone_1 = require("@headless-adminapp/app/utils/phone");
39
29
  const yup_1 = require("@hookform/resolvers/yup");
40
30
  const lodash_1 = require("lodash");
41
31
  const yup = __importStar(require("yup"));
42
- const DataResolver_1 = require("../../dataform/DataFormProvider/DataResolver");
43
- const utils_1 = require("../../locale/utils");
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, schemaStore, }) {
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 = schemaStore.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
- }
155
- function getInitialValues({ cloneRecord, form, record, recordId, defaultParameters, }) {
156
- const formColumns = (0, DataResolver_1.getColumns)(form);
157
- const editableGridControls = (0, DataResolver_1.getControls)(form).filter(control => control.type === 'editablegrid');
32
+ const utils_1 = require("../../dataform/DataFormProvider/utils");
33
+ const utils_2 = require("../../locale/utils");
34
+ var saveRecord_1 = require("./saveRecord");
35
+ Object.defineProperty(exports, "saveRecord", { enumerable: true, get: function () { return saveRecord_1.saveRecord; } });
36
+ function getInitialValues({ cloneRecord, form, record, recordId, schema, defaultParameters, }) {
37
+ const formColumns = (0, utils_1.getColumns)(form, schema);
38
+ const editableGridControls = (0, utils_1.getControls)(form).filter((control) => control.type === 'editablegrid');
158
39
  const allColumns = [
159
40
  ...formColumns,
160
- ...editableGridControls.map(x => x.attributeName),
41
+ ...editableGridControls.map((x) => x.attributeName),
161
42
  ];
162
43
  if (!recordId && !record && form.experience.cloneAttributes && cloneRecord) {
163
44
  const cloneAttributesObj = form.experience.cloneAttributes.reduce((acc, item) => {
@@ -171,7 +52,6 @@ function getInitialValues({ cloneRecord, form, record, recordId, defaultParamete
171
52
  return acc;
172
53
  }, {});
173
54
  return allColumns.reduce((acc, column) => {
174
- var _a;
175
55
  const cloneAttributeInfo = cloneAttributesObj[column];
176
56
  // | EditableGridCloneAttribute; // TODO:
177
57
  let value = null;
@@ -201,28 +81,33 @@ function getInitialValues({ cloneRecord, form, record, recordId, defaultParamete
201
81
  // }
202
82
  }
203
83
  else {
204
- value = (_a = defaultParameters[column]) !== null && _a !== void 0 ? _a : null;
84
+ value = defaultParameters[column] ?? null;
205
85
  }
206
- return Object.assign(Object.assign({}, acc), { [column]: value });
86
+ return {
87
+ ...acc,
88
+ [column]: value,
89
+ };
207
90
  }, {});
208
91
  }
209
92
  return allColumns.reduce((acc, column) => {
210
- var _a;
211
- const value = record ? record[column] : (_a = defaultParameters[column]) !== null && _a !== void 0 ? _a : null;
212
- return Object.assign(Object.assign({}, acc), { [column]: value });
93
+ const value = record ? record[column] : defaultParameters[column] ?? null;
94
+ return {
95
+ ...acc,
96
+ [column]: value,
97
+ };
213
98
  }, {});
214
99
  }
215
- exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, schema, readonlyAttributes, formReadOnly, schemaStore, language, strings, }) {
216
- return (values, context, options) => __awaiter(this, void 0, void 0, function* () {
100
+ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, schema, readonlyAttributes, formReadOnly, schemaStore, language, strings, region, }) {
101
+ return async (values, context, options) => {
217
102
  let validator = yup.object().shape({});
218
103
  if (!formReadOnly) {
219
104
  const activeControls = form.experience.tabs
220
- .flatMap(tab => tab.tabColumns)
221
- .flatMap(tabColumn => tabColumn.sections)
222
- .flatMap(section => {
105
+ .flatMap((tab) => tab.tabColumns)
106
+ .flatMap((tabColumn) => tabColumn.sections)
107
+ .flatMap((section) => {
223
108
  return section.controls;
224
109
  })
225
- .filter(control => {
110
+ .filter((control) => {
226
111
  if (control.type === 'standard') {
227
112
  const attribute = schema.attributes[control.attributeName];
228
113
  if (attribute.readonly) {
@@ -231,15 +116,15 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
231
116
  }
232
117
  return true;
233
118
  });
234
- const editableGridControls = activeControls.filter(control => control.type === 'editablegrid');
119
+ const editableGridControls = activeControls.filter((control) => control.type === 'editablegrid');
235
120
  const columns = Array.from(new Set([
236
121
  schema.primaryAttribute,
237
122
  ...activeControls
238
- .filter(control => control.type === 'standard')
239
- .map(control => control.attributeName),
123
+ .filter((control) => control.type === 'standard')
124
+ .map((control) => control.attributeName),
240
125
  ]));
241
126
  validator = (0, exports.generateValidationSchema)({
242
- editableGrids: editableGridControls.map(control => {
127
+ editableGrids: editableGridControls.map((control) => {
243
128
  if (control.type !== 'editablegrid') {
244
129
  throw new Error('Invalid control type');
245
130
  }
@@ -256,12 +141,13 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
256
141
  language,
257
142
  strings,
258
143
  readonlyAttributes,
144
+ region,
259
145
  });
260
146
  }
261
147
  const resolver = (0, yup_1.yupResolver)(validator);
262
- const result = yield resolver(values, context, options);
148
+ const result = await resolver(values, context, options);
263
149
  return result;
264
- });
150
+ };
265
151
  }, ({ form, language, schema, strings, readonlyAttributes, formReadOnly }) => JSON.stringify({
266
152
  schema,
267
153
  form,
@@ -270,40 +156,52 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
270
156
  readonlyAttributes,
271
157
  formReadOnly,
272
158
  }));
273
- exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValidationSchema({ columns, editableGrids, language, schema, strings, readonlyAttributes, }) {
274
- return yup.object().shape(Object.assign(Object.assign({}, columns.reduce((acc, column) => {
275
- if (readonlyAttributes === null || readonlyAttributes === void 0 ? void 0 : readonlyAttributes.includes(column)) {
159
+ exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValidationSchema({ columns, editableGrids, language, schema, strings, readonlyAttributes, region, }) {
160
+ return yup.object().shape({
161
+ ...columns.reduce((acc, column) => {
162
+ if (readonlyAttributes?.includes(column)) {
163
+ return acc;
164
+ }
165
+ const attribute = schema.attributes[column];
166
+ const validationSchema = (0, exports.generateAttributeValidationSchema)(attribute, language, strings, region);
167
+ return {
168
+ ...acc,
169
+ [column]: validationSchema,
170
+ };
171
+ }, {}),
172
+ ...editableGrids?.reduce((acc, grid) => {
173
+ let validationSchema = yup
174
+ .array()
175
+ .of(yup.object().shape({
176
+ ...grid.columns.reduce((acc, column) => {
177
+ const attribute = grid.schema.attributes[column];
178
+ const validationSchema = (0, exports.generateAttributeValidationSchema)(attribute, language, strings, region);
179
+ return {
180
+ ...acc,
181
+ [column]: validationSchema,
182
+ };
183
+ }, {}),
184
+ }))
185
+ .nullable();
186
+ if (grid.required) {
187
+ validationSchema = validationSchema
188
+ .required(strings.atLeastOneRowRequired)
189
+ .min(1, strings.atLeastOneRowRequired);
190
+ }
191
+ acc[grid.attributeName] = validationSchema;
276
192
  return acc;
277
- }
278
- const attribute = schema.attributes[column];
279
- const validationSchema = (0, exports.generateAttributeValidationSchema)(attribute, language, strings);
280
- return Object.assign(Object.assign({}, acc), { [column]: validationSchema });
281
- }, {})), editableGrids === null || editableGrids === void 0 ? void 0 : editableGrids.reduce((acc, grid) => {
282
- let validationSchema = yup
283
- .array()
284
- .of(yup.object().shape(Object.assign({}, grid.columns.reduce((acc, column) => {
285
- const attribute = grid.schema.attributes[column];
286
- const validationSchema = (0, exports.generateAttributeValidationSchema)(attribute, language, strings);
287
- return Object.assign(Object.assign({}, acc), { [column]: validationSchema });
288
- }, {}))))
289
- .nullable();
290
- if (grid.required) {
291
- validationSchema = validationSchema
292
- .required(strings.atLeastOneRowRequired)
293
- .min(1, strings.atLeastOneRowRequired);
294
- }
295
- acc[grid.attributeName] = validationSchema;
296
- return acc;
297
- }, {})));
298
- }, ({ columns, editableGrids, language, schema, strings, readonlyAttributes }) => JSON.stringify({
193
+ }, {}),
194
+ });
195
+ }, ({ columns, editableGrids, language, schema, strings, readonlyAttributes, region, }) => JSON.stringify({
299
196
  schema,
300
197
  columns,
301
198
  editableGrids,
302
199
  language,
303
200
  strings,
304
201
  readonlyAttributes,
202
+ region,
305
203
  }));
306
- exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function generateAttributeValidationSchema(attribute, language, strings) {
204
+ function createAttributeValidationSchema(attribute) {
307
205
  let validationSchema;
308
206
  switch (attribute.type) {
309
207
  case 'string':
@@ -312,36 +210,112 @@ exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function gener
312
210
  case 'number':
313
211
  validationSchema = yup.number().nullable();
314
212
  break;
213
+ case 'attachments':
214
+ case 'choices':
215
+ case 'lookups':
216
+ validationSchema = yup.array().nullable();
217
+ break;
315
218
  default:
316
219
  validationSchema = yup.mixed().nullable();
317
220
  break;
318
221
  }
319
- const label = (0, utils_1.localizedLabel)(language, attribute);
222
+ return validationSchema;
223
+ }
224
+ function extendAttributeRequiredValidationSchema({ attribute, validationSchema, label, strings, }) {
320
225
  if (attribute.required) {
321
226
  validationSchema = validationSchema.required(`${label}: ${strings.required}`);
322
227
  }
228
+ return validationSchema;
229
+ }
230
+ function extendAttributeValidationSchema({ attribute, validationSchema, label, strings, region, }) {
323
231
  switch (attribute.type) {
324
232
  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
- }
233
+ validationSchema = extendAttributeStringValidationSchema({
234
+ attribute,
235
+ validationSchema: validationSchema,
236
+ label,
237
+ strings,
238
+ region,
239
+ });
240
+ break;
241
+ case 'attachments':
242
+ validationSchema = extendAttributeAttachmentsValidationSchema({
243
+ attribute,
244
+ validationSchema: validationSchema,
245
+ label,
246
+ strings,
247
+ });
340
248
  break;
341
249
  default:
342
250
  break;
343
251
  }
344
- validationSchema = validationSchema.transform(value => {
252
+ return validationSchema;
253
+ }
254
+ function extendAttributeStringValidationSchema({ attribute, validationSchema, label, strings, region, }) {
255
+ if (attribute.maxLength) {
256
+ // extend the validation schema with the max length
257
+ validationSchema = validationSchema.max(attribute.maxLength, `${label}: ${strings.maxLength}`);
258
+ }
259
+ if (attribute.minLength) {
260
+ // extend the validation schema with the min length
261
+ validationSchema = validationSchema.min(attribute.minLength, `${label}: ${strings.minLength}`);
262
+ }
263
+ if (attribute.pattern) {
264
+ // extend the validation schema with the pattern
265
+ validationSchema = validationSchema.matches(new RegExp(attribute.pattern), `${label}: ${strings.invalidFormat}`);
266
+ }
267
+ if (attribute.format === 'email') {
268
+ // extend the validation schema with the email format
269
+ validationSchema = validationSchema.email(`${label}: ${strings.invalidEmail}`);
270
+ }
271
+ else if (attribute.format === 'phone') {
272
+ // extend the validation schema with the phone format
273
+ validationSchema = validationSchema.test({
274
+ message: `${label}: ${strings.invalidPhoneNumber}`,
275
+ test: (value) => {
276
+ if (!value) {
277
+ return true;
278
+ }
279
+ const phoneNumber = (0, phone_1.parsePhoneNumber)(value, region);
280
+ return phoneNumber.isValid;
281
+ },
282
+ });
283
+ }
284
+ return validationSchema;
285
+ }
286
+ function extendAttributeAttachmentsValidationSchema({ attribute, validationSchema, label, strings, }) {
287
+ if (attribute.required) {
288
+ // extend the validation schema with the min length
289
+ validationSchema = validationSchema.min(1, `${label}: ${strings.required}`);
290
+ }
291
+ if (attribute.maxSize) {
292
+ // extend the validation schema with the max size
293
+ validationSchema = validationSchema.test('fileSize', `${label}: ${strings.fileSizeExceeded}`, (value) => {
294
+ if (!value) {
295
+ return true;
296
+ }
297
+ return value.every((file) => file?.size && file.size <= attribute.maxSize);
298
+ });
299
+ }
300
+ return validationSchema;
301
+ }
302
+ exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function generateAttributeValidationSchema(attribute, language, strings, region) {
303
+ let validationSchema = createAttributeValidationSchema(attribute);
304
+ const label = (0, utils_2.localizedLabel)(language, attribute);
305
+ validationSchema = extendAttributeRequiredValidationSchema({
306
+ attribute,
307
+ validationSchema,
308
+ label,
309
+ strings,
310
+ });
311
+ validationSchema = extendAttributeValidationSchema({
312
+ attribute,
313
+ validationSchema,
314
+ label,
315
+ strings,
316
+ region,
317
+ });
318
+ validationSchema = validationSchema.transform((value) => {
345
319
  if (value === '') {
346
320
  return null;
347
321
  }
@@ -0,0 +1,27 @@
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 interface SaveRecordFnOptions {
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
+ }
25
+ export type SaveRecordFn = (options: SaveRecordFnOptions) => Promise<SaveRecordResult>;
26
+ export declare function saveRecord({ values, form, schema, dataService, initialValues, record, schemaStore, }: SaveRecordFnOptions): Promise<SaveRecordResult>;
27
+ export {};
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getModifiedValues = getModifiedValues;
4
+ exports.saveRecord = saveRecord;
5
+ const utils_1 = require("../../dataform/DataFormProvider/utils");
6
+ function getModifiedValues(initialValues, values, exclude) {
7
+ const keys = Object.keys(values);
8
+ return keys.reduce((p, c) => {
9
+ if (c === '_id') {
10
+ return p;
11
+ }
12
+ if (exclude?.includes(c)) {
13
+ return p;
14
+ }
15
+ if (JSON.stringify(values[c]) !== JSON.stringify(initialValues[c])) {
16
+ p[c] = values[c];
17
+ }
18
+ return p;
19
+ }, {});
20
+ }
21
+ async function executeOperation(operation, dataService) {
22
+ switch (operation.type) {
23
+ case 'create':
24
+ await dataService.createRecord(operation.logicalName, operation.data);
25
+ break;
26
+ case 'update':
27
+ await dataService.updateRecord(operation.logicalName, operation.id, operation.data);
28
+ break;
29
+ case 'delete':
30
+ await dataService.deleteRecord(operation.logicalName, operation.id);
31
+ }
32
+ }
33
+ function generateSubgridUpdateOperation({ recordId, control, schemaStore, values, initialValues, }) {
34
+ const operations = [];
35
+ const gridSchema = schemaStore.getSchema(control.logicalName);
36
+ const gridRows = values[control.attributeName];
37
+ const initialGridRows = initialValues[control.attributeName];
38
+ const newRows = gridRows.filter((x) => !x[gridSchema.idAttribute]);
39
+ const updatedRows = gridRows.filter((x) => x[gridSchema.idAttribute]);
40
+ const deletedIds = initialGridRows
41
+ ?.map((x) => x[gridSchema.idAttribute])
42
+ .filter((id) => !gridRows.find((x) => x[gridSchema.idAttribute] === id));
43
+ for (const row of newRows) {
44
+ operations.push({
45
+ type: 'create',
46
+ logicalName: control.logicalName,
47
+ data: {
48
+ ...row,
49
+ [control.referenceAttribute]: {
50
+ id: recordId,
51
+ },
52
+ },
53
+ });
54
+ }
55
+ for (const row of updatedRows) {
56
+ const initialRow = initialGridRows.find((x) => x[gridSchema.idAttribute] === row[gridSchema.idAttribute]);
57
+ if (!initialRow) {
58
+ throw new Error('Initial row not found');
59
+ }
60
+ const modifiedRow = getModifiedValues(initialRow, row);
61
+ if (!Object.keys(modifiedRow).length) {
62
+ continue;
63
+ }
64
+ operations.push({
65
+ type: 'update',
66
+ logicalName: control.logicalName,
67
+ data: modifiedRow,
68
+ id: row[gridSchema.idAttribute],
69
+ });
70
+ }
71
+ for (const id of deletedIds) {
72
+ operations.push({
73
+ type: 'delete',
74
+ logicalName: control.logicalName,
75
+ id,
76
+ });
77
+ }
78
+ return operations;
79
+ }
80
+ async function createRecord({ values, form, schema, dataService, }) {
81
+ const controls = (0, utils_1.getControls)(form);
82
+ const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
83
+ const result = await dataService.createRecord(schema.logicalName, values);
84
+ const recordId = result[schema.idAttribute];
85
+ for (const control of editableGridControls) {
86
+ const gridRows = values[control.attributeName];
87
+ for (const row of gridRows) {
88
+ await dataService.createRecord(control.logicalName, {
89
+ ...row,
90
+ [control.referenceAttribute]: {
91
+ id: recordId,
92
+ },
93
+ });
94
+ }
95
+ }
96
+ return recordId;
97
+ }
98
+ async function updateRecord({ recordId, values, form, schema, dataService, initialValues, schemaStore, }) {
99
+ const controls = (0, utils_1.getControls)(form);
100
+ const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
101
+ const modifiedValues = getModifiedValues(initialValues, values, editableGridControls.map((x) => x.attributeName));
102
+ const operations = [];
103
+ if (Object.keys(modifiedValues).length) {
104
+ operations.push({
105
+ type: 'update',
106
+ logicalName: schema.logicalName,
107
+ data: modifiedValues,
108
+ id: recordId,
109
+ });
110
+ }
111
+ for (const control of editableGridControls) {
112
+ operations.push(...generateSubgridUpdateOperation({
113
+ recordId,
114
+ control,
115
+ schemaStore,
116
+ initialValues,
117
+ values,
118
+ }));
119
+ }
120
+ if (!operations.length) {
121
+ return {
122
+ success: false,
123
+ title: 'No changes',
124
+ message: 'No changes made to the record',
125
+ isError: false,
126
+ };
127
+ }
128
+ for (const operation of operations) {
129
+ await executeOperation(operation, dataService);
130
+ }
131
+ return {
132
+ success: true,
133
+ recordId,
134
+ };
135
+ }
136
+ async function saveRecord({ values, form, schema, dataService, initialValues, record, schemaStore, }) {
137
+ let recordId;
138
+ if (record) {
139
+ recordId = record[schema.idAttribute];
140
+ const updateResult = await updateRecord({
141
+ recordId,
142
+ values,
143
+ form,
144
+ schema,
145
+ dataService,
146
+ initialValues,
147
+ schemaStore,
148
+ });
149
+ return updateResult;
150
+ }
151
+ else {
152
+ recordId = await createRecord({
153
+ dataService,
154
+ form,
155
+ schema,
156
+ values,
157
+ });
158
+ }
159
+ return {
160
+ success: true,
161
+ recordId,
162
+ };
163
+ }