From 1b0cd8d169372405c743d6fa71347e922fb53ddb Mon Sep 17 00:00:00 2001 From: Tom Robinson <tlrobinson@gmail.com> Date: Thu, 18 May 2017 13:30:29 -0700 Subject: [PATCH] Fix React component Flow types --- .../components/widgets/PublicLinksListing.jsx | 13 +++--- .../components/widgets/SecretKeyWidget.jsx | 2 +- .../src/metabase/components/ActionButton.jsx | 3 +- .../metabase/components/ConstrainToScreen.jsx | 4 +- .../src/metabase/components/CopyButton.jsx | 2 +- .../src/metabase/components/CopyWidget.jsx | 3 +- .../metabase/components/ShrinkableList.jsx | 3 +- .../dashboard/components/Dashboard.jsx | 19 ++++++--- .../dashboard/components/DashboardHeader.jsx | 15 +++---- .../dashboard/hoc/DashboardControls.jsx | 3 +- .../src/metabase/meta/types/Visualization.js | 6 +-- .../parameters/components/Parameters.jsx | 40 ++++++++++--------- .../components/widgets/CategoryWidget.jsx | 2 +- .../widgets/DateAllOptionsWidget.jsx | 3 +- .../metabase/public/components/EmbedFrame.jsx | 9 ++++- .../components/widgets/AdvancedEmbedPane.jsx | 3 +- .../widgets/AdvancedSettingsPane.jsx | 3 +- .../public/components/widgets/CodeSample.jsx | 12 ++---- .../components/widgets/EmbedCodePane.jsx | 7 +++- .../components/widgets/EmbedModalContent.jsx | 35 ++++++++-------- .../public/components/widgets/EmbedWidget.jsx | 23 +++++++++-- .../public/components/widgets/SharingPane.jsx | 18 ++++----- .../metabase/public/containers/PublicApp.jsx | 4 +- .../public/containers/PublicDashboard.jsx | 4 +- .../public/containers/PublicQuestion.jsx | 2 +- frontend/src/metabase/public/lib/code.js | 16 ++++++-- frontend/src/metabase/public/lib/types.js | 11 +++++ .../qb/components/TimeseriesFilterWidget.jsx | 8 ++-- .../components/TimeseriesGroupingWidget.jsx | 4 +- .../components/ActionsWidget.jsx | 11 ++++- .../filters/DateOperatorSelector.jsx | 8 ++-- .../components/filters/FilterList.jsx | 12 +++--- .../components/filters/FilterPopover.jsx | 19 +++++---- .../components/filters/FilterWidget.jsx | 13 +++--- .../components/filters/OperatorSelector.jsx | 2 +- .../components/filters/pickers/DatePicker.jsx | 18 ++++++--- .../filters/pickers/NumberPicker.jsx | 9 +++-- .../filters/pickers/RelativeDatePicker.jsx | 2 +- .../filters/pickers/SelectPicker.jsx | 4 +- .../filters/pickers/SpecificDatePicker.jsx | 2 +- .../components/filters/pickers/TextPicker.jsx | 11 ++++- .../components/ChartClickActions.jsx | 5 ++- .../visualizations/components/FunnelBar.jsx | 4 +- .../components/FunnelNormal.jsx | 6 ++- .../components/LineAreaBarChart.jsx | 5 ++- .../visualizations/components/PinMap.jsx | 5 ++- .../components/TableInteractive.jsx | 2 +- .../visualizations/components/TableSimple.jsx | 3 +- .../components/Visualization.jsx | 18 +++++---- frontend/src/metabase/visualizations/index.js | 1 + .../visualizations/lib/LineAreaBarRenderer.js | 10 ++--- .../visualizations/visualizations/Funnel.jsx | 5 ++- .../visualizations/visualizations/Map.jsx | 4 +- .../visualizations/PieChart.jsx | 4 +- .../visualizations/Progress.jsx | 4 +- .../visualizations/visualizations/Scalar.jsx | 4 +- .../visualizations/visualizations/Table.jsx | 9 ++++- 57 files changed, 304 insertions(+), 173 deletions(-) create mode 100644 frontend/src/metabase/public/lib/types.js diff --git a/frontend/src/metabase/admin/settings/components/widgets/PublicLinksListing.jsx b/frontend/src/metabase/admin/settings/components/widgets/PublicLinksListing.jsx index 49f5dfc9e88..8e2d000e936 100644 --- a/frontend/src/metabase/admin/settings/components/widgets/PublicLinksListing.jsx +++ b/frontend/src/metabase/admin/settings/components/widgets/PublicLinksListing.jsx @@ -20,10 +20,10 @@ type PublicLink = { }; type Props = { - load: () => Promise<PublicLink[]>, - revoke: (link: PublicLink) => Promise<void>, - getUrl: (link: PublicLink) => string, - getPublicUrl: (link: PublicLink) => string, + load: () => Promise<PublicLink[]>, + revoke?: (link: PublicLink) => Promise<void>, + getUrl: (link: PublicLink) => string, + getPublicUrl?: (link: PublicLink) => string, noLinksMessage: string, type: string }; @@ -33,7 +33,7 @@ type State = { error: ?any }; -export default class PublicLinksListing extends Component<*, Props, State> { +export default class PublicLinksListing extends Component { props: Props; state: State; @@ -59,6 +59,9 @@ export default class PublicLinksListing extends Component<*, Props, State> { } async revoke(link: PublicLink) { + if (!this.props.revoke) { + return; + } try { await this.props.revoke(link); this.load(); diff --git a/frontend/src/metabase/admin/settings/components/widgets/SecretKeyWidget.jsx b/frontend/src/metabase/admin/settings/components/widgets/SecretKeyWidget.jsx index 192e2b305c0..3db15bf88fe 100644 --- a/frontend/src/metabase/admin/settings/components/widgets/SecretKeyWidget.jsx +++ b/frontend/src/metabase/admin/settings/components/widgets/SecretKeyWidget.jsx @@ -13,7 +13,7 @@ type Props = { setting: {} }; -export default class SecretKeyWidget extends Component<*, Props, *> { +export default class SecretKeyWidget extends Component { props: Props; _generateToken = async () => { diff --git a/frontend/src/metabase/components/ActionButton.jsx b/frontend/src/metabase/components/ActionButton.jsx index 168d2c71a6e..148742f2575 100644 --- a/frontend/src/metabase/components/ActionButton.jsx +++ b/frontend/src/metabase/components/ActionButton.jsx @@ -26,7 +26,8 @@ type State = { result: null|"success"|"failed", } -export default class ActionButton extends Component<*, Props, State> { +export default class ActionButton extends Component { + props: Props; state: State; timeout: ?any; diff --git a/frontend/src/metabase/components/ConstrainToScreen.jsx b/frontend/src/metabase/components/ConstrainToScreen.jsx index 354878bbc8f..aee7690bd18 100644 --- a/frontend/src/metabase/components/ConstrainToScreen.jsx +++ b/frontend/src/metabase/components/ConstrainToScreen.jsx @@ -11,7 +11,9 @@ type Props = { children: React$Element<any> }; -export default class ConstrainToScreen extends Component<*, Props, *> { +export default class ConstrainToScreen extends Component { + props: Props; + static defaultProps = { directions: ["top", "bottom"], padding: 10 diff --git a/frontend/src/metabase/components/CopyButton.jsx b/frontend/src/metabase/components/CopyButton.jsx index 76a51cbf538..996ba43d1c0 100644 --- a/frontend/src/metabase/components/CopyButton.jsx +++ b/frontend/src/metabase/components/CopyButton.jsx @@ -15,7 +15,7 @@ type State = { copied: boolean }; -export default class CopyWidget extends Component<*, Props, State> { +export default class CopyWidget extends Component { props: Props; state: State; diff --git a/frontend/src/metabase/components/CopyWidget.jsx b/frontend/src/metabase/components/CopyWidget.jsx index 01a3b485407..62d5e963a25 100644 --- a/frontend/src/metabase/components/CopyWidget.jsx +++ b/frontend/src/metabase/components/CopyWidget.jsx @@ -8,8 +8,9 @@ type Props = { value: string }; -export default class CopyWidget extends Component<*, Props, *> { +export default class CopyWidget extends Component { props: Props; + render() { const { value } = this.props; return ( diff --git a/frontend/src/metabase/components/ShrinkableList.jsx b/frontend/src/metabase/components/ShrinkableList.jsx index 457841fd15c..3bae345fb74 100644 --- a/frontend/src/metabase/components/ShrinkableList.jsx +++ b/frontend/src/metabase/components/ShrinkableList.jsx @@ -17,7 +17,8 @@ type State = { }; @ExplicitSize -export default class ShrinkableList extends Component<*, Props, State> { +export default class ShrinkableList extends Component { + props: Props; state: State = { isShrunk: null } diff --git a/frontend/src/metabase/dashboard/components/Dashboard.jsx b/frontend/src/metabase/dashboard/components/Dashboard.jsx index 6a63a2900da..e9c8458e90b 100644 --- a/frontend/src/metabase/dashboard/components/Dashboard.jsx +++ b/frontend/src/metabase/dashboard/components/Dashboard.jsx @@ -18,7 +18,7 @@ import type { LocationDescriptor, ApiError, QueryParams } from "metabase/meta/ty import type { Card, CardId, VisualizationSettings } from "metabase/meta/types/Card"; import type { DashboardWithCards, DashboardId, DashCardId } from "metabase/meta/types/Dashboard"; -import type { RevisionId } from "metabase/meta/types/Revision"; +import type { Revision, RevisionId } from "metabase/meta/types/Revision"; import type { Parameter, ParameterId, ParameterValues, ParameterOption } from "metabase/meta/types/Parameter"; type Props = { @@ -27,7 +27,9 @@ type Props = { dashboardId: DashboardId, dashboard: DashboardWithCards, cards: Card[], + revisions: { [key: string]: Revision[] }, + isAdmin: boolean, isEditable: boolean, isEditing: boolean, isEditingParameter: boolean, @@ -48,7 +50,7 @@ type Props = { setDashboardAttributes: ({ [attribute: string]: any }) => void, fetchDashboardCardData: (options: { reload: bool, clear: bool }) => Promise<void>, - setEditingParameter: (parameterId: ParameterId) => void, + setEditingParameter: (parameterId: ?ParameterId) => void, setEditingDashboard: (isEditing: boolean) => void, addParameter: (option: ParameterOption) => Promise<Parameter>, @@ -59,9 +61,15 @@ type Props = { editingParameter: ?Parameter, + refreshPeriod: number, + refreshElapsed: number, isFullscreen: boolean, isNightMode: boolean, + onRefreshPeriodChange: (?number) => void, + onNightModeChange: (boolean) => void, + onFullscreenChange: (boolean) => void, + loadDashboardParams: () => void, onReplaceAllDashCardVisualizationSettings: (dashcardId: DashCardId, settings: VisualizationSettings) => void, @@ -76,8 +84,9 @@ type State = { } @DashboardControls -export default class Dashboard extends Component<*, Props, State> { - state = { +export default class Dashboard extends Component { + props: Props; + state: State = { error: null, }; @@ -197,7 +206,7 @@ export default class Dashboard extends Component<*, Props, State> { onEditingChange={this.setEditing} setDashboardAttribute={this.setDashboardAttribute} addParameter={this.props.addParameter} - parameters={parametersWidget} + parametersWidget={parametersWidget} /> </header> {!isFullscreen && parametersWidget && diff --git a/frontend/src/metabase/dashboard/components/DashboardHeader.jsx b/frontend/src/metabase/dashboard/components/DashboardHeader.jsx index 388589a93ab..7e9a0cfcabc 100644 --- a/frontend/src/metabase/dashboard/components/DashboardHeader.jsx +++ b/frontend/src/metabase/dashboard/components/DashboardHeader.jsx @@ -44,7 +44,7 @@ type Props = { refreshPeriod: ?number, refreshElapsed: ?number, - parameters: React$Element<*>[], + parametersWidget: React$Element<*>, addCardToDashboard: ({ dashId: DashCardId, cardId: CardId }) => void, archiveDashboard: (dashboardId: DashboardId) => void, @@ -58,7 +58,7 @@ type Props = { addParameter: (option: ParameterOption) => Promise<Parameter>, setEditingParameter: (parameterId: ?ParameterId) => void, - onEditingChange: () => void, + onEditingChange: (isEditing: boolean) => void, onRefreshPeriodChange: (?number) => void, onNightModeChange: (boolean) => void, onFullscreenChange: (boolean) => void, @@ -70,8 +70,9 @@ type State = { modal: null|"parameters", } -export default class DashboardHeader extends Component<*, Props, State> { - state = { +export default class DashboardHeader extends Component { + props: Props; + state: State = { modal: null, }; @@ -174,7 +175,7 @@ export default class DashboardHeader extends Component<*, Props, State> { } getHeaderButtons() { - const { dashboard, parameters, isEditing, isFullscreen, isEditable, isAdmin } = this.props; + const { dashboard, parametersWidget, isEditing, isFullscreen, isEditable, isAdmin } = this.props; const isEmpty = !dashboard || dashboard.ordered_cards.length === 0; const canEdit = isEditable && !!dashboard; @@ -183,8 +184,8 @@ export default class DashboardHeader extends Component<*, Props, State> { const buttons = []; - if (isFullscreen && parameters) { - buttons.push(parameters); + if (isFullscreen && parametersWidget) { + buttons.push(parametersWidget); } if (isEditing) { diff --git a/frontend/src/metabase/dashboard/hoc/DashboardControls.jsx b/frontend/src/metabase/dashboard/hoc/DashboardControls.jsx index f291c2a50ad..37722f5dd89 100644 --- a/frontend/src/metabase/dashboard/hoc/DashboardControls.jsx +++ b/frontend/src/metabase/dashboard/hoc/DashboardControls.jsx @@ -35,9 +35,10 @@ const TICK_PERIOD = 0.25; // seconds */ export default (ComposedComponent: ReactClass<any>) => connect(null, { replace })( - class extends Component<*, Props, State> { + class extends Component { static displayName = "DashboardControls["+(ComposedComponent.displayName || ComposedComponent.name)+"]"; + props: Props; state: State = { isFullscreen: false, isNightMode: false, diff --git a/frontend/src/metabase/meta/types/Visualization.js b/frontend/src/metabase/meta/types/Visualization.js index e172b2037c2..75b6f11e09c 100644 --- a/frontend/src/metabase/meta/types/Visualization.js +++ b/frontend/src/metabase/meta/types/Visualization.js @@ -57,10 +57,8 @@ export type ClickActionPopoverProps = { onClose: () => void, } -// type Visualization = Component<*, VisualizationProps, *>; - -// $FlowFixMe -export type Series = { card: Card, data: DatasetData }[] & { _raw: Series } +export type SingleSeries = { card: Card, data: DatasetData }; +export type Series = SingleSeries[] & { _raw: Series } export type VisualizationProps = { series: Series, diff --git a/frontend/src/metabase/parameters/components/Parameters.jsx b/frontend/src/metabase/parameters/components/Parameters.jsx index 22ab38f1d39..9e9bfec2dc6 100644 --- a/frontend/src/metabase/parameters/components/Parameters.jsx +++ b/frontend/src/metabase/parameters/components/Parameters.jsx @@ -14,8 +14,8 @@ type Props = { className?: string, parameters: Parameter[], - editingParameter: ?Parameter, - parameterValues: ParameterValues, + editingParameter?: ?Parameter, + parameterValues?: ParameterValues, isFullscreen?: boolean, isNightMode?: boolean, @@ -24,16 +24,18 @@ type Props = { vertical?: boolean, commitImmediately?: boolean, - query: QueryParams, + query?: QueryParams, - setParameterName: (parameterId: ParameterId, name: string) => void, - setParameterValue: (parameterId: ParameterId, value: string) => void, - setParameterDefaultValue: (parameterId: ParameterId, defaultValue: string) => void, - removeParameter: (parameterId: ParameterId) => void, - setEditingParameter: (parameterId: ParameterId) => void, + setParameterName?: (parameterId: ParameterId, name: string) => void, + setParameterValue?: (parameterId: ParameterId, value: string) => void, + setParameterDefaultValue?: (parameterId: ParameterId, defaultValue: string) => void, + removeParameter?: (parameterId: ParameterId) => void, + setEditingParameter?: (parameterId: ParameterId) => void, } -export default class Parameters extends Component<*, Props, *> { +export default class Parameters extends Component { + props: Props; + defaultProps = { syncQueryString: false, vertical: false, @@ -43,11 +45,13 @@ export default class Parameters extends Component<*, Props, *> { componentWillMount() { // sync parameters from URL query string const { parameters, setParameterValue, query } = this.props; - for (const parameter of parameters) { - if (query && query[parameter.slug] != null) { - setParameterValue(parameter.id, query[parameter.slug]); - } else if (parameter.default != null) { - setParameterValue(parameter.id, parameter.default); + if (setParameterValue) { + for (const parameter of parameters) { + if (query && query[parameter.slug] != null) { + setParameterValue(parameter.id, query[parameter.slug]); + } else if (parameter.default != null) { + setParameterValue(parameter.id, parameter.default); + } } } } @@ -112,10 +116,10 @@ export default class Parameters extends Component<*, Props, *> { editingParameter={editingParameter} setEditingParameter={setEditingParameter} - setName={(name) => setParameterName(parameter.id, name)} - setValue={(value) => setParameterValue(parameter.id, value)} - setDefaultValue={(value) => setParameterDefaultValue(parameter.id, value)} - remove={() => removeParameter(parameter.id)} + setName={setParameterName && ((name) => setParameterName(parameter.id, name))} + setValue={setParameterValue && ((value) => setParameterValue(parameter.id, value))} + setDefaultValue={setParameterDefaultValue && ((value) => setParameterDefaultValue(parameter.id, value))} + remove={removeParameter && (() => removeParameter(parameter.id))} commitImmediately={commitImmediately} /> diff --git a/frontend/src/metabase/parameters/components/widgets/CategoryWidget.jsx b/frontend/src/metabase/parameters/components/widgets/CategoryWidget.jsx index c995b515c3a..cd0ed861169 100644 --- a/frontend/src/metabase/parameters/components/widgets/CategoryWidget.jsx +++ b/frontend/src/metabase/parameters/components/widgets/CategoryWidget.jsx @@ -19,7 +19,7 @@ type State = { searchRegex: ?RegExp, } -export default class CategoryWidget extends Component<*, Props, State> { +export default class CategoryWidget extends Component { props: Props; state: State; diff --git a/frontend/src/metabase/parameters/components/widgets/DateAllOptionsWidget.jsx b/frontend/src/metabase/parameters/components/widgets/DateAllOptionsWidget.jsx index c29fd85d6f7..8f8e0b4c834 100644 --- a/frontend/src/metabase/parameters/components/widgets/DateAllOptionsWidget.jsx +++ b/frontend/src/metabase/parameters/components/widgets/DateAllOptionsWidget.jsx @@ -61,7 +61,8 @@ type Props = { type State = { filter: FieldFilter }; -export default class DateAllOptionsWidget extends Component<*, Props, State> { +export default class DateAllOptionsWidget extends Component { + props: Props; state: State; constructor(props: Props) { diff --git a/frontend/src/metabase/public/components/EmbedFrame.jsx b/frontend/src/metabase/public/components/EmbedFrame.jsx index 76c9443c931..c302bba0c0f 100644 --- a/frontend/src/metabase/public/components/EmbedFrame.jsx +++ b/frontend/src/metabase/public/components/EmbedFrame.jsx @@ -32,9 +32,14 @@ type Props = { setParameterValue: (id: string, value: string) => void } +type State = { + innerScroll: boolean +} + @withRouter -export default class EmbedFrame extends Component<*, Props, *> { - state = { +export default class EmbedFrame extends Component { + props: Props; + state: State = { innerScroll: true } diff --git a/frontend/src/metabase/public/components/widgets/AdvancedEmbedPane.jsx b/frontend/src/metabase/public/components/widgets/AdvancedEmbedPane.jsx index cf40db04da5..91a3c6081c6 100644 --- a/frontend/src/metabase/public/components/widgets/AdvancedEmbedPane.jsx +++ b/frontend/src/metabase/public/components/widgets/AdvancedEmbedPane.jsx @@ -11,7 +11,8 @@ import PreviewPane from "./PreviewPane"; import EmbedCodePane from "./EmbedCodePane"; import type { Parameter, ParameterId } from "metabase/meta/types/Parameter"; -import type { Pane, EmbedType, EmbeddableResource, EmbeddingParams, DisplayOptions } from "./EmbedModalContent"; +import type { Pane, EmbedType, DisplayOptions } from "./EmbedModalContent"; +import type { EmbeddableResource, EmbeddingParams } from "metabase/public/lib/types"; import _ from "underscore"; diff --git a/frontend/src/metabase/public/components/widgets/AdvancedSettingsPane.jsx b/frontend/src/metabase/public/components/widgets/AdvancedSettingsPane.jsx index 79af697674f..858030f8ddc 100644 --- a/frontend/src/metabase/public/components/widgets/AdvancedSettingsPane.jsx +++ b/frontend/src/metabase/public/components/widgets/AdvancedSettingsPane.jsx @@ -16,7 +16,8 @@ const getIconForParameter = (parameter) => parameter.type.indexOf("date/") === 0 ? "calendar" : "unknown"; -import type { EmbedType, EmbeddableResource, EmbeddingParams, DisplayOptions } from "./EmbedModalContent"; +import type { EmbedType, DisplayOptions } from "./EmbedModalContent"; +import type { EmbeddableResource, EmbeddingParams } from "metabase/public/lib/types"; import type { Parameter, ParameterId } from "metabase/meta/types/Parameter"; type Props = { diff --git a/frontend/src/metabase/public/components/widgets/CodeSample.jsx b/frontend/src/metabase/public/components/widgets/CodeSample.jsx index f236fd875b1..c998e906298 100644 --- a/frontend/src/metabase/public/components/widgets/CodeSample.jsx +++ b/frontend/src/metabase/public/components/widgets/CodeSample.jsx @@ -9,25 +9,21 @@ import AceEditor from "metabase/components/TextEditor"; import _ from "underscore"; -type CodeSampleOption = { - name: string, - value: string, - source: () => string, - mode: string -}; +import type { CodeSampleOption } from "metabase/public/lib/code"; type Props = { className?: string, title?: string, options?: Array<CodeSampleOption>, - onChangeOption: (option: ?CodeSampleOption) => void + onChangeOption?: (option: ?CodeSampleOption) => void }; type State = { name: ?string, }; -export default class CodeSample extends Component<*, Props, State> { +export default class CodeSample extends Component { + props: Props; state: State; constructor(props: Props) { diff --git a/frontend/src/metabase/public/components/widgets/EmbedCodePane.jsx b/frontend/src/metabase/public/components/widgets/EmbedCodePane.jsx index 3958f551e00..173b9f0ec12 100644 --- a/frontend/src/metabase/public/components/widgets/EmbedCodePane.jsx +++ b/frontend/src/metabase/public/components/widgets/EmbedCodePane.jsx @@ -15,7 +15,8 @@ import "ace/mode-ruby"; import "ace/mode-html"; import "ace/mode-jsx"; -import type { EmbedType, EmbeddableResource, EmbeddingParams, DisplayOptions } from "./EmbedModalContent"; +import type { EmbedType, DisplayOptions } from "./EmbedModalContent"; +import type { EmbeddableResource, EmbeddingParams } from "metabase/public/lib/types"; type Props = { className: string, @@ -30,7 +31,9 @@ type Props = { displayOptions: DisplayOptions } -export default class EmbedCodePane extends Component<*, Props, *> { +export default class EmbedCodePane extends Component { + props: Props; + _embedSample: ?CodeSample; render() { diff --git a/frontend/src/metabase/public/components/widgets/EmbedModalContent.jsx b/frontend/src/metabase/public/components/widgets/EmbedModalContent.jsx index 8e45a64699f..4133454a0d0 100644 --- a/frontend/src/metabase/public/components/widgets/EmbedModalContent.jsx +++ b/frontend/src/metabase/public/components/widgets/EmbedModalContent.jsx @@ -14,36 +14,36 @@ import { getSignedPreviewUrl, getUnsignedPreviewUrl, getSignedToken } from "meta import { getSiteUrl, getEmbeddingSecretKey, getIsPublicSharingEnabled, getIsApplicationEmbeddingEnabled } from "metabase/selectors/settings"; import { getUserIsAdmin } from "metabase/selectors/user"; -import type { Parameter, ParameterId } from "metabase/meta/types/Parameter"; - import MetabaseAnalytics from "metabase/lib/analytics"; +import type { Parameter, ParameterId } from "metabase/meta/types/Parameter"; +import type { EmbeddableResource, EmbeddingParams } from "metabase/public/lib/types"; + export type Pane = "preview"|"code"; export type EmbedType = null|"simple"|"application"; -export type EmbeddingParams = { - [key: string]: string -} - export type DisplayOptions = { theme: ?string, bordered: boolean, titled: boolean, } -export type EmbeddableResource = { - id: string, - public_uuid: string, - embedding_params: EmbeddingParams -} - type Props = { className?: string, - siteUrl: string, - secretKey: string, resource: EmbeddableResource, resourceType: string, resourceParameters: Parameter[], + + isAdmin: boolean, + siteUrl: string, + secretKey: string, + + // Flow doesn't understand these are provided by @connect? + // isPublicSharingEnabled: bool, + // isApplicationEmbeddingEnabled: bool, + + getPublicUrl: (resource: EmbeddableResource, extension: ?string) => string, + onUpdateEnableEmbedding: (enable_embedding: bool) => Promise<void>, onUpdateEmbeddingParams: (embedding_params: EmbeddingParams) => Promise<void>, onCreatePublicLink: () => Promise<void>, @@ -56,10 +56,9 @@ type State = { embedType: EmbedType, embeddingParams: EmbeddingParams, displayOptions: DisplayOptions, - parameterValues: { [id: ParameterId]: string } + parameterValues: { [id: ParameterId]: string }, }; - const mapStateToProps = (state, props) => ({ isAdmin: getUserIsAdmin(state, props), siteUrl: getSiteUrl(state, props), @@ -69,7 +68,8 @@ const mapStateToProps = (state, props) => ({ }) @connect(mapStateToProps) -export default class EmbedModalContent extends Component<*, Props, State> { +export default class EmbedModalContent extends Component { + props: Props; state: State; constructor(props: Props) { @@ -168,6 +168,7 @@ export default class EmbedModalContent extends Component<*, Props, State> { {/* Center only using margins because */} <div className="ml-auto mr-auto" style={{maxWidth: 1040}}> <SharingPane + // $FlowFixMe: Flow doesn't understand these are provided by @connect? {...this.props} publicUrl={getUnsignedPreviewUrl(siteUrl, resourceType, resource.public_uuid, displayOptions)} iframeUrl={getUnsignedPreviewUrl(siteUrl, resourceType, resource.public_uuid, displayOptions)} diff --git a/frontend/src/metabase/public/components/widgets/EmbedWidget.jsx b/frontend/src/metabase/public/components/widgets/EmbedWidget.jsx index 05a759a4ba8..af42e388e7f 100644 --- a/frontend/src/metabase/public/components/widgets/EmbedWidget.jsx +++ b/frontend/src/metabase/public/components/widgets/EmbedWidget.jsx @@ -12,12 +12,29 @@ import EmbedModalContent from "./EmbedModalContent"; import cx from "classnames"; +import type { EmbeddableResource, EmbeddingParams } from "metabase/public/lib/types"; +import type { Parameter } from "metabase/meta/types/Parameter"; + type Props = { className?: string, - resourceType: string + + resource: EmbeddableResource, + resourceType: string, + resourceParameters: Parameter[], + + siteUrl: string, + secretKey: string, + isAdmin: boolean, + + getPublicUrl: (resource: EmbeddableResource, extension: ?string) => string, + + onUpdateEnableEmbedding: (enable_embedding: bool) => Promise<void>, + onUpdateEmbeddingParams: (embedding_params: EmbeddingParams) => Promise<void>, + onCreatePublicLink: () => Promise<void>, + onDisablePublicLink: () => Promise<void>, }; -export default class EmbedWidget extends Component<*, Props, *> { +export default class EmbedWidget extends Component { props: Props; _modal: ?ModalWithTrigger @@ -38,7 +55,7 @@ export default class EmbedWidget extends Component<*, Props, *> { > <EmbedModalContent {...this.props} - onClose={() => this._modal && this._modal.close()} + onClose={() => { this._modal && this._modal.close() }} className="full-height" /> </ModalWithTrigger> diff --git a/frontend/src/metabase/public/components/widgets/SharingPane.jsx b/frontend/src/metabase/public/components/widgets/SharingPane.jsx index 5e89500a23e..25100f1aec3 100644 --- a/frontend/src/metabase/public/components/widgets/SharingPane.jsx +++ b/frontend/src/metabase/public/components/widgets/SharingPane.jsx @@ -12,7 +12,8 @@ import { getPublicEmbedHTML } from "metabase/public/lib/code"; import cx from "classnames"; -import type { EmbedType, EmbeddableResource } from "./EmbedModalContent"; +import type { EmbedType } from "./EmbedModalContent"; +import type { EmbeddableResource } from "metabase/public/lib/types"; import MetabaseAnalytics from "metabase/lib/analytics"; @@ -20,9 +21,12 @@ type Props = { resourceType: string, resource: EmbeddableResource, extensions?: string[], + isAdmin: bool, + isPublicSharingEnabled: bool, isApplicationEmbeddingEnabled: bool, + onCreatePublicLink: () => Promise<void>, onDisablePublicLink: () => Promise<void>, getPublicUrl: (resource: EmbeddableResource, extension: ?string) => string, @@ -33,15 +37,11 @@ type State = { extension: ?string, }; -export default class SharingPane extends Component<*, Props, State> { +export default class SharingPane extends Component { props: Props; - state: State; - constructor(props: Props) { - super(props); - this.state = { - extension: null - }; - } + state: State = { + extension: null + }; static defaultProps = { extensions: [] diff --git a/frontend/src/metabase/public/containers/PublicApp.jsx b/frontend/src/metabase/public/containers/PublicApp.jsx index 9405c6015ae..4d41faef88d 100644 --- a/frontend/src/metabase/public/containers/PublicApp.jsx +++ b/frontend/src/metabase/public/containers/PublicApp.jsx @@ -16,7 +16,9 @@ const mapStateToProps = (state, props) => ({ }); @connect(mapStateToProps) -export default class PublicApp extends Component<*, Props, *> { +export default class PublicApp extends Component { + props: Props; + render() { const { children, errorPage } = this.props; if (errorPage) { diff --git a/frontend/src/metabase/public/containers/PublicDashboard.jsx b/frontend/src/metabase/public/containers/PublicDashboard.jsx index 6fed2ce5ba6..aa9c4f505ef 100644 --- a/frontend/src/metabase/public/containers/PublicDashboard.jsx +++ b/frontend/src/metabase/public/containers/PublicDashboard.jsx @@ -63,7 +63,9 @@ type Props = { @connect(mapStateToProps, mapDispatchToProps) @DashboardControls -export default class PublicDashboard extends Component<*, Props, *> { +export default class PublicDashboard extends Component { + props: Props; + // $FlowFixMe async componentWillMount() { const { initialize, fetchDashboard, fetchDashboardCardData, setErrorPage, location, params: { uuid, token }} = this.props; diff --git a/frontend/src/metabase/public/containers/PublicQuestion.jsx b/frontend/src/metabase/public/containers/PublicQuestion.jsx index 5e94aa74f8f..1978c7c98de 100644 --- a/frontend/src/metabase/public/containers/PublicQuestion.jsx +++ b/frontend/src/metabase/public/containers/PublicQuestion.jsx @@ -45,7 +45,7 @@ const mapDispatchToProps = { @connect(null, mapDispatchToProps) @ExplicitSize -export default class PublicQuestion extends Component<*, Props, State> { +export default class PublicQuestion extends Component { props: Props; state: State; diff --git a/frontend/src/metabase/public/lib/code.js b/frontend/src/metabase/public/lib/code.js index a0d5b217701..b1184956a38 100644 --- a/frontend/src/metabase/public/lib/code.js +++ b/frontend/src/metabase/public/lib/code.js @@ -1,25 +1,33 @@ +/* @flow */ import { optionsToHashParams } from "./embed"; -export const getPublicEmbedOptions = ({ iframeUrl }) => [ +export type CodeSampleOption = { + name: string, + source: () => string, + mode?: string, + embedOption?: string +}; + +export const getPublicEmbedOptions = ({ iframeUrl }: { iframeUrl: string }): CodeSampleOption[] => [ { name: "HTML", source: () => html({ iframeUrl: `"${iframeUrl}"` }), mode: "ace/mode/html" } ]; -export const getSignedEmbedOptions = () => [ +export const getSignedEmbedOptions = (): CodeSampleOption[] => [ { name: "Mustache", source: () => html({ iframeUrl: `"{{iframeUrl}}"`, mode: "ace/mode/html" })}, { name: "Pug / Jade", source: () => pug({ iframeUrl: `iframeUrl` })}, { name: "ERB", source: () => html({ iframeUrl: `"<%= @iframe_url %>"` })}, { name: "JSX", source: () => jsx({ iframeUrl: `{iframeUrl}`, mode: "ace/mode/jsx" })}, ]; -export const getSignTokenOptions = (params) => [ +export const getSignTokenOptions = (params: any): CodeSampleOption[] => [ { name: "Node.js", source: () => node(params), mode: "ace/mode/javascript", embedOption: "Pug / Jade" }, { name: "Ruby", source: () => ruby(params), mode: "ace/mode/ruby", embedOption: "ERB" }, { name: "Python", source: () => python(params), mode: "ace/mode/python" }, { name: "Clojure", source: () => clojure(params), mode: "ace/mode/clojure" }, ]; -export const getPublicEmbedHTML = (iframeUrl) => html({ iframeUrl: JSON.stringify(iframeUrl )}); +export const getPublicEmbedHTML = (iframeUrl: string): string => html({ iframeUrl: JSON.stringify(iframeUrl )}); const html = ({ iframeUrl }) => `<iframe diff --git a/frontend/src/metabase/public/lib/types.js b/frontend/src/metabase/public/lib/types.js new file mode 100644 index 00000000000..7aa0f341524 --- /dev/null +++ b/frontend/src/metabase/public/lib/types.js @@ -0,0 +1,11 @@ +/* @flow */ + +export type EmbeddingParams = { + [key: string]: string +} + +export type EmbeddableResource = { + id: string, + public_uuid: string, + embedding_params: EmbeddingParams +} diff --git a/frontend/src/metabase/qb/components/TimeseriesFilterWidget.jsx b/frontend/src/metabase/qb/components/TimeseriesFilterWidget.jsx index 23a1601f49a..a7bc8ac5372 100644 --- a/frontend/src/metabase/qb/components/TimeseriesFilterWidget.jsx +++ b/frontend/src/metabase/qb/components/TimeseriesFilterWidget.jsx @@ -30,7 +30,7 @@ import type { TableMetadata } from "metabase/meta/types/Metadata"; import type { FieldFilter } from "metabase/meta/types/Query"; type Props = { - className: string, + className?: string, card: CardObject, tableMetadata: TableMetadata, setDatasetQuery: ( @@ -45,8 +45,10 @@ type State = { currentFilter: any }; -export default class TimeseriesFilterWidget extends Component<*, Props, State> { - state = { +export default class TimeseriesFilterWidget extends Component { + props: Props; + state: State = { + // $FlowFixMe filter: null, filterIndex: -1, currentFilter: null diff --git a/frontend/src/metabase/qb/components/TimeseriesGroupingWidget.jsx b/frontend/src/metabase/qb/components/TimeseriesGroupingWidget.jsx index c5adb221ad6..c037ce0f097 100644 --- a/frontend/src/metabase/qb/components/TimeseriesGroupingWidget.jsx +++ b/frontend/src/metabase/qb/components/TimeseriesGroupingWidget.jsx @@ -25,7 +25,9 @@ type Props = { ) => void }; -export default class TimeseriesGroupingWidget extends Component<*, Props, *> { +export default class TimeseriesGroupingWidget extends Component { + props: Props; + _popover: ?any; render() { diff --git a/frontend/src/metabase/query_builder/components/ActionsWidget.jsx b/frontend/src/metabase/query_builder/components/ActionsWidget.jsx index 981c66149e1..fba9d3ffc8d 100644 --- a/frontend/src/metabase/query_builder/components/ActionsWidget.jsx +++ b/frontend/src/metabase/query_builder/components/ActionsWidget.jsx @@ -24,12 +24,19 @@ type Props = { setCardAndRun: (card: Card) => void }; +type State = { + isVisible: boolean, + isOpen: boolean, + selectedActionIndex: ?number +}; + const CIRCLE_SIZE = 48; const NEEDLE_SIZE = 20; const POPOVER_WIDTH = 350; -export default class ActionsWidget extends Component<*, Props, *> { - state = { +export default class ActionsWidget extends Component { + props: Props; + state: State = { isVisible: false, isOpen: false, selectedActionIndex: null diff --git a/frontend/src/metabase/query_builder/components/filters/DateOperatorSelector.jsx b/frontend/src/metabase/query_builder/components/filters/DateOperatorSelector.jsx index 5aca73f9400..1ac002057af 100644 --- a/frontend/src/metabase/query_builder/components/filters/DateOperatorSelector.jsx +++ b/frontend/src/metabase/query_builder/components/filters/DateOperatorSelector.jsx @@ -8,12 +8,10 @@ import { titleCase } from "humanize-plus"; import Icon from "metabase/components/Icon"; -type Operator = { - name: string -} +import type { Operator } from "./pickers/DatePicker"; type Props = { - operator: string, + operator: ?string, operators: Operator[], onOperatorChange: (o: Operator) => void, hideTimeSelectors?: bool @@ -23,7 +21,7 @@ type State = { expanded: bool }; -export default class DateOperatorSelector extends Component<*, Props, State> { +export default class DateOperatorSelector extends Component { props: Props; state: State; diff --git a/frontend/src/metabase/query_builder/components/filters/FilterList.jsx b/frontend/src/metabase/query_builder/components/filters/FilterList.jsx index b83df09ce9e..b73ae5505d8 100644 --- a/frontend/src/metabase/query_builder/components/filters/FilterList.jsx +++ b/frontend/src/metabase/query_builder/components/filters/FilterList.jsx @@ -6,21 +6,21 @@ import { findDOMNode } from 'react-dom'; import FilterWidget from './FilterWidget.jsx'; import type { Filter } from "metabase/meta/types/Query"; -import type { Table } from "metabase/meta/types/Table"; +import type { TableMetadata } from "metabase/meta/types/Metadata"; type Props = { filters: Array<Filter>, - tableMetadata: Table, - removeFilter: (index: number) => void, - updateFilter: (index: number, filter: Filter) => void, - maxDisplayValues?: bool + tableMetadata: TableMetadata, + removeFilter?: (index: number) => void, + updateFilter?: (index: number, filter: Filter) => void, + maxDisplayValues?: number }; type State = { shouldScroll: bool }; -export default class FilterList extends Component<*, Props, State> { +export default class FilterList extends Component { props: Props; state: State; diff --git a/frontend/src/metabase/query_builder/components/filters/FilterPopover.jsx b/frontend/src/metabase/query_builder/components/filters/FilterPopover.jsx index e8aca1d2063..fbca456e1b2 100644 --- a/frontend/src/metabase/query_builder/components/filters/FilterPopover.jsx +++ b/frontend/src/metabase/query_builder/components/filters/FilterPopover.jsx @@ -19,22 +19,22 @@ import { singularize } from "metabase/lib/formatting"; import cx from "classnames"; -import type { FieldFilter, ConcreteField, ExpressionClause } from "metabase/meta/types/Query"; +import type { Filter, FieldFilter, ConcreteField, ExpressionClause } from "metabase/meta/types/Query"; import type { TableMetadata, FieldMetadata, Operator } from "metabase/meta/types/Metadata"; type Props = { - filter?: FieldFilter, - onCommitFilter: () => void, + filter?: Filter, + onCommitFilter: (filter: Filter) => void, onClose: () => void, tableMetadata: TableMetadata, - customFields: ExpressionClause + customFields?: ExpressionClause } type State = { filter: FieldFilter } -export default class FilterPopover extends Component<*, Props, State> { +export default class FilterPopover extends Component { props: Props; state: State; @@ -199,7 +199,8 @@ export default class FilterPopover extends Component<*, Props, State> { return ( <SelectPicker options={operatorField.values} - values={values} + // $FlowFixMe + values={(values: Array<string>)} onValuesChange={onValuesChange} placeholder={placeholder} multi={operator.multi} @@ -209,7 +210,8 @@ export default class FilterPopover extends Component<*, Props, State> { } else if (operatorField.type === "text") { return ( <TextPicker - values={values} + // $FlowFixMe + values={(values: Array<string>)} onValuesChange={onValuesChange} placeholder={placeholder} multi={operator.multi} @@ -219,7 +221,8 @@ export default class FilterPopover extends Component<*, Props, State> { } else if (operatorField.type === "number") { return ( <NumberPicker - values={values} + // $FlowFixMe + values={(values: Array<number|null>)} onValuesChange={onValuesChange} placeholder={placeholder} multi={operator.multi} diff --git a/frontend/src/metabase/query_builder/components/filters/FilterWidget.jsx b/frontend/src/metabase/query_builder/components/filters/FilterWidget.jsx index 274faf29b88..6da831633bd 100644 --- a/frontend/src/metabase/query_builder/components/filters/FilterWidget.jsx +++ b/frontend/src/metabase/query_builder/components/filters/FilterWidget.jsx @@ -15,22 +15,23 @@ import { isDate } from "metabase/lib/schema_metadata"; import cx from "classnames"; import _ from "underscore"; -import type { FieldFilter } from "metabase/meta/types/Query"; +import type { Filter } from "metabase/meta/types/Query"; import type { TableMetadata } from "metabase/meta/types/Metadata"; type Props = { - filter: FieldFilter, + filter: Filter, tableMetadata: TableMetadata, index: number, - updateFilter: (index: number, field: FieldFilter) => void, - removeFilter: (index: number) => void, + updateFilter?: (index: number, field: Filter) => void, + removeFilter?: (index: number) => void, maxDisplayValues?: number } type State = { isOpen: bool } -export default class FilterWidget extends Component<*, Props, State> { +export default class FilterWidget extends Component { + props: Props; state: State; constructor(props: Props) { @@ -144,7 +145,7 @@ export default class FilterWidget extends Component<*, Props, State> { <FilterPopover filter={this.props.filter} tableMetadata={this.props.tableMetadata} - onCommitFilter={(filter) => this.props.updateFilter(this.props.index, filter)} + onCommitFilter={(filter) => this.props.updateFilter && this.props.updateFilter(this.props.index, filter)} onClose={this.close} /> </Popover> diff --git a/frontend/src/metabase/query_builder/components/filters/OperatorSelector.jsx b/frontend/src/metabase/query_builder/components/filters/OperatorSelector.jsx index b6acdcbde66..8c08585fde9 100644 --- a/frontend/src/metabase/query_builder/components/filters/OperatorSelector.jsx +++ b/frontend/src/metabase/query_builder/components/filters/OperatorSelector.jsx @@ -20,7 +20,7 @@ type State = { expanded: bool }; -export default class OperatorSelector extends Component<*, Props, State> { +export default class OperatorSelector extends Component { props: Props; state: State; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx index 241aaaea4de..fd921191f55 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx @@ -69,7 +69,7 @@ type CurrentPickerState = { showUnits: boolean }; -class CurrentPicker extends Component<*, CurrentPickerProps, CurrentPickerState> { +class CurrentPicker extends Component { props: CurrentPickerProps; state: CurrentPickerState; @@ -223,13 +223,21 @@ type Props = { className?: string, filter: FieldFilter, onFilterChange: (filter: FieldFilter) => void, - className: ?string, - hideEmptinessOperators: boolean, // Don't show is empty / not empty dialog + hideEmptinessOperators?: boolean, // Don't show is empty / not empty dialog hideTimeSelectors?: boolean, includeAllTime?: boolean, } -export default class DatePicker extends Component<*, Props, *> { +type State = { + operators: Operator[] +} + +export default class DatePicker extends Component { + props: Props; + state: State = { + operators: [] + }; + static propTypes = { filter: PropTypes.array.isRequired, onFilterChange: PropTypes.func.isRequired, @@ -244,7 +252,7 @@ export default class DatePicker extends Component<*, Props, *> { const operator = this._getOperator(operators) || operators[0]; this.props.onFilterChange(operator.init(this.props.filter)); - this.setState({operators}) + this.setState({ operators }) } _getOperator(operators: Operator[]) { diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/NumberPicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/NumberPicker.jsx index 8fa6e7098ee..763d79577fc 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/NumberPicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/NumberPicker.jsx @@ -7,9 +7,10 @@ import TextPicker from "./TextPicker.jsx"; type Props = { values: Array<number|null>, - onValuesChange: (values: Array<number|null>) => void, + onValuesChange: (values: any[]) => void, placeholder?: string, multi?: bool, + onCommit: () => void, } type State = { @@ -17,7 +18,7 @@ type State = { validations: bool[] } -export default class NumberPicker extends Component<*, Props, State> { +export default class NumberPicker extends Component { props: Props; state: State; @@ -60,10 +61,12 @@ export default class NumberPicker extends Component<*, Props, State> { } render() { + // $FlowFixMe + const values: Array<string|null> = this.state.stringValues.slice(0, this.props.values.length); return ( <TextPicker {...this.props} - values={this.state.stringValues.slice(0, this.props.values.length)} + values={values} validations={this.state.validations} onValuesChange={(values) => this.onValuesChange(values)} /> diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/RelativeDatePicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/RelativeDatePicker.jsx index 50be208d149..0019b27ccd6 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/RelativeDatePicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/RelativeDatePicker.jsx @@ -35,7 +35,7 @@ type State = { showUnits: bool } -export default class RelativeDatePicker extends Component<*, Props, State> { +export default class RelativeDatePicker extends Component { props: Props; state: State; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/SelectPicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/SelectPicker.jsx index 040d960c548..b325ab9cafc 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/SelectPicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/SelectPicker.jsx @@ -19,7 +19,7 @@ type SelectOption = { type Props = { options: Array<SelectOption>, values: Array<string>, - onValuesChange: (values: any) => void, + onValuesChange: (values: any[]) => void, placeholder?: string, multi?: bool } @@ -29,7 +29,7 @@ type State = { searchRegex: ?RegExp, } -export default class SelectPicker extends Component<*, Props, State> { +export default class SelectPicker extends Component { state: State; props: Props; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/SpecificDatePicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/SpecificDatePicker.jsx index 83d9ab5ae3a..4560c1febfd 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/SpecificDatePicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/SpecificDatePicker.jsx @@ -27,7 +27,7 @@ type State = { showCalendar: bool } -export default class SpecificDatePicker extends Component<*, Props, State> { +export default class SpecificDatePicker extends Component { props: Props; state: State; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/TextPicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/TextPicker.jsx index 29e58cb2e13..1009b1f2882 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/TextPicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/TextPicker.jsx @@ -9,14 +9,21 @@ import _ from "underscore"; type Props = { values: Array<string|null>, - onValuesChange: (values: Array<string|null>) => void, + onValuesChange: (values: any[]) => void, validations: bool[], placeholder?: string, multi?: bool, onCommit: () => void, }; -export default class TextPicker extends Component<*, Props, *> { +type State = { + fieldString: string, +} + +export default class TextPicker extends Component { + props: Props; + state: State; + static propTypes = { values: PropTypes.array.isRequired, onValuesChange: PropTypes.func.isRequired, diff --git a/frontend/src/metabase/visualizations/components/ChartClickActions.jsx b/frontend/src/metabase/visualizations/components/ChartClickActions.jsx index 13182daf6a5..73b71b471e6 100644 --- a/frontend/src/metabase/visualizations/components/ChartClickActions.jsx +++ b/frontend/src/metabase/visualizations/components/ChartClickActions.jsx @@ -52,7 +52,7 @@ Object.values(SECTIONS).map((section, index) => { }); type Props = { - clicked: ClickObject, + clicked: ?ClickObject, clickActions: ?ClickAction[], onChangeCardAndRun: (card: ?Card) => void, onClose: () => void @@ -62,7 +62,8 @@ type State = { popoverAction: ?ClickAction; } -export default class ChartClickActions extends Component<*, Props, State> { +export default class ChartClickActions extends Component { + props: Props; state: State = { popoverAction: null }; diff --git a/frontend/src/metabase/visualizations/components/FunnelBar.jsx b/frontend/src/metabase/visualizations/components/FunnelBar.jsx index 1028592b937..50eb5245c74 100644 --- a/frontend/src/metabase/visualizations/components/FunnelBar.jsx +++ b/frontend/src/metabase/visualizations/components/FunnelBar.jsx @@ -9,7 +9,9 @@ import { assocIn } from "icepick"; import type { VisualizationProps } from "metabase/meta/types/Visualization"; -export default class BarFunnel extends Component<*, VisualizationProps, *> { +export default class BarFunnel extends Component { + props: VisualizationProps; + render() { return ( <BarChart diff --git a/frontend/src/metabase/visualizations/components/FunnelNormal.jsx b/frontend/src/metabase/visualizations/components/FunnelNormal.jsx index 104b44a799a..17f43b109c8 100644 --- a/frontend/src/metabase/visualizations/components/FunnelNormal.jsx +++ b/frontend/src/metabase/visualizations/components/FunnelNormal.jsx @@ -27,7 +27,9 @@ type StepInfo = { clicked?: ClickObject, }; -export default class Funnel extends Component<*, VisualizationProps, *> { +export default class Funnel extends Component { + props: VisualizationProps; + render() { const { className, series, gridSize, hovered, onHoverChange, onVisualizationClick, visualizationIsClickable } = this.props; @@ -35,7 +37,7 @@ export default class Funnel extends Component<*, VisualizationProps, *> { const metricIndex = 1; const cols = series[0].data.cols; // $FlowFixMe - const rows = series.map(s => s.data.rows[0]); + const rows: number[][] = series.map(s => s.data.rows[0]); const funnelSmallSize = gridSize && (gridSize.width < 7 || gridSize.height <= 5); diff --git a/frontend/src/metabase/visualizations/components/LineAreaBarChart.jsx b/frontend/src/metabase/visualizations/components/LineAreaBarChart.jsx index 17a6b75f3aa..759c375e64b 100644 --- a/frontend/src/metabase/visualizations/components/LineAreaBarChart.jsx +++ b/frontend/src/metabase/visualizations/components/LineAreaBarChart.jsx @@ -43,7 +43,9 @@ for (let i = 0; i < MAX_SERIES; i++) { import type { VisualizationProps } from "metabase/meta/types/Visualization"; -export default class LineAreaBarChart extends Component<*, VisualizationProps, *> { +export default class LineAreaBarChart extends Component { + props: VisualizationProps; + static identifier: string; static renderer: (element: Element, props: VisualizationProps) => any; @@ -186,6 +188,7 @@ export default class LineAreaBarChart extends Component<*, VisualizationProps, * let titleHeaderSeries, multiseriesHeaderSeries; + // $FlowFixMe let originalSeries = series._raw || series; let cardIds = _.uniq(originalSeries.map(s => s.card.id)) diff --git a/frontend/src/metabase/visualizations/components/PinMap.jsx b/frontend/src/metabase/visualizations/components/PinMap.jsx index e642709d999..a5f1371878b 100644 --- a/frontend/src/metabase/visualizations/components/PinMap.jsx +++ b/frontend/src/metabase/visualizations/components/PinMap.jsx @@ -31,7 +31,10 @@ const MAP_COMPONENTS_BY_TYPE = { "tiles": LeafletTilePinMap, } -export default class PinMap extends Component<*, Props, State> { +export default class PinMap extends Component { + props: Props; + state: State; + static uiName = "Pin Map"; static identifier = "pin_map"; static iconName = "pinmap"; diff --git a/frontend/src/metabase/visualizations/components/TableInteractive.jsx b/frontend/src/metabase/visualizations/components/TableInteractive.jsx index 32e26d8220e..af30802aff9 100644 --- a/frontend/src/metabase/visualizations/components/TableInteractive.jsx +++ b/frontend/src/metabase/visualizations/components/TableInteractive.jsx @@ -49,7 +49,7 @@ type CellRendererProps = { type GridComponent = Component<void, void, void> & { recomputeGridSize: () => void } @ExplicitSize -export default class TableInteractive extends Component<*, Props, State> { +export default class TableInteractive extends Component { state: State; props: Props; diff --git a/frontend/src/metabase/visualizations/components/TableSimple.jsx b/frontend/src/metabase/visualizations/components/TableSimple.jsx index c79e1791020..d8ebaca1b90 100644 --- a/frontend/src/metabase/visualizations/components/TableSimple.jsx +++ b/frontend/src/metabase/visualizations/components/TableSimple.jsx @@ -32,7 +32,8 @@ type State = { } @ExplicitSize -export default class TableSimple extends Component<*, Props, State> { +export default class TableSimple extends Component { + props: Props; state: State; constructor(props: Props) { diff --git a/frontend/src/metabase/visualizations/components/Visualization.jsx b/frontend/src/metabase/visualizations/components/Visualization.jsx index f81cef63a66..d476580e73e 100644 --- a/frontend/src/metabase/visualizations/components/Visualization.jsx +++ b/frontend/src/metabase/visualizations/components/Visualization.jsx @@ -84,7 +84,7 @@ type Props = { type State = { series: ?Series, - CardVisualization: ?(Component<*, VisualizationSettings, *> & { + CardVisualization: ?(Component<void, VisualizationSettings, void> & { checkRenderable: (any, any) => void, noHeader: boolean }), @@ -98,7 +98,7 @@ type State = { } @ExplicitSize -export default class Visualization extends Component<*, Props, State> { +export default class Visualization extends Component { state: State; props: Props; @@ -414,12 +414,14 @@ export default class Visualization extends Component<*, Props, State> { series={series} hovered={hovered} /> - <ChartClickActions - clicked={clicked} - clickActions={clickActions} - onChangeCardAndRun={this.props.onChangeCardAndRun ? this.handleOnChangeCardAndRun : null} - onClose={() => this.setState({ clicked: null })} - /> + { this.props.onChangeCardAndRun && + <ChartClickActions + clicked={clicked} + clickActions={clickActions} + onChangeCardAndRun={this.handleOnChangeCardAndRun} + onClose={() => this.setState({ clicked: null })} + /> + } </div> ); } diff --git a/frontend/src/metabase/visualizations/index.js b/frontend/src/metabase/visualizations/index.js index 0297c20a1cc..f9d9595e62a 100644 --- a/frontend/src/metabase/visualizations/index.js +++ b/frontend/src/metabase/visualizations/index.js @@ -62,6 +62,7 @@ export function getVisualizationTransformed(series: Series) { series = CardVisualization.transformSeries(series); } if (series !== lastSeries) { + // $FlowFixMe series = [...series]; // $FlowFixMe series._raw = lastSeries; diff --git a/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js b/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js index 0752437e658..89481add07b 100644 --- a/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js +++ b/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js @@ -35,7 +35,7 @@ import { parseTimestamp } from "metabase/lib/time"; import { datasetContainsNoResults } from "metabase/lib/dataset"; -import type { Series, ClickObject } from "metabase/meta/types/Visualization" +import type { SingleSeries, ClickObject } from "metabase/meta/types/Visualization" const MIN_PIXELS_PER_TICK = { x: 100, y: 32 }; const BAR_PADDING_RATIO = 0.2; @@ -109,7 +109,7 @@ function initChart(chart, element) { function applyChartTimeseriesXAxis(chart, settings, series, xValues, xDomain, xInterval) { // find the first nonempty single series // $FlowFixMe - const firstSeries: Series = _.find(series, (s) => !datasetContainsNoResults(s.data)); + const firstSeries: SingleSeries = _.find(series, (s) => !datasetContainsNoResults(s.data)); // setup an x-axis where the dimension is a timeseries let dimensionColumn = firstSeries.data.cols[0]; @@ -170,7 +170,7 @@ function applyChartTimeseriesXAxis(chart, settings, series, xValues, xDomain, xI function applyChartQuantitativeXAxis(chart, settings, series, xValues, xDomain, xInterval) { // find the first nonempty single series // $FlowFixMe - const firstSeries: Series = _.find(series, (s) => !datasetContainsNoResults(s.data)); + const firstSeries: SingleSeries = _.find(series, (s) => !datasetContainsNoResults(s.data)); const dimensionColumn = firstSeries.data.cols[0]; if (settings["graph.x_axis.labels_enabled"]) { @@ -211,7 +211,7 @@ function applyChartQuantitativeXAxis(chart, settings, series, xValues, xDomain, function applyChartOrdinalXAxis(chart, settings, series, xValues) { // find the first nonempty single series // $FlowFixMe - const firstSeries: Series = _.find(series, (s) => !datasetContainsNoResults(s.data)); + const firstSeries: SingleSeries = _.find(series, (s) => !datasetContainsNoResults(s.data)); const dimensionColumn = firstSeries.data.cols[0]; @@ -858,7 +858,7 @@ export default function lineAreaBar(element, { series, onHoverChange, onVisualiz // find the first nonempty single series // $FlowFixMe - const firstSeries: Series = _.find(series, (s) => !datasetContainsNoResults(s.data)); + const firstSeries: SingleSeries = _.find(series, (s) => !datasetContainsNoResults(s.data)); const isDimensionTimeseries = dimensionIsTimeseries(firstSeries.data); const isDimensionNumeric = dimensionIsNumeric(firstSeries.data); diff --git a/frontend/src/metabase/visualizations/visualizations/Funnel.jsx b/frontend/src/metabase/visualizations/visualizations/Funnel.jsx index 4050d610c05..dd73f1a37a5 100644 --- a/frontend/src/metabase/visualizations/visualizations/Funnel.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Funnel.jsx @@ -17,7 +17,9 @@ import cx from "classnames"; import type { VisualizationProps } from "metabase/meta/types/Visualization"; -export default class Funnel extends Component<*, VisualizationProps, *> { +export default class Funnel extends Component { + props: VisualizationProps; + static uiName = "Funnel"; static identifier = "funnel"; static iconName = "funnel"; @@ -114,6 +116,7 @@ export default class Funnel extends Component<*, VisualizationProps, *> { <div className={cx(className, "flex flex-column p1")}> <LegendHeader className="flex-no-shrink" + // $FlowFixMe series={series._raw || series} actionButtons={actionButtons} onChangeCardAndRun={onChangeCardAndRun} diff --git a/frontend/src/metabase/visualizations/visualizations/Map.jsx b/frontend/src/metabase/visualizations/visualizations/Map.jsx index cd65132915a..1be87044162 100644 --- a/frontend/src/metabase/visualizations/visualizations/Map.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Map.jsx @@ -14,7 +14,9 @@ import type { VisualizationProps } from "metabase/meta/types/Visualization"; import _ from "underscore"; -export default class Map extends Component<*, VisualizationProps, *> { +export default class Map extends Component { + props: VisualizationProps; + static uiName = "Map"; static identifier = "map"; static iconName = "pinmap"; diff --git a/frontend/src/metabase/visualizations/visualizations/PieChart.jsx b/frontend/src/metabase/visualizations/visualizations/PieChart.jsx index 73cc1b27ae7..aa494237f81 100644 --- a/frontend/src/metabase/visualizations/visualizations/PieChart.jsx +++ b/frontend/src/metabase/visualizations/visualizations/PieChart.jsx @@ -31,9 +31,9 @@ const PERCENT_REGEX = /percent/i; import type { VisualizationProps } from "metabase/meta/types/Visualization"; -type Props = VisualizationProps; +export default class PieChart extends Component { + props: VisualizationProps; -export default class PieChart extends Component<*, Props, *> { static uiName = "Pie"; static identifier = "pie"; static iconName = "pie"; diff --git a/frontend/src/metabase/visualizations/visualizations/Progress.jsx b/frontend/src/metabase/visualizations/visualizations/Progress.jsx index 1cf8fa459e3..5141e68ec6a 100644 --- a/frontend/src/metabase/visualizations/visualizations/Progress.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Progress.jsx @@ -17,7 +17,9 @@ const MAX_BAR_HEIGHT = 65; import type { VisualizationProps } from "metabase/meta/types/Visualization"; -export default class Progress extends Component<*, VisualizationProps, *> { +export default class Progress extends Component { + props: VisualizationProps; + static uiName = "Progress"; static identifier = "progress"; static iconName = "progress"; diff --git a/frontend/src/metabase/visualizations/visualizations/Scalar.jsx b/frontend/src/metabase/visualizations/visualizations/Scalar.jsx index a973509d374..27aed59e259 100644 --- a/frontend/src/metabase/visualizations/visualizations/Scalar.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Scalar.jsx @@ -16,7 +16,9 @@ import d3 from "d3"; import type { VisualizationProps } from "metabase/meta/types/Visualization"; -export default class Scalar extends Component<*, VisualizationProps, *> { +export default class Scalar extends Component { + props: VisualizationProps; + static uiName = "Number"; static identifier = "scalar"; static iconName = "number"; diff --git a/frontend/src/metabase/visualizations/visualizations/Table.jsx b/frontend/src/metabase/visualizations/visualizations/Table.jsx index d45ac9c8611..07840ddd15d 100644 --- a/frontend/src/metabase/visualizations/visualizations/Table.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Table.jsx @@ -29,7 +29,8 @@ type State = { data: ?DatasetData } -export default class Table extends Component<*, Props, State> { +export default class Table extends Component { + props: Props; state: State; static uiName = "Table"; @@ -126,7 +127,13 @@ export default class Table extends Component<*, Props, State> { const sort = getIn(card, ["dataset_query", "query", "order_by"]) || null; const isPivoted = settings["table.pivot"]; const TableComponent = isDashboard ? TableSimple : TableInteractive; + + if (!data) { + return null; + } + return ( + // $FlowFixMe <TableComponent {...this.props} data={data} -- GitLab