Junyi 05b9703101
feat(plugin-workflow-loop): add more configuration (#5342)
* feat(plugin-workflow-loop): add more configuration

* fix(plugin-workflow-loop): fix scope variable on current loop node

* refactor(plugin-workflow-loop): adjust order of exit options

* chore(plugin-workflow-loop): add migration

* fix(plugin-workflow): fix condition branch constant

* fix(plugin-workflow): fix additionalScope argument in parsing variable

* fix(plugin-workflow-loop): dependencies

* fix(plugin-workflow-loop): fix type

* fix(plugin-workflow-loop): fix client variable issues

* fix(plugin-workflow-loop): only use basic calculation due to expression variable issues

* refactor(plugin-workflow-loop): adjust configuration fields

* fix(plugin-workflow-loop): fix locale

* refactor(plugin-workflow-loop): adjust order of configuration fields

* fix(plugin-workflow-loop): fix number type properties

* fix(plugin-workflow-loop): fix null items in array are skipped
2024-10-16 21:15:35 +08:00

128 lines
2.8 KiB
TypeScript

/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { Registry } from '@nocobase/utils';
type Comparer = (a: any, b: any) => boolean;
export const calculators = new Registry<Comparer>();
// built-in functions
function equal(a, b) {
return a == b;
}
function notEqual(a, b) {
return a != b;
}
function gt(a, b) {
return a > b;
}
function gte(a, b) {
return a >= b;
}
function lt(a, b) {
return a < b;
}
function lte(a, b) {
return a <= b;
}
calculators.register('equal', equal);
calculators.register('notEqual', notEqual);
calculators.register('gt', gt);
calculators.register('gte', gte);
calculators.register('lt', lt);
calculators.register('lte', lte);
calculators.register('==', equal);
calculators.register('!=', notEqual);
calculators.register('>', gt);
calculators.register('>=', gte);
calculators.register('<', lt);
calculators.register('<=', lte);
function includes(a, b) {
return a.includes(b);
}
function notIncludes(a, b) {
return !a.includes(b);
}
function startsWith(a: string, b: string) {
return a.startsWith(b);
}
function notStartsWith(a: string, b: string) {
return !a.startsWith(b);
}
function endsWith(a: string, b: string) {
return a.endsWith(b);
}
function notEndsWith(a: string, b: string) {
return !a.endsWith(b);
}
calculators.register('includes', includes);
calculators.register('notIncludes', notIncludes);
calculators.register('startsWith', startsWith);
calculators.register('notStartsWith', notStartsWith);
calculators.register('endsWith', endsWith);
calculators.register('notEndsWith', notEndsWith);
type CalculationItem = {
calculator?: string;
operands?: [any?, any?];
};
type CalculationGroup = {
group: {
type: 'and' | 'or';
calculations?: Calculation[];
};
};
type Calculation = CalculationItem | CalculationGroup;
function calculate(calculation: CalculationItem = {}): boolean {
let fn: Comparer;
if (!calculation.calculator || !calculation.operands?.length) {
return true;
}
if (!(fn = calculators.get(calculation.calculator))) {
throw new Error(`no calculator function registered for "${calculation.calculator}"`);
}
return Boolean(fn(...(calculation.operands ?? [])));
}
const GroupTypeMethodMap = {
and: 'every',
or: 'some',
};
export function logicCalculate(calculation?: Calculation) {
if (!calculation) {
return true;
}
if (typeof calculation['group'] === 'object') {
const method = GroupTypeMethodMap[calculation['group'].type];
return (calculation['group'].calculations ?? [])[method]((item: Calculation) => logicCalculate(item));
}
return calculate(calculation as CalculationItem);
}