This is an automated email from the ASF dual-hosted git repository.

diegopucci pushed a commit to branch geido/fix/color-consistency-race-conditions
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to 
refs/heads/geido/fix/color-consistency-race-conditions by this push:
     new 0cc680f1ba chore(Dashboard): Store only shared label name references
0cc680f1ba is described below

commit 0cc680f1baab5abd8e0f878faf9445571b431538
Author: Diego Pucci <[email protected]>
AuthorDate: Wed Nov 6 18:33:13 2024 +0200

    chore(Dashboard): Store only shared label name references
---
 .../cypress/e2e/dashboard/editmode.test.ts         |  2 +-
 .../e2e/dashboard/shared_dashboard_functions.ts    |  2 +-
 .../src/shared-controls/sharedControls.tsx         |  4 +-
 .../test/color/CategoricalColorScale.test.ts       |  5 +-
 .../test/color/LabelsColorMapSingleton.test.ts     | 43 ++++++++++--
 .../plugins/legacy-plugin-chart-chord/src/Chord.js | 13 ++--
 .../src/CountryMap.js                              |  7 +-
 .../src/Histogram.jsx                              |  5 +-
 .../legacy-plugin-chart-partition/src/Partition.js |  5 +-
 .../plugins/legacy-plugin-chart-rose/src/Rose.js   |  5 +-
 .../src/SankeyLoop.js                              |  5 +-
 .../legacy-plugin-chart-sankey/src/Sankey.js       |  5 +-
 .../legacy-preset-chart-nvd3/src/NVD3Vis.js        |  4 +-
 .../src/Gauge/transformProps.ts                    |  3 +-
 .../src/chart/WordCloud.tsx                        |  8 +--
 .../src/configureEncodable.ts                      |  3 +-
 .../spec/fixtures/mockDashboardFormData.ts         |  5 +-
 .../spec/fixtures/mockDashboardState.js            |  2 +-
 .../src/dashboard/actions/dashboardState.js        | 39 +++++------
 .../dashboard/components/PropertiesModal/index.tsx |  6 +-
 .../components/SyncDashboardState/index.tsx        |  5 +-
 .../FilterBarSettings/FilterBarSettings.test.tsx   |  4 +-
 .../FiltersConfigForm/FilterScope/utils.test.ts    | 20 +++---
 .../src/dashboard/containers/Chart.jsx             | 12 ++--
 superset-frontend/src/dashboard/types.ts           |  4 +-
 .../util/charts/getFormDataWithExtraFilters.ts     | 15 ++---
 .../ColorSchemeControl/ColorSchemeControl.test.tsx |  6 +-
 .../controls/ColorSchemeControl/index.tsx          |  8 +--
 .../getFormDataFromDashboardContext.test.ts        |  6 +-
 superset-frontend/src/pages/Chart/index.tsx        |  4 +-
 .../src/types/DashboardContextForExplore.ts        |  2 +-
 superset-frontend/src/utils/colorScheme.ts         | 77 +++++++++++++---------
 superset/daos/dashboard.py                         |  4 +-
 superset/dashboards/schemas.py                     |  4 +-
 tests/integration_tests/dashboards/api_tests.py    |  2 +-
 tests/unit_tests/fixtures/assets_configs.py        |  8 +--
 tests/unit_tests/security/manager_test.py          |  4 +-
 37 files changed, 206 insertions(+), 150 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 9a42320d94..54d15a5562 100644
--- a/superset-frontend/cypress-base/cypress/e2e/dashboard/editmode.test.ts
+++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/editmode.test.ts
@@ -110,7 +110,7 @@ function resetTabbedDashboard(go = false) {
       ...metadata,
       color_scheme: '',
       label_colors: {},
-      shared_label_colors: {},
+      shared_label_colors: [],
     });
     cy.updateDashboard(r.id, {
       certification_details: r.certification_details,
diff --git 
a/superset-frontend/cypress-base/cypress/e2e/dashboard/shared_dashboard_functions.ts
 
b/superset-frontend/cypress-base/cypress/e2e/dashboard/shared_dashboard_functions.ts
index ad47116d34..b0f7853e94 100644
--- 
a/superset-frontend/cypress-base/cypress/e2e/dashboard/shared_dashboard_functions.ts
+++ 
b/superset-frontend/cypress-base/cypress/e2e/dashboard/shared_dashboard_functions.ts
@@ -91,7 +91,7 @@ export function prepareDashboardFilters(
         refresh_frequency: 0,
         color_scheme: '',
         label_colors: {},
-        shared_label_colors: {},
+        shared_label_colors: [],
         color_scheme_domain: [],
         cross_filters_enabled: false,
         positions: {
diff --git 
a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx
 
b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx
index 90e162aade..078d37a056 100644
--- 
a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx
+++ 
b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx
@@ -150,7 +150,7 @@ const linear_color_scheme: 
SharedControlConfig<'ColorSchemeControl'> = {
       hasDashboardColorScheme: dashboardId && !!state?.form_data?.color_scheme,
       hasCustomLabelsColor:
         Object.keys(state?.form_data?.label_colors || {}).length > 0,
-      sharedLabelsColor: state?.form_data?.shared_label_colors || {},
+      sharedLabelsColors: state?.form_data?.shared_label_colors || [],
     };
   },
 };
@@ -349,7 +349,7 @@ const color_scheme: 
SharedControlConfig<'ColorSchemeControl'> = {
       hasDashboardColorScheme: dashboardId && !!state?.form_data?.color_scheme,
       hasCustomLabelsColor:
         Object.keys(state?.form_data?.label_colors || {}).length > 0,
-      sharedLabelsColor: state?.form_data?.shared_label_colors || {},
+      sharedLabelsColors: state?.form_data?.shared_label_colors || [],
     };
   },
 };
diff --git 
a/superset-frontend/packages/superset-ui-core/test/color/CategoricalColorScale.test.ts
 
b/superset-frontend/packages/superset-ui-core/test/color/CategoricalColorScale.test.ts
index 6a44a73298..96ae5ac753 100644
--- 
a/superset-frontend/packages/superset-ui-core/test/color/CategoricalColorScale.test.ts
+++ 
b/superset-frontend/packages/superset-ui-core/test/color/CategoricalColorScale.test.ts
@@ -29,7 +29,7 @@ describe('CategoricalColorScale', () => {
     expect(CategoricalColorScale !== undefined).toBe(true);
   });
 
