|
@@ -24,16 +24,6 @@ import { FormBuilder, FormGroup, FormArray, FormControl, AbstractControlOptions
|
|
import { reduce, cloneDeep } from 'lodash/fp';
|
|
import { reduce, cloneDeep } from 'lodash/fp';
|
|
import * as fmdModels from '../models/field.model';
|
|
import * as fmdModels from '../models/field.model';
|
|
|
|
|
|
-// REMINDER: Import this directly from @angular/forms when we upgrade to Angular 6
|
|
|
|
-// While we're still on Angular 5 just declare it
|
|
|
|
-/*
|
|
|
|
-interface AbstractControlOptions {
|
|
|
|
- validators?: ValidatorFn | ValidatorFn[] | null;
|
|
|
|
- asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null;
|
|
|
|
- updateOn?: 'change' | 'blur' | 'submit';
|
|
|
|
-}
|
|
|
|
-*/
|
|
|
|
-
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
// AutoMeta: Generate Automatic Metadata from a model
|
|
// AutoMeta: Generate Automatic Metadata from a model
|
|
@@ -61,19 +51,56 @@ const autoMeta = model => Object.entries(model)
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
-// Combine automatically generated metadata with overrides
|
|
|
|
|
|
+// Combine automatically generated metadata with overrides (extraMeta)
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
// containerSeed = Metadata from container which seeds all contained fields
|
|
// containerSeed = Metadata from container which seeds all contained fields
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
const combineMetaForField = (metaF, containerSeed, extraMetaF) => ({ ...metaF, ...containerSeed, ...extraMetaF });
|
|
const combineMetaForField = (metaF, containerSeed, extraMetaF) => ({ ...metaF, ...containerSeed, ...extraMetaF });
|
|
const combineExtraMeta = (metaG, extraMeta, createFromExtra = false, containerSeed = {}) => {
|
|
const combineExtraMeta = (metaG, extraMeta, createFromExtra = false, containerSeed = {}) => {
|
|
const combinedMeta = {};
|
|
const combinedMeta = {};
|
|
Object.entries(extraMeta).forEach(([key, val]) => {
|
|
Object.entries(extraMeta).forEach(([key, val]) => {
|
|
if (typeof metaG[key] === 'object' || createFromExtra) { // If the key exists (in the model) OR we're creating from metadata
|
|
if (typeof metaG[key] === 'object' || createFromExtra) { // If the key exists (in the model) OR we're creating from metadata
|
|
const isCon = isContainer(val);
|
|
const isCon = isContainer(val);
|
|
|
|
+ const isRepeating = isRepeatingContainer(val);
|
|
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
|
|
|
|
+
|
|
|
|
+ // ---------------------------------------
|
|
|
|
+
|
|
|
|
+ // OK, so we need to... expand repeating containers here
|
|
|
|
+ if (isRepeating) {
|
|
|
|
+ const repeatInAutoMeta = Array.isArray(metaG[key].meta) ? metaG[key].meta.length : 0;
|
|
|
|
+ const repeatInExtraMeta = val['initialRepeat'] || val['minRepeat'];
|
|
|
|
+ const repeat = Math.max(repeatInAutoMeta, repeatInExtraMeta);
|
|
|
|
+
|
|
|
|
+ // Extend array from model (if any) to length repeat, apdding with empty values
|
|
|
|
+ const repeatingGroup = repeatInAutoMeta ?
|
|
|
|
+ [ ...metaG[key].meta, ...Array(repeat - repeatInAutoMeta).fill(metaG[key].meta[0]) ] // RETHING DEFAULT HERE - its first val from data repeated
|
|
|
|
+ :
|
|
|
|
+ arrayMemberAutoName(repeat).fill(val['meta'][0]);
|
|
|
|
+
|
|
|
|
+ if (Array.isArray(metaG[key])) {
|
|
|
|
+ combinedMeta[key] = combineExtraMeta(metaG[key], val['meta'][0], createFromExtra, val['seed']);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // ---------------------------------------
|
|
|
|
+ // Maybe else?
|
|
|
|
+
|
|
const extra = isCon ?
|
|
const extra = isCon ?
|
|
{
|
|
{
|
|
...val,
|
|
...val,
|
|
@@ -424,6 +451,12 @@ const isGroup = (metaFoG): boolean => !!metaFoG.meta;
|
|
// 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) && (!metaFoG.type || metaFoG.type.toLowerCase() === 'container');
|
|
const isContainer = (metaFoG): boolean => isGroup(metaFoG) && (!metaFoG.type || metaFoG.type.toLowerCase() === 'container');
|
|
|
|
|
|
|
|
+// Is Repeating Container
|
|
|
|
+// Helper function to distinguish a repeating container group (a group of child fields that can be repeated 1...N times)
|
|
|
|
+const isRepeatingContainer = (metaFoG): boolean => isContainer(metaFoG)
|
|
|
|
+ && Array.isArray(metaFoG.meta)
|
|
|
|
+ && !!(metaFoG.minRepeat || metaFoG.maxRepeat || metaFoG.initialRepeat);
|
|
|
|
+
|
|
// 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
|
|
const addNameIfMissing = (metaFoG, key) => metaFoG.name ? metaFoG : addProp(metaFoG, 'name', key);
|
|
const addNameIfMissing = (metaFoG, key) => metaFoG.name ? metaFoG : addProp(metaFoG, 'name', key);
|