Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Color consistency #17089

Merged
merged 31 commits into from
Nov 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c01c940
Update label colors on the fly
geido Sep 8, 2021
df8d585
Clean up
geido Sep 8, 2021
8b60722
Improve getFormDataWithExtraFilters
geido Sep 8, 2021
92c4829
Merge branch 'master' of https://github.com/apache/superset into fix/…
geido Oct 7, 2021
f284259
Improve code structure
geido Oct 7, 2021
69b7b62
Remove labelColors from formData
geido Oct 7, 2021
1c24ec5
Merge branch 'master' of https://github.com/apache/superset into fix/…
geido Oct 8, 2021
3f9ea84
Exclude label_colors from URL
geido Oct 8, 2021
70b477e
Refactor color scheme implementation
geido Oct 13, 2021
600e1e2
Clean up
geido Oct 13, 2021
c97cbc3
Refactor and simplify
geido Oct 15, 2021
bf1e1fb
Merge branch 'master' of https://github.com/apache/superset into fix/…
geido Oct 15, 2021
13aacf1
Fix lint
geido Oct 15, 2021
eb4b85a
Merge with latest changes
geido Oct 18, 2021
8b94bfe
Remove unnecessary ColorMapControl
geido Oct 18, 2021
0f408db
Merge branch 'master' of https://github.com/apache/superset into fix/…
geido Oct 20, 2021
5eb2e5a
Merge
geido Oct 26, 2021
a327e74
Lint
geido Oct 26, 2021
c70d6ba
Give json color scheme precedence
geido Oct 26, 2021
40640c7
Add label_colors prop in metadata
geido Oct 27, 2021
3520606
Merge branch 'master' of https://github.com/apache/superset into fix/…
geido Nov 2, 2021
56d9bc8
Separate owners and dashboard meta requests
geido Nov 2, 2021
81359c2
Remove label_colors control
geido Nov 3, 2021
f24d57e
bump superset-ui 0.18.19
geido Nov 3, 2021
dfe719b
Merge branch 'master' of https://github.com/apache/superset into fix/…
geido Nov 3, 2021
98650af
Fix end of file
geido Nov 3, 2021
3988496
Update tests
geido Nov 3, 2021
364e39b
Fix lint
geido Nov 3, 2021
65ba985
Update Cypress
geido Nov 3, 2021
3fccee6
Update setColorScheme method
geido Nov 3, 2021
acacba5
Use Antd modal body
geido Nov 3, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';

