PromucFlow_constructor/app/client/src/utils/Validators.ts

518 lines
13 KiB
TypeScript
Raw Normal View History

2019-11-19 12:44:58 +00:00
import _ from "lodash";
import {
ISO_DATE_FORMAT,
2019-11-19 12:44:58 +00:00
VALIDATION_TYPES,
2019-11-22 13:12:39 +00:00
ValidationResponse,
2019-11-19 12:44:58 +00:00
ValidationType,
Validator,
2019-11-25 05:07:27 +00:00
} from "constants/WidgetValidation";
2019-11-22 13:12:39 +00:00
import moment from "moment";
import { WIDGET_TYPE_VALIDATION_ERROR } from "constants/messages";
2020-04-20 05:42:46 +00:00
import { WidgetProps } from "widgets/BaseWidget";
import { DataTree } from "entities/DataTree/dataTreeFactory";
2019-11-19 12:44:58 +00:00
export const VALIDATORS: Record<ValidationType, Validator> = {
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.TEXT]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
2019-11-22 13:12:39 +00:00
let parsed = value;
2020-03-13 07:24:03 +00:00
if (_.isUndefined(value) || value === null) {
2019-12-10 13:30:16 +00:00
return {
2020-03-13 07:24:03 +00:00
isValid: true,
parsed: value,
message: "",
2019-12-10 13:30:16 +00:00
};
2019-11-22 13:12:39 +00:00
}
if (_.isObject(value)) {
return {
isValid: false,
parsed: JSON.stringify(value, null, 2),
message: `${WIDGET_TYPE_VALIDATION_ERROR}: text`,
};
}
2019-11-22 13:12:39 +00:00
let isValid = _.isString(value);
if (!isValid) {
try {
parsed = _.toString(value);
isValid = true;
} catch (e) {
console.error(`Error when parsing ${value} to string`);
console.error(e);
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: "",
message: `${WIDGET_TYPE_VALIDATION_ERROR}: text`,
};
2019-11-22 13:12:39 +00:00
}
}
return { isValid, parsed };
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.REGEX]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
2020-04-03 02:42:45 +00:00
const { isValid, parsed, message } = VALIDATORS[VALIDATION_TYPES.TEXT](
value,
2020-04-20 05:42:46 +00:00
props,
dataTree,
2020-04-03 02:42:45 +00:00
);
if (isValid) {
try {
new RegExp(parsed);
} catch (e) {
return {
isValid: false,
parsed: parsed,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: regex`,
};
}
}
return { isValid, parsed, message };
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.NUMBER]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
2019-11-22 13:12:39 +00:00
let parsed = value;
if (_.isUndefined(value)) {
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: 0,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: number`,
};
2019-11-22 13:12:39 +00:00
}
let isValid = _.isNumber(value);
if (!isValid) {
try {
parsed = _.toNumber(value);
if (isNaN(parsed)) {
return {
isValid: false,
parsed: 0,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: number`,
};
}
2019-11-22 13:12:39 +00:00
isValid = true;
} catch (e) {
console.error(`Error when parsing ${value} to number`);
console.error(e);
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: 0,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: number`,
};
2019-11-22 13:12:39 +00:00
}
}
return { isValid, parsed };
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.BOOLEAN]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
2019-11-22 13:12:39 +00:00
let parsed = value;
if (_.isUndefined(value)) {
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: false,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: boolean`,
};
2019-11-22 13:12:39 +00:00
}
2020-03-16 07:59:07 +00:00
const isBoolean = _.isBoolean(value);
const isStringTrueFalse = value === "true" || value === "false";
const isValid = isBoolean || isStringTrueFalse;
if (isStringTrueFalse) parsed = value !== "false";
2019-11-22 13:12:39 +00:00
if (!isValid) {
2020-03-16 07:59:07 +00:00
return {
isValid: isValid,
parsed: parsed,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: boolean`,
};
2019-11-22 13:12:39 +00:00
}
return { isValid, parsed };
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.OBJECT]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
2019-11-22 13:12:39 +00:00
let parsed = value;
if (_.isUndefined(value)) {
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: {},
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Object`,
};
2019-11-22 13:12:39 +00:00
}
let isValid = _.isObject(value);
if (!isValid) {
try {
parsed = JSON.parse(value);
isValid = true;
} catch (e) {
console.error(`Error when parsing ${value} to object`);
console.error(e);
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: {},
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Object`,
};
2019-11-22 13:12:39 +00:00
}
}
return { isValid, parsed };
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.ARRAY]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
2019-11-22 13:12:39 +00:00
let parsed = value;
2019-11-19 12:44:58 +00:00
try {
2019-11-22 13:12:39 +00:00
if (_.isUndefined(value)) {
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: [],
2020-06-19 13:06:45 +00:00
transformed: undefined,
2019-12-10 13:30:16 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Array/List`,
};
2019-11-19 12:44:58 +00:00
}
2019-11-22 13:12:39 +00:00
if (_.isString(value)) {
parsed = JSON.parse(parsed as string);
}
if (!Array.isArray(parsed)) {
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: [],
2020-06-19 13:06:45 +00:00
transformed: parsed,
2019-12-10 13:30:16 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Array/List`,
};
2019-11-22 13:12:39 +00:00
}
2020-06-19 13:06:45 +00:00
return { isValid: true, parsed, transformed: parsed };
2019-11-22 13:12:39 +00:00
} catch (e) {
console.error(e);
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: [],
2020-06-19 13:06:45 +00:00
transformed: parsed,
2019-12-10 13:30:16 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Array/List`,
};
2019-11-19 12:44:58 +00:00
}
},
[VALIDATION_TYPES.TABS_DATA]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
value,
props,
dataTree,
);
if (!isValid) {
return {
isValid,
parsed,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Tabs Data`,
};
} else if (!_.every(parsed, datum => _.isObject(datum))) {
return {
isValid: false,
parsed: [],
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Tabs Data`,
};
}
return { isValid, parsed };
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.TABLE_DATA]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
2020-06-19 13:06:45 +00:00
const { isValid, transformed, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
2020-04-20 05:42:46 +00:00
value,
props,
dataTree,
);
2019-11-22 13:12:39 +00:00
if (!isValid) {
2019-12-10 13:30:16 +00:00
return {
isValid,
2020-06-16 07:37:39 +00:00
parsed: [],
2020-06-19 13:06:45 +00:00
transformed,
2020-06-16 07:37:39 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR}: [{ "Col1" : "val1", "Col2" : "val2" }]`,
2019-12-10 13:30:16 +00:00
};
2020-06-16 07:37:39 +00:00
}
const isValidTableData = _.every(parsed, datum => {
return (
_.isObject(datum) &&
Object.keys(datum).filter(key => _.isString(key) && key.length === 0)
.length === 0
);
});
if (!isValidTableData) {
2019-12-10 13:30:16 +00:00
return {
isValid: false,
parsed: [],
2020-06-19 13:06:45 +00:00
transformed,
2020-06-16 07:37:39 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR}: [{ "Col1" : "val1", "Col2" : "val2" }]`,
2019-12-10 13:30:16 +00:00
};
2019-11-22 13:12:39 +00:00
}
return { isValid, parsed };
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.CHART_DATA]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
if (_.isString(value)) {
value = value.replace(/\s/g, "");
value = `${value}`;
}
2020-04-20 05:42:46 +00:00
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
value,
props,
dataTree,
);
2020-03-13 12:06:41 +00:00
if (!isValid) {
return {
isValid,
parsed,
2020-06-05 16:20:23 +00:00
transformed: parsed,
2020-03-13 12:06:41 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Chart Data`,
};
2020-05-07 10:51:37 +00:00
}
let validationMessage = "";
let index = 0;
const isValidChartData = _.every(
2020-05-07 10:51:37 +00:00
parsed,
(datum: { name: string; data: any }) => {
const validatedResponse: {
isValid: boolean;
parsed: object;
message?: string;
} = VALIDATORS[VALIDATION_TYPES.ARRAY](datum.data, props, dataTree);
validationMessage = `${index}##${WIDGET_TYPE_VALIDATION_ERROR}: [{ "x": "val", "y": "val" }]`;
let isValidChart = validatedResponse.isValid;
if (validatedResponse.isValid) {
datum.data = validatedResponse.parsed;
isValidChart = _.every(
datum.data,
(chartPoint: { x: string; y: any }) => {
return (
_.isObject(chartPoint) &&
_.isString(chartPoint.x) &&
!_.isUndefined(chartPoint.y)
);
},
2020-05-07 10:51:37 +00:00
);
}
index++;
return isValidChart;
2020-05-07 10:51:37 +00:00
},
);
if (!isValidChartData) {
2020-03-13 12:06:41 +00:00
return {
isValid: false,
parsed: [],
2020-06-05 16:20:23 +00:00
transformed: parsed,
message: validationMessage,
2020-03-13 12:06:41 +00:00
};
}
2020-06-05 16:20:23 +00:00
return { isValid, parsed, transformed: parsed };
2020-06-02 11:27:24 +00:00
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.MARKERS]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
value,
props,
dataTree,
);
2020-04-15 11:42:11 +00:00
if (!isValid) {
return {
isValid,
parsed,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Marker Data`,
};
} else if (!_.every(parsed, datum => _.isObject(datum))) {
return {
isValid: false,
parsed: [],
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Marker Data`,
};
}
return { isValid, parsed };
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.OPTIONS_DATA]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
value,
props,
dataTree,
);
2020-02-03 11:49:20 +00:00
if (!isValid) {
return {
isValid,
parsed,
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Options Data`,
};
}
2020-02-14 07:48:33 +00:00
const hasOptions = _.every(parsed, (datum: { label: any; value: any }) => {
if (_.isObject(datum)) {
return _.isString(datum.label) && _.isString(datum.value);
} else {
return false;
}
});
2020-02-03 11:49:20 +00:00
if (!hasOptions) {
return {
isValid: false,
parsed: [],
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Options Data`,
};
}
return { isValid, parsed };
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.DATE]: (
dateString: string,
2020-04-20 05:42:46 +00:00
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
2020-04-23 06:12:13 +00:00
const today = moment()
.hour(0)
.minute(0)
.second(0)
2020-06-09 13:04:47 +00:00
.millisecond(0);
const dateFormat = props.dateFormat ? props.dateFormat : ISO_DATE_FORMAT;
const todayDateString = today.format(dateFormat);
if (dateString === undefined) {
2020-03-16 15:42:39 +00:00
return {
isValid: false,
2020-06-09 13:04:47 +00:00
parsed: "",
2020-06-18 10:20:53 +00:00
message:
`${WIDGET_TYPE_VALIDATION_ERROR}: Date ` + props.dateFormat
? props.dateFormat
: "",
2020-03-16 15:42:39 +00:00
};
}
const isValid = moment(dateString, dateFormat).isValid();
const parsed = isValid ? dateString : todayDateString;
2019-12-10 13:30:16 +00:00
return {
isValid,
parsed,
message: isValid ? "" : `${WIDGET_TYPE_VALIDATION_ERROR}: Date`,
};
2019-11-22 13:12:39 +00:00
},
2020-04-20 05:42:46 +00:00
[VALIDATION_TYPES.ACTION_SELECTOR]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
2020-06-10 12:16:50 +00:00
if (Array.isArray(value) && value.length) {
return {
isValid: true,
parsed: undefined,
transformed: "Function Call",
};
}
/*
2020-03-31 10:40:52 +00:00
if (_.isString(value)) {
2020-04-20 05:42:46 +00:00
if (value.indexOf("navigateTo") !== -1) {
const pageNameOrUrl = modalGetter(value);
2020-04-29 05:35:02 +00:00
if (dataTree) {
if (isDynamicValue(pageNameOrUrl)) {
return {
isValid: true,
parsed: value,
};
}
const isPage =
(dataTree.pageList as PageListPayload).findIndex(
page => page.pageName === pageNameOrUrl,
) !== -1;
const isValidUrl = URL_REGEX.test(pageNameOrUrl);
if (!(isValidUrl || isPage)) {
return {
isValid: false,
parsed: value,
message: `${NAVIGATE_TO_VALIDATION_ERROR}`,
};
}
2020-03-31 10:40:52 +00:00
}
}
}
2020-06-10 12:16:50 +00:00
*/
2020-03-31 10:40:52 +00:00
return {
2020-06-10 12:16:50 +00:00
isValid: false,
parsed: undefined,
transformed: "undefined",
message: "Not a function call",
2020-03-31 10:40:52 +00:00
};
},
[VALIDATION_TYPES.ARRAY_ACTION_SELECTOR]: (
value: any,
2020-04-20 05:42:46 +00:00
props: WidgetProps,
dataTree?: DataTree,
2020-03-31 10:40:52 +00:00
): ValidationResponse => {
const { isValid, parsed, message } = VALIDATORS[VALIDATION_TYPES.ARRAY](
value,
2020-04-20 05:42:46 +00:00
props,
dataTree,
2020-03-31 10:40:52 +00:00
);
let isValidFinal = isValid;
let finalParsed = parsed.slice();
if (isValid) {
finalParsed = parsed.map((value: any) => {
const { isValid, message } = VALIDATORS[
VALIDATION_TYPES.ACTION_SELECTOR
2020-04-20 05:42:46 +00:00
](value.dynamicTrigger, props, dataTree);
2020-03-31 10:40:52 +00:00
isValidFinal = isValidFinal && isValid;
return {
...value,
message: message,
isValid: isValid,
};
});
}
return {
isValid: isValidFinal,
parsed: finalParsed,
message: message,
};
},
[VALIDATION_TYPES.SELECTED_TAB]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
const tabs =
props.tabs && _.isString(props.tabs)
? JSON.parse(props.tabs)
: props.tabs && Array.isArray(props.tabs)
? props.tabs
: [];
const tabNames = tabs.map((i: { label: string; id: string }) => i.label);
const isValidTabName = tabNames.includes(value);
return {
isValid: isValidTabName,
parsed: value,
message: isValidTabName
? ""
: `${WIDGET_TYPE_VALIDATION_ERROR}: Invalid tab name.`,
};
},
2019-11-19 12:44:58 +00:00
};