Chart validations, Tabs add new tab issue fix

This commit is contained in:
Vicky Bansal 2020-05-29 06:07:56 +00:00 committed by Hetu Nandu
parent a54a68832b
commit 747c3d5d8b
7 changed files with 189 additions and 51 deletions

View File

@ -43,6 +43,16 @@ export class DroppableComponent extends React.Component<
};
}
componentDidUpdate(prevProps: DroppableComponentProps) {
if (this.props.items.length !== prevProps.items.length) {
this.setState({ items: this.props.items });
} else if (
JSON.stringify(this.props.items) !== JSON.stringify(prevProps.items)
) {
this.setState({ items: this.props.items });
}
}
onDragEnd = (result: any) => {
const { destination, source } = result;
if (!destination) {

View File

@ -1,4 +1,5 @@
import React from "react";
import _ from "lodash";
import BaseControl, { ControlProps } from "./BaseControl";
import {
ControlWrapper,
@ -65,12 +66,22 @@ type RenderComponentProps = {
data: Array<{ x: string; y: string }> | any;
};
length: number;
isValid: boolean;
validationMessage: string;
deleteOption: Function;
updateOption: Function;
};
function DataControlComponent(props: RenderComponentProps) {
const { deleteOption, updateOption, item, index, length } = props;
const {
deleteOption,
updateOption,
item,
index,
length,
isValid,
validationMessage,
} = props;
return (
<StyledOptionControlWrapper orientation={"VERTICAL"}>
<StyledOptionControlWrapper orientation={"HORIZONTAL"}>
@ -107,7 +118,7 @@ function DataControlComponent(props: RenderComponentProps) {
},
}}
meta={{
error: "",
error: isValid ? "" : validationMessage,
touched: true,
}}
theme={"DARK"}
@ -120,12 +131,52 @@ function DataControlComponent(props: RenderComponentProps) {
}
class ChartDataControl extends BaseControl<ControlProps> {
getValidations = (message: string, isValid: boolean, len: number) => {
const validations: Array<{
isValid: boolean;
validationMessage: string;
}> = [];
let index = -1;
let validationMessage = "";
if (message.indexOf("##") !== -1) {
const messages = message.split("##");
index = Number(messages[0]);
validationMessage = messages[1];
}
for (let i = 0; i < len; i++) {
if (i === index) {
validations.push({
isValid: false,
validationMessage: validationMessage,
});
} else {
validations.push({
isValid: true,
validationMessage: "",
});
}
}
return validations;
};
render() {
const chartData: Array<{
seriesName: string;
data: Array<{ x: string; y: string }> | any;
}> = this.props.propertyValue || [];
}> =
this.props.propertyValue && _.isString(this.props.propertyValue)
? JSON.parse(this.props.propertyValue)
: this.props.propertyValue;
const dataLength = chartData.length;
const { validationMessage, isValid } = this.props;
const validations: Array<{
isValid: boolean;
validationMessage: string;
}> = this.getValidations(
validationMessage || "",
isValid,
chartData.length,
);
return (
<React.Fragment>
{chartData.map((data, index) => {
@ -137,6 +188,8 @@ class ChartDataControl extends BaseControl<ControlProps> {
length={dataLength}
deleteOption={this.deleteOption}
updateOption={this.updateOption}
isValid={validations[index].isValid}
validationMessage={validations[index].validationMessage}
/>
);
})}
@ -152,9 +205,12 @@ class ChartDataControl extends BaseControl<ControlProps> {
}
deleteOption = (index: number) => {
const chartData: object[] = this.props.propertyValue.slice();
const chartData: object[] =
this.props.propertyValue && _.isString(this.props.propertyValue)
? JSON.parse(this.props.propertyValue)
: this.props.propertyValue;
chartData.splice(index, 1);
this.updateProperty(this.props.propertyName, chartData);
this.updateProperty(this.props.propertyName, JSON.stringify(chartData));
};
updateOption = (
@ -165,23 +221,27 @@ class ChartDataControl extends BaseControl<ControlProps> {
const chartData: Array<{
seriesName: string;
data: Array<{ x: string; y: string }> | any;
}> = this.props.propertyValue;
this.updateProperty(
this.props.propertyName,
chartData.map((item, i) => {
if (index === i) {
if (propertyName === "seriesName") {
item.seriesName = updatedValue;
} else {
try {
item.data = JSON.parse(updatedValue);
} catch (err) {
item.data = updatedValue;
}
}> =
this.props.propertyValue && _.isString(this.props.propertyValue)
? JSON.parse(this.props.propertyValue)
: this.props.propertyValue;
const updatedChartData = chartData.map((item, i) => {
if (index === i) {
if (propertyName === "seriesName") {
item.seriesName = updatedValue;
} else {
try {
item.data = JSON.parse(updatedValue);
} catch (err) {
item.data = updatedValue;
}
}
return item;
}),
}
return item;
});
this.updateProperty(
this.props.propertyName,
JSON.stringify(updatedChartData),
);
};
@ -189,9 +249,12 @@ class ChartDataControl extends BaseControl<ControlProps> {
const chartData: Array<{
seriesName: string;
data: Array<{ x: string; y: string }> | any;
}> = this.props.propertyValue ? this.props.propertyValue.slice() : [];
}> =
this.props.propertyValue && _.isString(this.props.propertyValue)
? JSON.parse(this.props.propertyValue)
: this.props.propertyValue;
chartData.push({ seriesName: "", data: [{ x: "", y: "" }] });
this.updateProperty(this.props.propertyName, chartData);
this.updateProperty(this.props.propertyName, JSON.stringify(chartData));
};
static getControlType() {

View File

@ -7,6 +7,7 @@ import { ControlIcons } from "icons/ControlIcons";
import { AnyStyledComponent } from "styled-components";
import { generateReactKey } from "utils/generators";
import { DroppableComponent } from "../designSystems/appsmith/DraggableListComponent";
import _ from "lodash";
const StyledDeleteIcon = styled(FormIcons.DELETE_ICON as AnyStyledComponent)`
padding: 0;
@ -98,14 +99,16 @@ function TabControlComponent(props: RenderComponentProps) {
class TabControl extends BaseControl<ControlProps> {
updateItems = (items: object[]) => {
this.updateProperty(this.props.propertyName, items);
this.updateProperty(this.props.propertyName, JSON.stringify(items));
};
render() {
const tabs: Array<{
id: string;
label: string;
}> = this.props.propertyValue || [{ id: "" }];
}> = _.isString(this.props.propertyValue)
? JSON.parse(this.props.propertyValue)
: this.props.propertyValue;
return (
<TabsWrapper>
<DroppableComponent
@ -128,35 +131,39 @@ class TabControl extends BaseControl<ControlProps> {
}
deleteOption = (index: number) => {
const tabs: object[] = this.props.propertyValue.slice();
const tabs: object[] = _.isString(this.props.propertyValue)
? JSON.parse(this.props.propertyValue).slice()
: this.props.propertyValue.slice();
tabs.splice(index, 1);
this.updateProperty(this.props.propertyName, tabs);
this.updateProperty(this.props.propertyName, JSON.stringify(tabs));
};
updateOption = (index: number, updatedLabel: string) => {
const tabs: Array<{
id: string;
label: string;
}> = this.props.propertyValue;
this.updateProperty(
this.props.propertyName,
tabs.map((tab, tabIndex) => {
if (index === tabIndex) {
tab.label = updatedLabel;
}
return tab;
}),
);
}> = _.isString(this.props.propertyValue)
? JSON.parse(this.props.propertyValue)
: this.props.propertyValue;
const updatedTabs = tabs.map((tab, tabIndex) => {
if (index === tabIndex) {
tab.label = updatedLabel;
}
return tab;
});
this.updateProperty(this.props.propertyName, JSON.stringify(updatedTabs));
};
addOption = () => {
const tabs: Array<{
id: string;
label: string;
}> = this.props.propertyValue ? this.props.propertyValue.slice() : [];
}> = _.isString(this.props.propertyValue)
? JSON.parse(this.props.propertyValue)
: this.props.propertyValue;
const newTabId = generateReactKey({ prefix: "tab" });
tabs.push({ id: newTabId, label: `Tab ${tabs.length + 1}` });
this.updateProperty(this.props.propertyName, tabs);
this.updateProperty(this.props.propertyName, JSON.stringify(tabs));
};
static getControlType() {

View File

@ -12,6 +12,7 @@ export const VALIDATION_TYPES = {
TABLE_DATA: "TABLE_DATA",
OPTIONS_DATA: "OPTIONS_DATA",
DATE: "DATE",
TABS_DATA: "TABS_DATA",
CHART_DATA: "CHART_DATA",
MARKERS: "MARKERS",
ACTION_SELECTOR: "ACTION_SELECTOR",

View File

@ -143,6 +143,13 @@ export const createDynamicValueString = (
if (Array.isArray(value) || _.isObject(value)) {
value = JSON.stringify(value);
}
try {
if (JSON.parse(value)) {
value = value.replace(/\\([\s\S])|(")/g, "\\$1$2");
}
} catch (e) {
// do nothing
}
finalValue = finalValue.replace(b, value);
});
return finalValue;

View File

@ -207,6 +207,31 @@ export const VALIDATORS: Record<ValidationType, Validator> = {
};
}
},
[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 };
},
[VALIDATION_TYPES.TABLE_DATA]: (
value: any,
props: WidgetProps,
@ -237,6 +262,10 @@ export const VALIDATORS: Record<ValidationType, Validator> = {
props: WidgetProps,
dataTree?: DataTree,
): ValidationResponse => {
if (_.isString(value)) {
value = value.replace(/\s/g, "");
value = `${value}`;
}
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](
value,
props,
@ -249,27 +278,40 @@ export const VALIDATORS: Record<ValidationType, Validator> = {
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Chart Data`,
};
}
const hasChartData = _.every(
let validationMessage = "";
let index = 0;
const isValidChartData = _.every(
parsed,
(datum: { seriesName: any; data: any }) => {
if (_.isObject(datum)) {
return (
_.isString(datum.seriesName) &&
_.isArray(datum.data) &&
_.every(datum.data, (item: { x: any; y: any }) => {
return _.isString(item.x) && !_.isUndefined(item.y);
})
(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)
);
},
);
} else {
return false;
}
index++;
return isValidChart;
},
);
if (!hasChartData) {
if (!isValidChartData) {
return {
isValid: false,
parsed: [],
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Chart Data`,
message: validationMessage,
};
}
return { isValid, parsed };

View File

@ -4,11 +4,19 @@ import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
import WidgetFactory from "utils/WidgetFactory";
import { generateReactKey } from "utils/generators";
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
import { VALIDATION_TYPES } from "constants/WidgetValidation";
class TabsWidget extends BaseWidget<
TabsWidgetProps<TabContainerWidgetProps>,
WidgetState
> {
static getPropertyValidationMap(): WidgetPropertyValidationType {
return {
tabs: VALIDATION_TYPES.TABS_DATA,
};
}
onTabChange = (tabId: string) => {
this.updateWidgetMetaProperty("selectedTabId", tabId);
};