Skip to content
Snippets Groups Projects
Unverified Commit 1bb08949 authored by Aleksandr Lesnenko's avatar Aleksandr Lesnenko Committed by GitHub
Browse files

Fix sunburst color assignment that causes pie chart crashing (#49183)


* pie chart crashes when light or dark accents of instance colors overriden

* Update Loki Snapshots

---------

Co-authored-by: default avatarMetabase Automation <github-automation@metabase.com>
parent 006dbdec
No related branches found
No related tags found
No related merge requests found
Showing
with 102 additions and 37 deletions
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png

63.8 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png

63.7 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png
  • 2-up
  • Swipe
  • Onion skin
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png

67.8 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png

67.8 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -7,6 +7,7 @@ import { ...@@ -7,6 +7,7 @@ import {
cartesianChartCircle, cartesianChartCircle,
chartPathWithFillColor, chartPathWithFillColor,
createQuestion, createQuestion,
describeEE,
echartsContainer, echartsContainer,
editDashboard, editDashboard,
filter, filter,
...@@ -24,9 +25,11 @@ import { ...@@ -24,9 +25,11 @@ import {
saveDashboard, saveDashboard,
saveSavedQuestion, saveSavedQuestion,
selectFilterOperator, selectFilterOperator,
setTokenFeatures,
sidebar, sidebar,
summarize, summarize,
testPairedTooltipValues, testPairedTooltipValues,
updateSetting,
visitAlias, visitAlias,
visitDashboard, visitDashboard,
visitQuestionAdhoc, visitQuestionAdhoc,
...@@ -1207,3 +1210,55 @@ describe("issue 43077", () => { ...@@ -1207,3 +1210,55 @@ describe("issue 43077", () => {
cy.wait(100).then(() => expect(cardRequestSpy).not.to.have.been.called); cy.wait(100).then(() => expect(cardRequestSpy).not.to.have.been.called);
}); });
}); });
describeEE("issue 49160", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
setTokenFeatures("all");
});
it("pie chart should have a placeholder", () => {
visitQuestionAdhoc({
dataset_query: {
type: "query",
query: {
"source-table": PRODUCTS_ID,
},
database: SAMPLE_DB_ID,
},
display: "pie",
});
// Shows pie placeholder
echartsContainer().findByText("18,760").should("be.visible");
cy.findByTestId("qb-header-action-panel").findByText("Summarize").click();
cy.findByLabelText("Rating").click();
echartsContainer().findByText("200").should("be.visible");
echartsContainer().findByText("TOTAL").should("be.visible");
});
it("pie chart should work when instance colors have overrides", () => {
updateSetting("application-colors", { "accent0-light": "#98b4ce" });
visitQuestionAdhoc({
dataset_query: {
type: "query",
query: {
"source-table": PRODUCTS_ID,
aggregation: [["count"]],
breakout: [["field", PRODUCTS.CATEGORY, null]],
},
database: SAMPLE_DB_ID,
},
display: "pie",
});
echartsContainer().findByText("200").should("be.visible");
cy.findByTestId("viz-settings-button").click();
leftSidebar().findByText("Gizmo");
});
});
...@@ -330,11 +330,11 @@ export function getPieChartModel( ...@@ -330,11 +330,11 @@ export function getPieChartModel(
if (!hasMultipleRings) { if (!hasMultipleRings) {
return hexColor; return hexColor;
} }
const accentNumber = hexToAccentColorMap.get(hexColor); const accentKey = hexToAccentColorMap.get(hexColor);
if (accentNumber == null) { if (accentKey == null) {
return hexColor; return hexColor;
} }
return renderingContext.getColor(getRingColorAlias(accentNumber, ring)); return renderingContext.getColor(getRingColorAlias(accentKey, ring));
} }
// Create sliceTree, fill out the innermost slice ring // Create sliceTree, fill out the innermost slice ring
......
import { aliases, colors } from "metabase/lib/colors"; import { aliases, colors } from "metabase/lib/colors";
import { checkNumber } from "metabase/lib/types";
const ACCENT_KEY_PREFIX = "accent"; const ACCENT_KEY_PREFIX = "accent";
type AccentKey = string;
const isAccentColorKey = (key: string) => key.startsWith(ACCENT_KEY_PREFIX);
const extractAccentKey = (input: string): AccentKey => {
const withoutPrefix = input.slice(ACCENT_KEY_PREFIX.length);
return withoutPrefix.split("-")[0] ?? null;
};
export function createHexToAccentNumberMap() { export function createHexToAccentNumberMap() {
const hexToAccentNumber = new Map<string, number>(); const hexToAccentNumber = new Map<string, AccentKey>();
for (const [key, hex] of Object.entries(colors)) { for (const [colorKey, hex] of Object.entries(colors)) {
if (!key.startsWith(ACCENT_KEY_PREFIX)) { if (!isAccentColorKey(colorKey)) {
continue; continue;
} }
const accentKey = extractAccentKey(colorKey);
const accentNumber = checkNumber( if (accentKey) {
Number(key.slice(ACCENT_KEY_PREFIX.length)), hexToAccentNumber.set(hex, accentKey);
); }
hexToAccentNumber.set(hex, accentNumber);
} }
for (const [key, hexGetter] of Object.entries(aliases)) { for (const [colorKey, hexGetter] of Object.entries(aliases)) {
if (!key.startsWith(ACCENT_KEY_PREFIX)) { if (!isAccentColorKey(colorKey)) {
continue; continue;
} }
const accentNumber = checkNumber( const accentKey = extractAccentKey(colorKey);
Number(key.slice(ACCENT_KEY_PREFIX.length, ACCENT_KEY_PREFIX.length + 1)), if (accentKey) {
); hexToAccentNumber.set(hexGetter(colors), accentKey);
const hex = hexGetter(colors); }
hexToAccentNumber.set(hex, accentNumber);
} }
return hexToAccentNumber; return hexToAccentNumber;
} }
export function getRingColorAlias( export function getRingColorAlias(
accentColorNumber: number, accentKey: AccentKey,
ring: "inner" | "middle" | "outer", ring: "inner" | "middle" | "outer",
) { ) {
let suffix = ""; let suffix = "";
...@@ -45,9 +49,9 @@ export function getRingColorAlias( ...@@ -45,9 +49,9 @@ export function getRingColorAlias(
suffix = "-light"; suffix = "-light";
} }
return `${ACCENT_KEY_PREFIX}${accentColorNumber}${suffix}`; return `${ACCENT_KEY_PREFIX}${accentKey}${suffix}`;
} }
export function getPickerColorAlias(accentNumber: number) { export function getPickerColorAlias(accentKey: AccentKey) {
return `${ACCENT_KEY_PREFIX}${accentNumber}-dark`; return `${ACCENT_KEY_PREFIX}${accentKey}-dark`;
} }
...@@ -31,6 +31,8 @@ export function PieChart(props: VisualizationProps) { ...@@ -31,6 +31,8 @@ export function PieChart(props: VisualizationProps) {
onRender, onRender,
isDashboard, isDashboard,
isFullscreen, isFullscreen,
isPlaceholder,
series: transformedSeries,
} = props; } = props;
const hoveredIndex = props.hovered?.index; const hoveredIndex = props.hovered?.index;
const hoveredSliceKeyPath = props.hovered?.pieSliceKeyPath; const hoveredSliceKeyPath = props.hovered?.pieSliceKeyPath;
...@@ -57,22 +59,22 @@ export function PieChart(props: VisualizationProps) { ...@@ -57,22 +59,22 @@ export function PieChart(props: VisualizationProps) {
() => extractRemappings(rawSeries), () => extractRemappings(rawSeries),
[rawSeries], [rawSeries],
); );
const seriesToRender = useMemo(
() => (isPlaceholder ? transformedSeries : rawSeriesWithRemappings),
[isPlaceholder, transformedSeries, rawSeriesWithRemappings],
);
const chartModel = useMemo( const chartModel = useMemo(
() => () =>
getPieChartModel( getPieChartModel(
rawSeriesWithRemappings, seriesToRender,
settings, settings,
Array.from(hiddenSlices), Array.from(hiddenSlices),
renderingContext, renderingContext,
showWarning, showWarning,
), ),
[ [seriesToRender, settings, hiddenSlices, renderingContext, showWarning],
rawSeriesWithRemappings,
settings,
hiddenSlices,
renderingContext,
showWarning,
],
); );
const formatters = useMemo( const formatters = useMemo(
() => getPieChartFormatters(chartModel, settings), () => getPieChartFormatters(chartModel, settings),
......
...@@ -41,11 +41,11 @@ export function PieRowsPicker({ ...@@ -41,11 +41,11 @@ export function PieRowsPicker({
if (!hasMultipleRings || hexColor == null) { if (!hasMultipleRings || hexColor == null) {
return hexColor; return hexColor;
} }
const accentNumber = hexToAccentNumberMap.get(hexColor); const accentKey = hexToAccentNumberMap.get(hexColor);
if (accentNumber == null) { if (accentKey == null) {
return hexColor; return hexColor;
} }
return color(getPickerColorAlias(accentNumber)); return color(getPickerColorAlias(accentKey));
}; };
const onChangeSeriesColor = (sliceKey: string, color: string) => const onChangeSeriesColor = (sliceKey: string, color: string) =>
......
...@@ -77,7 +77,11 @@ export const PIE_CHART_DEFINITION: VisualizationDefinition = { ...@@ -77,7 +77,11 @@ export const PIE_CHART_DEFINITION: VisualizationDefinition = {
if (rows.length < 1) { if (rows.length < 1) {
throw new MinRowsError(1, 0); throw new MinRowsError(1, 0);
} }
if (!settings["pie.dimension"] || !settings["pie.metric"]) { const isDimensionMissing =
!settings["pie.dimension"] ||
(Array.isArray(settings["pie.dimension"]) &&
settings["pie.dimension"].every(col => col == null));
if (isDimensionMissing || !settings["pie.metric"]) {
throw new ChartSettingsError(t`Which columns do you want to use?`, { throw new ChartSettingsError(t`Which columns do you want to use?`, {
section: `Data`, section: `Data`,
}); });
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment