@headless-adminapp/app 0.0.17-alpha.45 → 0.0.17-alpha.48
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.
- package/board/hooks/useSearchText.js +4 -4
- package/dataform/hooks/useProcessFlowSteps.d.ts +1 -1
- package/dataform/hooks/useRecordTitle.d.ts +1 -1
- package/dataform/hooks/useRecordTitle.js +9 -2
- package/dataform/utils/index.d.ts +1 -21
- package/dataform/utils/index.js +78 -142
- package/dataform/utils/saveRecord.d.ts +25 -0
- package/dataform/utils/saveRecord.js +167 -0
- package/package.json +2 -2
- package/utils/getAttributeFormattedValue.d.ts +1 -1
- package/utils/getAttributeFormattedValue.js +102 -67
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useSearchText = useSearchText;
|
|
4
|
+
const context_1 = require("@headless-adminapp/app/mutable/context");
|
|
4
5
|
const react_1 = require("react");
|
|
5
|
-
const
|
|
6
|
-
const context_2 = require("@headless-adminapp/app/mutable/context");
|
|
6
|
+
const context_2 = require("../context");
|
|
7
7
|
function useSearchText() {
|
|
8
|
-
const searchText = (0,
|
|
9
|
-
const setValue = (0,
|
|
8
|
+
const searchText = (0, context_1.useContextSelector)(context_2.BoardContext, (context) => context.searchText);
|
|
9
|
+
const setValue = (0, context_1.useContextSetValue)(context_2.BoardContext);
|
|
10
10
|
const setSearchText = (0, react_1.useCallback)((value) => {
|
|
11
11
|
setValue({ searchText: value });
|
|
12
12
|
}, [setValue]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function useProcessFlowSteps(): import("@headless-adminapp/core/experience/form/ProcessFlowInfo").ProcessFlowStep[] | undefined;
|
|
1
|
+
export declare function useProcessFlowSteps(): import("@headless-adminapp/core/experience/form/ProcessFlowInfo").ProcessFlowStep[] | null | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function useRecordTitle():
|
|
1
|
+
export declare function useRecordTitle(): any;
|
|
@@ -5,11 +5,18 @@ const useFormInstance_1 = require("./useFormInstance");
|
|
|
5
5
|
const useFormSchema_1 = require("./useFormSchema");
|
|
6
6
|
const useRecordId_1 = require("./useRecordId");
|
|
7
7
|
function useRecordTitle() {
|
|
8
|
-
var _a;
|
|
9
8
|
const formInstance = (0, useFormInstance_1.useFormInstance)();
|
|
10
9
|
const schema = (0, useFormSchema_1.useDataFormSchema)();
|
|
11
10
|
const recordId = (0, useRecordId_1.useRecordId)();
|
|
12
|
-
|
|
11
|
+
let primaryAttributeValue = formInstance.watch(schema.primaryAttribute);
|
|
12
|
+
const primaryAttribute = schema.attributes[schema.primaryAttribute];
|
|
13
|
+
if ((primaryAttribute === null || primaryAttribute === void 0 ? void 0 : primaryAttribute.type) === 'lookup') {
|
|
14
|
+
// Handle lookup attribute as primary
|
|
15
|
+
primaryAttributeValue = primaryAttributeValue === null || primaryAttributeValue === void 0 ? void 0 : primaryAttributeValue.name;
|
|
16
|
+
}
|
|
17
|
+
if (primaryAttributeValue && typeof primaryAttributeValue !== 'string') {
|
|
18
|
+
return String(primaryAttributeValue);
|
|
19
|
+
}
|
|
13
20
|
if (primaryAttributeValue) {
|
|
14
21
|
return primaryAttributeValue;
|
|
15
22
|
}
|
|
@@ -2,31 +2,12 @@ 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
4
|
import { ISchemaStore } from '@headless-adminapp/core/store';
|
|
5
|
-
import { IDataService } from '@headless-adminapp/core/transport';
|
|
6
5
|
import { Nullable } from '@headless-adminapp/core/types';
|
|
7
6
|
import { MemoizedFunction } from 'lodash';
|
|
8
7
|
import { ResolverResult } from 'react-hook-form';
|
|
9
8
|
import * as yup from 'yup';
|
|
10
9
|
import { FormValidationStringSet } from '../../form/FormValidationStringContext';
|
|
11
|
-
export
|
|
12
|
-
type SaveRecordResult = {
|
|
13
|
-
success: true;
|
|
14
|
-
recordId: string;
|
|
15
|
-
} | {
|
|
16
|
-
success: false;
|
|
17
|
-
title?: string;
|
|
18
|
-
message: string;
|
|
19
|
-
isError: boolean;
|
|
20
|
-
};
|
|
21
|
-
export declare function saveRecord({ values, form, schema, dataService, initialValues, record, schemaStore, }: {
|
|
22
|
-
values: any;
|
|
23
|
-
form: Form<SchemaAttributes>;
|
|
24
|
-
record: InferredSchemaType<SchemaAttributes> | undefined;
|
|
25
|
-
initialValues: Nullable<InferredSchemaType<SchemaAttributes>>;
|
|
26
|
-
schema: Schema<SchemaAttributes>;
|
|
27
|
-
dataService: IDataService;
|
|
28
|
-
schemaStore: ISchemaStore;
|
|
29
|
-
}): Promise<SaveRecordResult>;
|
|
10
|
+
export { saveRecord } from './saveRecord';
|
|
30
11
|
export declare function getInitialValues({ cloneRecord, form, record, recordId, defaultParameters, }: {
|
|
31
12
|
cloneRecord: InferredSchemaType<SchemaAttributes> | undefined;
|
|
32
13
|
form: Form<SchemaAttributes>;
|
|
@@ -64,4 +45,3 @@ export declare const generateValidationSchema: (<A extends SchemaAttributes = Sc
|
|
|
64
45
|
[x: string]: any;
|
|
65
46
|
}, "">) & MemoizedFunction;
|
|
66
47
|
export declare const generateAttributeValidationSchema: ((attribute: Attribute, language: string, strings: FormValidationStringSet) => yup.Schema<any, any, any, "">) & MemoizedFunction;
|
|
67
|
-
export {};
|
package/dataform/utils/index.js
CHANGED
|
@@ -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
40
|
const DataResolver_1 = require("../../dataform/DataFormProvider/DataResolver");
|
|
43
41
|
const utils_1 = require("../../locale/utils");
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
}
|
|
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');
|
|
@@ -303,7 +192,7 @@ exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValida
|
|
|
303
192
|
strings,
|
|
304
193
|
readonlyAttributes,
|
|
305
194
|
}));
|
|
306
|
-
|
|
195
|
+
function createAttributeValidationSchema(attribute) {
|
|
307
196
|
let validationSchema;
|
|
308
197
|
switch (attribute.type) {
|
|
309
198
|
case 'string':
|
|
@@ -321,44 +210,91 @@ exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function gener
|
|
|
321
210
|
validationSchema = yup.mixed().nullable();
|
|
322
211
|
break;
|
|
323
212
|
}
|
|
324
|
-
|
|
213
|
+
return validationSchema;
|
|
214
|
+
}
|
|
215
|
+
function extendAttributeRequiredValidationSchema({ attribute, validationSchema, label, strings, }) {
|
|
325
216
|
if (attribute.required) {
|
|
326
217
|
validationSchema = validationSchema.required(`${label}: ${strings.required}`);
|
|
327
218
|
}
|
|
219
|
+
return validationSchema;
|
|
220
|
+
}
|
|
221
|
+
function extendAttributeValidationSchema({ attribute, validationSchema, label, strings, }) {
|
|
328
222
|
switch (attribute.type) {
|
|
329
223
|
case 'string':
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
if (attribute.pattern) {
|
|
337
|
-
validationSchema = validationSchema.matches(new RegExp(attribute.pattern), `${label}: ${strings.invalidFormat}`);
|
|
338
|
-
}
|
|
339
|
-
if (attribute.format === 'email') {
|
|
340
|
-
validationSchema = validationSchema.email(`${label}: ${strings.invalidEmail}`);
|
|
341
|
-
}
|
|
342
|
-
else if (attribute.format === 'phone') {
|
|
343
|
-
validationSchema = validationSchema.matches(/^(\+\d{1,2}\s?)?\d{10}$/, `${label}: ${strings.invalidPhoneNumber}`);
|
|
344
|
-
}
|
|
224
|
+
validationSchema = extendAttributeStringValidationSchema({
|
|
225
|
+
attribute,
|
|
226
|
+
validationSchema: validationSchema,
|
|
227
|
+
label,
|
|
228
|
+
strings,
|
|
229
|
+
});
|
|
345
230
|
break;
|
|
346
231
|
case 'attachments':
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
return true;
|
|
354
|
-
}
|
|
355
|
-
return value.every((file) => (file === null || file === void 0 ? void 0 : file.size) && file.size <= attribute.maxSize);
|
|
356
|
-
});
|
|
357
|
-
}
|
|
232
|
+
validationSchema = extendAttributeAttachmentsValidationSchema({
|
|
233
|
+
attribute,
|
|
234
|
+
validationSchema: validationSchema,
|
|
235
|
+
label,
|
|
236
|
+
strings,
|
|
237
|
+
});
|
|
358
238
|
break;
|
|
359
239
|
default:
|
|
360
240
|
break;
|
|
361
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
|
+
});
|
|
362
298
|
validationSchema = validationSchema.transform((value) => {
|
|
363
299
|
if (value === '') {
|
|
364
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
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@headless-adminapp/app",
|
|
3
|
-
"version": "0.0.17-alpha.
|
|
3
|
+
"version": "0.0.17-alpha.48",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"react-hook-form": "7.52.2",
|
|
40
40
|
"yup": "^1.4.0"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "e8887232802a525648c316b2b8526b2571bc8b8c"
|
|
43
43
|
}
|
|
@@ -13,5 +13,5 @@ export declare function getAttributeFormattedValue<A extends Attribute = Attribu
|
|
|
13
13
|
currencySign?: 'accounting' | 'standard';
|
|
14
14
|
currencyDisplay?: 'symbol' | 'narrowSymbol' | 'code';
|
|
15
15
|
timezone?: string;
|
|
16
|
-
}): string | null
|
|
16
|
+
}): string | null;
|
|
17
17
|
export {};
|
|
@@ -19,89 +19,124 @@ const defaultLocale = 'en-US';
|
|
|
19
19
|
const defaultCurrency = 'USD';
|
|
20
20
|
const defaultCurrencySign = 'accounting';
|
|
21
21
|
const defaultCurrencyDisplay = 'symbol';
|
|
22
|
+
function getAttributeLookupsFormattedValue(value, options) {
|
|
23
|
+
const items = value === null || value === void 0 ? void 0 : value.map((v) => v.name);
|
|
24
|
+
if ((options === null || options === void 0 ? void 0 : options.maxCount) && (items === null || items === void 0 ? void 0 : items.length) > options.maxCount) {
|
|
25
|
+
return (items.slice(0, options.maxCount).join(', ') +
|
|
26
|
+
` (+${items.length - options.maxCount})`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return items === null || items === void 0 ? void 0 : items.join(', ');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function getAttributeAttachmentFormattedValue(value) {
|
|
33
|
+
var _a;
|
|
34
|
+
return (_a = value === null || value === void 0 ? void 0 : value.url) !== null && _a !== void 0 ? _a : null;
|
|
35
|
+
}
|
|
36
|
+
function getAttributeDateFormattedValue(attribute, value, options) {
|
|
37
|
+
var _a, _b;
|
|
38
|
+
const dateFormat = (_a = options === null || options === void 0 ? void 0 : options.dateFormat) !== null && _a !== void 0 ? _a : defaultDateFormat;
|
|
39
|
+
const timeFormat = (_b = options === null || options === void 0 ? void 0 : options.timeFormat) !== null && _b !== void 0 ? _b : defaultTimeFormat;
|
|
40
|
+
if (attribute.format === 'datetime') {
|
|
41
|
+
return (0, dayjs_1.default)(value)
|
|
42
|
+
.tz(options === null || options === void 0 ? void 0 : options.timezone)
|
|
43
|
+
.format(dateFormat + ' ' + timeFormat);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
return (0, dayjs_1.default)(value)
|
|
47
|
+
.tz(options === null || options === void 0 ? void 0 : options.timezone)
|
|
48
|
+
.format(dateFormat);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function getAttributeDateRangeFormattedValue(value, options) {
|
|
52
|
+
var _a;
|
|
53
|
+
if (!value)
|
|
54
|
+
return null;
|
|
55
|
+
const dateFormat = (_a = options === null || options === void 0 ? void 0 : options.dateFormat) !== null && _a !== void 0 ? _a : defaultDateFormat;
|
|
56
|
+
const from = value[0];
|
|
57
|
+
const to = value[1];
|
|
58
|
+
if (!from && !to) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
if (from && to) {
|
|
62
|
+
return ((0, dayjs_1.default)(from).tz(options === null || options === void 0 ? void 0 : options.timezone).format(dateFormat) +
|
|
63
|
+
' - ' +
|
|
64
|
+
(0, dayjs_1.default)(to).tz(options === null || options === void 0 ? void 0 : options.timezone).format(dateFormat));
|
|
65
|
+
}
|
|
66
|
+
if (from) {
|
|
67
|
+
return 'After ' + (0, dayjs_1.default)(from).tz(options === null || options === void 0 ? void 0 : options.timezone).format(dateFormat);
|
|
68
|
+
}
|
|
69
|
+
if (to) {
|
|
70
|
+
return 'Before ' + (0, dayjs_1.default)(to).tz(options === null || options === void 0 ? void 0 : options.timezone).format(dateFormat);
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
function getAttributeBooleanFormattedValue(attribute, value, options) {
|
|
75
|
+
var _a, _b, _c;
|
|
76
|
+
const strings = (_a = options === null || options === void 0 ? void 0 : options.strings) !== null && _a !== void 0 ? _a : defaultAttributeFormattedValueStrings;
|
|
77
|
+
return value
|
|
78
|
+
? (_b = attribute.trueLabel) !== null && _b !== void 0 ? _b : strings.yes
|
|
79
|
+
: (_c = attribute.falseLabel) !== null && _c !== void 0 ? _c : strings.no;
|
|
80
|
+
}
|
|
81
|
+
function getAttributeChoiceFormattedValue(attribute, value) {
|
|
82
|
+
var _a;
|
|
83
|
+
return ((_a = attribute.options.find((option) => option.value === value)) !== null && _a !== void 0 ? _a : {
|
|
84
|
+
label: '',
|
|
85
|
+
}).label;
|
|
86
|
+
}
|
|
87
|
+
function getAttributeChoicesFormattedValue(attribute, value) {
|
|
88
|
+
return value
|
|
89
|
+
.map((v) => {
|
|
90
|
+
var _a;
|
|
91
|
+
return ((_a = attribute.options.find((option) => option.value === v)) !== null && _a !== void 0 ? _a : {
|
|
92
|
+
label: '',
|
|
93
|
+
}).label;
|
|
94
|
+
})
|
|
95
|
+
.join(', ');
|
|
96
|
+
}
|
|
97
|
+
function getAttributeLookupFormattedValue(value) {
|
|
98
|
+
return value === null || value === void 0 ? void 0 : value.name;
|
|
99
|
+
}
|
|
100
|
+
function getAttributeMoneyFormattedValue(value, options) {
|
|
101
|
+
var _a, _b, _c, _d;
|
|
102
|
+
const locale = (_a = options === null || options === void 0 ? void 0 : options.locale) !== null && _a !== void 0 ? _a : defaultLocale;
|
|
103
|
+
const currency = (_b = options === null || options === void 0 ? void 0 : options.currency) !== null && _b !== void 0 ? _b : defaultCurrency;
|
|
104
|
+
const currencySign = (_c = options === null || options === void 0 ? void 0 : options.currencySign) !== null && _c !== void 0 ? _c : defaultCurrencySign;
|
|
105
|
+
const currencyDisplay = (_d = options === null || options === void 0 ? void 0 : options.currencyDisplay) !== null && _d !== void 0 ? _d : defaultCurrencyDisplay;
|
|
106
|
+
return new Intl.NumberFormat(locale, {
|
|
107
|
+
style: 'currency',
|
|
108
|
+
currency,
|
|
109
|
+
currencySign,
|
|
110
|
+
currencyDisplay,
|
|
111
|
+
}).format(value);
|
|
112
|
+
}
|
|
22
113
|
function getAttributeFormattedValue(attribute, value, options) {
|
|
23
|
-
var _a
|
|
114
|
+
var _a;
|
|
24
115
|
if (value === null || value === undefined) {
|
|
25
116
|
return null;
|
|
26
117
|
}
|
|
27
|
-
const
|
|
28
|
-
const dateFormat = (_b = options === null || options === void 0 ? void 0 : options.dateFormat) !== null && _b !== void 0 ? _b : defaultDateFormat;
|
|
29
|
-
const timeFormat = (_c = options === null || options === void 0 ? void 0 : options.timeFormat) !== null && _c !== void 0 ? _c : defaultTimeFormat;
|
|
30
|
-
const locale = (_d = options === null || options === void 0 ? void 0 : options.locale) !== null && _d !== void 0 ? _d : defaultLocale;
|
|
31
|
-
const currency = (_e = options === null || options === void 0 ? void 0 : options.currency) !== null && _e !== void 0 ? _e : defaultCurrency;
|
|
32
|
-
const currencySign = (_f = options === null || options === void 0 ? void 0 : options.currencySign) !== null && _f !== void 0 ? _f : defaultCurrencySign;
|
|
33
|
-
const currencyDisplay = (_g = options === null || options === void 0 ? void 0 : options.currencyDisplay) !== null && _g !== void 0 ? _g : defaultCurrencyDisplay;
|
|
118
|
+
const locale = (_a = options === null || options === void 0 ? void 0 : options.locale) !== null && _a !== void 0 ? _a : defaultLocale;
|
|
34
119
|
switch (attribute.type) {
|
|
35
120
|
case 'boolean':
|
|
36
|
-
return value
|
|
37
|
-
? (_h = attribute.trueLabel) !== null && _h !== void 0 ? _h : strings.yes
|
|
38
|
-
: (_j = attribute.falseLabel) !== null && _j !== void 0 ? _j : strings.no;
|
|
121
|
+
return getAttributeBooleanFormattedValue(attribute, value, options);
|
|
39
122
|
case 'choice':
|
|
40
|
-
return (
|
|
41
|
-
label: '',
|
|
42
|
-
}).label;
|
|
123
|
+
return getAttributeChoiceFormattedValue(attribute, value);
|
|
43
124
|
case 'choices':
|
|
44
|
-
return value
|
|
45
|
-
.map((v) => {
|
|
46
|
-
var _a;
|
|
47
|
-
return ((_a = attribute.options.find((option) => option.value === v)) !== null && _a !== void 0 ? _a : {
|
|
48
|
-
label: '',
|
|
49
|
-
}).label;
|
|
50
|
-
})
|
|
51
|
-
.join(', ');
|
|
125
|
+
return getAttributeChoicesFormattedValue(attribute, value);
|
|
52
126
|
case 'date':
|
|
53
|
-
|
|
54
|
-
return (0, dayjs_1.default)(value)
|
|
55
|
-
.tz(options === null || options === void 0 ? void 0 : options.timezone)
|
|
56
|
-
.format(dateFormat + ' ' + timeFormat);
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
return (0, dayjs_1.default)(value)
|
|
60
|
-
.tz(options === null || options === void 0 ? void 0 : options.timezone)
|
|
61
|
-
.format(dateFormat);
|
|
62
|
-
}
|
|
127
|
+
return getAttributeDateFormattedValue(attribute, value, options);
|
|
63
128
|
case 'daterange':
|
|
64
|
-
|
|
65
|
-
return null;
|
|
66
|
-
const from = value[0];
|
|
67
|
-
const to = value[1];
|
|
68
|
-
if (!from && !to) {
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
if (from && to) {
|
|
72
|
-
return ((0, dayjs_1.default)(from).tz(options === null || options === void 0 ? void 0 : options.timezone).format(dateFormat) +
|
|
73
|
-
' - ' +
|
|
74
|
-
(0, dayjs_1.default)(to).tz(options === null || options === void 0 ? void 0 : options.timezone).format(dateFormat));
|
|
75
|
-
}
|
|
76
|
-
if (from) {
|
|
77
|
-
return 'After ' + (0, dayjs_1.default)(from).tz(options === null || options === void 0 ? void 0 : options.timezone).format(dateFormat);
|
|
78
|
-
}
|
|
79
|
-
if (to) {
|
|
80
|
-
return 'Before ' + (0, dayjs_1.default)(to).tz(options === null || options === void 0 ? void 0 : options.timezone).format(dateFormat);
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
129
|
+
return getAttributeDateRangeFormattedValue(value, options);
|
|
83
130
|
case 'lookup':
|
|
84
|
-
return value
|
|
131
|
+
return getAttributeLookupFormattedValue(value);
|
|
85
132
|
case 'lookups':
|
|
86
|
-
|
|
87
|
-
if ((options === null || options === void 0 ? void 0 : options.maxCount) && (items === null || items === void 0 ? void 0 : items.length) > options.maxCount) {
|
|
88
|
-
return (items.slice(0, options.maxCount).join(', ') +
|
|
89
|
-
` (+${items.length - options.maxCount})`);
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
return items === null || items === void 0 ? void 0 : items.join(', ');
|
|
93
|
-
}
|
|
133
|
+
return getAttributeLookupsFormattedValue(value, options);
|
|
94
134
|
case 'money':
|
|
95
|
-
return
|
|
96
|
-
style: 'currency',
|
|
97
|
-
currency,
|
|
98
|
-
currencySign,
|
|
99
|
-
currencyDisplay,
|
|
100
|
-
}).format(value);
|
|
135
|
+
return getAttributeMoneyFormattedValue(value, options);
|
|
101
136
|
case 'number':
|
|
102
137
|
return new Intl.NumberFormat(locale).format(value);
|
|
103
138
|
case 'attachment':
|
|
104
|
-
return (
|
|
139
|
+
return getAttributeAttachmentFormattedValue(value);
|
|
105
140
|
default:
|
|
106
141
|
return typeof value === 'object'
|
|
107
142
|
? JSON.stringify(value)
|