Merge branch 'feature/graph-components' into 'release'
Feature/graph components Support for Graph components, Line|Bar|Pie|Area|Column graphs added See merge request theappsmith/internal-tools-client!334
This commit is contained in:
commit
4b9d8a9d43
|
|
@ -44,6 +44,7 @@
|
|||
"flow-bin": "^0.91.0",
|
||||
"fontfaceobserver": "^2.1.0",
|
||||
"fuse.js": "^3.4.5",
|
||||
"fusioncharts": "^3.15.0-sr.1",
|
||||
"history": "^4.10.1",
|
||||
"husky": "^3.0.5",
|
||||
"interweave": "^12.1.1",
|
||||
|
|
@ -67,6 +68,7 @@
|
|||
"react-dnd-html5-backend": "^9.3.4",
|
||||
"react-dnd-touch-backend": "^9.4.0",
|
||||
"react-dom": "^16.7.0",
|
||||
"react-fusioncharts": "^3.1.2",
|
||||
"react-helmet": "^5.2.1",
|
||||
"react-redux": "^7.1.3",
|
||||
"react-router": "^5.1.2",
|
||||
|
|
|
|||
3
app/client/src/assets/icons/widget/chart.svg
Normal file
3
app/client/src/assets/icons/widget/chart.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.7494 13.8508L13.069 10.0279L4.21712 19.024L3 17.8274L13.0818 7.58082L16.798 11.4404L23.1909 5.31898L21.3593 3.48817H26.1416V8.26875L24.3978 6.52586L16.7494 13.8508ZM7.23518 26.3199H12.9965V18.2114H7.23518V26.3199ZM16.237 26.3199H20.9982V15.6509H16.237V26.3199ZM24.2387 10.3164V26.3199H29V10.3164H24.2387Z" fill="#F1F7FC"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 439 B |
|
|
@ -0,0 +1,83 @@
|
|||
import React from "react";
|
||||
import ReactFC from "react-fusioncharts";
|
||||
import FusionCharts from "fusioncharts";
|
||||
import Column2D from "fusioncharts/fusioncharts.charts";
|
||||
import FusionTheme from "fusioncharts/themes/fusioncharts.theme.fusion";
|
||||
import { ChartType, ChartData } from "widgets/ChartWidget";
|
||||
import styled from "styled-components";
|
||||
import { invisible } from "constants/DefaultTheme";
|
||||
|
||||
ReactFC.fcRoot(FusionCharts, Column2D, FusionTheme);
|
||||
|
||||
export interface ChartComponentProps {
|
||||
chartType: ChartType;
|
||||
chartData: ChartData[];
|
||||
xAxisName: string;
|
||||
yAxisName: string;
|
||||
chartName: string;
|
||||
componentWidth: number;
|
||||
componentHeight: number;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
const CanvasContainer = styled.div<ChartComponentProps>`
|
||||
border: none;
|
||||
border-radius: ${props => `${props.theme.radii[1]}px`};
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: white;
|
||||
box-shadow: 0 1px 1px 0 rgba(60,75,100,.14),0 2px 1px -1px rgba(60,75,100,.12),0 1px 3px 0 rgba(60,75,100,.2);
|
||||
position: relative;
|
||||
${props => (!props.isVisible ? invisible : "")};
|
||||
}`;
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
const ChartComponent = (props: ChartComponentProps) => {
|
||||
const getChartType = (chartType: ChartType) => {
|
||||
switch (chartType) {
|
||||
case "LINE_CHART":
|
||||
return "line";
|
||||
case "BAR_CHART":
|
||||
return "bar2d";
|
||||
case "PIE_CHART":
|
||||
return "pie2d";
|
||||
case "COLUMN_CHART":
|
||||
return "column2d";
|
||||
case "AREA_CHART":
|
||||
return "area2d";
|
||||
default:
|
||||
return "column2d";
|
||||
}
|
||||
};
|
||||
|
||||
const getChartData = (chartData: ChartData[]) => {
|
||||
return chartData.map(item => {
|
||||
return {
|
||||
label: item.x,
|
||||
value: item.y,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<CanvasContainer {...props}>
|
||||
<ReactFC
|
||||
type={getChartType(props.chartType)}
|
||||
width={props.componentWidth.toString()}
|
||||
height={props.componentHeight.toString()}
|
||||
dataForma="json"
|
||||
dataSource={{
|
||||
chart: {
|
||||
xAxisName: props.xAxisName,
|
||||
yAxisName: props.yAxisName,
|
||||
theme: "fusion",
|
||||
caption: props.chartName,
|
||||
},
|
||||
data: getChartData(props.chartData),
|
||||
}}
|
||||
/>
|
||||
</CanvasContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChartComponent;
|
||||
|
|
@ -11,6 +11,7 @@ export type WidgetType =
|
|||
| "RADIO_GROUP_WIDGET"
|
||||
| "FILE_PICKER_WIDGET"
|
||||
| "INPUT_WIDGET"
|
||||
| "CHART_WIDGET"
|
||||
| "SWITCH_WIDGET"
|
||||
| "FORM_WIDGET"
|
||||
| "FORM_BUTTON_WIDGET";
|
||||
|
|
@ -28,6 +29,7 @@ export const WidgetTypes: { [id: string]: WidgetType } = {
|
|||
DROP_DOWN_WIDGET: "DROP_DOWN_WIDGET",
|
||||
CHECKBOX_WIDGET: "CHECKBOX_WIDGET",
|
||||
RADIO_GROUP_WIDGET: "RADIO_GROUP_WIDGET",
|
||||
CHART_WIDGET: "CHART_WIDGET",
|
||||
FORM_WIDGET: "FORM_WIDGET",
|
||||
FORM_BUTTON_WIDGET: "FORM_BUTTON_WIDGET",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export const VALIDATION_TYPES = {
|
|||
TABLE_DATA: "TABLE_DATA",
|
||||
OPTIONS_DATA: "OPTIONS_DATA",
|
||||
DATE: "DATE",
|
||||
CHART_DATA: "CHART_DATA",
|
||||
};
|
||||
|
||||
export type ValidationResponse = {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { ReactComponent as SwitchIcon } from "assets/icons/widget/switch.svg";
|
|||
import { ReactComponent as TextIcon } from "assets/icons/widget/text.svg";
|
||||
import { ReactComponent as ImageIcon } from "assets/icons/widget/image.svg";
|
||||
import { ReactComponent as FilePickerIcon } from "assets/icons/widget/filepicker.svg";
|
||||
import { ReactComponent as ChartIcon } from "assets/icons/widget/chart.svg";
|
||||
import { ReactComponent as FormIcon } from "assets/icons/widget/form.svg";
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
|
|
@ -91,6 +92,11 @@ export const WidgetIcons: {
|
|||
<FilePickerIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
CHART_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<ChartIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
FORM_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<FormIcon />
|
||||
|
|
|
|||
|
|
@ -885,6 +885,67 @@ const PropertyPaneConfigResponse = {
|
|||
],
|
||||
},
|
||||
],
|
||||
CHART_WIDGET: [
|
||||
{
|
||||
sectionName: "General",
|
||||
id: "21",
|
||||
children: [
|
||||
{
|
||||
id: "21.1",
|
||||
propertyName: "chartType",
|
||||
label: "Chart Type",
|
||||
controlType: "DROP_DOWN",
|
||||
options: [
|
||||
{
|
||||
label: "Line Chart",
|
||||
value: "LINE_CHART",
|
||||
},
|
||||
{
|
||||
label: "Bar Chart",
|
||||
value: "BAR_CHART",
|
||||
},
|
||||
{
|
||||
label: "Pie Chart",
|
||||
value: "PIE_CHART",
|
||||
},
|
||||
{
|
||||
label: "Column Chart",
|
||||
value: "COLUMN_CHART",
|
||||
},
|
||||
{
|
||||
label: "Area Chart",
|
||||
value: "AREA_CHART",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "21.2",
|
||||
propertyName: "chartName",
|
||||
label: "Chart Name",
|
||||
controlType: "INPUT_TEXT",
|
||||
},
|
||||
{
|
||||
id: "21.3",
|
||||
propertyName: "xAxisName",
|
||||
label: "X-axis Label",
|
||||
controlType: "INPUT_TEXT",
|
||||
},
|
||||
{
|
||||
id: "21.4",
|
||||
propertyName: "yAxisName",
|
||||
label: "Y-axis Label",
|
||||
controlType: "INPUT_TEXT",
|
||||
},
|
||||
{
|
||||
id: "21.5",
|
||||
propertyName: "chartData",
|
||||
label: "Chart Data",
|
||||
controlType: "INPUT_TEXT",
|
||||
inputType: "ARRAY",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
name: "propertyPane",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -154,6 +154,45 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
widgetName: "FilePicker",
|
||||
isDefaultClickDisabled: true,
|
||||
},
|
||||
CHART_WIDGET: {
|
||||
rows: 8,
|
||||
columns: 6,
|
||||
widgetName: "Chart",
|
||||
chartType: "LINE_CHART",
|
||||
chartName: "Sales on working days",
|
||||
chartData: [
|
||||
{
|
||||
x: "Mon",
|
||||
y: 10000,
|
||||
},
|
||||
{
|
||||
x: "Tue",
|
||||
y: 12000,
|
||||
},
|
||||
{
|
||||
x: "Wed",
|
||||
y: 32000,
|
||||
},
|
||||
{
|
||||
x: "Thu",
|
||||
y: 28000,
|
||||
},
|
||||
{
|
||||
x: "Fri",
|
||||
y: 14000,
|
||||
},
|
||||
{
|
||||
x: "Sat",
|
||||
y: 19000,
|
||||
},
|
||||
{
|
||||
x: "Sun",
|
||||
y: 36000,
|
||||
},
|
||||
],
|
||||
xAxisName: "Last Week",
|
||||
yAxisName: "Total Order Revenue $",
|
||||
},
|
||||
FORM_BUTTON_WIDGET: {
|
||||
rows: 1,
|
||||
columns: 3,
|
||||
|
|
|
|||
|
|
@ -96,6 +96,11 @@ const WidgetSidebarResponse: {
|
|||
widgetCardName: "Table",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "CHART_WIDGET",
|
||||
widgetCardName: "Chart",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
],
|
||||
["Layout widgets"]: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ import { ImageWidgetProps } from "widgets/ImageWidget";
|
|||
import { InputWidgetProps } from "widgets/InputWidget";
|
||||
import { SwitchWidgetProps } from "widgets/SwitchWidget";
|
||||
import { SpinnerWidgetProps } from "widgets/SpinnerWidget";
|
||||
import { DatePickerWidgetProps } from "widgets/DatePickerWidget";
|
||||
import { TableWidgetProps } from "widgets/TableWidget";
|
||||
import { DropdownWidgetProps } from "widgets/DropdownWidget";
|
||||
import { CheckboxWidgetProps } from "widgets/CheckboxWidget";
|
||||
import { RadioGroupWidgetProps } from "widgets/RadioGroupWidget";
|
||||
import { AlertWidgetProps } from "widgets/AlertWidget";
|
||||
import { FilePickerWidgetProps } from "widgets/FilepickerWidget";
|
||||
import { DatePickerWidgetProps } from "../../widgets/DatePickerWidget";
|
||||
import { TableWidgetProps } from "../../widgets/TableWidget";
|
||||
import { DropdownWidgetProps } from "../../widgets/DropdownWidget";
|
||||
import { CheckboxWidgetProps } from "../../widgets/CheckboxWidget";
|
||||
import { RadioGroupWidgetProps } from "../../widgets/RadioGroupWidget";
|
||||
import { AlertWidgetProps } from "../../widgets/AlertWidget";
|
||||
import { FilePickerWidgetProps } from "../../widgets/FilepickerWidget";
|
||||
import { ChartWidgetProps } from "../../widgets/ChartWidget";
|
||||
import { FormWidgetProps } from "widgets/FormWidget";
|
||||
import { FormButtonWidgetProps } from "widgets/FormButtonWidget";
|
||||
|
||||
|
|
@ -53,6 +54,7 @@ export interface WidgetConfigReducerState {
|
|||
RADIO_GROUP_WIDGET: Partial<RadioGroupWidgetProps> & WidgetConfigProps;
|
||||
ALERT_WIDGET: Partial<AlertWidgetProps> & WidgetConfigProps;
|
||||
FILE_PICKER_WIDGET: Partial<FilePickerWidgetProps> & WidgetConfigProps;
|
||||
CHART_WIDGET: Partial<ChartWidgetProps> & WidgetConfigProps;
|
||||
FORM_WIDGET: Partial<FormWidgetProps> & WidgetConfigProps;
|
||||
FORM_BUTTON_WIDGET: Partial<FormButtonWidgetProps> & WidgetConfigProps;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -174,6 +174,23 @@ export const VALIDATORS: Record<ValidationType, Validator> = {
|
|||
}
|
||||
return { isValid, parsed };
|
||||
},
|
||||
[VALIDATION_TYPES.CHART_DATA]: (value: any): ValidationResponse => {
|
||||
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](value);
|
||||
if (!isValid) {
|
||||
return {
|
||||
isValid,
|
||||
parsed,
|
||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Chart Data`,
|
||||
};
|
||||
} else if (!_.every(parsed, datum => _.isObject(datum))) {
|
||||
return {
|
||||
isValid: false,
|
||||
parsed: [],
|
||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Chart Data`,
|
||||
};
|
||||
}
|
||||
return { isValid, parsed };
|
||||
},
|
||||
[VALIDATION_TYPES.OPTIONS_DATA]: (value: any): ValidationResponse => {
|
||||
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](value);
|
||||
if (!isValid) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import ButtonWidget, { ButtonWidgetProps } from "widgets/ButtonWidget";
|
|||
import DropdownWidget, { DropdownWidgetProps } from "widgets/DropdownWidget";
|
||||
import ImageWidget, { ImageWidgetProps } from "widgets/ImageWidget";
|
||||
import TableWidget, { TableWidgetProps } from "widgets/TableWidget";
|
||||
import ChartWidget, { ChartWidgetProps } from "widgets/ChartWidget";
|
||||
|
||||
import FilePickerWidget, {
|
||||
FilePickerWidgetProps,
|
||||
|
|
@ -169,7 +170,17 @@ class WidgetBuilderRegistry {
|
|||
DatePickerWidget.getDerivedPropertiesMap(),
|
||||
DatePickerWidget.getTriggerPropertyMap(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
"CHART_WIDGET",
|
||||
{
|
||||
buildWidget(widgetData: ChartWidgetProps): JSX.Element {
|
||||
return <ChartWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
ChartWidget.getPropertyValidationMap(),
|
||||
ChartWidget.getDerivedPropertiesMap(),
|
||||
ChartWidget.getTriggerPropertyMap(),
|
||||
);
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
"FORM_WIDGET",
|
||||
{
|
||||
|
|
|
|||
63
app/client/src/widgets/ChartWidget.tsx
Normal file
63
app/client/src/widgets/ChartWidget.tsx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import ChartComponent from "components/designSystems/appsmith/ChartComponent";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
class ChartWidget extends BaseWidget<ChartWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
chartData: VALIDATION_TYPES.CHART_DATA,
|
||||
xAxisName: VALIDATION_TYPES.TEXT,
|
||||
yAxisName: VALIDATION_TYPES.TEXT,
|
||||
chartName: VALIDATION_TYPES.TEXT,
|
||||
};
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<ChartComponent
|
||||
key={this.props.widgetId}
|
||||
isVisible={this.props.isVisible}
|
||||
chartType={this.props.chartType}
|
||||
xAxisName={this.props.xAxisName}
|
||||
yAxisName={this.props.yAxisName}
|
||||
chartName={this.props.chartName}
|
||||
componentWidth={this.state.componentWidth - 10}
|
||||
componentHeight={this.state.componentHeight - 10}
|
||||
chartData={this.props.chartData}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "CHART_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export type ChartType =
|
||||
| "LINE_CHART"
|
||||
| "BAR_CHART"
|
||||
| "PIE_CHART"
|
||||
| "COLUMN_CHART"
|
||||
| "AREA_CHART"
|
||||
| "SCATTER_CHART";
|
||||
|
||||
export interface ChartData {
|
||||
x: any;
|
||||
y: any;
|
||||
}
|
||||
|
||||
export interface ChartWidgetProps extends WidgetProps {
|
||||
chartType: ChartType;
|
||||
chartData: ChartData[];
|
||||
xAxisName: string;
|
||||
yAxisName: string;
|
||||
chartName: string;
|
||||
componentWidth: number;
|
||||
componentHeight: number;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
export default ChartWidget;
|
||||
2250
app/client/yarn.lock
2250
app/client/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user