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

add pie.decimal_places setting (#46397)


* add pie.decimal_places setting

* add unit spec

* add stories

* Update Loki Snapshots

* add placeholder text

---------

Co-authored-by: default avatarMetabase Automation <github-automation@metabase.com>
parent cffca8af
No related branches found
No related tags found
No related merge requests found
Showing
with 716 additions and 9 deletions
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png

56 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png

55.9 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png
  • 2-up
  • Swipe
  • Onion skin
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png

55.5 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png

55.4 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png
  • 2-up
  • Swipe
  • Onion skin
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png

17.5 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png

17.4 KiB | W: | H:

.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png
  • 2-up
  • Swipe
  • Onion skin
.loki/reference/chrome_laptop_static_viz_PieChart_Num_Decimal_Places_Chart.png

65.8 KiB

.loki/reference/chrome_laptop_static_viz_PieChart_Num_Decimal_Places_Legend.png

66.4 KiB

...@@ -196,6 +196,7 @@ export type VisualizationSettings = { ...@@ -196,6 +196,7 @@ export type VisualizationSettings = {
"pie.show_legend"?: boolean; "pie.show_legend"?: boolean;
"pie.show_total"?: boolean; "pie.show_total"?: boolean;
"pie.percent_visibility"?: "off" | "legend" | "inside"; "pie.percent_visibility"?: "off" | "legend" | "inside";
"pie.decimal_places"?: number;
"pie.slice_threshold"?: number; "pie.slice_threshold"?: number;
"pie.colors"?: Record<string, string>; "pie.colors"?: Record<string, string>;
......
...@@ -182,6 +182,20 @@ NullDimension.args = { ...@@ -182,6 +182,20 @@ NullDimension.args = {
renderingContext, renderingContext,
}; };
export const NumDecimalPlacesChart = Template.bind({});
NumDecimalPlacesChart.args = {
rawSeries: data.numDecimalPlacesChart as any,
dashcardSettings: {},
renderingContext,
};
export const NumDecimalPlacesLegend = Template.bind({});
NumDecimalPlacesLegend.args = {
rawSeries: data.numDecimalPlacesLegend as any,
dashcardSettings: {},
renderingContext,
};
export const UnaggregatedDimension = Template.bind({}); export const UnaggregatedDimension = Template.bind({});
UnaggregatedDimension.args = { UnaggregatedDimension.args = {
rawSeries: data.unaggregatedDimension as any, rawSeries: data.unaggregatedDimension as any,
......
...@@ -21,6 +21,8 @@ import missingLabelLargeSlice38424 from "./missing-label-large-slice-38424.json" ...@@ -21,6 +21,8 @@ import missingLabelLargeSlice38424 from "./missing-label-large-slice-38424.json"
import mixedPostiiveNegative from "./mixed-positive-negative.json"; import mixedPostiiveNegative from "./mixed-positive-negative.json";
import noSingleColumnLegend45149 from "./no-single-column-legend-45149.json"; import noSingleColumnLegend45149 from "./no-single-column-legend-45149.json";
import nullDimension from "./null-dimension.json"; import nullDimension from "./null-dimension.json";
import numDecimalPlacesChart from "./num-decimal-places-chart.json";
import numDecimalPlacesLegend from "./num-decimal-places-legend.json";
import numericDimension from "./numeric-dimension.json"; import numericDimension from "./numeric-dimension.json";
import numericSQLColumnCrashes28568 from "./numeric-sql-column-crashes-28568.json"; import numericSQLColumnCrashes28568 from "./numeric-sql-column-crashes-28568.json";
import percentagesOnChartBooleanDimensionCrashes44085 from "./percentages-on-chart-boolean-dimension-crashes-44085.json"; import percentagesOnChartBooleanDimensionCrashes44085 from "./percentages-on-chart-boolean-dimension-crashes-44085.json";
...@@ -57,6 +59,8 @@ export const data = { ...@@ -57,6 +59,8 @@ export const data = {
dateDimension, dateDimension,
relativeDateDimension, relativeDateDimension,
nullDimension, nullDimension,
numDecimalPlacesChart,
numDecimalPlacesLegend,
unaggregatedDimension, unaggregatedDimension,
singleDimension, singleDimension,
longDimensionName, longDimensionName,
......
[
{
"card": {
"original_card_id": 398,
"can_delete": false,
"public_uuid": null,
"parameter_usage_count": 0,
"created_at": "2024-08-01T21:22:49.134055Z",
"parameters": [],
"metabase_version": "v0.1.26-SNAPSHOT (7892978)",
"collection": {
"authority_level": null,
"description": null,
"archived": false,
"trashed_from_location": null,
"slug": "pie",
"archive_operation_id": null,
"name": "Pie",
"personal_owner_id": null,
"type": null,
"is_sample": false,
"id": 23,
"archived_directly": null,
"entity_id": "hy98llXqY3i_uwtm5ISY_",
"location": "/5/",
"namespace": null,
"is_personal": false,
"created_at": "2024-06-03T19:59:20.91934Z"
},
"visualization_settings": {
"pie.percent_visibility": "inside",
"pie.decimal_places": 2,
"pie.slice_threshold": 2.5
},
"last-edit-info": {
"id": 1,
"email": "emmad@metabase.com",
"first_name": "Emmad",
"last_name": "Usmani",
"timestamp": "2024-08-01T21:22:49.387375Z"
},
"collection_preview": true,
"entity_id": "ihJeRTVb-c1uOA9nz6mqI",
"archived_directly": false,
"display": "pie",
"parameter_mappings": [],
"id": 398,
"dataset_query": {
"database": 2,
"type": "query",
"query": {
"aggregation": [["count"]],
"breakout": [
[
"field",
"platform",
{
"base-type": "type/Text"
}
]
],
"source-table": "card__77"
}
},
"cache_ttl": null,
"embedding_params": null,
"made_public_by_id": null,
"updated_at": "2024-08-01T21:59:42.979845Z",
"moderation_reviews": [],
"can_restore": false,
"creator_id": 1,
"average_query_time": 428.6666666666667,
"type": "question",
"last_used_at": "2024-08-01T21:59:25.328312Z",
"dashboard_count": 2,
"last_query_start": "2024-08-01T21:59:25.079201Z",
"name": "Pie - Number of Decimal Places Chart - Metacritic Games by platform",
"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-07-18T22:43:41.982476Z",
"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": "platform",
"field_ref": [
"field",
"platform",
{
"base-type": "type/Text"
}
],
"effective_type": "type/Text",
"id": 1352,
"visibility_type": "normal",
"display_name": "Platform",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.5754
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Count",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"base_type": "type/BigInteger",
"effective_type": "type/BigInteger",
"name": "count",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Number": {
"min": 2,
"q1": 186,
"q3": 1122,
"max": 4592,
"sd": 1015.5250832969095,
"avg": 815.6363636363636
}
}
}
}
],
"can_run_adhoc_query": true,
"table_id": 143,
"collection_position": null,
"view_count": 6,
"archived": false,
"description": null,
"cache_invalidated_at": null,
"displayIsLocked": true
},
"data": {
"rows": [
["3DS", 400],
["DS", 730],
["Dreamcast", 125],
["GameBoyAdvance", 444],
["GameCube", 452],
["Nintendo64", 70],
["PC", 4592],
["PSP", 513],
["PlayStation", 188],
["PlayStation2", 1418],
["PlayStation3", 1269],
["PlayStation4", 1928],
["PlayStation5", 3],
["PlayStationVita", 257],
["Stadia", 4],
["Switch", 1122],
["Wii", 664],
["WiiU", 186],
["Xbox", 793],
["Xbox360", 1666],
["XboxOne", 1118],
["XboxSeriesX", 2]
],
"cols": [
{
"database_type": "varchar",
"semantic_type": "type/Category",
"table_id": 143,
"name": "platform",
"source": "breakout",
"field_ref": [
"field",
"platform",
{
"base-type": "type/Text"
}
],
"effective_type": "type/Text",
"id": 1352,
"position": 2,
"visibility_type": "normal",
"display_name": "Platform",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.5754
}
}
},
"base_type": "type/Text"
},
{
"database_type": "int8",
"semantic_type": "type/Quantity",
"name": "count",
"source": "aggregation",
"field_ref": ["aggregation", 0],
"effective_type": "type/BigInteger",
"aggregation_index": 0,
"display_name": "Count",
"base_type": "type/BigInteger"
}
],
"native_form": {
"query": "SELECT \"source\".\"platform\" AS \"platform\", COUNT(*) AS \"count\" FROM (SELECT \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"id\" AS \"id\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"name\" AS \"name\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"platform\" AS \"platform\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"r_date\" AS \"r_date\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"score\" AS \"score\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"user_score\" AS \"user_score\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"developer\" AS \"developer\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"genre\" AS \"genre\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"players\" AS \"players\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"critics\" AS \"critics\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"users\" AS \"users\" FROM \"csv_upload_data\".\"csv_upload_games_20231121140652\") AS \"source\" GROUP BY \"source\".\"platform\" ORDER BY \"source\".\"platform\" ASC",
"params": null
},
"dataset": true,
"model": true,
"format-rows?": true,
"results_timezone": "America/Los_Angeles",
"results_metadata": {
"columns": [
{
"semantic_type": "type/Category",
"name": "platform",
"field_ref": [
"field",
"platform",
{
"base-type": "type/Text"
}
],
"effective_type": "type/Text",
"id": 1352,
"visibility_type": "normal",
"display_name": "Platform",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.5754
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Count",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"base_type": "type/BigInteger",
"effective_type": "type/BigInteger",
"name": "count",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Number": {
"min": 2,
"q1": 186,
"q3": 1122,
"max": 4592,
"sd": 1015.5250832969095,
"avg": 815.6363636363636
}
}
}
}
]
},
"insights": null
}
}
]
[
{
"card": {
"original_card_id": 399,
"can_delete": false,
"public_uuid": null,
"parameter_usage_count": 0,
"created_at": "2024-08-01T21:23:56.967417Z",
"parameters": [],
"metabase_version": "v0.1.26-SNAPSHOT (7892978)",
"collection": {
"authority_level": null,
"description": null,
"archived": false,
"trashed_from_location": null,
"slug": "pie",
"archive_operation_id": null,
"name": "Pie",
"personal_owner_id": null,
"type": null,
"is_sample": false,
"id": 23,
"archived_directly": null,
"entity_id": "hy98llXqY3i_uwtm5ISY_",
"location": "/5/",
"namespace": null,
"is_personal": false,
"created_at": "2024-06-03T19:59:20.91934Z"
},
"visualization_settings": {
"pie.percent_visibility": "legend",
"pie.slice_threshold": 2.5,
"pie.decimal_places": 4
},
"last-edit-info": {
"id": 1,
"email": "emmad@metabase.com",
"first_name": "Emmad",
"last_name": "Usmani",
"timestamp": "2024-08-01T21:23:57.177037Z"
},
"collection_preview": true,
"entity_id": "a58QVQk3JMHDLyD3DbOfc",
"archived_directly": false,
"display": "pie",
"parameter_mappings": [],
"id": 399,
"dataset_query": {
"database": 2,
"type": "query",
"query": {
"aggregation": [["count"]],
"breakout": [
[
"field",
"platform",
{
"base-type": "type/Text"
}
]
],
"source-table": "card__77"
}
},
"cache_ttl": null,
"embedding_params": null,
"made_public_by_id": null,
"updated_at": "2024-08-01T21:57:01.087959Z",
"moderation_reviews": [],
"can_restore": false,
"creator_id": 1,
"average_query_time": 357.6666666666667,
"type": "question",
"last_used_at": "2024-08-01T21:56:46.222032Z",
"dashboard_count": 1,
"last_query_start": "2024-08-01T21:56:45.945356Z",
"name": "Pie - Number of Decimal Places Legend - Metacritic Games by platform - Modified",
"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-07-18T22:43:41.982476Z",
"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": "platform",
"field_ref": [
"field",
"platform",
{
"base-type": "type/Text"
}
],
"effective_type": "type/Text",
"id": 1352,
"visibility_type": "normal",
"display_name": "Platform",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.5754
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Count",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"base_type": "type/BigInteger",
"effective_type": "type/BigInteger",
"name": "count",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Number": {
"min": 2,
"q1": 186,
"q3": 1122,
"max": 4592,
"sd": 1015.5250832969095,
"avg": 815.6363636363636
}
}
}
}
],
"can_run_adhoc_query": true,
"table_id": 143,
"collection_position": null,
"view_count": 3,
"archived": false,
"description": null,
"cache_invalidated_at": null,
"displayIsLocked": true
},
"data": {
"rows": [
["3DS", 400],
["DS", 730],
["Dreamcast", 125],
["GameBoyAdvance", 444],
["GameCube", 452],
["Nintendo64", 70],
["PC", 4592],
["PSP", 513],
["PlayStation", 188],
["PlayStation2", 1418],
["PlayStation3", 1269],
["PlayStation4", 1928],
["PlayStation5", 3],
["PlayStationVita", 257],
["Stadia", 4],
["Switch", 1122],
["Wii", 664],
["WiiU", 186],
["Xbox", 793],
["Xbox360", 1666],
["XboxOne", 1118],
["XboxSeriesX", 2]
],
"cols": [
{
"database_type": "varchar",
"semantic_type": "type/Category",
"table_id": 143,
"name": "platform",
"source": "breakout",
"field_ref": [
"field",
"platform",
{
"base-type": "type/Text"
}
],
"effective_type": "type/Text",
"id": 1352,
"position": 2,
"visibility_type": "normal",
"display_name": "Platform",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.5754
}
}
},
"base_type": "type/Text"
},
{
"database_type": "int8",
"semantic_type": "type/Quantity",
"name": "count",
"source": "aggregation",
"field_ref": ["aggregation", 0],
"effective_type": "type/BigInteger",
"aggregation_index": 0,
"display_name": "Count",
"base_type": "type/BigInteger"
}
],
"native_form": {
"query": "SELECT \"source\".\"platform\" AS \"platform\", COUNT(*) AS \"count\" FROM (SELECT \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"id\" AS \"id\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"name\" AS \"name\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"platform\" AS \"platform\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"r_date\" AS \"r_date\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"score\" AS \"score\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"user_score\" AS \"user_score\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"developer\" AS \"developer\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"genre\" AS \"genre\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"players\" AS \"players\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"critics\" AS \"critics\", \"csv_upload_data\".\"csv_upload_games_20231121140652\".\"users\" AS \"users\" FROM \"csv_upload_data\".\"csv_upload_games_20231121140652\") AS \"source\" GROUP BY \"source\".\"platform\" ORDER BY \"source\".\"platform\" ASC",
"params": null
},
"dataset": true,
"model": true,
"format-rows?": true,
"results_timezone": "America/Los_Angeles",
"results_metadata": {
"columns": [
{
"semantic_type": "type/Category",
"name": "platform",
"field_ref": [
"field",
"platform",
{
"base-type": "type/Text"
}
],
"effective_type": "type/Text",
"id": 1352,
"visibility_type": "normal",
"display_name": "Platform",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.5754
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Count",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"base_type": "type/BigInteger",
"effective_type": "type/BigInteger",
"name": "count",
"fingerprint": {
"global": {
"distinct-count": 22,
"nil%": 0
},
"type": {
"type/Number": {
"min": 2,
"q1": 186,
"q3": 1122,
"max": 4592,
"sd": 1015.5250832969095,
"avg": 815.6363636363636
}
}
}
}
]
},
"insights": null
}
}
]
...@@ -20,15 +20,22 @@ const ALLOWED_CHARS = [ ...@@ -20,15 +20,22 @@ const ALLOWED_CHARS = [
"e", "e",
]; ];
// Note: there are more props than these that are provided by the viz settings
// code, we just don't have types for them here.
interface ChartSettingInputProps { interface ChartSettingInputProps {
value: number | undefined; value: number | undefined;
onChange: (value: number | undefined) => void; onChange: (value: number | undefined) => void;
onChangeSettings: () => void; onChangeSettings: () => void;
options?: {
isInteger?: boolean;
isNonNegative?: boolean;
};
} }
export const ChartSettingInputNumeric = ({ export const ChartSettingInputNumeric = ({
onChange, onChange,
value, value,
options,
...props ...props
}: ChartSettingInputProps) => { }: ChartSettingInputProps) => {
const [internalValue, setInternalValue] = useState(value?.toString() ?? ""); const [internalValue, setInternalValue] = useState(value?.toString() ?? "");
...@@ -49,11 +56,19 @@ export const ChartSettingInputNumeric = ({ ...@@ -49,11 +56,19 @@ export const ChartSettingInputNumeric = ({
} }
}} }}
onBlur={(e: React.ChangeEvent<HTMLInputElement>) => { onBlur={(e: React.ChangeEvent<HTMLInputElement>) => {
const num = e.target.value !== "" ? Number(e.target.value) : Number.NaN; let num = e.target.value !== "" ? Number(e.target.value) : Number.NaN;
if (options?.isInteger) {
num = Math.round(num);
}
if (options?.isNonNegative && num < 0) {
num *= -1;
}
if (isNaN(num)) { if (isNaN(num)) {
onChange(undefined); onChange(undefined);
} else { } else {
onChange(num); onChange(num);
setInternalValue(String(num));
} }
}} }}
/> />
......
...@@ -6,8 +6,13 @@ import { ChartSettingInputNumeric } from "./ChartSettingInputNumeric"; ...@@ -6,8 +6,13 @@ import { ChartSettingInputNumeric } from "./ChartSettingInputNumeric";
function setup({ function setup({
value, value,
options,
}: { }: {
value?: number; value?: number;
options?: {
isInteger?: boolean;
isNonNegative?: boolean;
};
} = {}) { } = {}) {
const onChange = jest.fn(); const onChange = jest.fn();
...@@ -16,6 +21,7 @@ function setup({ ...@@ -16,6 +21,7 @@ function setup({
value={value} value={value}
onChange={onChange} onChange={onChange}
onChangeSettings={() => null} onChangeSettings={() => null}
options={options}
/>, />,
); );
...@@ -65,10 +71,48 @@ describe("ChartSettingInputNumber", () => { ...@@ -65,10 +71,48 @@ describe("ChartSettingInputNumber", () => {
const { input, onChange } = setup(); const { input, onChange } = setup();
await type({ input, value: "1.5e3" }); await type({ input, value: "1.5e3" });
expect(input).toHaveDisplayValue("1.5e3"); expect(input).toHaveDisplayValue("1500");
expect(onChange).toHaveBeenCalledWith(1.5e3); expect(onChange).toHaveBeenCalledWith(1.5e3);
}); });
it("rounds decimals to integers when `isInteger` is `true`", async () => {
const { input, onChange } = setup({ options: { isInteger: true } });
await type({ input, value: "4.9" });
expect(input).toHaveDisplayValue("5");
expect(onChange).toHaveBeenCalledWith(5);
await type({ input, value: "79512.3e-3" });
expect(input).toHaveDisplayValue("80");
expect(onChange).toHaveBeenCalledWith(80);
});
it("makes negatives positive when `isNonNegative` is `true`", async () => {
const { input, onChange } = setup({ options: { isNonNegative: true } });
await type({ input, value: "-5.4" });
expect(input).toHaveDisplayValue("5.4");
expect(onChange).toHaveBeenCalledWith(5.4);
await type({ input, value: "-5.4e3" });
expect(input).toHaveDisplayValue("5400");
expect(onChange).toHaveBeenCalledWith(5400);
});
it("rounds decimals and makes them postiive when `isInteger` and `isNonNegative` are `true`", async () => {
const { input, onChange } = setup({
options: { isInteger: true, isNonNegative: true },
});
await type({ input, value: "-254.953" });
expect(input).toHaveDisplayValue("255");
expect(onChange).toHaveBeenCalledWith(255);
await type({ input, value: "-9.4123458e3" });
expect(input).toHaveDisplayValue("9412");
expect(onChange).toHaveBeenCalledWith(9412);
});
it("does not allow non-numeric values", async () => { it("does not allow non-numeric values", async () => {
const { input, onChange } = setup(); const { input, onChange } = setup();
......
...@@ -39,19 +39,25 @@ export function getPieChartFormatters( ...@@ -39,19 +39,25 @@ export function getPieChartFormatters(
...metricColSettings, ...metricColSettings,
}); });
const formatPercent = (value: unknown, location: "legend" | "chart") => const formatPercent = (value: unknown, location: "legend" | "chart") => {
renderingContext.formatValue(value, { let decimals = settings["pie.decimal_places"];
column: metricColSettings.column, if (decimals == null) {
number_separators: metricColSettings.number_separators as string, decimals = computeMaxDecimalsForValues(
number_style: "percent",
decimals: computeMaxDecimalsForValues(
chartModel.slices.map(s => s.data.normalizedPercentage), chartModel.slices.map(s => s.data.normalizedPercentage),
{ {
style: "percent", style: "percent",
maximumSignificantDigits: location === "legend" ? 3 : 2, maximumSignificantDigits: location === "legend" ? 3 : 2,
}, },
), );
}
return renderingContext.formatValue(value, {
column: metricColSettings.column,
number_separators: metricColSettings.number_separators as string,
number_style: "percent",
decimals,
}); });
};
return { formatDimension, formatMetric, formatPercent }; return { formatDimension, formatMetric, formatPercent };
} }
...@@ -112,6 +112,19 @@ export const PIE_CHART_DEFINITION: VisualizationDefinition = { ...@@ -112,6 +112,19 @@ export const PIE_CHART_DEFINITION: VisualizationDefinition = {
], ],
}, },
}, },
"pie.decimal_places": {
section: t`Display`,
title: t`Number of decimal places`,
widget: "number",
props: {
placeholder: t`Auto`,
options: { isInteger: true, isNonNegative: true },
},
getHidden: (_, settings) =>
settings["pie.percent_visibility"] == null ||
settings["pie.percent_visibility"] === "off",
readDependencies: ["pie.percent_visibility"],
},
"pie.slice_threshold": { "pie.slice_threshold": {
section: t`Display`, section: t`Display`,
title: t`Minimum slice percentage`, title: t`Minimum slice percentage`,
......
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