Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 60 additions & 19 deletions app/client/src/components/designSystems/appsmith/ChartComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import _, { get } from "lodash";
import React from "react";
import styled from "styled-components";

import { getBorderCSSShorthand, invisible } from "constants/DefaultTheme";
import { getAppsmithConfigs } from "configs";
import { AllChartData, ChartDataPoint, ChartType } from "widgets/ChartWidget";
import log from "loglevel";
import { AllChartData, ChartDataPoint, ChartType } from "widgets/ChartWidget";
import { getAppsmithConfigs } from "configs";
import { getBorderCSSShorthand, invisible } from "constants/DefaultTheme";
import {
LabelOrientation,
LABEL_ORIENTATION_COMPATIBLE_CHARTS,
} from "constants/ChartConstants";

export interface CustomFusionChartConfig {
type: string;
Expand Down Expand Up @@ -48,16 +52,17 @@ FusionCharts.options.license({
});

export interface ChartComponentProps {
chartType: ChartType;
allowHorizontalScroll: boolean;
chartData: AllChartData;
customFusionChartConfig: CustomFusionChartConfig;
xAxisName: string;
yAxisName: string;
chartName: string;
widgetId: string;
chartType: ChartType;
customFusionChartConfig: CustomFusionChartConfig;
isVisible?: boolean;
allowHorizontalScroll: boolean;
labelOrientation?: LabelOrientation;
onDataPointClick: (selectedDataPoint: ChartSelectedDataPoint) => void;
widgetId: string;
xAxisName: string;
yAxisName: string;
}

const CanvasContainer = styled.div<
Expand All @@ -74,9 +79,14 @@ const CanvasContainer = styled.div<
padding: 10px 0 0 0;
}`;

export const isLabelOrientationApplicableFor = (chartType: string) =>
LABEL_ORIENTATION_COMPATIBLE_CHARTS.includes(chartType);

class ChartComponent extends React.Component<ChartComponentProps> {
chartInstance = new FusionCharts();

chartContainerId = this.props.widgetId + "chart-container";

getChartType = () => {
const { allowHorizontalScroll, chartData, chartType } = this.props;
const dataLength = Object.keys(chartData).length;
Expand Down Expand Up @@ -151,7 +161,7 @@ class ChartComponent extends React.Component<ChartComponentProps> {
});
};

getChartCategoriesMutliSeries = (chartData: AllChartData) => {
getChartCategoriesMultiSeries = (chartData: AllChartData) => {
const categories: string[] = [];

Object.keys(chartData).forEach((key: string) => {
Expand All @@ -173,7 +183,7 @@ class ChartComponent extends React.Component<ChartComponentProps> {
};

getChartCategories = (chartData: AllChartData) => {
const categories: string[] = this.getChartCategoriesMutliSeries(chartData);
const categories: string[] = this.getChartCategoriesMultiSeries(chartData);

if (categories.length === 0) {
return [
Expand Down Expand Up @@ -218,7 +228,7 @@ class ChartComponent extends React.Component<ChartComponentProps> {
* @returns
*/
getChartDataset = (chartData: AllChartData) => {
const categories: string[] = this.getChartCategoriesMutliSeries(chartData);
const categories: string[] = this.getChartCategoriesMultiSeries(chartData);

const dataset = Object.keys(chartData).map((key: string) => {
const item = get(chartData, `${key}`);
Expand All @@ -236,8 +246,32 @@ class ChartComponent extends React.Component<ChartComponentProps> {
return dataset;
};

getLabelOrientationConfig = () => {
switch (this.props.labelOrientation) {
case LabelOrientation.AUTO:
return {};
case LabelOrientation.ROTATE:
return {
labelDisplay: "rotate",
slantLabel: "0",
};
case LabelOrientation.SLANT:
return {
labelDisplay: "rotate",
slantLabel: "1",
};
case LabelOrientation.STAGGER:
return {
labelDisplay: "stagger",
};
default: {
return {};
}
}
};

getChartConfig = () => {
return {
let config = {
caption: this.props.chartName,
xAxisName: this.props.xAxisName,
yAxisName: this.props.yAxisName,
Expand All @@ -246,6 +280,15 @@ class ChartComponent extends React.Component<ChartComponentProps> {
captionHorizontalPadding: 10,
alignCaptionWithCanvas: 0,
};

if (isLabelOrientationApplicableFor(this.props.chartType)) {
config = {
...config,
...this.getLabelOrientationConfig(),
};
}

return config;
};

getDatalength = () => {
Expand Down Expand Up @@ -338,7 +381,7 @@ class ChartComponent extends React.Component<ChartComponentProps> {
createGraph = () => {
if (this.props.chartType === "CUSTOM_FUSION_CHART") {
const chartConfig = {
renderAt: this.props.widgetId + "chart-container",
renderAt: this.chartContainerId,
width: "100%",
height: "100%",
events: {
Expand All @@ -364,7 +407,7 @@ class ChartComponent extends React.Component<ChartComponentProps> {

const chartConfig = {
type: this.getChartType(),
renderAt: this.props.widgetId + "chart-container",
renderAt: this.chartContainerId,
width: "100%",
height: "100%",
dataFormat: "json",
Expand Down Expand Up @@ -410,7 +453,7 @@ class ChartComponent extends React.Component<ChartComponentProps> {
if (!_.isEqual(prevProps, this.props)) {
if (this.props.chartType === "CUSTOM_FUSION_CHART") {
const chartConfig = {
renderAt: this.props.widgetId + "chart-container",
renderAt: this.chartContainerId,
width: "100%",
height: "100%",
events: {
Expand Down Expand Up @@ -446,9 +489,7 @@ class ChartComponent extends React.Component<ChartComponentProps> {
render() {
//eslint-disable-next-line @typescript-eslint/no-unused-vars
const { onDataPointClick, ...rest } = this.props;
return (
<CanvasContainer {...rest} id={this.props.widgetId + "chart-container"} />
);
return <CanvasContainer {...rest} id={this.chartContainerId} />;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,16 @@ export const CUSTOM_CHART_DEFAULT_PARSED = {
data: [],
},
};

export enum LabelOrientation {
AUTO = "auto",
SLANT = "slant",
ROTATE = "rotate",
STAGGER = "stagger",
}

export const LABEL_ORIENTATION_COMPATIBLE_CHARTS = [
"LINE_CHART",
"AREA_CHART",
"COLUMN_CHART",
];
2 changes: 2 additions & 0 deletions app/client/src/mockResponses/WidgetConfigResponse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
ButtonStyleTypes,
ButtonVariantTypes,
} from "components/designSystems/appsmith/IconButtonComponent";
import { LabelOrientation } from "constants/ChartConstants";

/*
********************************{Grid Density Migration}*********************************
Expand Down Expand Up @@ -655,6 +656,7 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
},
xAxisName: "Last Week",
yAxisName: "Total Order Revenue $",
labelOrientation: LabelOrientation.AUTO,
customFusionChartConfig: {
type: "column2d",
dataSource: {
Expand Down
29 changes: 13 additions & 16 deletions app/client/src/widgets/ChartWidget/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import * as Sentry from "@sentry/react";
import React, { lazy, Suspense } from "react";

import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget";
import { WidgetType } from "constants/WidgetConstants";
import propertyConfig from "widgets/ChartWidget/propertyConfig";
import Skeleton from "components/utils/Skeleton";
import * as Sentry from "@sentry/react";
import { retryPromise } from "utils/AppsmithUtils";
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
import withMeta, { WithMeta } from "widgets/MetaHOC";
import propertyConfig from "widgets/ChartWidget/propertyConfig";
import {
CustomFusionChartConfig,
ChartComponentProps,
ChartSelectedDataPoint,
} from "components/designSystems/appsmith/ChartComponent";
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
import { retryPromise } from "utils/AppsmithUtils";
import { WidgetType } from "constants/WidgetConstants";

const ChartComponent = lazy(() =>
retryPromise(() =>
Expand Down Expand Up @@ -56,6 +57,7 @@ class ChartWidget extends BaseWidget<ChartWidgetProps, WidgetState> {
customFusionChartConfig={this.props.customFusionChartConfig}
isVisible={this.props.isVisible}
key={this.props.widgetId}
labelOrientation={this.props.labelOrientation}
onDataPointClick={this.onDataPointClick}
widgetId={this.props.widgetId}
xAxisName={this.props.xAxisName}
Expand Down Expand Up @@ -92,17 +94,12 @@ export interface ChartData {
data: ChartDataPoint[];
}

export interface ChartWidgetProps extends WidgetProps, WithMeta {
chartType: ChartType;
chartData: AllChartData;
customFusionChartConfig: CustomFusionChartConfig;
xAxisName: string;
yAxisName: string;
chartName: string;
isVisible?: boolean;
allowHorizontalScroll: boolean;
type ChartComponentPartialProps = Omit<ChartComponentProps, "onDataPointClick">;
export interface ChartWidgetProps
extends WidgetProps,
WithMeta,
ChartComponentPartialProps {
onDataPointClick?: string;
selectedDataPoint?: ChartDataPoint;
}

export default ChartWidget;
Expand Down
16 changes: 16 additions & 0 deletions app/client/src/widgets/ChartWidget/propertyConfig.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable @typescript-eslint/no-namespace */
import { isString, get } from "lodash";

import config from "./propertyConfig";
import { PropertyPaneControlConfig } from "constants/PropertyControlConstants";

declare global {
namespace jest {
Expand Down Expand Up @@ -87,4 +89,18 @@ describe("Validate Chart Widget's property config", () => {
expect(result).toBeTruthy();
});
});

it("Validates that axis labelOrientation is visible when chartType are LINE_CHART AREA_CHART COLUMN_CHART", () => {
const allowedChartsTypes = ["LINE_CHART", "AREA_CHART", "COLUMN_CHART"];

const axisSection = config.find((c) => c.sectionName === "Axis");
const labelOrientationProperty = ((axisSection?.children as unknown) as PropertyPaneControlConfig[]).find(
(p) => p.propertyName === "labelOrientation",
);

allowedChartsTypes.forEach((chartType) => {
const result = labelOrientationProperty?.hidden?.({ chartType }, "");
expect(result).toBeFalsy();
});
});
});
34 changes: 32 additions & 2 deletions app/client/src/widgets/ChartWidget/propertyConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ChartWidgetProps } from "widgets/ChartWidget";
import { ValidationTypes } from "constants/WidgetValidation";
import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
import { CUSTOM_CHART_TYPES } from "constants/CustomChartConstants";
import { CUSTOM_CHART_TYPES, LabelOrientation } from "constants/ChartConstants";
import { isLabelOrientationApplicableFor } from "components/designSystems/appsmith/ChartComponent";

export default [
{
Expand Down Expand Up @@ -244,9 +245,38 @@ export default [
controlType: "SWITCH",
isBindProperty: false,
isTriggerProperty: false,
hidden: (x: any) => x.chartType === "CUSTOM_FUSION_CHART",
hidden: (x: ChartWidgetProps) => x.chartType === "CUSTOM_FUSION_CHART",
dependencies: ["chartType"],
},
{
helpText: "Changes the x-axis label orientation",
propertyName: "labelOrientation",
label: "x-axis Label Orientation",
hidden: (x: ChartWidgetProps) =>
!isLabelOrientationApplicableFor(x.chartType),
isBindProperty: false,
isTriggerProperty: false,
dependencies: ["chartType"],
controlType: "DROP_DOWN",
options: [
{
label: "Auto",
value: LabelOrientation.AUTO,
},
{
label: "Slant",
value: LabelOrientation.SLANT,
},
{
label: "Rotate",
value: LabelOrientation.ROTATE,
},
{
label: "Stagger",
value: LabelOrientation.STAGGER,
},
],
},
],
},
{
Expand Down