diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts index c63df51d1..ebcd7d6d0 100644 --- a/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts +++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts @@ -25,7 +25,7 @@ export const WORLD_HEALTH_CHARTS = [ { name: 'Most Populated Countries', viz: 'table' }, { name: "World's Population", viz: 'big_number' }, { name: 'Growth Rate', viz: 'line' }, - { name: 'Rural Breakdown', viz: 'sunburst' }, + { name: 'Rural Breakdown', viz: 'sunburst_v2' }, { name: "World's Pop Growth", viz: 'area' }, { name: 'Life Expectancy VS Rural %', viz: 'bubble' }, { name: 'Treemap', viz: 'treemap_v2' }, diff --git a/superset-frontend/cypress-base/cypress/e2e/explore/visualizations/sunburst.test.js b/superset-frontend/cypress-base/cypress/e2e/explore/visualizations/sunburst.test.js index 03090db9c..4d55d592c 100644 --- a/superset-frontend/cypress-base/cypress/e2e/explore/visualizations/sunburst.test.js +++ b/superset-frontend/cypress-base/cypress/e2e/explore/visualizations/sunburst.test.js @@ -18,17 +18,17 @@ */ describe('Visualization > Sunburst', () => { beforeEach(() => { - cy.intercept('POST', '/superset/explore_json/**').as('getJson'); + cy.intercept('POST', '/api/v1/chart/data**').as('chartData'); }); const SUNBURST_FORM_DATA = { datasource: '2__table', - viz_type: 'sunburst', + viz_type: 'sunburst_v2', slice_id: 47, granularity_sqla: 'year', time_grain_sqla: 'P1D', time_range: 'No filter', - groupby: ['region'], + columns: ['region'], metric: 'sum__SP_POP_TOTL', adhoc_filters: [], row_limit: 50000, @@ -37,32 +37,35 @@ describe('Visualization > Sunburst', () => { function verify(formData) { cy.visitChartByParams(formData); - cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' }); + cy.verifySliceSuccess({ waitAlias: '@chartData' }); } - it('should work without secondary metric', () => { + // requires the ability to render charts using SVG only for tests + it.skip('should work without secondary metric', () => { verify(SUNBURST_FORM_DATA); - // There should be 7 visible arcs + 1 hidden - cy.get('.chart-container svg g#arcs path').should('have.length', 8); + cy.get('.chart-container svg g path').should('have.length', 7); }); - it('should work with secondary metric', () => { + // requires the ability to render charts using SVG only for tests + it.skip('should work with secondary metric', () => { verify({ ...SUNBURST_FORM_DATA, secondary_metric: 'sum__SP_RUR_TOTL', }); - cy.get('.chart-container svg g#arcs path').should('have.length', 8); + cy.get('.chart-container svg g path').should('have.length', 7); }); - it('should work with multiple groupbys', () => { + // requires the ability to render charts using SVG only for tests + it.skip('should work with multiple columns', () => { verify({ ...SUNBURST_FORM_DATA, - groupby: ['region', 'country_name'], + columns: ['region', 'country_name'], }); - cy.get('.chart-container svg g#arcs path').should('have.length', 117); + cy.get('.chart-container svg g path').should('have.length', 221); }); - it('should work with filter', () => { + // requires the ability to render charts using SVG only for tests + it.skip('should work with filter', () => { verify({ ...SUNBURST_FORM_DATA, adhoc_filters: [ @@ -77,7 +80,7 @@ describe('Visualization > Sunburst', () => { }, ], }); - cy.get('.chart-container svg g#arcs path').should('have.length', 3); + cy.get('.chart-container svg g path').should('have.length', 2); }); it('should allow type to search color schemes', () => { diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 35f211eff..e4af28554 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -39,7 +39,6 @@ "@superset-ui/legacy-plugin-chart-rose": "file:./plugins/legacy-plugin-chart-rose", "@superset-ui/legacy-plugin-chart-sankey": "file:./plugins/legacy-plugin-chart-sankey", "@superset-ui/legacy-plugin-chart-sankey-loop": "file:./plugins/legacy-plugin-chart-sankey-loop", - "@superset-ui/legacy-plugin-chart-sunburst": "file:./plugins/legacy-plugin-chart-sunburst", "@superset-ui/legacy-plugin-chart-world-map": "file:./plugins/legacy-plugin-chart-world-map", "@superset-ui/legacy-preset-chart-deckgl": "file:./plugins/legacy-preset-chart-deckgl", "@superset-ui/legacy-preset-chart-nvd3": "file:./plugins/legacy-preset-chart-nvd3", @@ -18338,10 +18337,6 @@ "resolved": "plugins/legacy-plugin-chart-sankey-loop", "link": true }, - "node_modules/@superset-ui/legacy-plugin-chart-sunburst": { - "resolved": "plugins/legacy-plugin-chart-sunburst", - "link": true - }, "node_modules/@superset-ui/legacy-plugin-chart-world-map": { "resolved": "plugins/legacy-plugin-chart-world-map", "link": true @@ -62257,7 +62252,6 @@ "@superset-ui/legacy-plugin-chart-rose": "*", "@superset-ui/legacy-plugin-chart-sankey": "*", "@superset-ui/legacy-plugin-chart-sankey-loop": "*", - "@superset-ui/legacy-plugin-chart-sunburst": "*", "@superset-ui/legacy-plugin-chart-time-table": "*", "@superset-ui/legacy-plugin-chart-world-map": "*", "@superset-ui/legacy-preset-chart-deckgl": "*", @@ -63291,20 +63285,6 @@ "react": "^16.13.1" } }, - "plugins/legacy-plugin-chart-sunburst": { - "name": "@superset-ui/legacy-plugin-chart-sunburst", - "version": "0.18.25", - "license": "Apache-2.0", - "dependencies": { - "d3": "^3.5.17", - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "@superset-ui/chart-controls": "*", - "@superset-ui/core": "*", - "react": "^16.13.1" - } - }, "plugins/legacy-plugin-chart-time-table": { "name": "@superset-ui/legacy-plugin-chart-time-table", "version": "0.0.1", @@ -78157,13 +78137,6 @@ "prop-types": "^15.8.1" } }, - "@superset-ui/legacy-plugin-chart-sunburst": { - "version": "file:plugins/legacy-plugin-chart-sunburst", - "requires": { - "d3": "^3.5.17", - "prop-types": "^15.8.1" - } - }, "@superset-ui/legacy-plugin-chart-world-map": { "version": "file:plugins/legacy-plugin-chart-world-map", "requires": { diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 4aeb85c6e..4cbff6e5e 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -105,7 +105,6 @@ "@superset-ui/legacy-plugin-chart-rose": "file:./plugins/legacy-plugin-chart-rose", "@superset-ui/legacy-plugin-chart-sankey": "file:./plugins/legacy-plugin-chart-sankey", "@superset-ui/legacy-plugin-chart-sankey-loop": "file:./plugins/legacy-plugin-chart-sankey-loop", - "@superset-ui/legacy-plugin-chart-sunburst": "file:./plugins/legacy-plugin-chart-sunburst", "@superset-ui/legacy-plugin-chart-world-map": "file:./plugins/legacy-plugin-chart-world-map", "@superset-ui/legacy-preset-chart-deckgl": "file:./plugins/legacy-preset-chart-deckgl", "@superset-ui/legacy-preset-chart-nvd3": "file:./plugins/legacy-preset-chart-nvd3", diff --git a/superset-frontend/packages/superset-ui-core/test/chart/fixtures/formData.ts b/superset-frontend/packages/superset-ui-core/test/chart/fixtures/formData.ts index 9d926f461..88a78c601 100644 --- a/superset-frontend/packages/superset-ui-core/test/chart/fixtures/formData.ts +++ b/superset-frontend/packages/superset-ui-core/test/chart/fixtures/formData.ts @@ -56,13 +56,13 @@ export const wordCloudFormData = { export const sunburstFormData = { datasource: '2__table', - viz_type: 'sunburst', + viz_type: 'sunburst_v2', slice_id: 47, url_params: {}, granularity_sqla: 'year', time_grain_sqla: 'P1D', time_range: '2011-01-01 : 2011-01-01', - groupby: ['region', 'country_name'], + columns: ['region', 'country_name'], metric: 'sum__SP_POP_TOTL', secondary_metric: 'sum__SP_RUR_TOTL', adhoc_filters: [], diff --git a/superset-frontend/packages/superset-ui-demo/package.json b/superset-frontend/packages/superset-ui-demo/package.json index 883165a53..7c04c590a 100644 --- a/superset-frontend/packages/superset-ui-demo/package.json +++ b/superset-frontend/packages/superset-ui-demo/package.json @@ -80,7 +80,6 @@ "@superset-ui/legacy-plugin-chart-rose": "*", "@superset-ui/legacy-plugin-chart-sankey": "*", "@superset-ui/legacy-plugin-chart-sankey-loop": "*", - "@superset-ui/legacy-plugin-chart-sunburst": "*", "@superset-ui/legacy-plugin-chart-time-table": "*", "@superset-ui/legacy-plugin-chart-world-map": "*", "@superset-ui/legacy-preset-chart-deckgl": "*", diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/Stories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/Stories.tsx deleted file mode 100644 index 35b6388be..000000000 --- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/Stories.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 no-magic-numbers */ -import React from 'react'; -import { SuperChart } from '@superset-ui/core'; -import SunburstChartPlugin from '@superset-ui/legacy-plugin-chart-sunburst'; -import ResizableChartDemo from '../../../shared/components/ResizableChartDemo'; -import data from './data'; - -new SunburstChartPlugin().configure({ key: 'sunburst' }).register(); - -export default { - title: 'Legacy Chart Plugins/legacy-plugin-chart-sunburst', -}; - -export const basic = () => ( - -); - -export const resizable = () => ( - - {({ width, height }) => ( - - )} - -); diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/data.ts deleted file mode 100644 index 69df74de4..000000000 --- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sunburst/data.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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, no-magic-numbers */ -export default [ - ['East Asia & Pacific', 'China', 1344130000.0, 664363135.0], - ['South Asia', 'India', 1247446011.0, 857294797.0], - ['North America', 'United States', 311721632.0, 59414143.0], - ['East Asia & Pacific', 'Indonesia', 244808254.0, 120661092.0], - ['Latin America & Caribbean', 'Brazil', 200517584.0, 30833589.0], - ['South Asia', 'Pakistan', 173669648.0, 109399721.0], - ['Sub-Saharan Africa', 'Nigeria', 163770669.0, 91118725.0], - ['South Asia', 'Bangladesh', 153405612.0, 105504710.0], - ['Europe & Central Asia', 'Russian Federation', 142960868.0, 37552961.0], - ['East Asia & Pacific', 'Japan', 127817277.0, 11186568.0], -]; diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProviderStories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProviderStories.tsx index ddf21df79..1abc9ee65 100644 --- a/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProviderStories.tsx +++ b/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProviderStories.tsx @@ -27,7 +27,6 @@ import { } from '@superset-ui/core'; import { BigNumberChartPlugin } from '@superset-ui/plugin-chart-echarts'; import LegacySankeyPlugin from '@superset-ui/legacy-plugin-chart-sankey'; -import LegacySunburstPlugin from '@superset-ui/legacy-plugin-chart-sunburst'; import { WordCloudChartPlugin } from '@superset-ui/plugin-chart-word-cloud'; import { @@ -50,8 +49,6 @@ new BigNumberChartPlugin().configure({ key: BIG_NUMBER }).register(); // eslint-disable-next-line new LegacySankeyPlugin().configure({ key: SANKEY }).register(); // eslint-disable-next-line -new LegacySunburstPlugin().configure({ key: SUNBURST }).register(); -// eslint-disable-next-line new WordCloudChartPlugin().configure({ key: WORD_CLOUD }).register(); const VIS_TYPES = [BIG_NUMBER, SANKEY, SUNBURST, WORD_CLOUD, WORD_CLOUD_LEGACY]; diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/CHANGELOG.md b/superset-frontend/plugins/legacy-plugin-chart-sunburst/CHANGELOG.md deleted file mode 100644 index 01a75d202..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/CHANGELOG.md +++ /dev/null @@ -1,35 +0,0 @@ - - -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# [0.18.0](https://github.com/apache-superset/superset-ui/compare/v0.17.87...v0.18.0) (2021-08-30) - -**Note:** Version bump only for package @superset-ui/legacy-plugin-chart-sunburst - - - - - -## [0.17.61](https://github.com/apache-superset/superset-ui/compare/v0.17.60...v0.17.61) (2021-07-02) - -**Note:** Version bump only for package @superset-ui/legacy-plugin-chart-sunburst diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/README.md b/superset-frontend/plugins/legacy-plugin-chart-sunburst/README.md deleted file mode 100644 index 20bfb8a48..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/README.md +++ /dev/null @@ -1,52 +0,0 @@ - - -## @superset-ui/legacy-plugin-chart-sunburst - -[![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-sunburst.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-sunburst) -[![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-plugin-chart-sunburst&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-plugin-chart-sunburst) - -This plugin provides Sunburst 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 SunburstChartPlugin from '@superset-ui/legacy-plugin-chart-sunburst'; - -new SunburstChartPlugin().configure({ key: 'sunburst' }).register(); -``` - -Then use it via `SuperChart`. See -[storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-sunburst) -for more details. - -```js - -``` diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/package.json b/superset-frontend/plugins/legacy-plugin-chart-sunburst/package.json deleted file mode 100644 index fd2a5405a..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@superset-ui/legacy-plugin-chart-sunburst", - "version": "0.18.25", - "description": "Superset Legacy Chart - Sunburst", - "keywords": [ - "superset" - ], - "homepage": "https://github.com/apache/superset/tree/master/superset-frontend/plugins/legacy-plugin-chart-sunburst#readme", - "bugs": { - "url": "https://github.com/apache/superset/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/apache/superset.git", - "directory": "superset-frontend/plugins/legacy-plugin-chart-sunburst" - }, - "license": "Apache-2.0", - "author": "Superset", - "main": "lib/index.js", - "module": "esm/index.js", - "files": [ - "esm", - "lib" - ], - "dependencies": { - "d3": "^3.5.17", - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "@superset-ui/chart-controls": "*", - "@superset-ui/core": "*", - "react": "^16.13.1" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/ReactSunburst.jsx b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/ReactSunburst.jsx deleted file mode 100644 index 10e959285..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/ReactSunburst.jsx +++ /dev/null @@ -1,66 +0,0 @@ -/** - * 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 React from 'react'; -import { reactify, styled } from '@superset-ui/core'; -import Component from './Sunburst'; - -const ReactComponent = reactify(Component); - -const Sunburst = ({ className, ...otherProps }) => ( -
- -
-); - -export default styled(Sunburst)` - ${({ theme }) => ` - .superset-legacy-chart-sunburst text { - text-rendering: optimizeLegibility; - } - .superset-legacy-chart-sunburst path { - stroke: ${theme.colors.grayscale.light2}; - stroke-width: 0.5px; - } - .superset-legacy-chart-sunburst .center-label { - text-anchor: middle; - fill: ${theme.colors.grayscale.dark1}; - pointer-events: none; - } - .superset-legacy-chart-sunburst .path-abs-percent { - font-size: ${theme.typography.sizes.m}px; - font-weight: ${theme.typography.weights.bold}; - } - .superset-legacy-chart-sunburst .path-cond-percent { - font-size: ${theme.typography.sizes.s}px; - } - .superset-legacy-chart-sunburst .path-metrics { - color: ${theme.colors.grayscale.base}; - } - .superset-legacy-chart-sunburst .path-ratio { - color: ${theme.colors.grayscale.base}; - } - - .superset-legacy-chart-sunburst .breadcrumbs text { - font-weight: ${theme.typography.weights.bold}; - font-size: ${theme.typography.sizes.m}px; - text-anchor: middle; - fill: ${theme.colors.grayscale.dark1}; - } - `} -`; diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/Sunburst.js b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/Sunburst.js deleted file mode 100644 index 138788495..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/Sunburst.js +++ /dev/null @@ -1,531 +0,0 @@ -/** - * 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 no-param-reassign, react/sort-prop-types */ -import d3 from 'd3'; -import PropTypes from 'prop-types'; -import { - getNumberFormatter, - NumberFormats, - CategoricalColorNamespace, - getSequentialSchemeRegistry, - t, -} from '@superset-ui/core'; -import wrapSvgText from './utils/wrapSvgText'; - -const propTypes = { - // Each row is an array of [hierarchy-lvl1, hierarchy-lvl2, metric1, metric2] - // hierarchy-lvls are string. metrics are number - data: PropTypes.arrayOf(PropTypes.array), - width: PropTypes.number, - height: PropTypes.number, - colorScheme: PropTypes.string, - linearColorScheme: PropTypes.string, - numberFormat: PropTypes.string, - metrics: PropTypes.arrayOf( - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.object, // The metric object - ]), - ), -}; - -function metricLabel(metric) { - return typeof metric === 'string' || metric instanceof String - ? metric - : metric.label; -} - -// Given a node in a partition layout, return an array of all of its ancestor -// nodes, highest first, but excluding the root. -function getAncestors(node) { - const path = []; - let current = node; - while (current.parent) { - path.unshift(current); - current = current.parent; - } - - return path; -} - -function buildHierarchy(rows) { - const root = { - name: 'root', - children: [], - }; - - // each record [groupby1val, groupby2val, ( or 0)n, m1, m2] - rows.forEach(row => { - const m1 = Number(row[row.length - 2]); - const m2 = Number(row[row.length - 1]); - const levels = row.slice(0, -2); - if (Number.isNaN(m1)) { - // e.g. if this is a header row - return; - } - let currentNode = root; - for (let level = 0; level < levels.length; level += 1) { - const children = currentNode.children || []; - const node = levels[level]; - const nodeName = node ? node.toString() : t('N/A'); - // If the next node has the name '0', it will - const isLeafNode = level >= levels.length - 1 || levels[level + 1] === 0; - let childNode; - - if (!isLeafNode) { - childNode = children.find( - child => child.name === nodeName && child.level === level, - ); - - if (!childNode) { - childNode = { - name: nodeName, - children: [], - level, - }; - children.push(childNode); - } - currentNode = childNode; - } else if (nodeName !== 0) { - // Reached the end of the sequence; create a leaf node. - childNode = { - name: nodeName, - m1, - m2, - }; - children.push(childNode); - } - } - }); - - function recurse(node) { - if (node.children) { - let sums; - let m1 = 0; - let m2 = 0; - for (let i = 0; i < node.children.length; i += 1) { - sums = recurse(node.children[i]); - m1 += sums[0]; - m2 += sums[1]; - } - node.m1 = m1; - node.m2 = m2; - } - - return [node.m1, node.m2]; - } - - recurse(root); - - return root; -} - -function getResponsiveContainerClass(width) { - if (width > 500) { - return 'l'; - } - - if (width > 200 && width <= 500) { - return 'm'; - } - - return 's'; -} - -function getYOffset(width) { - if (width > 500) { - return ['0', '20', '40', '60']; - } - - if (width > 200 && width <= 500) { - return ['0', '15', '30', '45']; - } - - return ['0', '10', '20', '30']; -} - -// Modified from http://bl.ocks.org/kerryrodden/7090426 -function Sunburst(element, props) { - const container = d3.select(element); - const { - data, - width, - height, - colorScheme, - linearColorScheme, - metrics, - numberFormat, - sliceId, - } = props; - const responsiveClass = getResponsiveContainerClass(width); - const isSmallWidth = responsiveClass === 's'; - container.attr('class', `superset-legacy-chart-sunburst ${responsiveClass}`); - // vars with shared scope within this function - const margin = { top: 10, right: 5, bottom: 10, left: 5 }; - const containerWidth = width; - const containerHeight = height; - const breadcrumbHeight = containerHeight * 0.085; - const visWidth = containerWidth - margin.left - margin.right; - const visHeight = - containerHeight - margin.top - margin.bottom - breadcrumbHeight; - const radius = Math.min(visWidth, visHeight) / 2; - - let colorByCategory = true; // color by category if primary/secondary metrics match - let maxBreadcrumbs; - let breadcrumbDims; // set based on data - let totalSize; // total size of all segments; set after loading the data. - let breadcrumbs; - let vis; - let arcs; - let gMiddleText; // dom handles - - const categoricalColorScale = CategoricalColorNamespace.getScale(colorScheme); - let linearColorScale; - - // Helper + path gen functions - const partition = d3.layout - .partition() - .size([2 * Math.PI, radius * radius]) - .value(d => d.m1); - - const arc = d3.svg - .arc() - .startAngle(d => d.x) - .endAngle(d => d.x + d.dx) - .innerRadius(d => Math.sqrt(d.y)) - .outerRadius(d => Math.sqrt(d.y + d.dy)); - - const formatNum = getNumberFormatter( - numberFormat || NumberFormats.SI_3_DIGIT, - ); - const formatPerc = getNumberFormatter(NumberFormats.PERCENT_3_POINT); - - container.select('svg').remove(); - - const svg = container - .append('svg:svg') - .attr('width', containerWidth) - .attr('height', containerHeight); - - function createBreadcrumbs(firstRowData) { - // -2 bc row contains 2x metrics, +extra for %label and buffer - maxBreadcrumbs = firstRowData.length - 2 + 1; - breadcrumbDims = { - width: visWidth / maxBreadcrumbs, - height: breadcrumbHeight * 0.8, // more margin - spacing: 3, - tipTailWidth: 10, - }; - - breadcrumbs = svg - .append('svg:g') - .attr('class', 'breadcrumbs') - .attr('transform', `translate(${margin.left},${margin.top})`); - - breadcrumbs.append('svg:text').attr('class', 'end-label'); - } - - // Generate a string that describes the points of a breadcrumb polygon. - function breadcrumbPoints(d, i) { - const points = []; - if (isSmallWidth) { - points.push('0,0'); - points.push(`${width},0`); - points.push(`${width},0`); - points.push(`${width},${breadcrumbDims.height}`); - points.push(`0,${breadcrumbDims.height}`); - if (i > 0) { - // Leftmost breadcrumb; don't include 6th vertex. - // points.push(`${breadcrumbDims.tipTailWidth},${breadcrumbDims.height / 2}`); - } - } else { - points.push('0,0'); - points.push(`${breadcrumbDims.width},0`); - points.push( - `${breadcrumbDims.width + breadcrumbDims.tipTailWidth},${ - breadcrumbDims.height / 2 - }`, - ); - points.push(`${breadcrumbDims.width},${breadcrumbDims.height}`); - points.push(`0,${breadcrumbDims.height}`); - if (i > 0) { - // Leftmost breadcrumb; don't include 6th vertex. - points.push( - `${breadcrumbDims.tipTailWidth},${breadcrumbDims.height / 2}`, - ); - } - } - - return points.join(' '); - } - - function updateBreadcrumbs(sequenceArray, percentageString) { - const breadcrumbWidth = isSmallWidth ? width : breadcrumbDims.width; - const g = breadcrumbs - .selectAll('g') - .data(sequenceArray, d => d.name + d.depth); - - // Add breadcrumb and label for entering nodes. - const entering = g.enter().append('svg:g'); - - entering - .append('svg:polygon') - .attr('points', breadcrumbPoints) - .style('fill', d => - colorByCategory - ? categoricalColorScale(d.name, sliceId) - : linearColorScale(d.m2 / d.m1), - ); - - entering - .append('svg:text') - .attr('x', (breadcrumbWidth + breadcrumbDims.tipTailWidth) / 2) - .attr('y', breadcrumbDims.height / 4) - .attr('dy', '0.35em') - .style('fill', d => { - // Make text white or black based on the lightness of the background - const col = d3.hsl( - colorByCategory - ? categoricalColorScale(d.name, sliceId) - : linearColorScale(d.m2 / d.m1), - ); - - return col.l < 0.5 ? 'white' : 'black'; - }) - .attr('class', 'step-label') - .text(d => d.name.replace(/_/g, ' ')) - .call(wrapSvgText, breadcrumbWidth, breadcrumbDims.height / 2); - - // Set position for entering and updating nodes. - g.attr('transform', (d, i) => { - if (isSmallWidth) { - return `translate(0, ${ - i * (breadcrumbDims.height + breadcrumbDims.spacing) - })`; - } - return `translate(${ - i * (breadcrumbDims.width + breadcrumbDims.spacing) - }, 0)`; - }); - - // Remove exiting nodes. - g.exit().remove(); - - // Now move and update the percentage at the end. - breadcrumbs - .select('.end-label') - .attr('x', () => { - if (isSmallWidth) { - return (breadcrumbWidth + breadcrumbDims.tipTailWidth) / 2; - } - - return ( - (sequenceArray.length + 0.5) * - (breadcrumbDims.width + breadcrumbDims.spacing) - ); - }) - .attr('y', () => { - if (isSmallWidth) { - return (sequenceArray.length + 1) * breadcrumbDims.height; - } - - return breadcrumbDims.height / 2; - }) - .attr('dy', '0.35em') - .text(percentageString); - - // Make the breadcrumb trail visible, if it's hidden. - breadcrumbs.style('visibility', null); - } - - // Fade all but the current sequence, and show it in the breadcrumb trail. - function mouseenter(d) { - const sequenceArray = getAncestors(d); - const parentOfD = sequenceArray[sequenceArray.length - 2] || null; - - const absolutePercentage = (d.m1 / totalSize).toPrecision(3); - const conditionalPercentage = parentOfD - ? (d.m1 / parentOfD.m1).toPrecision(3) - : null; - - const absolutePercString = formatPerc(absolutePercentage); - const conditionalPercString = parentOfD - ? formatPerc(conditionalPercentage) - : ''; - - // 3 levels of text if inner-most level, 4 otherwise - const yOffsets = getYOffset(width); - let offsetIndex = 0; - - // If metrics match, assume we are coloring by category - const metricsMatch = Math.abs(d.m1 - d.m2) < 0.00001; - - gMiddleText.selectAll('*').remove(); - - offsetIndex += 1; - gMiddleText - .append('text') - .attr('class', 'path-abs-percent') - .attr('y', yOffsets[offsetIndex]) - // eslint-disable-next-line prefer-template - .text(absolutePercString + ' ' + t('of total')); - - const OF_PARENT_TEXT = t('of parent'); - - if (conditionalPercString) { - offsetIndex += 1; - gMiddleText - .append('text') - .attr('class', 'path-cond-percent') - .attr('y', yOffsets[offsetIndex]) - .text(`${conditionalPercString} ${OF_PARENT_TEXT}`); - } - - offsetIndex += 1; - gMiddleText - .append('text') - .attr('class', 'path-metrics') - .attr('y', yOffsets[offsetIndex]) - .text( - `${metricLabel(metrics[0])}: ${formatNum(d.m1)}${ - metricsMatch ? '' : `, ${metricLabel(metrics[1])}: ${formatNum(d.m2)}` - }`, - ); - - offsetIndex += 1; - gMiddleText - .append('text') - .attr('class', 'path-ratio') - .attr('y', yOffsets[offsetIndex]) - .text( - metricsMatch - ? '' - : `${metricLabel(metrics[1])}/${metricLabel( - metrics[0], - )}: ${formatPerc(d.m2 / d.m1)}`, - ); - - // Reset and fade all the segments. - arcs - .selectAll('path') - .style('stroke-width', null) - .style('stroke', null) - .style('opacity', 0.3); - - // Then highlight only those that are an ancestor of the current segment. - arcs - .selectAll('path') - .filter(node => sequenceArray.includes(node)) - .style('opacity', 1) - .style('stroke', '#aaa'); - - updateBreadcrumbs(sequenceArray, absolutePercString); - } - - // Restore everything to full opacity when moving off the visualization. - function mouseleave() { - // Hide the breadcrumb trail - breadcrumbs.style('visibility', 'hidden'); - - gMiddleText.selectAll('*').remove(); - - // Deactivate all segments during transition. - arcs.selectAll('path').on('mouseenter', null); - - // Transition each segment to full opacity and then reactivate it. - arcs - .selectAll('path') - .transition() - .duration(200) - .style('opacity', 1) - .style('stroke', null) - .style('stroke-width', null) - .each('end', function end() { - d3.select(this).on('mouseenter', mouseenter); - }); - } - - // Main function to draw and set up the visualization, once we have the data. - function createVisualization(rows) { - const root = buildHierarchy(rows); - maxBreadcrumbs = rows[0].length - 2; - vis = svg - .append('svg:g') - .attr('class', 'sunburst-vis') - .attr( - 'transform', - 'translate(' + - `${margin.left + visWidth / 2},` + - `${ - margin.top + - (isSmallWidth - ? breadcrumbHeight * maxBreadcrumbs - : breadcrumbHeight) + - visHeight / 2 - }` + - ')', - ) - .on('mouseleave', mouseleave); - - arcs = vis.append('svg:g').attr('id', 'arcs'); - - gMiddleText = vis.append('svg:g').attr('class', 'center-label'); - - // Bounding circle underneath the sunburst, to make it easier to detect - // when the mouse leaves the parent g. - arcs.append('svg:circle').attr('r', radius).style('opacity', 0); - - // For efficiency, filter nodes to keep only those large enough to see. - const nodes = partition.nodes(root).filter(d => d.dx > 0.005); // 0.005 radians = 0.29 degrees - - if (metrics[0] !== metrics[1] && metrics[1]) { - colorByCategory = false; - const ext = d3.extent(nodes, d => d.m2 / d.m1); - linearColorScale = getSequentialSchemeRegistry() - .get(linearColorScheme) - .createLinearScale(ext); - } - - arcs - .selectAll('path') - .data(nodes) - .enter() - .append('svg:path') - .attr('display', d => (d.depth ? null : 'none')) - .attr('d', arc) - .attr('fill-rule', 'evenodd') - .style('fill', d => - colorByCategory - ? categoricalColorScale(d.name, sliceId) - : linearColorScale(d.m2 / d.m1), - ) - .style('opacity', 1) - .on('mouseenter', mouseenter); - - // Get total size of the tree = value of root node from partition. - totalSize = root.value; - } - createBreadcrumbs(data[0]); - createVisualization(data); -} - -Sunburst.displayName = 'Sunburst'; -Sunburst.propTypes = propTypes; - -export default Sunburst; diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/controlPanel.ts b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/controlPanel.ts deleted file mode 100644 index 32b56fb9e..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/controlPanel.ts +++ /dev/null @@ -1,108 +0,0 @@ -/** - * 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/core'; -import { - ControlPanelConfig, - ControlPanelsContainerProps, - getStandardizedControls, - sections, -} from '@superset-ui/chart-controls'; - -const config: ControlPanelConfig = { - controlPanelSections: [ - sections.legacyRegularTime, - { - label: t('Query'), - expanded: true, - controlSetRows: [ - ['groupby'], - ['metric'], - ['secondary_metric'], - ['adhoc_filters'], - ['row_limit'], - [ - { - name: 'sort_by_metric', - config: { - type: 'CheckboxControl', - label: t('Sort by metric'), - description: t( - 'Whether to sort results by the selected metric in descending order.', - ), - }, - }, - ], - ], - }, - { - label: t('Chart Options'), - expanded: true, - controlSetRows: [['color_scheme'], ['linear_color_scheme']], - }, - ], - controlOverrides: { - metric: { - label: t('Primary Metric'), - description: t( - 'The primary metric is used to define the arc segment sizes', - ), - }, - secondary_metric: { - label: t('Secondary Metric'), - default: null, - description: t( - '[optional] this secondary metric is used to ' + - 'define the color as a ratio against the primary metric. ' + - 'When omitted, the color is categorical and based on labels', - ), - }, - color_scheme: { - description: t( - 'When only a primary metric is provided, a categorical color scale is used.', - ), - visibility: ({ controls }: ControlPanelsContainerProps) => - Boolean( - !controls?.secondary_metric?.value || - controls?.secondary_metric?.value === controls?.metric.value, - ), - }, - linear_color_scheme: { - description: t( - 'When a secondary metric is provided, a linear color scale is used.', - ), - visibility: ({ controls }: ControlPanelsContainerProps) => - Boolean( - controls?.secondary_metric?.value && - controls?.secondary_metric?.value !== controls?.metric.value, - ), - }, - groupby: { - label: t('Hierarchy'), - description: t('This defines the level of the hierarchy'), - }, - }, - formDataOverrides: formData => ({ - ...formData, - groupby: getStandardizedControls().popAllColumns(), - metric: getStandardizedControls().shiftMetric(), - secondary_metric: getStandardizedControls().shiftMetric(), - }), -}; - -export default config; diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/example.png b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/example.png deleted file mode 100644 index 003d00e96..000000000 Binary files a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/example.png and /dev/null differ diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/thumbnail.png b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/thumbnail.png deleted file mode 100644 index 46f8262b8..000000000 Binary files a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/thumbnail.png and /dev/null differ diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/thumbnailLarge.png b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/thumbnailLarge.png deleted file mode 100644 index 6c4706bf7..000000000 Binary files a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/images/thumbnailLarge.png and /dev/null differ diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/index.js b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/index.js deleted file mode 100644 index c3ea740e2..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/index.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * 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, ChartMetadata, ChartPlugin } from '@superset-ui/core'; -import transformProps from './transformProps'; -import thumbnail from './images/thumbnail.png'; -import example from './images/example.png'; -import controlPanel from './controlPanel'; - -const metadata = new ChartMetadata({ - category: t('Part of a Whole'), - credits: ['https://bl.ocks.org/kerryrodden/7090426'], - description: t( - 'Uses circles to visualize the flow of data through different stages of a system. Hover over individual paths in the visualization to understand the stages a value took. Useful for multi-stage, multi-group visualizing funnels and pipelines.', - ), - exampleGallery: [{ url: example }], - name: t('Sunburst Chart'), - tags: [t('Aesthetic'), t('Legacy'), t('Multi-Levels'), t('Proportional')], - thumbnail, - useLegacyApi: true, -}); - -export default class SunburstChartPlugin extends ChartPlugin { - constructor() { - super({ - loadChart: () => import('./ReactSunburst'), - metadata, - transformProps, - controlPanel, - }); - } -} diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/transformProps.js b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/transformProps.js deleted file mode 100644 index 92c4d99f0..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/transformProps.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * 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. - */ -export default function transformProps(chartProps) { - const { width, height, formData, queriesData, datasource } = chartProps; - const { colorScheme, linearColorScheme, metric, secondaryMetric, sliceId } = - formData; - - const returnProps = { - width, - height, - data: queriesData[0].data, - colorScheme, - linearColorScheme, - metrics: [metric, secondaryMetric], - sliceId, - }; - - if (datasource && datasource.metrics) { - const metricWithFormat = datasource.metrics.find( - ({ metric_name: metricName, d3format }) => - metricName === formData.metric && d3format, - ); - if (metricWithFormat) { - Object.assign(returnProps, { numberFormat: metricWithFormat.d3format }); - } - } - - return returnProps; -} diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/utils/wrapSvgText.js b/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/utils/wrapSvgText.js deleted file mode 100644 index 12cdead8d..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/src/utils/wrapSvgText.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -/* - Utility function that takes a d3 svg:text selection and a max width, and splits the - text's text across multiple tspan lines such that any given line does not exceed max width - - If text does not span multiple lines AND adjustedY is passed, - will set the text to the passed val -*/ -import d3 from 'd3'; - -export default function wrapSvgText(text, width, adjustedY) { - const lineHeight = 1; - // ems - text.each(function each() { - const d3Text = d3.select(this); - const words = d3Text.text().split(/\s+/); - let line = []; - let lineNumber = 0; - const x = d3Text.attr('x'); - const y = d3Text.attr('y'); - const dy = parseFloat(d3Text.attr('dy')); - let tspan = d3Text - .text(null) - .append('tspan') - .attr('x', x) - .attr('y', y) - .attr('dy', `${dy}em`); - - let didWrap = false; - words.forEach(word => { - line.push(word); - tspan.text(line.join(' ')); - if (tspan.node().getComputedTextLength() > width) { - lineNumber += 1; - line.pop(); - // remove word that pushes over the limit - tspan.text(line.join(' ')); - line = [word]; - tspan = d3Text - .append('tspan') - .attr('x', x) - .attr('y', y) - .attr('dy', `${lineNumber * lineHeight + dy}em`) - .text(word); - didWrap = true; - } - }); - - if (!didWrap && typeof adjustedY !== 'undefined') { - tspan.attr('y', adjustedY); - } - }); -} diff --git a/superset-frontend/plugins/legacy-plugin-chart-sunburst/tsconfig.json b/superset-frontend/plugins/legacy-plugin-chart-sunburst/tsconfig.json deleted file mode 100644 index b6bfaa2d9..000000000 --- a/superset-frontend/plugins/legacy-plugin-chart-sunburst/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "declarationDir": "lib", - "outDir": "lib", - "rootDir": "src" - }, - "exclude": [ - "lib", - "test" - ], - "extends": "../../tsconfig.json", - "include": [ - "src/**/*", - "types/**/*", - "../../types/**/*" - ], - "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } - ] -} diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/index.ts index 420870780..43309d5d2 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/index.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/index.ts @@ -43,7 +43,7 @@ export default class EchartsSunburstChartPlugin extends EchartsChartPlugin { 'Uses circles to visualize the flow of data through different stages of a system. Hover over individual paths in the visualization to understand the stages a value took. Useful for multi-stage, multi-group visualizing funnels and pipelines.', ), exampleGallery: [{ url: example1 }, { url: example2 }], - name: t('Sunburst Chart v2'), + name: t('Sunburst Chart'), tags: [ t('ECharts'), t('Aesthetic'), diff --git a/superset-frontend/spec/fixtures/mockSliceEntities.js b/superset-frontend/spec/fixtures/mockSliceEntities.js index 73e96ae87..2737d35d0 100644 --- a/superset-frontend/spec/fixtures/mockSliceEntities.js +++ b/superset-frontend/spec/fixtures/mockSliceEntities.js @@ -149,7 +149,7 @@ export const sliceEntitiesForDashboard = { slice_url: '/explore/?form_data=%7B%22slice_id%22%3A%20133%7D', slice_name: 'Rural Breakdown', form_data: {}, - viz_type: 'sunburst', + viz_type: 'sunburst_v2', datasource: '2__table', description: null, description_markeddown: '', diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx b/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx index add9bb973..2d7b5c05b 100644 --- a/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx @@ -37,7 +37,7 @@ jest.mock('src/components/Dropdown', () => { }; }); -const createProps = (viz_type = 'sunburst') => +const createProps = (viz_type = 'sunburst_v2') => ({ addDangerToast: jest.fn(), addSuccessToast: jest.fn(), @@ -59,7 +59,9 @@ const createProps = (viz_type = 'sunburst') => adhoc_filters: [], color_scheme: 'supersetColors', datasource: '58__table', - groupby: ['product_category', 'clinical_stage'], + ...(viz_type === 'sunburst_v2' + ? { columns: ['product_category', 'clinical_stage'] } + : { groupby: ['product_category', 'clinical_stage'] }), linear_color_scheme: 'schemeYlOrBr', metric: 'count', queryFields: { @@ -93,7 +95,7 @@ const createProps = (viz_type = 'sunburst') => chartStatus: 'rendered', showControls: true, supersetCanShare: true, - formData: { slice_id: 1, datasource: '58__table', viz_type: 'sunburst' }, + formData: { slice_id: 1, datasource: '58__table', viz_type: 'sunburst_v2' }, exploreUrl: '/explore', } as SliceHeaderControlsProps); diff --git a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx index 2d1437651..8934ca9cf 100644 --- a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx +++ b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx @@ -93,7 +93,6 @@ const DEFAULT_ORDER = [ 'deck_screengrid', 'treemap_v2', 'box_plot', - 'sunburst', 'sankey', 'word_cloud', 'mapbox', diff --git a/superset-frontend/src/visualizations/presets/MainPreset.js b/superset-frontend/src/visualizations/presets/MainPreset.js index f37a9155e..4e25ef018 100644 --- a/superset-frontend/src/visualizations/presets/MainPreset.js +++ b/superset-frontend/src/visualizations/presets/MainPreset.js @@ -30,7 +30,6 @@ import ParallelCoordinatesChartPlugin from '@superset-ui/legacy-plugin-chart-par import PartitionChartPlugin from '@superset-ui/legacy-plugin-chart-partition'; import RoseChartPlugin from '@superset-ui/legacy-plugin-chart-rose'; import SankeyChartPlugin from '@superset-ui/legacy-plugin-chart-sankey'; -import SunburstChartPlugin from '@superset-ui/legacy-plugin-chart-sunburst'; import TableChartPlugin from '@superset-ui/plugin-chart-table'; import { WordCloudChartPlugin } from '@superset-ui/plugin-chart-word-cloud'; import WorldMapChartPlugin from '@superset-ui/legacy-plugin-chart-world-map'; @@ -127,7 +126,6 @@ export default class MainPreset extends Preset { new PivotTableChartPluginV2().configure({ key: 'pivot_table_v2' }), new RoseChartPlugin().configure({ key: 'rose' }), new SankeyChartPlugin().configure({ key: 'sankey' }), - new SunburstChartPlugin().configure({ key: 'sunburst' }), new TableChartPlugin().configure({ key: 'table' }), new TimePivotChartPlugin().configure({ key: 'time_pivot' }), new TimeTableChartPlugin().configure({ key: 'time_table' }), diff --git a/superset/examples/configs/charts/Vaccine_Candidates_per_Country__Stage.yaml b/superset/examples/configs/charts/Vaccine_Candidates_per_Country__Stage.yaml index 81c54e69e..ea9d4c67e 100644 --- a/superset/examples/configs/charts/Vaccine_Candidates_per_Country__Stage.yaml +++ b/superset/examples/configs/charts/Vaccine_Candidates_per_Country__Stage.yaml @@ -15,14 +15,14 @@ # specific language governing permissions and limitations # under the License. slice_name: Vaccine Candidates per Country & Stage -viz_type: sunburst +viz_type: sunburst_v2 params: adhoc_filters: [] color_scheme: supersetColors datasource: 69__table - groupby: - - product_category - - clinical_stage + columns: + - product_category + - clinical_stage linear_color_scheme: schemeYlOrBr metric: count queryFields: @@ -33,7 +33,7 @@ params: slice_id: 3964 time_range: No filter url_params: {} - viz_type: sunburst + viz_type: sunburst_v2 cache_timeout: null uuid: f69c556f-15fe-4a82-a8bb-69d5b6954123 version: 1.0.0 diff --git a/superset/examples/supported_charts_dashboard.py b/superset/examples/supported_charts_dashboard.py index 7354b369b..926750ffb 100644 --- a/superset/examples/supported_charts_dashboard.py +++ b/superset/examples/supported_charts_dashboard.py @@ -397,12 +397,12 @@ def create_slices(tbl: SqlaTable) -> list[Slice]: Slice( **slice_kwargs, slice_name="Sunburst Chart", - viz_type="sunburst", + viz_type="sunburst_v2", params=get_slice_json( defaults, - viz_type="sunburst", + viz_type="sunburst_v2", metric="sum__num", - groupby=["gender", "state"], + columns=["gender", "state"], ), ), Slice( diff --git a/superset/examples/world_bank.py b/superset/examples/world_bank.py index 1541e3e47..5e895fd78 100644 --- a/superset/examples/world_bank.py +++ b/superset/examples/world_bank.py @@ -266,13 +266,13 @@ def create_slices(tbl: BaseDatasource) -> list[Slice]: ), Slice( slice_name="Rural Breakdown", - viz_type="sunburst", + viz_type="sunburst_v2", datasource_type=DatasourceType.TABLE, datasource_id=tbl.id, params=get_slice_json( defaults, - viz_type="sunburst", - groupby=["region", "country_name"], + viz_type="sunburst_v2", + columns=["region", "country_name"], since="2011-01-01", until="2011-01-02", metric=metric, diff --git a/superset/migrations/versions/2024-01-18_14-41_a32e0c4d8646_migrate_sunburst_chart.py b/superset/migrations/versions/2024-01-18_14-41_a32e0c4d8646_migrate_sunburst_chart.py new file mode 100644 index 000000000..10644e407 --- /dev/null +++ b/superset/migrations/versions/2024-01-18_14-41_a32e0c4d8646_migrate_sunburst_chart.py @@ -0,0 +1,44 @@ +# 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. +"""migrate-sunburst-chart + +Revision ID: a32e0c4d8646 +Revises: 59a1450b3c10 +Create Date: 2023-12-22 14:41:43.638321 + +""" + +# revision identifiers, used by Alembic. +revision = "a32e0c4d8646" +down_revision = "59a1450b3c10" + +from alembic import op + +from superset import db +from superset.migrations.shared.migrate_viz import MigrateSunburst + + +def upgrade(): + bind = op.get_bind() + session = db.Session(bind=bind) + MigrateSunburst.upgrade(session) + + +def downgrade(): + bind = op.get_bind() + session = db.Session(bind=bind) + MigrateSunburst.downgrade(session) diff --git a/superset/viz.py b/superset/viz.py index 8ba785ddc..5738fabc9 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -1352,55 +1352,6 @@ class DistributionBarViz(BaseViz): return chart_data -class SunburstViz(BaseViz): - - """A multi level sunburst chart""" - - viz_type = "sunburst" - verbose_name = _("Sunburst") - is_timeseries = False - credits = ( - "Kerry Rodden " - '@bl.ocks.org' - ) - - @deprecated(deprecated_in="3.0") - def get_data(self, df: pd.DataFrame) -> VizData: - if df.empty: - return None - form_data = copy.deepcopy(self.form_data) - cols = get_column_names(form_data.get("groupby")) - cols.extend(["m1", "m2"]) - metric = utils.get_metric_name(form_data["metric"]) - secondary_metric = ( - utils.get_metric_name(form_data["secondary_metric"]) - if form_data.get("secondary_metric") - else None - ) - if metric == secondary_metric or secondary_metric is None: - df.rename(columns={df.columns[-1]: "m1"}, inplace=True) - df["m2"] = df["m1"] - else: - df.rename(columns={df.columns[-2]: "m1"}, inplace=True) - df.rename(columns={df.columns[-1]: "m2"}, inplace=True) - - # Re-order the columns as the query result set column ordering may differ from - # that listed in the hierarchy. - df = df[cols] - return df.to_numpy().tolist() - - @deprecated(deprecated_in="3.0") - def query_obj(self) -> QueryObjectDict: - query_obj = super().query_obj() - query_obj["metrics"] = [self.form_data["metric"]] - secondary_metric = self.form_data.get("secondary_metric") - if secondary_metric and secondary_metric != self.form_data["metric"]: - query_obj["metrics"].append(secondary_metric) - if self.form_data.get("sort_by_metric", False): - query_obj["orderby"] = [(query_obj["metrics"][0], False)] - return query_obj - - class SankeyViz(BaseViz): """A Sankey diagram that requires a parent-child dataset"""