2021-01-04 10:16:08 +00:00
|
|
|
import {
|
|
|
|
|
ISO_DATE_FORMAT,
|
|
|
|
|
VALIDATION_TYPES,
|
|
|
|
|
ValidationResponse,
|
|
|
|
|
Validator,
|
|
|
|
|
} from "../constants/WidgetValidation";
|
|
|
|
|
import { DataTree } from "../entities/DataTree/dataTreeFactory";
|
|
|
|
|
import _, {
|
|
|
|
|
every,
|
2021-06-01 14:57:58 +00:00
|
|
|
indexOf,
|
2021-01-04 10:16:08 +00:00
|
|
|
isBoolean,
|
2021-03-24 19:25:38 +00:00
|
|
|
isNil,
|
2021-01-04 10:16:08 +00:00
|
|
|
isNumber,
|
|
|
|
|
isObject,
|
2021-02-16 10:29:08 +00:00
|
|
|
isPlainObject,
|
2021-01-04 10:16:08 +00:00
|
|
|
isString,
|
|
|
|
|
isUndefined,
|
|
|
|
|
toNumber,
|
|
|
|
|
toString,
|
|
|
|
|
} from "lodash";
|
|
|
|
|
import { WidgetProps } from "../widgets/BaseWidget";
|
2021-06-01 14:57:58 +00:00
|
|
|
import {
|
|
|
|
|
CUSTOM_CHART_TYPES,
|
|
|
|
|
CUSTOM_CHART_DEFAULT_PARSED,
|
|
|
|
|
} from "../constants/CustomChartConstants";
|
2021-01-04 10:16:08 +00:00
|
|
|
import moment from "moment";
|
|
|
|
|
|
2021-03-24 12:12:24 +00:00
|
|
|
export function validateDateString(
|
|
|
|
|
dateString: string,
|
|
|
|
|
dateFormat: string,
|
|
|
|
|
version: number,
|
|
|
|
|
) {
|
|
|
|
|
let isValid = true;
|
|
|
|
|
if (version === 2) {
|
|
|
|
|
try {
|
2021-03-30 09:02:25 +00:00
|
|
|
const d = moment(dateString);
|
|
|
|
|
isValid =
|
|
|
|
|
d.toISOString(true) === dateString || d.toISOString() === dateString;
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
const parsedDate = moment(dateString);
|
|
|
|
|
isValid = parsedDate.isValid();
|
|
|
|
|
}
|
2021-03-24 12:12:24 +00:00
|
|
|
} catch (e) {
|
|
|
|
|
isValid = false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const parsedDate = moment(dateString, dateFormat);
|
|
|
|
|
isValid = parsedDate.isValid();
|
|
|
|
|
}
|
|
|
|
|
return isValid;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-23 13:50:55 +00:00
|
|
|
const WIDGET_TYPE_VALIDATION_ERROR = "This value does not evaluate to type"; // TODO: Lot's of changes in validations.ts file
|
2021-03-13 14:24:45 +00:00
|
|
|
|
2021-04-21 14:34:25 +00:00
|
|
|
export const VALIDATORS: Record<VALIDATION_TYPES, Validator> = {
|
2021-01-04 10:16:08 +00:00
|
|
|
[VALIDATION_TYPES.TEXT]: (value: any): ValidationResponse => {
|
|
|
|
|
let parsed = value;
|
|
|
|
|
if (isUndefined(value) || value === null) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
|
|
|
|
parsed: value,
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (isObject(value)) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: JSON.stringify(value, null, 2),
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "text"`,
|
2021-01-04 10:16:08 +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);
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: "",
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "text"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.REGEX]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
): ValidationResponse => {
|
2021-05-13 08:35:39 +00:00
|
|
|
const { isValid, message, parsed } = VALIDATORS[VALIDATION_TYPES.TEXT](
|
2021-01-04 10:16:08 +00:00
|
|
|
value,
|
|
|
|
|
props,
|
|
|
|
|
dataTree,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (isValid) {
|
|
|
|
|
try {
|
|
|
|
|
new RegExp(parsed);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: parsed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "regex"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { isValid, parsed, message };
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.NUMBER]: (value: any): ValidationResponse => {
|
|
|
|
|
let parsed = value;
|
|
|
|
|
if (isUndefined(value)) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: 0,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "number"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
let isValid = isNumber(value);
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
try {
|
|
|
|
|
parsed = toNumber(value);
|
|
|
|
|
if (isNaN(parsed)) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: 0,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "number"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
isValid = true;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(`Error when parsing ${value} to number`);
|
|
|
|
|
console.error(e);
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: 0,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "number"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.BOOLEAN]: (value: any): ValidationResponse => {
|
|
|
|
|
let parsed = value;
|
|
|
|
|
if (isUndefined(value)) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: false,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "boolean"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const isABoolean = isBoolean(value);
|
|
|
|
|
const isStringTrueFalse = value === "true" || value === "false";
|
|
|
|
|
const isValid = isABoolean || isStringTrueFalse;
|
|
|
|
|
if (isStringTrueFalse) parsed = value !== "false";
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValid,
|
2021-05-26 12:13:25 +00:00
|
|
|
parsed: !!parsed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "boolean"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.OBJECT]: (value: any): ValidationResponse => {
|
|
|
|
|
let parsed = value;
|
|
|
|
|
if (isUndefined(value)) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: {},
|
|
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Object`,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: {},
|
|
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Object`,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.ARRAY]: (value: any): ValidationResponse => {
|
|
|
|
|
let parsed = value;
|
|
|
|
|
try {
|
|
|
|
|
if (isUndefined(value)) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: [],
|
|
|
|
|
transformed: undefined,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (isString(value)) {
|
|
|
|
|
parsed = JSON.parse(parsed as string);
|
|
|
|
|
}
|
2021-04-26 10:35:59 +00:00
|
|
|
|
2021-01-04 10:16:08 +00:00
|
|
|
if (!Array.isArray(parsed)) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: [],
|
|
|
|
|
transformed: parsed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
2021-04-26 10:35:59 +00:00
|
|
|
|
2021-01-04 10:16:08 +00:00
|
|
|
return { isValid: true, parsed, transformed: parsed };
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: [],
|
|
|
|
|
transformed: parsed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array"`,
|
2021-01-04 10:16:08 +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,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<{ label: string, id: string(unique), widgetId: string(unique) }>"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
2021-03-03 05:59:02 +00:00
|
|
|
} else if (
|
|
|
|
|
!every(
|
|
|
|
|
parsed,
|
|
|
|
|
(datum: {
|
|
|
|
|
id: string;
|
|
|
|
|
label: string;
|
|
|
|
|
widgetId: string;
|
|
|
|
|
isVisible?: boolean;
|
|
|
|
|
}) =>
|
|
|
|
|
isObject(datum) &&
|
|
|
|
|
!isUndefined(datum.id) &&
|
|
|
|
|
!isUndefined(datum.label) &&
|
|
|
|
|
!isUndefined(datum.widgetId),
|
|
|
|
|
)
|
|
|
|
|
) {
|
2021-01-04 10:16:08 +00:00
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: [],
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<{ label: string, id: string(unique), widgetId: string(unique) }>"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
},
|
2021-04-23 05:43:13 +00:00
|
|
|
[VALIDATION_TYPES.LIST_DATA]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
): ValidationResponse => {
|
2021-05-13 08:35:39 +00:00
|
|
|
const { isValid, parsed, transformed } = VALIDATORS.ARRAY(
|
2021-04-23 05:43:13 +00:00
|
|
|
value,
|
|
|
|
|
props,
|
|
|
|
|
dataTree,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid,
|
|
|
|
|
parsed: [],
|
|
|
|
|
transformed,
|
2021-05-21 08:48:59 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR}: "Array<Object>"`,
|
2021-04-23 05:43:13 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isValidListData = every(parsed, (datum) => {
|
|
|
|
|
return (
|
|
|
|
|
isObject(datum) &&
|
|
|
|
|
Object.keys(datum).filter((key) => isString(key) && key.length === 0)
|
|
|
|
|
.length === 0
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!isValidListData) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: [],
|
|
|
|
|
transformed,
|
2021-05-21 08:48:59 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR}: "Array<Object>"`,
|
2021-04-23 05:43:13 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
},
|
2021-01-04 10:16:08 +00:00
|
|
|
[VALIDATION_TYPES.TABLE_DATA]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
): ValidationResponse => {
|
2021-05-13 08:35:39 +00:00
|
|
|
const { isValid, parsed, transformed } = VALIDATORS.ARRAY(
|
2021-01-04 10:16:08 +00:00
|
|
|
value,
|
|
|
|
|
props,
|
|
|
|
|
dataTree,
|
|
|
|
|
);
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid,
|
|
|
|
|
parsed: [],
|
|
|
|
|
transformed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<Object>"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const isValidTableData = every(parsed, (datum) => {
|
|
|
|
|
return (
|
2021-02-16 10:29:08 +00:00
|
|
|
isPlainObject(datum) &&
|
2021-01-04 10:16:08 +00:00
|
|
|
Object.keys(datum).filter((key) => isString(key) && key.length === 0)
|
|
|
|
|
.length === 0
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
if (!isValidTableData) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: [],
|
|
|
|
|
transformed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<Object>"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
},
|
2021-04-26 10:35:59 +00:00
|
|
|
[VALIDATION_TYPES.CHART_SERIES_DATA]: (
|
2021-01-04 10:16:08 +00:00
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
): ValidationResponse => {
|
2021-04-26 10:35:59 +00:00
|
|
|
let parsed = [];
|
|
|
|
|
let transformed = [];
|
|
|
|
|
let isValid = false;
|
2021-01-04 10:16:08 +00:00
|
|
|
let validationMessage = "";
|
2021-03-04 18:58:43 +00:00
|
|
|
|
2021-04-26 10:35:59 +00:00
|
|
|
try {
|
|
|
|
|
const validatedResponse: ValidationResponse = VALIDATORS[
|
|
|
|
|
VALIDATION_TYPES.ARRAY
|
|
|
|
|
](value, props, dataTree);
|
|
|
|
|
|
|
|
|
|
if (validatedResponse.isValid) {
|
|
|
|
|
isValid = every(
|
|
|
|
|
validatedResponse.parsed,
|
|
|
|
|
(chartPoint: { x: string; y: any }) => {
|
|
|
|
|
return (
|
|
|
|
|
isObject(chartPoint) &&
|
|
|
|
|
isString(chartPoint.x) &&
|
|
|
|
|
!isUndefined(chartPoint.y)
|
|
|
|
|
);
|
|
|
|
|
},
|
2021-03-04 18:58:43 +00:00
|
|
|
);
|
|
|
|
|
}
|
2021-04-26 10:35:59 +00:00
|
|
|
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
parsed = [];
|
|
|
|
|
transformed = validatedResponse.transformed;
|
2021-05-25 13:48:35 +00:00
|
|
|
validationMessage = `${WIDGET_TYPE_VALIDATION_ERROR}: "Array<x:string, y:number>"`;
|
2021-04-26 10:35:59 +00:00
|
|
|
} else {
|
|
|
|
|
parsed = validatedResponse.parsed;
|
|
|
|
|
transformed = validatedResponse.parsed;
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
2021-03-04 18:58:43 +00:00
|
|
|
}
|
2021-04-26 10:35:59 +00:00
|
|
|
|
|
|
|
|
if (!isValid) {
|
2021-01-04 10:16:08 +00:00
|
|
|
return {
|
|
|
|
|
isValid: false,
|
2021-04-26 10:35:59 +00:00
|
|
|
parsed: [],
|
|
|
|
|
transformed: transformed,
|
2021-01-04 10:16:08 +00:00
|
|
|
message: validationMessage,
|
|
|
|
|
};
|
|
|
|
|
}
|
2021-04-26 10:35:59 +00:00
|
|
|
|
|
|
|
|
return { isValid, parsed, transformed };
|
2021-01-04 10:16:08 +00:00
|
|
|
},
|
2021-03-24 22:05:04 +00:00
|
|
|
[VALIDATION_TYPES.CUSTOM_FUSION_CHARTS_DATA]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
): ValidationResponse => {
|
|
|
|
|
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.OBJECT](
|
|
|
|
|
value,
|
|
|
|
|
props,
|
|
|
|
|
dataTree,
|
|
|
|
|
);
|
|
|
|
|
if (props.chartName && parsed.dataSource && parsed.dataSource.chart) {
|
|
|
|
|
parsed.dataSource.chart.caption = props.chartName;
|
|
|
|
|
}
|
2021-04-26 10:35:59 +00:00
|
|
|
|
2021-03-24 22:05:04 +00:00
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid,
|
|
|
|
|
parsed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "{type: string, dataSource: { chart: object, data: Array<{label: string, value: number}>}}"`,
|
2021-03-24 22:05:04 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (parsed.renderAt) {
|
|
|
|
|
delete parsed.renderAt;
|
|
|
|
|
}
|
|
|
|
|
if (!parsed.dataSource || !parsed.type) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: parsed,
|
|
|
|
|
transformed: parsed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "{type: string, dataSource: { chart: object, data: Array<{label: string, value: number}>}}"`,
|
2021-03-24 22:05:04 +00:00
|
|
|
};
|
|
|
|
|
}
|
2021-06-01 14:57:58 +00:00
|
|
|
// check custom chart exist or not
|
|
|
|
|
const typeExist = indexOf(CUSTOM_CHART_TYPES, parsed.type) !== -1;
|
|
|
|
|
if (!typeExist) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: { ...CUSTOM_CHART_DEFAULT_PARSED },
|
|
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "{type: string, dataSource: { chart: object, data: Array<{label: string, value: number}>}}"`,
|
|
|
|
|
};
|
|
|
|
|
}
|
2021-03-24 22:05:04 +00:00
|
|
|
return { isValid, parsed, transformed: parsed };
|
|
|
|
|
},
|
2021-01-04 10:16:08 +00:00
|
|
|
[VALIDATION_TYPES.MARKERS]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
): ValidationResponse => {
|
|
|
|
|
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
|
|
|
|
|
value,
|
|
|
|
|
props,
|
|
|
|
|
dataTree,
|
|
|
|
|
);
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid,
|
|
|
|
|
parsed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<{ lat: number, long: number }>"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
2021-01-19 07:29:15 +00:00
|
|
|
} else if (
|
|
|
|
|
!every(
|
|
|
|
|
parsed,
|
|
|
|
|
(datum) => VALIDATORS[VALIDATION_TYPES.LAT_LONG](datum, props).isValid,
|
|
|
|
|
)
|
|
|
|
|
) {
|
2021-01-04 10:16:08 +00:00
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: [],
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<{ lat: number, long: number }>"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.OPTIONS_DATA]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
): ValidationResponse => {
|
|
|
|
|
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
|
|
|
|
|
value,
|
|
|
|
|
props,
|
|
|
|
|
dataTree,
|
|
|
|
|
);
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid,
|
|
|
|
|
parsed,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<{ label: string, value: string }>"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
const isValidOption = (option: { label: any; value: any }) =>
|
|
|
|
|
_.isObject(option) &&
|
|
|
|
|
_.isString(option.label) &&
|
2021-03-15 09:55:37 +00:00
|
|
|
!_.isEmpty(option.label);
|
2021-01-04 10:16:08 +00:00
|
|
|
|
|
|
|
|
const hasOptions = every(parsed, isValidOption);
|
|
|
|
|
const validOptions = parsed.filter(isValidOption);
|
|
|
|
|
const uniqValidOptions = _.uniqBy(validOptions, "value");
|
|
|
|
|
|
|
|
|
|
if (!hasOptions || uniqValidOptions.length !== validOptions.length) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: uniqValidOptions,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<{ label: string, value: string }>"`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: [],
|
|
|
|
|
transformed: parsed,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
},
|
2021-03-24 12:12:24 +00:00
|
|
|
[VALIDATION_TYPES.DATE_ISO_STRING]: (
|
2021-01-04 10:16:08 +00:00
|
|
|
dateString: string,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
): ValidationResponse => {
|
2021-02-23 12:35:09 +00:00
|
|
|
const dateFormat =
|
|
|
|
|
props.version === 2
|
|
|
|
|
? ISO_DATE_FORMAT
|
|
|
|
|
: props.dateFormat || ISO_DATE_FORMAT;
|
2021-03-24 12:12:24 +00:00
|
|
|
if (dateString === null) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
|
|
|
|
parsed: "",
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
}
|
2021-01-04 10:16:08 +00:00
|
|
|
if (dateString === undefined) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: "",
|
|
|
|
|
message:
|
2021-05-21 08:48:59 +00:00
|
|
|
`${WIDGET_TYPE_VALIDATION_ERROR}: Date String ` +
|
|
|
|
|
(props.dateFormat ? props.dateFormat : ""),
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
2021-03-24 12:12:24 +00:00
|
|
|
const isValid = validateDateString(dateString, dateFormat, props.version);
|
2021-03-30 09:02:25 +00:00
|
|
|
let parsedDate = dateString;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (isValid && props.version === 2) {
|
|
|
|
|
parsedDate = moment(dateString).toISOString(true);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error("Could not parse date", parsedDate, e);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-02 14:42:49 +00:00
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValid,
|
|
|
|
|
parsed: "",
|
2021-03-24 12:12:24 +00:00
|
|
|
message: `Value does not match ISO 8601 standard date string`,
|
2021-02-02 14:42:49 +00:00
|
|
|
};
|
|
|
|
|
}
|
2021-01-04 10:16:08 +00:00
|
|
|
return {
|
|
|
|
|
isValid,
|
2021-03-30 09:02:25 +00:00
|
|
|
parsed: parsedDate,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: isValid
|
|
|
|
|
? ""
|
|
|
|
|
: `Value does not match ISO 8601 standard date string`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.DEFAULT_DATE]: (
|
|
|
|
|
dateString: string,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
): ValidationResponse => {
|
2021-02-23 12:35:09 +00:00
|
|
|
const dateFormat =
|
|
|
|
|
props.version === 2
|
|
|
|
|
? ISO_DATE_FORMAT
|
|
|
|
|
: props.dateFormat || ISO_DATE_FORMAT;
|
2021-03-24 12:12:24 +00:00
|
|
|
if (dateString === null) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
|
|
|
|
parsed: "",
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
}
|
2021-01-04 10:16:08 +00:00
|
|
|
if (dateString === undefined) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: "",
|
|
|
|
|
message:
|
2021-05-21 08:48:59 +00:00
|
|
|
`${WIDGET_TYPE_VALIDATION_ERROR}: Date String ` +
|
|
|
|
|
(dateFormat ? dateFormat : ""),
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
}
|
2021-03-30 09:02:25 +00:00
|
|
|
|
2021-03-24 12:12:24 +00:00
|
|
|
const isValid = validateDateString(dateString, dateFormat, props.version);
|
2021-03-30 09:02:25 +00:00
|
|
|
let parsedDate = dateString;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (isValid && props.version === 2) {
|
|
|
|
|
parsedDate = moment(dateString).toISOString(true);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error("Could not parse date", parsedDate, e);
|
|
|
|
|
}
|
2021-02-02 14:42:49 +00:00
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValid,
|
|
|
|
|
parsed: "",
|
2021-03-24 12:12:24 +00:00
|
|
|
message: `Value does not match ISO 8601 standard date string`,
|
2021-02-02 14:42:49 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValid,
|
2021-03-30 09:02:25 +00:00
|
|
|
parsed: parsedDate,
|
2021-02-02 14:42:49 +00:00
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.MIN_DATE]: (
|
|
|
|
|
dateString: string,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
): ValidationResponse => {
|
2021-02-23 12:35:09 +00:00
|
|
|
const dateFormat =
|
|
|
|
|
props.version === 2
|
|
|
|
|
? ISO_DATE_FORMAT
|
|
|
|
|
: props.dateFormat || ISO_DATE_FORMAT;
|
2021-02-02 14:42:49 +00:00
|
|
|
if (dateString === undefined) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: "",
|
|
|
|
|
message:
|
2021-05-21 08:48:59 +00:00
|
|
|
`${WIDGET_TYPE_VALIDATION_ERROR}: Date String ` +
|
|
|
|
|
(dateFormat ? dateFormat : ""),
|
2021-02-02 14:42:49 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const parsedMinDate = moment(dateString, dateFormat);
|
2021-03-24 12:12:24 +00:00
|
|
|
let isValid = validateDateString(dateString, dateFormat, props.version);
|
2021-02-02 14:42:49 +00:00
|
|
|
if (!props.defaultDate) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValid,
|
|
|
|
|
parsed: dateString,
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const parsedDefaultDate = moment(props.defaultDate, dateFormat);
|
2021-01-04 10:16:08 +00:00
|
|
|
|
2021-02-02 14:42:49 +00:00
|
|
|
if (
|
|
|
|
|
isValid &&
|
|
|
|
|
parsedDefaultDate.isValid() &&
|
|
|
|
|
parsedDefaultDate.isBefore(parsedMinDate)
|
|
|
|
|
) {
|
|
|
|
|
isValid = false;
|
|
|
|
|
}
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValid,
|
|
|
|
|
parsed: "",
|
2021-05-21 08:48:59 +00:00
|
|
|
message:
|
|
|
|
|
`${WIDGET_TYPE_VALIDATION_ERROR}: Date String ` +
|
|
|
|
|
(dateFormat ? dateFormat : ""),
|
2021-02-02 14:42:49 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValid,
|
|
|
|
|
parsed: dateString,
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.MAX_DATE]: (
|
|
|
|
|
dateString: string,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
): ValidationResponse => {
|
2021-02-23 12:35:09 +00:00
|
|
|
const dateFormat =
|
|
|
|
|
props.version === 2
|
|
|
|
|
? ISO_DATE_FORMAT
|
|
|
|
|
: props.dateFormat || ISO_DATE_FORMAT;
|
2021-02-02 14:42:49 +00:00
|
|
|
if (dateString === undefined) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: "",
|
|
|
|
|
message:
|
2021-05-21 08:48:59 +00:00
|
|
|
`${WIDGET_TYPE_VALIDATION_ERROR}: Date String ` +
|
|
|
|
|
(dateFormat ? dateFormat : ""),
|
2021-02-02 14:42:49 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const parsedMaxDate = moment(dateString, dateFormat);
|
2021-03-24 12:12:24 +00:00
|
|
|
let isValid = validateDateString(dateString, dateFormat, props.version);
|
2021-02-02 14:42:49 +00:00
|
|
|
if (!props.defaultDate) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValid,
|
|
|
|
|
parsed: dateString,
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const parsedDefaultDate = moment(props.defaultDate, dateFormat);
|
2021-01-04 10:16:08 +00:00
|
|
|
|
2021-02-02 14:42:49 +00:00
|
|
|
if (
|
|
|
|
|
isValid &&
|
|
|
|
|
parsedDefaultDate.isValid() &&
|
|
|
|
|
parsedDefaultDate.isAfter(parsedMaxDate)
|
|
|
|
|
) {
|
|
|
|
|
isValid = false;
|
|
|
|
|
}
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValid,
|
|
|
|
|
parsed: "",
|
2021-05-21 08:48:59 +00:00
|
|
|
message:
|
|
|
|
|
`${WIDGET_TYPE_VALIDATION_ERROR}: Date String ` +
|
|
|
|
|
(dateFormat ? dateFormat : ""),
|
2021-02-02 14:42:49 +00:00
|
|
|
};
|
|
|
|
|
}
|
2021-01-04 10:16:08 +00:00
|
|
|
return {
|
2021-02-02 14:42:49 +00:00
|
|
|
isValid: isValid,
|
|
|
|
|
parsed: dateString,
|
|
|
|
|
message: "",
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.ACTION_SELECTOR]: (value: any): ValidationResponse => {
|
|
|
|
|
if (Array.isArray(value) && value.length) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
|
|
|
|
parsed: undefined,
|
|
|
|
|
transformed: "Function Call",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: undefined,
|
|
|
|
|
transformed: "undefined",
|
|
|
|
|
message: "Not a function call",
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.ARRAY_ACTION_SELECTOR]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
): ValidationResponse => {
|
2021-05-13 08:35:39 +00:00
|
|
|
const { isValid, message, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
|
2021-01-04 10:16:08 +00:00
|
|
|
value,
|
|
|
|
|
props,
|
|
|
|
|
dataTree,
|
|
|
|
|
);
|
|
|
|
|
let isValidFinal = isValid;
|
|
|
|
|
let finalParsed = parsed.slice();
|
|
|
|
|
if (isValid) {
|
|
|
|
|
finalParsed = parsed.map((value: any) => {
|
|
|
|
|
const { isValid, message } = VALIDATORS[
|
|
|
|
|
VALIDATION_TYPES.ACTION_SELECTOR
|
|
|
|
|
](value.dynamicTrigger, props, dataTree);
|
|
|
|
|
|
|
|
|
|
isValidFinal = isValidFinal && isValid;
|
|
|
|
|
return {
|
|
|
|
|
...value,
|
|
|
|
|
message: message,
|
|
|
|
|
isValid: isValid,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValidFinal,
|
|
|
|
|
parsed: finalParsed,
|
|
|
|
|
message: message,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.SELECTED_TAB]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
): ValidationResponse => {
|
2021-04-27 07:16:54 +00:00
|
|
|
const tabs: any = props.tabsObj
|
|
|
|
|
? Object.values(props.tabsObj)
|
|
|
|
|
: props.tabs || [];
|
2021-01-04 10:16:08 +00:00
|
|
|
const tabNames = tabs.map((i: { label: string; id: string }) => i.label);
|
|
|
|
|
const isValidTabName = tabNames.includes(value);
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValidTabName,
|
2021-04-27 07:16:54 +00:00
|
|
|
parsed: isValidTabName ? value : "",
|
|
|
|
|
message: isValidTabName ? "" : `Tab name provided does not exist.`,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.DEFAULT_OPTION_VALUE]: (
|
|
|
|
|
value: string | string[],
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
) => {
|
|
|
|
|
let values = value;
|
|
|
|
|
|
|
|
|
|
if (props) {
|
|
|
|
|
if (props.selectionType === "SINGLE_SELECT") {
|
2021-05-04 17:12:15 +00:00
|
|
|
const defaultValue = value && _.isString(value) ? value.trim() : value;
|
2021-04-27 05:59:52 +00:00
|
|
|
return VALIDATORS[VALIDATION_TYPES.TEXT](defaultValue, props, dataTree);
|
2021-01-04 10:16:08 +00:00
|
|
|
} else if (props.selectionType === "MULTI_SELECT") {
|
|
|
|
|
if (typeof value === "string") {
|
|
|
|
|
try {
|
|
|
|
|
values = JSON.parse(value);
|
|
|
|
|
if (!Array.isArray(values)) {
|
|
|
|
|
throw new Error();
|
|
|
|
|
}
|
|
|
|
|
} catch {
|
|
|
|
|
values = value.length ? value.split(",") : [];
|
|
|
|
|
if (values.length > 0) {
|
|
|
|
|
values = values.map((value) => value.trim());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(values)) {
|
|
|
|
|
values = _.uniq(values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
|
|
|
|
parsed: values,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.DEFAULT_SELECTED_ROW]: (
|
|
|
|
|
value: string | string[],
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
) => {
|
|
|
|
|
if (props) {
|
|
|
|
|
if (props.multiRowSelection) {
|
2021-03-24 19:25:38 +00:00
|
|
|
return VALIDATORS[VALIDATION_TYPES.ROW_INDICES](value, props);
|
2021-01-04 10:16:08 +00:00
|
|
|
} else {
|
|
|
|
|
try {
|
2021-03-24 19:25:38 +00:00
|
|
|
const _value: string = value as string;
|
|
|
|
|
if (
|
|
|
|
|
Number.isInteger(parseInt(_value, 10)) &&
|
|
|
|
|
parseInt(_value, 10) > -1
|
|
|
|
|
)
|
|
|
|
|
return { isValid: true, parsed: parseInt(_value, 10) };
|
|
|
|
|
|
2021-01-04 10:16:08 +00:00
|
|
|
return {
|
|
|
|
|
isValid: true,
|
2021-03-24 19:25:38 +00:00
|
|
|
parsed: -1,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
|
|
|
|
parsed: -1,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
2021-03-24 19:25:38 +00:00
|
|
|
parsed: value,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
|
|
|
|
},
|
2021-02-16 10:29:08 +00:00
|
|
|
[VALIDATION_TYPES.COLUMN_PROPERTIES_ARRAY]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
dataTree?: DataTree,
|
|
|
|
|
) => {
|
|
|
|
|
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
|
|
|
|
|
value,
|
|
|
|
|
props,
|
|
|
|
|
dataTree,
|
|
|
|
|
);
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
return {
|
|
|
|
|
isValid,
|
|
|
|
|
parsed,
|
|
|
|
|
transformed: parsed,
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const isValidProperty = (data: any) =>
|
|
|
|
|
isString(data) || isNumber(data) || isBoolean(data);
|
|
|
|
|
const isValidColumns = every(parsed, (datum: any) => {
|
|
|
|
|
const validatedResponse: {
|
|
|
|
|
isValid: boolean;
|
|
|
|
|
parsed: Record<string, unknown>;
|
|
|
|
|
message?: string;
|
|
|
|
|
} = VALIDATORS[VALIDATION_TYPES.OBJECT](datum, props, dataTree);
|
|
|
|
|
const isValidColumn = validatedResponse.isValid;
|
|
|
|
|
if (isValidColumn) {
|
|
|
|
|
for (const key in validatedResponse.parsed) {
|
|
|
|
|
const columnProperty = validatedResponse.parsed[key];
|
|
|
|
|
let isValidColumnProperty = true;
|
|
|
|
|
if (Array.isArray(columnProperty)) {
|
|
|
|
|
isValidColumnProperty = every(columnProperty, (data: any) => {
|
|
|
|
|
return isValidProperty(data);
|
|
|
|
|
});
|
|
|
|
|
} else if (!isObject(columnProperty)) {
|
|
|
|
|
isValidColumnProperty = isValidProperty(columnProperty);
|
|
|
|
|
}
|
|
|
|
|
if (!isValidColumnProperty) {
|
|
|
|
|
validatedResponse.parsed[key] = "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return isValidColumn;
|
|
|
|
|
});
|
|
|
|
|
if (!isValidColumns) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: isValidColumns,
|
|
|
|
|
parsed: [],
|
|
|
|
|
transformed: parsed,
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed, transformed: parsed };
|
|
|
|
|
},
|
2021-01-19 07:29:15 +00:00
|
|
|
[VALIDATION_TYPES.LAT_LONG]: (unparsedValue: {
|
|
|
|
|
lat?: number;
|
|
|
|
|
long?: number;
|
|
|
|
|
[x: string]: any;
|
|
|
|
|
}): ValidationResponse => {
|
|
|
|
|
let value = unparsedValue;
|
|
|
|
|
const invalidResponse = {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: undefined,
|
2021-04-23 13:50:55 +00:00
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR} "{ lat: number, long: number }"`,
|
2021-01-19 07:29:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (isString(unparsedValue)) {
|
|
|
|
|
try {
|
|
|
|
|
value = JSON.parse(unparsedValue);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(`Error when parsing string as object`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { lat, long } = value || {};
|
|
|
|
|
const validLat = typeof lat === "number" && lat <= 90 && lat >= -90;
|
|
|
|
|
const validLong = typeof long === "number" && long <= 180 && long >= -180;
|
|
|
|
|
|
|
|
|
|
if (!validLat || !validLong) {
|
|
|
|
|
return invalidResponse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
|
|
|
|
parsed: value,
|
|
|
|
|
};
|
|
|
|
|
},
|
2021-04-30 07:00:13 +00:00
|
|
|
[VALIDATION_TYPES.IMAGE]: (value: any): ValidationResponse => {
|
|
|
|
|
let parsed = value;
|
|
|
|
|
const base64ImageRegex = /^data:image\/.*;base64/;
|
|
|
|
|
const imageUrlRegex = /(http(s?):)([/|.|\w|\s|-])*\.(?:jpeg|jpg|gif|png)??(?:&?[^=&]*=[^=&]*)*/;
|
|
|
|
|
if (isUndefined(value) || value === null) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
|
|
|
|
parsed: value,
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (isObject(value)) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: JSON.stringify(value, null, 2),
|
|
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR}: text`,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (imageUrlRegex.test(value)) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: true,
|
|
|
|
|
parsed: value,
|
|
|
|
|
message: "",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
let isValid = base64ImageRegex.test(value);
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
try {
|
|
|
|
|
parsed =
|
|
|
|
|
btoa(atob(value)) === value
|
|
|
|
|
? "data:image/png;base64," + value
|
|
|
|
|
: value;
|
|
|
|
|
isValid = true;
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error(`Error when parsing ${value} to string`);
|
|
|
|
|
console.error(err);
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: "",
|
|
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR}: text`,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return { isValid, parsed };
|
|
|
|
|
},
|
2021-03-24 19:25:38 +00:00
|
|
|
// If we keep adding these here there will be a huge unmaintainable list
|
|
|
|
|
// TODO(abhinav: WIDGET DEV API):
|
|
|
|
|
// - Compile validators from the widgets during widget registration
|
|
|
|
|
// - Use the compiled list in the web worker startup
|
|
|
|
|
// - Remove widget specific validations from this file
|
|
|
|
|
// - Design consideration: If widgets can be dynamically imported, how will this work?
|
|
|
|
|
[VALIDATION_TYPES.TABLE_PAGE_NO]: (value: any): ValidationResponse => {
|
|
|
|
|
if (!value || !Number.isInteger(value) || value < 0)
|
|
|
|
|
return { isValid: false, parsed: 1, message: "" };
|
|
|
|
|
return { isValid: true, parsed: value };
|
|
|
|
|
},
|
|
|
|
|
[VALIDATION_TYPES.ROW_INDICES]: (
|
|
|
|
|
value: any,
|
|
|
|
|
props: any,
|
|
|
|
|
): ValidationResponse => {
|
|
|
|
|
if (props && !props.multiRowSelection)
|
|
|
|
|
return { isValid: true, parsed: undefined };
|
|
|
|
|
|
|
|
|
|
if (isString(value)) {
|
|
|
|
|
const trimmed = value.trim();
|
|
|
|
|
try {
|
|
|
|
|
const parsedArray = JSON.parse(trimmed);
|
|
|
|
|
if (Array.isArray(parsedArray)) {
|
|
|
|
|
const sanitized = parsedArray.filter((entry) => {
|
|
|
|
|
return (
|
|
|
|
|
Number.isInteger(parseInt(entry, 10)) && parseInt(entry, 10) > -1
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
return { isValid: true, parsed: sanitized };
|
|
|
|
|
} else {
|
|
|
|
|
throw Error("Not a stringified array");
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// If cannot be parsed as an array
|
|
|
|
|
const arrayEntries = trimmed.split(",");
|
|
|
|
|
const result: number[] = [];
|
|
|
|
|
arrayEntries.forEach((entry) => {
|
|
|
|
|
if (
|
|
|
|
|
Number.isInteger(parseInt(entry, 10)) &&
|
|
|
|
|
parseInt(entry, 10) > -1
|
|
|
|
|
) {
|
|
|
|
|
if (!isNil(entry)) result.push(parseInt(entry, 10));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return { isValid: true, parsed: result };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (Array.isArray(value)) {
|
|
|
|
|
const sanitized = value.filter((entry) => {
|
|
|
|
|
return (
|
|
|
|
|
Number.isInteger(parseInt(entry, 10)) && parseInt(entry, 10) > -1
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
return { isValid: true, parsed: sanitized };
|
|
|
|
|
}
|
|
|
|
|
if (Number.isInteger(value) && value > -1) {
|
|
|
|
|
return { isValid: true, parsed: [value] };
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
parsed: [],
|
|
|
|
|
message: `${WIDGET_TYPE_VALIDATION_ERROR}: number[]`,
|
|
|
|
|
};
|
|
|
|
|
},
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|