From 1e47bb246e1f5c8ad0b8357403a40410858dd083 Mon Sep 17 00:00:00 2001 From: cesarParra Date: Fri, 3 Nov 2023 12:14:21 -0400 Subject: [PATCH 1/4] Fixing issue where collection function combination was not correctly resolving the query because it was caching the parent's list of fields, rather than using the list of fields based on the current Sobject type during child subquery resolution. --- .idea/formula-evaluator.iml | 2 +- .idea/jsLibraryMappings.xml | 6 ------ .../components/base/lwc/baseButton/baseButton.js | 2 ++ .../main/api/tests/CollectionFunctionsTest.cls | 15 +++++++++++++++ .../main/src/interpreter/ContextResolver.cls | 9 +++++---- 5 files changed, 23 insertions(+), 11 deletions(-) delete mode 100644 .idea/jsLibraryMappings.xml diff --git a/.idea/formula-evaluator.iml b/.idea/formula-evaluator.iml index 5bcabc71..b25edf75 100644 --- a/.idea/formula-evaluator.iml +++ b/.idea/formula-evaluator.iml @@ -8,7 +8,7 @@ diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml deleted file mode 100644 index cc3da93f..00000000 --- a/.idea/jsLibraryMappings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/expression-components/main/ui/components/base/lwc/baseButton/baseButton.js b/expression-components/main/ui/components/base/lwc/baseButton/baseButton.js index 759ca8e1..abdd0969 100644 --- a/expression-components/main/ui/components/base/lwc/baseButton/baseButton.js +++ b/expression-components/main/ui/components/base/lwc/baseButton/baseButton.js @@ -1,6 +1,8 @@ import {api} from 'lwc'; import TwElement from "c/twElement"; import {NavigationMixin} from "lightning/navigation"; +import { RefreshEvent } from "lightning/refresh"; +// TODO: next let's dispatch the event import execute from '@salesforce/apex/FormulaEvaluatorUiController.execute'; import {classNames} from 'c/utils'; diff --git a/expression-src/main/api/tests/CollectionFunctionsTest.cls b/expression-src/main/api/tests/CollectionFunctionsTest.cls index 7d702137..5256282f 100644 --- a/expression-src/main/api/tests/CollectionFunctionsTest.cls +++ b/expression-src/main/api/tests/CollectionFunctionsTest.cls @@ -359,6 +359,21 @@ private class CollectionFunctionsTest { Assert.areEqual('Child2', result[0]); } + @IsTest + private static void combiningWhereAndMap_withRelationshipsBetweenDifferentSObjectTypes() { + Account parentAccount = new Account(Name = 'Parent'); + insert parentAccount; + + Contact childContact = new Contact(LastName = 'Child', AccountId = parentAccount.Id); + insert childContact; + + String expr = 'MAP(WHERE(Contacts, BEGINS(LastName, "C")), Name)'; + List result = (List) Evaluator.run(expr, parentAccount.Id); + + Assert.areEqual(1, result.size()); + Assert.areEqual('Child', result[0]); + } + @IsTest private static void nestingWheres() { Account parentAccount = new Account(Name = 'Parent'); diff --git a/expression-src/main/src/interpreter/ContextResolver.cls b/expression-src/main/src/interpreter/ContextResolver.cls index 0cd1cb17..536f8c54 100644 --- a/expression-src/main/src/interpreter/ContextResolver.cls +++ b/expression-src/main/src/interpreter/ContextResolver.cls @@ -189,13 +189,14 @@ public with sharing class ContextResolver implements Visitor { return null; } - private Set cachedFields; + private final Map> cachedFieldsBySObjectType = new Map>(); private Set getFields() { - if (cachedFields == null) { - cachedFields = new Set(); - cachedFields = this.queryContext.objectType.getDescribe().fields.getMap().keySet(); + if (cachedFieldsBySObjectType.containsKey(this.queryContext.objectType)) { + return cachedFieldsBySObjectType.get(this.queryContext.objectType); } + Set cachedFields = this.queryContext.objectType.getDescribe().fields.getMap().keySet(); + cachedFieldsBySObjectType.put(this.queryContext.objectType, cachedFields); return cachedFields; } From fb9f3a1ab542ed657ca9b2d3939fdfae61efa748 Mon Sep 17 00:00:00 2001 From: cesarParra Date: Fri, 3 Nov 2023 17:35:25 -0400 Subject: [PATCH 2/4] Sending and receiving refresh notifications during a change. --- .../base/lwc/baseButton/baseButton.js | 34 +++++++++++++------ .../expressionElementContainer.html | 2 +- .../expressionElementContainer.js | 4 +++ .../expressionSiteElement.js | 18 +++++++++- .../interpreter/ActionVariableResolver.cls | 5 +++ src-pull/classes/UpdateAccount.cls | 13 +++++++ src-pull/classes/UpdateAccount.cls-meta.xml | 5 +++ 7 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 src-pull/classes/UpdateAccount.cls create mode 100644 src-pull/classes/UpdateAccount.cls-meta.xml diff --git a/expression-components/main/ui/components/base/lwc/baseButton/baseButton.js b/expression-components/main/ui/components/base/lwc/baseButton/baseButton.js index abdd0969..625cce87 100644 --- a/expression-components/main/ui/components/base/lwc/baseButton/baseButton.js +++ b/expression-components/main/ui/components/base/lwc/baseButton/baseButton.js @@ -1,8 +1,7 @@ import {api} from 'lwc'; import TwElement from "c/twElement"; import {NavigationMixin} from "lightning/navigation"; -import { RefreshEvent } from "lightning/refresh"; -// TODO: next let's dispatch the event +import {RefreshEvent} from "lightning/refresh"; import execute from '@salesforce/apex/FormulaEvaluatorUiController.execute'; import {classNames} from 'c/utils'; @@ -15,7 +14,7 @@ export default class BaseButton extends NavigationMixin(TwElement) { /** * @typedef ApexFunctionCallback - * @property { "navigate__namedPage" | "navigate__url" } type + * @property { "navigate__namedPage" | "navigate__url", "reload", "refresh" } type * @property { string } name * @property { Object } args */ @@ -23,7 +22,7 @@ export default class BaseButton extends NavigationMixin(TwElement) { /** * The action to execute when the button is clicked * @property {string} label - * @property {"action" | "navigation_namedPage" | "navigation_url" } type + * @property {"action", "submit" | "navigation_namedPage" | "navigation_url" } type * @property {string | ApexFunction} src * @property {ApexFunctionCallback} callback */ @@ -34,6 +33,7 @@ export default class BaseButton extends NavigationMixin(TwElement) { @api variant = "primary"; disabled = false; + get btnClasses() { switch (this.variant) { case "primary": @@ -58,6 +58,8 @@ export default class BaseButton extends NavigationMixin(TwElement) { e.preventDefault(); e.stopPropagation(); + // TODO: This needs to be more robust because it doesn't work for refresh + // and also doesn't work if the validation fails on a submit. this.disabled = true; if (this.action.type === 'submit') { @@ -101,16 +103,28 @@ export default class BaseButton extends NavigationMixin(TwElement) { get displayAsButton() { return this.action.type === "submit" || this.action.type === "action"; } + actionCallback = (result) => { - if (this.action.callback.type === 'reload') { - // Reload is not handled by the navigation mixin, so we handle it here - // as a special case. - location.reload(); - } else { - this[NavigationMixin.Navigate](this._getNavigationObjectFromActionResult(result)); + switch (this.action.callback.type) { + case "reload": + this.dispatchEvent(new RefreshEvent()); + break; + case "refresh": + this.dispatchEvent(new CustomEvent('expression_refresh', {bubbles: true, composed: true})); + break; + case "navigate__namedPage": + case "navigate__url": + this._navigate(result); + break; + default: + throw new Error(`Unknown callback type: ${this.action.callback.type}`); } } + _navigate(result) { + this[NavigationMixin.Navigate](this._getNavigationObjectFromActionResult(result)); + } + _getNavigationObjectFromActionResult = (result) => { return { type: this._mapApexCallbackToNavigationMixinType(this.action.callback.type), diff --git a/expression-components/main/ui/components/base/lwc/expressionElementContainer/expressionElementContainer.html b/expression-components/main/ui/components/base/lwc/expressionElementContainer/expressionElementContainer.html index 83d2a0e4..abda2eea 100644 --- a/expression-components/main/ui/components/base/lwc/expressionElementContainer/expressionElementContainer.html +++ b/expression-components/main/ui/components/base/lwc/expressionElementContainer/expressionElementContainer.html @@ -1,5 +1,5 @@