function selectColorScheme(color: string) {
// open color scheme dropdown
cy.get('.modal-body')
.contains('Color Scheme')
cy.get('.ant-modal-body')
.contains('Color scheme')
.parents('.ControlHeader')
.next('.Select')
.next('.ant-select')
.click()
.then($colorSelect => {
// select a new color scheme
Expand All @@ -37,7 +37,7 @@ function selectColorScheme(color: string) {

function assertMetadata(text: string) {
const regex = new RegExp(text);
cy.get('.modal-body')
cy.get('.ant-modal-body')
.find('#json_metadata')
.should('be.visible')
.then(() => {
Expand All @@ -50,12 +50,15 @@ function assertMetadata(text: string) {
}

function typeMetadata(text: string) {
cy.get('.modal-body').find('#json_metadata').should('be.visible').type(text);
cy.get('.ant-modal-body')
.find('#json_metadata')
.should('be.visible')
.type(text);
}

function openAdvancedProperties() {
return cy
.get('.modal-body')
.get('.ant-modal-body')
.contains('Advanced')
.should('be.visible')
.click();
Expand Down Expand Up @@ -94,6 +97,10 @@ describe('Dashboard edit action', () => {
.get('[data-test="dashboard-title-input"]')
.type(`{selectall}{backspace}${dashboardTitle}`);

cy.wait('@dashboardGet').then(() => {
selectColorScheme('d3Category20b');
});

// save edit changes
cy.get('.ant-modal-footer')
.contains('Save')
Expand Down Expand Up @@ -146,7 +153,7 @@ describe('Dashboard edit action', () => {
.click()
.then(() => {
// assert that modal edit window has closed
cy.get('.modal-body').should('not.exist');
cy.get('.ant-modal-body').should('not.exist');

// assert color has been updated
openDashboardEditProperties();
Expand Down Expand Up @@ -177,7 +184,7 @@ describe('Dashboard edit action', () => {
.click()
.then(() => {
// assert that modal edit window has closed
cy.get('.modal-body')
cy.get('.ant-modal-body')
.contains('A valid color scheme is required')
.should('be.visible');
});
Expand Down
604 changes: 302 additions & 302 deletions superset-frontend/package-lock.json

Large diffs are not rendered by default.

56 changes: 28 additions & 28 deletions superset-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,35 +68,35 @@
"@emotion/cache": "^11.4.0",
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@superset-ui/chart-controls": "^0.18.18",
"@superset-ui/core": "^0.18.18",
"@superset-ui/legacy-plugin-chart-calendar": "^0.18.18",
"@superset-ui/legacy-plugin-chart-chord": "^0.18.18",
"@superset-ui/legacy-plugin-chart-country-map": "^0.18.18",
"@superset-ui/legacy-plugin-chart-event-flow": "^0.18.18",
"@superset-ui/legacy-plugin-chart-force-directed": "^0.18.18",
"@superset-ui/legacy-plugin-chart-heatmap": "^0.18.18",
"@superset-ui/legacy-plugin-chart-histogram": "^0.18.18",
"@superset-ui/legacy-plugin-chart-horizon": "^0.18.18",
"@superset-ui/legacy-plugin-chart-map-box": "^0.18.18",
"@superset-ui/legacy-plugin-chart-paired-t-test": "^0.18.18",
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.18.18",
"@superset-ui/legacy-plugin-chart-partition": "^0.18.18",
"@superset-ui/legacy-plugin-chart-pivot-table": "^0.18.18",
"@superset-ui/legacy-plugin-chart-rose": "^0.18.18",
"@superset-ui/legacy-plugin-chart-sankey": "^0.18.18",
"@superset-ui/legacy-plugin-chart-sankey-loop": "^0.18.18",
"@superset-ui/legacy-plugin-chart-sunburst": "^0.18.18",
"@superset-ui/legacy-plugin-chart-treemap": "^0.18.18",
"@superset-ui/legacy-plugin-chart-world-map": "^0.18.18",
"@superset-ui/legacy-preset-chart-big-number": "^0.18.18",
"@superset-ui/chart-controls": "^0.18.19",
"@superset-ui/core": "^0.18.19",
"@superset-ui/legacy-plugin-chart-calendar": "^0.18.19",
"@superset-ui/legacy-plugin-chart-chord": "^0.18.19",
"@superset-ui/legacy-plugin-chart-country-map": "^0.18.19",
"@superset-ui/legacy-plugin-chart-event-flow": "^0.18.19",
"@superset-ui/legacy-plugin-chart-force-directed": "^0.18.19",
"@superset-ui/legacy-plugin-chart-heatmap": "^0.18.19",
"@superset-ui/legacy-plugin-chart-histogram": "^0.18.19",
"@superset-ui/legacy-plugin-chart-horizon": "^0.18.19",
"@superset-ui/legacy-plugin-chart-map-box": "^0.18.19",
"@superset-ui/legacy-plugin-chart-paired-t-test": "^0.18.19",
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.18.19",
"@superset-ui/legacy-plugin-chart-partition": "^0.18.19",
"@superset-ui/legacy-plugin-chart-pivot-table": "^0.18.19",
"@superset-ui/legacy-plugin-chart-rose": "^0.18.19",
"@superset-ui/legacy-plugin-chart-sankey": "^0.18.19",
"@superset-ui/legacy-plugin-chart-sankey-loop": "^0.18.19",
"@superset-ui/legacy-plugin-chart-sunburst": "^0.18.19",
"@superset-ui/legacy-plugin-chart-treemap": "^0.18.19",
"@superset-ui/legacy-plugin-chart-world-map": "^0.18.19",
"@superset-ui/legacy-preset-chart-big-number": "^0.18.19",
"@superset-ui/legacy-preset-chart-deckgl": "^0.4.13",
"@superset-ui/legacy-preset-chart-nvd3": "^0.18.18",
"@superset-ui/plugin-chart-echarts": "^0.18.18",
"@superset-ui/plugin-chart-pivot-table": "^0.18.18",
"@superset-ui/plugin-chart-table": "^0.18.18",
"@superset-ui/plugin-chart-word-cloud": "^0.18.18",
"@superset-ui/preset-chart-xy": "^0.18.18",
"@superset-ui/legacy-preset-chart-nvd3": "^0.18.19",
"@superset-ui/plugin-chart-echarts": "^0.18.19",
"@superset-ui/plugin-chart-pivot-table": "^0.18.19",
"@superset-ui/plugin-chart-table": "^0.18.19",
"@superset-ui/plugin-chart-word-cloud": "^0.18.19",
"@superset-ui/preset-chart-xy": "^0.18.19",
"@vx/responsive": "^0.0.195",
"abortcontroller-polyfill": "^1.1.9",
"antd": "^4.9.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,12 @@ describe('PropertiesModal', () => {
describe('without metadata', () => {
const wrapper = setup({ colorScheme: 'SUPERSET_DEFAULT' });
const modalInstance = wrapper.find('PropertiesModal').instance();
it('does not update the color scheme in the metadata', () => {
it('updates the color scheme in the metadata', () => {
const spy = jest.spyOn(modalInstance, 'onMetadataChange');
modalInstance.onColorSchemeChange('SUPERSET_DEFAULT');
expect(spy).not.toHaveBeenCalled();
expect(spy).toHaveBeenCalledWith(
'{"something": "foo", "color_scheme": "SUPERSET_DEFAULT", "label_colors": {}}',
);
});
});
describe('with metadata', () => {
Expand Down Expand Up @@ -125,10 +127,12 @@ describe('PropertiesModal', () => {
json_metadata: '{"timed_refresh_immune_slices": []}',
},
});
it('will not update the metadata', () => {
it('will update the metadata', () => {
const spy = jest.spyOn(modalInstance, 'onMetadataChange');
modalInstance.onColorSchemeChange('SUPERSET_DEFAULT');
expect(spy).not.toHaveBeenCalled();
expect(spy).toHaveBeenCalledWith(
'{"something": "foo", "color_scheme": "SUPERSET_DEFAULT", "label_colors": {}}',
);
});
});
});
Expand Down
1 change: 1 addition & 0 deletions superset-frontend/src/chart/Chart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const propTypes = {
// formData contains chart's own filter parameter
// and merged with extra filter that current dashboard applying
formData: PropTypes.object.isRequired,
labelColors: PropTypes.object,
width: PropTypes.number,
height: PropTypes.number,
setControlValue: PropTypes.func,
Expand Down
2 changes: 2 additions & 0 deletions superset-frontend/src/chart/ChartRenderer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const propTypes = {
datasource: PropTypes.object,
initialValues: PropTypes.object,
formData: PropTypes.object.isRequired,
labelColors: PropTypes.object,
height: PropTypes.number,
width: PropTypes.number,
setControlValue: PropTypes.func,
Expand Down Expand Up @@ -100,6 +101,7 @@ class ChartRenderer extends React.Component {
nextProps.height !== this.props.height ||
nextProps.width !== this.props.width ||
nextProps.triggerRender ||
nextProps.labelColors !== this.props.labelColors ||
nextProps.formData.color_scheme !== this.props.formData.color_scheme ||
nextProps.cacheBusterProp !== this.props.cacheBusterProp
);
Expand Down
21 changes: 20 additions & 1 deletion superset-frontend/src/dashboard/actions/dashboardInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,32 @@
* under the License.
*/
import { Dispatch } from 'redux';
import { makeApi } from '@superset-ui/core';
import { makeApi, CategoricalColorNamespace } from '@superset-ui/core';
import { isString } from 'lodash';
import { ChartConfiguration, DashboardInfo } from '../reducers/types';

export const DASHBOARD_INFO_UPDATED = 'DASHBOARD_INFO_UPDATED';

// updates partially changed dashboard info
export function dashboardInfoChanged(newInfo: { metadata: any }) {
const { metadata } = newInfo;

const categoricalNamespace = CategoricalColorNamespace.getNamespace(
metadata?.color_namespace,
);

categoricalNamespace.resetColors();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that in superset-frontend/src/dashboard/actions/hydrate.js you're not calling resetColors before setting the colors. Is it ok or do we need to change something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. Resetting the colors is only useful when the colors of the label change or are removed. This is only the case here. As for the QA approval, we will need to discuss how is best to proceed as this requires potentially disruptive changes in Superset-UI.


if (metadata?.label_colors) {
const labelColors = metadata.label_colors;
const colorMap = isString(labelColors)
? JSON.parse(labelColors)
: labelColors;
Object.keys(colorMap).forEach(label => {
categoricalNamespace.setColor(label, colorMap[label]);
});
}

return { type: DASHBOARD_INFO_UPDATED, newInfo };
}
export const SET_CHART_CONFIG_BEGIN = 'SET_CHART_CONFIG_BEGIN';
Expand Down
10 changes: 5 additions & 5 deletions superset-frontend/src/dashboard/actions/hydrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,16 @@ export const hydrateDashboard = (dashboardData, chartData) => (
// Priming the color palette with user's label-color mapping provided in
// the dashboard's JSON metadata
if (metadata?.label_colors) {
const scheme = metadata.color_scheme;
const namespace = metadata.color_namespace;
const colorMap = isString(metadata.label_colors)
? JSON.parse(metadata.label_colors)
: metadata.label_colors;
const categoricalNamespace = CategoricalColorNamespace.getNamespace(
namespace,
);

Object.keys(colorMap).forEach(label => {
CategoricalColorNamespace.getScale(scheme, namespace).setColor(
label,
colorMap[label],
);
categoricalNamespace.setColor(label, colorMap[label]);
});
}

Expand Down
19 changes: 5 additions & 14 deletions superset-frontend/src/dashboard/components/Header/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import moment from 'moment';
import React from 'react';
import PropTypes from 'prop-types';
import { styled, CategoricalColorNamespace, t } from '@superset-ui/core';
import { styled, t } from '@superset-ui/core';
import ButtonGroup from 'src/components/ButtonGroup';

import {
Expand Down Expand Up @@ -348,19 +348,10 @@ class Header extends React.PureComponent {
lastModifiedTime,
} = this.props;

const scale = CategoricalColorNamespace.getScale(
colorScheme,
colorNamespace,
);

// use the colorScheme for default labels
let labelColors = colorScheme ? scale.getColorMap() : {};
// but allow metadata to overwrite if it exists
// eslint-disable-next-line camelcase
const metadataLabelColors = dashboardInfo.metadata?.label_colors;
if (metadataLabelColors) {
labelColors = { ...labelColors, ...metadataLabelColors };
}
const labelColors =
colorScheme && dashboardInfo?.metadata?.label_colors
? dashboardInfo.metadata.label_colors
: {};

// check refresh frequency is for current session or persist
const refreshFrequency = shouldPersistRefreshFrequency
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
t,
SupersetClient,
getCategoricalSchemeRegistry,
CategoricalColorNamespace,
} from '@superset-ui/core';

import Modal from 'src/components/Modal';
Expand Down Expand Up @@ -140,14 +139,15 @@ class PropertiesModal extends React.PureComponent {
JsonEditor.preload();
}

onColorSchemeChange(value, { updateMetadata = true } = {}) {
onColorSchemeChange(colorScheme, { updateMetadata = true } = {}) {
// check that color_scheme is valid
const colorChoices = getCategoricalSchemeRegistry().keys();
const { json_metadata: jsonMetadata } = this.state.values;
const jsonMetadataObj = jsonMetadata?.length
? JSON.parse(jsonMetadata)
: {};
if (!colorChoices.includes(value)) {

if (!colorScheme || !colorChoices.includes(colorScheme)) {
Modal.error({
title: 'Error',
content: t('A valid color scheme is required'),
Expand All @@ -157,24 +157,14 @@ class PropertiesModal extends React.PureComponent {
}

// update metadata to match selection
if (
updateMetadata &&
Object.keys(jsonMetadataObj).includes('color_scheme')
) {
jsonMetadataObj.color_scheme = value;
jsonMetadataObj.label_colors = Object.keys(
jsonMetadataObj.label_colors ?? {},
).reduce(
(prev, next) => ({
...prev,
[next]: CategoricalColorNamespace.getScale(value)(next),
}),
{},
);
if (updateMetadata) {
jsonMetadataObj.color_scheme = colorScheme;
jsonMetadataObj.label_colors = jsonMetadataObj.label_colors || {};

this.onMetadataChange(jsonStringify(jsonMetadataObj));
}

this.updateFormState('colorScheme', value);
this.updateFormState('colorScheme', colorScheme);
}

onOwnersChange(value) {
Expand Down Expand Up @@ -261,21 +251,22 @@ class PropertiesModal extends React.PureComponent {
roles: rolesValue,
},
} = this.state;

const { onlyApply } = this.props;
const owners = ownersValue?.map(o => o.value) ?? [];
const roles = rolesValue?.map(o => o.value) ?? [];
let metadataColorScheme;
let currentColorScheme = colorScheme;

// update color scheme to match metadata
// color scheme in json metadata has precedence over selection
if (jsonMetadata?.length) {
const { color_scheme: metadataColorScheme } = JSON.parse(jsonMetadata);
if (metadataColorScheme) {
this.onColorSchemeChange(metadataColorScheme, {
updateMetadata: false,
});
}
const metadata = JSON.parse(jsonMetadata);
currentColorScheme = metadata?.color_scheme || colorScheme;
}

this.onColorSchemeChange(currentColorScheme, {
updateMetadata: false,
});

const moreProps = {};
const morePutProps = {};
if (isFeatureEnabled(FeatureFlag.DASHBOARD_RBAC)) {
Expand All @@ -289,7 +280,7 @@ class PropertiesModal extends React.PureComponent {
slug,
jsonMetadata,
ownerIds: owners,
colorScheme: metadataColorScheme || colorScheme,
colorScheme: currentColorScheme,
...moreProps,
});
this.props.onHide();
Expand All @@ -316,7 +307,7 @@ class PropertiesModal extends React.PureComponent {
slug: result.slug,
jsonMetadata: result.json_metadata,
ownerIds: result.owners,
colorScheme: metadataColorScheme || colorScheme,
colorScheme: currentColorScheme,
...moreResultProps,
});
this.props.onHide();
Expand Down