Skip to content
This repository has been archived by the owner on Jun 25, 2020. It is now read-only.

feat: line chart with revised encodeable utilities #26

Merged
merged 19 commits into from
Mar 28, 2019
Merged

Conversation

kristw
Copy link
Collaborator

@kristw kristw commented Mar 23, 2019

tl;dr. This PR add the first working version of the new Line Chart.

🌕Code Overview

This PR adds two new LineChart plugins under the preset-chart-xy package. Both plugins point to the same Chart component but has different ChartMetadata and transformProps. The legacy-compatible plugin will have the same ChartMetadata with the useLegacyApi field set to true. The transformProps is the key difference as the legacy-compatible plugin converts legacy formData to the new formData while the new plugin's transformProps does very little.

image

📈 Line Chart

In Line.tsx, which is the main chart component. Line uses XYChartLayout, which is a cross-chart utility, to compute necessary margins and labelling strategy for the axes. It also uses ChartLegend to display legend. In addition, it has two chart-specific subcomponents.

Encoder

The Encoder captures it visual encoding channels (x, y, color, fill, strokeDasharray). Each channel has a ChannelType (X | Y | XBand | YBand | Color, Category | Text) and Output (string | boolean | number | null). These two type parameters are used to generate Encoding type, which is a vega-lite-ish encoding grammar.

Once the Encoder is initialized and passed in the actual encoding config, it can provide utility functions for getting value from datum, encoding values, as well as things we usually want from scale or axis.

Tooltip

This simply renders chart-specific tooltip.

📐 Chart Layout

A chart has multiple wrappers. At the top level <WithLegend /> attaches legend to one side of the chart, splitting the container into two parts: legend and ChartFrame. Legend will take only necessary space and give the rest to ChartFrame. The actual chart is contained within the ChartFrame and usually has the same size. However, in some case when the chart has to guarantee minimum width and/or height to be usable and the ChartFrame is too small for that, the chart will be given the specified minimum width and/or height, making the ChartFrame scrollable instead.

IMG_4686

📘 Documentation

Update the storybook for line chart in packages/superset-ui-plugins-demo/storybook/stories/preset-chart-xy

  • Basic line chart
  • Legacy-compatible version
    image
  • Line chart with missing data
    image
  • Encoding dasharray and fill
    image

🔮 Future Work

There are still work remaining after this PR. This PR is a major milestone but not completion.

  • Optimize to create Encoder only when necessary.
  • Make creating an Encoder class more convenient.
  • Merge computeXAxisLayout() and computeYAxisLayout() into AxisAgent.
  • Make AxisAgent derive config type (XAxis | YAxis) from channel type.
  • Handle data points surrounded by missing data.
  • Make storybook demo tsx work with knobs without complaining about types

@kristw kristw requested a review from a team as a code owner March 23, 2019 01:21
@kristw kristw mentioned this pull request Mar 26, 2019
Copy link
Contributor

@williaster williaster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great overall, thanks for all the effort here! 💛 💜

type: 'time',
},
axis: {
orientation: 'bottom',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could abstract these into knobs for easy debugging and demo-ing what it does.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I converted it to tsx then add knobs. Then it starts complaining for missing types definition for external module. I renamed it back to jsx and will take care of the tsx and external type def issue in a follow-up pr.

packages/superset-ui-preset-chart-xy/src/Line/Line.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@conglei conglei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work!! Just left some comments on

  1. Customizability issue'

  2. the style Props and defaultProps.

Both are nit :)

packages/superset-ui-preset-chart-xy/src/Line/Line.tsx Outdated Show resolved Hide resolved
parent: Series;
}

const CIRCLE_STYLE = { strokeWidth: 1.5 };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it mean users cannot customize the style? If the chart is tailored specially for superset, I won't see it will be an issue. But just was thinking of the customization part.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only for the highlighted circle when using crosshair. May have to think more carefully about how to expose customization.

return (
<div key={field} style={LEGEND_CONTAINER_STYLE}>
<LegendOrdinal scale={scale} labelFormat={channelEncoder.formatValue}>
{(labels: Label[]) => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we done the test with extremely large number of legends here? So far, there are a lot of chart in Superset that has more than I'd say 20 legends. At least we need to make sure the chart can be rendered.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LEGEND_CONTAINER_STYLE caps the legend with maxHeight.

@@ -29,34 +11,32 @@ type Props = {
legendJustifyContent: 'center' | 'flex-start' | 'flex-end';
position: 'top' | 'left' | 'bottom' | 'right';
renderChart: (dim: { width: number; height: number }) => ReactNode;
renderLegend: (params: { direction: string }) => ReactNode;
hideLegend: boolean;
renderLegend?: (params: { direction: string }) => ReactNode;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw we have two different ways to define Props with defaultProps. Can we make the styles consistent? I do like the way you defined before, with & typeof defaultProps.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, fixed.

@kristw kristw merged commit c9b8195 into master Mar 28, 2019
@delete-merged-branch delete-merged-branch bot deleted the kristw--line3 branch March 28, 2019 23:58
nytai referenced this pull request in preset-io/superset-ui-plugins Apr 27, 2020
nytai referenced this pull request in preset-io/superset-ui-plugins Apr 27, 2020
* feat: line chart

* feat: implement scale extraction

* refactor: no error

* fix: handle null

* fix: nicing and demo

* fix: legend and demo

* fix: remove commented code

* fix: clean

* fix: reviewer comments

* fix: legend and series

* docs: make demos tsx

* fix: reactnode

* fix: label angle

* fix: resolve labelxxx field names

* docs: try knobs

* feat: improve axis

* refactor: combine computelayout into axisagent

* refactor: cleaner use of scale

* fix: proptypes
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants