From a341c694859c038321beafd282146ae3e6cfe72f Mon Sep 17 00:00:00 2001 From: Johnny McQuade Date: Mon, 27 Jan 2025 12:33:53 +0000 Subject: [PATCH 1/5] hotfix: handle action param with self-reference concatenation --- .../instance/template-action.service.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/app/shared/components/template/services/instance/template-action.service.ts b/src/app/shared/components/template/services/instance/template-action.service.ts index 3725ad000..5ee0954fa 100644 --- a/src/app/shared/components/template/services/instance/template-action.service.ts +++ b/src/app/shared/components/template/services/instance/template-action.service.ts @@ -217,12 +217,22 @@ export class TemplateActionService extends SyncServiceBase { // Update action.params if (action.params) { action.params = Object.fromEntries( - Object.entries(action.params).map(([key, value]) => { - if (typeof value === "string" && value.startsWith("this.")) { - const selfField = value.split(".")[1]; - value = this.container?.templateRowMap[action._triggeredBy?._nested_name]?.[selfField]; + Object.entries(action.params).map(([key, paramValue]) => { + if (typeof paramValue === "string" && paramValue.includes("+this.value")) { + const thisValue = + this.container?.templateRowMap[action._triggeredBy?._nested_name]?.value; + paramValue = paramValue.replace(" + this.value", `${thisValue}`); } - return [key, value]; + if ( + typeof paramValue === "string" && + paramValue.startsWith("this.") && + !paramValue.startsWith("this.item") + ) { + const selfField = paramValue.split(".")[1]; + paramValue = + this.container?.templateRowMap[action._triggeredBy?._nested_name]?.[selfField]; + } + return [key, paramValue]; }) ); } From d23bd6ee6fad0a2189a450ae55e296595125bdf1 Mon Sep 17 00:00:00 2001 From: Johnny McQuade Date: Mon, 27 Jan 2025 13:01:56 +0000 Subject: [PATCH 2/5] chore: code tidy --- .../instance/template-action.service.ts | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/app/shared/components/template/services/instance/template-action.service.ts b/src/app/shared/components/template/services/instance/template-action.service.ts index 5ee0954fa..0fdd3c519 100644 --- a/src/app/shared/components/template/services/instance/template-action.service.ts +++ b/src/app/shared/components/template/services/instance/template-action.service.ts @@ -218,19 +218,18 @@ export class TemplateActionService extends SyncServiceBase { if (action.params) { action.params = Object.fromEntries( Object.entries(action.params).map(([key, paramValue]) => { - if (typeof paramValue === "string" && paramValue.includes("+this.value")) { - const thisValue = - this.container?.templateRowMap[action._triggeredBy?._nested_name]?.value; - paramValue = paramValue.replace(" + this.value", `${thisValue}`); - } - if ( - typeof paramValue === "string" && - paramValue.startsWith("this.") && - !paramValue.startsWith("this.item") - ) { - const selfField = paramValue.split(".")[1]; - paramValue = - this.container?.templateRowMap[action._triggeredBy?._nested_name]?.[selfField]; + // @item is temporarily replaced with `this.item` to avoid parsing without context – do not touch here + if (typeof paramValue === "string" && !paramValue.startsWith("this.item")) { + if (paramValue.includes("+this.value")) { + const thisValue = + this.container?.templateRowMap[action._triggeredBy?._nested_name]?.value; + paramValue = paramValue.replace(" + this.value", `${thisValue}`); + } + if (typeof paramValue === "string" && paramValue.startsWith("this.")) { + const selfField = paramValue.split(".")[1]; + paramValue = + this.container?.templateRowMap[action._triggeredBy?._nested_name]?.[selfField]; + } } return [key, paramValue]; }) From 9d1acf32ec53dc5bd1c56e37412156d1822d78b8 Mon Sep 17 00:00:00 2001 From: Johnny McQuade Date: Mon, 27 Jan 2025 13:20:05 +0000 Subject: [PATCH 3/5] fix: handle cases of this.item --- .../services/instance/template-action.service.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/app/shared/components/template/services/instance/template-action.service.ts b/src/app/shared/components/template/services/instance/template-action.service.ts index c762ad6a0..3c386c1e3 100644 --- a/src/app/shared/components/template/services/instance/template-action.service.ts +++ b/src/app/shared/components/template/services/instance/template-action.service.ts @@ -218,15 +218,19 @@ export class TemplateActionService extends SyncServiceBase { if (action.params) { action.params = Object.fromEntries( Object.entries(action.params).map(([key, paramValue]) => { - // @item is temporarily replaced with `this.item` to avoid parsing without context – do not touch here - if (typeof paramValue === "string" && !paramValue.startsWith("this.item")) { + if (typeof paramValue === "string") { // HACK: handle cases of intended concatenation of self-reference value if (paramValue.includes("+this.value")) { const thisValue = this.container?.templateRowMap[action._triggeredBy?._nested_name]?.value; paramValue = paramValue.replace("+this.value", `${thisValue}`); } - if (typeof paramValue === "string" && paramValue.startsWith("this.")) { + if ( + typeof paramValue === "string" && + paramValue.startsWith("this.") && + // @item is temporarily replaced with `this.item` to avoid parsing without context – do not touch here + !paramValue.startsWith("this.item") + ) { const selfField = paramValue.split(".")[1]; paramValue = this.container?.templateRowMap[action._triggeredBy?._nested_name]?.[selfField]; From 2e23bc1b2eb9bf5e8705aeaf817798eb11dfa355 Mon Sep 17 00:00:00 2001 From: Johnny McQuade Date: Wed, 29 Jan 2025 14:20:22 +0000 Subject: [PATCH 4/5] chore: add explanatory comment --- .../template/services/instance/template-action.service.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/shared/components/template/services/instance/template-action.service.ts b/src/app/shared/components/template/services/instance/template-action.service.ts index 3cd480884..996ca422b 100644 --- a/src/app/shared/components/template/services/instance/template-action.service.ts +++ b/src/app/shared/components/template/services/instance/template-action.service.ts @@ -350,6 +350,10 @@ export class TemplateActionService extends SyncServiceBase { if (value === "this.value") { action.params[key] = currentValue; } + // HACK: workaround for a specific use case of concatenating the current value + // within a param, see https://github.com/IDEMSInternational/open-app-builder/pull/2750 + // TODO: support general data evaluation and remove this workaround + // See https://github.com/IDEMSInternational/open-app-builder/pull/2753 if (typeof value === "string" && value.includes("+this.value")) { action.params[key] = value.replace("+this.value", `${currentValue}`); } From 3bb2c316b8217d103675754d5fe04cf4397d1d8d Mon Sep 17 00:00:00 2001 From: chrismclarke Date: Wed, 29 Jan 2025 11:06:18 -0800 Subject: [PATCH 5/5] chore: code tidying --- .../instance/template-action.service.spec.ts | 16 ++++++++-- .../instance/template-action.service.ts | 29 +++++++++---------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/app/shared/components/template/services/instance/template-action.service.spec.ts b/src/app/shared/components/template/services/instance/template-action.service.spec.ts index 9398bf0d4..42f948cbb 100644 --- a/src/app/shared/components/template/services/instance/template-action.service.spec.ts +++ b/src/app/shared/components/template/services/instance/template-action.service.spec.ts @@ -84,7 +84,7 @@ describe("TemplateActionService", () => { expect(service.container.templateRowMap.mock_row_1.value).toEqual("updated"); }); - it("Uses updated args when successive actions change same variable", async () => { + it("Uses latest value for `this.value` arg", async () => { const _triggeredBy = { _nested_name: "mock_row_1", name: "mock_row_1", type: "" }; await service.handleActions( [ @@ -98,9 +98,21 @@ describe("TemplateActionService", () => { _triggeredBy ); expect(service.container.templateRowMap.mock_row_2.value).toEqual("updated"); + // also include test case of concatenated expression + await service.handleActions( + [ + { + trigger: "click", + action_id: "set_local", + args: ["mock_row_2", "prefix_{this.value}"], + }, + ], + _triggeredBy + ); + expect(service.container.templateRowMap.mock_row_2.value).toEqual("prefix_updated"); }); - it("Uses updated params when successive actions change same variable", async () => { + it("Uses latest value for `this.value` param", async () => { const _triggeredBy = { _nested_name: "mock_row_1", name: "mock_row_1", type: "" }; await service.handleActions( [ diff --git a/src/app/shared/components/template/services/instance/template-action.service.ts b/src/app/shared/components/template/services/instance/template-action.service.ts index 996ca422b..d9b28f3e2 100644 --- a/src/app/shared/components/template/services/instance/template-action.service.ts +++ b/src/app/shared/components/template/services/instance/template-action.service.ts @@ -337,26 +337,25 @@ export class TemplateActionService extends SyncServiceBase { ): FlowTypes.TemplateRowAction { // Update action.args and action.params const currentValue = this.container?.templateRowMap?.[action._triggeredBy?._nested_name]?.value; - if (action.args) { - action.args = action.args.map((arg) => { - if (arg === "this.value") { + // define a replacer that preserves type if `this.value` specified, replacing as string for + // other expressions `@local.some_field_{this.value}` + function replaceReference(v: any) { + if (typeof v === "string") { + if (v === "this.value") { return currentValue; } - return arg; - }); + if (v.includes("{this.value}")) { + return v.replace("{this.value}", currentValue); + } + } + return v; + } + if (action.args) { + action.args = action.args.map((arg) => replaceReference(arg)); } if (action.params) { for (const [key, value] of Object.entries(action.params)) { - if (value === "this.value") { - action.params[key] = currentValue; - } - // HACK: workaround for a specific use case of concatenating the current value - // within a param, see https://github.com/IDEMSInternational/open-app-builder/pull/2750 - // TODO: support general data evaluation and remove this workaround - // See https://github.com/IDEMSInternational/open-app-builder/pull/2753 - if (typeof value === "string" && value.includes("+this.value")) { - action.params[key] = value.replace("+this.value", `${currentValue}`); - } + action.params[key] = replaceReference(value); } } return action;