From d9edcb845375ea3719b86640860110ce260979ca Mon Sep 17 00:00:00 2001 From: Tom Robinson <tlrobinson@gmail.com> Date: Tue, 18 Sep 2018 16:11:37 -0700 Subject: [PATCH] Fix flow --- .../src/metabase/components/ButtonGroup.jsx | 15 ++++++- frontend/src/metabase/lib/formatting.js | 41 +++++++++++++++---- .../components/TableInteractive.jsx | 2 +- .../metabase/visualizations/lib/settings.js | 1 - .../visualizations/visualizations/Scalar.jsx | 4 +- .../visualizations/visualizations/Table.jsx | 4 +- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/frontend/src/metabase/components/ButtonGroup.jsx b/frontend/src/metabase/components/ButtonGroup.jsx index 7083eeaad17..286af5c1a4c 100644 --- a/frontend/src/metabase/components/ButtonGroup.jsx +++ b/frontend/src/metabase/components/ButtonGroup.jsx @@ -4,6 +4,19 @@ import React from "react"; import cx from "classnames"; +type Value = any; +type Option = any; + +type Props = { + value: Value, + onChange: (value: Value) => void, + options: Option[], + optionNameFn?: (o: Option) => string | React$Element<any>, + optionValueFn?: (o: Option) => Value, + optionKeyFn?: (o: Option) => string, + className?: string, +}; + const ButtonGroup = ({ value, onChange, @@ -12,7 +25,7 @@ const ButtonGroup = ({ optionValueFn = o => o.value, optionKeyFn = optionValueFn, className, -}) => { +}: Props) => { return ( <div className={cx(className, "rounded bordered flex")}> {options.map((o, index) => ( diff --git a/frontend/src/metabase/lib/formatting.js b/frontend/src/metabase/lib/formatting.js index c97dcfd01ca..f1f2ccdfe95 100644 --- a/frontend/src/metabase/lib/formatting.js +++ b/frontend/src/metabase/lib/formatting.js @@ -38,17 +38,19 @@ import type { DatetimeUnit } from "metabase/meta/types/Query"; import type { Moment } from "metabase/meta/types"; export type FormattingOptions = { + // GENERIC column?: Column | Field, majorWidth?: number, type?: "axis" | "cell" | "tooltip", jsx?: boolean, // render links for type/URLs, type/Email, etc rich?: boolean, - // number options: compact?: boolean, // always format as the start value rather than the range, e.x. for bar histogram noRange?: boolean, + // NUMBER // TODO: docoument these: + number_style?: null | "decimal" | "percent" | "scientific" | "currency", prefix?: string, suffix?: string, scale?: number, @@ -61,8 +63,21 @@ export type FormattingOptions = { useGrouping?: boolean, // decimals sets both minimumFractionDigits and maximumFractionDigits decimals?: number, + // STRING + view_as?: "link" | "email_link" | "image", + link_text?: string, + // DATE/TIME + // date/timeout style string that is used to derive a date_format or time_format for different units, see metabase/lib/formatting/date + date_style?: string, + time_style?: string, + date_format?: string, + date_abbreviate?: boolean, + time_format?: string, + time_enabled?: null | "minutes" | "seconds" | "milliseconds", }; +type FormattedString = string | React$Element<any>; + const DEFAULT_NUMBER_OPTIONS: FormattingOptions = { compact: false, maximumFractionDigits: 2, @@ -105,6 +120,7 @@ const RANGE_SEPARATOR = ` – `; export function numberFormatterForOptions(options: FormattingOptions) { options = { ...getDefaultNumberOptions(options), ...options }; // if we don't provide a locale much of the formatting doens't work + // $FlowFixMe: doesn't know about Intl.NumberFormat return new Intl.NumberFormat(options.locale || "en", { style: options.number_style, currency: options.currency, @@ -146,7 +162,10 @@ export function formatNumber(number: number, options: FormattingOptions = {}) { } } -function formatNumberScientific(value: number, options: FormattingOptions) { +function formatNumberScientific( + value: number, + options: FormattingOptions, +): FormattedString { if (options.maximumFractionDigits) { value = d3.round(value, options.maximumFractionDigits); } @@ -207,12 +226,19 @@ export function formatCoordinate( export function formatRange( range: [number, number], - formatter: (value: number) => string, + formatter: (value: number) => any, options: FormattingOptions = {}, ) { - return range - .map(value => formatter(value, options)) - .join(` ${RANGE_SEPARATOR} `); + const [start, end] = range.map(value => formatter(value, options)); + if ((options.jsx && typeof start !== "string") || typeof end !== "string") { + return ( + <span> + {start} {RANGE_SEPARATOR} {end} + </span> + ); + } else { + return `${start} ${RANGE_SEPARATOR} ${start}`; + } } function formatMajorMinor(major, minor, options = {}) { @@ -327,7 +353,7 @@ function formatDateTime(value, options) { options, ); } else { - if (options.show_time === false) { + if (options.time_enabled === false) { return m.format(options.date_abbreviate ? "ll" : "LL"); } else { return m.format(options.date_abbreviate ? "llll" : "LLLL"); @@ -486,6 +512,7 @@ export function formatValue(value: Value, options: FormattingOptions = {}) { </span> ); } else { + // $FlowFixMe: doesn't understand formatted is a string return `${options.prefix || ""}${formatted}${options.suffix || ""}`; } } else { diff --git a/frontend/src/metabase/visualizations/components/TableInteractive.jsx b/frontend/src/metabase/visualizations/components/TableInteractive.jsx index c8025df11fb..468a1bd9202 100644 --- a/frontend/src/metabase/visualizations/components/TableInteractive.jsx +++ b/frontend/src/metabase/visualizations/components/TableInteractive.jsx @@ -160,7 +160,7 @@ export default class TableInteractive extends Component { } } - _getColumnSettings(props) { + _getColumnSettings(props: Props) { return props.data && props.data.cols.map(col => props.settings.column(col)); } diff --git a/frontend/src/metabase/visualizations/lib/settings.js b/frontend/src/metabase/visualizations/lib/settings.js index 605de962f63..034c16692d4 100644 --- a/frontend/src/metabase/visualizations/lib/settings.js +++ b/frontend/src/metabase/visualizations/lib/settings.js @@ -208,7 +208,6 @@ export function getSettingsWidgets( ) { return Object.keys(settingDefs) .map(settingId => - // $FlowFixMe: doesn't understand settingDef is a SettingDef getSettingWidget( settingDefs, settingId, diff --git a/frontend/src/metabase/visualizations/visualizations/Scalar.jsx b/frontend/src/metabase/visualizations/visualizations/Scalar.jsx index a1d0c03c455..7e0ed33454a 100644 --- a/frontend/src/metabase/visualizations/visualizations/Scalar.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Scalar.jsx @@ -17,6 +17,8 @@ import cx from "classnames"; import _ from "underscore"; import type { VisualizationProps } from "metabase/meta/types/Visualization"; +import type { Column } from "metabase/meta/types/Dataset"; +import type { VisualizationSettings } from "metabase/meta/types/Card"; // convert legacy `scalar.*` visualization settings to format options function legacyScalarSettingsToFormatOptions(settings) { @@ -126,7 +128,7 @@ export default class Scalar extends Component { }, }; - _getColumnIndex(cols, settings) { + _getColumnIndex(cols: Column[], settings: VisualizationSettings) { const columnIndex = _.findIndex( cols, col => col.name === settings["scalar.field"], diff --git a/frontend/src/metabase/visualizations/visualizations/Table.jsx b/frontend/src/metabase/visualizations/visualizations/Table.jsx index cd330466680..dc4869f6078 100644 --- a/frontend/src/metabase/visualizations/visualizations/Table.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Table.jsx @@ -130,7 +130,9 @@ export default class Table extends Component { } if (isString(column)) { let defaultValue = null; - const options = [{ name: t`Off`, value: null }]; + const options: { name: string, value: null | string }[] = [ + { name: t`Off`, value: null }, + ]; if (!column.special_type || isURL(column)) { defaultValue = "link"; options.push({ name: t`Link`, value: "link" }); -- GitLab