diff --git a/frontend/src/metabase/lib/formatting.js b/frontend/src/metabase/lib/formatting.js index 0cf958d4eba35b36a5ec3cc9236526ae27fb1491..66869617119737a499e1ce179fc4fa6c7d1bc802 100644 --- a/frontend/src/metabase/lib/formatting.js +++ b/frontend/src/metabase/lib/formatting.js @@ -133,11 +133,11 @@ export function numberFormatterForOptions(options: FormattingOptions) { currency: options.currency, currencyDisplay: options.currency_style, useGrouping: options.useGrouping, - // minimumIntegerDigits: options.minimumIntegerDigits, + minimumIntegerDigits: options.minimumIntegerDigits, minimumFractionDigits: options.minimumFractionDigits, maximumFractionDigits: options.maximumFractionDigits, - // minimumSignificantDigits: options.minimumSignificantDigits, - // maximumSignificantDigits: options.maximumSignificantDigits, + minimumSignificantDigits: options.minimumSignificantDigits, + maximumSignificantDigits: options.maximumSignificantDigits, }); } @@ -154,9 +154,22 @@ export function formatNumber(number: number, options: FormattingOptions = {}) { return formatNumberScientific(number, options); } else { try { - // NOTE: options._numberFormatter allows you to provide a predefined - // Intl.NumberFormat object for increased performance - const nf = options._numberFormatter || numberFormatterForOptions(options); + let nf; + if (number < 1 && number > -1 && options.decimals == null) { + // NOTE: special case to match existing behavior for small numbers, use + // max significant digits instead of max fraction digits + nf = numberFormatterForOptions({ + ...options, + maximumSignificantDigits: 2, + maximumFractionDigits: undefined, + }); + } else if (options._numberFormatter) { + // NOTE: options._numberFormatter allows you to provide a predefined + // Intl.NumberFormat object for increased performance + nf = options._numberFormatter; + } else { + nf = numberFormatterForOptions(options); + } return nf.format(number); } catch (e) { console.warn("Error formatting number", e); @@ -428,7 +441,7 @@ const EMAIL_WHITELIST_REGEX = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a export function formatEmail( value: Value, - { jsx, rich, view_as, link_text }: FormattingOptions = {}, + { jsx, rich, view_as = "auto", link_text }: FormattingOptions = {}, ) { const email = String(value); if ( @@ -450,7 +463,7 @@ const URL_WHITELIST_REGEX = /^(https?|mailto):\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s: export function formatUrl( value: Value, - { jsx, rich, view_as, link_text }: FormattingOptions = {}, + { jsx, rich, view_as = "auto", link_text }: FormattingOptions = {}, ) { const url = String(value); if ( @@ -471,7 +484,7 @@ export function formatUrl( export function formatImage( value: Value, - { jsx, rich, view_as, link_text }: FormattingOptions = {}, + { jsx, rich, view_as = "auto", link_text }: FormattingOptions = {}, ) { const url = String(value); if (jsx && rich && view_as === "image" && URL_WHITELIST_REGEX.test(url)) { diff --git a/frontend/test/lib/formatting.unit.spec.js b/frontend/test/lib/formatting.unit.spec.js index 55daf41302d0372fa5e73037208106b6ce5c7478..d3084378341b116dd6ebbcbe64ec0d922bf1c7c6 100644 --- a/frontend/test/lib/formatting.unit.spec.js +++ b/frontend/test/lib/formatting.unit.spec.js @@ -40,6 +40,18 @@ describe("formatting", () => { expect(formatNumber(1111, { compact: true })).toEqual("1.1k"); }); }); + it("should format to correct number of decimal places", () => { + expect(formatNumber(0.1)).toEqual("0.1"); + expect(formatNumber(0.11)).toEqual("0.11"); + expect(formatNumber(0.111)).toEqual("0.11"); + expect(formatNumber(0.01)).toEqual("0.01"); + expect(formatNumber(0.011)).toEqual("0.011"); + expect(formatNumber(0.0111)).toEqual("0.011"); + expect(formatNumber(1.1)).toEqual("1.1"); + expect(formatNumber(1.11)).toEqual("1.11"); + expect(formatNumber(1.111)).toEqual("1.11"); + expect(formatNumber(111.111)).toEqual("111.11"); + }); }); describe("formatValue", () => { @@ -75,11 +87,7 @@ describe("formatting", () => { it("should return a component for links in jsx + rich mode", () => { expect( isElementOfType( - formatValue("http://metabase.com/", { - jsx: true, - rich: true, - view_as: "link", - }), + formatValue("http://metabase.com/", { jsx: true, rich: true }), ExternalLink, ), ).toEqual(true); @@ -87,11 +95,7 @@ describe("formatting", () => { it("should return a component for email addresses in jsx + rich mode", () => { expect( isElementOfType( - formatValue("tom@metabase.com", { - jsx: true, - rich: true, - view_as: "email_link", - }), + formatValue("tom@metabase.com", { jsx: true, rich: true }), ExternalLink, ), ).toEqual(true); @@ -105,31 +109,19 @@ describe("formatting", () => { it("should return a component for http:, https:, and mailto: links in jsx mode", () => { expect( isElementOfType( - formatUrl("http://metabase.com/", { - jsx: true, - rich: true, - view_as: "link", - }), + formatUrl("http://metabase.com/", { jsx: true, rich: true }), ExternalLink, ), ).toEqual(true); expect( isElementOfType( - formatUrl("https://metabase.com/", { - jsx: true, - rich: true, - view_as: "link", - }), + formatUrl("https://metabase.com/", { jsx: true, rich: true }), ExternalLink, ), ).toEqual(true); expect( isElementOfType( - formatUrl("mailto:tom@metabase.com", { - jsx: true, - rich: true, - view_as: "link", - }), + formatUrl("mailto:tom@metabase.com", { jsx: true, rich: true }), ExternalLink, ), ).toEqual(true); @@ -137,34 +129,25 @@ describe("formatting", () => { it("should not return a link component for unrecognized links in jsx mode", () => { expect( isElementOfType( - formatUrl("nonexistent://metabase.com/", { - jsx: true, - rich: true, - view_as: "link", - }), + formatUrl("nonexistent://metabase.com/", { jsx: true, rich: true }), ExternalLink, ), ).toEqual(false); expect( isElementOfType( - formatUrl("metabase.com", { jsx: true, rich: true, view_as: "link" }), + formatUrl("metabase.com", { jsx: true, rich: true }), ExternalLink, ), ).toEqual(false); }); it("should return a string for javascript:, data:, and other links in jsx mode", () => { expect( - formatUrl("javascript:alert('pwnd')", { - jsx: true, - rich: true, - view_as: "link", - }), + formatUrl("javascript:alert('pwnd')", { jsx: true, rich: true }), ).toEqual("javascript:alert('pwnd')"); expect( formatUrl("data:text/plain;charset=utf-8,hello%20world", { jsx: true, rich: true, - view_as: "link", }), ).toEqual("data:text/plain;charset=utf-8,hello%20world"); }); diff --git a/frontend/test/visualizations/components/LineAreaBarRenderer-bar.unit.spec.js b/frontend/test/visualizations/components/LineAreaBarRenderer-bar.unit.spec.js index e3d0f7b33bb2c9746f20d948b8234e738bc834c0..9f6d63747b3b856988baa0eab251e3d3faaa4743 100644 --- a/frontend/test/visualizations/components/LineAreaBarRenderer-bar.unit.spec.js +++ b/frontend/test/visualizations/components/LineAreaBarRenderer-bar.unit.spec.js @@ -99,7 +99,7 @@ describe("LineAreaBarRenderer-bar", () => { normalizedDisplay = [ { key: "Category", value: "A" }, - { key: "% Sum", value: "33.33%" }, + { key: "% Sum", value: "33%" }, ]; expect(data).toEqual( @@ -116,7 +116,7 @@ describe("LineAreaBarRenderer-bar", () => { normalizedDisplay = [ { key: "Category", value: "A" }, - { key: "% Count", value: "66.67%" }, + { key: "% Count", value: "67%" }, ]; expect(data).toEqual(