|
@@ -15,6 +15,7 @@
|
|
* Variable names
|
|
* Variable names
|
|
* --------------
|
|
* --------------
|
|
* metaF = metadata for Field
|
|
* metaF = metadata for Field
|
|
|
|
+ * metaRF = metadata for Repeating Field
|
|
* metaG = metadata for Group (possibly nested)
|
|
* metaG = metadata for Group (possibly nested)
|
|
* metaFoG = metadata for Field or Group
|
|
* metaFoG = metadata for Field or Group
|
|
* rcMem = Repeating Container member
|
|
* rcMem = Repeating Container member
|
|
@@ -25,6 +26,7 @@
|
|
import { FormBuilder, FormGroup, FormArray, FormControl, AbstractControl, AbstractControlOptions } from '@angular/forms';
|
|
import { FormBuilder, FormGroup, FormArray, FormControl, AbstractControl, AbstractControlOptions } from '@angular/forms';
|
|
import { cloneDeep, omit, reduce } from 'lodash/fp';
|
|
import { cloneDeep, omit, reduce } from 'lodash/fp';
|
|
import * as fmdModels from '../models/field.model';
|
|
import * as fmdModels from '../models/field.model';
|
|
|
|
+import { meta } from '@mock/testfields.v15';
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
@@ -75,6 +77,22 @@ const combineExtraMeta = (metaG, extraMeta, createFromExtra = false, containerSe
|
|
const metaFoG = metaG[key] || {};
|
|
const metaFoG = metaG[key] || {};
|
|
const seed = isCon ? {} : containerSeed; // Container's don't seed themselves, only their children
|
|
const seed = isCon ? {} : containerSeed; // Container's don't seed themselves, only their children
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ console.log('******************* BEFORE MODELLING *******************');
|
|
|
|
+ console.log(val);
|
|
|
|
+ console.log('IS REPEATING', isRepeating(val));
|
|
|
|
+ console.log('HAS META', hasMeta(val));
|
|
|
|
+ console.log('IS ARRAY', Array.isArray(val.meta));
|
|
|
|
+ console.log('MEMBER 1 DEFINED', !!val.meta[0]);
|
|
|
|
+ console.log('OBJECT VALUES .........', Object.values(val.meta[0]));
|
|
|
|
+ console.log('MEMBER 1 1st entry .........', Object.values(val.meta[0])[0]);
|
|
|
|
+ console.log('MEMBER 1 1st entry is SCALAR', isScalar(Object.values(val.meta[0])));
|
|
|
|
+ */
|
|
|
|
+ /*
|
|
|
|
+ console.log('IS REP Field', isRepeatingField(val));
|
|
|
|
+ console.log('IS REP Container', isRepeatingContainer(val));
|
|
|
|
+ console.log('IS ORD Container', isContainer(val));
|
|
|
|
+ */
|
|
if (isRepeatingContainer(val))
|
|
if (isRepeatingContainer(val))
|
|
{
|
|
{
|
|
// We've got a Repeating Container
|
|
// We've got a Repeating Container
|
|
@@ -103,23 +121,9 @@ const combineExtraMeta = (metaG, extraMeta, createFromExtra = false, containerSe
|
|
}
|
|
}
|
|
else // ----------------------------------------------
|
|
else // ----------------------------------------------
|
|
{
|
|
{
|
|
- // We've got a Container or a Field
|
|
|
|
- /*
|
|
|
|
- const extra = isCon ?
|
|
|
|
- {
|
|
|
|
- ...val,
|
|
|
|
- meta: combineExtraMeta( // RECURSION
|
|
|
|
- metaFoG.meta || {},
|
|
|
|
- val['meta'],
|
|
|
|
- createFromExtra,
|
|
|
|
- val['seed'] || containerSeed // Inherit seeded data if this group's seed isn't set
|
|
|
|
- )
|
|
|
|
- }
|
|
|
|
- :
|
|
|
|
- isRepeatingField(val) ? [ val, val, val ] : val; // <----------! HERE WE BE WORKING!
|
|
|
|
- */
|
|
|
|
let extra: StringMap<any>;
|
|
let extra: StringMap<any>;
|
|
if (isCon) {
|
|
if (isCon) {
|
|
|
|
+ // We've got a container
|
|
extra = {
|
|
extra = {
|
|
...val,
|
|
...val,
|
|
meta: combineExtraMeta( // RECURSION
|
|
meta: combineExtraMeta( // RECURSION
|
|
@@ -132,12 +136,19 @@ const combineExtraMeta = (metaG, extraMeta, createFromExtra = false, containerSe
|
|
}
|
|
}
|
|
else // ----------------------------------------------
|
|
else // ----------------------------------------------
|
|
{
|
|
{
|
|
- if (isRepeatingField(val)) {
|
|
|
|
|
|
+ if (val.minRepeat || val.maxRepeat || val.initialRepeat) {
|
|
|
|
+ // We've got a repeating field
|
|
|
|
+ const metaForFieldToRepeat = {
|
|
|
|
+ ...containerSeed,
|
|
|
|
+ ...omit(['seed', 'minRepeat', 'maxRepeat', 'initialRepeat', 'showAddControl', 'showDeleteControl'], val as StringMap<any>)
|
|
|
|
+ };
|
|
|
|
+ delete val.type;
|
|
extra = {
|
|
extra = {
|
|
...val,
|
|
...val,
|
|
- meta: [ val, val, val ] // <----------! HERE WE BE WORKING!
|
|
|
|
|
|
+ meta: Array.from(Array(val.initialRepeat || 1).keys()).map((f, i) => ({ ...metaForFieldToRepeat, label: `${val.label || key} ${i + 1}` }))
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
|
|
+ // We've got a standard field
|
|
extra = val;
|
|
extra = val;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -195,6 +206,9 @@ const buildFieldSpecificMetaInClosure = (metaG, context) => {
|
|
if (metaFoG.type) {
|
|
if (metaFoG.type) {
|
|
return metaFoG.type;
|
|
return metaFoG.type;
|
|
}
|
|
}
|
|
|
|
+ if (isRepeatingField(metaFoG)) {
|
|
|
|
+ return 'repeatingField';
|
|
|
|
+ }
|
|
if (isContainer(metaFoG)) {
|
|
if (isContainer(metaFoG)) {
|
|
return 'container';
|
|
return 'container';
|
|
}
|
|
}
|
|
@@ -206,7 +220,7 @@ const buildFieldSpecificMetaInClosure = (metaG, context) => {
|
|
|
|
|
|
const buildFieldClassName = (t: string): string => {
|
|
const buildFieldClassName = (t: string): string => {
|
|
const start = t[0].toUpperCase() + t.slice(1);
|
|
const start = t[0].toUpperCase() + t.slice(1);
|
|
- if (start === 'Container' || start === 'RepeatingContainer' || start === 'Heading' || t.slice(-5) === 'Group') {
|
|
|
|
|
|
+ if (['RepeatingField', 'Container', 'RepeatingContainer', 'Heading'].includes(start) || t.slice(-5) === 'Group') {
|
|
return start;
|
|
return start;
|
|
}
|
|
}
|
|
return start + 'Field';
|
|
return start + 'Field';
|
|
@@ -224,9 +238,19 @@ const buildFieldSpecificMetaInClosure = (metaG, context) => {
|
|
// Build Form Group Member
|
|
// Build Form Group Member
|
|
const buildModeledFieldGroupMember = (metaFoG) => {
|
|
const buildModeledFieldGroupMember = (metaFoG) => {
|
|
const modeledGroupMember = buildModeledField(metaFoG);
|
|
const modeledGroupMember = buildModeledField(metaFoG);
|
|
- if (isContainer(metaFoG)) {
|
|
|
|
|
|
+
|
|
|
|
+ console.log('------------- DEBUGGING -------------');
|
|
|
|
+ console.log(modeledGroupMember);
|
|
|
|
+ console.log('IS REP Field', isRepeatingField(modeledGroupMember));
|
|
|
|
+ console.log('IS REP Container', isRepeatingContainer(modeledGroupMember));
|
|
|
|
+ console.log('IS ORD Container', isContainer(modeledGroupMember));
|
|
|
|
+ console.log(modeledGroupMember);
|
|
|
|
+
|
|
|
|
+ if (isRepeatingField(modeledGroupMember)) {
|
|
|
|
+ modeledGroupMember.meta = modeledGroupMember.meta.map(metaF => buildModeledField(metaF));
|
|
|
|
+ } else if (isContainer(modeledGroupMember)) {
|
|
modeledGroupMember.meta = _buildFieldSpecificMeta(modeledGroupMember.meta);
|
|
modeledGroupMember.meta = _buildFieldSpecificMeta(modeledGroupMember.meta);
|
|
- } else if (isRepeatingContainer(metaFoG)) {
|
|
|
|
|
|
+ } else if (isRepeatingContainer(modeledGroupMember)) {
|
|
modeledGroupMember.meta = modeledGroupMember.meta.map(rcMem => ({ ...rcMem, meta: _buildFieldSpecificMeta(rcMem.meta) }));
|
|
modeledGroupMember.meta = modeledGroupMember.meta.map(rcMem => ({ ...rcMem, meta: _buildFieldSpecificMeta(rcMem.meta) }));
|
|
modeledGroupMember.__containerTemplate = {
|
|
modeledGroupMember.__containerTemplate = {
|
|
...modeledGroupMember.meta[0],
|
|
...modeledGroupMember.meta[0],
|
|
@@ -245,7 +269,10 @@ const buildFieldSpecificMetaInClosure = (metaG, context) => {
|
|
reduce(buildModeledFieldGroupReducerIteree, {}, metaG);
|
|
reduce(buildModeledFieldGroupReducerIteree, {}, metaG);
|
|
const buildFieldSpecificMeta = metaG => _buildFieldSpecificMeta(addMissingNames(metaG));
|
|
const buildFieldSpecificMeta = metaG => _buildFieldSpecificMeta(addMissingNames(metaG));
|
|
|
|
|
|
- return buildFieldSpecificMeta(metaG);
|
|
|
|
|
|
+ // DEBUGGING
|
|
|
|
+ console.log('buildFieldSpecificMetaInClosure', metaG, context);
|
|
|
|
+
|
|
|
|
+ return buildFieldSpecificMeta(metaG); // RUN CODE
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -291,7 +318,7 @@ const prependParentPathRecursive = (parentPath: string, obj: StringMap<any>) =>
|
|
|
|
|
|
const _extractFieldMapping = ( [key, metaFoG] ) => {
|
|
const _extractFieldMapping = ( [key, metaFoG] ) => {
|
|
let source;
|
|
let source;
|
|
- if (isGroup(metaFoG)) {
|
|
|
|
|
|
+ if (hasMeta(metaFoG)) {
|
|
if (Array.isArray(metaFoG.source)) {
|
|
if (Array.isArray(metaFoG.source)) {
|
|
source = extractFieldMappings(metaFoG.meta);
|
|
source = extractFieldMappings(metaFoG.meta);
|
|
source.__ = metaFoG.source; // Store the functional mapping (including function executed later to provide container's data)
|
|
source.__ = metaFoG.source; // Store the functional mapping (including function executed later to provide container's data)
|
|
@@ -379,7 +406,6 @@ const extractFieldMappings = (metaG, parentPath = '') => Object.entries(metaG)
|
|
// returns a function to build FormGroups containing FormControls, FormArrays and other FormGroups
|
|
// returns a function to build FormGroups containing FormControls, FormArrays and other FormGroups
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
-
|
|
|
|
// TODO: In progress: elegantly adding validators at FormGroup and FormArray levels
|
|
// TODO: In progress: elegantly adding validators at FormGroup and FormArray levels
|
|
// Working, but code needs a rework
|
|
// Working, but code needs a rework
|
|
|
|
|
|
@@ -399,9 +425,9 @@ const buildFormGroupFunctionFactory = (fb: FormBuilder): (meta) => FormGroup =>
|
|
if (!metaFoG || !(metaFoG.validators || metaFoG.asyncValidators)) {
|
|
if (!metaFoG || !(metaFoG.validators || metaFoG.asyncValidators)) {
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
- // console.log(metaFoG);
|
|
|
|
|
|
+ console.log(metaFoG);
|
|
const res = buildValidators(metaFoG);
|
|
const res = buildValidators(metaFoG);
|
|
- // console.log(res);
|
|
|
|
|
|
+ console.log(res);
|
|
return res;
|
|
return res;
|
|
}
|
|
}
|
|
const buildFormControl = metaF => new FormControl(buildControlState(metaF), buildValidators(metaF));
|
|
const buildFormControl = metaF => new FormControl(buildControlState(metaF), buildValidators(metaF));
|
|
@@ -416,7 +442,7 @@ const buildFormGroupFunctionFactory = (fb: FormBuilder): (meta) => FormGroup =>
|
|
|
|
|
|
// Build Form Group Member
|
|
// Build Form Group Member
|
|
// Builds a FormControl, FormArray or another FormGroup - which in turn can contain any of these
|
|
// Builds a FormControl, FormArray or another FormGroup - which in turn can contain any of these
|
|
- const buildFormGroupMember = metaFoG => isGroup(metaFoG) ?
|
|
|
|
|
|
+ const buildFormGroupMember = metaFoG => hasMeta(metaFoG) ?
|
|
(isArray(metaFoG.meta) ? buildFormArray(metaFoG.meta, metaFoG) : _buildFormGroup(metaFoG.meta, metaFoG)) : // TODO: STINKY! REWORK with 1 param
|
|
(isArray(metaFoG.meta) ? buildFormArray(metaFoG.meta, metaFoG) : _buildFormGroup(metaFoG.meta, metaFoG)) : // TODO: STINKY! REWORK with 1 param
|
|
buildFormControl(metaFoG);
|
|
buildFormControl(metaFoG);
|
|
|
|
|
|
@@ -688,25 +714,46 @@ const undefinedNullOrScalar = val => {
|
|
// Add Property to object, returning updated object
|
|
// Add Property to object, returning updated object
|
|
const addProp = (obj, key, val) => { obj[key] = val; return obj; };
|
|
const addProp = (obj, key, val) => { obj[key] = val; return obj; };
|
|
|
|
|
|
|
|
+// Has Meta
|
|
|
|
+// Helper function to distinguish a group from a simple field - where a group is a container os repeating container, or repeating field * AFTER* modelling
|
|
|
|
+const hasMeta = (metaFoG): boolean => !!metaFoG.meta;
|
|
|
|
+
|
|
|
|
+// Is Repeating
|
|
|
|
+const isRepeating = (metaFoG): boolean => !!(metaFoG.minRepeat || metaFoG.maxRepeat || metaFoG.initialRepeat);
|
|
|
|
+
|
|
// Is Repeating Field
|
|
// Is Repeating Field
|
|
// Helper function to distinguish a repeating field (a field that can be repeated 1...N times)
|
|
// Helper function to distinguish a repeating field (a field that can be repeated 1...N times)
|
|
-const isRepeatingField = (metaF): boolean => metaF.minRepeat || metaF.maxRepeat || metaF.initialRepeat;
|
|
|
|
-
|
|
|
|
-// Is Group
|
|
|
|
-// Helper function to distinguish group from field
|
|
|
|
-const isGroup = (metaFoG): boolean => !!metaFoG.meta;
|
|
|
|
|
|
+const isRepeatingField = (metaRF): boolean => metaRF.type && metaRF.type.toLowerCase() === 'repeatingfield'
|
|
|
|
+ || (
|
|
|
|
+ !metaRF.type
|
|
|
|
+ && isRepeating(metaRF)
|
|
|
|
+ && (
|
|
|
|
+ !hasMeta(metaRF) || hasMeta (metaRF)
|
|
|
|
+ && Array.isArray(metaRF.meta)
|
|
|
|
+ && metaRF.meta[0]
|
|
|
|
+ && isScalar(Object.values(metaRF.meta[0])[0])
|
|
|
|
+ )
|
|
|
|
+ );
|
|
|
|
|
|
// Is Container
|
|
// Is Container
|
|
// Helper function to distinguish container group (a group of child fields)
|
|
// Helper function to distinguish container group (a group of child fields)
|
|
-const isContainer = (metaFoG): boolean => isGroup(metaFoG)
|
|
|
|
- && !Array.isArray(metaFoG.meta)
|
|
|
|
- && (!metaFoG.type || metaFoG.type.toLowerCase() === 'container');
|
|
|
|
|
|
+const isContainer = (metaFoG): boolean => metaFoG.type && metaFoG.type.toLowerCase() === 'container'
|
|
|
|
+ || (
|
|
|
|
+ !metaFoG.type
|
|
|
|
+ && hasMeta(metaFoG)
|
|
|
|
+ && !Array.isArray(metaFoG.meta)
|
|
|
|
+ );
|
|
|
|
|
|
// Is Repeating Container
|
|
// Is Repeating Container
|
|
// Helper function to distinguish a repeating container group (a group of child fields that can be repeated 1...N times)
|
|
// Helper function to distinguish a repeating container group (a group of child fields that can be repeated 1...N times)
|
|
-const isRepeatingContainer = (metaFoG): boolean => isGroup(metaFoG)
|
|
|
|
- && Array.isArray(metaFoG.meta)
|
|
|
|
- && (!metaFoG.type || metaFoG.type.toLowerCase() === 'repeatingContainer');
|
|
|
|
|
|
+const isRepeatingContainer = (metaFoG): boolean => metaFoG.type && metaFoG.type.toLowerCase() === 'repeatingcontainer'
|
|
|
|
+ || (
|
|
|
|
+ !metaFoG.type
|
|
|
|
+ && isRepeating(metaFoG)
|
|
|
|
+ && hasMeta(metaFoG)
|
|
|
|
+ && Array.isArray(metaFoG.meta) && metaFoG.meta[0]
|
|
|
|
+ && !isScalar(Object.values(metaFoG.meta[0])[0])
|
|
|
|
+ );
|
|
|
|
|
|
// Add Missing Names
|
|
// Add Missing Names
|
|
// Helper function to add any missing 'name' properties to Fields and Groups using property's key, recursively
|
|
// Helper function to add any missing 'name' properties to Fields and Groups using property's key, recursively
|
|
@@ -714,7 +761,7 @@ const isRepeatingContainer = (metaFoG): boolean => isGroup(metaFoG)
|
|
const addNameIfMissing = (metaFoG, key) => metaFoG.name ? metaFoG : addProp(metaFoG, 'name', key);
|
|
const addNameIfMissing = (metaFoG, key) => metaFoG.name ? metaFoG : addProp(metaFoG, 'name', key);
|
|
const addNameToSelfAndChildren = ( [key, metaFoG] ) => {
|
|
const addNameToSelfAndChildren = ( [key, metaFoG] ) => {
|
|
metaFoG = addNameIfMissing(metaFoG, key);
|
|
metaFoG = addNameIfMissing(metaFoG, key);
|
|
- if (isGroup(metaFoG) && !isRepeatingContainer(metaFoG)) {
|
|
|
|
|
|
+ if (hasMeta(metaFoG) && !isRepeatingContainer(metaFoG)) {
|
|
metaFoG.meta = isArray(metaFoG.meta) ? Object.values(addMissingNames(metaFoG.meta)) : addMissingNames(metaFoG.meta); // Recursion
|
|
metaFoG.meta = isArray(metaFoG.meta) ? Object.values(addMissingNames(metaFoG.meta)) : addMissingNames(metaFoG.meta); // Recursion
|
|
}
|
|
}
|
|
return [key, metaFoG];
|
|
return [key, metaFoG];
|