2020-10-21 04:25:32 +00:00
|
|
|
import _, { VERSION as lodashVersion } from "lodash";
|
2020-04-10 08:48:00 +00:00
|
|
|
import {
|
|
|
|
|
DATA_BIND_REGEX,
|
|
|
|
|
DATA_BIND_REGEX_GLOBAL,
|
|
|
|
|
} from "constants/BindingsConstants";
|
2020-07-03 08:58:58 +00:00
|
|
|
import { Action } from "entities/Action";
|
2020-10-21 04:25:32 +00:00
|
|
|
import moment from "moment-timezone";
|
2020-11-12 11:23:32 +00:00
|
|
|
import { WidgetProps } from "../widgets/BaseWidget";
|
2019-12-06 13:16:08 +00:00
|
|
|
|
2020-07-03 08:58:58 +00:00
|
|
|
export const removeBindingsFromActionObject = (obj: Action) => {
|
2020-01-27 13:53:33 +00:00
|
|
|
const string = JSON.stringify(obj);
|
2020-04-10 08:48:00 +00:00
|
|
|
const withBindings = string.replace(DATA_BIND_REGEX_GLOBAL, "{{ }}");
|
2020-01-27 13:53:33 +00:00
|
|
|
return JSON.parse(withBindings);
|
|
|
|
|
};
|
2020-04-10 08:48:00 +00:00
|
|
|
// referencing DATA_BIND_REGEX fails for the value "{{Table1.tableData[Table1.selectedRowIndex]}}" if you run it multiple times and don't recreate
|
2019-11-14 09:28:51 +00:00
|
|
|
export const isDynamicValue = (value: string): boolean =>
|
2019-12-02 07:37:33 +00:00
|
|
|
DATA_BIND_REGEX.test(value);
|
2019-11-28 03:56:44 +00:00
|
|
|
|
|
|
|
|
//{{}}{{}}}
|
2020-06-03 17:27:24 +00:00
|
|
|
export function getDynamicStringSegments(dynamicString: string): string[] {
|
|
|
|
|
let stringSegments = [];
|
2019-11-28 03:56:44 +00:00
|
|
|
const indexOfDoubleParanStart = dynamicString.indexOf("{{");
|
|
|
|
|
if (indexOfDoubleParanStart === -1) {
|
|
|
|
|
return [dynamicString];
|
|
|
|
|
}
|
|
|
|
|
//{{}}{{}}}
|
|
|
|
|
const firstString = dynamicString.substring(0, indexOfDoubleParanStart);
|
2020-06-03 17:27:24 +00:00
|
|
|
firstString && stringSegments.push(firstString);
|
2019-11-28 03:56:44 +00:00
|
|
|
let rest = dynamicString.substring(
|
|
|
|
|
indexOfDoubleParanStart,
|
|
|
|
|
dynamicString.length,
|
|
|
|
|
);
|
|
|
|
|
//{{}}{{}}}
|
|
|
|
|
let sum = 0;
|
|
|
|
|
for (let i = 0; i <= rest.length - 1; i++) {
|
|
|
|
|
const char = rest[i];
|
|
|
|
|
const prevChar = rest[i - 1];
|
|
|
|
|
|
|
|
|
|
if (char === "{") {
|
|
|
|
|
sum++;
|
|
|
|
|
} else if (char === "}") {
|
|
|
|
|
sum--;
|
|
|
|
|
if (prevChar === "}" && sum === 0) {
|
2020-06-03 17:27:24 +00:00
|
|
|
stringSegments.push(rest.substring(0, i + 1));
|
2019-11-28 03:56:44 +00:00
|
|
|
rest = rest.substring(i + 1, rest.length);
|
|
|
|
|
if (rest) {
|
2020-06-03 17:27:24 +00:00
|
|
|
stringSegments = stringSegments.concat(
|
|
|
|
|
getDynamicStringSegments(rest),
|
2019-11-28 03:56:44 +00:00
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (sum !== 0 && dynamicString !== "") {
|
|
|
|
|
return [dynamicString];
|
|
|
|
|
}
|
2020-06-03 17:27:24 +00:00
|
|
|
return stringSegments;
|
2019-11-28 03:56:44 +00:00
|
|
|
}
|
2019-11-14 09:28:51 +00:00
|
|
|
|
|
|
|
|
export const getDynamicBindings = (
|
|
|
|
|
dynamicString: string,
|
2020-06-03 17:27:24 +00:00
|
|
|
): { stringSegments: string[]; jsSnippets: string[] } => {
|
2020-03-06 09:45:21 +00:00
|
|
|
// Protect against bad string parse
|
|
|
|
|
if (!dynamicString || !_.isString(dynamicString)) {
|
2020-06-03 17:27:24 +00:00
|
|
|
return { stringSegments: [], jsSnippets: [] };
|
2020-03-06 09:45:21 +00:00
|
|
|
}
|
2020-01-17 09:28:26 +00:00
|
|
|
const sanitisedString = dynamicString.trim();
|
2019-11-14 09:28:51 +00:00
|
|
|
// Get the {{binding}} bound values
|
2020-06-03 17:27:24 +00:00
|
|
|
const stringSegments = getDynamicStringSegments(sanitisedString);
|
2019-11-14 09:28:51 +00:00
|
|
|
// Get the "binding" path values
|
2020-06-03 17:27:24 +00:00
|
|
|
const paths = stringSegments.map(segment => {
|
|
|
|
|
const length = segment.length;
|
|
|
|
|
const matches = isDynamicValue(segment);
|
2019-11-28 03:56:44 +00:00
|
|
|
if (matches) {
|
2020-06-03 17:27:24 +00:00
|
|
|
return segment.substring(2, length - 2);
|
2019-11-28 03:56:44 +00:00
|
|
|
}
|
2019-11-14 09:28:51 +00:00
|
|
|
return "";
|
|
|
|
|
});
|
2020-06-03 17:27:24 +00:00
|
|
|
return { stringSegments: stringSegments, jsSnippets: paths };
|
2019-11-14 09:28:51 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
export enum EvalErrorTypes {
|
|
|
|
|
DEPENDENCY_ERROR = "DEPENDENCY_ERROR",
|
|
|
|
|
EVAL_PROPERTY_ERROR = "EVAL_PROPERTY_ERROR",
|
|
|
|
|
EVAL_TREE_ERROR = "EVAL_TREE_ERROR",
|
|
|
|
|
UNESCAPE_STRING_ERROR = "UNESCAPE_STRING_ERROR",
|
|
|
|
|
EVAL_ERROR = "EVAL_ERROR",
|
2020-03-23 12:40:17 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
export type EvalError = {
|
|
|
|
|
type: EvalErrorTypes;
|
2020-10-22 13:15:50 +00:00
|
|
|
message: string;
|
2020-10-21 04:25:32 +00:00
|
|
|
context?: Record<string, any>;
|
2020-01-30 13:23:04 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
export enum EVAL_WORKER_ACTIONS {
|
|
|
|
|
EVAL_TREE = "EVAL_TREE",
|
|
|
|
|
EVAL_SINGLE = "EVAL_SINGLE",
|
|
|
|
|
EVAL_TRIGGER = "EVAL_TRIGGER",
|
|
|
|
|
CLEAR_PROPERTY_CACHE = "CLEAR_PROPERTY_CACHE",
|
2020-12-01 05:26:35 +00:00
|
|
|
CLEAR_PROPERTY_CACHE_OF_WIDGET = "CLEAR_PROPERTY_CACHE_OF_WIDGET",
|
2020-10-21 04:25:32 +00:00
|
|
|
CLEAR_CACHE = "CLEAR_CACHE",
|
|
|
|
|
VALIDATE_PROPERTY = "VALIDATE_PROPERTY",
|
|
|
|
|
}
|
2020-01-30 13:23:04 +00:00
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
export type ExtraLibrary = {
|
|
|
|
|
version: string;
|
|
|
|
|
docsURL: string;
|
|
|
|
|
displayName: string;
|
|
|
|
|
accessor: string;
|
|
|
|
|
lib: any;
|
2020-01-30 13:23:04 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
export const extraLibraries: ExtraLibrary[] = [
|
2020-04-17 16:15:09 +00:00
|
|
|
{
|
2020-10-21 04:25:32 +00:00
|
|
|
accessor: "_",
|
|
|
|
|
lib: _,
|
|
|
|
|
version: lodashVersion,
|
|
|
|
|
docsURL: `https://lodash.com/docs/${lodashVersion}`,
|
|
|
|
|
displayName: "lodash",
|
|
|
|
|
},
|
2020-04-23 14:57:37 +00:00
|
|
|
{
|
2020-10-21 04:25:32 +00:00
|
|
|
accessor: "moment",
|
|
|
|
|
lib: moment,
|
|
|
|
|
version: moment.version,
|
|
|
|
|
docsURL: `https://momentjs.com/docs/`,
|
|
|
|
|
displayName: "moment",
|
|
|
|
|
},
|
|
|
|
|
];
|
2020-11-12 11:23:32 +00:00
|
|
|
|
|
|
|
|
export interface DynamicPath {
|
|
|
|
|
key: string;
|
|
|
|
|
value?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface WidgetDynamicPathListProps {
|
|
|
|
|
dynamicBindingPathList?: DynamicPath[];
|
|
|
|
|
dynamicTriggerPathList?: DynamicPath[];
|
|
|
|
|
dynamicPropertyPathList?: DynamicPath[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface WidgetEvaluatedProps {
|
|
|
|
|
invalidProps?: Record<string, boolean>;
|
|
|
|
|
validationMessages?: Record<string, string>;
|
|
|
|
|
evaluatedValues?: Record<string, any>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface EntityWithBindings {
|
|
|
|
|
dynamicBindingPathList?: DynamicPath[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const getEntityDynamicBindingPathList = (
|
|
|
|
|
entity: EntityWithBindings,
|
|
|
|
|
): DynamicPath[] => {
|
|
|
|
|
if (
|
|
|
|
|
entity &&
|
|
|
|
|
entity.dynamicBindingPathList &&
|
|
|
|
|
Array.isArray(entity.dynamicBindingPathList)
|
|
|
|
|
) {
|
|
|
|
|
return [...entity.dynamicBindingPathList];
|
|
|
|
|
}
|
|
|
|
|
return [];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const isPathADynamicBinding = (
|
|
|
|
|
entity: EntityWithBindings,
|
|
|
|
|
path: string,
|
|
|
|
|
): boolean => {
|
|
|
|
|
if (
|
|
|
|
|
entity &&
|
|
|
|
|
entity.dynamicBindingPathList &&
|
|
|
|
|
Array.isArray(entity.dynamicBindingPathList)
|
|
|
|
|
) {
|
|
|
|
|
return _.find(entity.dynamicBindingPathList, { key: path }) !== undefined;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getWidgetDynamicTriggerPathList = (
|
|
|
|
|
widget: WidgetProps,
|
|
|
|
|
): DynamicPath[] => {
|
|
|
|
|
if (
|
|
|
|
|
widget &&
|
|
|
|
|
widget.dynamicTriggerPathList &&
|
|
|
|
|
Array.isArray(widget.dynamicTriggerPathList)
|
|
|
|
|
) {
|
|
|
|
|
return [...widget.dynamicTriggerPathList];
|
|
|
|
|
}
|
|
|
|
|
return [];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const isPathADynamicTrigger = (
|
|
|
|
|
widget: WidgetProps,
|
|
|
|
|
path: string,
|
|
|
|
|
): boolean => {
|
|
|
|
|
if (
|
|
|
|
|
widget &&
|
|
|
|
|
widget.dynamicTriggerPathList &&
|
|
|
|
|
Array.isArray(widget.dynamicTriggerPathList)
|
|
|
|
|
) {
|
|
|
|
|
return _.find(widget.dynamicTriggerPathList, { key: path }) !== undefined;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getWidgetDynamicPropertyPathList = (
|
|
|
|
|
widget: WidgetProps,
|
|
|
|
|
): DynamicPath[] => {
|
|
|
|
|
if (
|
|
|
|
|
widget &&
|
|
|
|
|
widget.dynamicPropertyPathList &&
|
|
|
|
|
Array.isArray(widget.dynamicPropertyPathList)
|
|
|
|
|
) {
|
|
|
|
|
return [...widget.dynamicPropertyPathList];
|
|
|
|
|
}
|
|
|
|
|
return [];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const isPathADynamicProperty = (
|
|
|
|
|
widget: WidgetProps,
|
|
|
|
|
path: string,
|
|
|
|
|
): boolean => {
|
|
|
|
|
if (
|
|
|
|
|
widget &&
|
|
|
|
|
widget.dynamicPropertyPathList &&
|
|
|
|
|
Array.isArray(widget.dynamicPropertyPathList)
|
|
|
|
|
) {
|
|
|
|
|
return _.find(widget.dynamicPropertyPathList, { key: path }) !== undefined;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
2020-12-10 08:30:49 +00:00
|
|
|
|
2020-12-10 11:52:18 +00:00
|
|
|
export const unsafeFunctionForEval = [
|
|
|
|
|
"setTimeout",
|
|
|
|
|
"fetch",
|
|
|
|
|
"setInterval",
|
|
|
|
|
"Promise",
|
|
|
|
|
];
|