From bbfe5c0ae88df8556b3390b06ce9e400cabdc943 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 9 May 2024 16:43:58 +0200 Subject: [PATCH] feat(explore): Color scheme groups, new color schemes (#27995) --- .../cypress/e2e/dashboard/editmode.test.ts | 28 +-- .../superset-ui-core/src/color/ColorScheme.ts | 7 + .../color/colorSchemes/categorical/airbnb.ts | 1 + .../colorSchemes/categorical/blueToGreen.ts | 44 +++++ .../categorical/colorsOfRainbow.ts | 46 +++++ .../src/color/colorSchemes/categorical/d3.ts | 1 + .../color/colorSchemes/categorical/echarts.ts | 1 + .../color/colorSchemes/categorical/google.ts | 1 + .../color/colorSchemes/categorical/index.ts | 6 + .../color/colorSchemes/categorical/lyft.ts | 1 + .../colorSchemes/categorical/modernSunset.ts | 46 +++++ .../color/colorSchemes/categorical/preset.ts | 3 + .../categorical/presetAndSuperset.ts | 46 +++++ .../colorSchemes/categorical/redToYellow.ts | 44 +++++ .../colorSchemes/categorical/superset.ts | 3 + .../colorSchemes/categorical/wavesOfBlue.ts | 44 +++++ .../superset-ui-core/src/color/types.ts | 6 + .../src/components/Select/styles.tsx | 2 +- .../ColorSchemeControl.test.tsx | 73 ++++++- .../controls/ColorSchemeControl/index.tsx | 185 +++++++++++++----- superset-frontend/src/setup/setupColors.ts | 16 +- 21 files changed, 533 insertions(+), 71 deletions(-) create mode 100644 superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/blueToGreen.ts create mode 100644 superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/colorsOfRainbow.ts create mode 100644 superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/modernSunset.ts create mode 100644 superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/presetAndSuperset.ts create mode 100644 superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/redToYellow.ts create mode 100644 superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/wavesOfBlue.ts 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 1a10faf2ecf25..1584cd04e361e 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 25156e615d086..74d0d13fb8440 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 a126f502a9c3d..4aa147582e8df 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/blueToGreen.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/blueToGreen.ts new file mode 100644 index 0000000000000..343192e7057e2 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/blueToGreen.ts @@ -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. + */ + +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: 'blueToGreen', + label: 'Blue to green', + group: ColorSchemeGroup.Featured, + colors: [ + '#3200A7', + '#004CDA', + '#0074F1', + '#0096EF', + '#53BFFF', + '#41C8E6', + '#30DEDE', + '#04D9C7', + '#00EAA2', + '#A6FF93', + ], + }, +].map(s => new CategoricalScheme(s)); + +export default schemes; diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/colorsOfRainbow.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/colorsOfRainbow.ts new file mode 100644 index 0000000000000..7de0542d8c8f0 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/colorsOfRainbow.ts @@ -0,0 +1,46 @@ +/* + * 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 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: 'colorsOfRainbow', + label: 'Colors of rainbow', + group: ColorSchemeGroup.Featured, + colors: [ + '#41ED86', + '#2FC096', + '#01DFFF', + '#153AE0', + '#850AD6', + '#BD59FF', + '#FF4A96', + '#C32668', + '#F40000', + '#FF8901', + '#FFBC0A', + '#FFEC43', + ], + }, +].map(s => new CategoricalScheme(s)); + +export default schemes; 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 84aa0ec024908..861be69aec92f 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 a8dc350f17f3e..ccd6eb9cbd5a9 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 740d35870eee8..e0b4bb11f5ad4 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 81bab749a6c7b..b9fe9496b03aa 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 ec536826c9bcd..91b474ab537b9 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/modernSunset.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/modernSunset.ts new file mode 100644 index 0000000000000..bc1b3db48e2b2 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/modernSunset.ts @@ -0,0 +1,46 @@ +/* + * 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 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: 'modernSunset', + label: 'Modern sunset', + group: ColorSchemeGroup.Featured, + colors: [ + '#0080F6', + '#254081', + '#6C4592', + '#A94693', + '#DC4180', + '#F35193', + '#FF7582', + '#FF4C5D', + '#FF824E', + '#FFAD2A', + '#FFDB04', + '#F3F700', + ], + }, +].map(s => new CategoricalScheme(s)); + +export default schemes; 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 6bd51dc962730..180984263165a 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/presetAndSuperset.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/presetAndSuperset.ts new file mode 100644 index 0000000000000..9a7b3f98e1cad --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/presetAndSuperset.ts @@ -0,0 +1,46 @@ +/* + * 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 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: 'supersetAndPresetColors', + label: 'Preset + Superset', + group: ColorSchemeGroup.Featured, + colors: [ + '#004960', + '#2893B3', + '#20A7C9', + '#5CC0DA', + '#7DCDE1', + '#A9D3E1', + '#C6ECE1', + '#AAE2D2', + '#71CFB4', + '#2FC096', + '#178F7A', + '#067162', + ], + }, +].map(s => new CategoricalScheme(s)); + +export default schemes; diff --git a/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/redToYellow.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/redToYellow.ts new file mode 100644 index 0000000000000..430a3f1dd07e0 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/redToYellow.ts @@ -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. + */ + +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: 'redToYellow', + label: 'Red to yellow', + group: ColorSchemeGroup.Featured, + colors: [ + '#90042A', + '#D60039', + '#D1353B', + '#E45233', + '#F47028', + '#FE8E17', + '#FFAD00', + '#FFCC00', + '#FFE601', + '#FFF46D', + ], + }, +].map(s => new CategoricalScheme(s)); + +export default schemes; 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 e65c6b3600bfb..df407aaa953ec 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/wavesOfBlue.ts b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/wavesOfBlue.ts new file mode 100644 index 0000000000000..252a860058371 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/color/colorSchemes/categorical/wavesOfBlue.ts @@ -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. + */ + +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: 'wavesOfBlue', + label: 'Waves of blue', + group: ColorSchemeGroup.Featured, + colors: [ + '#070061', + '#0A0095', + '#0054B4', + '#006BE7', + '#2289FF', + '#4A9FFF', + '#76B6FF', + '#9DCBFF', + '#BEDCFF', + '#DAEBFF', + ], + }, +].map(s => new CategoricalScheme(s)); + +export default schemes; 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 bc8b50d7a9163..d3fab4b971766 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 cf9613d1c8e8c..d68b391593ca3 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 7def9e7f819f8..1f2b5c722cb40 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) => - render(); + render(); 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 2faa08d8eea2a..105cd1e45d34e 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: ( - - ), - 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: ( + + ) 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) => ( + + )); + } + return nonEmptyGroups.map((group, groupIndex) => ( + + {group.options.map((opt, optIndex) => ( + + ))} + + )); }, [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 ( -