This is an automated email from the ASF dual-hosted git repository. kgabryje pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push: new bbfe5c0ae8 feat(explore): Color scheme groups, new color schemes (#27995) bbfe5c0ae8 is described below commit bbfe5c0ae88df8556b3390b06ce9e400cabdc943 Author: Kamil Gabryjelski <kamil.gabryjel...@gmail.com> AuthorDate: Thu May 9 16:43:58 2024 +0200 feat(explore): Color scheme groups, new color schemes (#27995) --- .../cypress/e2e/dashboard/editmode.test.ts | 28 ++-- .../superset-ui-core/src/color/ColorScheme.ts | 7 + .../src/color/colorSchemes/categorical/airbnb.ts | 1 + .../categorical/{lyft.ts => blueToGreen.ts} | 27 +-- .../{superset.ts => colorsOfRainbow.ts} | 41 ++--- .../src/color/colorSchemes/categorical/d3.ts | 1 + .../src/color/colorSchemes/categorical/echarts.ts | 1 + .../src/color/colorSchemes/categorical/google.ts | 1 + .../src/color/colorSchemes/categorical/index.ts | 6 + .../src/color/colorSchemes/categorical/lyft.ts | 1 + .../categorical/{superset.ts => modernSunset.ts} | 41 ++--- .../src/color/colorSchemes/categorical/preset.ts | 3 + .../{superset.ts => presetAndSuperset.ts} | 41 ++--- .../categorical/{lyft.ts => redToYellow.ts} | 27 +-- .../src/color/colorSchemes/categorical/superset.ts | 3 + .../categorical/{lyft.ts => wavesOfBlue.ts} | 27 +-- .../packages/superset-ui-core/src/color/types.ts | 6 + superset-frontend/src/components/Select/styles.tsx | 2 +- .../ColorSchemeControl/ColorSchemeControl.test.tsx | 73 +++++++- .../controls/ColorSchemeControl/index.tsx | 185 +++++++++++++++------ superset-frontend/src/setup/setupColors.ts | 16 +- 21 files changed, 359 insertions(+), 179 deletions(-) diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/editmode.test.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/editmode.test.ts index 1a10faf2ec..1584cd04e3 100644 --- a/superset-frontend/cypress-base/cypress/e2e/dashboard/editmode.test.ts +++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/editmode.test.ts @@ -215,7 +215,7 @@ describe('Dashboard edit', () => { it('should apply same color to same labels with color scheme set', () => { openProperties(); - selectColorScheme('lyftColors'); + selectColorScheme('blueToGreen'); applyChanges(); saveChanges(); @@ -231,7 +231,7 @@ describe('Dashboard edit', () => { '[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol', ) .first() - .should('have.css', 'fill', 'rgb(51, 61, 71)'); + .should('have.css', 'fill', 'rgb(0, 234, 162)'); // open 2nd main tab openTab(0, 1); @@ -240,7 +240,7 @@ describe('Dashboard edit', () => { // label Anthony cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol') .eq(2) - .should('have.css', 'fill', 'rgb(51, 61, 71)'); + .should('have.css', 'fill', 'rgb(0, 234, 162)'); }); it('should apply same color to same labels with no color scheme set', () => { @@ -480,7 +480,7 @@ describe('Dashboard edit', () => { it.skip('should change color scheme multiple times', () => { openProperties(); - selectColorScheme('lyftColors'); + selectColorScheme('blueToGreen'); applyChanges(); saveChanges(); @@ -509,7 +509,7 @@ describe('Dashboard edit', () => { editDashboard(); openProperties(); - selectColorScheme('bnbColors'); + selectColorScheme('modernSunset'); applyChanges(); saveChanges(); @@ -532,7 +532,7 @@ describe('Dashboard edit', () => { it.skip('should apply the color scheme across main tabs', () => { openProperties(); - selectColorScheme('lyftColors'); + selectColorScheme('blueToGreen'); applyChanges(); saveChanges(); @@ -548,7 +548,7 @@ describe('Dashboard edit', () => { it.skip('should apply the color scheme across main tabs for rendered charts', () => { waitForChartLoad({ name: 'Treemap', viz: 'treemap_v2' }); openProperties(); - selectColorScheme('bnbColors'); + selectColorScheme('blueToGreen'); applyChanges(); saveChanges(); @@ -563,7 +563,7 @@ describe('Dashboard edit', () => { // change scheme now that charts are rendered across the main tabs editDashboard(); openProperties(); - selectColorScheme('lyftColors'); + selectColorScheme('modernSunset'); applyChanges(); saveChanges(); @@ -574,7 +574,7 @@ describe('Dashboard edit', () => { it.skip('should apply the color scheme in nested tabs', () => { openProperties(); - selectColorScheme('lyftColors'); + selectColorScheme('blueToGreen'); applyChanges(); saveChanges(); @@ -609,7 +609,7 @@ describe('Dashboard edit', () => { // go to previous tab openTab(1, 0); openProperties(); - selectColorScheme('lyftColors'); + selectColorScheme('blueToGreen'); applyChanges(); saveChanges(); @@ -646,16 +646,16 @@ describe('Dashboard edit', () => { }); it.skip('should overwrite the color scheme when advanced is closed', () => { - selectColorScheme('d3Category20b'); + selectColorScheme('blueToGreen'); openAdvancedProperties(); - assertMetadata('d3Category20b'); + assertMetadata('blueToGreen'); applyChanges(); }); it.skip('should overwrite the color scheme when advanced is open', () => { openAdvancedProperties(); - selectColorScheme('googleCategory10c'); - assertMetadata('googleCategory10c'); + selectColorScheme('modernSunset'); + assertMetadata('modernSunset'); applyChanges(); }); diff --git a/superset-frontend/packages/superset-ui-core/src/color/ColorScheme.ts b/superset-frontend/packages/superset-ui-core/src/color/ColorScheme.ts index 25156e615d..74d0d13fb8 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/ColorScheme.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/ColorScheme.ts @@ -17,12 +17,15 @@ * under the License. */ +import { ColorSchemeGroup } from './types'; + export interface ColorSchemeConfig { colors: string[]; description?: string; id: string; label?: string; isDefault?: boolean; + group?: ColorSchemeGroup; } export default class ColorScheme { @@ -36,17 +39,21 @@ export default class ColorScheme { isDefault?: boolean; + group?: ColorSchemeGroup; + constructor({ colors, description = '', id, label, isDefault, + group, }: ColorSchemeConfig) { this.id = id; this.label = label ?? id; this.colors = colors; this.description = description; this.isDefault = isDefault; + this.group = group; } } diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/airbnb.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/airbnb.ts index a126f502a9..4aa147582e 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/airbnb.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/airbnb.ts @@ -19,6 +19,7 @@ import CategoricalScheme from '../../CategoricalScheme'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { id: 'bnbColors', diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/blueToGreen.ts similarity index 70% copy from superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts copy to superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/blueToGreen.ts index ec536826c9..343192e705 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/blueToGreen.ts @@ -18,22 +18,25 @@ */ import CategoricalScheme from '../../CategoricalScheme'; +import { ColorSchemeGroup } from '../../types'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { - id: 'lyftColors', - label: 'Lyft Colors', + id: 'blueToGreen', + label: 'Blue to green', + group: ColorSchemeGroup.Featured, colors: [ - '#EA0B8C', - '#6C838E', - '#29ABE2', - '#33D9C1', - '#9DACB9', - '#7560AA', - '#2D5584', - '#831C4A', - '#333D47', - '#AC2077', + '#3200A7', + '#004CDA', + '#0074F1', + '#0096EF', + '#53BFFF', + '#41C8E6', + '#30DEDE', + '#04D9C7', + '#00EAA2', + '#A6FF93', ], }, ].map(s => new CategoricalScheme(s)); diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/colorsOfRainbow.ts similarity index 68% copy from superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts copy to superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/colorsOfRainbow.ts index e65c6b3600..7de0542d8c 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/colorsOfRainbow.ts @@ -18,34 +18,27 @@ */ import CategoricalScheme from '../../CategoricalScheme'; +import { ColorSchemeGroup } from '../../types'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { - id: 'supersetColors', - label: 'Superset Colors', + id: 'colorsOfRainbow', + label: 'Colors of rainbow', + group: ColorSchemeGroup.Featured, colors: [ - // Full color - '#1FA8C9', - '#454E7C', - '#5AC189', - '#FF7F44', - '#666666', - '#E04355', - '#FCC700', - '#A868B7', - '#3CCCCB', - '#A38F79', - // Pastels - '#8FD3E4', - '#A1A6BD', - '#ACE1C4', - '#FEC0A1', - '#B2B2B2', - '#EFA1AA', - '#FDE380', - '#D3B3DA', - '#9EE5E5', - '#D1C6BC', + '#41ED86', + '#2FC096', + '#01DFFF', + '#153AE0', + '#850AD6', + '#BD59FF', + '#FF4A96', + '#C32668', + '#F40000', + '#FF8901', + '#FFBC0A', + '#FFEC43', ], }, ].map(s => new CategoricalScheme(s)); diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/d3.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/d3.ts index 84aa0ec024..861be69aec 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/d3.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/d3.ts @@ -19,6 +19,7 @@ import CategoricalScheme from '../../CategoricalScheme'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { id: 'd3Category10', diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/echarts.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/echarts.ts index a8dc350f17..ccd6eb9cbd 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/echarts.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/echarts.ts @@ -19,6 +19,7 @@ import CategoricalScheme from '../../CategoricalScheme'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { id: 'echarts4Colors', diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/google.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/google.ts index 740d35870e..e0b4bb11f5 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/google.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/google.ts @@ -19,6 +19,7 @@ import CategoricalScheme from '../../CategoricalScheme'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { id: 'googleCategory10c', diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/index.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/index.ts index 81bab749a6..b9fe9496b0 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/index.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/index.ts @@ -24,3 +24,9 @@ export { default as CategoricalGoogle } from './google'; export { default as CategoricalLyft } from './lyft'; export { default as CategoricalPreset } from './preset'; export { default as CategoricalSuperset } from './superset'; +export { default as CategoricalPresetSuperset } from './presetAndSuperset'; +export { default as CategoricalModernSunset } from './modernSunset'; +export { default as CategoricalColorsOfRainbow } from './colorsOfRainbow'; +export { default as CategoricalBlueToGreen } from './blueToGreen'; +export { default as CategoricalRedToYellow } from './redToYellow'; +export { default as CategoricalWavesOfBlue } from './wavesOfBlue'; diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts index ec536826c9..91b474ab53 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts @@ -19,6 +19,7 @@ import CategoricalScheme from '../../CategoricalScheme'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { id: 'lyftColors', diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/modernSunset.ts similarity index 68% copy from superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts copy to superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/modernSunset.ts index e65c6b3600..bc1b3db48e 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/modernSunset.ts @@ -18,34 +18,27 @@ */ import CategoricalScheme from '../../CategoricalScheme'; +import { ColorSchemeGroup } from '../../types'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { - id: 'supersetColors', - label: 'Superset Colors', + id: 'modernSunset', + label: 'Modern sunset', + group: ColorSchemeGroup.Featured, colors: [ - // Full color - '#1FA8C9', - '#454E7C', - '#5AC189', - '#FF7F44', - '#666666', - '#E04355', - '#FCC700', - '#A868B7', - '#3CCCCB', - '#A38F79', - // Pastels - '#8FD3E4', - '#A1A6BD', - '#ACE1C4', - '#FEC0A1', - '#B2B2B2', - '#EFA1AA', - '#FDE380', - '#D3B3DA', - '#9EE5E5', - '#D1C6BC', + '#0080F6', + '#254081', + '#6C4592', + '#A94693', + '#DC4180', + '#F35193', + '#FF7582', + '#FF4C5D', + '#FF824E', + '#FFAD2A', + '#FFDB04', + '#F3F700', ], }, ].map(s => new CategoricalScheme(s)); diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/preset.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/preset.ts index 6bd51dc962..1809842631 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/preset.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/preset.ts @@ -18,11 +18,14 @@ */ import CategoricalScheme from '../../CategoricalScheme'; +import { ColorSchemeGroup } from '../../types'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { id: 'presetColors', label: 'Preset Colors', + group: ColorSchemeGroup.Featured, colors: [ // Full color '#6BD3B3', diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/presetAndSuperset.ts similarity index 67% copy from superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts copy to superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/presetAndSuperset.ts index e65c6b3600..9a7b3f98e1 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/presetAndSuperset.ts @@ -18,34 +18,27 @@ */ import CategoricalScheme from '../../CategoricalScheme'; +import { ColorSchemeGroup } from '../../types'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { - id: 'supersetColors', - label: 'Superset Colors', + id: 'supersetAndPresetColors', + label: 'Preset + Superset', + group: ColorSchemeGroup.Featured, colors: [ - // Full color - '#1FA8C9', - '#454E7C', - '#5AC189', - '#FF7F44', - '#666666', - '#E04355', - '#FCC700', - '#A868B7', - '#3CCCCB', - '#A38F79', - // Pastels - '#8FD3E4', - '#A1A6BD', - '#ACE1C4', - '#FEC0A1', - '#B2B2B2', - '#EFA1AA', - '#FDE380', - '#D3B3DA', - '#9EE5E5', - '#D1C6BC', + '#004960', + '#2893B3', + '#20A7C9', + '#5CC0DA', + '#7DCDE1', + '#A9D3E1', + '#C6ECE1', + '#AAE2D2', + '#71CFB4', + '#2FC096', + '#178F7A', + '#067162', ], }, ].map(s => new CategoricalScheme(s)); diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/redToYellow.ts similarity index 70% copy from superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts copy to superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/redToYellow.ts index ec536826c9..430a3f1dd0 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/redToYellow.ts @@ -18,22 +18,25 @@ */ import CategoricalScheme from '../../CategoricalScheme'; +import { ColorSchemeGroup } from '../../types'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { - id: 'lyftColors', - label: 'Lyft Colors', + id: 'redToYellow', + label: 'Red to yellow', + group: ColorSchemeGroup.Featured, colors: [ - '#EA0B8C', - '#6C838E', - '#29ABE2', - '#33D9C1', - '#9DACB9', - '#7560AA', - '#2D5584', - '#831C4A', - '#333D47', - '#AC2077', + '#90042A', + '#D60039', + '#D1353B', + '#E45233', + '#F47028', + '#FE8E17', + '#FFAD00', + '#FFCC00', + '#FFE601', + '#FFF46D', ], }, ].map(s => new CategoricalScheme(s)); diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts index e65c6b3600..df407aaa95 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/superset.ts @@ -18,11 +18,14 @@ */ import CategoricalScheme from '../../CategoricalScheme'; +import { ColorSchemeGroup } from '../../types'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { id: 'supersetColors', label: 'Superset Colors', + group: ColorSchemeGroup.Featured, colors: [ // Full color '#1FA8C9', diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/wavesOfBlue.ts similarity index 70% copy from superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts copy to superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/wavesOfBlue.ts index ec536826c9..252a860058 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/lyft.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/wavesOfBlue.ts @@ -18,22 +18,25 @@ */ import CategoricalScheme from '../../CategoricalScheme'; +import { ColorSchemeGroup } from '../../types'; +// TODO: add the colors to the theme while working on SIP https://github.com/apache/superset/issues/20159 const schemes = [ { - id: 'lyftColors', - label: 'Lyft Colors', + id: 'wavesOfBlue', + label: 'Waves of blue', + group: ColorSchemeGroup.Featured, colors: [ - '#EA0B8C', - '#6C838E', - '#29ABE2', - '#33D9C1', - '#9DACB9', - '#7560AA', - '#2D5584', - '#831C4A', - '#333D47', - '#AC2077', + '#070061', + '#0A0095', + '#0054B4', + '#006BE7', + '#2289FF', + '#4A9FFF', + '#76B6FF', + '#9DCBFF', + '#BEDCFF', + '#DAEBFF', ], }, ].map(s => new CategoricalScheme(s)); diff --git a/superset-frontend/packages/superset-ui-core/src/color/types.ts b/superset-frontend/packages/superset-ui-core/src/color/types.ts index bc8b50d7a9..d3fab4b971 100644 --- a/superset-frontend/packages/superset-ui-core/src/color/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/color/types.ts @@ -31,3 +31,9 @@ export interface RgbaColor { b: number; a: number; } + +export enum ColorSchemeGroup { + Custom = 'custom', + Featured = 'featured', + Other = 'other', +} diff --git a/superset-frontend/src/components/Select/styles.tsx b/superset-frontend/src/components/Select/styles.tsx index cf9613d1c8..d68b391593 100644 --- a/superset-frontend/src/components/Select/styles.tsx +++ b/superset-frontend/src/components/Select/styles.tsx @@ -41,7 +41,7 @@ export const StyledContainer = styled.div<{ headerPosition: string }>` export const StyledSelect = styled(AntdSelect, { shouldForwardProp: prop => prop !== 'headerPosition' && prop !== 'oneLine', -})<{ headerPosition: string; oneLine?: boolean }>` +})<{ headerPosition?: string; oneLine?: boolean }>` ${({ theme, headerPosition, oneLine }) => ` flex: ${headerPosition === 'left' ? 1 : 0}; && .ant-select-selector { diff --git a/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx b/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx index 7def9e7f81..1f2b5c722c 100644 --- a/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx +++ b/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx @@ -17,23 +17,37 @@ * under the License. */ import React from 'react'; +import { + CategoricalD3, + CategoricalModernSunset, + CategoricalScheme, + ColorSchemeGroup, + getCategoricalSchemeRegistry, +} from '@superset-ui/core'; +import userEvent from '@testing-library/user-event'; import { render, screen, waitFor } from 'spec/helpers/testing-library'; import ColorSchemeControl, { ColorSchemes } from '.'; -const defaultProps = { +const defaultProps = () => ({ hasCustomLabelColors: false, label: 'Color scheme', labelMargin: 0, name: 'color', value: 'supersetDefault', clearable: true, - choices: [], - schemes: () => ({}) as ColorSchemes, + choices: getCategoricalSchemeRegistry() + .keys() + .map(s => [s, s]), + schemes: getCategoricalSchemeRegistry().getMap() as ColorSchemes, isLinear: false, -}; +}); + +afterAll(() => { + getCategoricalSchemeRegistry().clear(); +}); const setup = (overrides?: Record<string, any>) => - render(<ColorSchemeControl {...defaultProps} {...overrides} />); + render(<ColorSchemeControl {...defaultProps()} {...overrides} />); test('should render', async () => { const { container } = setup(); @@ -56,7 +70,6 @@ test('should not display an alert icon if hasCustomLabelColors=false', async () test('should display an alert icon if hasCustomLabelColors=true', async () => { const hasCustomLabelColorsProps = { - ...defaultProps, hasCustomLabelColors: true, }; setup(hasCustomLabelColorsProps); @@ -66,3 +79,51 @@ test('should display an alert icon if hasCustomLabelColors=true', async () => { ).toBeInTheDocument(); }); }); + +test('displays color scheme options when only "other" group is registered', async () => { + [...CategoricalD3].forEach(scheme => + getCategoricalSchemeRegistry().registerValue(scheme.id, scheme), + ); + setup(); + userEvent.click( + screen.getByLabelText('Select color scheme', { selector: 'input' }), + ); + await waitFor(() => { + expect(screen.getByText('D3 Category 10')).toBeInTheDocument(); + expect(screen.getByText('D3 Category 20')).toBeInTheDocument(); + expect(screen.getByText('D3 Category 20b')).toBeInTheDocument(); + }); + expect(screen.queryByText('Other color palettes')).not.toBeInTheDocument(); + expect(screen.queryByText('Featured color palettes')).not.toBeInTheDocument(); + expect(screen.queryByText('Custom color palettes')).not.toBeInTheDocument(); +}); + +test('displays color scheme options', async () => { + [ + ...CategoricalD3, + ...CategoricalModernSunset, + { + id: 'customScheme', + label: 'Custom scheme', + group: ColorSchemeGroup.Custom, + colors: ['#0080F6', '#254081'], + } as CategoricalScheme, + ].forEach(scheme => + getCategoricalSchemeRegistry().registerValue(scheme.id, scheme), + ); + setup(); + userEvent.click( + screen.getByLabelText('Select color scheme', { selector: 'input' }), + ); + await waitFor(() => { + expect(screen.getByText('D3 Category 10')).toBeInTheDocument(); + expect(screen.getByText('D3 Category 20')).toBeInTheDocument(); + expect(screen.getByText('D3 Category 20b')).toBeInTheDocument(); + expect(screen.getByText('Modern sunset')).toBeInTheDocument(); + expect(screen.getByText('Custom scheme')).toBeInTheDocument(); + + expect(screen.getByText('Custom color palettes')).toBeInTheDocument(); + expect(screen.getByText('Featured color palettes')).toBeInTheDocument(); + expect(screen.getByText('Other color palettes')).toBeInTheDocument(); + }); +}); diff --git a/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx b/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx index 2faa08d8ee..105cd1e45d 100644 --- a/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx +++ b/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx @@ -17,14 +17,29 @@ * under the License. */ import React, { useMemo } from 'react'; -import { ColorScheme, SequentialScheme, styled, t } from '@superset-ui/core'; -import { isFunction } from 'lodash'; -import { Select } from 'src/components'; +import { + css, + ColorScheme, + ColorSchemeGroup, + SequentialScheme, + styled, + t, + useTheme, +} from '@superset-ui/core'; +import AntdSelect from 'antd/lib/select'; +import { isFunction, sortBy } from 'lodash'; import ControlHeader from 'src/explore/components/ControlHeader'; import { Tooltip } from 'src/components/Tooltip'; import Icons from 'src/components/Icons'; +import { SelectOptionsType } from 'src/components/Select/types'; +import { StyledSelect } from 'src/components/Select/styles'; +import { handleFilterOptionHelper } from 'src/components/Select/utils'; import ColorSchemeLabel from './ColorSchemeLabel'; +const { Option, OptGroup } = AntdSelect; + +export type OptionData = SelectOptionsType[number]['options'][number]; + export interface ColorSchemes { [key: string]: ColorScheme; } @@ -85,7 +100,6 @@ const ColorSchemeControl = ({ hasCustomLabelColors = false, dashboardId, label = t('Color scheme'), - name, onChange = () => {}, value, clearable = false, @@ -95,6 +109,7 @@ const ColorSchemeControl = ({ isLinear, ...rest }: ColorSchemeControlProps) => { + const theme = useTheme(); const currentScheme = useMemo(() => { if (dashboardId) { return 'dashboard'; @@ -130,30 +145,82 @@ const ColorSchemeControl = ({ return isValidColorOption; }); - return filteredColorOptions.map(([value]) => { - const currentScheme = schemesObject[value]; - - // For categorical scheme, display all the colors - // For sequential scheme, show 10 or interpolate to 10. - // Sequential schemes usually have at most 10 colors. - let colors: string[] = []; - if (currentScheme) { - colors = isLinear - ? (currentScheme as SequentialScheme).getColors(10) - : currentScheme.colors; - } - return { - customLabel: ( - <ColorSchemeLabel - id={currentScheme.id} - label={currentScheme.label} - colors={colors} - /> - ), - label: schemesObject?.[value]?.label || value, - value, - }; - }); + const groups = filteredColorOptions.reduce( + (acc, [value]) => { + const currentScheme = schemesObject[value]; + + // For categorical scheme, display all the colors + // For sequential scheme, show 10 or interpolate to 10. + // Sequential schemes usually have at most 10 colors. + let colors: string[] = []; + if (currentScheme) { + colors = isLinear + ? (currentScheme as SequentialScheme).getColors(10) + : currentScheme.colors; + } + const option = { + customLabel: ( + <ColorSchemeLabel + id={currentScheme.id} + label={currentScheme.label} + colors={colors} + /> + ) as React.ReactNode, + label: schemesObject?.[value]?.label || value, + value, + }; + acc[currentScheme.group ?? ColorSchemeGroup.Other].options.push(option); + return acc; + }, + { + [ColorSchemeGroup.Custom]: { + title: ColorSchemeGroup.Custom, + label: t('Custom color palettes'), + options: [] as OptionData, + }, + [ColorSchemeGroup.Featured]: { + title: ColorSchemeGroup.Featured, + label: t('Featured color palettes'), + options: [] as OptionData, + }, + [ColorSchemeGroup.Other]: { + title: ColorSchemeGroup.Other, + label: t('Other color palettes'), + options: [] as OptionData, + }, + }, + ); + const nonEmptyGroups = Object.values(groups) + .filter(group => group.options.length > 0) + .map(group => ({ + ...group, + options: sortBy(group.options, opt => opt.label), + })); + + // if there are no featured or custom color schemes, return the ungrouped options + if ( + nonEmptyGroups.length === 1 && + nonEmptyGroups[0].title === ColorSchemeGroup.Other + ) { + return nonEmptyGroups[0].options.map((opt, index) => ( + <Option value={opt.value} label={opt.label} key={index}> + {opt.customLabel} + </Option> + )); + } + return nonEmptyGroups.map((group, groupIndex) => ( + <OptGroup label={group.label} key={groupIndex}> + {group.options.map((opt, optIndex) => ( + <Option + value={opt.value} + label={opt.label} + key={`${groupIndex}-${optIndex}`} + > + {opt.customLabel} + </Option> + ))} + </OptGroup> + )); }, [choices, dashboardId, isLinear, schemes]); // We can't pass on change directly because it receives a second @@ -161,28 +228,48 @@ const ColorSchemeControl = ({ const handleOnChange = (value: string) => onChange(value); return ( - <Select - header={ - <ControlHeader - {...rest} - label={ - <Label - label={label} - hasCustomLabelColors={hasCustomLabelColors} - dashboardId={dashboardId} - /> + <> + <ControlHeader + {...rest} + label={ + <Label + label={label} + hasCustomLabelColors={hasCustomLabelColors} + dashboardId={dashboardId} + /> + } + /> + <StyledSelect + css={css` + width: 100%; + & .ant-select-item.ant-select-item-group { + padding-left: ${theme.gridUnit}px; + font-size: ${theme.typography.sizes.m}px; + } + & .ant-select-item-option-grouped { + padding-left: ${theme.gridUnit * 3}px; } - /> - } - ariaLabel={t('Select color scheme')} - allowClear={clearable} - disabled={!!dashboardId} - name={`select-${name}`} - onChange={handleOnChange} - options={options} - placeholder={t('Select scheme')} - value={currentScheme} - /> + `} + aria-label={t('Select color scheme')} + allowClear={clearable} + disabled={!!dashboardId} + onChange={handleOnChange} + placeholder={t('Select scheme')} + value={currentScheme} + getPopupContainer={triggerNode => triggerNode.parentNode} + showSearch + filterOption={(search, option) => + handleFilterOptionHelper( + search, + option as OptionData, + ['label', 'value'], + true, + ) + } + > + {options} + </StyledSelect> + </> ); }; diff --git a/superset-frontend/src/setup/setupColors.ts b/superset-frontend/src/setup/setupColors.ts index 01122243ce..140bf79b42 100644 --- a/superset-frontend/src/setup/setupColors.ts +++ b/superset-frontend/src/setup/setupColors.ts @@ -34,6 +34,13 @@ import { SequentialCommon, SequentialD3, ColorSchemeRegistry, + ColorSchemeGroup, + CategoricalPresetSuperset, + CategoricalModernSunset, + CategoricalColorsOfRainbow, + CategoricalBlueToGreen, + CategoricalRedToYellow, + CategoricalWavesOfBlue, } from '@superset-ui/core'; function registerColorSchemes<T extends ColorScheme>( @@ -55,7 +62,8 @@ export default function setupColors( extraSequentialColorSchemeConfigs: SequentialSchemeConfig[] = [], ) { const extraCategoricalColorSchemes = extraCategoricalColorSchemeConfigs.map( - config => new CategoricalScheme(config), + config => + new CategoricalScheme({ ...config, group: ColorSchemeGroup.Custom }), ); const extraSequentialColorSchemes = extraSequentialColorSchemeConfigs.map( config => new SequentialScheme(config), @@ -71,6 +79,12 @@ export default function setupColors( ...CategoricalLyft, ...CategoricalPreset, ...CategoricalSuperset, + ...CategoricalPresetSuperset, + ...CategoricalModernSunset, + ...CategoricalColorsOfRainbow, + ...CategoricalBlueToGreen, + ...CategoricalRedToYellow, + ...CategoricalWavesOfBlue, ...extraCategoricalColorSchemes, ], 'supersetColors',