-  describe('new CategoricalColorScale(colors, forcedColors)', () => {
+  describe('new CategoricalColorScale(colors, forcedColors, colorScheme, 
originalScheme)', () => {
     it('can create new scale when forcedColors is not given', () => {
       const scale = new CategoricalColorScale(['blue', 'red', 'green']);
       expect(scale).toBeInstanceOf(CategoricalColorScale);
@@ -156,7 +156,7 @@ describe('CategoricalColorScale', () => {
 
       expect(scale.chartLabelsColorMap.has(value)).toBe(false);
 
-      scale.getColor(value, sliceId, colorScheme);
+      scale.getColor(value, sliceId, colorScheme, 'originalColorScheme');
 
       expect(scale.chartLabelsColorMap.has(value)).toBe(true);
       expect(scale.chartLabelsColorMap.get(value)).toBeDefined();
@@ -166,6 +166,7 @@ describe('CategoricalColorScale', () => {
         expect.any(String),
         sliceId,
         colorScheme,
+        'originalColorScheme',
       );
 
       const expectedColor = scale.chartLabelsColorMap.get(value);
diff --git 
a/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts
 
b/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts
index b93a416e7f..1b42dd7484 100644
--- 
a/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts
+++ 
b/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts
@@ -92,11 +92,17 @@ describe('LabelsColorMap', () => {
       expect(Object.fromEntries(colorMap)).toEqual({ b: 'green' });
     });
 
-    it('should do nothing when source is not dashboard', () => {
+    it('should set a new color only when source is dashboard', () => {
       const labelsColorMap = getLabelsColorMap();
       labelsColorMap.source = LabelsColorMapSource.Explore;
       labelsColorMap.addSlice('a', 'red', 1);
-      expect(Object.fromEntries(labelsColorMap.chartsLabelsMap)).toEqual({});
+      const colorMap = labelsColorMap.getColorMap();
+      expect(Object.fromEntries(colorMap)).toEqual({});
+
+      labelsColorMap.source = LabelsColorMapSource.Dashboard;
+      labelsColorMap.addSlice('a', 'red', 1);
+      const colorMap2 = labelsColorMap.getColorMap();
+      expect(Object.fromEntries(colorMap2)).toEqual({ a: 'red' });
     });
   });
 
@@ -126,7 +132,7 @@ describe('LabelsColorMap', () => {
     });
   });
 
-  describe('.updateColorMap(namespace, scheme)', () => {
+  describe('.updateColorMap(namespace, scheme, merge)', () => {
     let categoricalNamespace: any;
     let mockedNamespace: any;
     let labelsColorMap: any;
@@ -141,6 +147,18 @@ describe('LabelsColorMap', () => {
       };
     });
 
+    it('should clear color map when not merge', () => {
+      labelsColorMap.addSlice('a', 'red', 1);
+      labelsColorMap.updateColorMap(mockedNamespace, 'testColors2', false);
+      expect(labelsColorMap.colorMap).toEqual(new Map([['a', 'mockColor']]));
+    });
+
+    it('should not clear color map when merge', () => {
+      labelsColorMap.addSlice('a', 'red', 1);
+      labelsColorMap.updateColorMap(mockedNamespace, 'testColors2', true);
+      expect(labelsColorMap.colorMap).not.toEqual(new Map());
+    });
+
     it('should use provided color scheme', () => {
       labelsColorMap.addSlice('a', 'red', 1);
       labelsColorMap.updateColorMap(mockedNamespace, 'testColors2');
@@ -148,7 +166,7 @@ describe('LabelsColorMap', () => {
     });
 
     it('should fallback to original chart color scheme if no color scheme is 
provided', () => {
-      labelsColorMap.addSlice('a', 'red', 1, 'originalScheme');
+      labelsColorMap.addSlice('a', 'red', 1, 'currentScheme', 
'originalScheme');
       labelsColorMap.updateColorMap(mockedNamespace);
       expect(mockedNamespace.getScale).toHaveBeenCalledWith('originalScheme');
     });
@@ -181,6 +199,23 @@ describe('LabelsColorMap', () => {
       });
     });
 
+    it('should update only new labels in the color map when merge', () => {
+      labelsColorMap.colorMap = new Map();
+
+      labelsColorMap.addSlice('a', 'yellow', 1);
+      labelsColorMap.addSlice('b', 'green', 1);
+      labelsColorMap.addSlice('c', 'purple', 1);
+
+      labelsColorMap.updateColorMap(categoricalNamespace, 'testColors2', true);
+
+      const mergedColorMap = labelsColorMap.getColorMap();
+      expect(Object.fromEntries(mergedColorMap)).toEqual({
+        a: 'yellow',
+        b: 'green',
+        c: 'purple',
+      });
+    });
+
     it('should use recycle colors', () => {
       window.featureFlags = {
         [FeatureFlag.UseAnalagousColors]: false,
diff --git a/superset-frontend/plugins/legacy-plugin-chart-chord/src/Chord.js 
b/superset-frontend/plugins/legacy-plugin-chart-chord/src/Chord.js
index dc20f3d15f..bf3db9579d 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-chord/src/Chord.js
+++ b/superset-frontend/plugins/legacy-plugin-chart-chord/src/Chord.js
@@ -54,7 +54,10 @@ function Chord(element, props) {
   const { nodes, matrix } = data;
   const f = getNumberFormatter(numberFormat);
   const appliedScheme = colorScheme || ownColorScheme;
-  const colorFn = CategoricalColorNamespace.getScale(appliedScheme, 
ownColorScheme);
+  const colorFn = CategoricalColorNamespace.getScale(
+    appliedScheme,
+    ownColorScheme,
+  );
 
   const outerRadius = Math.min(width, height) / 2 - 10;
   const innerRadius = outerRadius - 24;
@@ -103,9 +106,7 @@ function Chord(element, props) {
     .append('path')
     .attr('id', (d, i) => `group${i}`)
     .attr('d', arc)
-    .style('fill', (d, i) =>
-      colorFn(nodes[i], sliceId),
-    );
+    .style('fill', (d, i) => colorFn(nodes[i], sliceId));
 
   // Add a text label.
   const groupText = group.append('text').attr('x', 6).attr('dy', 15);
@@ -133,9 +134,7 @@ function Chord(element, props) {
     .on('mouseover', d => {
       chord.classed('fade', p => p !== d);
     })
-    .style('fill', d =>
-      colorFn(nodes[d.source.index], sliceId),
-    )
+    .style('fill', d => colorFn(nodes[d.source.index], sliceId))
     .attr('d', path);
 
   // Add an elaborate mouseover title for each chord.
diff --git 
a/superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.js 
b/superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.js
index cbbbde8dfe..94b7b3f68a 100644
--- 
a/superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.js
+++ 
b/superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.js
@@ -17,7 +17,7 @@
  * under the License.
  */
 /* eslint-disable react/sort-prop-types */
-import d3, { color } from 'd3';
+import d3 from 'd3';
 import PropTypes from 'prop-types';
 import { extent as d3Extent } from 'd3-array';
 import {
@@ -65,7 +65,10 @@ function CountryMap(element, props) {
     .get(linearColorScheme)
     .createLinearScale(d3Extent(data, v => v.metric));
   const appliedScheme = colorScheme || ownColorScheme;
-  const colorScale = CategoricalColorNamespace.getScale(appliedScheme, 
ownColorScheme);
+  const colorScale = CategoricalColorNamespace.getScale(
+    appliedScheme,
+    ownColorScheme,
+  );
 
   const colorMap = {};
   data.forEach(d => {
diff --git 
a/superset-frontend/plugins/legacy-plugin-chart-histogram/src/Histogram.jsx 
b/superset-frontend/plugins/legacy-plugin-chart-histogram/src/Histogram.jsx
index 8edc544cce..ff35d8701c 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-histogram/src/Histogram.jsx
+++ b/superset-frontend/plugins/legacy-plugin-chart-histogram/src/Histogram.jsx
@@ -77,7 +77,10 @@ class CustomHistogram extends PureComponent {
       sliceId,
     } = this.props;
     const appliedScheme = colorScheme || ownColorScheme;
-    const colorFn = CategoricalColorNamespace.getScale(appliedScheme, 
ownColorScheme);
+    const colorFn = CategoricalColorNamespace.getScale(
+      appliedScheme,
+      ownColorScheme,
+    );
     const keys = data.map(d => d.key);
     const colorScale = scaleOrdinal({
       domain: keys,
diff --git 
a/superset-frontend/plugins/legacy-plugin-chart-partition/src/Partition.js 
b/superset-frontend/plugins/legacy-plugin-chart-partition/src/Partition.js
index c58b0746c9..fdbbd813c1 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-partition/src/Partition.js
+++ b/superset-frontend/plugins/legacy-plugin-chart-partition/src/Partition.js
@@ -132,7 +132,10 @@ function Icicle(element, props) {
   const format = getNumberFormatter(numberFormat);
   const timeFormat = getTimeFormatter(dateTimeFormat);
   const appliedScheme = colorScheme || ownColorScheme;
-  const colorFn = CategoricalColorNamespace.getScale(appliedScheme, 
ownColorScheme);
+  const colorFn = CategoricalColorNamespace.getScale(
+    appliedScheme,
+    ownColorScheme,
+  );
 
   div.selectAll('*').remove();
   const tooltip = div.append('div').classed('partition-tooltip', true);
diff --git a/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.js 
b/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.js
index 668e13445d..aa6acfa440 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.js
+++ b/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.js
@@ -93,7 +93,10 @@ function Rose(element, props) {
   const format = getNumberFormatter(numberFormat);
   const timeFormat = getTimeFormatter(dateTimeFormat);
   const appliedScheme = colorScheme || ownColorScheme;
-  const colorFn = CategoricalColorNamespace.getScale(appliedScheme, 
ownColorScheme);
+  const colorFn = CategoricalColorNamespace.getScale(
+    appliedScheme,
+    ownColorScheme,
+  );
 
   d3.select('.nvtooltip').remove();
   div.selectAll('*').remove();
diff --git 
a/superset-frontend/plugins/legacy-plugin-chart-sankey-loop/src/SankeyLoop.js 
b/superset-frontend/plugins/legacy-plugin-chart-sankey-loop/src/SankeyLoop.js
index 7eaa6a9629..24a6747296 100644
--- 
a/superset-frontend/plugins/legacy-plugin-chart-sankey-loop/src/SankeyLoop.js
+++ 
b/superset-frontend/plugins/legacy-plugin-chart-sankey-loop/src/SankeyLoop.js
@@ -85,7 +85,10 @@ function computeGraph(links) {
 function SankeyLoop(element, props) {
   const { data, width, height, colorScheme, ownColorScheme, sliceId } = props;
   const appliedScheme = colorScheme || ownColorScheme;
-  const colorFn = CategoricalColorNamespace.getScale(appliedScheme, 
ownColorScheme);
+  const colorFn = CategoricalColorNamespace.getScale(
+    appliedScheme,
+    ownColorScheme,
+  );
   const margin = { ...defaultMargin, ...props.margin };
   const innerWidth = width - margin.left - margin.right;
   const innerHeight = height - margin.top - margin.bottom;
diff --git a/superset-frontend/plugins/legacy-plugin-chart-sankey/src/Sankey.js 
b/superset-frontend/plugins/legacy-plugin-chart-sankey/src/Sankey.js
index 6797d50f61..2e075d92af 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-sankey/src/Sankey.js
+++ b/superset-frontend/plugins/legacy-plugin-chart-sankey/src/Sankey.js
@@ -69,7 +69,10 @@ function Sankey(element, props) {
     .append('g')
     .attr('transform', `translate(${margin.left},${margin.top})`);
   const appliedScheme = colorScheme || ownColorScheme;
-  const colorFn = CategoricalColorNamespace.getScale(appliedScheme, 
ownColorScheme);
+  const colorFn = CategoricalColorNamespace.getScale(
+    appliedScheme,
+    ownColorScheme,
+  );
 
   const sankey = d3Sankey()
     .nodeWidth(15)
diff --git a/superset-frontend/plugins/legacy-preset-chart-nvd3/src/NVD3Vis.js 
b/superset-frontend/plugins/legacy-preset-chart-nvd3/src/NVD3Vis.js
index 39f2f7cd91..293957f17a 100644
--- a/superset-frontend/plugins/legacy-preset-chart-nvd3/src/NVD3Vis.js
+++ b/superset-frontend/plugins/legacy-preset-chart-nvd3/src/NVD3Vis.js
@@ -660,9 +660,7 @@ function nvd3Vis(element, props) {
     } else if (vizType !== 'bullet') {
       const colorFn = getScale(appliedScheme, ownColorScheme);
       chart.color(
-        d =>
-          d.color ||
-          colorFn(cleanColorInput(d[colorKey]), sliceId),
+        d => d.color || colorFn(cleanColorInput(d[colorKey]), sliceId),
       );
     }
 
diff --git 
a/superset-frontend/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts 
b/superset-frontend/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts
index b624119148..9878705a15 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts
@@ -171,6 +171,7 @@ export default function transformProps(
       const name = groupbyLabels
         .map(column => `${verboseMap[column] || column}: 
${data_point[column]}`)
         .join(', ');
+      const colorLabel = groupbyLabels.map(col => data_point[col] as string);
       columnsLabelMap.set(
         name,
         groupbyLabels.map(col => data_point[col] as string),
@@ -179,7 +180,7 @@ export default function transformProps(
         value: data_point[metricLabel] as number,
         name,
         itemStyle: {
-          color: colorFn(index, sliceId),
+          color: colorFn(colorLabel, sliceId),
         },
         title: {
           offsetCenter: [
diff --git 
a/superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx 
b/superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx
index 53bf98fe90..883ef5efe3 100644
--- a/superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx
+++ b/superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx
@@ -222,7 +222,7 @@ class WordCloud extends PureComponent<FullWordCloudProps, 
WordCloudState> {
 
   render() {
     const { scaleFactor } = this.state;
-    const { width, height, encoding, sliceId, colorScheme } = this.props;
+    const { width, height, encoding, sliceId } = this.props;
     const { words } = this.state;
 
     // @ts-ignore
@@ -250,11 +250,7 @@ class WordCloud extends PureComponent<FullWordCloudProps, 
WordCloudState> {
               fontSize={`${w.size}px`}
               fontWeight={w.weight}
               fontFamily={w.font}
-              fill={colorFn(
-                getValueFromDatum(w) as string,
-                sliceId,
-                colorScheme,
-              )}
+              fill={colorFn(getValueFromDatum(w) as string, sliceId)}
               textAnchor="middle"
               transform={`translate(${w.x}, ${w.y}) rotate(${w.rotate})`}
             >
diff --git 
a/superset-frontend/plugins/plugin-chart-word-cloud/src/configureEncodable.ts 
b/superset-frontend/plugins/plugin-chart-word-cloud/src/configureEncodable.ts
index 05a2041286..c18072d33c 100644
--- 
a/superset-frontend/plugins/plugin-chart-word-cloud/src/configureEncodable.ts
+++ 
b/superset-frontend/plugins/plugin-chart-word-cloud/src/configureEncodable.ts
@@ -72,8 +72,9 @@ const colorSchemeResolver: ColorSchemeResolver = ({
 
 const colorScaleResolver: CategoricalColorScaleResolver = ({
   name,
+  colorScheme,
   namespace,
-} = {}) => CategoricalColorNamespace.getScale(name, namespace);
+} = {}) => CategoricalColorNamespace.getScale(name, colorScheme, namespace);
 
 export default function configureEncodable() {
   Encodable.setNumberFormatResolver(getNumberFormatter)
diff --git a/superset-frontend/spec/fixtures/mockDashboardFormData.ts 
b/superset-frontend/spec/fixtures/mockDashboardFormData.ts
index a1adb18a7e..3f08980250 100644
--- a/superset-frontend/spec/fixtures/mockDashboardFormData.ts
+++ b/superset-frontend/spec/fixtures/mockDashboardFormData.ts
@@ -26,10 +26,7 @@ export const getDashboardFormData = (overrides: JsonObject = 
{}) => ({
     girl: '#FF69B4',
     boy: '#ADD8E6',
   },
-  shared_label_colors: {
-    boy: '#ADD8E6',
-    girl: '#FF69B4',
-  },
+  shared_label_colors: ['boy', 'girl'],
   color_scheme: 'd3Category20b',
   extra_filters: [
     {
diff --git a/superset-frontend/spec/fixtures/mockDashboardState.js 
b/superset-frontend/spec/fixtures/mockDashboardState.js
index 737e38aef5..42360cdc71 100644
--- a/superset-frontend/spec/fixtures/mockDashboardState.js
+++ b/superset-frontend/spec/fixtures/mockDashboardState.js
@@ -113,6 +113,6 @@ export const overwriteConfirmMetadata = {
     slug: null,
     owners: [],
     json_metadata:
-      
'{"timed_refresh_immune_slices":[],"expanded_slices":{},"refresh_frequency":0,"default_filters":"{}","color_scheme":"supersetColors","label_colors":{"0":"#FCC700","1":"#A868B7","15":"#3CCCCB","30":"#A38F79","45":"#8FD3E4","age":"#1FA8C9","Yes,":"#1FA8C9","Female":"#454E7C","Prefer":"#5AC189","No,":"#FF7F44","Male":"#666666","Prefer
 not to say":"#E04355","Ph.D.":"#FCC700","associate\'s 
degree":"#A868B7","bachelor\'s degree":"#3CCCCB","high school diploma or 
equivalent (GED)":"#A38F7 [...]
+      
'{"timed_refresh_immune_slices":[],"expanded_slices":{},"refresh_frequency":0,"default_filters":"{}","color_scheme":"supersetColors","label_colors":{"0":"#FCC700","1":"#A868B7","15":"#3CCCCB","30":"#A38F79","45":"#8FD3E4","age":"#1FA8C9","Yes,":"#1FA8C9","Female":"#454E7C","Prefer":"#5AC189","No,":"#FF7F44","Male":"#666666","Prefer
 not to say":"#E04355","Ph.D.":"#FCC700","associate\'s 
degree":"#A868B7","bachelor\'s degree":"#3CCCCB","high school diploma or 
equivalent (GED)":"#A38F7 [...]
   },
 };
diff --git a/superset-frontend/src/dashboard/actions/dashboardState.js 
b/superset-frontend/src/dashboard/actions/dashboardState.js
index f6b14f446e..95b6bf929c 100644
--- a/superset-frontend/src/dashboard/actions/dashboardState.js
+++ b/superset-frontend/src/dashboard/actions/dashboardState.js
@@ -55,7 +55,6 @@ import { getActiveFilters } from 
'src/dashboard/util/activeDashboardFilters';
 import { safeStringify } from 'src/utils/safeStringify';
 import { logEvent } from 'src/logger/actions';
 import { LOG_ACTIONS_CONFIRM_OVERWRITE_DASHBOARD_METADATA } from 
'src/logger/LogUtils';
-import { areObjectsEqual } from 'src/reduxUtils';
 import { UPDATE_COMPONENTS_PARENTS_LIST } from './dashboardLayout';
 import {
   saveChartConfiguration,
@@ -69,9 +68,10 @@ import getOverwriteItems from '../util/getOverwriteItems';
 import {
   applyColors,
   isLabelsColorMapSynced,
-  getLabelsColorMapEntries,
   getColorSchemeDomain,
   getColorNamespace,
+  getLabelsColorMapEntries,
+  getSharedLabels,
 } from '../../utils/colorScheme';
 
 export const SET_UNSAVED_CHANGES = 'SET_UNSAVED_CHANGES';
@@ -278,8 +278,8 @@ export function saveDashboardRequest(data, id, saveType) {
           : [],
         expanded_slices: data.metadata?.expanded_slices || {},
         label_colors: data.metadata?.label_colors || {},
-        shared_label_colors: getLabelsColorMapEntries(true),
-        full_label_colors: getLabelsColorMapEntries(),
+        shared_label_colors: getSharedLabels(),
+        map_label_colors: getLabelsColorMapEntries(),
         refresh_frequency: data.metadata?.refresh_frequency || 0,
         timed_refresh_immune_slices:
           data.metadata?.timed_refresh_immune_slices || [],
@@ -704,11 +704,19 @@ export const updateDashboardLabelsColor = () => async 
(dispatch, getState) => {
   const defaultScheme = categoricalSchemes.defaultKey;
   const fallbackScheme = defaultScheme?.toString() || 'supersetColors';
   const colorSchemeDomain = metadata?.color_scheme_domain || [];
+  const sharedLabels = metadata?.shared_label_colors;
+  let requiresUpdate = false;
 
   try {
     const updatedMetadata = { ...metadata };
     let updatedScheme = metadata?.color_scheme;
 
+    // sanitize shared labels color map for backward compatibility
+    if (!Array.isArray(sharedLabels) && Object.keys(sharedLabels).length > 0) {
+      updatedMetadata.shared_label_colors = getSharedLabels();
+      requiresUpdate = true;
+    }
+
     // Color scheme does not exist anymore, fallback to default
     if (colorScheme && !colorSchemeRegistry) {
       updatedScheme = fallbackScheme;
@@ -718,6 +726,7 @@ export const updateDashboardLabelsColor = () => async 
(dispatch, getState) => {
       dispatch(setColorScheme(updatedScheme));
       // must re-apply colors from fresh labels color map
       applyColors(updatedMetadata, true);
+      requiresUpdate = true;
     }
 
     // stored labels color map and applied might differ
@@ -729,8 +738,9 @@ export const updateDashboardLabelsColor = () => async 
(dispatch, getState) => {
       // re-apply the color map first
       applyColors(updatedMetadata, false, true, !colorScheme);
       // store the just applied labels color map
-      updatedMetadata.shared_label_colors = getLabelsColorMapEntries(true);
-      updatedMetadata.full_label_colors = getLabelsColorMapEntries();
+      updatedMetadata.shared_label_colors = getSharedLabels();
+      updatedMetadata.map_label_colors = getLabelsColorMapEntries();
+      requiresUpdate = true;
     }
 
     // the stored color domain registry and fresh might differ at this point
@@ -741,23 +751,10 @@ export const updateDashboardLabelsColor = () => async 
(dispatch, getState) => {
 
     if (!isRegistrySynced) {
       updatedMetadata.color_scheme_domain = freshColorSchemeDomain;
+      requiresUpdate = true;
     }
 
-    if (
-      !areObjectsEqual(
-        metadata.color_scheme_domain,
-        updatedMetadata.color_scheme_domain,
-      ) ||
-      !areObjectsEqual(
-        metadata.shared_label_colors,
-        updatedMetadata.shared_label_colors,
-      ) ||
-      !areObjectsEqual(
-        metadata.full_label_colors,
-        updatedMetadata.full_label_colors,
-      ) ||
-      metadata.color_scheme !== updatedMetadata.color_scheme
-    ) {
+    if (requiresUpdate) {
       await updateDashboardMetadata(id, updatedMetadata, dispatch);
     }
   } catch (error) {
diff --git 
a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx 
b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
index f97fff94c8..5b1987937a 100644
--- a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
+++ b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
@@ -196,7 +196,7 @@ const PropertiesModal = ({
       const metaDataCopy = omit(metadata, [
         'positions',
         'shared_label_colors',
-        'full_label_colors',
+        'map_label_colors',
         'color_scheme_domain',
       ]);
 
@@ -334,8 +334,8 @@ const PropertiesModal = ({
     if (metadata?.shared_label_colors) {
       delete metadata.shared_label_colors;
     }
-    if (metadata?.full_label_colors) {
-      delete metadata.full_label_colors;
+    if (metadata?.map_label_colors) {
+      delete metadata.map_label_colors;
     }
     if (metadata?.color_scheme_domain) {
       delete metadata.color_scheme_domain;
diff --git 
a/superset-frontend/src/dashboard/components/SyncDashboardState/index.tsx 
b/superset-frontend/src/dashboard/components/SyncDashboardState/index.tsx
index 0c178df3d8..174ec92d66 100644
--- a/superset-frontend/src/dashboard/components/SyncDashboardState/index.tsx
+++ b/superset-frontend/src/dashboard/components/SyncDashboardState/index.tsx
@@ -66,9 +66,8 @@ const SyncDashboardState: FC<Props> = ({ dashboardPageId }) 
=> {
   >(
     ({ dashboardInfo, dashboardState, nativeFilters, dataMask }) => ({
       labelsColor: dashboardInfo.metadata?.label_colors || EMPTY_OBJECT,
-      labelsColorMap: dashboardInfo.metadata?.full_label_colors || 
EMPTY_OBJECT,
-      sharedLabelsColorMap:
-        dashboardInfo.metadata?.shared_label_colors || EMPTY_OBJECT,
+      labelsColorMap: dashboardInfo.metadata?.map_label_colors || EMPTY_OBJECT,
+      sharedLabelsColors: dashboardInfo.metadata?.shared_label_colors || [],
       colorScheme: dashboardState?.colorScheme,
       chartConfiguration:
         dashboardInfo.metadata?.chart_configuration || EMPTY_OBJECT,
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarSettings/FilterBarSettings.test.tsx
 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarSettings/FilterBarSettings.test.tsx
index 5bdacdec1a..0e52e4def6 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarSettings/FilterBarSettings.test.tsx
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarSettings/FilterBarSettings.test.tsx
@@ -41,8 +41,8 @@ const initialState: { dashboardInfo: DashboardInfo } = {
       color_namespace: '',
       color_scheme_domain: [],
       label_colors: {},
-      shared_label_colors: {},
-      full_label_colors: {},
+      shared_label_colors: [],
+      map_label_colors: {},
       cross_filters_enabled: false,
     },
     json_metadata: '',
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.test.ts
 
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.test.ts
index 60ae8b8e5f..0657e4574c 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.test.ts
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.test.ts
@@ -485,7 +485,7 @@ describe('Ensure buildTree does not throw runtime errors 
when encountering an in
           Sports: '#8FD3E4',
           Strategy: '#A1A6BD',
         },
-        shared_label_colors: {},
+        shared_label_colors: [],
         color_scheme: 'supersetColors',
         extra_filters: [
           {
@@ -710,7 +710,7 @@ describe('Ensure buildTree does not throw runtime errors 
when encountering an in
         queryFields: {
           metric: 'metrics',
         },
-        shared_label_colors: {},
+        shared_label_colors: [],
         color_scheme: 'supersetColors',
         extra_filters: [
           {
@@ -759,7 +759,7 @@ describe('Ensure buildTree does not throw runtime errors 
when encountering an in
             queryFields: {
               metric: 'metrics',
             },
-            shared_label_colors: {},
+            shared_label_colors: [],
             color_scheme: 'supersetColors',
             dashboardId: 9,
             applied_time_extras: {},
@@ -3046,7 +3046,7 @@ describe('Ensure buildTree does not throw runtime errors 
when encountering an in
           groupby: 'groupby',
           metrics: 'metrics',
         },
-        shared_label_colors: {},
+        shared_label_colors: [],
         extra_filters: [
           {
             col: '__time_range',
@@ -3125,7 +3125,7 @@ describe('Ensure buildTree does not throw runtime errors 
when encountering an in
               groupby: 'groupby',
               metrics: 'metrics',
             },
-            shared_label_colors: {},
+            shared_label_colors: [],
             dashboardId: 9,
             applied_time_extras: {},
             where: '',
@@ -16514,7 +16514,7 @@ describe('Ensure buildTree does not throw runtime 
errors when encountering an in
           groupby: 'groupby',
           metrics: 'metrics',
         },
-        shared_label_colors: {},
+        shared_label_colors: [],
         extra_filters: [
           {
             col: '__time_range',
@@ -16661,7 +16661,7 @@ describe('Ensure buildTree does not throw runtime 
errors when encountering an in
               groupby: 'groupby',
               metrics: 'metrics',
             },
-            shared_label_colors: {},
+            shared_label_colors: [],
             dashboardId: 9,
             applied_time_extras: {},
             where: '',
@@ -17523,7 +17523,7 @@ describe('Ensure buildTree does not throw runtime 
errors when encountering an in
           Sports: '#8FD3E4',
           Strategy: '#A1A6BD',
         },
-        shared_label_colors: {},
+        shared_label_colors: [],
         extra_filters: [
           {
             col: '__time_range',
@@ -17678,7 +17678,7 @@ describe('Ensure buildTree does not throw runtime 
errors when encountering an in
           groupby: 'groupby',
           metrics: 'metrics',
         },
-        shared_label_colors: {},
+        shared_label_colors: [],
         extra_filters: [
           {
             col: '__time_range',
@@ -17715,7 +17715,7 @@ describe('Ensure buildTree does not throw runtime 
errors when encountering an in
               groupby: 'groupby',
               metrics: 'metrics',
             },
-            shared_label_colors: {},
+            shared_label_colors: [],
             dashboardId: 9,
             applied_time_extras: {},
             where: '',
diff --git a/superset-frontend/src/dashboard/containers/Chart.jsx 
b/superset-frontend/src/dashboard/containers/Chart.jsx
index 3ea7c807f1..940cdaaa1f 100644
--- a/superset-frontend/src/dashboard/containers/Chart.jsx
+++ b/superset-frontend/src/dashboard/containers/Chart.jsx
@@ -59,10 +59,14 @@ function mapStateToProps(
   const datasource =
     (chart && chart.form_data && datasources[chart.form_data.datasource]) ||
     PLACEHOLDER_DATASOURCE;
-  const { colorScheme: appliedColorScheme, colorNamespace, datasetsStatus } = 
dashboardState;
+  const {
+    colorScheme: appliedColorScheme,
+    colorNamespace,
+    datasetsStatus,
+  } = dashboardState;
   const labelsColor = dashboardInfo?.metadata?.label_colors || {};
-  const labelsColorMap = dashboardInfo?.metadata?.full_label_colors || {};
-  const sharedLabelsColorMap = dashboardInfo?.metadata?.shared_label_colors || 
{};
+  const labelsColorMap = dashboardInfo?.metadata?.map_label_colors || {};
+  const sharedLabelsColors = dashboardInfo?.metadata?.shared_label_colors || 
[];
   const ownColorScheme = chart.form_data?.color_scheme;
   // note: this method caches filters if possible to prevent render cascades
   const formData = getFormDataWithExtraFilters({
@@ -80,7 +84,7 @@ function mapStateToProps(
     extraControls,
     labelsColor,
     labelsColorMap,
-    sharedLabelsColorMap,
+    sharedLabelsColors,
   });
 
   formData.dashboardId = dashboardInfo.id;
diff --git a/superset-frontend/src/dashboard/types.ts 
b/superset-frontend/src/dashboard/types.ts
index 6272c9a055..2b1bbf01e5 100644
--- a/superset-frontend/src/dashboard/types.ts
+++ b/superset-frontend/src/dashboard/types.ts
@@ -132,8 +132,8 @@ export type DashboardInfo = {
     color_namespace: string;
     color_scheme_domain: string[];
     label_colors: JsonObject;
-    shared_label_colors: JsonObject;
-    full_label_colors: JsonObject;
+    shared_label_colors: string[];
+    map_label_colors: JsonObject;
     cross_filters_enabled: boolean;
   };
   crossFiltersEnabled: boolean;
diff --git 
a/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts 
b/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts
index 6f16792ab5..2190318547 100644
--- a/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts
+++ b/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts
@@ -25,6 +25,7 @@ import {
 import { ChartConfiguration, ChartQueryPayload } from 'src/dashboard/types';
 import { getExtraFormData } from 
'src/dashboard/components/nativeFilters/utils';
 import { areObjectsEqual } from 'src/reduxUtils';
+import { isEqual } from 'lodash';
 import getEffectiveExtraFilters from './getEffectiveExtraFilters';
 import { getAllActiveFilters } from '../activeAllDashboardFilters';
 
@@ -46,7 +47,7 @@ export interface GetFormDataWithExtraFiltersArguments {
   extraControls: Record<string, string | boolean | null>;
   labelsColor?: Record<string, string>;
   labelsColorMap?: Record<string, string>;
-  sharedLabelsColorMap?: Record<string, string>;
+  sharedLabelsColors?: string[];
   allSliceIds: number[];
 }
 
@@ -66,7 +67,7 @@ export default function getFormDataWithExtraFilters({
   extraControls,
   labelsColor,
   labelsColorMap,
-  sharedLabelsColorMap,
+  sharedLabelsColors,
   allSliceIds,
 }: GetFormDataWithExtraFiltersArguments) {
   // if dashboard metadata + filters have not changed, use cache if possible
@@ -81,12 +82,10 @@ export default function getFormDataWithExtraFilters({
     areObjectsEqual(cachedFormData?.label_colors, labelsColor, {
       ignoreUndefined: true,
     }) &&
-    areObjectsEqual(cachedFormData?.full_label_colors, labelsColorMap, {
-      ignoreUndefined: true,
-    }) &&
-    areObjectsEqual(cachedFormData?.shared_label_colors, sharedLabelsColorMap, 
{
+    areObjectsEqual(cachedFormData?.map_label_colors, labelsColorMap, {
       ignoreUndefined: true,
     }) &&
+    isEqual(cachedFormData?.shared_label_colors, sharedLabelsColors) &&
     !!cachedFormData &&
     areObjectsEqual(cachedFormData?.dataMask, dataMask, {
       ignoreUndefined: true,
@@ -118,8 +117,8 @@ export default function getFormDataWithExtraFilters({
     ...chart.form_data,
     chart_id: chart.id,
     label_colors: labelsColor,
-    shared_label_colors: sharedLabelsColorMap,
-    full_label_colors: labelsColorMap,
+    shared_label_colors: sharedLabelsColors,
+    map_label_colors: labelsColorMap,
     ...(colorScheme && { color_scheme: colorScheme }),
     ...(ownColorScheme && {
       own_color_scheme: ownColorScheme,
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 70fbb2efe3..264e6968c8 100644
--- 
a/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx
+++ 
b/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx
@@ -29,7 +29,7 @@ import ColorSchemeControl, { ColorSchemes } from '.';
 
 const defaultProps = () => ({
   hasCustomLabelsColor: false,
-  sharedLabelsColor: {},
+  sharedLabelsColors: [],
   label: 'Color scheme',
   labelMargin: 0,
   name: 'color',
@@ -129,8 +129,8 @@ test('displays color scheme options', async () => {
   });
 });
 
-test('Renders control with dashboard id', () => {
-  setup({ dashboardId: 1 });
+test('Renders control with dashboard id and dashboard color scheme', () => {
+  setup({ dashboardId: 1, hasDashboardColorScheme: true });
   expect(screen.getByText('Dashboard scheme')).toBeInTheDocument();
   expect(
     screen.getByLabelText('Select color scheme', { selector: 'input' }),
diff --git 
a/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx
 
b/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx
index 4d296a54d7..9c5734fdbe 100644
--- 
a/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx
+++ 
b/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx
@@ -50,7 +50,7 @@ export interface ColorSchemeControlProps {
   hasCustomLabelsColor: boolean;
   hasDashboardColorScheme?: boolean;
   hasSharedLabelsColor?: boolean;
-  sharedLabelsColor: Record<string, string>;
+  sharedLabelsColors: string[];
   chartId?: number;
   dashboardId?: number;
   label: string;
@@ -125,7 +125,7 @@ const Label = ({
 const ColorSchemeControl = ({
   hasCustomLabelsColor = false,
   hasDashboardColorScheme = false,
-  sharedLabelsColor = {},
+  sharedLabelsColors = [],
   dashboardId,
   chartId,
   label = t('Color scheme'),
@@ -138,7 +138,7 @@ const ColorSchemeControl = ({
   isLinear,
   ...rest
 }: ColorSchemeControlProps) => {
-  const countSharedLabelsColor = Object.keys(sharedLabelsColor).length;
+  const countSharedLabelsColor = sharedLabelsColors.length;
   const colorMapInstance = getLabelsColorMap();
   const chartLabels = chartId
     ? colorMapInstance.chartsLabelsMap.get(chartId)?.labels || []
@@ -146,7 +146,7 @@ const ColorSchemeControl = ({
   const hasSharedLabelsColor = !!(
     dashboardId &&
     countSharedLabelsColor > 0 &&
-    chartLabels.some(label => sharedLabelsColor[label])
+    chartLabels.some(label => sharedLabelsColors.includes(label))
   );
   const hasDashboardScheme = dashboardId && hasDashboardColorScheme;
   const theme = useTheme();
diff --git 
a/superset-frontend/src/explore/controlUtils/getFormDataFromDashboardContext.test.ts
 
b/superset-frontend/src/explore/controlUtils/getFormDataFromDashboardContext.test.ts
index fd120355c8..3dea89148b 100644
--- 
a/superset-frontend/src/explore/controlUtils/getFormDataFromDashboardContext.test.ts
+++ 
b/superset-frontend/src/explore/controlUtils/getFormDataFromDashboardContext.test.ts
@@ -151,10 +151,8 @@ const getExpectedResultFormData = (overrides: JsonObject = 
{}) => ({
     girl: '#FF69B4',
     boy: '#ADD8E6',
   },
-  shared_label_colors: {
-    boy: '#ADD8E6',
-    girl: '#FF69B4',
-  },
+  shared_label_colors: ['boy', 'girl'],
+  own_color_scheme: 'supersetColors',
   extra_filters: [
     {
       col: '__time_range',
diff --git a/superset-frontend/src/pages/Chart/index.tsx 
b/superset-frontend/src/pages/Chart/index.tsx
index 3f061014a6..5bbeb5fa86 100644
--- a/superset-frontend/src/pages/Chart/index.tsx
+++ b/superset-frontend/src/pages/Chart/index.tsx
@@ -102,7 +102,7 @@ const getDashboardContextFormData = () => {
       colorScheme,
       labelsColor,
       labelsColorMap,
-      sharedLabelsColorMap,
+      sharedLabelsColors,
       chartConfiguration,
       nativeFilters,
       filterBoxFilters,
@@ -118,7 +118,7 @@ const getDashboardContextFormData = () => {
       colorScheme,
       labelsColor,
       labelsColorMap,
-      sharedLabelsColorMap,
+      sharedLabelsColors,
       sliceId,
       allSliceIds: [sliceId],
       extraControls: {},
diff --git a/superset-frontend/src/types/DashboardContextForExplore.ts 
b/superset-frontend/src/types/DashboardContextForExplore.ts
index be6fab0157..117a182606 100644
--- a/superset-frontend/src/types/DashboardContextForExplore.ts
+++ b/superset-frontend/src/types/DashboardContextForExplore.ts
@@ -26,7 +26,7 @@ import { ChartConfiguration } from 'src/dashboard/types';
 export interface DashboardContextForExplore {
   labelsColor: Record<string, string>;
   labelsColorMap: Record<string, string>;
-  sharedLabelsColorMap: Record<string, string>;
+  sharedLabelsColors: string[];
   colorScheme: string;
   chartConfiguration: ChartConfiguration;
   nativeFilters: PartialFilters;
diff --git a/superset-frontend/src/utils/colorScheme.ts 
b/superset-frontend/src/utils/colorScheme.ts
index 9905661ed8..3fe50b51c1 100644
--- a/superset-frontend/src/utils/colorScheme.ts
+++ b/superset-frontend/src/utils/colorScheme.ts
@@ -32,42 +32,43 @@ import {
 export const getColorNamespace = (namespace?: string) => namespace || 
undefined;
 
 /**
- * Get the labels color map entries
+ * Get labels shared across multiple charts
  *
- * @param shared - filter out labels not shared across multiple charts
  * @returns Record<string, string>
  */
-export const getLabelsColorMapEntries = (
-  shared = false,
-): Record<string, string> => {
+
+export const getSharedLabels = (): string[] => {
   const labelsColorMapInstance = getLabelsColorMap();
-  const updatedLabelsColorMapEntries = Object.fromEntries(
-    labelsColorMapInstance.getColorMap(),
-  );
-  // filter out all labels that are not shared across multiple charts
   const { chartsLabelsMap } = labelsColorMapInstance;
 
-  if (shared) {
-    const allLabels = new Set<string>();
-    const sharedLabels = new Set<string>();
-    chartsLabelsMap.forEach(({ labels }) => {
-      labels.forEach(label => {
-        if (allLabels.has(label)) {
-          sharedLabels.add(label);
-        }
-        allLabels.add(label);
-      });
+  const allLabels = new Set<string>();
+  const sharedLabels: string[] = [];
+  chartsLabelsMap.forEach(({ labels }) => {
+    labels.forEach(label => {
+      if (allLabels.has(label) && !sharedLabels.includes(label)) {
+        sharedLabels.push(label);
+      }
+      allLabels.add(label);
     });
-    const sharedLabelsColorMapEntries = Object.fromEntries(
-      Object.entries(updatedLabelsColorMapEntries).filter(([label]) =>
-        sharedLabels.has(label),
-      ),
-    );
+  });
 
-    return sharedLabelsColorMapEntries;
-  }
+  return sharedLabels;
+};
 
-  return updatedLabelsColorMapEntries;
+export const getSharedLabelsColorMapEntries = (
+  currentColorMap: Record<string, string>,
+): Record<string, string> => {
+  const sharedLabels = getSharedLabels();
+  return Object.fromEntries(
+    Object.entries(currentColorMap).filter(([label]) =>
+      sharedLabels.includes(label),
+    ),
+  );
+};
+
+export const getLabelsColorMapEntries = (): Record<string, string> => {
+  const labelsColorMapInstance = getLabelsColorMap();
+  return Object.fromEntries(labelsColorMapInstance.getColorMap());
 };
 
 export const getColorSchemeDomain = (colorScheme: string) =>
@@ -82,7 +83,7 @@ export const getColorSchemeDomain = (colorScheme: string) =>
 export const isLabelsColorMapSynced = (
   metadata: Record<string, any>,
 ): boolean => {
-  const currentLabelsColorMap = metadata?.full_label_colors || {};
+  const currentLabelsColorMap = metadata?.map_label_colors || {};
   const customLabelColors = metadata?.label_colors || {};
   const freshLabelsColorMap = getLabelsColorMap().getColorMap();
 
@@ -155,10 +156,20 @@ export const applyColors = (
     CategoricalColorNamespace.getNamespace(colorNameSpace);
   const colorScheme = metadata?.color_scheme;
   const customLabelColors = metadata?.label_colors || {};
-  const sharedLabelsColorMap = metadata?.shared_label_colors || {};
+  const sharedLabels = Array.isArray(metadata?.shared_label_colors)
+    ? metadata.shared_label_colors
+    : getSharedLabels();
+  const fullLabelsColor = metadata?.map_label_colors || {};
+  // filter the fullLabelsColor object to only shared labels
+  const sharedLabelsColors = Object.fromEntries(
+    Object.entries(fullLabelsColor).filter(([label]) =>
+      sharedLabels.includes(label),
+    ),
+  );
+
   const labelsColorMap = shared
-    ? sharedLabelsColorMap
-    : metadata?.full_label_colors || {};
+    ? sharedLabelsColors
+    : metadata?.map_label_colors || {};
 
   if (fresh) {
     // reset custom label colors
@@ -177,7 +188,9 @@ export const applyColors = (
     refreshLabelsColorMap(metadata?.color_namespace, colorScheme, merge);
   }
 
-  const currentColorMapEntries = getLabelsColorMapEntries(shared);
+  const currentColorMapEntries = shared
+    ? getSharedLabelsColorMapEntries(fullLabelsColor)
+    : getLabelsColorMapEntries();
 
   // get the fresh map that was just updated or existing
   const labelsColorMapEntries = fresh
diff --git a/superset/daos/dashboard.py b/superset/daos/dashboard.py
index 2b4fc05d74..d5cc08582c 100644
--- a/superset/daos/dashboard.py
+++ b/superset/daos/dashboard.py
@@ -259,8 +259,8 @@ class DashboardDAO(BaseDAO[Dashboard]):
         md["refresh_frequency"] = data.get("refresh_frequency", 0)
         md["color_scheme"] = data.get("color_scheme", "")
         md["label_colors"] = data.get("label_colors", {})
-        md["shared_label_colors"] = data.get("shared_label_colors", {})
-        md["full_label_colors"] = data.get("full_label_colors", {})
+        md["shared_label_colors"] = data.get("shared_label_colors", [])
+        md["map_label_colors"] = data.get("map_label_colors", {})
         md["color_scheme_domain"] = data.get("color_scheme_domain", [])
         md["cross_filters_enabled"] = data.get("cross_filters_enabled", True)
         dashboard.json_metadata = json.dumps(md)
diff --git a/superset/dashboards/schemas.py b/superset/dashboards/schemas.py
index c501ff3191..2464847bf1 100644
--- a/superset/dashboards/schemas.py
+++ b/superset/dashboards/schemas.py
@@ -137,8 +137,8 @@ class DashboardJSONMetadataSchema(Schema):
     color_namespace = fields.Str(allow_none=True)
     positions = fields.Dict(allow_none=True)
     label_colors = fields.Dict()
-    shared_label_colors = fields.Dict()
-    full_label_colors = fields.Dict()
+    shared_label_colors = fields.List(fields.Str())
+    map_label_colors = fields.Dict()
     color_scheme_domain = fields.List(fields.Str())
     cross_filters_enabled = fields.Boolean(dump_default=True)
     # used for v0 import/export
diff --git a/tests/integration_tests/dashboards/api_tests.py 
b/tests/integration_tests/dashboards/api_tests.py
index df8461814b..cb97eb3f58 100644
--- a/tests/integration_tests/dashboards/api_tests.py
+++ b/tests/integration_tests/dashboards/api_tests.py
@@ -81,7 +81,7 @@ class TestDashboardApi(ApiOwnersTestCaseMixin, 
InsertChartMixin, SupersetTestCas
         "slug": "slug1_changed",
         "position_json": '{"b": "B"}',
         "css": "css_changed",
-        "json_metadata": '{"refresh_frequency": 30, 
"timed_refresh_immune_slices": [], "expanded_slices": {}, "color_scheme": "", 
"label_colors": {}, "shared_label_colors": {}, "full_label_colors": {}, 
"color_scheme_domain": [], "cross_filters_enabled": false}',
+        "json_metadata": '{"refresh_frequency": 30, 
"timed_refresh_immune_slices": [], "expanded_slices": {}, "color_scheme": "", 
"label_colors": {}, "shared_label_colors": [], "map_label_colors": {}, 
"color_scheme_domain": [], "cross_filters_enabled": false}',
         "published": False,
     }
 
diff --git a/tests/unit_tests/fixtures/assets_configs.py 
b/tests/unit_tests/fixtures/assets_configs.py
index bbccdcd179..0bb7e2711e 100644
--- a/tests/unit_tests/fixtures/assets_configs.py
+++ b/tests/unit_tests/fixtures/assets_configs.py
@@ -175,8 +175,8 @@ dashboards_config_1: dict[str, Any] = {
             "color_scheme": "supersetColors",
             "label_colors": {},
             "color_scheme_domain": [],
-            "shared_label_colors": {},
-            "full_label_colors": {},
+            "shared_label_colors": [],
+            "map_label_colors": {},
             "cross_filters_enabled": False,
         },
         "version": "1.0.0",
@@ -252,8 +252,8 @@ dashboards_config_2: dict[str, Any] = {
             "color_scheme": "supersetColors",
             "label_colors": {},
             "color_scheme_domain": [],
-            "shared_label_colors": {},
-            "full_label_colors": {},
+            "shared_label_colors": [],
+            "map_label_colors": {},
         },
         "version": "1.0.0",
     },
diff --git a/tests/unit_tests/security/manager_test.py 
b/tests/unit_tests/security/manager_test.py
index 35cf2d03db..a6022525ac 100644
--- a/tests/unit_tests/security/manager_test.py
+++ b/tests/unit_tests/security/manager_test.py
@@ -750,8 +750,8 @@ def test_query_context_modified_sankey_tampered(mocker: 
MockerFixture) -> None:
         "dashboards": [11],
         "extra_form_data": {},
         "label_colors": {},
-        "shared_label_colors": {},
-        "full_label_colors": {},
+        "shared_label_colors": [],
+        "map_label_colors": {},
         "extra_filters": [],
         "dashboardId": 11,
         "force": False,

Reply via email to