From 6ada23c99156062bbbbdc5a41b1f37bea27921be Mon Sep 17 00:00:00 2001 From: chrismclarke Date: Fri, 12 Apr 2024 12:47:30 -0700 Subject: [PATCH 1/2] refactor: extract dynamic fields --- packages/data-models/functions.ts | 53 ++++++++++--------- .../processors/flowParser/flowParser.ts | 2 +- src/app/feature/campaign/campaign.service.ts | 2 +- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/packages/data-models/functions.ts b/packages/data-models/functions.ts index 883424d1a5..32222e5039 100644 --- a/packages/data-models/functions.ts +++ b/packages/data-models/functions.ts @@ -18,34 +18,37 @@ const DYNAMIC_STRING_REGEX = /[`!]?@([a-z]+)\.([0-9a-z_]+)([0-9a-z_.]*)/gi; * * Store these references in a separate object so they can be evaluated at runtime */ -export function extractDynamicFields(data: any) { +export function extractDynamicFields(data: any): FlowTypes.IDynamicField | undefined { + // validate input + if (!data) return; + if (typeof data !== "object") return; + + // extract fields let dynamicFields: FlowTypes.IDynamicField = {}; - switch (typeof data) { - case "object": - // simply convert array to object to handle in next case - // ie. ["a","b"] => {0: "a", 1: "b"} - if (Array.isArray(data)) { - data = _arrayToObject(data); - } - if (data !== null) { - // data is a json-like object - Object.entries(data).forEach(([key, value]) => { - // skip processing some columns (remember these can be nested in other objects like parameter_list) - if (!["comments", "_dynamicFields"].includes(key)) { - const nestedDynamic = extractDynamicFields(value); - if (nestedDynamic) { - dynamicFields[key] = nestedDynamic; - } - } - }); - } - break; - case "string": - const dynamicEvaluators = extractDynamicEvaluators(data as string); - if (dynamicEvaluators) { - return dynamicEvaluators; + if (typeof data === "object") { + // simply convert array to object to handle in next case + // ie. ["a","b"] => {0: "a", 1: "b"} + if (Array.isArray(data)) { + data = _arrayToObject(data); + } + // data is a json-like object + Object.entries(data).forEach(([key, value]) => { + // skip processing some columns (remember these can be nested in other objects like parameter_list) + if (!["comments", "_dynamicFields"].includes(key)) { + let nestedDynamic: FlowTypes.IDynamicField | FlowTypes.TemplateRowDynamicEvaluator[] = + undefined; + if (typeof value === "string") { + nestedDynamic = extractDynamicEvaluators(value); + } else { + nestedDynamic = extractDynamicFields(value); + } + if (nestedDynamic) { + dynamicFields[key] = nestedDynamic; + } } + }); } + // nested dynamic fields are managed in the row themselves if (dynamicFields.hasOwnProperty("rows")) { delete dynamicFields["rows"]; diff --git a/packages/scripts/src/commands/app-data/convert/processors/flowParser/flowParser.ts b/packages/scripts/src/commands/app-data/convert/processors/flowParser/flowParser.ts index c0c162a950..e21473fdf3 100644 --- a/packages/scripts/src/commands/app-data/convert/processors/flowParser/flowParser.ts +++ b/packages/scripts/src/commands/app-data/convert/processors/flowParser/flowParser.ts @@ -4,7 +4,7 @@ import { IConverterPaths, IFlowHashmapByType, IParsedWorkbookData } from "../../ import { arrayToHashmap, groupJsonByKey, IContentsEntry } from "../../utils"; import BaseProcessor from "../base"; -const cacheVersion = 20240412.0; +const cacheVersion = 20240412.3; export class FlowParserProcessor extends BaseProcessor { public parsers: { [flowType in FlowTypes.FlowType]: Parsers.DefaultParser } = { diff --git a/src/app/feature/campaign/campaign.service.ts b/src/app/feature/campaign/campaign.service.ts index cfd2fb6d74..41a8136cfe 100644 --- a/src/app/feature/campaign/campaign.service.ts +++ b/src/app/feature/campaign/campaign.service.ts @@ -282,7 +282,7 @@ export class CampaignService extends AsyncServiceBase { // process translations first as these are made with dynamic content in place (e.g. "hello @name") const translatedRow = this.templateTranslateService.translateRow(row as any); // Continue processing full row - translatedRow._dynamicFields = extractDynamicFields(translatedRow) as FlowTypes.IDynamicField; + translatedRow._dynamicFields = extractDynamicFields(translatedRow); const parsedRow = await this.templateVariablesService.evaluatePLHData(translatedRow, { row: translatedRow, templateRowMap: {}, From 0ae0fe1c1c1dda5b89b07db5af42c62345147b1c Mon Sep 17 00:00:00 2001 From: chrismclarke Date: Fri, 12 Apr 2024 12:58:22 -0700 Subject: [PATCH 2/2] chore: code tidying --- packages/data-models/functions.ts | 49 +++++++++++++++---------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/packages/data-models/functions.ts b/packages/data-models/functions.ts index 32222e5039..1d6940e02e 100644 --- a/packages/data-models/functions.ts +++ b/packages/data-models/functions.ts @@ -19,35 +19,34 @@ const DYNAMIC_STRING_REGEX = /[`!]?@([a-z]+)\.([0-9a-z_]+)([0-9a-z_.]*)/gi; * Store these references in a separate object so they can be evaluated at runtime */ export function extractDynamicFields(data: any): FlowTypes.IDynamicField | undefined { - // validate input - if (!data) return; - if (typeof data !== "object") return; + // only extract from string, array or nested json object types + if (!data || typeof data !== "object") return; // extract fields let dynamicFields: FlowTypes.IDynamicField = {}; - if (typeof data === "object") { - // simply convert array to object to handle in next case - // ie. ["a","b"] => {0: "a", 1: "b"} - if (Array.isArray(data)) { - data = _arrayToObject(data); - } - // data is a json-like object - Object.entries(data).forEach(([key, value]) => { - // skip processing some columns (remember these can be nested in other objects like parameter_list) - if (!["comments", "_dynamicFields"].includes(key)) { - let nestedDynamic: FlowTypes.IDynamicField | FlowTypes.TemplateRowDynamicEvaluator[] = - undefined; - if (typeof value === "string") { - nestedDynamic = extractDynamicEvaluators(value); - } else { - nestedDynamic = extractDynamicFields(value); - } - if (nestedDynamic) { - dynamicFields[key] = nestedDynamic; - } - } - }); + // simply convert array to object to handle in next case + // ie. ["a","b"] => {0: "a", 1: "b"} + if (Array.isArray(data)) { + data = _arrayToObject(data); } + // data is a json-like object + Object.entries(data).forEach(([key, value]) => { + // skip processing some columns (remember these can be nested in other objects like parameter_list) + if (!["comments", "_dynamicFields"].includes(key)) { + let nestedDynamic: FlowTypes.IDynamicField | FlowTypes.TemplateRowDynamicEvaluator[] = + undefined; + if (typeof value === "string") { + // extract evaluators from string expression + nestedDynamic = extractDynamicEvaluators(value); + } else { + // extract evaluators from deeper nested objects or arrays + nestedDynamic = extractDynamicFields(value); + } + if (nestedDynamic) { + dynamicFields[key] = nestedDynamic; + } + } + }); // nested dynamic fields are managed in the row themselves if (dynamicFields.hasOwnProperty("rows")) {