diff --git a/packages/superset-ui-legacy-plugin-grouped-column-line-chart/README.md b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/README.md new file mode 100644 index 000000000..f1fa855c8 --- /dev/null +++ b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/README.md @@ -0,0 +1,31 @@ +## @superset-ui/legacy-plugin-grouped_column_line_chart + +[![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-plugin-chart-table&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-plugin-chart-table) + +This plugin provides Grouped Column Line Chart for Superset. + +### Usage + +Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app. + +```js +import TableChartPlugin from '@superset-ui/legacy-plugin-grouped-column-line-chart'; + +new TableChartPlugin() + .configure({ key: 'grouped_column_line_chart' }) + .register(); +``` + +Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui-plugins/) for more details. + +```js + +``` \ No newline at end of file diff --git a/packages/superset-ui-legacy-plugin-grouped-column-line-chart/package.json b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/package.json new file mode 100644 index 000000000..50b312644 --- /dev/null +++ b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/package.json @@ -0,0 +1,44 @@ +{ + "name": "@superset-ui/legacy-plugin-grouped-column-line-chart", + "version": "0.1.1", + "description": "Superset Legacy Chart - Grouped Chart", + "sideEffects": [ + "*.css" + ], + "main": "lib/index.js", + "module": "esm/index.js", + "files": [ + "esm", + "lib" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/apache-superset/superset-ui-plugins.git" + }, + "keywords": [ + "superset" + ], + "author": "Superset", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/apache-superset/superset-ui-plugins/issues" + }, + "homepage": "https://github.com/apache-superset/superset-ui-plugins#readme", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@data-ui/xy-chart": "^0.0.84", + "@data-ui/theme": "^0.0.82", + "@vx/legend": "^0.0.192", + "@vx/responsive": "^0.0.192", + "@vx/scale": "^0.0.192", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "@superset-ui/chart": "^0.12.0", + "@superset-ui/color": "^0.12.0", + "@superset-ui/translation": "^0.12.0", + "react": "^15 || ^16" + } +} diff --git a/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/GroupedChart.css b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/GroupedChart.css new file mode 100644 index 000000000..ff5643cfd --- /dev/null +++ b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/GroupedChart.css @@ -0,0 +1,24 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.superset-legacy-grouped-chart { + margin-left: 2%; + overflow-x: scroll; + overflow-y: hidden; +} \ No newline at end of file diff --git a/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/GroupedChart.jsx b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/GroupedChart.jsx new file mode 100644 index 000000000..bab6915c6 --- /dev/null +++ b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/GroupedChart.jsx @@ -0,0 +1,164 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* eslint-disable sort-keys */ +import PropTypes from 'prop-types'; +import React from 'react'; +import { XYChart, LineSeries, CrossHair, BarSeries, XAxis, YAxis } from '@data-ui/xy-chart'; +import { chartTheme } from '@data-ui/theme'; +import { LegendOrdinal } from '@vx/legend'; +import { scaleOrdinal } from '@vx/scale'; +import { CategoricalColorNamespace } from '@superset-ui/color'; +import WithLegend from './WithLegend'; +import './GroupedChart.css'; + +const propTypes = { + className: PropTypes.string, + data: PropTypes.arrayOf( + PropTypes.shape({ + key: PropTypes.string, + values: PropTypes.arrayOf(PropTypes.number), + }), + ).isRequired, + width: PropTypes.number.isRequired, + height: PropTypes.number.isRequired, + colorScheme: PropTypes.string, + normalized: PropTypes.bool, + binCount: PropTypes.number, + opacity: PropTypes.number, + xAxisLabel: PropTypes.string, + yAxisLabel: PropTypes.string, +}; +const defaultProps = { + className: '', + colorScheme: '', + normalized: false, + binCount: 15, + opacity: 1, + xAxisLabel: '', + yAxisLabel: '', +}; + +class GroupedChart extends React.PureComponent { + render() { + const { + className, + data, + width, + height, + binCount, + colorScheme, + normalized, + opacity, + xAxisLabel, + yAxisLabel, + } = this.props; + + const colorFn = CategoricalColorNamespace.getScale(colorScheme); + const keys = data.map(d => d.key); + const colorScale = scaleOrdinal({ + domain: keys, + range: keys.map(colorFn), + }); + + return ( + ( + + )} + renderChart={parent => ( + ( +
+ {datum.label} +
+ x + {datum.x} +
+
+ y + {datum.y} +
+
+ )} + valueAccessor={datum => datum} + theme={chartTheme} + > + {data.map(series => (series.renderas === "bar" ? ( + + ):( + + )))} + + { + if (tick >= 1000000000) { + return (tick / 1000000000).toFixed(1).replace(/\.0$/, '') + 'G'; + } + if (tick >= 1000000) { + return (tick / 1000000).toFixed(1).replace(/\.0$/, '') + 'M'; + } + if (tick >= 1000) { + return (tick / 1000).toFixed(1).replace(/\.0$/, '') + 'K'; + } else { + return tick; + } + }} /> + +
+ )} + /> + ); + } +} + +GroupedChart.propTypes = propTypes; +GroupedChart.defaultProps = defaultProps; + +export default GroupedChart; diff --git a/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/WithLegend.jsx b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/WithLegend.jsx new file mode 100644 index 000000000..1960d9d06 --- /dev/null +++ b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/WithLegend.jsx @@ -0,0 +1,147 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* eslint-disable sort-keys */ +import React from 'react'; +import PropTypes from 'prop-types'; +import { ParentSize } from '@vx/responsive'; + +const propTypes = { + className: PropTypes.string, + width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + renderChart: PropTypes.func.isRequired, + renderLegend: PropTypes.func.isRequired, + position: PropTypes.oneOf(['top', 'left', 'bottom', 'right']), + legendJustifyContent: PropTypes.oneOf(['center', 'flex-start', 'flex-end']), +}; +const defaultProps = { + className: '', + width: 'auto', + height: 'auto', + position: 'top', + legendJustifyContent: undefined, +}; + +const LEGEND_STYLE_BASE = { + display: 'flex', + flexGrow: 0, + flexShrink: 0, + order: -1, + paddingTop: '5px', + fontSize: '0.9em', +}; + +const CHART_STYLE_BASE = { + flexGrow: 1, + flexShrink: 1, + flexBasis: 'auto', + position: 'relative', +}; + +class WithLegend extends React.Component { + getContainerDirection() { + const { position } = this.props; + switch (position) { + case 'left': + return 'row'; + case 'right': + return 'row-reverse'; + case 'bottom': + return 'column-reverse'; + default: + case 'top': + return 'column'; + } + } + + getLegendJustifyContent() { + const { legendJustifyContent, position } = this.props; + if (legendJustifyContent) { + return legendJustifyContent; + } + switch (position) { + case 'left': + return 'flex-start'; + case 'right': + return 'flex-start'; + case 'bottom': + return 'flex-end'; + default: + case 'top': + return 'flex-end'; + } + } + + render() { + const { className, width, height, position, renderChart, renderLegend } = this.props; + + const isHorizontal = position === 'left' || position === 'right'; + + const style = { + display: 'flex', + flexDirection: this.getContainerDirection(), + }; + if (width) { + style.width = width; + } + if (height) { + style.height = height; + } + + const chartStyle = { ...CHART_STYLE_BASE }; + if (isHorizontal) { + chartStyle.width = 0; + } else { + chartStyle.height = 0; + } + + const legendDirection = isHorizontal ? 'column' : 'row'; + const legendStyle = { + ...LEGEND_STYLE_BASE, + flexDirection: legendDirection, + justifyContent: this.getLegendJustifyContent(), + }; + + return ( +
+
+ {renderLegend({ + // Pass flexDirection for @vx/legend to arrange legend items + direction: legendDirection, + })} +
+
+ + {parent => + parent.width > 0 && parent.height > 0 + ? // Only render when necessary + renderChart(parent) + : null + } + +
+
+ ); + } +} + +WithLegend.propTypes = propTypes; +WithLegend.defaultProps = defaultProps; + +export default WithLegend; diff --git a/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/images/thumbnail.png b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/images/thumbnail.png new file mode 100644 index 000000000..f9f6af5a5 Binary files /dev/null and b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/images/thumbnail.png differ diff --git a/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/images/thumbnailLarge.png b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/images/thumbnailLarge.png new file mode 100644 index 000000000..8a97d47d8 Binary files /dev/null and b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/images/thumbnailLarge.png differ diff --git a/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/index.js b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/index.js new file mode 100644 index 000000000..f15a150f3 --- /dev/null +++ b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/index.js @@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { t } from '@superset-ui/translation'; +import { ChartMetadata, ChartPlugin } from '@superset-ui/chart'; +import transformProps from './transformProps'; +import thumbnail from './images/thumbnail.png'; + +const metadata = new ChartMetadata({ + description: '', + name: t('Grouped Column Line Chart'), + thumbnail, + useLegacyApi: true, +}); + +export default class GroupedChart extends ChartPlugin { + constructor() { + super({ + loadChart: () => import('./GroupedChart'), + metadata, + transformProps, + }); + } +} \ No newline at end of file diff --git a/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/transformProps.js b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/transformProps.js new file mode 100644 index 000000000..c80df5d37 --- /dev/null +++ b/packages/superset-ui-legacy-plugin-grouped-column-line-chart/src/transformProps.js @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* eslint-disable sort-keys */ +export default function transformProps(chartProps) { + const { width, height, formData, queryData } = chartProps; + const { colorScheme, linkLength, normalized, globalOpacity, xAxisLabel, yAxisLabel } = formData; + + return { + width, + height, + data: queryData.data, + binCount: parseInt(linkLength, 10), + colorScheme, + normalized, + opacity: globalOpacity, + xAxisLabel, + yAxisLabel, + }; +} diff --git a/packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-grouped-column-line-chart/Stories.tsx b/packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-grouped-column-line-chart/Stories.tsx new file mode 100644 index 000000000..d94a13f1a --- /dev/null +++ b/packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-grouped-column-line-chart/Stories.tsx @@ -0,0 +1,27 @@ +/* eslint-disable no-magic-numbers */ +import React from 'react'; +import { SuperChart } from '@superset-ui/chart'; +import data from './data'; + +export default [ + { + renderStory: () => ( + + ), + storyName: 'Basic', + storyPath: 'legacy-|plugin-chart-grouped-chart|GroupedChartPlugin', + }, +]; diff --git a/packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-grouped-column-line-chart/data.js b/packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-grouped-column-line-chart/data.js new file mode 100644 index 000000000..4026dfcd6 --- /dev/null +++ b/packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-grouped-column-line-chart/data.js @@ -0,0 +1,48 @@ +/* eslint-disable sort-keys, no-magic-numbers */ +export default [ + { + key: 'Entrance exam', + renderas: 'bar', + values: [ + { x: 'A', y: 5.87}, + { x: 'B', y: 20.944}, + { x: 'C', y: 10.0}, + { x: 'D', y: 9.879}, + { x: 'E', y: 0.69}, + { x: 'F', y: 0.667}, + { x: 'G', y: 0.794}, + { x: 'H', y: 6.838}, + { x: 'I', y: 4.875} + ], + }, + { + key: 'National exam', + renderas: 'line', + values: [ + { x: 'A', y: 5.37}, + { x: 'B', y: 20.544}, + { x: 'C', y: 9.908}, + { x: 'D', y: 20.849}, + { x: 'E', y: 10.19}, + { x: 'F', y: 20.967}, + { x: 'G', y: 20.894}, + { x: 'H', y: 20.898}, + { x: 'I', y: 20.845} + ], + }, + { + key: 'Other exam', + renderas: 'line', + values: [ + { x: 'A', y: 10.1}, + { x: 'B', y: 10.944}, + { x: 'C', y: 10.308}, + { x: 'D', y: 10.899}, + { x: 'E', y: 10.919}, + { x: 'F', y: 10.967}, + { x: 'G', y: 10.894}, + { x: 'H', y: 10.898}, + { x: 'I', y: 10.845} + ], + } +]; diff --git a/packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-grouped-column-line-chart/index.js b/packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-grouped-column-line-chart/index.js new file mode 100644 index 000000000..a4053568c --- /dev/null +++ b/packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-grouped-column-line-chart/index.js @@ -0,0 +1,8 @@ +import GroupedChartPlugin from '../../../../superset-ui-legacy-plugin-grouped-column-line-chart'; +import Stories from './Stories'; + +new GroupedChartPlugin().configure({key: 'grouped_column_line_chart'}).register(); + +export default { + examples: [...Stories], +};