Skip to content
Snippets Groups Projects
Unverified Commit 9eea034b authored by Emmad Usmani's avatar Emmad Usmani Committed by GitHub
Browse files

truncate total text in pie chart (#46466)


* truncate total text in pie chart

* add story

* Update Loki Snapshots

* add e2e test

---------

Co-authored-by: default avatarMetabase Automation <github-automation@metabase.com>
parent fd263907
No related branches found
No related tags found
No related merge requests found
.loki/reference/chrome_laptop_static_viz_PieChart_Truncated_Total.png

37.3 KiB

......@@ -85,6 +85,39 @@ describe("scenarios > visualizations > pie chart", () => {
cy.findByText("TOTAL").should("be.visible");
});
});
it("should truncate the center dimension label if it overflows", () => {
visitQuestionAdhoc({
dataset_query: {
type: "query",
query: {
"source-table": PRODUCTS_ID,
expressions: {
category_foo: [
"concat",
["field", PRODUCTS.CATEGORY, null],
" the quick brown fox jumps over the lazy dog",
],
},
aggregation: [["count"]],
breakout: [["expression", "category_foo"]],
},
database: SAMPLE_DB_ID,
},
display: "pie",
});
// Ensure chart renders before hovering the legend item
cy.findByTestId("query-visualization-root").within(() => {
cy.findByText("TOTAL");
});
cy.findAllByTestId("legend-item").eq(0).realHover();
cy.findByTestId("query-visualization-root").within(() => {
cy.findByText("DOOHICKEY THE QUICK BROWN FOX J…");
});
});
});
function ensurePieChartRendered(rows, totalValue) {
......
......@@ -203,6 +203,13 @@ NumDecimalPlacesLegend.args = {
renderingContext,
};
export const TruncatedTotal = Template.bind({});
TruncatedTotal.args = {
rawSeries: data.truncatedTotal as any,
dashcardSettings: {},
renderingContext,
};
export const UnaggregatedDimension = Template.bind({});
UnaggregatedDimension.args = {
rawSeries: data.unaggregatedDimension as any,
......
......@@ -35,6 +35,7 @@ import singleDimension from "./single-dimension.json";
import smallMinimumSlicePercentage from "./small-min-slice-percentage.json";
import sortedMetricCol from "./sorted-metric-col.json";
import tinySlicesDisappear43766 from "./tiny-slices-disappear-43766.json";
import truncatedTotal from "./truncated-total.json";
import unaggregatedDimension from "./unaggregated-dimension.json";
import zeroMinimumSlicePercentage from "./zero-min-slice-percentage.json";
......@@ -63,6 +64,7 @@ export const data = {
nullDimension,
numDecimalPlacesChart,
numDecimalPlacesLegend,
truncatedTotal,
unaggregatedDimension,
singleDimension,
longDimensionName,
......
[
{
"card": {
"original_card_id": 346,
"public_uuid": null,
"parameter_usage_count": 0,
"created_at": "2024-06-05T23:14:45.449636Z",
"parameters": [],
"metabase_version": "v0.2.0-SNAPSHOT (a727fad)",
"collection": {
"authority_level": null,
"description": null,
"archived": false,
"trashed_from_location": null,
"slug": "pie",
"name": "Pie",
"personal_owner_id": null,
"type": null,
"is_sample": false,
"id": 23,
"entity_id": "hy98llXqY3i_uwtm5ISY_",
"location": "/5/",
"namespace": null,
"is_personal": false,
"created_at": "2024-06-03T19:59:20.91934Z"
},
"visualization_settings": {
"column_settings": {
"[\"name\",\"sum\"]": {
"number_style": "decimal",
"scale": 0.001,
"suffix": " kg",
"prefix": "incredibly super duper long prefix for the weight of this penguin that weighs ",
"decimals": 2
}
}
},
"last-edit-info": {
"id": 1,
"email": "emmad@metabase.com",
"first_name": "Emmad",
"last_name": "Usmani",
"timestamp": "2024-06-05T23:14:45.710965Z"
},
"collection_preview": true,
"entity_id": "-lZmLkBMVbB0U5puWZnOu",
"display": "pie",
"parameter_mappings": [],
"id": 346,
"dataset_query": {
"database": 2,
"type": "query",
"query": {
"aggregation": [
[
"sum",
[
"field",
"body_mass_g",
{
"base-type": "type/Float"
}
]
]
],
"breakout": [
[
"field",
"species",
{
"base-type": "type/Text"
}
]
],
"source-table": "card__92"
}
},
"cache_ttl": null,
"embedding_params": null,
"made_public_by_id": null,
"updated_at": "2024-06-06T00:13:07.782678Z",
"moderation_reviews": [],
"creator_id": 1,
"average_query_time": 319.5882352941176,
"type": "question",
"last_used_at": "2024-06-06T00:13:07.782678Z",
"dashboard_count": 1,
"last_query_start": "2024-06-06T00:13:07.345851Z",
"name": "Pie - Column Settings - Penguins sum of body mass by species",
"query_type": "query",
"collection_id": 23,
"enable_embedding": false,
"database_id": 2,
"trashed_from_collection_id": null,
"can_write": true,
"initially_published_at": null,
"creator": {
"email": "emmad@metabase.com",
"first_name": "Emmad",
"last_login": "2024-06-05T21:21:49.288174Z",
"is_qbnewb": false,
"is_superuser": true,
"id": 1,
"last_name": "Usmani",
"date_joined": "2023-11-21T21:25:41.062104Z",
"common_name": "Emmad Usmani"
},
"result_metadata": [
{
"semantic_type": "type/Category",
"name": "species",
"field_ref": [
"field",
"species",
{
"base-type": "type/Text"
}
],
"effective_type": "type/Text",
"id": 1403,
"visibility_type": "normal",
"display_name": "Species",
"fingerprint": {
"global": {
"distinct-count": 3,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.593023255813954
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Sum of Body Mass G",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"name": "sum",
"base_type": "type/Float",
"effective_type": "type/Float",
"fingerprint": {
"global": {
"distinct-count": 3,
"nil%": 0
},
"type": {
"type/Number": {
"min": 253850,
"q1": 330087.5,
"q3": 607962.5,
"max": 624350,
"sd": 197720.9966088579,
"avg": 479000
}
}
}
}
],
"can_run_adhoc_query": true,
"table_id": 151,
"collection_position": null,
"view_count": 12,
"archived": false,
"description": null,
"cache_invalidated_at": null,
"displayIsLocked": true
},
"data": {
"rows": [
["Adelie", 558800],
["Chinstrap", 253850],
["Gentoo", 624350]
],
"cols": [
{
"database_type": "varchar",
"semantic_type": "type/Category",
"table_id": 151,
"name": "species",
"source": "breakout",
"field_ref": [
"field",
"species",
{
"base-type": "type/Text"
}
],
"effective_type": "type/Text",
"id": 1403,
"position": 1,
"visibility_type": "normal",
"display_name": "Species",
"fingerprint": {
"global": {
"distinct-count": 3,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.593023255813954
}
}
},
"base_type": "type/Text"
},
{
"semantic_type": "type/Quantity",
"base_type": "type/Float",
"name": "sum",
"display_name": "Sum of Body Mass G",
"source": "aggregation",
"field_ref": ["aggregation", 0],
"aggregation_index": 0,
"effective_type": "type/Float"
}
],
"native_form": {
"query": "SELECT \"source\".\"species\" AS \"species\", SUM(\"source\".\"body_mass_g\") AS \"sum\" FROM (SELECT \"csv_upload_data\".\"csv_upload_penguins_20231130074915\".\"id\" AS \"id\", \"csv_upload_data\".\"csv_upload_penguins_20231130074915\".\"species\" AS \"species\", \"csv_upload_data\".\"csv_upload_penguins_20231130074915\".\"island\" AS \"island\", \"csv_upload_data\".\"csv_upload_penguins_20231130074915\".\"bill_length_mm\" AS \"bill_length_mm\", \"csv_upload_data\".\"csv_upload_penguins_20231130074915\".\"bill_depth_mm\" AS \"bill_depth_mm\", \"csv_upload_data\".\"csv_upload_penguins_20231130074915\".\"flipper_length_mm\" AS \"flipper_length_mm\", \"csv_upload_data\".\"csv_upload_penguins_20231130074915\".\"body_mass_g\" AS \"body_mass_g\", \"csv_upload_data\".\"csv_upload_penguins_20231130074915\".\"sex\" AS \"sex\" FROM \"csv_upload_data\".\"csv_upload_penguins_20231130074915\") AS \"source\" GROUP BY \"source\".\"species\" ORDER BY \"source\".\"species\" ASC",
"params": null
},
"dataset": true,
"model": true,
"format-rows?": true,
"results_timezone": "America/Los_Angeles",
"results_metadata": {
"columns": [
{
"semantic_type": "type/Category",
"name": "species",
"field_ref": [
"field",
"species",
{
"base-type": "type/Text"
}
],
"effective_type": "type/Text",
"id": 1403,
"visibility_type": "normal",
"display_name": "Species",
"fingerprint": {
"global": {
"distinct-count": 3,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.593023255813954
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Sum of Body Mass G",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"name": "sum",
"base_type": "type/Float",
"effective_type": "type/Float",
"fingerprint": {
"global": {
"distinct-count": 3,
"nil%": 0
},
"type": {
"type/Number": {
"min": 253850,
"q1": 330087.5,
"q3": 607962.5,
"max": 624350,
"sd": 197720.9966088579,
"avg": 479000
}
}
}
}
]
},
"insights": null
}
}
]
......@@ -2,7 +2,6 @@ import { t } from "ttag";
export const DIMENSIONS = {
maxSideLength: 550,
totalDiameterThreshold: 120,
padding: {
legend: 16,
side: 12,
......@@ -17,6 +16,11 @@ export const DIMENSIONS = {
padding: 4,
},
},
total: {
minWidth: 120,
valueFontSize: 22,
labelFontSize: 14,
},
};
export const SLICE_THRESHOLD = 0.025; // approx 1 degree in percentage
......
......@@ -2,6 +2,7 @@ import Color from "color";
import type { EChartsOption } from "echarts";
import { getTextColorForBackground } from "metabase/lib/colors";
import { truncateText } from "metabase/static-viz/lib/text";
import type {
ComputedVisualizationSettings,
RenderingContext,
......@@ -36,21 +37,27 @@ function getTotalGraphicOption(
let labelText = "";
// Don't display any text if there isn't enough width
const hasSufficientWidth =
outerRadius * 2 >= DIMENSIONS.totalDiameterThreshold;
const hasSufficientWidth = outerRadius * 2 >= DIMENSIONS.total.minWidth;
if (hasSufficientWidth && settings["pie.show_total"]) {
valueText = formatters.formatMetric(
hoveredIndex != null
? chartModel.slices[hoveredIndex].data.displayValue
: chartModel.total,
valueText = truncateText(
formatters.formatMetric(
hoveredIndex != null
? chartModel.slices[hoveredIndex].data.displayValue
: chartModel.total,
),
outerRadius, // innerRadius technically makes more sense, but looks too narrow in practice
DIMENSIONS.total.valueFontSize,
);
labelText =
labelText = truncateText(
hoveredIndex != null
? formatters
.formatDimension(chartModel.slices[hoveredIndex].data.key)
.toUpperCase()
: TOTAL_TEXT;
: TOTAL_TEXT,
outerRadius,
DIMENSIONS.total.labelFontSize,
);
}
return {
......@@ -59,10 +66,11 @@ function getTotalGraphicOption(
left: "center",
children: [
{
// Value
type: "text",
cursor: "text",
style: {
fontSize: "22px",
fontSize: `${DIMENSIONS.total.valueFontSize}px`,
fontWeight: "700",
textAlign: "center",
fontFamily: renderingContext.fontFamily,
......@@ -71,11 +79,12 @@ function getTotalGraphicOption(
},
},
{
// Label
type: "text",
cursor: "text",
top: 26,
style: {
fontSize: "14px",
fontSize: `${DIMENSIONS.total.labelFontSize}px`,
fontWeight: "700",
textAlign: "center",
fontFamily: renderingContext.fontFamily,
......
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