Skip to content

Commit

Permalink
Add option to choose color scheme for charts (#7062)
Browse files Browse the repository at this point in the history
  • Loading branch information
ezraodio1 authored Aug 8, 2024
1 parent 285c2b6 commit 9de135c
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 55 deletions.
70 changes: 50 additions & 20 deletions client/cypress/integration/visualizations/chart_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,33 @@ const SQL = `
describe("Chart", () => {
beforeEach(() => {
cy.login();
cy.createQuery({ name: "Chart Visualization", query: SQL })
.its("id")
.as("queryId");
cy.createQuery({ name: "Chart Visualization", query: SQL }).its("id").as("queryId");
});

it("creates Bar charts", function() {
it("creates Bar charts", function () {
cy.visit(`queries/${this.queryId}/source`);
cy.getByTestId("ExecuteButton").click();

const getBarChartAssertionFunction = (specificBarChartAssertionFn = () => {}) => () => {
// checks for TabbedEditor standard tabs
assertTabbedEditor();
const getBarChartAssertionFunction =
(specificBarChartAssertionFn = () => {}) =>
() => {
// checks for TabbedEditor standard tabs
assertTabbedEditor();

// standard chart should be bar
cy.getByTestId("Chart.GlobalSeriesType").contains(".ant-select-selection-item", "Bar");
// standard chart should be bar
cy.getByTestId("Chart.GlobalSeriesType").contains(".ant-select-selection-item", "Bar");

// checks the plot canvas exists and is empty
assertPlotPreview("not.exist");
// checks the plot canvas exists and is empty
assertPlotPreview("not.exist");

// creates a chart and checks it is plotted
cy.getByTestId("Chart.ColumnMapping.x").selectAntdOption("Chart.ColumnMapping.x.stage");
cy.getByTestId("Chart.ColumnMapping.y").selectAntdOption("Chart.ColumnMapping.y.value1");
cy.getByTestId("Chart.ColumnMapping.y").selectAntdOption("Chart.ColumnMapping.y.value2");
assertPlotPreview("exist");
// creates a chart and checks it is plotted
cy.getByTestId("Chart.ColumnMapping.x").selectAntdOption("Chart.ColumnMapping.x.stage");
cy.getByTestId("Chart.ColumnMapping.y").selectAntdOption("Chart.ColumnMapping.y.value1");
cy.getByTestId("Chart.ColumnMapping.y").selectAntdOption("Chart.ColumnMapping.y.value2");
assertPlotPreview("exist");

specificBarChartAssertionFn();
};
specificBarChartAssertionFn();
};

const chartTests = [
{
Expand Down Expand Up @@ -95,8 +95,8 @@ describe("Chart", () => {

const withDashboardWidgetsAssertionFn = (widgetGetters, dashboardUrl) => {
cy.visit(dashboardUrl);
widgetGetters.forEach(widgetGetter => {
cy.get(`@${widgetGetter}`).then(widget => {
widgetGetters.forEach((widgetGetter) => {
cy.get(`@${widgetGetter}`).then((widget) => {
cy.getByTestId(getWidgetTestId(widget)).within(() => {
cy.get("g.points").should("exist");
});
Expand All @@ -107,4 +107,34 @@ describe("Chart", () => {
createDashboardWithCharts("Bar chart visualizations", chartGetters, withDashboardWidgetsAssertionFn);
cy.percySnapshot("Visualizations - Charts - Bar");
});
it("colors Bar charts", function () {
cy.visit(`queries/${this.queryId}/source`);
cy.getByTestId("ExecuteButton").click();
cy.getByTestId("NewVisualization").click();
cy.getByTestId("Chart.ColumnMapping.x").selectAntdOption("Chart.ColumnMapping.x.stage");
cy.getByTestId("Chart.ColumnMapping.y").selectAntdOption("Chart.ColumnMapping.y.value1");
cy.getByTestId("VisualizationEditor.Tabs.Colors").click();
cy.getByTestId("ColorScheme").click();
cy.getByTestId("ColorOptionViridis").click();
cy.getByTestId("ColorScheme").click();
cy.getByTestId("ColorOptionTableau 10").click();
cy.getByTestId("ColorScheme").click();
cy.getByTestId("ColorOptionD3 Category 10").click();
});
it("colors Pie charts", function () {
cy.visit(`queries/${this.queryId}/source`);
cy.getByTestId("ExecuteButton").click();
cy.getByTestId("NewVisualization").click();
cy.getByTestId("Chart.GlobalSeriesType").click();
cy.getByTestId("Chart.ChartType.pie").click();
cy.getByTestId("Chart.ColumnMapping.x").selectAntdOption("Chart.ColumnMapping.x.stage");
cy.getByTestId("Chart.ColumnMapping.y").selectAntdOption("Chart.ColumnMapping.y.value1");
cy.getByTestId("VisualizationEditor.Tabs.Colors").click();
cy.getByTestId("ColorScheme").click();
cy.getByTestId("ColorOptionViridis").click();
cy.getByTestId("ColorScheme").click();
cy.getByTestId("ColorOptionTableau 10").click();
cy.getByTestId("ColorScheme").click();
cy.getByTestId("ColorOptionD3 Category 10").click();
});
});
73 changes: 70 additions & 3 deletions viz-lib/src/visualizations/ColorPalette.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { values } from "lodash";

// The following colors will be used if you pick "Automatic" color
// Define color palettes
export const BaseColors = {
Blue: "#356AFF",
Red: "#E92828",
Expand Down Expand Up @@ -28,11 +28,78 @@ export const AdditionalColors = {
"Pink 2": "#C63FA9",
};

export const ColorPaletteArray = values(BaseColors);
const Viridis = {
1: '#440154',
2: '#48186a',
3: '#472d7b',
4: '#424086',
5: '#3b528b',
6: '#33638d',
7: '#2c728e',
8: '#26828e',
9: '#21918c',
10: '#1fa088',
11: '#28ae80',
12: '#3fbc73',
13: '#5ec962',
14: '#84d44b',
15: '#addc30',
16: '#d8e219',
17: '#fde725',
};

const Tableau = {
1 : "#4e79a7",
2 : "#f28e2c",
3 : "#e15759",
4 : "#76b7b2",
5 : "#59a14f",
6 : "#edc949",
7 : "#af7aa1",
8 : "#ff9da7",
9 : "#9c755f",
10 : "#bab0ab",
}

const ColorPalette = {
const D3Category10 = {
1 : "#1f77b4",
2 : "#ff7f0e",
3 : "#2ca02c",
4 : "#d62728",
5 : "#9467bd",
6 : "#8c564b",
7 : "#e377c2",
8 : "#7f7f7f",
9 : "#bcbd22",
10 : "#17becf",
}

let ColorPalette = {
...BaseColors,
...AdditionalColors,
};

export const ColorPaletteArray = values(ColorPalette);

export default ColorPalette;

export const AllColorPalettes = {
"Redash" : ColorPalette,
"Viridis" : Viridis,
"Tableau 10" : Tableau,
"D3 Category 10" : D3Category10,
}

export const AllColorPaletteArrays = {
"Redash" : ColorPaletteArray,
"Viridis" : values(Viridis),
"Tableau 10" : values(Tableau),
"D3 Category 10" : values(D3Category10),
};

export const ColorPaletteTypes = {
"Redash" : 'discrete',
"Viridis" : 'continuous',
"Tableau 10" : 'discrete',
"D3 Category 10" : 'discrete',
}
29 changes: 24 additions & 5 deletions viz-lib/src/visualizations/chart/Editor/DefaultColorsSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ import React, { useMemo, useCallback } from "react";
import Table from "antd/lib/table";
import ColorPicker from "@/components/ColorPicker";
import { EditorPropTypes } from "@/visualizations/prop-types";
import ColorPalette from "@/visualizations/ColorPalette";
import { AllColorPalettes } from "@/visualizations/ColorPalette";
import getChartData from "../getChartData";
import { Section, Select } from "@/components/visualizations/editor";

export default function DefaultColorsSettings({ options, data, onOptionsChange }: any) {
const colors = useMemo(
() => ({
Automatic: null,
...ColorPalette,
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
...AllColorPalettes[options.color_scheme],
}),
[]
[options.color_scheme]
);

const series = useMemo(
Expand Down Expand Up @@ -67,8 +69,25 @@ export default function DefaultColorsSettings({ options, data, onOptionsChange }
},
];

// @ts-expect-error ts-migrate(2322) FIXME: Type 'boolean[]' is not assignable to type 'object... Remove this comment to see the full error message
return <Table showHeader={false} dataSource={series} columns={columns} pagination={false} />;
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Select
label="Color Scheme"
defaultValue={options.color_scheme}
data-test="ColorScheme"
onChange={(val : any) => onOptionsChange({ color_scheme: val })}>
{Object.keys(AllColorPalettes).map(option => (
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message
<Select.Option data-test={`ColorOption${option}`} key={option} value={option}>{option}</Select.Option>
))}
</Select>
</Section>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type 'boolean[]' is not assignable to type 'object... Remove this comment to see the full error message */}
<Table showHeader={false} dataSource={series} columns={columns} pagination={false} />
</React.Fragment>
)
}

DefaultColorsSettings.propTypes = EditorPropTypes;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useMemo } from "react";
import { Section, Select, Checkbox, InputNumber, ContextHelp, Input } from "@/components/visualizations/editor";
import { UpdateOptionsStrategy } from "@/components/visualizations/editor/createTabbedEditor";
import { EditorPropTypes } from "@/visualizations/prop-types";

import { AllColorPalettes } from "@/visualizations/ColorPalette";
import ChartTypeSelect from "./ChartTypeSelect";
import ColumnMappingSelect from "./ColumnMappingSelect";
import { useDebouncedCallback } from "use-debounce/lib";
Expand Down
27 changes: 23 additions & 4 deletions viz-lib/src/visualizations/chart/Editor/PieColorsSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import React, { useMemo, useCallback } from "react";
import Table from "antd/lib/table";
import ColorPicker from "@/components/ColorPicker";
import { EditorPropTypes } from "@/visualizations/prop-types";
import ColorPalette from "@/visualizations/ColorPalette";
import { AllColorPalettes } from "@/visualizations/ColorPalette";
import getChartData from "../getChartData";
import { Section, Select } from "@/components/visualizations/editor";

function getUniqueValues(chartData: any) {
const uniqueValuesNames = new Set();
Expand All @@ -20,9 +21,10 @@ export default function PieColorsSettings({ options, data, onOptionsChange }: an
const colors = useMemo(
() => ({
Automatic: null,
...ColorPalette,
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
...AllColorPalettes[options.color_scheme],
}),
[]
[options.color_scheme]
);

const series = useMemo(
Expand Down Expand Up @@ -78,7 +80,24 @@ export default function PieColorsSettings({ options, data, onOptionsChange }: an
},
];

return <Table showHeader={false} dataSource={series} columns={columns} pagination={false} />;
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Select
label="Color Scheme"
defaultValue={options.color_scheme}
data-test="ColorScheme"
onChange={(val : any) => onOptionsChange({ color_scheme: val })}>
{Object.keys(AllColorPalettes).map(option => (
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message
<Select.Option data-test={`ColorOption${option}`} key={option} value={option}>{option}</Select.Option>
))}
</Select>
</Section>
<Table showHeader={false} dataSource={series} columns={columns} pagination={false} />
</React.Fragment>
)
}

PieColorsSettings.propTypes = EditorPropTypes;
1 change: 1 addition & 0 deletions viz-lib/src/visualizations/chart/getOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const DEFAULT_OPTIONS = {
sizemode: "diameter",
coefficient: 1,
piesort: true,
color_scheme: "Redash",

// showDataLabels: false, // depends on chart type
numberFormat: "0,0[.]00000",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"columnMapping": {
"x": "x",
"y": "y"
}
},
"color_scheme": "Redash"
},
"data": [
{
Expand Down Expand Up @@ -47,7 +48,8 @@
"textfont": { "color": ["#ffffff", "#ffffff", "#333333", "#ffffff"] },
"name": "a",
"direction": "counterclockwise",
"domain": { "x": [0, 0.98], "y": [0, 0.9] }
"domain": { "x": [0, 0.98], "y": [0, 0.9] },
"color_scheme": "Redash"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"columnMapping": {
"x": "x",
"y": "y"
}
},
"color_scheme": "Redash"
},
"data": [
{
Expand Down Expand Up @@ -47,7 +48,8 @@
"textfont": { "color": ["#ffffff", "#ffffff", "#333333", "#ffffff"] },
"name": "a",
"direction": "counterclockwise",
"domain": { "x": [0, 0.98], "y": [0, 0.9] }
"domain": { "x": [0, 0.98], "y": [0, 0.9] },
"color_scheme": "Redash"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"columnMapping": {
"x": "x",
"y": "y"
}
},
"color_scheme": "Redash"
},
"data": [
{
Expand Down Expand Up @@ -47,7 +48,8 @@
"textfont": { "color": ["#ffffff", "#ffffff", "#333333", "#ffffff"] },
"name": "a",
"direction": "counterclockwise",
"domain": { "x": [0, 0.98], "y": [0, 0.9] }
"domain": { "x": [0, 0.98], "y": [0, 0.9] },
"color_scheme": "Redash"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"direction": { "type": "counterclockwise" },
"xAxis": { "type": "-", "labels": { "enabled": true } },
"yAxis": [{ "type": "linear" }, { "type": "linear", "opposite": true }],
"series": { "stacking": null, "error_y": { "type": "data", "visible": true } }
"series": { "stacking": null, "error_y": { "type": "data", "visible": true } },
"color_scheme": "Redash"
},
"data": [
{
Expand Down Expand Up @@ -43,7 +44,8 @@
"textfont": { "color": ["#ffffff"] },
"name": "a",
"direction": "counterclockwise",
"domain": { "x": [0, 0.98], "y": [0, 0.9] }
"domain": { "x": [0, 0.98], "y": [0, 0.9] },
"color_scheme": "Redash"
}
]
}
Expand Down
Loading

0 comments on commit 9de135c

Please sign in to comment.