PromucFlow_constructor/app/client/src/workers/validations.ts

1037 lines
27 KiB
TypeScript
Raw Normal View History

import {
ISO_DATE_FORMAT,
VALIDATION_TYPES,
ValidationResponse,
Validator,
} from "../constants/WidgetValidation";
import { DataTree } from "../entities/DataTree/dataTreeFactory";
import _, {
every,
indexOf,
isBoolean,
isNil,
isNumber,
isObject,
isPlainObject,
isString,
isUndefined,
toNumber,
toString,
} from "lodash";
import { WidgetProps } from "../widgets/BaseWidget";
import {
CUSTOM_CHART_TYPES,
CUSTOM_CHART_DEFAULT_PARSED,
} from "../constants/CustomChartConstants";
import moment from "moment";
export function validateDateString(
dateString: string,
dateFormat: string,
version: number,
) {
let isValid = true;
if (version === 2) {
try {
const d = moment(dateString);
isValid =
d.toISOString(true) === dateString || d.toISOString() === dateString;
if (!isValid) {
const parsedDate = moment(dateString);
isValid = parsedDate.isValid();
}
} 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
export const VALIDATORS: Record<VALIDATION_TYPES, Validator> = {
[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"`,
};
}
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"`,
};
}
}
return { isValid, parsed };
},
[VALIDATION_TYPES.REGEX]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
const { isValid, message, parsed } = VALIDATORS[VALIDATION_TYPES.TEXT](
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"`,
};
}
}
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"`,
};
}
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"`,
};
}
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"`,
};
}
}
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"`,
};
}
const isABoolean = isBoolean(value);
const isStringTrueFalse = value === "true" || value === "false";
const isValid = isABoolean || isStringTrueFalse;
if (isStringTrueFalse) parsed = value !== "false";
if (!isValid) {
return {
isValid: isValid,
parsed: !!parsed,
2021-04-23 13:50:55 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR} "boolean"`,
};
}
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"`,
};
}
if (isString(value)) {
parsed = JSON.parse(parsed as string);
}
if (!Array.isArray(parsed)) {
return {
isValid: false,
parsed: [],
transformed: parsed,
2021-04-23 13:50:55 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array"`,
};
}
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"`,
};
}
},
[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) }>"`,
};
} else if (
!every(
parsed,
(datum: {
id: string;
label: string;
widgetId: string;
isVisible?: boolean;
}) =>
isObject(datum) &&
!isUndefined(datum.id) &&
!isUndefined(datum.label) &&
!isUndefined(datum.widgetId),
)
) {
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) }>"`,
};
}
return { isValid, parsed };
},
[Feature] Grid Widget (#2389) * Updated test * updated assertions * Resizing image to take full width of table cell * updated assertion * Stop updating dynamicBindingPathList directly from widget * Fix selectedRow and selectedRows computations * Fix primaryColumns computations * Updated test for derived column * Added tests for computed value * Added check clear data * Reordering of test * updated common method * Made image size as 100% of table cell size * add templating logic * Updated flow and dsl * Clear old primary columns * Updated testname * updated assertion * use evaluated values for children * Fix primary columns update on component mount and component update * add isArray check * remove property pane enhancement reducer * add property pane enhancement reducer * disable items other than template + fix running property enchancment on drop of list widget * disbled drag, resize, settingsControl, drag for items other than template * add grid options * uncomment the widget operation for add child for grid children * handle delete scenario for child widget in list widget * WIP: Use the new delete and update property features * add listdsl.json for testcases * add test cases for correct no. of items being rendered * add test cases currentItem binding in list widget * change dragEnabled to dragDisabled * change resizeEnabled to resizeDisabled * change settingsControlEnabled to settingsControlDisabled * change dropEnabled to dropDisabled * update settingsControlDisabled default value * Use deleteProperties in propertyControls * Fix unsetting of array indices when deleting widget properties * remove old TableWidget.tsx file * Fix derived column property update on primary column property update * Handle undefined primary columns * Fix filepicker immutable prop issue * Fix object.freeze issue when adding ids to the property pane configuration * fix widget issue in grid * Fix column actions dynamicBindingPathList inclusion issue * remove consoles + fix typo around batch update * Remove redundant tests * js binding test for date picker * hydate enhancement map on copy list widget * check for dynamicleaf * fixes * improve check * fix getNextWidgetName * update template in list widget when copying * updating template copy logic when copying widget * update dynamicBindingPathList in copied widget * Add path parameter to hidden functions in property pane configs * fix copy bug when copying list widget * add computed list property control * Remove time column type Fix editor prompt for currentRow Fix undefined derivedColumns scenario Remove validations for primaryColums and derivedColumns Fix section toggle for video, image and button column types * Fix table widget actions and custom column migrations * Add logs for cyclical dependency map :recycle: * Process array differences * add property control for list widget * Fix onClick migrations * Property pane config parity * binding and trigger paths from the property pane config (#2920) * try react virtualized library * Fix unit test * Fix unit test :white_check_mark: * Fix minor issues in table widget * Add default meta props to binding paths to ensure eval and validation * Dummy commit :tada: * Remove unnecessary datepicker test Fix chart data as string issue * Achieve table column sorting and resizing parity with release * handle scenario where last column isn't available to access * Fix for panel config path not existing in the widget * Fix bindings in currentRow (default) Add dummy property pane config for canvas widget * Update canvas widgets with dynamicPathLists on delete of property paths * Add all diffs to change paths and trim later * Add back default properties 🚶🏻‍♂️ * Use object based paths instead of arrays for primaryColumns and derivedColumns * Fix issue in reordered columns * Fix inccorect update order * add virtualized list * Fix failing property pane tests * minor change * minor list widget change * Remove .vscode from git * Rename ads to alloy Fix isVisible in list widget * move grid component to widget folder * fix import in widget registry * add sticky row in virtualized list * add sticky container * Fix Height of grid widget items container * fix dragging of items in children other than template children * update list widget * update list widget * Fix padding in list widget * hide scrollbar in list widget list * fix copy bug in list widget * regenrate enhancement map on undo delete widget * Use enhancementmap for autocomplete in list widget Basic styles for list widget scrollbar * add custom control in widget config * minor commit * update scrollbar styles * remove unused variable * fix typo in custom control * comment out test cases * remove unused imports * remove unused imports * add JSON stringify in interweave * add noPad styling in dragLayer for noPad prop * implement grid gap * add list item background color prop * add white color in color picker control * fix gap in last list item * remove onBeforeParse in textcomponent * remove virtualization in grid widget * allow overflow-y * add onListItemClick action * add beta label * add pagination * fix actions in pagination in list widget * add list widget icon * add list background color default value * remove extra div * fix pagination issue * fix list widget crashing on perpage change * extract child operation function to widgetblueprint saga * refactor enhancements * add enhancement hook * refactor propertyUpdate hook enhancment * remove enhacement map * revert renaming ads to alloy * add autopagination * Cleanup unused vars Re-write loop using map Fix binding with external input widget * update default background color * remove unnessary scrol + fix pagination per page * remove console.log * use grid gap in pixel instead of snap * fix list widget tests for binding * add tests for on click action and pagination * remove unnecessary imports * remove overflow hidden in list component * Add feature to enable template actions * update property pane help text for list widget * disable pagination in editor view * update property pane options * add test case for action * uncomment tests * fix grid gap validation * update test cases * fix property pane opening issue for list tempalte * Disable form widgets in list widget * fix template issue for actions * add validation tests for list data * update starting template * add selectedRow + enable pagination in edit mode * remove extra padding in list widget + popper fix on settingDisabled * add stop propagation for button click * fix click event in edit mode * disallow filepicker widget for list widget * add test for list widget entity definition for selectItem * remove unused imports * fix test * remove evaluated value for list child widgets * add comment * remove log * fix copying bug in list widget * add check for not allowing template to copy * fix test * add test for property pane actions * remove unused import * add draglayercomponent test * add test for draggable component * add test for evaluatedvalue popup * add test for messages.ts * add test for widgeticons * add test for property pane selector * add test for widget config response * start testing widget configresponse * add test for enhancements in widget config * add test for codeeditor * add test for base widget + list widget * add test for executeWidgetBlueprintChildOperations * remove unused import * add test for widget operation utils * remove unused import * add test for handleSpecificCasesWhilePasting * remove unused function * remove unused import * add empty list styling * resolve all review comments * fix message test * add test for widget operation utils * fix merge conflicts * move validations in property config Co-authored-by: Abhinav Jha <abhinav@appsmith.com> Co-authored-by: nandan.anantharamu <nandan.anantharamu@thoughtspot.com> Co-authored-by: vicky-primathon.in <vicky.bansal@primathon.in> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local> Co-authored-by: Piyush <piyush@codeitout.com> Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain>
2021-04-23 05:43:13 +00:00
[VALIDATION_TYPES.LIST_DATA]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
const { isValid, parsed, transformed } = VALIDATORS.ARRAY(
[Feature] Grid Widget (#2389) * Updated test * updated assertions * Resizing image to take full width of table cell * updated assertion * Stop updating dynamicBindingPathList directly from widget * Fix selectedRow and selectedRows computations * Fix primaryColumns computations * Updated test for derived column * Added tests for computed value * Added check clear data * Reordering of test * updated common method * Made image size as 100% of table cell size * add templating logic * Updated flow and dsl * Clear old primary columns * Updated testname * updated assertion * use evaluated values for children * Fix primary columns update on component mount and component update * add isArray check * remove property pane enhancement reducer * add property pane enhancement reducer * disable items other than template + fix running property enchancment on drop of list widget * disbled drag, resize, settingsControl, drag for items other than template * add grid options * uncomment the widget operation for add child for grid children * handle delete scenario for child widget in list widget * WIP: Use the new delete and update property features * add listdsl.json for testcases * add test cases for correct no. of items being rendered * add test cases currentItem binding in list widget * change dragEnabled to dragDisabled * change resizeEnabled to resizeDisabled * change settingsControlEnabled to settingsControlDisabled * change dropEnabled to dropDisabled * update settingsControlDisabled default value * Use deleteProperties in propertyControls * Fix unsetting of array indices when deleting widget properties * remove old TableWidget.tsx file * Fix derived column property update on primary column property update * Handle undefined primary columns * Fix filepicker immutable prop issue * Fix object.freeze issue when adding ids to the property pane configuration * fix widget issue in grid * Fix column actions dynamicBindingPathList inclusion issue * remove consoles + fix typo around batch update * Remove redundant tests * js binding test for date picker * hydate enhancement map on copy list widget * check for dynamicleaf * fixes * improve check * fix getNextWidgetName * update template in list widget when copying * updating template copy logic when copying widget * update dynamicBindingPathList in copied widget * Add path parameter to hidden functions in property pane configs * fix copy bug when copying list widget * add computed list property control * Remove time column type Fix editor prompt for currentRow Fix undefined derivedColumns scenario Remove validations for primaryColums and derivedColumns Fix section toggle for video, image and button column types * Fix table widget actions and custom column migrations * Add logs for cyclical dependency map :recycle: * Process array differences * add property control for list widget * Fix onClick migrations * Property pane config parity * binding and trigger paths from the property pane config (#2920) * try react virtualized library * Fix unit test * Fix unit test :white_check_mark: * Fix minor issues in table widget * Add default meta props to binding paths to ensure eval and validation * Dummy commit :tada: * Remove unnecessary datepicker test Fix chart data as string issue * Achieve table column sorting and resizing parity with release * handle scenario where last column isn't available to access * Fix for panel config path not existing in the widget * Fix bindings in currentRow (default) Add dummy property pane config for canvas widget * Update canvas widgets with dynamicPathLists on delete of property paths * Add all diffs to change paths and trim later * Add back default properties 🚶🏻‍♂️ * Use object based paths instead of arrays for primaryColumns and derivedColumns * Fix issue in reordered columns * Fix inccorect update order * add virtualized list * Fix failing property pane tests * minor change * minor list widget change * Remove .vscode from git * Rename ads to alloy Fix isVisible in list widget * move grid component to widget folder * fix import in widget registry * add sticky row in virtualized list * add sticky container * Fix Height of grid widget items container * fix dragging of items in children other than template children * update list widget * update list widget * Fix padding in list widget * hide scrollbar in list widget list * fix copy bug in list widget * regenrate enhancement map on undo delete widget * Use enhancementmap for autocomplete in list widget Basic styles for list widget scrollbar * add custom control in widget config * minor commit * update scrollbar styles * remove unused variable * fix typo in custom control * comment out test cases * remove unused imports * remove unused imports * add JSON stringify in interweave * add noPad styling in dragLayer for noPad prop * implement grid gap * add list item background color prop * add white color in color picker control * fix gap in last list item * remove onBeforeParse in textcomponent * remove virtualization in grid widget * allow overflow-y * add onListItemClick action * add beta label * add pagination * fix actions in pagination in list widget * add list widget icon * add list background color default value * remove extra div * fix pagination issue * fix list widget crashing on perpage change * extract child operation function to widgetblueprint saga * refactor enhancements * add enhancement hook * refactor propertyUpdate hook enhancment * remove enhacement map * revert renaming ads to alloy * add autopagination * Cleanup unused vars Re-write loop using map Fix binding with external input widget * update default background color * remove unnessary scrol + fix pagination per page * remove console.log * use grid gap in pixel instead of snap * fix list widget tests for binding * add tests for on click action and pagination * remove unnecessary imports * remove overflow hidden in list component * Add feature to enable template actions * update property pane help text for list widget * disable pagination in editor view * update property pane options * add test case for action * uncomment tests * fix grid gap validation * update test cases * fix property pane opening issue for list tempalte * Disable form widgets in list widget * fix template issue for actions * add validation tests for list data * update starting template * add selectedRow + enable pagination in edit mode * remove extra padding in list widget + popper fix on settingDisabled * add stop propagation for button click * fix click event in edit mode * disallow filepicker widget for list widget * add test for list widget entity definition for selectItem * remove unused imports * fix test * remove evaluated value for list child widgets * add comment * remove log * fix copying bug in list widget * add check for not allowing template to copy * fix test * add test for property pane actions * remove unused import * add draglayercomponent test * add test for draggable component * add test for evaluatedvalue popup * add test for messages.ts * add test for widgeticons * add test for property pane selector * add test for widget config response * start testing widget configresponse * add test for enhancements in widget config * add test for codeeditor * add test for base widget + list widget * add test for executeWidgetBlueprintChildOperations * remove unused import * add test for widget operation utils * remove unused import * add test for handleSpecificCasesWhilePasting * remove unused function * remove unused import * add empty list styling * resolve all review comments * fix message test * add test for widget operation utils * fix merge conflicts * move validations in property config Co-authored-by: Abhinav Jha <abhinav@appsmith.com> Co-authored-by: nandan.anantharamu <nandan.anantharamu@thoughtspot.com> Co-authored-by: vicky-primathon.in <vicky.bansal@primathon.in> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local> Co-authored-by: Piyush <piyush@codeitout.com> Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain>
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>"`,
[Feature] Grid Widget (#2389) * Updated test * updated assertions * Resizing image to take full width of table cell * updated assertion * Stop updating dynamicBindingPathList directly from widget * Fix selectedRow and selectedRows computations * Fix primaryColumns computations * Updated test for derived column * Added tests for computed value * Added check clear data * Reordering of test * updated common method * Made image size as 100% of table cell size * add templating logic * Updated flow and dsl * Clear old primary columns * Updated testname * updated assertion * use evaluated values for children * Fix primary columns update on component mount and component update * add isArray check * remove property pane enhancement reducer * add property pane enhancement reducer * disable items other than template + fix running property enchancment on drop of list widget * disbled drag, resize, settingsControl, drag for items other than template * add grid options * uncomment the widget operation for add child for grid children * handle delete scenario for child widget in list widget * WIP: Use the new delete and update property features * add listdsl.json for testcases * add test cases for correct no. of items being rendered * add test cases currentItem binding in list widget * change dragEnabled to dragDisabled * change resizeEnabled to resizeDisabled * change settingsControlEnabled to settingsControlDisabled * change dropEnabled to dropDisabled * update settingsControlDisabled default value * Use deleteProperties in propertyControls * Fix unsetting of array indices when deleting widget properties * remove old TableWidget.tsx file * Fix derived column property update on primary column property update * Handle undefined primary columns * Fix filepicker immutable prop issue * Fix object.freeze issue when adding ids to the property pane configuration * fix widget issue in grid * Fix column actions dynamicBindingPathList inclusion issue * remove consoles + fix typo around batch update * Remove redundant tests * js binding test for date picker * hydate enhancement map on copy list widget * check for dynamicleaf * fixes * improve check * fix getNextWidgetName * update template in list widget when copying * updating template copy logic when copying widget * update dynamicBindingPathList in copied widget * Add path parameter to hidden functions in property pane configs * fix copy bug when copying list widget * add computed list property control * Remove time column type Fix editor prompt for currentRow Fix undefined derivedColumns scenario Remove validations for primaryColums and derivedColumns Fix section toggle for video, image and button column types * Fix table widget actions and custom column migrations * Add logs for cyclical dependency map :recycle: * Process array differences * add property control for list widget * Fix onClick migrations * Property pane config parity * binding and trigger paths from the property pane config (#2920) * try react virtualized library * Fix unit test * Fix unit test :white_check_mark: * Fix minor issues in table widget * Add default meta props to binding paths to ensure eval and validation * Dummy commit :tada: * Remove unnecessary datepicker test Fix chart data as string issue * Achieve table column sorting and resizing parity with release * handle scenario where last column isn't available to access * Fix for panel config path not existing in the widget * Fix bindings in currentRow (default) Add dummy property pane config for canvas widget * Update canvas widgets with dynamicPathLists on delete of property paths * Add all diffs to change paths and trim later * Add back default properties 🚶🏻‍♂️ * Use object based paths instead of arrays for primaryColumns and derivedColumns * Fix issue in reordered columns * Fix inccorect update order * add virtualized list * Fix failing property pane tests * minor change * minor list widget change * Remove .vscode from git * Rename ads to alloy Fix isVisible in list widget * move grid component to widget folder * fix import in widget registry * add sticky row in virtualized list * add sticky container * Fix Height of grid widget items container * fix dragging of items in children other than template children * update list widget * update list widget * Fix padding in list widget * hide scrollbar in list widget list * fix copy bug in list widget * regenrate enhancement map on undo delete widget * Use enhancementmap for autocomplete in list widget Basic styles for list widget scrollbar * add custom control in widget config * minor commit * update scrollbar styles * remove unused variable * fix typo in custom control * comment out test cases * remove unused imports * remove unused imports * add JSON stringify in interweave * add noPad styling in dragLayer for noPad prop * implement grid gap * add list item background color prop * add white color in color picker control * fix gap in last list item * remove onBeforeParse in textcomponent * remove virtualization in grid widget * allow overflow-y * add onListItemClick action * add beta label * add pagination * fix actions in pagination in list widget * add list widget icon * add list background color default value * remove extra div * fix pagination issue * fix list widget crashing on perpage change * extract child operation function to widgetblueprint saga * refactor enhancements * add enhancement hook * refactor propertyUpdate hook enhancment * remove enhacement map * revert renaming ads to alloy * add autopagination * Cleanup unused vars Re-write loop using map Fix binding with external input widget * update default background color * remove unnessary scrol + fix pagination per page * remove console.log * use grid gap in pixel instead of snap * fix list widget tests for binding * add tests for on click action and pagination * remove unnecessary imports * remove overflow hidden in list component * Add feature to enable template actions * update property pane help text for list widget * disable pagination in editor view * update property pane options * add test case for action * uncomment tests * fix grid gap validation * update test cases * fix property pane opening issue for list tempalte * Disable form widgets in list widget * fix template issue for actions * add validation tests for list data * update starting template * add selectedRow + enable pagination in edit mode * remove extra padding in list widget + popper fix on settingDisabled * add stop propagation for button click * fix click event in edit mode * disallow filepicker widget for list widget * add test for list widget entity definition for selectItem * remove unused imports * fix test * remove evaluated value for list child widgets * add comment * remove log * fix copying bug in list widget * add check for not allowing template to copy * fix test * add test for property pane actions * remove unused import * add draglayercomponent test * add test for draggable component * add test for evaluatedvalue popup * add test for messages.ts * add test for widgeticons * add test for property pane selector * add test for widget config response * start testing widget configresponse * add test for enhancements in widget config * add test for codeeditor * add test for base widget + list widget * add test for executeWidgetBlueprintChildOperations * remove unused import * add test for widget operation utils * remove unused import * add test for handleSpecificCasesWhilePasting * remove unused function * remove unused import * add empty list styling * resolve all review comments * fix message test * add test for widget operation utils * fix merge conflicts * move validations in property config Co-authored-by: Abhinav Jha <abhinav@appsmith.com> Co-authored-by: nandan.anantharamu <nandan.anantharamu@thoughtspot.com> Co-authored-by: vicky-primathon.in <vicky.bansal@primathon.in> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local> Co-authored-by: Piyush <piyush@codeitout.com> Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain>
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>"`,
[Feature] Grid Widget (#2389) * Updated test * updated assertions * Resizing image to take full width of table cell * updated assertion * Stop updating dynamicBindingPathList directly from widget * Fix selectedRow and selectedRows computations * Fix primaryColumns computations * Updated test for derived column * Added tests for computed value * Added check clear data * Reordering of test * updated common method * Made image size as 100% of table cell size * add templating logic * Updated flow and dsl * Clear old primary columns * Updated testname * updated assertion * use evaluated values for children * Fix primary columns update on component mount and component update * add isArray check * remove property pane enhancement reducer * add property pane enhancement reducer * disable items other than template + fix running property enchancment on drop of list widget * disbled drag, resize, settingsControl, drag for items other than template * add grid options * uncomment the widget operation for add child for grid children * handle delete scenario for child widget in list widget * WIP: Use the new delete and update property features * add listdsl.json for testcases * add test cases for correct no. of items being rendered * add test cases currentItem binding in list widget * change dragEnabled to dragDisabled * change resizeEnabled to resizeDisabled * change settingsControlEnabled to settingsControlDisabled * change dropEnabled to dropDisabled * update settingsControlDisabled default value * Use deleteProperties in propertyControls * Fix unsetting of array indices when deleting widget properties * remove old TableWidget.tsx file * Fix derived column property update on primary column property update * Handle undefined primary columns * Fix filepicker immutable prop issue * Fix object.freeze issue when adding ids to the property pane configuration * fix widget issue in grid * Fix column actions dynamicBindingPathList inclusion issue * remove consoles + fix typo around batch update * Remove redundant tests * js binding test for date picker * hydate enhancement map on copy list widget * check for dynamicleaf * fixes * improve check * fix getNextWidgetName * update template in list widget when copying * updating template copy logic when copying widget * update dynamicBindingPathList in copied widget * Add path parameter to hidden functions in property pane configs * fix copy bug when copying list widget * add computed list property control * Remove time column type Fix editor prompt for currentRow Fix undefined derivedColumns scenario Remove validations for primaryColums and derivedColumns Fix section toggle for video, image and button column types * Fix table widget actions and custom column migrations * Add logs for cyclical dependency map :recycle: * Process array differences * add property control for list widget * Fix onClick migrations * Property pane config parity * binding and trigger paths from the property pane config (#2920) * try react virtualized library * Fix unit test * Fix unit test :white_check_mark: * Fix minor issues in table widget * Add default meta props to binding paths to ensure eval and validation * Dummy commit :tada: * Remove unnecessary datepicker test Fix chart data as string issue * Achieve table column sorting and resizing parity with release * handle scenario where last column isn't available to access * Fix for panel config path not existing in the widget * Fix bindings in currentRow (default) Add dummy property pane config for canvas widget * Update canvas widgets with dynamicPathLists on delete of property paths * Add all diffs to change paths and trim later * Add back default properties 🚶🏻‍♂️ * Use object based paths instead of arrays for primaryColumns and derivedColumns * Fix issue in reordered columns * Fix inccorect update order * add virtualized list * Fix failing property pane tests * minor change * minor list widget change * Remove .vscode from git * Rename ads to alloy Fix isVisible in list widget * move grid component to widget folder * fix import in widget registry * add sticky row in virtualized list * add sticky container * Fix Height of grid widget items container * fix dragging of items in children other than template children * update list widget * update list widget * Fix padding in list widget * hide scrollbar in list widget list * fix copy bug in list widget * regenrate enhancement map on undo delete widget * Use enhancementmap for autocomplete in list widget Basic styles for list widget scrollbar * add custom control in widget config * minor commit * update scrollbar styles * remove unused variable * fix typo in custom control * comment out test cases * remove unused imports * remove unused imports * add JSON stringify in interweave * add noPad styling in dragLayer for noPad prop * implement grid gap * add list item background color prop * add white color in color picker control * fix gap in last list item * remove onBeforeParse in textcomponent * remove virtualization in grid widget * allow overflow-y * add onListItemClick action * add beta label * add pagination * fix actions in pagination in list widget * add list widget icon * add list background color default value * remove extra div * fix pagination issue * fix list widget crashing on perpage change * extract child operation function to widgetblueprint saga * refactor enhancements * add enhancement hook * refactor propertyUpdate hook enhancment * remove enhacement map * revert renaming ads to alloy * add autopagination * Cleanup unused vars Re-write loop using map Fix binding with external input widget * update default background color * remove unnessary scrol + fix pagination per page * remove console.log * use grid gap in pixel instead of snap * fix list widget tests for binding * add tests for on click action and pagination * remove unnecessary imports * remove overflow hidden in list component * Add feature to enable template actions * update property pane help text for list widget * disable pagination in editor view * update property pane options * add test case for action * uncomment tests * fix grid gap validation * update test cases * fix property pane opening issue for list tempalte * Disable form widgets in list widget * fix template issue for actions * add validation tests for list data * update starting template * add selectedRow + enable pagination in edit mode * remove extra padding in list widget + popper fix on settingDisabled * add stop propagation for button click * fix click event in edit mode * disallow filepicker widget for list widget * add test for list widget entity definition for selectItem * remove unused imports * fix test * remove evaluated value for list child widgets * add comment * remove log * fix copying bug in list widget * add check for not allowing template to copy * fix test * add test for property pane actions * remove unused import * add draglayercomponent test * add test for draggable component * add test for evaluatedvalue popup * add test for messages.ts * add test for widgeticons * add test for property pane selector * add test for widget config response * start testing widget configresponse * add test for enhancements in widget config * add test for codeeditor * add test for base widget + list widget * add test for executeWidgetBlueprintChildOperations * remove unused import * add test for widget operation utils * remove unused import * add test for handleSpecificCasesWhilePasting * remove unused function * remove unused import * add empty list styling * resolve all review comments * fix message test * add test for widget operation utils * fix merge conflicts * move validations in property config Co-authored-by: Abhinav Jha <abhinav@appsmith.com> Co-authored-by: nandan.anantharamu <nandan.anantharamu@thoughtspot.com> Co-authored-by: vicky-primathon.in <vicky.bansal@primathon.in> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local> Co-authored-by: Piyush <piyush@codeitout.com> Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain>
2021-04-23 05:43:13 +00:00
};
}
return { isValid, parsed };
},
[VALIDATION_TYPES.TABLE_DATA]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
const { isValid, parsed, transformed } = VALIDATORS.ARRAY(
value,
props,
dataTree,
);
if (!isValid) {
return {
isValid,
parsed: [],
transformed,
2021-04-23 13:50:55 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<Object>"`,
};
}
const isValidTableData = every(parsed, (datum) => {
return (
isPlainObject(datum) &&
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>"`,
};
}
return { isValid, parsed };
},
[VALIDATION_TYPES.CHART_SERIES_DATA]: (
value: any,
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
let parsed = [];
let transformed = [];
let isValid = false;
let validationMessage = "";
2021-03-04 18:58:43 +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
);
}
if (!isValid) {
parsed = [];
transformed = validatedResponse.transformed;
2021-05-25 13:48:35 +00:00
validationMessage = `${WIDGET_TYPE_VALIDATION_ERROR}: "Array<x:string, y:number>"`;
} else {
parsed = validatedResponse.parsed;
transformed = validatedResponse.parsed;
}
} catch (e) {
console.error(e);
2021-03-04 18:58:43 +00:00
}
if (!isValid) {
return {
isValid: false,
parsed: [],
transformed: transformed,
message: validationMessage,
};
}
return { isValid, parsed, transformed };
},
[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;
}
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}>}}"`,
};
}
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}>}}"`,
};
}
// 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}>}}"`,
};
}
return { isValid, parsed, transformed: parsed };
},
[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 }>"`,
};
} else if (
!every(
parsed,
(datum) => VALIDATORS[VALIDATION_TYPES.LAT_LONG](datum, props).isValid,
)
) {
return {
isValid: false,
parsed: [],
2021-04-23 13:50:55 +00:00
message: `${WIDGET_TYPE_VALIDATION_ERROR} "Array<{ lat: number, long: number }>"`,
};
}
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 }>"`,
};
}
try {
const isValidOption = (option: { label: any; value: any }) =>
_.isObject(option) &&
_.isString(option.label) &&
!_.isEmpty(option.label);
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 }>"`,
};
}
return { isValid, parsed };
} catch (e) {
return {
isValid: false,
parsed: [],
transformed: parsed,
};
}
},
[VALIDATION_TYPES.DATE_ISO_STRING]: (
dateString: string,
props: WidgetProps,
): ValidationResponse => {
const dateFormat =
props.version === 2
? ISO_DATE_FORMAT
: props.dateFormat || ISO_DATE_FORMAT;
if (dateString === null) {
return {
isValid: true,
parsed: "",
message: "",
};
}
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 : ""),
};
}
const isValid = validateDateString(dateString, dateFormat, props.version);
let parsedDate = dateString;
try {
if (isValid && props.version === 2) {
parsedDate = moment(dateString).toISOString(true);
}
} catch (e) {
console.error("Could not parse date", parsedDate, e);
}
if (!isValid) {
return {
isValid: isValid,
parsed: "",
message: `Value does not match ISO 8601 standard date string`,
};
}
return {
isValid,
parsed: parsedDate,
2021-04-23 13:50:55 +00:00
message: isValid
? ""
: `Value does not match ISO 8601 standard date string`,
};
},
[VALIDATION_TYPES.DEFAULT_DATE]: (
dateString: string,
props: WidgetProps,
): ValidationResponse => {
const dateFormat =
props.version === 2
? ISO_DATE_FORMAT
: props.dateFormat || ISO_DATE_FORMAT;
if (dateString === null) {
return {
isValid: true,
parsed: "",
message: "",
};
}
if (dateString === undefined) {
return {
isValid: false,
parsed: "",
message:
2021-05-21 08:48:59 +00:00
`${WIDGET_TYPE_VALIDATION_ERROR}: Date String ` +
(dateFormat ? dateFormat : ""),
};
}
const isValid = validateDateString(dateString, dateFormat, props.version);
let parsedDate = dateString;
try {
if (isValid && props.version === 2) {
parsedDate = moment(dateString).toISOString(true);
}
} catch (e) {
console.error("Could not parse date", parsedDate, e);
}
if (!isValid) {
return {
isValid: isValid,
parsed: "",
message: `Value does not match ISO 8601 standard date string`,
};
}
return {
isValid: isValid,
parsed: parsedDate,
message: "",
};
},
[VALIDATION_TYPES.MIN_DATE]: (
dateString: string,
props: WidgetProps,
): ValidationResponse => {
const dateFormat =
props.version === 2
? ISO_DATE_FORMAT
: props.dateFormat || ISO_DATE_FORMAT;
if (dateString === undefined) {
return {
isValid: false,
parsed: "",
message:
2021-05-21 08:48:59 +00:00
`${WIDGET_TYPE_VALIDATION_ERROR}: Date String ` +
(dateFormat ? dateFormat : ""),
};
}
const parsedMinDate = moment(dateString, dateFormat);
let isValid = validateDateString(dateString, dateFormat, props.version);
if (!props.defaultDate) {
return {
isValid: isValid,
parsed: dateString,
message: "",
};
}
const parsedDefaultDate = moment(props.defaultDate, dateFormat);
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 : ""),
};
}
return {
isValid: isValid,
parsed: dateString,
message: "",
};
},
[VALIDATION_TYPES.MAX_DATE]: (
dateString: string,
props: WidgetProps,
): ValidationResponse => {
const dateFormat =
props.version === 2
? ISO_DATE_FORMAT
: props.dateFormat || ISO_DATE_FORMAT;
if (dateString === undefined) {
return {
isValid: false,
parsed: "",
message:
2021-05-21 08:48:59 +00:00
`${WIDGET_TYPE_VALIDATION_ERROR}: Date String ` +
(dateFormat ? dateFormat : ""),
};
}
const parsedMaxDate = moment(dateString, dateFormat);
let isValid = validateDateString(dateString, dateFormat, props.version);
if (!props.defaultDate) {
return {
isValid: isValid,
parsed: dateString,
message: "",
};
}
const parsedDefaultDate = moment(props.defaultDate, dateFormat);
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 : ""),
};
}
return {
isValid: isValid,
parsed: dateString,
message: "",
};
},
[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 => {
const { isValid, message, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
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 => {
const tabs: any = props.tabsObj
? Object.values(props.tabsObj)
: props.tabs || [];
const tabNames = tabs.map((i: { label: string; id: string }) => i.label);
const isValidTabName = tabNames.includes(value);
return {
isValid: isValidTabName,
parsed: isValidTabName ? value : "",
message: isValidTabName ? "" : `Tab name provided does not exist.`,
};
},
[VALIDATION_TYPES.DEFAULT_OPTION_VALUE]: (
value: string | string[],
props: WidgetProps,
dataTree?: DataTree,
) => {
let values = value;
if (props) {
if (props.selectionType === "SINGLE_SELECT") {
const defaultValue = value && _.isString(value) ? value.trim() : value;
return VALIDATORS[VALIDATION_TYPES.TEXT](defaultValue, props, dataTree);
} 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) {
return VALIDATORS[VALIDATION_TYPES.ROW_INDICES](value, props);
} else {
try {
const _value: string = value as string;
if (
Number.isInteger(parseInt(_value, 10)) &&
parseInt(_value, 10) > -1
)
return { isValid: true, parsed: parseInt(_value, 10) };
return {
isValid: true,
parsed: -1,
};
} catch (e) {
return {
isValid: true,
parsed: -1,
};
}
}
}
return {
isValid: true,
parsed: value,
};
},
[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 };
},
[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 }"`,
};
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,
};
},
[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 };
},
// 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[]`,
};
},
};