Chart validations, Tabs add new tab issue fix
This commit is contained in:
parent
a54a68832b
commit
747c3d5d8b
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user