Skip to content

Commit

Permalink
Add condition as an optional third parameter to functions as: sumInAr…
Browse files Browse the repository at this point in the history
…ray, minInArray... fix #8257 (#8261)
  • Loading branch information
andrewtelnov committed May 13, 2024
1 parent 0a8407c commit 78844a0
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 7 deletions.
24 changes: 17 additions & 7 deletions src/functionsfactory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { HashTable, Helpers } from "./helpers";
import { settings } from "./settings";
import { ConsoleWarnings } from "./console-warnings";
import { ConditionRunner } from "./conditions";

export class FunctionFactory {
public static Instance: FunctionFactory = new FunctionFactory();
Expand Down Expand Up @@ -129,22 +130,27 @@ function avg(params: any[]): any {
FunctionFactory.Instance.register("avg", avg);

function getInArrayParams(params: any[]): any {
if (params.length != 2) return null;
var arr = params[0];
if (params.length < 2 || params.length > 3) return null;
const arr = params[0];
if (!arr) return null;
if (!Array.isArray(arr) && !Array.isArray(Object.keys(arr))) return null;
var name = params[1];
const name = params[1];
if (typeof name !== "string" && !(name instanceof String)) return null;
return { data: arr, name: name };
let expression = params.length === 3 ? params[2] : undefined;
if (typeof expression !== "string" && !(expression instanceof String)) {
expression = undefined;
}
return { data: arr, name: name, expression: expression };
}

function convertToNumber(val: any): number {
if(typeof val === "string") return Helpers.isNumber(val) ? Helpers.getNumber(val) : undefined;
return val;
}
function processItemInArray(item: any, name: string, res: number,
func: (res: number, val: number) => number, needToConvert: boolean): number {
func: (res: number, val: number) => number, needToConvert: boolean, condition: ConditionRunner): number {
if(!item || Helpers.isValueEmpty(item[name])) return res;
if(condition && !condition.run(item)) return res;
const val = needToConvert ? convertToNumber(item[name]) : 1;
return func(res, val);
}
Expand All @@ -154,14 +160,18 @@ function calcInArray(
): any {
var v = getInArrayParams(params);
if (!v) return undefined;
let condition = !!v.expression ? new ConditionRunner(v.expression) : undefined;
if(condition && condition.isAsync) {
condition = undefined;
}
var res = undefined;
if (Array.isArray(v.data)) {
for (var i = 0; i < v.data.length; i++) {
res = processItemInArray(v.data[i], v.name, res, func, needToConvert);
res = processItemInArray(v.data[i], v.name, res, func, needToConvert, condition);
}
} else {
for (var key in v.data) {
res = processItemInArray(v.data[key], v.name, res, func, needToConvert);
res = processItemInArray(v.data[key], v.name, res, func, needToConvert, condition);
}
}
return res;
Expand Down
5 changes: 5 additions & 0 deletions tests/expressions/expressionParserTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,11 @@ QUnit.test("ExpressionRunner: sumInArray, for objects", function(assert) {
};
assert.equal(runner.run(values), 30, "10 + 20");
});
QUnit.test("ExpressionRunner: sumInArray with conditional logic", function(assert) {
var runner = new ExpressionRunner("sumInArray({a}, 'val1', '{val2} > 3')");
var values = { a: [{ val1: 1, val2: 4 }, { val1: 2, val2: 3 }, { val1: 3, val2: 5 }] };
assert.equal(runner.run(values), 4, "1 + 3");
});

QUnit.test("ExpressionRunner: countInArray", function(assert) {
var runner = new ExpressionRunner("countInArray({a}, 'val1')");
Expand Down

0 comments on commit 78844a0

Please sign in to comment.