|
@@ -129,7 +129,7 @@ const combineModelWithMeta = (model, extraMeta, createFromExtra = false) => comb
|
|
|
|
|
|
// <--- Utilities supporting Repreating Containers --->
|
|
|
|
|
|
-const generateRepeatedGroup = (metaFoG, extraMeta, baseObjWithAllKeys): StringMap[] => {
|
|
|
+const generateRepeatedGroup = (metaFoG, extraMeta, baseObjWithAllKeys): StringMap<any>[] => {
|
|
|
// Calculate the number of repeats
|
|
|
const repeatInAutoMeta = Array.isArray(metaFoG.meta) ? metaFoG.meta.length : 0;
|
|
|
const repeatInExtraMeta = extraMeta['initialRepeat'] || extraMeta['minRepeat'];
|
|
@@ -146,7 +146,7 @@ const generateRepeatedGroup = (metaFoG, extraMeta, baseObjWithAllKeys): StringMa
|
|
|
}
|
|
|
|
|
|
// Get Repeating Container Base Object With All Keys
|
|
|
-const getRCBaseObjectWithAllKeys = (metaFoG, extraMeta, createFromExtra = false): StringMap => {
|
|
|
+const getRCBaseObjectWithAllKeys = (metaFoG, extraMeta, createFromExtra = false): StringMap<any> => {
|
|
|
// If creating from extra, make sure all group members have all keys in both model and meta (as this is a repeating group)
|
|
|
const keysFromModel = isArray(metaFoG.meta) && metaFoG.meta.length ? Object.keys(metaFoG.meta[0].meta) : [];
|
|
|
const keysFromExtraMeta = extraMeta['meta'] && extraMeta['meta'][0] ? Object.keys(extraMeta['meta'][0]) : [];
|
|
@@ -160,63 +160,71 @@ const getRCBaseObjectWithAllKeys = (metaFoG, extraMeta, createFromExtra = false)
|
|
|
// Build Form-Field-Type-Specific Metadata (using the field models in dynaform/models)
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
-const resolveType = (metaFoG: StringMap): string => {
|
|
|
- if (metaFoG.type) {
|
|
|
- return metaFoG.type;
|
|
|
- }
|
|
|
- if (isContainer(metaFoG)) {
|
|
|
- return 'container';
|
|
|
- }
|
|
|
- if (isRepeatingContainer(metaFoG)) {
|
|
|
- return 'repeatingContainer';
|
|
|
- }
|
|
|
- return 'text';
|
|
|
-}
|
|
|
+// MAYBE CHANGE INTO A MODULE SO WE CAN USE CLOSURE BUT ALSO METHODS INSIDE IT
|
|
|
+// More Elegant But Not Urgent
|
|
|
|
|
|
-const buildFieldClassName = (t: string): string => {
|
|
|
- const start = t[0].toUpperCase() + t.slice(1);
|
|
|
- if (start === 'Container' || start === 'RepeatingContainer' || start === 'Heading' || t.slice(-5) === 'Group') {
|
|
|
- return start;
|
|
|
- }
|
|
|
- return start + 'Field';
|
|
|
-};
|
|
|
+const buildModeledFieldGroupMember = metaFog => metaFog; // THIS MAY BREAK THINGS NOW WE'VE MOVED FUNCTION INTO CLOSURE BELOW
|
|
|
|
|
|
-const buildModeledField = metaFoG => {
|
|
|
- const type = resolveType(metaFoG);
|
|
|
- const className = buildFieldClassName(type);
|
|
|
- if (!fmdModels[className]) {
|
|
|
- throw new Error(`No metadata model "${className}" for type "${type}"`);
|
|
|
- }
|
|
|
- return new fmdModels[className](metaFoG);
|
|
|
-};
|
|
|
+const buildFieldSpecificMetaInClosure = (metaG, context) => {
|
|
|
|
|
|
-// Build Form Group Member
|
|
|
-const buildModeledFieldGroupMember = metaFoG => {
|
|
|
- const modeledGroupMember = buildModeledField(metaFoG);
|
|
|
- if (isContainer(metaFoG)) {
|
|
|
- modeledGroupMember.meta = _buildFieldSpecificMeta(modeledGroupMember.meta);
|
|
|
- } else if (isRepeatingContainer(metaFoG)) {
|
|
|
- modeledGroupMember.meta = modeledGroupMember.meta.map(rcMem => ({ ...rcMem, meta: _buildFieldSpecificMeta(rcMem.meta) }));
|
|
|
- modeledGroupMember.__defaultContainer = {
|
|
|
- ...modeledGroupMember.meta[0],
|
|
|
- meta: _buildFieldSpecificMeta(modeledGroupMember.__defaultContainer),
|
|
|
- name: '__defaultContainer',
|
|
|
- button: ''
|
|
|
- };
|
|
|
+ const resolveType = (metaFoG: StringMap<any>): string => {
|
|
|
+ if (metaFoG.type) {
|
|
|
+ return metaFoG.type;
|
|
|
+ }
|
|
|
+ if (isContainer(metaFoG)) {
|
|
|
+ return 'container';
|
|
|
+ }
|
|
|
+ if (isRepeatingContainer(metaFoG)) {
|
|
|
+ return 'repeatingContainer';
|
|
|
+ }
|
|
|
+ return 'text';
|
|
|
}
|
|
|
- return modeledGroupMember;
|
|
|
-};
|
|
|
-
|
|
|
-// Build Form Group
|
|
|
- const buildModeledFieldGroupReducerIteree = (res, metaFoG) => ({ ...res, [metaFoG.name]: buildModeledFieldGroupMember(metaFoG) });
|
|
|
-const _buildFieldSpecificMeta = metaG => isRepeatingContainer(metaG) ?
|
|
|
- metaG.map(rcMem => _buildFieldSpecificMeta(rcMem)) :
|
|
|
- reduce(buildModeledFieldGroupReducerIteree, {}, metaG);
|
|
|
-const buildFieldSpecificMeta = metaG => {
|
|
|
- const withNames = addMissingNames(metaG);
|
|
|
- return _buildFieldSpecificMeta(addMissingNames(metaG));
|
|
|
+
|
|
|
+ const buildFieldClassName = (t: string): string => {
|
|
|
+ const start = t[0].toUpperCase() + t.slice(1);
|
|
|
+ if (start === 'Container' || start === 'RepeatingContainer' || start === 'Heading' || t.slice(-5) === 'Group') {
|
|
|
+ return start;
|
|
|
+ }
|
|
|
+ return start + 'Field';
|
|
|
+ };
|
|
|
+
|
|
|
+ const buildModeledField = (metaFoG) => {
|
|
|
+ const type = resolveType(metaFoG);
|
|
|
+ const className = buildFieldClassName(type);
|
|
|
+ if (!fmdModels[className]) {
|
|
|
+ throw new Error(`No metadata model "${className}" for type "${type}"`);
|
|
|
+ }
|
|
|
+ return new fmdModels[className](metaFoG, context);
|
|
|
+ };
|
|
|
+
|
|
|
+ // Build Form Group Member
|
|
|
+ const buildModeledFieldGroupMember = (metaFoG) => {
|
|
|
+ const modeledGroupMember = buildModeledField(metaFoG);
|
|
|
+ if (isContainer(metaFoG)) {
|
|
|
+ modeledGroupMember.meta = _buildFieldSpecificMeta(modeledGroupMember.meta);
|
|
|
+ } else if (isRepeatingContainer(metaFoG)) {
|
|
|
+ modeledGroupMember.meta = modeledGroupMember.meta.map(rcMem => ({ ...rcMem, meta: _buildFieldSpecificMeta(rcMem.meta) }));
|
|
|
+ modeledGroupMember.__defaultContainer = {
|
|
|
+ ...modeledGroupMember.meta[0],
|
|
|
+ meta: _buildFieldSpecificMeta(modeledGroupMember.__defaultContainer),
|
|
|
+ name: '__defaultContainer',
|
|
|
+ button: ''
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return modeledGroupMember;
|
|
|
+ };
|
|
|
+
|
|
|
+ // Build Form Group
|
|
|
+ const buildModeledFieldGroupReducerIteree = (res, metaFoG) => ({ ...res, [metaFoG.name]: buildModeledFieldGroupMember(metaFoG) });
|
|
|
+ const _buildFieldSpecificMeta = metaG => isRepeatingContainer(metaG) ?
|
|
|
+ metaG.map(rcMem => _buildFieldSpecificMeta(rcMem)) :
|
|
|
+ reduce(buildModeledFieldGroupReducerIteree, {}, metaG);
|
|
|
+ const buildFieldSpecificMeta = metaG => _buildFieldSpecificMeta(addMissingNames(metaG));
|
|
|
+
|
|
|
+ return buildFieldSpecificMeta(metaG);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
// Generate mapping from source attributes
|
|
|
// (used to grab data from model when using METAFIRST form generation)
|
|
@@ -229,7 +237,7 @@ const isAbsPath = path => typeof path === 'string' && path[0] === '/';
|
|
|
const isRootPath = path => path === '/';
|
|
|
const processPath = (parentPath, path) => isAbsPath(path) ? path : `${parentPath}.${path}`;
|
|
|
|
|
|
-const prependParentPathRecursive = (parentPath: string, obj: StringMap) => {
|
|
|
+const prependParentPathRecursive = (parentPath: string, obj: StringMap<any>) => {
|
|
|
return Object.entries(obj)
|
|
|
.map( ([key, mapping] ) => {
|
|
|
let mappingRes;
|
|
@@ -383,7 +391,8 @@ const buildFormGroupFunctionFactory = (fb: FormBuilder): (meta) => FormGroup =>
|
|
|
// Ensure that we have Field-Specific Metadata, not raw Objects
|
|
|
const metaWithNameKeys = addMissingNames(metaG); // <!--- DO WE REALLY HAVE TO CALL addMissingManes again here - it should have been done already?
|
|
|
// MAYBE only run this if first entry isn't right, for reasons of efficiency
|
|
|
- const fieldModeledMeta = addMissingFieldSpecificMeta(metaWithNameKeys);
|
|
|
+ // const fieldModeledMeta = addMissingFieldSpecificMeta(metaWithNameKeys);
|
|
|
+ const fieldModeledMeta = metaWithNameKeys;
|
|
|
return _buildFormGroup(fieldModeledMeta);
|
|
|
};
|
|
|
return buildFormGroup;
|
|
@@ -422,7 +431,7 @@ const insertAfter = (obj, afterKey, key, val = null) => {
|
|
|
};
|
|
|
|
|
|
// Process reordeing instructions recursively
|
|
|
-const _execMetaReorderingInstructions = (metaG: StringMap) => {
|
|
|
+const _execMetaReorderingInstructions = (metaG: StringMap<any>) => {
|
|
|
let reorderedGroup = { ...metaG };
|
|
|
Object.entries(metaG).forEach(([key, metaFoG]) => {
|
|
|
if (metaFoG.before) {
|
|
@@ -437,7 +446,7 @@ const _execMetaReorderingInstructions = (metaG: StringMap) => {
|
|
|
return reorderedGroup;
|
|
|
};
|
|
|
|
|
|
-const execMetaReorderingInstructions = (metaG: StringMap) => {
|
|
|
+const execMetaReorderingInstructions = (metaG: StringMap<any>) => {
|
|
|
// Repeating Containers (which have array meta *at this point*) can't be reordered, but other types of containers can
|
|
|
return Array.isArray(metaG) ? cloneDeep(metaG) : _execMetaReorderingInstructions(cloneDeep(metaG));
|
|
|
};
|
|
@@ -454,6 +463,13 @@ const generateNewModel = (originalModel, updates) => {
|
|
|
|
|
|
const updateObject = (obj, updates, createAdditionalKeys = false) => {
|
|
|
// THIS DOES NOT MUTATE obj, instead returning a new object
|
|
|
+ if (typeof obj !== 'object') {
|
|
|
+ obj = {};
|
|
|
+ }
|
|
|
+ console.log('obj is', obj, typeof obj);
|
|
|
+ if (Object.keys(obj).length === 0) {
|
|
|
+ createAdditionalKeys = true;
|
|
|
+ }
|
|
|
const shallowClone = { ...obj };
|
|
|
Object.entries(updates).forEach(([key, val]) => safeSet(shallowClone, key, val, createAdditionalKeys));
|
|
|
return shallowClone;
|
|
@@ -468,8 +484,9 @@ const safeSet = (obj, key, val, createAdditionalKeys = false) => {
|
|
|
if (val === currentVal) {
|
|
|
return;
|
|
|
}
|
|
|
- if (nullOrScaler(currentVal)) {
|
|
|
- console.log('safeSet nullOrScaler', key, val);
|
|
|
+
|
|
|
+ if (undefinedNullOrScalar(currentVal)) {
|
|
|
+ console.log('safeSet undefinedNullOrScalar', key, val);
|
|
|
obj[key] = val;
|
|
|
} else {
|
|
|
if (Array.isArray(currentVal)) {
|
|
@@ -492,8 +509,8 @@ const safeSet = (obj, key, val, createAdditionalKeys = false) => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-const nullOrScaler = val => {
|
|
|
- if (val === null) { return true; }
|
|
|
+const undefinedNullOrScalar = val => {
|
|
|
+ if (val === null || val === undefined) { return true; }
|
|
|
const t = typeof val;
|
|
|
return t === 'number' || t === 'string' || t === 'boolean';
|
|
|
};
|
|
@@ -557,6 +574,6 @@ const addMissingFieldSpecificMeta = metaG => Object.entries(metaG)
|
|
|
|
|
|
export {
|
|
|
autoMeta, combineModelWithMeta, combineExtraMeta, execMetaReorderingInstructions,
|
|
|
- buildFieldSpecificMeta, extractFieldMappings, buildFormGroupFunctionFactory,
|
|
|
+ buildFieldSpecificMetaInClosure, extractFieldMappings, buildFormGroupFunctionFactory,
|
|
|
generateNewModel
|
|
|
};
|