From e498004c99f5212762df298010f0321eface36ff Mon Sep 17 00:00:00 2001 From: Alexander Polyankin <alexander.polyankin@metabase.com> Date: Thu, 26 Aug 2021 18:26:27 +0300 Subject: [PATCH] Add simple static categorical bar (#17600) --- .../metabase/internal/pages/StaticVizPage.jsx | 23 +++++- .../metabase/static-viz/categorical/bar.js | 74 +++++++++++++++++++ .../metabase/static-viz/categorical/index.js | 5 +- frontend/src/metabase/static-viz/index.js | 11 ++- 4 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 frontend/src/metabase/static-viz/categorical/bar.js diff --git a/frontend/src/metabase/internal/pages/StaticVizPage.jsx b/frontend/src/metabase/internal/pages/StaticVizPage.jsx index bde75c497ea..d86f2fe05ce 100644 --- a/frontend/src/metabase/internal/pages/StaticVizPage.jsx +++ b/frontend/src/metabase/internal/pages/StaticVizPage.jsx @@ -34,7 +34,7 @@ export default function StaticVizPage() { }, }), }} - ></Box> + /> </Box> <Box py={3}> <Subhead>Line chart with timeseries data</Subhead> @@ -55,7 +55,24 @@ export default function StaticVizPage() { }, }), }} - ></Box> + /> + </Box> + <Box py={3}> + <Subhead>Bar chart showing categorical data</Subhead> + <Box + dangerouslySetInnerHTML={{ + __html: RenderChart("categorical/bar", { + data: [["donut", 20], ["cronut", 31]], + accessors: { + x: row => row[0], + y: row => row[1], + }, + labels: { + bottom: "Category", + }, + }), + }} + /> </Box> <Box py={3}> <Subhead>Donut chart showing categorical data</Subhead> @@ -73,7 +90,7 @@ export default function StaticVizPage() { }, }), }} - ></Box> + /> </Box> </Box> </Box> diff --git a/frontend/src/metabase/static-viz/categorical/bar.js b/frontend/src/metabase/static-viz/categorical/bar.js new file mode 100644 index 00000000000..5b0145472d7 --- /dev/null +++ b/frontend/src/metabase/static-viz/categorical/bar.js @@ -0,0 +1,74 @@ +/* eslint-disable react/prop-types */ +import React from "react"; +import { t } from "ttag"; +import { Bar } from "@visx/shape"; +import { AxisLeft, AxisBottom } from "@visx/axis"; +import { scaleBand, scaleLinear } from "@visx/scale"; +import { bottomAxisTickStyles, leftAxisTickStyles } from "../utils.js"; +import { GridRows } from "@visx/grid"; + +export default function CategoricalBar( + { data, yScaleType = scaleLinear, accessors, labels }, + layout, +) { + const leftMargin = 55; + const xAxisScale = scaleBand({ + domain: data.map(accessors.x), + range: [leftMargin, layout.xMax], + round: true, + padding: 0.2, + }); + + const yAxisScale = yScaleType({ + domain: [0, Math.max(...data.map(accessors.y))], + range: [layout.yMax, 0], + nice: true, + }); + + return ( + <svg width={layout.width} height={layout.height}> + <GridRows + scale={yAxisScale} + width={layout.xMax - leftMargin} + left={leftMargin} + strokeDasharray="4" + /> + {data.map(d => { + const barWidth = xAxisScale.bandwidth(); + const barHeight = layout.yMax - yAxisScale(accessors.y(d)); + const x = xAxisScale(accessors.x(d)); + const y = layout.yMax - barHeight; + return ( + <Bar + key={`bar-${x}`} + width={barWidth} + height={barHeight} + x={x} + y={y} + fill="#509ee3" + /> + ); + })} + <AxisLeft + hideTicks + hideAxisLine + tickFormat={d => { + return String(d); + }} + scale={yAxisScale} + label={labels.left || t`Count`} + left={leftMargin} + tickLabelProps={() => leftAxisTickStyles(layout)} + /> + <AxisBottom + hideTicks={false} + numTicks={5} + top={layout.yMax} + scale={xAxisScale} + stroke={layout.colors.axis.stroke} + label={labels.bottom || t`Category`} + tickLabelProps={() => bottomAxisTickStyles(layout)} + /> + </svg> + ); +} diff --git a/frontend/src/metabase/static-viz/categorical/index.js b/frontend/src/metabase/static-viz/categorical/index.js index 14562178cf6..8777f0d0ad5 100644 --- a/frontend/src/metabase/static-viz/categorical/index.js +++ b/frontend/src/metabase/static-viz/categorical/index.js @@ -1,3 +1,4 @@ -import Donut from "./donut.js"; +import CategoricalBar from "./bar.js"; +import CategoricalDonut from "./donut.js"; -export { Donut }; +export { CategoricalBar, CategoricalDonut }; diff --git a/frontend/src/metabase/static-viz/index.js b/frontend/src/metabase/static-viz/index.js index a5166be810d..9e594d69534 100644 --- a/frontend/src/metabase/static-viz/index.js +++ b/frontend/src/metabase/static-viz/index.js @@ -1,7 +1,10 @@ import ReactDOMServer from "react-dom/server"; import { TimeseriesBar, TimeseriesLine } from "metabase/static-viz/timeseries/"; -import { Donut } from "metabase/static-viz/categorical/"; +import { + CategoricalBar, + CategoricalDonut, +} from "metabase/static-viz/categorical/"; const DEFAULTS = { width: 540, @@ -24,6 +27,7 @@ const DEFAULTS = { const TIMESERIES_BAR = "timeseries/bar"; const TIMESERIES_LINE = "timeseries/line"; +const CATEGORICAL_BAR = "categorical/bar"; const CATEGORICAL_DONUT = "categorical/donut"; export function RenderChart(type, logic, layout = DEFAULTS) { @@ -39,8 +43,11 @@ export function RenderChart(type, logic, layout = DEFAULTS) { case TIMESERIES_LINE: chart = TimeseriesLine(logic, { ...layout, xMax, yMax }); break; + case CATEGORICAL_BAR: + chart = CategoricalBar(logic, { ...layout, xMax, yMax }); + break; case CATEGORICAL_DONUT: - chart = Donut(logic, { ...layout, height: 540, xMax, yMax }); + chart = CategoricalDonut(logic, { ...layout, height: 540, xMax, yMax }); break; } -- GitLab