From 756ed0e36acead74944112a8b678a7151319c26f Mon Sep 17 00:00:00 2001 From: Geido <60598000+geido@users.noreply.github.com> Date: Mon, 22 Aug 2022 10:44:15 +0300 Subject: [PATCH] feat: Add label and tooltip for the color schemes control (#21040) * Add tooltip * Remove title * Add license * Enhance E2E tests * Update tests * Lint and test fixes * Enhance layout --- .../dashboard/edit_properties.test.ts | 2 +- .../integration/explore/control.test.ts | 31 +++++ .../explore/visualizations/area.test.js | 2 +- .../explore/visualizations/box_plot.test.js | 2 +- .../explore/visualizations/bubble.test.js | 2 +- .../explore/visualizations/compare.test.js | 2 +- .../explore/visualizations/dist_bar.test.js | 2 +- .../explore/visualizations/dual_line.test.js | 2 +- .../explore/visualizations/gauge.test.js | 2 +- .../explore/visualizations/graph.test.ts | 2 +- .../explore/visualizations/histogram.test.ts | 2 +- .../explore/visualizations/line.test.ts | 2 +- .../explore/visualizations/pie.test.js | 2 +- .../explore/visualizations/sankey.test.js | 2 +- .../explore/visualizations/sunburst.test.js | 2 +- .../explore/visualizations/treemap.test.js | 2 +- .../explore/visualizations/world_map.test.js | 2 +- .../ColorSchemeLabel.test.tsx | 59 ++++++++ .../ColorSchemeControl/ColorSchemeLabel.tsx | 126 ++++++++++++++++++ .../controls/ColorSchemeControl/index.jsx | 36 +---- 20 files changed, 238 insertions(+), 46 deletions(-) create mode 100644 superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeLabel.test.tsx create mode 100644 superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeLabel.tsx diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/edit_properties.test.ts b/superset-frontend/cypress-base/cypress/integration/dashboard/edit_properties.test.ts index f748a48ac..0bb83fa41 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/edit_properties.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/edit_properties.test.ts @@ -154,7 +154,7 @@ describe('Dashboard edit action', () => { openAdvancedProperties().then(() => { assertMetadata('d3Category20'); }); - cy.get('.ant-select-selection-item ul').should( + cy.get('.ant-select-selection-item .color-scheme-option').should( 'have.attr', 'data-test', 'd3Category20', diff --git a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts index a4b85de4d..c64f99140 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts @@ -88,6 +88,37 @@ describe('Datasource control', () => { }); }); +describe('Color scheme control', () => { + beforeEach(() => { + cy.login(); + interceptChart({ legacy: true }).as('chartData'); + + cy.visitChartByName('Num Births Trend'); + cy.verifySliceSuccess({ waitAlias: '@chartData' }); + }); + + it('should show color options with and without tooltips', () => { + cy.get('#controlSections-tab-display').click(); + cy.get('.ant-select-selection-item .color-scheme-label').contains( + 'Superset Colors', + ); + cy.get('.ant-select-selection-item .color-scheme-label').trigger( + 'mouseover', + ); + cy.get('.color-scheme-tooltip').contains('Superset Colors'); + cy.get('.Control[data-test="color_scheme"]').scrollIntoView(); + cy.get('.Control[data-test="color_scheme"] input[type="search"]') + .focus() + .type('lyftColors{enter}'); + cy.get( + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="lyftColors"]', + ).should('exist'); + cy.get('.ant-select-selection-item .color-scheme-label').trigger( + 'mouseover', + ); + cy.get('.color-scheme-tooltip').should('not.exist'); + }); +}); describe('VizType control', () => { beforeEach(() => { cy.login(); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/area.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/area.test.js index eea352039..069b457aa 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/area.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/area.test.js @@ -111,7 +111,7 @@ describe('Visualization > Area', () => { .focus() .type('supersetColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="supersetColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]', ).should('exist'); cy.get('.area .nv-legend .nv-legend-symbol') .first() diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/box_plot.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/box_plot.test.js index 43f644b92..46242e011 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/box_plot.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/box_plot.test.js @@ -54,7 +54,7 @@ describe('Visualization > Box Plot', () => { .focus() .type('supersetColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="supersetColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]', ).should('exist'); }); }); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/bubble.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/bubble.test.js index 28243f686..e41535b54 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/bubble.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/bubble.test.js @@ -114,7 +114,7 @@ describe('Visualization > Bubble', () => { .focus() .type('supersetColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="supersetColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]', ).should('exist'); cy.get('[data-test=run-query-button]').click(); cy.get('.bubble .nv-legend .nv-legend-symbol').should( diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/compare.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/compare.test.js index d4334bbe9..71f61c143 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/compare.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/compare.test.js @@ -94,7 +94,7 @@ describe('Visualization > Compare', () => { .focus() .type('supersetColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="supersetColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]', ).should('exist'); cy.get('.compare .nv-legend .nv-legend-symbol') .first() diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/dist_bar.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/dist_bar.test.js index ecdab93cc..9f62003c8 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/dist_bar.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/dist_bar.test.js @@ -85,7 +85,7 @@ describe('Visualization > Distribution bar chart', () => { .focus() .type('bnbColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="bnbColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="bnbColors"]', ).should('exist'); cy.get('.dist_bar .nv-legend .nv-legend-symbol') .first() diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/dual_line.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/dual_line.test.js index e570836d3..1e7ed4c45 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/dual_line.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/dual_line.test.js @@ -74,7 +74,7 @@ describe('Visualization > Dual Line', () => { .focus() .type('supersetColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="supersetColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]', ).should('exist'); cy.get('.dual_line .nv-legend .nv-legend-symbol') .first() diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/gauge.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/gauge.test.js index 0bb5cb48d..6895d9ef8 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/gauge.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/gauge.test.js @@ -68,7 +68,7 @@ describe('Visualization > Gauge', () => { .focus() .type('bnbColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="bnbColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="bnbColors"]', ).should('exist'); }); }); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/graph.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/graph.test.ts index b54ff10e7..16747d722 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/graph.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/graph.test.ts @@ -85,7 +85,7 @@ describe('Visualization > Graph', () => { .focus() .type('bnbColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="bnbColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="bnbColors"]', ).should('exist'); }); }); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/histogram.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/histogram.test.ts index ef1a2df2d..fbd5cfade 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/histogram.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/histogram.test.ts @@ -92,7 +92,7 @@ describe('Visualization > Histogram', () => { .focus() .type('supersetColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="supersetColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]', ).should('exist'); cy.get('.histogram .vx-legend .vx-legend-shape div') .first() diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/line.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/line.test.ts index b20f69a21..03ab7a6ed 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/line.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/line.test.ts @@ -82,7 +82,7 @@ describe('Visualization > Line', () => { .focus() .type('bnbColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="bnbColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="bnbColors"]', ).should('exist'); cy.get('.line .nv-legend .nv-legend-symbol') .first() diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/pie.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/pie.test.js index 0590d64fa..6c6d33e6e 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/pie.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/pie.test.js @@ -76,7 +76,7 @@ describe('Visualization > Pie', () => { .focus() .type('supersetColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="supersetColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]', ).should('exist'); }); }); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/sankey.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/sankey.test.js index b9f6ced3f..fccefecf3 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/sankey.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/sankey.test.js @@ -81,7 +81,7 @@ describe('Visualization > Sankey', () => { .focus() .type('bnbColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="bnbColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="bnbColors"]', ).should('exist'); }); }); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/sunburst.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/sunburst.test.js index 5118fdfe2..990d1d529 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/sunburst.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/sunburst.test.js @@ -88,7 +88,7 @@ describe('Visualization > Sunburst', () => { .focus() .type('supersetColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="supersetColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]', ).should('exist'); }); }); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/treemap.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/treemap.test.js index 435e363cb..efd92a3e4 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/treemap.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/treemap.test.js @@ -87,7 +87,7 @@ describe('Visualization > Treemap', () => { .focus() .type('supersetColors{enter}'); cy.get( - '.Control[data-test="color_scheme"] .ant-select-selection-item ul[data-test="supersetColors"]', + '.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]', ).should('exist'); cy.get('[data-test=run-query-button]').click(); cy.get('#rect-IND').should('have.css', 'fill', 'rgb(69, 78, 124)'); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/world_map.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/world_map.test.js index 8b733ee3f..8faa4e412 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/world_map.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/world_map.test.js @@ -87,7 +87,7 @@ describe('Visualization > World Map', () => { .focus() .type('greens{enter}'); cy.get( - '.Control[data-test="linear_color_scheme"] .ant-select-selection-item ul[data-test="greens"]', + '.Control[data-test="linear_color_scheme"] .ant-select-selection-item [data-test="greens"]', ).should('exist'); }); }); diff --git a/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeLabel.test.tsx b/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeLabel.test.tsx new file mode 100644 index 000000000..e3117d2f7 --- /dev/null +++ b/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeLabel.test.tsx @@ -0,0 +1,59 @@ +/** + * 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 { render, screen, waitFor } from 'spec/helpers/testing-library'; +import ColorSchemeLabel from './ColorSchemeLabel'; + +const defaultProps = { + colors: [ + '#000000', + '#FFFFFF', + '#CCCCCC', + '#000000', + '#FFFFFF', + '#CCCCCC', + '#000000', + '#FFFFFF', + '#CCCCCC', + '#000000', + '#FFFFFF', + '#CCCCCC', + ], + label: 'Superset Colors', + id: 'colorScheme', +}; + +const setup = (overrides?: Record) => + render(); + +test('should render', async () => { + const { container } = setup(); + await waitFor(() => expect(container).toBeVisible()); +}); + +test('should render the label', () => { + setup(); + expect(screen.getByText('Superset Colors')).toBeInTheDocument(); +}); + +test('should render the colors', () => { + setup(); + const allColors = screen.getAllByTestId('color'); + expect(allColors).toHaveLength(12); +}); diff --git a/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeLabel.tsx b/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeLabel.tsx new file mode 100644 index 000000000..cd046eb1f --- /dev/null +++ b/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeLabel.tsx @@ -0,0 +1,126 @@ +/** + * 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 { css, SupersetTheme } from '@superset-ui/core'; +import React, { useRef, useState } from 'react'; +import { Tooltip } from 'src/components/Tooltip'; + +type ColorSchemeLabelProps = { + colors: string[]; + id: string; + label: string; +}; + +export default function ColorSchemeLabel(props: ColorSchemeLabelProps) { + const { id, label, colors } = props; + const [showTooltip, setShowTooltip] = useState(false); + const labelNameRef = useRef(null); + const labelColorsRef = useRef(null); + const handleShowTooltip = () => { + const labelNameElement = labelNameRef.current; + const labelColorsElement = labelColorsRef.current; + if ( + labelNameElement && + labelColorsElement && + (labelNameElement.scrollWidth > labelNameElement.offsetWidth || + labelNameElement.scrollHeight > labelNameElement.offsetHeight || + labelColorsElement.scrollWidth > labelColorsElement.offsetWidth || + labelColorsElement.scrollHeight > labelColorsElement.offsetHeight) + ) { + setShowTooltip(true); + } + }; + const handleHideTooltip = () => { + setShowTooltip(false); + }; + + const colorsList = () => + colors.map((color: string, i: number) => ( + css` + padding-left: ${theme.gridUnit / 2}px; + :before { + content: ''; + display: inline-block; + background-color: ${color}; + border: 1px solid ${color === 'white' ? 'black' : color}; + width: 9px; + height: 10px; + } + `} + /> + )); + + const tooltipContent = () => ( + <> + {label} +
{colorsList()}
+ + ); + + return ( + + + css` + min-width: 125px; + padding-right: ${theme.gridUnit * 2}px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + `} + > + {label} + + css` + flex: 100%; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + padding-right: ${theme.gridUnit}px; + `} + > + {colorsList()} + + + + ); +} diff --git a/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.jsx b/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.jsx index f0ccc1239..d58552078 100644 --- a/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.jsx +++ b/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.jsx @@ -24,6 +24,7 @@ import { Tooltip } from 'src/components/Tooltip'; import { styled, t } from '@superset-ui/core'; import Icons from 'src/components/Icons'; import ControlHeader from 'src/explore/components/ControlHeader'; +import ColorSchemeLabel from './ColorSchemeLabel'; const propTypes = { hasCustomLabelColors: PropTypes.bool, @@ -86,36 +87,11 @@ export default class ColorSchemeControl extends React.PureComponent { } return ( - -
    - {colors.map((color, i) => ( -
  • -   -
  • - ))} -
-
+ ); }