From bceca3b31e90e6ab5d23ed4937b439e466baefbd Mon Sep 17 00:00:00 2001 From: Alexander Polyankin <alexander.polyankin@metabase.com> Date: Mon, 6 Dec 2021 23:33:46 +0300 Subject: [PATCH] Remove broken flow types (#19227) --- frontend/src/metabase/meta/Card.js | 68 ++++------ .../src/metabase/query_builder/actions.js | 29 +---- .../components/AlertListPopoverContent.jsx | 14 -- .../query_builder/components/AlertModals.jsx | 37 ------ .../components/BreakoutPopover.jsx | 20 +-- .../components/DimensionList.jsx | 41 +----- .../components/ExtendedOptions.jsx | 21 +-- .../query_builder/components/FieldList.jsx | 42 +----- .../query_builder/components/Filter.jsx | 32 +---- .../query_builder/components/FilterList.jsx | 11 -- .../components/GuiQueryEditor.jsx | 43 +----- .../components/NativeQueryEditor.jsx | 76 +---------- .../components/QueryVisualization.jsx | 40 ------ .../components/VisualizationResult.jsx | 27 +--- .../filters/DateOperatorSelector.jsx | 14 +- .../components/filters/DateUnitSelector.jsx | 14 +- .../components/filters/FilterOptions.jsx | 4 +- .../components/filters/FilterPopover.jsx | 46 ++----- .../filters/FilterPopoverPicker.jsx | 6 +- .../components/filters/FilterWidget.jsx | 27 +--- .../components/filters/FilterWidgetList.jsx | 23 +--- .../components/filters/OperatorSelector.jsx | 15 +-- .../components/filters/pickers/DatePicker.jsx | 89 ++----------- .../filters/pickers/DefaultPicker.jsx | 24 +--- .../filters/pickers/NumberPicker.jsx | 28 +--- .../filters/pickers/RelativeDatePicker.jsx | 30 +---- .../filters/pickers/SelectPicker.jsx | 30 +---- .../filters/pickers/SpecificDatePicker.jsx | 20 +-- .../components/filters/pickers/TextPicker.jsx | 21 +-- .../components/filters/pickers/TimePicker.jsx | 4 +- .../components/notebook/lib/steps.js | 99 +------------- .../components/notebook/steps/SortStep.jsx | 16 +-- .../template_tags/SnippetSidebar.jsx | 24 +--- .../template_tags/TagEditorParam.jsx | 17 --- .../template_tags/TagEditorSidebar.jsx | 24 +--- .../snippet-sidebar/SnippetRow.jsx | 2 - .../query_builder/containers/QueryBuilder.jsx | 4 - frontend/src/metabase/services.js | 36 ++---- .../components/CardRenderer.jsx | 15 +-- .../components/ChartClickActions.jsx | 31 +---- .../components/ColumnSettings.jsx | 15 +-- .../visualizations/components/FunnelBar.jsx | 5 +- .../components/FunnelNormal.jsx | 35 +---- .../components/LineAreaBarChart.jsx | 6 - .../visualizations/components/PinMap.jsx | 35 ++--- .../components/TableInteractive.jsx | 122 ++++-------------- .../visualizations/components/TableSimple.jsx | 30 +---- .../components/Visualization.jsx | 120 +---------------- .../settings/ChartNestedSettingColumns.jsx | 4 - .../settings/ChartNestedSettingSeries.jsx | 5 +- .../settings/ChartSettingNestedSettings.jsx | 70 +--------- frontend/src/metabase/visualizations/index.js | 6 +- .../visualizations/lib/LineAreaBarRenderer.js | 18 +-- .../visualizations/lib/RowRenderer.js | 4 +- .../src/metabase/visualizations/lib/action.js | 18 +-- .../metabase/visualizations/lib/apply_axis.js | 17 +-- .../src/metabase/visualizations/lib/errors.js | 18 +-- .../visualizations/lib/renderer_utils.js | 19 +-- .../metabase/visualizations/lib/settings.js | 111 +++++----------- .../visualizations/lib/settings/column.js | 115 ++++++----------- .../visualizations/lib/settings/nested.js | 52 +------- .../visualizations/lib/settings/series.js | 12 +- .../lib/settings/visualization.js | 24 ++-- .../src/metabase/visualizations/lib/table.js | 10 +- .../visualizations/lib/table_format.js | 92 ++----------- .../metabase/visualizations/lib/tooltip.js | 2 +- .../visualizations/visualizations/Funnel.jsx | 4 +- .../visualizations/visualizations/Gauge.jsx | 6 +- .../visualizations/visualizations/Map.jsx | 2 +- .../visualizations/ObjectDetail.jsx | 34 +---- .../visualizations/PieChart.jsx | 6 +- .../visualizations/PivotTable.jsx | 2 - .../visualizations/Progress.jsx | 7 +- .../visualizations/visualizations/Scalar.jsx | 11 +- .../visualizations/SmartScalar.jsx | 2 - .../visualizations/visualizations/Table.jsx | 36 +----- .../visualizations/visualizations/Text.jsx | 14 +- 77 files changed, 331 insertions(+), 1922 deletions(-) diff --git a/frontend/src/metabase/meta/Card.js b/frontend/src/metabase/meta/Card.js index 07a8b6dc8be..38f97a074fc 100644 --- a/frontend/src/metabase/meta/Card.js +++ b/frontend/src/metabase/meta/Card.js @@ -10,25 +10,10 @@ import * as Q_DEPRECATED from "metabase/lib/query"; // legacy import Utils from "metabase/lib/utils"; import * as Urls from "metabase/lib/urls"; -import type { StructuredQuery } from "metabase-types/types/Query"; -import type { - Card, - DatasetQuery, - StructuredDatasetQuery, - NativeDatasetQuery, -} from "metabase-types/types/Card"; -import type { - Parameter, - ParameterMapping, - ParameterValues, -} from "metabase-types/types/Parameter"; -import type Metadata from "metabase-lib/lib/metadata/Metadata"; -import type Table from "metabase-lib/lib/metadata/Table"; - // TODO Atte Keinänen 6/5/17 Should these be moved to corresponding metabase-lib classes? // Is there any reason behind keeping them in a central place? -export const STRUCTURED_QUERY_TEMPLATE: StructuredDatasetQuery = { +export const STRUCTURED_QUERY_TEMPLATE = { type: "query", database: null, query: { @@ -39,7 +24,7 @@ export const STRUCTURED_QUERY_TEMPLATE: StructuredDatasetQuery = { }, }; -export const NATIVE_QUERY_TEMPLATE: NativeDatasetQuery = { +export const NATIVE_QUERY_TEMPLATE = { type: "native", database: null, native: { @@ -48,25 +33,22 @@ export const NATIVE_QUERY_TEMPLATE: NativeDatasetQuery = { }, }; -export function isStructured(card: Card): boolean { +export function isStructured(card) { return card.dataset_query.type === "query"; } -export function isNative(card: Card): boolean { +export function isNative(card) { return card.dataset_query.type === "native"; } -export function cardVisualizationIsEquivalent( - cardA: Card, - cardB: Card, -): boolean { +export function cardVisualizationIsEquivalent(cardA, cardB) { return _.isEqual( _.pick(cardA, "display", "visualization_settings"), _.pick(cardB, "display", "visualization_settings"), ); } -export function cardQueryIsEquivalent(cardA: Card, cardB: Card): boolean { +export function cardQueryIsEquivalent(cardA, cardB) { cardA = updateIn(cardA, ["dataset_query", "parameters"], p => p || []); cardB = updateIn(cardB, ["dataset_query", "parameters"], p => p || []); return _.isEqual( @@ -76,10 +58,10 @@ export function cardQueryIsEquivalent(cardA: Card, cardB: Card): boolean { } export function cardIsEquivalent( - cardA: Card, - cardB: Card, - { checkParameters = false }: { checkParameters: boolean } = {}, -): boolean { + cardA, + cardB, + { checkParameters = false } = {}, +) { return ( cardQueryIsEquivalent(cardA, cardB) && cardVisualizationIsEquivalent(cardA, cardB) && @@ -88,7 +70,7 @@ export function cardIsEquivalent( ); } -export function getQuery(card: Card): ?StructuredQuery { +export function getQuery(card) { if (card.dataset_query.type === "query") { return card.dataset_query.query; } else { @@ -96,7 +78,7 @@ export function getQuery(card: Card): ?StructuredQuery { } } -export function getTableMetadata(card: Card, metadata: Metadata): ?Table { +export function getTableMetadata(card, metadata) { const query = getQuery(card); if (query && query["source-table"] != null) { return metadata.table(query["source-table"]) || null; @@ -107,11 +89,11 @@ export function getTableMetadata(card: Card, metadata: Metadata): ?Table { // NOTE Atte Keinänen 7/5/17: Still used in dashboards and public questions. // Query builder uses `Question.getResults` which contains similar logic. export function applyParameters( - card: Card, - parameters: Parameter[], - parameterValues: ParameterValues = {}, - parameterMappings: ParameterMapping[] = [], -): DatasetQuery { + card, + parameters, + parameterValues = {}, + parameterMappings = [], +) { const datasetQuery = Utils.copy(card.dataset_query); // clean the query if (datasetQuery.type === "query") { @@ -163,19 +145,19 @@ export function applyParameters( return datasetQuery; } -export function isTransientId(id: ?any) { +export function isTransientId(id) { return id != null && typeof id === "string" && isNaN(parseInt(id)); } /** returns a question URL with parameters added to query string or MBQL filters */ export function questionUrlWithParameters( - card: Card, - metadata: Metadata, - parameters: Parameter[], - parameterValues: ParameterValues = {}, - parameterMappings: ParameterMapping[] = [], - cardIsDirty: boolean = true, -): DatasetQuery { + card, + metadata, + parameters, + parameterValues = {}, + parameterMappings = [], + cardIsDirty = true, +) { if (!card.dataset_query) { return Urls.question(card); } diff --git a/frontend/src/metabase/query_builder/actions.js b/frontend/src/metabase/query_builder/actions.js index b1e1f0180af..afbd162efce 100644 --- a/frontend/src/metabase/query_builder/actions.js +++ b/frontend/src/metabase/query_builder/actions.js @@ -1,6 +1,6 @@ import { fetchAlertsForQuestion } from "metabase/alert/alert"; -declare var ace: any; +/*global ace*/ import { createAction } from "redux-actions"; import _ from "underscore"; @@ -79,25 +79,15 @@ import Snippets from "metabase/entities/snippets"; import { getMetadata } from "metabase/selectors/metadata"; import { setRequestUnloaded } from "metabase/redux/requests"; -import type { Card } from "metabase-types/types/Card"; - import { getQueryBuilderModeFromLocation, getPathNameFromQueryBuilderMode, isAdHocDatasetQuestion, } from "./utils"; -type UiControls = { - isEditing?: boolean, - isShowingTemplateTagsEditor?: boolean, - isShowingNewbModal?: boolean, - queryBuilderMode?: "view" | "notebook", - isShowingSummarySidebar?: boolean, -}; - const PREVIEW_RESULT_LIMIT = 10; -const getTemplateTagWithoutSnippetsCount = (question: Question) => { +const getTemplateTagWithoutSnippetsCount = question => { const query = question.query(); return query instanceof NativeQuery ? query.templateTagsWithoutSnippets().length @@ -335,7 +325,7 @@ export const initializeQB = (location, params, queryParams) => { const cardId = Urls.extractEntityId(params.slug); let card, originalCard; - const uiControls: UiControls = { + const uiControls = { isEditing: false, isShowingTemplateTagsEditor: false, queryBuilderMode: getQueryBuilderModeFromLocation(location), @@ -1136,25 +1126,20 @@ export const apiUpdateQuestion = (question, { rerunQuery = false } = {}) => { * Queries the result for the currently active question or alternatively for the card provided in `overrideWithCard`. * The API queries triggered by this action creator can be cancelled using the deferred provided in RUN_QUERY action. */ -export type RunQueryParams = { - shouldUpdateUrl?: boolean, - ignoreCache?: boolean, // currently only implemented for saved cards - overrideWithCard?: Card, // override the current question with the provided card -}; export const RUN_QUERY = "metabase/qb/RUN_QUERY"; export const runQuestionQuery = ({ shouldUpdateUrl = true, ignoreCache = false, overrideWithCard, -}: RunQueryParams = {}) => { +} = {}) => { return async (dispatch, getState) => { - const questionFromCard = (card: Card): Question => + const questionFromCard = card => card && new Question(card, getMetadata(getState())); - let question: Question = overrideWithCard + let question = overrideWithCard ? questionFromCard(overrideWithCard) : getQuestion(getState()); - const originalQuestion: ?Question = getOriginalQuestion(getState()); + const originalQuestion = getOriginalQuestion(getState()); // When viewing a dataset, its dataset_query is swapped with a clean query using the dataset as a source table // This ensures we still run the underlying query instead of a nested one if there are not extra clauses diff --git a/frontend/src/metabase/query_builder/components/AlertListPopoverContent.jsx b/frontend/src/metabase/query_builder/components/AlertListPopoverContent.jsx index 7d4436521a7..047a1c2b718 100644 --- a/frontend/src/metabase/query_builder/components/AlertListPopoverContent.jsx +++ b/frontend/src/metabase/query_builder/components/AlertListPopoverContent.jsx @@ -25,12 +25,6 @@ import { null, ) export default class AlertListPopoverContent extends Component { - props: { - questionAlerts: any[], - setMenuFreeze: boolean => void, - closeMenu: () => void, - }; - state = { adding: false, hasJustUnsubscribedFromOwnAlert: false, @@ -121,14 +115,6 @@ export default class AlertListPopoverContent extends Component { deleteAlert, }) export class AlertListItem extends Component { - props: { - alert: any, - user: any, - setMenuFreeze: boolean => void, - closeMenu: () => void, - onUnsubscribe: () => void, - }; - state = { unsubscribingProgress: null, hasJustUnsubscribed: false, diff --git a/frontend/src/metabase/query_builder/components/AlertModals.jsx b/frontend/src/metabase/query_builder/components/AlertModals.jsx index 96499485c46..2319dc48f52 100644 --- a/frontend/src/metabase/query_builder/components/AlertModals.jsx +++ b/frontend/src/metabase/query_builder/components/AlertModals.jsx @@ -48,7 +48,6 @@ import MetabaseCookies from "metabase/lib/cookies"; import * as MetabaseAnalytics from "metabase/lib/analytics"; // types -import type { AlertType } from "metabase-lib/lib/Alert"; import { alertIsValid } from "metabase/lib/alert"; const getScheduleFromChannel = channel => @@ -76,11 +75,6 @@ const textStyle = { { createAlert, fetchPulseFormInput, apiUpdateQuestion, updateUrl }, ) export class CreateAlertModalContent extends Component { - props: { - onCancel: () => void, - onAlertCreated: () => void, - }; - constructor(props) { super(); @@ -208,10 +202,6 @@ export class CreateAlertModalContent extends Component { } export class AlertEducationalScreen extends Component { - props: { - onProceed: () => void, - }; - render() { const { onProceed } = this.props; @@ -300,15 +290,6 @@ export class AlertEducationalScreen extends Component { { apiUpdateQuestion, updateAlert, deleteAlert, updateUrl }, ) export class UpdateAlertModalContent extends Component { - props: { - alert: any, - onCancel: boolean, - onAlertUpdated: any => void, - updateAlert: any => void, - deleteAlert: any => void, - isAdmin: boolean, - }; - constructor(props) { super(); this.state = { @@ -396,8 +377,6 @@ export class UpdateAlertModalContent extends Component { } export class DeleteAlertSection extends Component { - deleteModal: any; - getConfirmItems() { // same as in PulseEdit but with some changes to copy return this.props.alert.channels.map(c => @@ -470,13 +449,6 @@ const AlertModalTitle = ({ text }) => ( @connect(state => ({ isAdmin: getUserIsAdmin(state) }), null) export class AlertEditForm extends Component { - props: { - alertType: AlertType, - alert: any, - onAlertChange: any => void, - isAdmin: boolean, - }; - onScheduleChange = schedule => { const { alert, onAlertChange } = this.props; @@ -620,15 +592,6 @@ export class AlertEditSchedule extends Component { }, ) export class AlertEditChannels extends Component { - props: { - onChannelsChange: any => void, - user: any, - users: any[], - // this stupidly named property contains different channel options, nothing else - formInput: any, - fetchPulseFormInput: () => Promise<void>, - }; - componentDidMount() { this.props.fetchPulseFormInput(); } diff --git a/frontend/src/metabase/query_builder/components/BreakoutPopover.jsx b/frontend/src/metabase/query_builder/components/BreakoutPopover.jsx index 706707a8d1e..91983f07b2c 100644 --- a/frontend/src/metabase/query_builder/components/BreakoutPopover.jsx +++ b/frontend/src/metabase/query_builder/components/BreakoutPopover.jsx @@ -1,25 +1,9 @@ +/* eslint-disable react/prop-types */ import React from "react"; import cx from "classnames"; import FieldList from "metabase/query_builder/components/FieldList"; -import type { Breakout } from "metabase-types/types/Query"; -import type { FieldOptions } from "metabase-types/types/Metadata"; -import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; - -type Props = { - className?: string, - breakout?: Breakout, - onChangeBreakout: (breakout: Breakout) => void, - query: StructuredQuery, - breakoutOptions?: FieldOptions, - onClose?: () => void, - maxHeight?: number, - alwaysExpanded?: boolean, - searchable?: boolean, - width?: number, -}; - const BreakoutPopover = ({ className, breakout, @@ -30,7 +14,7 @@ const BreakoutPopover = ({ maxHeight, alwaysExpanded, width = 400, -}: Props) => { +}) => { const table = query.table(); // FieldList requires table if (!table) { diff --git a/frontend/src/metabase/query_builder/components/DimensionList.jsx b/frontend/src/metabase/query_builder/components/DimensionList.jsx index 4dee0d965c9..eeabbc474b0 100644 --- a/frontend/src/metabase/query_builder/components/DimensionList.jsx +++ b/frontend/src/metabase/query_builder/components/DimensionList.jsx @@ -8,42 +8,9 @@ import Icon from "metabase/components/Icon"; import PopoverWithTrigger from "metabase/components/PopoverWithTrigger"; import Tooltip from "metabase/components/Tooltip"; -import Dimension, { FieldDimension } from "metabase-lib/lib/Dimension"; +import { FieldDimension } from "metabase-lib/lib/Dimension"; import { DimensionPicker } from "./DimensionPicker"; -// import type { Section } from "metabase/components/AccordionList"; -export type AccordionListItem = {}; - -export type AccordionListSection = { - name: ?string, - items: AccordionListItem[], -}; - -type Props = { - className?: string, - maxHeight?: number, - width?: ?number | ?string, - - dimension?: ?Dimension, - dimensions?: Dimension[], - onChangeDimension: (dimension: Dimension) => void, - onChangeOther?: (item: any) => void, - - onAddDimension?: (dimension: Dimension, item: AccordionListItem) => void, - onRemoveDimension?: (dimension: Dimension, item: AccordionListItem) => void, - - sections: AccordionListSection[], - - alwaysExpanded?: boolean, - enableSubDimensions?: boolean, - useOriginalDimension?: boolean, - preventNumberSubDimensions?: boolean, -}; - -type State = { - sections: AccordionListSection[], -}; - const SUBMENU_TETHER_OPTIONS = { attachment: "top left", targetAttachment: "top right", @@ -58,11 +25,7 @@ const SUBMENU_TETHER_OPTIONS = { }; export default class DimensionList extends Component { - props: Props; - state: State = { - sections: [], - }; - state: State = { + state = { sections: [], }; diff --git a/frontend/src/metabase/query_builder/components/ExtendedOptions.jsx b/frontend/src/metabase/query_builder/components/ExtendedOptions.jsx index 7f476db23e8..58244a4ac17 100644 --- a/frontend/src/metabase/query_builder/components/ExtendedOptions.jsx +++ b/frontend/src/metabase/query_builder/components/ExtendedOptions.jsx @@ -13,27 +13,8 @@ import Popover from "metabase/components/Popover"; import * as MetabaseAnalytics from "metabase/lib/analytics"; -import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; -import type { DatasetQuery } from "metabase-types/types/Card"; -import type { GuiQueryEditorFeatures } from "./GuiQueryEditor"; - -type Props = { - query: StructuredQuery, - setDatasetQuery: ( - datasetQuery: DatasetQuery, - options: { run: boolean }, - ) => void, - features: GuiQueryEditorFeatures, - onClose?: () => void, -}; - -type State = { - editExpression: any, -}; - export class ExtendedOptionsPopover extends Component { - props: Props; - state: State = { + state = { editExpression: null, }; diff --git a/frontend/src/metabase/query_builder/components/FieldList.jsx b/frontend/src/metabase/query_builder/components/FieldList.jsx index c63606dc1ec..0be1572d0b7 100644 --- a/frontend/src/metabase/query_builder/components/FieldList.jsx +++ b/frontend/src/metabase/query_builder/components/FieldList.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import DimensionList from "./DimensionList"; @@ -5,50 +6,11 @@ import DimensionList from "./DimensionList"; import Dimension from "metabase-lib/lib/Dimension"; import DimensionOptions from "metabase-lib/lib/DimensionOptions"; -import type { ConcreteField } from "metabase-types/types/Query"; -import type Metadata from "metabase-lib/lib/metadata/Metadata"; -import type StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; - // import type { Section } from "metabase/components/AccordionList"; -export type AccordionListItem = {}; - -export type AccordionListSection = { - name: ?string, - items: AccordionListItem[], -}; - -type Props = { - field: ?ConcreteField, - onFieldChange: (field: ConcreteField) => void, - fieldOptions: any, - - // HACK: for segments - onFilterChange?: (filter: any) => void, - - // query should be included otherwise FieldList may not display field-literal display name correctly - query?: StructuredQuery, - metadata?: Metadata, - - // AccordionList props: - className?: string, - maxHeight?: number, - width?: number, - alwaysExpanded?: boolean, - - // DimensionList props: - enableSubDimensions?: boolean, - useOriginalDimension?: boolean, - preventNumberSubDimensions?: boolean, -}; - -type State = { - sections: AccordionListSection[], -}; // DEPRECATED: use DimensionList directly export default class FieldList extends Component { - props: Props; - state: State = { + state = { sections: [], }; diff --git a/frontend/src/metabase/query_builder/components/Filter.jsx b/frontend/src/metabase/query_builder/components/Filter.jsx index 590ac7ff73c..0cd6d33952a 100644 --- a/frontend/src/metabase/query_builder/components/Filter.jsx +++ b/frontend/src/metabase/query_builder/components/Filter.jsx @@ -11,29 +11,7 @@ import { getFilterArgumentFormatOptions } from "metabase/lib/schema_metadata"; import { t, ngettext, msgid } from "ttag"; -import type { Filter as FilterObject } from "metabase-types/types/Query"; -import type { Value as ValueType } from "metabase-types/types/Dataset"; -import Metadata from "metabase-lib/lib/metadata/Metadata"; -import FilterWrapper from "metabase-lib/lib/queries/structured/Filter"; - -export type FilterRenderer = ({ - field?: React.Element, - operator: ?string, - values: (React.Element | string)[], -}) => React.Element; - -type Props = { - filter: FilterObject | FilterWrapper, - metadata: Metadata, - maxDisplayValues?: number, - children?: FilterRenderer, -}; - -const DEFAULT_FILTER_RENDERER: FilterRenderer = ({ - field, - operator, - values, -}) => { +const DEFAULT_FILTER_RENDERER = ({ field, operator, values }) => { const items = [field, operator, ...values]; // insert an "and" at the end if multiple values // NOTE: works for "between", not sure about others @@ -59,9 +37,9 @@ export const OperatorFilter = ({ metadata, maxDisplayValues, children = DEFAULT_FILTER_RENDERER, -}: Props) => { +}) => { const [op, field] = filter; - const values: ValueType[] = hasFilterOptions(filter) + const values = hasFilterOptions(filter) ? filter.slice(2, -1) : filter.slice(2); @@ -107,7 +85,7 @@ export const SegmentFilter = ({ metadata, maxDisplayValues, children = DEFAULT_FILTER_RENDERER, -}: Props) => { +}) => { const segment = metadata.segment(filter[1]); return children({ operator: t`Matches`, @@ -115,7 +93,7 @@ export const SegmentFilter = ({ }); }; -const Filter = ({ filter, ...props }: Props) => +const Filter = ({ filter, ...props }) => filter[0] === "segment" ? ( <SegmentFilter filter={filter} {...props} /> ) : ( diff --git a/frontend/src/metabase/query_builder/components/FilterList.jsx b/frontend/src/metabase/query_builder/components/FilterList.jsx index 4b811bcde05..68bab8985e6 100644 --- a/frontend/src/metabase/query_builder/components/FilterList.jsx +++ b/frontend/src/metabase/query_builder/components/FilterList.jsx @@ -7,23 +7,12 @@ import { filterWidgetFilterRenderer } from "./filters/FilterWidget"; import { getMetadata } from "metabase/selectors/metadata"; -import type { Filter as FilterType } from "metabase-types/types/Query"; -import type { FilterRenderer } from "./Filter"; - -type Props = { - filters: Array<FilterType>, - maxDisplayValues?: number, - filterRenderer?: FilterRenderer, -}; - const mapStateToProps = state => ({ metadata: getMetadata(state), }); @connect(mapStateToProps) export default class FilterList extends Component { - props: Props; - static defaultProps = { filterRenderer: filterWidgetFilterRenderer, }; diff --git a/frontend/src/metabase/query_builder/components/GuiQueryEditor.jsx b/frontend/src/metabase/query_builder/components/GuiQueryEditor.jsx index c61d79f00e4..9eef03157ae 100644 --- a/frontend/src/metabase/query_builder/components/GuiQueryEditor.jsx +++ b/frontend/src/metabase/query_builder/components/GuiQueryEditor.jsx @@ -17,46 +17,15 @@ import { DatabaseSchemaAndTableDataSelector } from "metabase/query_builder/compo import cx from "classnames"; -import type { DatasetQuery } from "metabase-types/types/Card"; -import type { Aggregation, Breakout } from "metabase-types/types/Query"; -import type { Children } from "react"; - -import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; -export type GuiQueryEditorFeatures = { - filter?: boolean, - aggregation?: boolean, - breakout?: boolean, - sort?: boolean, - limit?: boolean, -}; - -type Props = { - children?: Children, - - features: GuiQueryEditorFeatures, - - query: StructuredQuery, - - supportMultipleAggregations?: boolean, - - setDatasetQuery: (datasetQuery: DatasetQuery) => void, - - isShowingDataReference?: boolean, -}; - -type State = { - expanded: boolean, -}; - export default class GuiQueryEditor extends React.Component { - constructor(props: Props) { + constructor(props) { super(props); this.filterPopover = React.createRef(); this.guiBuilder = React.createRef(); } - state: State = { + state = { expanded: true, }; @@ -78,7 +47,7 @@ export default class GuiQueryEditor extends React.Component { supportMultipleAggregations: true, }; - renderAdd(text: ?string, onClick: ?() => void, targetRefName?: string) { + renderAdd(text, onClick, targetRefName) { const className = "AddButton text-light text-bold flex align-center text-medium-hover cursor-pointer no-decoration transition-color"; if (onClick) { @@ -98,7 +67,7 @@ export default class GuiQueryEditor extends React.Component { } } - renderAddIcon(targetRefName?: string) { + renderAddIcon(targetRefName) { return ( <IconBorder borderRadius="3px" ref={targetRefName}> <Icon name="add" size={14} /> @@ -193,7 +162,7 @@ export default class GuiQueryEditor extends React.Component { // aggregation clause. must have table details available if (query.isEditable()) { - const aggregations: (Aggregation | null)[] = query.aggregations(); + const aggregations = query.aggregations(); if (aggregations.length === 0) { // add implicit rows aggregation @@ -255,7 +224,7 @@ export default class GuiQueryEditor extends React.Component { const breakoutList = []; - const breakouts: (Breakout | null)[] = query.breakouts(); + const breakouts = query.breakouts(); // Placeholder breakout for showing the add button if (query.canAddBreakout()) { diff --git a/frontend/src/metabase/query_builder/components/NativeQueryEditor.jsx b/frontend/src/metabase/query_builder/components/NativeQueryEditor.jsx index 408b7dc048a..8d39a00685f 100644 --- a/frontend/src/metabase/query_builder/components/NativeQueryEditor.jsx +++ b/frontend/src/metabase/query_builder/components/NativeQueryEditor.jsx @@ -27,8 +27,6 @@ import Snippets from "metabase/entities/snippets"; import SnippetCollections from "metabase/entities/snippet-collections"; import SnippetModal from "metabase/query_builder/components/template_tags/SnippetModal"; import SyncedParametersList from "metabase/parameters/components/SyncedParametersList/SyncedParametersList"; -import Question from "metabase-lib/lib/Question"; -import NativeQuery from "metabase-lib/lib/queries/NativeQuery"; import NativeQueryEditorSidebar from "./NativeQueryEditor/NativeQueryEditorSidebar"; import VisibilityToggler from "./NativeQueryEditor/VisibilityToggler"; import RightClickPopover from "./NativeQueryEditor/RightClickPopover"; @@ -36,62 +34,6 @@ import DataSourceSelectors from "./NativeQueryEditor/DataSourceSelectors"; import "./NativeQueryEditor.css"; -import type { DatasetQuery } from "metabase-types/types/Card"; -import type { DatabaseId } from "metabase-types/types/Database"; -import type { TableId } from "metabase-types/types/Table"; -import type { ParameterId } from "metabase-types/types/Parameter"; -import type { LocationDescriptor } from "metabase-types/types"; -import type { RunQueryParams } from "metabase/query_builder/actions"; - -type AutoCompleteResult = [string, string, string]; -type AceEditor = any; // TODO; - -type Props = { - readOnly?: boolean, - - location: LocationDescriptor, - - question: Question, - query: NativeQuery, - - handleResize: () => void, - - runQuestionQuery: (options?: RunQueryParams) => void, - setDatasetQuery: (datasetQuery: DatasetQuery) => void, - cancelQuery: () => void, - - setParameterValue: (parameterId: ParameterId, value: string) => void, - - autocompleteResultsFn: (input: string) => Promise<AutoCompleteResult[]>, - - isNativeEditorOpen: boolean, - isInitiallyOpen: boolean, - setIsNativeEditorOpen: (isOpen: boolean) => void, - nativeEditorSelectedText: string, - setNativeEditorSelectedRange: any => void, - hasParametersList: boolean, - - isRunnable: boolean, - isRunning: boolean, - isResultDirty: boolean, - isPreviewing: boolean, - isNativeEditorOpen: boolean, - - viewHeight: number, - width: number, - - openSnippetModalWithSelectedText: () => void, - insertSnippet: () => void, - closeSnippetModal: () => void, - snippets: { name: string }[], - snippetCollections: { can_write: boolean }[], -}; - -type State = { - initialHeight: number, - isSelectedTextPopoverOpen: boolean, -}; - const SCROLL_MARGIN = 8; const LINE_HEIGHT = 16; @@ -104,13 +46,9 @@ const getLinesForHeight = height => (height - 2 * SCROLL_MARGIN) / LINE_HEIGHT; @Snippets.loadList({ loadingAndErrorWrapper: false }) @SnippetCollections.loadList({ loadingAndErrorWrapper: false }) export default class NativeQueryEditor extends Component { - props: Props; - state: State; - - _editor: AceEditor; - _localUpdate: boolean = false; + _localUpdate = false; - constructor(props: Props) { + constructor(props) { super(props); const lines = Math.max( @@ -174,7 +112,7 @@ export default class NativeQueryEditor extends Component { } }; - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps) { const { query } = this.props; if (!query || !this._editor) { return; @@ -252,7 +190,7 @@ export default class NativeQueryEditor extends Component { this.props.setNativeEditorSelectedRange(this._editor.getSelectionRange()); }, 100); - handleKeyDown = (e: KeyboardEvent) => { + handleKeyDown = e => { const ENTER_KEY = 13; if (e.keyCode === ENTER_KEY && (e.metaKey || e.ctrlKey)) { this.runQuery(); @@ -432,7 +370,7 @@ export default class NativeQueryEditor extends Component { }; /// Change the Database we're currently editing a query for. - setDatabaseId = (databaseId: DatabaseId) => { + setDatabaseId = databaseId => { const { query } = this.props; if (query.databaseId() !== databaseId) { query @@ -446,7 +384,7 @@ export default class NativeQueryEditor extends Component { } }; - setTableId = (tableId: TableId) => { + setTableId = tableId => { // TODO: push more of this into metabase-lib? const { query } = this.props; const table = query.metadata().table(tableId); @@ -455,7 +393,7 @@ export default class NativeQueryEditor extends Component { } }; - setParameterIndex = (parameterId: ParameterId, parameterIndex: number) => { + setParameterIndex = (parameterId, parameterIndex) => { const { query, setDatasetQuery } = this.props; query .setParameterIndex(parameterId, parameterIndex) diff --git a/frontend/src/metabase/query_builder/components/QueryVisualization.jsx b/frontend/src/metabase/query_builder/components/QueryVisualization.jsx index bc1df7c8bec..9890bd20500 100644 --- a/frontend/src/metabase/query_builder/components/QueryVisualization.jsx +++ b/frontend/src/metabase/query_builder/components/QueryVisualization.jsx @@ -13,49 +13,9 @@ import Utils from "metabase/lib/utils"; import cx from "classnames"; -import Question from "metabase-lib/lib/Question"; -import type Database from "metabase-lib/lib/metadata/Database"; -import type Table from "metabase-lib/lib/metadata/Table"; -import type { DatasetQuery } from "metabase-types/types/Card"; - -import type { ParameterValues } from "metabase-types/types/Parameter"; - import { HARD_ROW_LIMIT } from "metabase/lib/query"; -type Props = { - question: Question, - originalQuestion: Question, - result?: Object, - databases?: Database[], - tableMetadata?: Table, - tableForeignKeys?: [], - tableForeignKeyReferences?: {}, - onUpdateVisualizationSettings: any => void, - onReplaceAllVisualizationSettings: any => void, - onOpenChartSettings: any => void, - cellIsClickableFn?: any => void, - cellClickedFn?: any => void, - isRunning: boolean, - isRunnable: boolean, - isAdmin: boolean, - isResultDirty: boolean, - isObjectDetail: boolean, - isNativeEditorOpen: boolean, - runQuestionQuery: any => void, - cancelQuery?: any => void, - className: string, -}; - -type State = { - lastRunDatasetQuery: DatasetQuery, - lastRunParameterValues: ParameterValues, - warnings: string[], -}; - export default class QueryVisualization extends Component { - props: Props; - state: State; - constructor(props, context) { super(props, context); this.state = this._getStateFromProps(props); diff --git a/frontend/src/metabase/query_builder/components/VisualizationResult.jsx b/frontend/src/metabase/query_builder/components/VisualizationResult.jsx index d92282b4016..5095c87db0c 100644 --- a/frontend/src/metabase/query_builder/components/VisualizationResult.jsx +++ b/frontend/src/metabase/query_builder/components/VisualizationResult.jsx @@ -1,5 +1,4 @@ -/* eslint "react/prop-types": "warn" */ - +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import { t, jt } from "ttag"; import cx from "classnames"; @@ -7,35 +6,11 @@ import cx from "classnames"; import ErrorMessage from "metabase/components/ErrorMessage"; import Visualization from "metabase/visualizations/components/Visualization"; import { datasetContainsNoResults } from "metabase/lib/dataset"; -import { DatasetQuery } from "metabase-types/types/Card"; import { CreateAlertModalContent } from "metabase/query_builder/components/AlertModals"; import Modal from "metabase/components/Modal"; import { ALERT_TYPE_ROWS } from "metabase-lib/lib/Alert"; -import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; - -import type { Question } from "metabase-lib/lib/Question"; - -type Props = { - className?: string, - question: Question, - isObjectDetail: boolean, - result: any, - results: any[], - isDirty: boolean, - lastRunDatasetQuery: DatasetQuery, - navigateToNewCardInsideQB: any => void, - rawSeries: any, - - isVisualizationClickable: boolean, - - onOpenChartSettings: () => void, - onUpdateWarnings: () => void, - onUpdateVisualizationSettings: (settings: any) => void, - query?: StructuredQuery, -}; export default class VisualizationResult extends Component { - props: Props; state = { showCreateAlertModal: false, }; diff --git a/frontend/src/metabase/query_builder/components/filters/DateOperatorSelector.jsx b/frontend/src/metabase/query_builder/components/filters/DateOperatorSelector.jsx index 2753c8029be..58e6f2d799b 100644 --- a/frontend/src/metabase/query_builder/components/filters/DateOperatorSelector.jsx +++ b/frontend/src/metabase/query_builder/components/filters/DateOperatorSelector.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import _ from "underscore"; @@ -5,20 +6,7 @@ import cx from "classnames"; import Select, { Option } from "metabase/components/Select"; -import type { Operator } from "./pickers/DatePicker"; - -type Props = { - operator: ?string, - operators: Operator[], - onOperatorChange: (o: Operator) => void, - hideTimeSelectors?: boolean, - - className?: string, -}; - export default class DateOperatorSelector extends Component { - props: Props; - render() { const { className, operator, operators, onOperatorChange } = this.props; diff --git a/frontend/src/metabase/query_builder/components/filters/DateUnitSelector.jsx b/frontend/src/metabase/query_builder/components/filters/DateUnitSelector.jsx index 02eca70f29f..1d9091664e7 100644 --- a/frontend/src/metabase/query_builder/components/filters/DateUnitSelector.jsx +++ b/frontend/src/metabase/query_builder/components/filters/DateUnitSelector.jsx @@ -4,18 +4,6 @@ import React from "react"; import Select, { Option } from "metabase/components/Select"; import { formatBucketing } from "metabase/lib/query_time"; -import type { RelativeDatetimeUnit } from "metabase-types/types/Query"; - -type DateUnitSelectorProps = { - value: RelativeDatetimeUnit, - onChange: (value: RelativeDatetimeUnit) => void, - open: boolean, - intervals?: number, - togglePicker: () => void, - formatter: (value: ?number) => ?number, - periods: RelativeDatetimeUnit[], -}; - const DateUnitSelector = ({ className, open, @@ -25,7 +13,7 @@ const DateUnitSelector = ({ intervals, formatter, periods, -}: DateUnitSelectorProps) => ( +}) => ( <Select className={className} value={value} diff --git a/frontend/src/metabase/query_builder/components/filters/FilterOptions.jsx b/frontend/src/metabase/query_builder/components/filters/FilterOptions.jsx index 802b84c10c9..0a7a80f2fb9 100644 --- a/frontend/src/metabase/query_builder/components/filters/FilterOptions.jsx +++ b/frontend/src/metabase/query_builder/components/filters/FilterOptions.jsx @@ -7,8 +7,6 @@ import { getFilterOptions, setFilterOptions } from "metabase/lib/query/filter"; import CheckBox from "metabase/components/CheckBox"; import * as MetabaseAnalytics from "metabase/lib/analytics"; -import type { FieldFilter } from "metabase-types/types/Query"; - const OPTION_NAMES = { "include-current": filter => { const period = ( @@ -30,7 +28,7 @@ const CURRENT_INTERVAL_NAME = { hour: t`this hour`, }; -function getCurrentIntervalName(filter: FieldFilter): ?string { +function getCurrentIntervalName(filter) { if (filter[0] === "time-interval") { return CURRENT_INTERVAL_NAME[filter[3]]; } diff --git a/frontend/src/metabase/query_builder/components/filters/FilterPopover.jsx b/frontend/src/metabase/query_builder/components/filters/FilterPopover.jsx index 21934faef08..de648194d84 100644 --- a/frontend/src/metabase/query_builder/components/filters/FilterPopover.jsx +++ b/frontend/src/metabase/query_builder/components/filters/FilterPopover.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import PropTypes from "prop-types"; @@ -15,36 +16,8 @@ import FilterPopoverFooter from "./FilterPopoverFooter"; import ExpressionPopover from "metabase/query_builder/components/ExpressionPopover"; import SidebarHeader from "metabase/query_builder/components/SidebarHeader"; -import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; import Filter from "metabase-lib/lib/queries/structured/Filter"; -import type Dimension from "metabase-lib/lib/Dimension"; - -type Props = { - query: StructuredQuery, - filter?: Filter, - onChange?: (filter: ?Filter) => void, - // NOTE: this should probably be called onCommit - onChangeFilter?: (filter: Filter) => void, - onClose: () => void, - - style?: {}, - className?: string, - - fieldPickerTitle?: string, - showFieldPicker?: boolean, - isTopLevel?: boolean, - isSidebar?: boolean, - - showCustom?: boolean, -}; - -type State = { - filter: ?Filter, - choosingField: boolean, - editingFilter: boolean, -}; - const MIN_WIDTH = 300; const MAX_WIDTH = 410; @@ -53,16 +26,13 @@ const CUSTOM_SECTION_NAME = t`Custom Expression`; // NOTE: this is duplicated from FilterPopover but allows you to add filters on // the last two "stages" of a nested query, e.x. post aggregation filtering export default class ViewFilterPopover extends Component { - props: Props; - state: State; - static defaultProps = { style: {}, showFieldPicker: true, showCustom: true, }; - constructor(props: Props) { + constructor(props) { super(props); const filter = props.filter instanceof Filter ? props.filter : null; this.state = { @@ -72,7 +42,7 @@ export default class ViewFilterPopover extends Component { }; } - UNSAFE_componentWillReceiveProps(nextProps: Props) { + UNSAFE_componentWillReceiveProps(nextProps) { const { filter } = this.state; // HACK?: if the underlying query changes (e.x. additional metadata is loaded) update the filter's query if (filter && this.props.query !== nextProps.query) { @@ -82,14 +52,14 @@ export default class ViewFilterPopover extends Component { } } - setFilter(filter: ?Filter) { + setFilter(filter) { this.setState({ filter }); if (this.props.onChange) { this.props.onChange(filter); } } - handleUpdateAndCommit = (newFilter: ?Filter) => { + handleUpdateAndCommit = newFilter => { const base = this.state.filter || new Filter([], null, this.props.query); const filter = base.set(newFilter); this.setState({ filter }, () => { @@ -101,7 +71,7 @@ export default class ViewFilterPopover extends Component { this.handleCommitFilter(this.state.filter, this.props.query); }; - handleCommitFilter = (filter: ?Filter, query: StructuredQuery) => { + handleCommitFilter = (filter, query) => { if (filter && !(filter instanceof Filter)) { filter = new Filter(filter, null, query); } @@ -113,7 +83,7 @@ export default class ViewFilterPopover extends Component { } }; - handleDimensionChange = (dimension: Dimension) => { + handleDimensionChange = dimension => { let filter = this.state.filter; if (!filter || filter.query() !== dimension.query()) { filter = new Filter( @@ -128,7 +98,7 @@ export default class ViewFilterPopover extends Component { this.setState({ choosingField: false }); }; - handleFilterChange = (newFilter: ?Filter) => { + handleFilterChange = newFilter => { const filter = this.state.filter || new Filter([], null, this.props.query); this.setFilter(filter.set(newFilter)); }; diff --git a/frontend/src/metabase/query_builder/components/filters/FilterPopoverPicker.jsx b/frontend/src/metabase/query_builder/components/filters/FilterPopoverPicker.jsx index b4c11d4a43b..dd296236a6e 100644 --- a/frontend/src/metabase/query_builder/components/filters/FilterPopoverPicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/FilterPopoverPicker.jsx @@ -15,7 +15,7 @@ export default class FilterPopoverPicker extends React.Component { window.removeEventListener("keydown", this.handleKeyDown); } - handleKeyDown = (event: KeyboardEvent) => { + handleKeyDown = event => { if (event.key === "Enter") { this.props.onCommit(); } @@ -32,11 +32,11 @@ export default class FilterPopoverPicker extends React.Component { maxWidth, } = this.props; - const setValue = (index: number, value: any) => { + const setValue = (index, value) => { onFilterChange(filter.setArgument(index, value)); }; - const setValues = (values: any[]) => { + const setValues = values => { onFilterChange(filter.setArguments(values)); }; diff --git a/frontend/src/metabase/query_builder/components/filters/FilterWidget.jsx b/frontend/src/metabase/query_builder/components/filters/FilterWidget.jsx index d625710ecf9..f238b94d376 100644 --- a/frontend/src/metabase/query_builder/components/filters/FilterWidget.jsx +++ b/frontend/src/metabase/query_builder/components/filters/FilterWidget.jsx @@ -8,27 +8,7 @@ import Filter from "metabase/query_builder/components/Filter"; import cx from "classnames"; -import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; -import type { FilterRenderer } from "metabase/query_builder/components/Filter"; -import type FilterWrapper from "metabase-lib/lib/queries/structured/Filter"; - -type Props = { - query: StructuredQuery, - filter: FilterWrapper, - index: number, - updateFilter?: (index: number, filter: FilterWrapper) => void, - removeFilter?: (index: number) => void, - maxDisplayValues?: number, -}; -type State = { - isOpen: boolean, -}; - -export const filterWidgetFilterRenderer: FilterRenderer = ({ - field, - operator, - values, -}) => ( +export const filterWidgetFilterRenderer = ({ field, operator, values }) => ( <div className="flex flex-column justify-center"> <div className="flex align-center" @@ -64,10 +44,7 @@ export const filterWidgetFilterRenderer: FilterRenderer = ({ ); export default class FilterWidget extends Component { - props: Props; - state: State; - - constructor(props: Props) { + constructor(props) { super(props); this.state = { diff --git a/frontend/src/metabase/query_builder/components/filters/FilterWidgetList.jsx b/frontend/src/metabase/query_builder/components/filters/FilterWidgetList.jsx index eedbd0a3100..6f84ef09582 100644 --- a/frontend/src/metabase/query_builder/components/filters/FilterWidgetList.jsx +++ b/frontend/src/metabase/query_builder/components/filters/FilterWidgetList.jsx @@ -1,28 +1,11 @@ +/* eslint-disable react/prop-types */ import React from "react"; import { findDOMNode } from "react-dom"; import { t } from "ttag"; import FilterWidget from "./FilterWidget"; -import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; -import Filter from "metabase-lib/lib/queries/structured/Filter"; - -type Props = { - query: StructuredQuery, - filters: Filter[], - removeFilter?: (index: number) => void, - updateFilter?: (index: number, filter: Filter) => void, - maxDisplayValues?: number, -}; - -type State = { - shouldScroll: boolean, -}; - export default class FilterWidgetList extends React.Component { - props: Props; - state: State; - - constructor(props: Props) { + constructor(props) { super(props); this.state = { shouldScroll: false, @@ -35,7 +18,7 @@ export default class FilterWidgetList extends React.Component { : null; } - UNSAFE_componentWillReceiveProps(nextProps: Props) { + UNSAFE_componentWillReceiveProps(nextProps) { // only scroll when a filter is added if (nextProps.filters.length > this.props.filters.length) { this.setState({ shouldScroll: true }); diff --git a/frontend/src/metabase/query_builder/components/filters/OperatorSelector.jsx b/frontend/src/metabase/query_builder/components/filters/OperatorSelector.jsx index 4a06ef932a3..af7396ac601 100644 --- a/frontend/src/metabase/query_builder/components/filters/OperatorSelector.jsx +++ b/frontend/src/metabase/query_builder/components/filters/OperatorSelector.jsx @@ -1,24 +1,11 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import PropTypes from "prop-types"; import Select, { Option } from "metabase/components/Select"; import cx from "classnames"; -import type { - FilterOperator, - FilterOperatorName, -} from "metabase-types/types/Metadata"; - -type Props = { - operator: string, - operators: FilterOperator[], - onOperatorChange: (name: FilterOperatorName) => void, - className?: string, -}; - export default class OperatorSelector extends Component { - props: Props; - static propTypes = { operator: PropTypes.string, operators: PropTypes.array.isRequired, 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 4c88d6341c1..258651b5054 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import PropTypes from "prop-types"; import { t } from "ttag"; @@ -13,16 +14,6 @@ import Calendar from "metabase/components/Calendar"; import { FieldDimension } from "metabase-lib/lib/Dimension"; -import type { - FieldFilter, - TimeIntervalFilter, - DatetimeUnit, - ConcreteField, - LocalFieldReference, - ForeignFieldReference, - ExpressionReference, -} from "metabase-types/types/Query"; - const singleDatePickerPropTypes = { className: PropTypes.string, filter: PropTypes.object, @@ -102,20 +93,7 @@ const NextPicker = props => <RelativeDatePicker {...props} />; NextPicker.horizontalLayout = true; -type CurrentPickerProps = { - filter: TimeIntervalFilter, - onFilterChange: (filter: TimeIntervalFilter) => void, - className?: string, -}; - -type CurrentPickerState = { - showUnits: boolean, -}; - class CurrentPicker extends Component { - props: CurrentPickerProps; - state: CurrentPickerState; - state = { showUnits: false, }; @@ -166,10 +144,7 @@ const hasTime = value => * Returns MBQL :field clause with temporal bucketing applied. * @deprecated -- just use FieldDimension to do this stuff. */ -function getDateTimeField( - field: ConcreteField, - bucketing: ?DatetimeUnit, -): ConcreteField { +function getDateTimeField(field, bucketing) { const dimension = FieldDimension.parseMBQLOrWarn(field); if (dimension) { if (bucketing) { @@ -181,9 +156,7 @@ function getDateTimeField( return field; } -export function getDateTimeFieldTarget( - field: ConcreteField, -): LocalFieldReference | ForeignFieldReference | ExpressionReference { +export function getDateTimeFieldTarget(field) { const dimension = FieldDimension.parseMBQLOrWarn(field); if (dimension && dimension.temporalUnit()) { return dimension.withoutTemporalBucketing().mbql(); @@ -193,10 +166,7 @@ export function getDateTimeFieldTarget( } // add temporal-unit to fields if any of them have a time component -function getDateTimeFieldAndValues( - filter: FieldFilter, - count: number, -): [ConcreteField, any] { +function getDateTimeFieldAndValues(filter, count) { const values = filter .slice(2, 2 + count) .map(value => value && getDate(value)); @@ -205,27 +175,6 @@ function getDateTimeFieldAndValues( return [field, ...values]; } -export type OperatorName = - | "all" - | "previous" - | "next" - | "current" - | "before" - | "after" - | "on" - | "between" - | "empty" - | "not-empty"; - -export type Operator = { - name: OperatorName, - displayName: string, - widget?: any, - init: (filter: FieldFilter) => any, - test: (filter: FieldFilter) => boolean, - options?: { [key: string]: any }, -}; - const ALL_TIME_OPERATOR = { name: "all", displayName: t`All Time`, @@ -233,7 +182,7 @@ const ALL_TIME_OPERATOR = { test: op => op === null, }; -export const DATE_OPERATORS: Operator[] = [ +export const DATE_OPERATORS = [ { name: "previous", displayName: t`Previous`, @@ -305,7 +254,7 @@ export const DATE_OPERATORS: Operator[] = [ }, ]; -export const EMPTINESS_OPERATORS: Operator[] = [ +export const EMPTINESS_OPERATORS = [ { name: "empty", displayName: t`Is Empty`, @@ -320,34 +269,14 @@ export const EMPTINESS_OPERATORS: Operator[] = [ }, ]; -export const ALL_OPERATORS: Operator[] = DATE_OPERATORS.concat( - EMPTINESS_OPERATORS, -); +export const ALL_OPERATORS = DATE_OPERATORS.concat(EMPTINESS_OPERATORS); -export function getOperator( - filter: FieldFilter, - operators?: Operator[] = ALL_OPERATORS, -) { +export function getOperator(filter, operators = ALL_OPERATORS) { return _.find(operators, o => o.test(filter)); } -type Props = { - className?: string, - filter: FieldFilter, - onFilterChange: (filter: FieldFilter) => void, - hideEmptinessOperators?: boolean, // Don't show is empty / not empty dialog - hideTimeSelectors?: boolean, - includeAllTime?: boolean, - operators?: Operator[], -}; - -type State = { - operators: Operator[], -}; - export default class DatePicker extends Component { - props: Props; - state: State = { + state = { operators: [], }; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DefaultPicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/DefaultPicker.jsx index 1f4d3c11079..79244015471 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DefaultPicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DefaultPicker.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React from "react"; import PropTypes from "prop-types"; import cx from "classnames"; @@ -13,19 +14,6 @@ import { isFuzzyOperator, } from "metabase/lib/schema_metadata"; -import type Filter from "metabase-lib/lib/queries/structured/Filter"; - -type Props = { - filter: Filter, - setValue: (index: number, value: any) => void, - setValues: (value: any[]) => void, - onCommit: () => void, - className?: string, - isSidebar?: boolean, - minWidth?: number, - maxWidth?: number, -}; - const defaultPickerPropTypes = { filter: PropTypes.object, setValue: PropTypes.func, @@ -51,7 +39,7 @@ export default function DefaultPicker({ isSidebar, minWidth, maxWidth, -}: Props) { +}) { const operator = filter.operator(); if (!operator) { return <div className={className} />; @@ -81,7 +69,7 @@ export default function DefaultPicker({ <SelectPicker key={index} options={operatorField.values} - values={(values: Array<string>)} + values={values} onValuesChange={onValuesChange} placeholder={placeholder} multi={operator.multi} @@ -98,7 +86,7 @@ export default function DefaultPicker({ return ( <FieldValuesWidget className="input" - value={(values: Array<string>)} + value={values} onChange={onValuesChange} multi={operator.multi} placeholder={placeholder} @@ -117,7 +105,7 @@ export default function DefaultPicker({ return ( <TextPicker key={index} - values={(values: Array<string>)} + values={values} onValuesChange={onValuesChange} placeholder={placeholder} multi={operator.multi} @@ -128,7 +116,7 @@ export default function DefaultPicker({ return ( <NumberPicker key={index} - values={(values: Array<number | null>)} + values={values} onValuesChange={onValuesChange} placeholder={placeholder} multi={operator.multi} 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 20a612938c8..2a66af8f1a3 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/NumberPicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/NumberPicker.jsx @@ -1,26 +1,11 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import PropTypes from "prop-types"; import { t } from "ttag"; import TextPicker from "./TextPicker"; -type Props = { - values: Array<number | null>, - onValuesChange: (values: any[]) => void, - placeholder?: string, - multi?: boolean, - onCommit: () => void, -}; - -type State = { - stringValues: Array<string>, - validations: boolean[], -}; - export default class NumberPicker extends Component { - props: Props; - state: State; - - constructor(props: Props) { + constructor(props) { super(props); this.state = { stringValues: props.values.map(v => { @@ -45,11 +30,11 @@ export default class NumberPicker extends Component { placeholder: t`Enter desired number`, }; - _validate(values: Array<number | null>) { + _validate(values) { return values.map(v => v === undefined || !isNaN(v)); } - onValuesChange(stringValues: string[]) { + onValuesChange(stringValues) { const values = stringValues.map(v => parseFloat(v)); this.props.onValuesChange(values.map(v => (isNaN(v) ? null : v))); this.setState({ @@ -59,10 +44,7 @@ export default class NumberPicker extends Component { } render() { - const values: Array<string | null> = this.state.stringValues.slice( - 0, - this.props.values.length, - ); + const values = this.state.stringValues.slice(0, this.props.values.length); return ( <TextPicker {...this.props} 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 a931c325668..ab8bf87ad13 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/RelativeDatePicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/RelativeDatePicker.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import cx from "classnames"; @@ -6,39 +7,14 @@ import DateUnitSelector from "../DateUnitSelector"; import { assoc } from "icepick"; -import type { - TimeIntervalFilter, - RelativeDatetimeUnit, -} from "metabase-types/types/Query"; +export const DATE_PERIODS = ["day", "week", "month", "quarter", "year"]; -export const DATE_PERIODS: RelativeDatetimeUnit[] = [ - "day", - "week", - "month", - "quarter", - "year", -]; - -const TIME_PERIODS: RelativeDatetimeUnit[] = ["minute", "hour"]; +const TIME_PERIODS = ["minute", "hour"]; // define ALL_PERIODS in increasing order of duration const ALL_PERIODS = TIME_PERIODS.concat(DATE_PERIODS); -type Props = { - filter: TimeIntervalFilter, - onFilterChange: (filter: TimeIntervalFilter) => void, - formatter: (value: any) => any, - className?: string, -}; - -type State = { - showUnits: boolean, -}; - export default class RelativeDatePicker extends Component { - props: Props; - state: State; - state = { showUnits: false, }; 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 5d57ca01dc1..08f7a2da1ee 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/SelectPicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/SelectPicker.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import PropTypes from "prop-types"; import { t } from "ttag"; @@ -9,29 +10,8 @@ import { createMultiwordSearchRegex } from "metabase/lib/string"; import cx from "classnames"; -type SelectOption = { - name: string, - key: string, -}; - -type Props = { - options: Array<SelectOption>, - values: Array<string>, - onValuesChange: (values: any[]) => void, - placeholder?: string, - multi?: boolean, -}; - -type State = { - searchText: string, - searchRegex: ?RegExp, -}; - export default class SelectPicker extends Component { - state: State; - props: Props; - - constructor(props: Props) { + constructor(props) { super(props); this.state = { @@ -48,7 +28,7 @@ export default class SelectPicker extends Component { multi: PropTypes.bool, }; - updateSearchText = (value: string) => { + updateSearchText = value => { let regex = null; if (value) { @@ -61,7 +41,7 @@ export default class SelectPicker extends Component { }); }; - selectValue(key: string, selected: boolean) { + selectValue(key, selected) { let values; if (this.props.multi) { values = this.props.values.slice().filter(v => v != null); @@ -76,7 +56,7 @@ export default class SelectPicker extends Component { this.props.onValuesChange(values); } - nameForOption(option: SelectOption) { + nameForOption(option) { if (option.name === "") { return t`Empty`; } else if ( 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 7c628c72b68..502fcac4601 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/SpecificDatePicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/SpecificDatePicker.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import PropTypes from "prop-types"; import { t } from "ttag"; @@ -14,23 +15,8 @@ import cx from "classnames"; const DATE_FORMAT = "YYYY-MM-DD"; const DATE_TIME_FORMAT = "YYYY-MM-DDTHH:mm:ss"; -type Props = { - value: ?string, - onChange: (value: ?string) => void, - calendar?: boolean, - hideTimeSelectors?: boolean, - className?: string, -}; - -type State = { - showCalendar: boolean, -}; - export default class SpecificDatePicker extends Component { - props: Props; - state: State; - - constructor(props: Props) { + constructor(props) { super(props); this.state = { @@ -43,7 +29,7 @@ export default class SpecificDatePicker extends Component { onChange: PropTypes.func.isRequired, }; - onChange = (date: ?string, hours: ?number, minutes: ?number) => { + onChange = (date, hours, minutes) => { const m = moment(date); if (!m.isValid()) { this.props.onChange(null); 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 02bd625e051..751211ecd81 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/TextPicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/TextPicker.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import PropTypes from "prop-types"; import AutosizeTextarea from "react-textarea-autosize"; @@ -5,23 +6,7 @@ import { t } from "ttag"; import cx from "classnames"; import _ from "underscore"; -type Props = { - values: Array<string>, - onValuesChange: (values: any[]) => void, - validations: boolean[], - placeholder?: string, - multi?: boolean, - onCommit: () => void, -}; - -type State = { - fieldString: string, -}; - export default class TextPicker extends Component { - props: Props; - state: State; - static propTypes = { values: PropTypes.array.isRequired, onValuesChange: PropTypes.func.isRequired, @@ -36,14 +21,14 @@ export default class TextPicker extends Component { placeholder: t`Enter desired text`, }; - constructor(props: Props) { + constructor(props) { super(props); this.state = { fieldString: props.values.join(", "), }; } - setValue(fieldString: ?string) { + setValue(fieldString) { if (fieldString != null) { // Only strip newlines from field string to not interfere with copy-pasting const newLineRegex = /\r?\n|\r/g; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/TimePicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/TimePicker.jsx index 35e1f5fba64..97958748337 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/TimePicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/TimePicker.jsx @@ -7,8 +7,6 @@ import HoursMinutesInput from "./HoursMinutesInput"; import { parseTime } from "metabase/lib/time"; -import type { Operator } from "./DatePicker"; - const TimeInput = ({ value, onChange }) => { const time = parseTime(value); return ( @@ -70,7 +68,7 @@ const getTime = value => { } }; -export const TIME_OPERATORS: Operator[] = [ +export const TIME_OPERATORS = [ { name: "before", displayName: t`Before`, diff --git a/frontend/src/metabase/query_builder/components/notebook/lib/steps.js b/frontend/src/metabase/query_builder/components/notebook/lib/steps.js index 86ff21204c3..65f06b2a14e 100644 --- a/frontend/src/metabase/query_builder/components/notebook/lib/steps.js +++ b/frontend/src/metabase/query_builder/components/notebook/lib/steps.js @@ -1,7 +1,4 @@ import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; -import type Question from "metabase-lib/lib/Question"; - -import type { StructuredDatasetQuery } from "metabase-types/types/Card"; import _ from "underscore"; @@ -9,90 +6,9 @@ import _ from "underscore"; // allowed to be added at every other step, generating a preview query at each step, how to delete a step, // ensuring steps that become invalid after modifying an upstream step are removed, etc. -type StepType = - | "data" - | "join" - | "expression" - | "filter" - | "summarize" - | "sort" - | "limit"; - -type StepDefinition = NormalStepDefinition | SubStepDefinition; - -type NormalStepDefinition = { - // a type name for the step - type: StepType, - // returns true if the step can be added to the provided query - valid: (query: StructuredQuery) => boolean, - // returns true if the provided query already has this step - active: (query: StructuredQuery) => boolean, - // logic to remove invalid clauses that were added by this step from the provided query - clean: (query: StructuredQuery) => StructuredQuery, - // logic to remove this step from the provided query - revert?: (query: StructuredQuery) => StructuredQuery, -}; - -type SubStepDefinition = { - // a type name for the step - type: StepType, - // returns true if the step can be added to the provided query - valid: (query: StructuredQuery, subStepIndex: number) => boolean, - // returns true if the provided query already has this step - active: (query: StructuredQuery, subStepIndex: number) => boolean, - // logic to remove invalid clauses that were added by this step from the provided query - clean: (query: StructuredQuery, subStepIndex: number) => StructuredQuery, - // logic to remove this step from the provided query - revert?: (query: StructuredQuery, subStepIndex: number) => StructuredQuery, - // how many sub-steps are there - subSteps?: (query: StructuredQuery) => number, -}; - // identifier for this step, e.x. `0:data` (or `0:join:1` for sub-steps) -type StepId = string; - -type Step = { - id: StepId, - // the step type, corresponds with type in StepDefinition - type: StepType, - // if there are nested queries, this indicates the level of nested (0 being the root query) - stageIndex: number, - // if there are sub-steps, this indicates the index of the sub-step - itemIndex: number, - // is this step currently allowed? - valid: boolean, - // is this step currently applied? - active: boolean, - // is this step visible? (if it's active or just added) - visible: boolean, - // the query for this "stage" - query: StructuredQuery, - // a query to preview query at this step - previewQuery: ?StructuredQuery, - // remove this step - revert: ?(query: StructuredQuery) => StructuredQuery, - // remove invalid clauses set by this step - clean: (query: StructuredQuery) => StructuredQuery, - // update the query at this step and clean subsequent queries - update: (datasetQuery: StructuredDatasetQuery) => StructuredQuery, - // any valid actions that can be applied after this step - actions: StepAction[], - // pointer to the next step, if any - next: ?Step, - // pointer to the previous step, if any - previous: ?Step, -}; - -type StepAction = { - type: StepType, - action: Function, -}; - -type OpenSteps = { - [id: StepId]: boolean, -}; -const STEPS: StepDefinition[] = [ +const STEPS = [ { type: "data", valid: query => !query.sourceQuery(), @@ -186,10 +102,7 @@ const STEPS: StepDefinition[] = [ /** * Returns an array of "steps" to be displayed in the notebook for one "stage" (nesting) of a query */ -export function getQuestionSteps( - question: Question, - openSteps: OpenSteps = {}, -): Step[] { +export function getQuestionSteps(question, openSteps = {}) { const allSteps = []; let query = question.query(); @@ -231,17 +144,13 @@ export function getQuestionSteps( /** * Returns an array of "steps" to be displayed in the notebook for one "stage" (nesting) of a query */ -export function getStageSteps( - stageQuery: StructuredQuery, - stageIndex: number, - openSteps: OpenSteps, -): { steps: Step[], actions: StepAction[] } { +export function getStageSteps(stageQuery, stageIndex, openSteps) { const getId = (step, itemIndex) => `${stageIndex}:${step.type}` + (itemIndex > 0 ? `:${itemIndex}` : ``); function getStep(STEP, itemIndex = null) { const id = getId(STEP, itemIndex); - const step: Step = { + const step = { id: id, type: STEP.type, stageIndex: stageIndex, diff --git a/frontend/src/metabase/query_builder/components/notebook/steps/SortStep.jsx b/frontend/src/metabase/query_builder/components/notebook/steps/SortStep.jsx index 26ae3b41b37..35fe6ed8593 100644 --- a/frontend/src/metabase/query_builder/components/notebook/steps/SortStep.jsx +++ b/frontend/src/metabase/query_builder/components/notebook/steps/SortStep.jsx @@ -52,20 +52,6 @@ export default function SortStep({ import FieldList from "metabase/query_builder/components/FieldList"; -import type { OrderBy } from "metabase-types/types/Query"; -import type { FieldOptions } from "metabase-types/types/Metadata"; -import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"; - -type Props = { - sort?: OrderBy, - onChangeSort: (sort: OrderBy) => void, - query: StructuredQuery, - sortOptions?: FieldOptions, - onClose?: () => void, - maxHeight?: number, - alwaysExpanded?: boolean, -}; - const SortPopover = ({ sort = ["asc", null], onChangeSort, @@ -74,7 +60,7 @@ const SortPopover = ({ onClose, maxHeight, alwaysExpanded, -}: Props) => { +}) => { const table = query.table(); // FieldList requires table if (!table) { diff --git a/frontend/src/metabase/query_builder/components/template_tags/SnippetSidebar.jsx b/frontend/src/metabase/query_builder/components/template_tags/SnippetSidebar.jsx index 12b3a3b854c..04205cee206 100644 --- a/frontend/src/metabase/query_builder/components/template_tags/SnippetSidebar.jsx +++ b/frontend/src/metabase/query_builder/components/template_tags/SnippetSidebar.jsx @@ -24,26 +24,6 @@ import SnippetCollections from "metabase/entities/snippet-collections"; import { canonicalCollectionId } from "metabase/entities/collections"; import Search from "metabase/entities/search"; -import type { Snippet } from "metabase-types/types/Snippet"; - -type Props = { - onClose: () => void, - setModalSnippet: () => void, - openSnippetModalWithSelectedText: () => void, - insertSnippet: () => void, - snippets: Snippet[], - snippetCollection: any, - snippetCollections: any[], - search: any[], - setSnippetCollectionId: () => void, -}; - -type State = { - showSearch: boolean, - searchString: string, - showArchived: boolean, -}; - const ICON_SIZE = 16; const HEADER_ICON_SIZE = 18; const MIN_SNIPPETS_FOR_SEARCH = 15; @@ -63,13 +43,11 @@ const MIN_SNIPPETS_FOR_SEARCH = 15; }), }) export default class SnippetSidebar extends React.Component { - props: Props; - state: State = { + state = { showSearch: false, searchString: "", showArchived: false, }; - searchBox: ?HTMLInputElement; static propTypes = { onClose: PropTypes.func.isRequired, diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.jsx b/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.jsx index cca3de56e4f..ec330cde30f 100644 --- a/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.jsx +++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.jsx @@ -11,31 +11,14 @@ import Select, { Option } from "metabase/components/Select"; import ParameterValueWidget from "metabase/parameters/components/ParameterValueWidget"; import { getParameterOptionsForField } from "metabase/parameters/utils/template-tag-options"; -import type { TemplateTag } from "metabase-types/types/Query"; -import type { Database } from "metabase-types/types/Database"; -import Field from "metabase-lib/lib/metadata/Field"; import { fetchField } from "metabase/redux/metadata"; import { getMetadata } from "metabase/selectors/metadata"; import { SchemaTableAndFieldDataSelector } from "metabase/query_builder/components/DataSelector"; -import Metadata from "metabase-lib/lib/metadata/Metadata"; import MetabaseSettings from "metabase/lib/settings"; -import type { FieldId } from "metabase-types/types/Field"; - -type Props = { - tag: TemplateTag, - setTemplateTag: (tag: TemplateTag) => void, - databaseFields: Field[], - database: Database, - databases: Database[], - metadata: Metadata, - fetchField: FieldId => void, -}; @connect(state => ({ metadata: getMetadata(state) }), { fetchField }) export default class TagEditorParam extends Component { - props: Props; - UNSAFE_componentWillMount() { const { tag, fetchField } = this.props; diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorSidebar.jsx b/frontend/src/metabase/query_builder/components/template_tags/TagEditorSidebar.jsx index 640b9fe7c45..8b49fb8ecd0 100644 --- a/frontend/src/metabase/query_builder/components/template_tags/TagEditorSidebar.jsx +++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorSidebar.jsx @@ -14,31 +14,9 @@ import SidebarContent from "metabase/query_builder/components/SidebarContent"; import * as MetabaseAnalytics from "metabase/lib/analytics"; import NativeQuery from "metabase-lib/lib/queries/NativeQuery"; -import type { DatasetQuery } from "metabase-types/types/Card"; -import type { TableId } from "metabase-types/types/Table"; -import type { Database } from "metabase-types/types/Database"; -import type { TemplateTag } from "metabase-types/types/Query"; -import type { Field as FieldObject } from "metabase-types/types/Field"; - -type Props = { - query: NativeQuery, - - setDatasetQuery: (datasetQuery: DatasetQuery) => void, - setTemplateTag: (tag: TemplateTag) => void, - - databaseFields: FieldObject[], - databases: Database[], - sampleDatasetId: TableId, - - onClose: () => void, -}; -type State = { - section: "help" | "settings", -}; export default class TagEditorSidebar extends React.Component { - props: Props; - state: State = { + state = { section: "settings", }; diff --git a/frontend/src/metabase/query_builder/components/template_tags/snippet-sidebar/SnippetRow.jsx b/frontend/src/metabase/query_builder/components/template_tags/snippet-sidebar/SnippetRow.jsx index 9ea57a1d0d0..af973474313 100644 --- a/frontend/src/metabase/query_builder/components/template_tags/snippet-sidebar/SnippetRow.jsx +++ b/frontend/src/metabase/query_builder/components/template_tags/snippet-sidebar/SnippetRow.jsx @@ -14,8 +14,6 @@ const ICON_SIZE = 16; wrapped: true, }) class SnippetRow extends React.Component { - state: { isOpen: boolean }; - constructor(props) { super(props); this.state = { isOpen: false }; diff --git a/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx b/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx index 32faeb13501..347f6d337f0 100644 --- a/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx +++ b/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx @@ -159,10 +159,6 @@ const mapDispatchToProps = { @titleWithLoadingTime("queryStartTime") @fitViewport export default class QueryBuilder extends Component { - timeout: any; - - forceUpdateDebounced: () => void; - constructor(props, context) { super(props, context); diff --git a/frontend/src/metabase/services.js b/frontend/src/metabase/services.js index 49d6b46333d..a679a2ae083 100644 --- a/frontend/src/metabase/services.js +++ b/frontend/src/metabase/services.js @@ -2,7 +2,6 @@ import _ from "underscore"; import { GET, PUT, POST, DELETE } from "metabase/lib/api"; import { IS_EMBED_PREVIEW } from "metabase/lib/embed"; -import Metadata from "metabase-lib/lib/metadata/Metadata"; import Question from "metabase-lib/lib/Question"; import { FieldDimension } from "metabase-lib/lib/Dimension"; @@ -11,13 +10,6 @@ const embedBase = IS_EMBED_PREVIEW ? "/api/preview_embed" : "/api/embed"; import getGAMetadata from "promise-loader?global!metabase/lib/ga-metadata"; // eslint-disable-line import/default -import type { Data, Options, APIMethod } from "metabase/lib/api"; - -import type { Card } from "metabase-types/types/Card"; -import type { DatabaseId } from "metabase-types/types/Database"; -import type { DatabaseCandidates } from "metabase-types/types/Auto"; -import type { DashboardWithCards } from "metabase-types/types/Dashboard"; - export const ActivityApi = { list: GET("/api/activity"), recent_views: GET("/api/activity/recent_views"), @@ -35,11 +27,7 @@ export const GTAPApi = { // To fetch that extra data we rely on specific APIs for pivot tables that mirrow the normal endpoints. // Those endpoints take the query along with `pivot_rows` and `pivot_cols` to return the subtotal data. // If we add breakout/grouping sets to MBQL in the future we can remove this API switching. -export function maybeUsePivotEndpoint( - api: APIMethod, - card: Card, - metadata?: Metadata, -): APIMethod { +export function maybeUsePivotEndpoint(api, card, metadata) { function canonicalFieldRef(ref) { // Field refs between the query and setting might differ slightly. // This function trims binned dimensions to just the field-id @@ -53,7 +41,7 @@ export function maybeUsePivotEndpoint( const question = new Question(card, metadata); function wrap(api) { - return (params: ?Data, ...rest: any) => { + return (params, ...rest) => { const setting = question.setting("pivot_table.column_split"); const breakout = (question.isStructured() && question.query().breakouts()) || []; @@ -191,12 +179,7 @@ export const EmbedApi = { ), }; -type $AutoApi = { - dashboard: ({ subPath: string }) => DashboardWithCards, - db_candidates: ({ id: DatabaseId }) => DatabaseCandidates, -}; - -export const AutoApi: $AutoApi = { +export const AutoApi = { dashboard: GET("/api/automagic-dashboards/:subPath", { // this prevents the `subPath` parameter from being URL encoded raw: { subPath: true }, @@ -439,13 +422,13 @@ export const TaskApi = { getJobsInfo: GET("/api/task/info"), }; -export function setPublicQuestionEndpoints(uuid: string) { +export function setPublicQuestionEndpoints(uuid) { setFieldEndpoints("/api/public/card/:uuid", { uuid }); } export function setPublicDashboardEndpoints() { setParamsEndpoints("/api/public"); } -export function setEmbedQuestionEndpoints(token: string) { +export function setEmbedQuestionEndpoints(token) { if (!IS_EMBED_PREVIEW) { setFieldEndpoints("/api/embed/card/:token", { token }); } @@ -456,12 +439,11 @@ export function setEmbedDashboardEndpoints() { } } -function GET_with(url: string, params: Data) { - return (data: Data, options?: Options) => - GET(url)({ ...params, ...data }, options); +function GET_with(url, params) { + return (data, options) => GET(url)({ ...params, ...data }, options); } -function setFieldEndpoints(prefix: string, params: Data) { +function setFieldEndpoints(prefix, params) { MetabaseApi.field_values = GET_with( prefix + "/field/:fieldId/values", params, @@ -476,7 +458,7 @@ function setFieldEndpoints(prefix: string, params: Data) { ); } -function setParamsEndpoints(prefix: string) { +function setParamsEndpoints(prefix) { DashboardApi.parameterValues = GET( prefix + "/dashboard/:dashId/params/:paramId/values", ); diff --git a/frontend/src/metabase/visualizations/components/CardRenderer.jsx b/frontend/src/metabase/visualizations/components/CardRenderer.jsx index b996c9997d5..0f312d58afe 100644 --- a/frontend/src/metabase/visualizations/components/CardRenderer.jsx +++ b/frontend/src/metabase/visualizations/components/CardRenderer.jsx @@ -10,15 +10,6 @@ import { startTimer } from "metabase/lib/performance"; import { isSameSeries } from "metabase/visualizations/lib/utils"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; - -type DeregisterFunction = () => void; - -type Props = VisualizationProps & { - renderer: (element: Element, props: VisualizationProps) => DeregisterFunction, - style?: any, -}; - // We track this as part of the render loop. // It's throttled to prevent pounding GA on every prop update. const trackEventThrottled = _.throttle( @@ -28,8 +19,6 @@ const trackEventThrottled = _.throttle( @ExplicitSize({ wrapped: true }) export default class CardRenderer extends Component { - props: Props; - static propTypes = { className: PropTypes.string, series: PropTypes.array.isRequired, @@ -39,9 +28,7 @@ export default class CardRenderer extends Component { isDashboard: PropTypes.bool, }; - _deregister: ?DeregisterFunction; - - shouldComponentUpdate(nextProps: Props) { + shouldComponentUpdate(nextProps) { // a chart only needs re-rendering when the result itself changes OR the chart type is different const sameSize = this.props.width === nextProps.width && diff --git a/frontend/src/metabase/visualizations/components/ChartClickActions.jsx b/frontend/src/metabase/visualizations/components/ChartClickActions.jsx index b1cfacf96d5..ce4c8ab3160 100644 --- a/frontend/src/metabase/visualizations/components/ChartClickActions.jsx +++ b/frontend/src/metabase/visualizations/components/ChartClickActions.jsx @@ -14,11 +14,6 @@ import * as MetabaseAnalytics from "metabase/lib/analytics"; import { performAction } from "metabase/visualizations/lib/action"; -import type { - ClickObject, - ClickAction, -} from "metabase-types/types/Visualization"; - import cx from "classnames"; import _ from "underscore"; @@ -76,21 +71,9 @@ Object.values(SECTIONS).map((section, index) => { const getGALabelForAction = action => action ? `${action.section || ""}:${action.name || ""}` : null; -type Props = { - clicked: ?ClickObject, - clickActions: ?(ClickAction[]), - onChangeCardAndRun: Object => void, - onClose: () => void, -}; - -type State = { - popoverAction: ?ClickAction, -}; - @connect() export default class ChartClickActions extends Component { - props: Props; - state: State = { + state = { popoverAction: null, }; @@ -101,7 +84,7 @@ export default class ChartClickActions extends Component { } }; - handleClickAction = (action: ClickAction) => { + handleClickAction = action => { const { dispatch, onChangeCardAndRun } = this.props; if (action.popover) { MetabaseAnalytics.trackStructEvent( @@ -271,15 +254,7 @@ export default class ChartClickActions extends Component { } } -export const ChartClickAction = ({ - action, - isLastItem, - handleClickAction, -}: { - action: any, - isLastItem: any, - handleClickAction: any, -}) => { +export const ChartClickAction = ({ action, isLastItem, handleClickAction }) => { // This is where all the different action button styles get applied. // Some of them have bespoke classes defined in ChartClickActions.css, // like for cases when we needed to really dial in the spacing. diff --git a/frontend/src/metabase/visualizations/components/ColumnSettings.jsx b/frontend/src/metabase/visualizations/components/ColumnSettings.jsx index 1bc9fcfd8f8..3b2d454c19b 100644 --- a/frontend/src/metabase/visualizations/components/ColumnSettings.jsx +++ b/frontend/src/metabase/visualizations/components/ColumnSettings.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React from "react"; import { t } from "ttag"; @@ -13,18 +14,6 @@ import { import ChartSettingsWidget from "metabase/visualizations/components/ChartSettingsWidget"; import NoResults from "assets/img/no_results.svg"; -type SettingId = string; -type Settings = { [id: SettingId]: any }; - -type Props = { - value: Settings, - onChange: (settings: Settings) => void, - column: any, - allowlist?: Set<SettingId>, - denylist?: Set<SettingId>, - inheritedSettings?: Settings, -}; - const ColumnSettings = ({ value, onChange, @@ -32,7 +21,7 @@ const ColumnSettings = ({ allowlist, denylist, inheritedSettings = {}, -}: Props) => { +}) => { const storedSettings = value || {}; // fake series diff --git a/frontend/src/metabase/visualizations/components/FunnelBar.jsx b/frontend/src/metabase/visualizations/components/FunnelBar.jsx index ee7a016ea16..172e4cd0c5f 100644 --- a/frontend/src/metabase/visualizations/components/FunnelBar.jsx +++ b/frontend/src/metabase/visualizations/components/FunnelBar.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import BarChart from "metabase/visualizations/visualizations/BarChart"; @@ -5,11 +6,7 @@ import BarChart from "metabase/visualizations/visualizations/BarChart"; import { getComputedSettingsForSeries } from "metabase/visualizations/lib/settings/visualization"; import { assocIn } from "icepick"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; - export default class FunnelBar 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 033f01d4695..9af0dc1ec9f 100644 --- a/frontend/src/metabase/visualizations/components/FunnelNormal.jsx +++ b/frontend/src/metabase/visualizations/components/FunnelNormal.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import cx from "classnames"; @@ -11,27 +12,7 @@ import { normal } from "metabase/lib/colors"; const DEFAULT_COLORS = Object.values(normal); -import type { - VisualizationProps, - HoverObject, - ClickObject, -} from "metabase-types/types/Visualization"; - -type StepInfo = { - value: number, - graph: { - startBottom: number, - startTop: number, - endBottom: number, - endTop: number, - }, - hovered?: HoverObject, - clicked?: ClickObject, -}; - export default class FunnelNormal extends Component { - props: VisualizationProps; - render() { const { className, @@ -47,7 +28,7 @@ export default class FunnelNormal extends Component { const dimensionIndex = 0; const metricIndex = 1; const cols = series[0].data.cols; - const rows: number[][] = series.map(s => s.data.rows[0]); + const rows = series.map(s => s.data.rows[0]); const isNarrow = gridSize && gridSize.width < 7; const isShort = gridSize && gridSize.height <= 5; @@ -68,7 +49,7 @@ export default class FunnelNormal extends Component { const formatPercent = percent => `${(100 * percent).toFixed(2)} %`; // Initial infos (required for step calculation) - let infos: StepInfo[] = [ + let infos = [ { value: rows[0][metricIndex], graph: { @@ -80,7 +61,7 @@ export default class FunnelNormal extends Component { }, ]; - let remaining: number = rows[0][metricIndex]; + let remaining = rows[0][metricIndex]; rows.map((row, rowIndex) => { remaining -= infos[rowIndex].value - row[metricIndex]; @@ -207,14 +188,6 @@ const GraphSection = ({ onHoverChange, onVisualizationClick, className, -}: { - className?: string, - index: number, - info: StepInfo, - infos: StepInfo[], - hovered: ?HoverObject, - onVisualizationClick: ?(clicked: ?ClickObject) => void, - onHoverChange: (hovered: ?HoverObject) => void, }) => { return ( <div className="relative full-height"> diff --git a/frontend/src/metabase/visualizations/components/LineAreaBarChart.jsx b/frontend/src/metabase/visualizations/components/LineAreaBarChart.jsx index d41cea72f46..9779bd9a9c8 100644 --- a/frontend/src/metabase/visualizations/components/LineAreaBarChart.jsx +++ b/frontend/src/metabase/visualizations/components/LineAreaBarChart.jsx @@ -74,15 +74,9 @@ for (let i = 0; i < MAX_SERIES; i++) { addCSSRule(`.LineAreaBarChart.mute-${i} svg:not(.stacked) .row`, MUTE_STYLE); } -import type { VisualizationProps } from "metabase-types/types/Visualization"; import { normal } from "metabase/lib/colors"; export default class LineAreaBarChart extends Component { - props: VisualizationProps; - - static identifier: string; - static renderer: (element: Element, props: VisualizationProps) => any; - static noHeader = true; static supportsSeries = true; diff --git a/frontend/src/metabase/visualizations/components/PinMap.jsx b/frontend/src/metabase/visualizations/components/PinMap.jsx index 3cf447b9f97..b0a1791e57e 100644 --- a/frontend/src/metabase/visualizations/components/PinMap.jsx +++ b/frontend/src/metabase/visualizations/components/PinMap.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import { t } from "ttag"; import { hasLatitudeAndLongitudeColumns } from "metabase/lib/schema_metadata"; @@ -14,28 +15,11 @@ import d3 from "d3"; import L from "leaflet"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; - const WORLD_BOUNDS = [ [-90, -180], [90, 180], ]; -type Props = VisualizationProps; - -type State = { - lat: ?number, - lng: ?number, - min: ?number, - max: ?number, - binHeight: ?number, - binWidth: ?number, - zoom: ?number, - points: L.Point[], - bounds: L.Bounds, - filtering: boolean, -}; - const MAP_COMPONENTS_BY_TYPE = { markers: LeafletMarkerPinMap, tiles: LeafletTilePinMap, @@ -44,9 +28,6 @@ const MAP_COMPONENTS_BY_TYPE = { }; export default class PinMap extends Component { - props: Props; - state: State; - static uiName = t`Pin Map`; static identifier = "pin_map"; static iconName = "pinmap"; @@ -65,10 +46,10 @@ export default class PinMap extends Component { } } - state: State; - _map: ?(LeafletMarkerPinMap | LeafletTilePinMap) = null; + state; + _map = null; - constructor(props: Props) { + constructor(props) { super(props); this.state = { lat: null, @@ -79,7 +60,7 @@ export default class PinMap extends Component { }; } - UNSAFE_componentWillReceiveProps(newProps: Props) { + UNSAFE_componentWillReceiveProps(newProps) { const SETTINGS_KEYS = [ "map.latitude_column", "map.longitude_column", @@ -111,15 +92,15 @@ export default class PinMap extends Component { this.setState({ lat: null, lng: null, zoom: null }); }; - onMapCenterChange = (lat: number, lng: number) => { + onMapCenterChange = (lat, lng) => { this.setState({ lat, lng }); }; - onMapZoomChange = (zoom: number) => { + onMapZoomChange = zoom => { this.setState({ zoom }); }; - _getPoints(props: Props) { + _getPoints(props) { const { settings, series: [ diff --git a/frontend/src/metabase/visualizations/components/TableInteractive.jsx b/frontend/src/metabase/visualizations/components/TableInteractive.jsx index 8e1ef43aaa7..bfe699c580f 100644 --- a/frontend/src/metabase/visualizations/components/TableInteractive.jsx +++ b/frontend/src/metabase/visualizations/components/TableInteractive.jsx @@ -41,13 +41,6 @@ const HEADER_DRAG_THRESHOLD = 5; // HACK: used to get react-draggable to reset after a drag let DRAG_COUNTER = 0; -import type { - VisualizationProps, - ClickObject, -} from "metabase-types/types/Visualization"; -import type { VisualizationSettings } from "metabase-types/types/Card"; -import type { DatasetData, Value } from "metabase-types/types/Dataset"; - function pickRowsToMeasure(rows, columnIndex, count = 10) { const rowIndexes = []; // measure up to 10 non-nil cells @@ -63,62 +56,9 @@ function pickRowsToMeasure(rows, columnIndex, count = 10) { return rowIndexes; } -type Props = VisualizationProps & { - width: number, - height: number, - sort: any, - isPivoted: boolean, - onActionDismissal: () => void, - onContentWidthChange: (number, number[]) => void, - renderTableCellWrapper: any, - renderTableHeaderWrapper: any, - tableHeaderHeight: number, - getColumnTitle: number => string, - data: any, -}; -type State = { - columnWidths: number[], - contentWidths: ?(number[]), - - dragColIndex?: ?number, - dragColStyle?: ?{ [key: string]: any }, - dragColNewLefts?: ?(number[]), - dragColNewIndex?: ?number, - columnPositions?: ?({ - left: number, - right: number, - center: number, - width: number, - }[]), -}; - -type CellRendererProps = { - key: string, - style: { [key: string]: any }, - columnIndex: number, - rowIndex: number, -}; - -type GridComponent = Component<void, void, void> & { - recomputeGridSize: () => void, -}; - @ExplicitSize() export default class TableInteractive extends Component { - state: State; - props: Props; - - columnHasResized: { [key: number]: boolean }; - columnNeedsResize: { [key: number]: boolean }; - _div: HTMLElement; - _totalContentWidth: ?number; - _previousOverscrollBehaviorX: any; - - header: GridComponent; - grid: GridComponent; - headerRefs: HTMLElement[]; - - constructor(props: Props) { + constructor(props) { super(props); this.state = { @@ -168,7 +108,7 @@ export default class TableInteractive extends Component { } } - UNSAFE_componentWillReceiveProps(newProps: Props) { + UNSAFE_componentWillReceiveProps(newProps) { if ( this.props.data && newProps.data && @@ -185,12 +125,12 @@ export default class TableInteractive extends Component { } } - _getColumnSettings(props: Props) { + _getColumnSettings(props) { return props.data && props.data.cols.map(col => props.settings.column(col)); } - shouldComponentUpdate(nextProps: Props, nextState: State) { - const PROP_KEYS: string[] = ["width", "height", "settings", "data"]; + shouldComponentUpdate(nextProps, nextState) { + const PROP_KEYS = ["width", "height", "settings", "data"]; // compare specific props and state to determine if we should re-render return ( !_.isEqual( @@ -260,7 +200,7 @@ export default class TableInteractive extends Component { columnElement => columnElement.offsetWidth, ); - const columnWidths: number[] = cols.map((col, index) => { + const columnWidths = cols.map((col, index) => { if (this.columnNeedsResize) { if ( this.columnNeedsResize[index] && @@ -298,13 +238,13 @@ export default class TableInteractive extends Component { this.setState({ contentWidths: null }); }, 100); - onCellResize(columnIndex: number) { + onCellResize(columnIndex) { this.columnNeedsResize = this.columnNeedsResize || {}; this.columnNeedsResize[columnIndex] = true; this.recomputeColumnSizes(); } - onColumnResize(columnIndex: number, width: number) { + onColumnResize(columnIndex, width) { const { settings } = this.props; const columnWidthsSetting = settings["table.column_widths"] ? settings["table.column_widths"].slice() @@ -316,7 +256,7 @@ export default class TableInteractive extends Component { setTimeout(() => this.recomputeGridSize(), 1); } - onColumnReorder(columnIndex: number, newColumnIndex: number) { + onColumnReorder(columnIndex, newColumnIndex) { const { settings, onUpdateVisualizationSettings } = this.props; const columns = settings["table.columns"].slice(); // copy since splice mutates columns.splice(newColumnIndex, 0, columns.splice(columnIndex, 1)[0]); @@ -325,14 +265,14 @@ export default class TableInteractive extends Component { }); } - onVisualizationClick(clicked: ?ClickObject, element: HTMLElement) { + onVisualizationClick(clicked, element) { const { onVisualizationClick } = this.props; if (this.visualizationIsClickable(clicked)) { onVisualizationClick({ ...clicked, element }); } } - getCellClickedObject(rowIndex: number, columnIndex: number) { + getCellClickedObject(rowIndex, columnIndex) { try { return this._getCellClickedObjectCached( this.props.data, @@ -374,7 +314,7 @@ export default class TableInteractive extends Component { ); } - getHeaderClickedObject(columnIndex: number) { + getHeaderClickedObject(columnIndex) { try { return this._getHeaderClickedObjectCached( this.props.data, @@ -387,15 +327,11 @@ export default class TableInteractive extends Component { } // NOTE: all arguments must be passed to the memoized method, not taken from this.props etc @memoize - _getHeaderClickedObjectCached( - data: DatasetData, - columnIndex: number, - isPivoted: boolean, - ) { + _getHeaderClickedObjectCached(data, columnIndex, isPivoted) { return getTableHeaderClickedObject(data, columnIndex, isPivoted); } - visualizationIsClickable(clicked: ?ClickObject) { + visualizationIsClickable(clicked) { try { const { onVisualizationClick, visualizationIsClickable } = this.props; const { dragColIndex } = this.state; @@ -417,21 +353,13 @@ export default class TableInteractive extends Component { } // NOTE: all arguments must be passed to the memoized method, not taken from this.props etc @memoize - _visualizationIsClickableCached( - visualizationIsClickable: Function, - clicked: ClickObject, - ) { + _visualizationIsClickableCached(visualizationIsClickable, clicked) { return visualizationIsClickable(clicked); } // NOTE: all arguments must be passed to the memoized method, not taken from this.props etc @memoize - getCellBackgroundColor( - settings: VisualizationSettings, - value: Value, - rowIndex: number, - columnName: number, - ) { + getCellBackgroundColor(settings, value, rowIndex, columnName) { try { return settings["table._cell_background_getter"]( value, @@ -445,11 +373,7 @@ export default class TableInteractive extends Component { // NOTE: all arguments must be passed to the memoized method, not taken from this.props etc @memoize - getCellFormattedValue( - value: Value, - columnSettings: any, - clicked: ?ClickObject, - ) { + getCellFormattedValue(value, columnSettings, clicked) { try { return formatValue(value, { ...columnSettings, @@ -463,7 +387,7 @@ export default class TableInteractive extends Component { } } - cellRenderer = ({ key, style, rowIndex, columnIndex }: CellRendererProps) => { + cellRenderer = ({ key, style, rowIndex, columnIndex }) => { const { data, settings } = this.props; const { dragColIndex } = this.state; const { rows, cols } = data; @@ -540,7 +464,7 @@ export default class TableInteractive extends Component { ); }; - getDragColNewIndex(data: { x: number }) { + getDragColNewIndex(data) { const { columnPositions, dragColNewIndex, dragColStyle } = this.state; if (dragColStyle) { if (data.x < 0) { @@ -575,7 +499,7 @@ export default class TableInteractive extends Component { }); } - getNewColumnLefts(dragColNewIndex: number) { + getNewColumnLefts(dragColNewIndex) { const { dragColIndex, columnPositions } = this.state; const { cols } = this.props.data; const indexes = cols.map((col, index) => index); @@ -590,7 +514,7 @@ export default class TableInteractive extends Component { return lefts.map(p => p.left); } - getColumnLeft(style: any, index: number) { + getColumnLeft(style, index) { const { dragColNewIndex, dragColNewLefts } = this.state; if (dragColNewIndex != null && dragColNewLefts) { return dragColNewLefts[index]; @@ -598,7 +522,7 @@ export default class TableInteractive extends Component { return style.left; } - tableHeaderRenderer = ({ key, style, columnIndex }: CellRendererProps) => { + tableHeaderRenderer = ({ key, style, columnIndex }) => { const { data, sort, @@ -761,7 +685,7 @@ export default class TableInteractive extends Component { ); }; - getColumnWidth = ({ index }: { index: number }) => { + getColumnWidth = ({ index }) => { const { settings } = this.props; const { columnWidths } = this.state; const columnWidthsSetting = settings["table.column_widths"] || []; diff --git a/frontend/src/metabase/visualizations/components/TableSimple.jsx b/frontend/src/metabase/visualizations/components/TableSimple.jsx index 34c2126278e..fa7c4e96a72 100644 --- a/frontend/src/metabase/visualizations/components/TableSimple.jsx +++ b/frontend/src/metabase/visualizations/components/TableSimple.jsx @@ -27,33 +27,9 @@ import { getIn } from "icepick"; import { isID, isFK } from "metabase/lib/schema_metadata"; -import type { - ClickObject, - VisualizationProps, -} from "metabase-types/types/Visualization"; - -type Props = VisualizationProps & { - height: number, - className?: string, - isPivoted: boolean, - getColumnTitle: number => string, - getExtraDataForClick?: Function, - limit?: number, -}; - -type State = { - page: number, - pageSize: number, - sortColumn: ?number, - sortDescending: boolean, -}; - @ExplicitSize() export default class TableSimple extends Component { - props: Props; - state: State; - - constructor(props: Props) { + constructor(props) { super(props); this.state = { @@ -76,7 +52,7 @@ export default class TableSimple extends Component { className: "", }; - setSort(colIndex: number) { + setSort(colIndex) { if (this.state.sortColumn === colIndex) { this.setState({ sortDescending: !this.state.sortDescending }); } else { @@ -100,7 +76,7 @@ export default class TableSimple extends Component { } } - visualizationIsClickable(clicked: ?ClickObject) { + visualizationIsClickable(clicked) { const { onVisualizationClick, visualizationIsClickable } = this.props; return ( onVisualizationClick && diff --git a/frontend/src/metabase/visualizations/components/Visualization.jsx b/frontend/src/metabase/visualizations/components/Visualization.jsx index 6f2874d03d6..08a6752c901 100644 --- a/frontend/src/metabase/visualizations/components/Visualization.jsx +++ b/frontend/src/metabase/visualizations/components/Visualization.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React from "react"; import ExplicitSize from "metabase/components/ExplicitSize"; @@ -37,113 +38,13 @@ export const ERROR_MESSAGE_GENERIC = t`There was a problem displaying this chart export const ERROR_MESSAGE_PERMISSION = t`Sorry, you don't have permission to see this card.`; import Question from "metabase-lib/lib/Question"; -import Query from "metabase-lib/lib/queries/Query"; import Mode from "metabase-lib/lib/Mode"; -import type { - Card as CardObject, - VisualizationSettings, -} from "metabase-types/types/Card"; -import type { - HoverObject, - ClickObject, - Series, - RawSeries, - OnChangeCardAndRun, -} from "metabase-types/types/Visualization"; -import Metadata from "metabase-lib/lib/metadata/Metadata"; import { memoize } from "metabase-lib/lib/utils"; -type Props = { - rawSeries: RawSeries, - - className: string, - style: { [key: string]: any }, - - showTitle: boolean, - isDashboard: boolean, - isEditing: boolean, - isSettings: boolean, - isQueryBuilder: boolean, - isClickable: boolean, - - headerIcon?: { - name: string, - color?: string, - size?: Number, - tooltip?: string, - }, - - actionButtons: React.Element<any>, - - // errors - error: string, - errorIcon: string, - - // slow card warnings - isSlow: boolean, - expectedDuration: number, - - // injected by ExplicitSize - width: number, - height: number, - - // settings overrides from settings panel - settings: VisualizationSettings, - - // for click actions - metadata: Metadata, - dispatch: Function, - onChangeCardAndRun: OnChangeCardAndRun, - onChangeLocation: (url: string) => void, - - // for checking renderability - query: Query, - - mode?: Mode, - - // used for showing content in place of visualization, e.x. dashcard filter mapping - replacementContent: React.Element<any>, - - // misc - onUpdateWarnings: (string[]) => void, - onOpenChartSettings: ({ section?: ?string, widget?: ?any }) => void, - onUpdateVisualizationSettings: (settings: { [key: string]: any }) => void, - - // number of grid cells wide and tall - gridSize?: { width: number, height: number }, - // if gridSize isn't specified, compute using this gridSize (4x width, 3x height) - gridUnit?: number, - - classNameWidgets?: string, - - getExtraDataForClick?: Function, -}; - -type State = { - series: ?Series, - visualization: ?(React.Component<void, VisualizationSettings, void> & { - checkRenderable: (any, any, any) => void, - noHeader: boolean, - }), - computedSettings: VisualizationSettings, - - hovered: ?HoverObject, - clicked: ?ClickObject, - - error: ?Error, - warnings: string[], - yAxisSplit: ?(number[][]), -}; - // NOTE: pass `CardVisualization` so that we don't include header when providing size to child element @ExplicitSize({ selector: ".CardVisualization" }) export default class Visualization extends React.PureComponent { - state: State; - props: Props; - - _resetHoverTimer: ?number; - - constructor(props: Props) { + constructor(props) { super(props); this.state = { @@ -291,7 +192,7 @@ export default class Visualization extends React.PureComponent { return question.isDataset() ? question.composeDataset() : question; } - getClickActions(clicked: ?ClickObject) { + getClickActions(clicked) { if (!clicked) { return []; } @@ -312,7 +213,7 @@ export default class Visualization extends React.PureComponent { : []; } - visualizationIsClickable = (clicked: ClickObject) => { + visualizationIsClickable = clicked => { const { onChangeCardAndRun, isClickable } = this.props; if (!onChangeCardAndRun || !isClickable) { return false; @@ -325,7 +226,7 @@ export default class Visualization extends React.PureComponent { } }; - handleVisualizationClick = (clicked: ClickObject) => { + handleVisualizationClick = clicked => { if (clicked) { MetabaseAnalytics.trackStructEvent( "Actions", @@ -352,18 +253,11 @@ export default class Visualization extends React.PureComponent { }; // Add the underlying card of current series to onChangeCardAndRun if available - handleOnChangeCardAndRun = ({ - nextCard, - seriesIndex, - }: { - nextCard: CardObject, - seriesIndex: number, - }) => { + handleOnChangeCardAndRun = ({ nextCard, seriesIndex }) => { const { series, clicked } = this.state; const index = seriesIndex || (clicked && clicked.seriesIndex) || 0; - const previousCard: ?CardObject = - series && series[index] && series[index].card; + const previousCard = series && series[index] && series[index].card; this.props.onChangeCardAndRun({ nextCard, previousCard }); }; diff --git a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingColumns.jsx b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingColumns.jsx index 494cc71bd52..c0789abc69f 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingColumns.jsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingColumns.jsx @@ -6,12 +6,8 @@ import ColumnItem from "./ColumnItem"; const displayNameForColumn = column => column ? column.display_name || column.name : "[Unknown]"; -import type { NestedSettingComponentProps } from "./ChartSettingNestedSettings"; - // various props injected by chartSettingNestedSettings HOC export default class ChartNestedSettingColumns extends React.Component { - props: NestedSettingComponentProps; - render() { const { object, objects, onChangeEditingObject } = this.props; if (object) { diff --git a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeries.jsx b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeries.jsx index 92231c63f93..82bf2891599 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeries.jsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeries.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React from "react"; import ColorPicker from "metabase/components/ColorPicker"; @@ -5,12 +6,8 @@ import { SegmentedControl } from "metabase/components/SegmentedControl"; import Icon from "metabase/components/Icon"; import IconWrapper from "metabase/components/IconWrapper"; -import type { NestedSettingComponentProps } from "./ChartSettingNestedSettings"; - // various props injected by chartSettingNestedSettings HOC export default class ChartNestedSettingSeries extends React.Component { - props: NestedSettingComponentProps; - render() { const { objects, diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingNestedSettings.jsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingNestedSettings.jsx index b05a761213f..bb23a754f15 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartSettingNestedSettings.jsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingNestedSettings.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React from "react"; import ChartSettingsWidget from "../ChartSettingsWidget"; @@ -6,63 +7,12 @@ import _ from "underscore"; import { updateSettings } from "metabase/visualizations/lib/settings"; -import type { - Settings, - ExtraProps, - WidgetDef, -} from "metabase/visualizations/lib/settings"; -import type { - NestedObject, - NestedObjectKey, - SettingsWidgetsForObjectGetter, - NestedObjectKeyGetter, -} from "metabase/visualizations/lib/settings/nested"; -import type { Series } from "metabase-types/types/Visualization"; - -export type NestedSettingComponentProps = { - objects: NestedObject[], - object: ?NestedObject, - objectSettingsWidgets: ?(WidgetDef[]), - onChangeEditingObject: (editingObject: ?NestedObject) => void, - onChangeObjectSettings: (object: NestedObject, newSettings: Settings) => void, - getObjectKey: NestedObjectKeyGetter, - settings: Settings, - allComputedSettings: Settings, -}; -type NestedSettingComponent = React.ComponentClass; - -type SettingsByObjectKey = { [key: NestedObjectKey]: Settings }; - -type Props = { - value: SettingsByObjectKey, - onChange: (newSettings: SettingsByObjectKey) => void, - onEndShowWidget?: () => void, - series: Series, - extra: ExtraProps, - objects: NestedObject[], - initialKey?: NestedObjectKey, -}; - -type State = { - editingObjectKey: ?NestedObjectKey, -}; - -type ChartSettingsNestedSettingHOCProps = { - getObjectKey: NestedObjectKeyGetter, - getSettingsWidgetsForObject: SettingsWidgetsForObjectGetter, -}; - const chartSettingNestedSettings = ({ getObjectKey, getSettingsWidgetsForObject, -}: ChartSettingsNestedSettingHOCProps) => ( - ComposedComponent: NestedSettingComponent, -) => +}) => ComposedComponent => class extends React.Component { - props: Props; - state: State; - - constructor(props: Props) { + constructor(props) { super(props); this.state = {}; } @@ -77,7 +27,7 @@ const chartSettingNestedSettings = ({ ); }; - handleChangeEditingObject = (editingObject: ?NestedObject) => { + handleChangeEditingObject = editingObject => { // objectKeyOverride allows child components to set the editing object key to a different value than is derived // from the props. For example, this is used by the "More options" button in ChartNestedSettingSeries. this.setState({ @@ -89,27 +39,21 @@ const chartSettingNestedSettings = ({ } }; - handleChangeSettingsForEditingObject = (newSettings: Settings) => { + handleChangeSettingsForEditingObject = newSettings => { const editingObjectKey = this.getEditingObjectKey(); if (editingObjectKey) { this.handleChangeSettingsForObjectKey(editingObjectKey, newSettings); } }; - handleChangeSettingsForObject = ( - object: NestedObject, - newSettings: Settings, - ) => { + handleChangeSettingsForObject = (object, newSettings) => { const objectKey = getObjectKey(object); if (objectKey != null) { this.handleChangeSettingsForObjectKey(objectKey, newSettings); } }; - handleChangeSettingsForObjectKey = ( - objectKey: NestedObjectKey, - changedSettings: Settings, - ) => { + handleChangeSettingsForObjectKey = (objectKey, changedSettings) => { const { onChange } = this.props; const objectsSettings = this.props.value || {}; const objectSettings = objectsSettings[objectKey] || {}; diff --git a/frontend/src/metabase/visualizations/index.js b/frontend/src/metabase/visualizations/index.js index 5bd19baeba4..1ce98b8a90d 100644 --- a/frontend/src/metabase/visualizations/index.js +++ b/frontend/src/metabase/visualizations/index.js @@ -1,8 +1,6 @@ import { t } from "ttag"; import _ from "underscore"; -import type { Series } from "metabase-types/types/Visualization"; - const visualizations = new Map(); const aliases = new Map(); visualizations.get = function(key) { @@ -51,14 +49,14 @@ export function registerVisualization(visualization) { } } -export function getVisualizationRaw(series: Series) { +export function getVisualizationRaw(series) { return { series: series, visualization: visualizations.get(series[0].card.display), }; } -export function getVisualizationTransformed(series: Series) { +export function getVisualizationTransformed(series) { // don't transform if we don't have the data if (_.any(series, s => s.data == null)) { return getVisualizationRaw(series); diff --git a/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js b/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js index 49bcf2be5c2..893d5f7fdc5 100644 --- a/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js +++ b/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import crossfilter from "crossfilter"; import d3 from "d3"; import dc from "dc"; @@ -69,8 +70,6 @@ import { lineAddons } from "./graph/addons"; import { initBrush } from "./graph/brush"; import { stack, stackOffsetDiverging } from "./graph/stack"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; - const BAR_PADDING_RATIO = 0.2; const DEFAULT_INTERPOLATION = "linear"; @@ -805,18 +804,7 @@ function doHistogramBarStuff(parent) { /************************************************************ PUTTING IT ALL TOGETHER ************************************************************/ -type LineAreaBarProps = VisualizationProps & { - chartType: "line" | "area" | "bar" | "waterfall" | "scatter", - isScalarSeries: boolean, - maxSeries: number, -}; - -type DeregisterFunction = () => void; - -export default function lineAreaBar( - element: Element, - props: LineAreaBarProps, -): DeregisterFunction { +export default function lineAreaBar(element, props) { const { onRender, isScalarSeries, settings, series } = props; const warnings = {}; @@ -937,7 +925,7 @@ export default function lineAreaBar( if (onRender) { onRender({ yAxisSplit: yAxisProps.yAxisSplit, - warnings: (Object.values(warnings): string[]), + warnings: Object.values(warnings), }); } diff --git a/frontend/src/metabase/visualizations/lib/RowRenderer.js b/frontend/src/metabase/visualizations/lib/RowRenderer.js index e47fbeabbd5..c0005a4ccd1 100644 --- a/frontend/src/metabase/visualizations/lib/RowRenderer.js +++ b/frontend/src/metabase/visualizations/lib/RowRenderer.js @@ -19,12 +19,10 @@ import { checkXAxisLabelOverlap } from "./LineAreaBarPostRender"; const ROW_GAP = 5; const ROW_MAX_HEIGHT = 30; -type DeregisterFunction = () => void; - export default function rowRenderer( element, { settings, series, onHoverChange, onVisualizationClick, height }, -): DeregisterFunction { +) { const { cols } = series[0].data; const chart = dc.rowChart(element); diff --git a/frontend/src/metabase/visualizations/lib/action.js b/frontend/src/metabase/visualizations/lib/action.js index b80196deed2..f85cf5edf6c 100644 --- a/frontend/src/metabase/visualizations/lib/action.js +++ b/frontend/src/metabase/visualizations/lib/action.js @@ -1,18 +1,9 @@ +/* eslint-disable react/prop-types */ import { open } from "metabase/lib/dom"; import _ from "underscore"; -import type { ClickAction } from "metabase-types/types/Visualization"; - -type PerformActionProps = { - dispatch: Function, - onChangeCardAndRun: Function, -}; - -export function performAction( - action: ClickAction, - { dispatch, onChangeCardAndRun }: PerformActionProps, -) { +export function performAction(action, { dispatch, onChangeCardAndRun }) { let didPerform = false; if (action.action) { const reduxAction = action.action(); @@ -38,10 +29,7 @@ export function performAction( return didPerform; } -export function performDefaultAction( - actions: ClickAction[], - props: PerformActionProps, -) { +export function performDefaultAction(actions, props) { if (!actions) { return false; } diff --git a/frontend/src/metabase/visualizations/lib/apply_axis.js b/frontend/src/metabase/visualizations/lib/apply_axis.js index a8f27055f01..cba6b0d72f0 100644 --- a/frontend/src/metabase/visualizations/lib/apply_axis.js +++ b/frontend/src/metabase/visualizations/lib/apply_axis.js @@ -16,8 +16,6 @@ import { isMultipleOf } from "./numeric"; import { getFriendlyName } from "./utils"; import { isHistogram } from "./renderer_utils"; -import type { SingleSeries } from "metabase-types/types/Visualization"; - // label offset (doesn't increase padding) const X_LABEL_PADDING = 10; const Y_LABEL_PADDING = 22; @@ -91,10 +89,7 @@ export function applyChartTimeseriesXAxis( { xValues, xDomain, xInterval }, ) { // find the first nonempty single series - const firstSeries: SingleSeries = _.find( - series, - s => !datasetContainsNoResults(s.data), - ); + const firstSeries = _.find(series, s => !datasetContainsNoResults(s.data)); // setup an x-axis where the dimension is a timeseries let dimensionColumn = firstSeries.data.cols[0]; @@ -222,10 +217,7 @@ export function applyChartQuantitativeXAxis( { xValues, xDomain, xInterval }, ) { // find the first nonempty single series - const firstSeries: SingleSeries = _.find( - series, - s => !datasetContainsNoResults(s.data), - ); + const firstSeries = _.find(series, s => !datasetContainsNoResults(s.data)); const dimensionColumn = firstSeries.data.cols[0]; const waterfallTotalX = @@ -294,10 +286,7 @@ export function applyChartOrdinalXAxis( { xValues, isHistogramBar }, ) { // find the first nonempty single series - const firstSeries: SingleSeries = _.find( - series, - s => !datasetContainsNoResults(s.data), - ); + const firstSeries = _.find(series, s => !datasetContainsNoResults(s.data)); const dimensionColumn = firstSeries.data.cols[0]; diff --git a/frontend/src/metabase/visualizations/lib/errors.js b/frontend/src/metabase/visualizations/lib/errors.js index cb13dc5d5c1..6a74463e789 100644 --- a/frontend/src/metabase/visualizations/lib/errors.js +++ b/frontend/src/metabase/visualizations/lib/errors.js @@ -1,10 +1,8 @@ import { t, ngettext, msgid } from "ttag"; // NOTE: extending Error with Babel requires babel-plugin-transform-builtin-extend -type ChartSettingsInitial = { section?: ?string, widget?: ?any }; - export class MinColumnsError extends Error { - constructor(minColumns: number, actualColumns: number) { + constructor(minColumns, actualColumns) { super( t`Doh! The data from your query doesn't fit the chosen display choice. This visualization requires at least ${actualColumns} ${ngettext( msgid`column`, @@ -16,7 +14,7 @@ export class MinColumnsError extends Error { } export class MinRowsError extends Error { - constructor(minRows: number, actualRows: number) { + constructor(minRows, actualRows) { super( t`No dice. We have ${actualRows} data ${ngettext( msgid`point`, @@ -36,20 +34,16 @@ export class LatitudeLongitudeError extends Error { } export class NoBreakoutError extends Error { - constructor(message: string) { + constructor(message) { super(message || t`This visualization requires you to group by a field.`); } } export class ChartSettingsError extends Error { - initial: ?ChartSettingsInitial; - buttonText: ?string; + initial; + buttonText; - constructor( - message: string, - initial?: ChartSettingsInitial, - buttonText?: string, - ) { + constructor(message, initial, buttonText) { super(message || t`Please configure this chart in the chart settings`); this.initial = initial; this.buttonText = buttonText || t`Edit Settings`; diff --git a/frontend/src/metabase/visualizations/lib/renderer_utils.js b/frontend/src/metabase/visualizations/lib/renderer_utils.js index 3c570ff1afe..7e4d093ba5a 100644 --- a/frontend/src/metabase/visualizations/lib/renderer_utils.js +++ b/frontend/src/metabase/visualizations/lib/renderer_utils.js @@ -23,8 +23,6 @@ import { computeNumericDataInverval, dimensionIsNumeric } from "./numeric"; import { getAvailableCanvasWidth, getAvailableCanvasHeight } from "./utils"; import { invalidDateWarning, nullDimensionWarning } from "./warnings"; -import type { Value } from "metabase-types/types/Dataset"; - export function initChart(chart, element) { // set the bounds chart.width(getAvailableCanvasWidth(element)); @@ -37,7 +35,7 @@ export function initChart(chart, element) { } } -export function makeIndexMap(values: Array<Value>): Map<Value, number> { +export function makeIndexMap(values) { const indexMap = new Map(); for (const [index, key] of values.entries()) { indexMap.set(key, index); @@ -45,18 +43,10 @@ export function makeIndexMap(values: Array<Value>): Map<Value, number> { return indexMap; } -type CrossfilterGroup = { - top: (n: number) => { key: any, value: any }, - all: () => { key: any, value: any }, -}; - // HACK: This ensures each group is sorted by the same order as xValues, // otherwise we can end up with line charts with x-axis labels in the correct order // but the points in the wrong order. There may be a more efficient way to do this. -export function forceSortedGroup( - group: CrossfilterGroup, - indexMap: Map<Value, number>, -): void { +export function forceSortedGroup(group, indexMap) { const sorted = group .top(Infinity) .sort((a, b) => indexMap.get(a.key) - indexMap.get(b.key)); @@ -66,10 +56,7 @@ export function forceSortedGroup( group.all = () => sorted; } -export function forceSortedGroupsOfGroups( - groupsOfGroups: CrossfilterGroup[][], - indexMap: Map<Value, number>, -): void { +export function forceSortedGroupsOfGroups(groupsOfGroups, indexMap) { for (const groups of groupsOfGroups) { for (const group of groups) { forceSortedGroup(group, indexMap); diff --git a/frontend/src/metabase/visualizations/lib/settings.js b/frontend/src/metabase/visualizations/lib/settings.js index ab684079e56..405cfc00d63 100644 --- a/frontend/src/metabase/visualizations/lib/settings.js +++ b/frontend/src/metabase/visualizations/lib/settings.js @@ -1,7 +1,6 @@ +/* eslint-disable react/prop-types */ import { getIn } from "icepick"; -import * as React from "react"; - import ChartSettingInput from "metabase/visualizations/components/settings/ChartSettingInput"; import ChartSettingInputGroup from "metabase/visualizations/components/settings/ChartSettingInputGroup"; import ChartSettingInputNumeric from "metabase/visualizations/components/settings/ChartSettingInputNumeric"; @@ -17,52 +16,6 @@ import ChartSettingColorsPicker from "metabase/visualizations/components/setting import * as MetabaseAnalytics from "metabase/lib/analytics"; -export type SettingId = string; - -export type Settings = { - [settingId: SettingId]: any, -}; - -export type SettingDefs = { - [settingId: SettingId]: SettingDef, -}; - -export type SettingDef = { - title?: string, - props?: { [key: string]: any }, - default?: any, - hidden?: boolean, - disabled?: boolean, - getTitle?: (object: any, settings: Settings, extra: ExtraProps) => ?string, - getHidden?: (object: any, settings: Settings, extra: ExtraProps) => boolean, - getDisabled?: (object: any, settings: Settings, extra: ExtraProps) => boolean, - getProps?: ( - object: any, - settings: Settings, - onChange: Function, - extra: ExtraProps, - ) => { [key: string]: any }, - getDefault?: (object: any, settings: Settings, extra: ExtraProps) => any, - getValue?: (object: any, settings: Settings, extra: ExtraProps) => any, - isValid?: (object: any, settings: Settings, extra: ExtraProps) => boolean, - widget?: string | React.Component, - writeDependencies?: SettingId[], - readDependencies?: SettingId[], -}; - -export type WidgetDef = { - id: SettingId, - value: any, - title: ?string, - hidden: boolean, - disabled: boolean, - props: { [key: string]: any }, - widget?: React.Component, - onChange: (value: any) => void, -}; - -export type ExtraProps = { [key: string]: any }; - const WIDGETS = { input: ChartSettingInput, inputGroup: ChartSettingInputGroup, @@ -79,10 +32,10 @@ const WIDGETS = { }; export function getComputedSettings( - settingsDefs: SettingDefs, - object: any, - storedSettings: Settings, - extra?: ExtraProps = {}, + settingsDefs, + object, + storedSettings, + extra = {}, ) { const computedSettings = {}; for (const settingId in settingsDefs) { @@ -99,13 +52,13 @@ export function getComputedSettings( } function getComputedSetting( - computedSettings: Settings, // MUTATED! - settingDefs: SettingDefs, - settingId: SettingId, - object: any, - storedSettings: Settings, - extra?: ExtraProps = {}, -): any { + computedSettings, // MUTATED! + settingDefs, + settingId, + object, + storedSettings, + extra = {}, +) { if (settingId in computedSettings) { return; } @@ -160,14 +113,14 @@ function getComputedSetting( } function getSettingWidget( - settingDefs: SettingDefs, - settingId: SettingId, - storedSettings: Settings, - computedSettings: Settings, - object: any, - onChangeSettings: (settings: Settings) => void, - extra?: ExtraProps = {}, -): WidgetDef { + settingDefs, + settingId, + storedSettings, + computedSettings, + object, + onChangeSettings, + extra = {}, +) { const settingDef = settingDefs[settingId]; const value = computedSettings[settingId]; const onChange = value => { @@ -210,12 +163,12 @@ function getSettingWidget( } export function getSettingsWidgets( - settingDefs: SettingDefs, - storedSettings: Settings, - computedSettings: Settings, - object: any, - onChangeSettings: (settings: Settings) => void, - extra?: ExtraProps = {}, + settingDefs, + storedSettings, + computedSettings, + object, + onChangeSettings, + extra = {}, ) { return Object.keys(settingDefs) .map(settingId => @@ -232,10 +185,7 @@ export function getSettingsWidgets( .filter(widget => widget.widget); } -export function getPersistableDefaultSettings( - settingsDefs: SettingDefs, - completeSettings: Settings, -): Settings { +export function getPersistableDefaultSettings(settingsDefs, completeSettings) { const persistableDefaultSettings = {}; for (const settingId in settingsDefs) { const settingDef = settingsDefs[settingId]; @@ -246,10 +196,7 @@ export function getPersistableDefaultSettings( return persistableDefaultSettings; } -export function updateSettings( - storedSettings: Settings, - changedSettings: Settings, -): Settings { +export function updateSettings(storedSettings, changedSettings) { for (const key of Object.keys(changedSettings)) { MetabaseAnalytics.trackStructEvent("Chart Settings", "Change Setting", key); } @@ -268,7 +215,7 @@ export function updateSettings( // Merge two settings objects together. // Settings from the second argument take precedence over the first. -export function mergeSettings(first: Settings = {}, second: Settings = {}) { +export function mergeSettings(first = {}, second = {}) { // Note: This hardcoded list of all nested settings is potentially fragile, // but both the list of nested settings and the keys used are very stable. const nestedSettings = ["series_settings", "column_settings"]; diff --git a/frontend/src/metabase/visualizations/lib/settings/column.js b/frontend/src/metabase/visualizations/lib/settings/column.js index 35bbfb6dc74..596ce9702fa 100644 --- a/frontend/src/metabase/visualizations/lib/settings/column.js +++ b/frontend/src/metabase/visualizations/lib/settings/column.js @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import { t } from "ttag"; import moment from "moment"; import _ from "underscore"; @@ -32,31 +33,13 @@ import { import { currency } from "cljs/metabase.shared.util.currency"; -import type { Settings, SettingDef } from "../settings"; -import type { DateStyle, TimeStyle } from "metabase/lib/formatting/date"; -import type { DatetimeUnit } from "metabase-types/types/Query"; -import type { Column } from "metabase-types/types/Dataset"; -import type { Series } from "metabase-types/types/Visualization"; -import type { VisualizationSettings } from "metabase-types/types/Card"; - -type ColumnSettings = Settings; - -type ColumnGetter = ( - series: Series, - vizSettings: VisualizationSettings, -) => Column[]; - -const DEFAULT_GET_COLUMNS: ColumnGetter = (series, vizSettings) => +const DEFAULT_GET_COLUMNS = (series, vizSettings) => [].concat(...series.map(s => (s.data && s.data.cols) || [])); -type ColumnSettingDef = SettingDef & { - getColumns?: ColumnGetter, -}; - export function columnSettings({ getColumns = DEFAULT_GET_COLUMNS, ...def -}: ColumnSettingDef = {}) { +} = {}) { return nestedSettings("column_settings", { section: t`Formatting`, objectName: "column", @@ -72,7 +55,7 @@ export function columnSettings({ import MetabaseSettings from "metabase/lib/settings"; -export function getGlobalSettingsForColumn(column: Column) { +export function getGlobalSettingsForColumn(column) { const columnSettings = {}; const customFormatting = MetabaseSettings.get("custom-formatting") || {}; @@ -84,11 +67,11 @@ export function getGlobalSettingsForColumn(column: Column) { return columnSettings; } -function getLocalSettingsForColumn(column: Column): Settings { +function getLocalSettingsForColumn(column) { return column.settings || {}; } -function getInhertiedSettingsForColumn(column: Column): Settings { +function getInhertiedSettingsForColumn(column) { return { ...getGlobalSettingsForColumn(column), ...getLocalSettingsForColumn(column), @@ -97,11 +80,7 @@ function getInhertiedSettingsForColumn(column: Column): Settings { const EXAMPLE_DATE = moment("2018-01-07 17:24"); -function getDateStyleOptionsForUnit( - unit: ?DatetimeUnit, - abbreviate?: boolean = false, - separator?: string, -) { +function getDateStyleOptionsForUnit(unit, abbreviate = false, separator) { // hour-of-day shouldn't have any date style. It's handled as a time instead. // Other date parts are handled as dates, but hour-of-day needs to use the // time settings for 12/24 hour clock. @@ -148,11 +127,11 @@ function getDateStyleOptionsForUnit( } function dateStyleOption( - style: DateStyle, - unit: ?DatetimeUnit, - description?: ?string, - abbreviate?: boolean = false, - separator?: string, + style, + unit, + description, + abbreviate = false, + separator, ) { let format = getDateFormatFromStyle(style, unit, separator); if (abbreviate) { @@ -165,7 +144,7 @@ function dateStyleOption( }; } -function timeStyleOption(style: TimeStyle, description?: ?string) { +function timeStyleOption(style, description) { const format = style; return { name: @@ -178,31 +157,30 @@ export const DATE_COLUMN_SETTINGS = { date_style: { title: t`Date style`, widget: "select", - getDefault: ({ unit }: Column) => { + getDefault: ({ unit }) => { // Grab the first option's value. If there were no options (for // hour-of-day probably), use an empty format string instead. const [{ value = "" } = {}] = getDateStyleOptionsForUnit(unit); return value; }, - isValid: ({ unit }: Column, settings: ColumnSettings) => { + isValid: ({ unit }, settings) => { const options = getDateStyleOptionsForUnit(unit); return !!_.findWhere(options, { value: settings["date_style"] }); }, - getProps: ({ unit }: Column, settings: ColumnSettings) => ({ + getProps: ({ unit }, settings) => ({ options: getDateStyleOptionsForUnit( unit, settings["date_abbreviate"], settings["date_separator"], ), }), - getHidden: ({ unit }: Column) => - getDateStyleOptionsForUnit(unit).length < 2, + getHidden: ({ unit }) => getDateStyleOptionsForUnit(unit).length < 2, }, date_separator: { title: t`Date separators`, widget: "radio", default: "/", - getProps: (column: Column, settings: ColumnSettings) => { + getProps: (column, settings) => { const style = /\//.test(settings["date_style"]) ? settings["date_style"] : "M/D/YYYY"; @@ -214,14 +192,13 @@ export const DATE_COLUMN_SETTINGS = { ], }; }, - getHidden: ({ unit }: Column, settings: ColumnSettings) => - !/\//.test(settings["date_style"] || ""), + getHidden: ({ unit }, settings) => !/\//.test(settings["date_style"] || ""), }, date_abbreviate: { title: t`Abbreviate names of days and months`, widget: "toggle", default: false, - getHidden: ({ unit }: Column, settings: ColumnSettings) => { + getHidden: ({ unit }, settings) => { const format = getDateFormatFromStyle(settings["date_style"], unit); return !format.match(/MMMM|dddd/); }, @@ -230,9 +207,8 @@ export const DATE_COLUMN_SETTINGS = { time_enabled: { title: t`Show the time`, widget: "radio", - isValid: ({ unit }: Column, settings: ColumnSettings) => - !settings["time_enabled"] || hasHour(unit), - getProps: ({ unit }: Column, settings: ColumnSettings) => { + isValid: ({ unit }, settings) => !settings["time_enabled"] || hasHour(unit), + getProps: ({ unit }, settings) => { const options = [ { name: t`Off`, value: null }, { name: t`HH:MM`, value: "minutes" }, @@ -253,15 +229,15 @@ export const DATE_COLUMN_SETTINGS = { } return { options }; }, - getHidden: (column: Column, settings: ColumnSettings) => + getHidden: (column, settings) => !hasHour(column.unit) || isDateWithoutTime(column), - getDefault: ({ unit }: Column) => (hasHour(unit) ? "minutes" : null), + getDefault: ({ unit }) => (hasHour(unit) ? "minutes" : null), }, time_style: { title: t`Time style`, widget: "radio", default: "h:mm A", - getProps: (column: Column, settings: ColumnSettings) => ({ + getProps: (column, settings) => ({ options: [ timeStyleOption("h:mm A", t`12-hour clock`), ...(column.unit === "hour-of-day" @@ -270,7 +246,7 @@ export const DATE_COLUMN_SETTINGS = { timeStyleOption("HH:mm", t`24-hour clock`), ], }), - getHidden: (column: Column, settings: ColumnSettings) => + getHidden: (column, settings) => !settings["time_enabled"] || isDateWithoutTime(column), readDependencies: ["time_enabled"], }, @@ -299,10 +275,10 @@ export const NUMBER_COLUMN_SETTINGS = { { name: "Currency", value: "currency" }, ], }, - getDefault: (column: Column, settings: ColumnSettings) => + getDefault: (column, settings) => isCurrency(column) && settings["currency"] ? "currency" : "decimal", // hide this for currency - getHidden: (column: Column, settings: ColumnSettings) => + getHidden: (column, settings) => isCurrency(column) && settings["number_style"] === "currency", readDependencies: ["currency"], }, @@ -311,23 +287,20 @@ export const NUMBER_COLUMN_SETTINGS = { widget: "select", props: { // FIXME: rest of these options - options: currency.map( - ([_, currency: { name: string, code: string }]) => ({ - name: currency.name, - value: currency.code, - }), - ), + options: currency.map(([_, currency]) => ({ + name: currency.name, + value: currency.code, + })), searchProp: "name", searchCaseSensitive: false, }, default: "USD", - getHidden: (column: Column, settings: ColumnSettings) => - settings["number_style"] !== "currency", + getHidden: (column, settings) => settings["number_style"] !== "currency", }, currency_style: { title: t`Currency label style`, widget: "radio", - getProps: (column: Column, settings: ColumnSettings) => { + getProps: (column, settings) => { const c = settings["currency"] || "USD"; const symbol = getCurrency(c, "symbol"); const code = getCurrency(c, "code"); @@ -353,14 +326,13 @@ export const NUMBER_COLUMN_SETTINGS = { ], }; }, - getDefault: (column: Column, settings: ColumnSettings) => { + getDefault: (column, settings) => { const c = settings["currency"] || "USD"; return getCurrency(c, "symbol") !== getCurrency(c, "code") ? "symbol" : "code"; }, - getHidden: (column: Column, settings: ColumnSettings) => - settings["number_style"] !== "currency", + getHidden: (column, settings) => settings["number_style"] !== "currency", readDependencies: ["number_style"], }, currency_in_header: { @@ -373,11 +345,7 @@ export const NUMBER_COLUMN_SETTINGS = { ], }, default: true, - getHidden: ( - column: Column, - settings: ColumnSettings, - { series }: { series: Series }, - ) => + getHidden: (column, settings, { series }) => settings["number_style"] !== "currency" || series[0].card.display !== "table", readDependencies: ["number_style"], @@ -418,8 +386,7 @@ export const NUMBER_COLUMN_SETTINGS = { }, // Optimization: build a single NumberFormat object that is used by formatting.js _numberFormatter: { - getValue: (column: Column, settings: ColumnSettings) => - numberFormatterForOptions(settings), + getValue: (column, settings) => numberFormatterForOptions(settings), // NOTE: make sure to include every setting that affects the number formatter here readDependencies: [ "number_style", @@ -429,7 +396,7 @@ export const NUMBER_COLUMN_SETTINGS = { ], }, _header_unit: { - getValue: (column: Column, settings: ColumnSettings) => { + getValue: (column, settings) => { if ( settings["number_style"] === "currency" && settings["currency_in_header"] @@ -459,7 +426,7 @@ const COMMON_COLUMN_SETTINGS = { getValue: column => column, }, _column_title_full: { - getValue: (column: Column, settings: ColumnSettings) => { + getValue: (column, settings) => { let columnTitle = settings["column_title"] || formatColumn(column); const headerUnit = settings["_header_unit"]; if (headerUnit) { @@ -471,7 +438,7 @@ const COMMON_COLUMN_SETTINGS = { }, }; -export function getSettingDefintionsForColumn(series: Series, column: Column) { +export function getSettingDefintionsForColumn(series, column) { const { visualization } = getVisualizationRaw(series); const extraColumnSettings = typeof visualization.columnSettings === "function" diff --git a/frontend/src/metabase/visualizations/lib/settings/nested.js b/frontend/src/metabase/visualizations/lib/settings/nested.js index 4b60a0e4168..2807a4f94ec 100644 --- a/frontend/src/metabase/visualizations/lib/settings/nested.js +++ b/frontend/src/metabase/visualizations/lib/settings/nested.js @@ -1,53 +1,13 @@ +/* eslint-disable react/prop-types */ import _ from "underscore"; import { t } from "ttag"; -import * as React from "react"; - import { getComputedSettings, getSettingsWidgets } from "../settings"; import chartSettingNestedSettings from "metabase/visualizations/components/settings/ChartSettingNestedSettings"; -import type { - SettingId, - SettingDef, - SettingDefs, - Settings, - WidgetDef, - ExtraProps, -} from "metabase/visualizations/lib/settings"; - -import type { Series } from "metabase-types/types/Visualization"; - -export type NestedObject = any; -export type NestedObjectKey = string; - -type NestedSettingDef = SettingDef & { - objectName: string, - getObjects: (series: Series, settings: Settings) => NestedObject[], - getObjectKey: (object: NestedObject) => string, - getSettingDefintionsForObject: ( - series: Series, - object: NestedObject, - ) => SettingDefs, - getInheritedSettingsForObject?: ( - object: NestedObject, - ) => { [key: string]: any }, - component: React.ComponentClass, - id?: SettingId, -}; - -export type SettingsWidgetsForObjectGetter = ( - series: Series, - object: NestedObject, - storedSettings: Settings, - onChangeSettings: (newSettings: Settings) => void, - extra: ExtraProps, -) => WidgetDef[]; - -export type NestedObjectKeyGetter = (object: NestedObject) => NestedObjectKey; - export function nestedSettings( - id: SettingId, + id, { objectName = "object", getObjects, @@ -56,7 +16,7 @@ export function nestedSettings( getInheritedSettingsForObject = () => ({}), component, ...def - }: NestedSettingDef = {}, + } = {}, ) { function getComputedSettingsForObject(series, object, storedSettings, extra) { const settingsDefs = getSettingDefintionsForObject(series, object); @@ -125,7 +85,7 @@ export function nestedSettings( [id]: { section: t`Display`, default: {}, - getProps: (series: Series, settings: Settings) => { + getProps: (series, settings) => { const objects = getObjects(series, settings); const allComputedSettings = getComputedSettingsForAllObjects( series, @@ -145,9 +105,9 @@ export function nestedSettings( ...def, }, [objectName]: { - getDefault(series: Series, settings: Settings) { + getDefault(series, settings) { const cache = new Map(); - return (object: NestedObject) => { + return object => { const key = getObjectKey(object); if (!cache.has(key)) { const inheritedSettings = getInheritedSettingsForObject(object); diff --git a/frontend/src/metabase/visualizations/lib/settings/series.js b/frontend/src/metabase/visualizations/lib/settings/series.js index 6d34d83718b..9beffd783ab 100644 --- a/frontend/src/metabase/visualizations/lib/settings/series.js +++ b/frontend/src/metabase/visualizations/lib/settings/series.js @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import { t } from "ttag"; import _ from "underscore"; import { getIn } from "icepick"; @@ -6,25 +7,18 @@ import ChartNestedSettingSeries from "metabase/visualizations/components/setting import { nestedSettings } from "./nested"; import { getColorsForValues } from "metabase/lib/colors"; -import type { SettingDef } from "../settings"; -import type { SingleSeries } from "metabase-types/types/Visualization"; - -export function keyForSingleSeries(single: SingleSeries): string { +export function keyForSingleSeries(single) { // _seriesKey is sometimes set by transformSeries return single.card._seriesKey || String(single.card.name); } const LINE_DISPLAY_TYPES = new Set(["line", "area"]); -type SeriesSettingDef = SettingDef & { - noPadding?: boolean, -}; - export function seriesSetting({ readDependencies = [], noPadding, ...def -}: SeriesSettingDef = {}) { +} = {}) { const settingId = "series_settings"; const colorSettingId = `${settingId}.colors`; diff --git a/frontend/src/metabase/visualizations/lib/settings/visualization.js b/frontend/src/metabase/visualizations/lib/settings/visualization.js index f1e030dba2f..f0e2a23c521 100644 --- a/frontend/src/metabase/visualizations/lib/settings/visualization.js +++ b/frontend/src/metabase/visualizations/lib/settings/visualization.js @@ -8,10 +8,6 @@ import { getVisualizationRaw } from "metabase/visualizations"; import { normalizeFieldRef } from "metabase/lib/dataset"; import { t } from "ttag"; -import type { Settings, SettingDefs, WidgetDef } from "../settings"; -import type { Series } from "metabase-types/types/Visualization"; -import type { VisualizationSettings } from "metabase-types/types/Card"; - const COMMON_SETTINGS = { "card.title": { title: t`Title`, @@ -31,7 +27,7 @@ const COMMON_SETTINGS = { click_behavior: {}, }; -function getSettingDefintionsForSeries(series: ?Series): SettingDefs { +function getSettingDefintionsForSeries(series) { if (!series) { return {}; } @@ -60,8 +56,8 @@ function normalizeColumnSettings(columnSettings) { return newColumnSettings; } -export function getStoredSettingsForSeries(series: ?Series): Settings { - const storedSettings: VisualizationSettings = +export function getStoredSettingsForSeries(series) { + const storedSettings = (series && series[0] && series[0].card.visualization_settings) || {}; if (storedSettings.column_settings) { // normalize any settings stored under old style keys: [ref, [fk->, 1, 2]] @@ -72,7 +68,7 @@ export function getStoredSettingsForSeries(series: ?Series): Settings { return storedSettings; } -export function getComputedSettingsForSeries(series: ?Series): Settings { +export function getComputedSettingsForSeries(series) { if (!series) { return {}; } @@ -81,9 +77,7 @@ export function getComputedSettingsForSeries(series: ?Series): Settings { return getComputedSettings(settingsDefs, series, storedSettings); } -export function getPersistableDefaultSettingsForSeries( - series: ?Series, -): Settings { +export function getPersistableDefaultSettingsForSeries(series) { // A complete set of settings (not only defaults) is loaded because // some persistable default settings need other settings as dependency for calculating the default value const settingsDefs = getSettingDefintionsForSeries(series); @@ -92,10 +86,10 @@ export function getPersistableDefaultSettingsForSeries( } export function getSettingsWidgetsForSeries( - series: ?Series, - onChangeSettings: (settings: Settings) => void, - isDashboard: boolean = false, -): WidgetDef[] { + series, + onChangeSettings, + isDashboard = false, +) { const settingsDefs = getSettingDefintionsForSeries(series); const storedSettings = getStoredSettingsForSeries(series); const computedSettings = getComputedSettingsForSeries(series); diff --git a/frontend/src/metabase/visualizations/lib/table.js b/frontend/src/metabase/visualizations/lib/table.js index 67127623e6b..cef66244869 100644 --- a/frontend/src/metabase/visualizations/lib/table.js +++ b/frontend/src/metabase/visualizations/lib/table.js @@ -1,5 +1,3 @@ -import type { DatasetData, Column } from "metabase-types/types/Dataset"; -import type { ClickObject } from "metabase-types/types/Visualization"; import { isNumber, isCoordinate } from "metabase/lib/schema_metadata"; export function getTableClickedObjectRowData( @@ -76,11 +74,7 @@ export function getTableCellClickedObject( } } -export function getTableHeaderClickedObject( - data: DatasetData, - columnIndex: number, - isPivoted: boolean, -): ?ClickObject { +export function getTableHeaderClickedObject(data, columnIndex, isPivoted) { const column = data.cols[columnIndex]; if (isPivoted) { // if it's a pivot table, the first column is @@ -98,7 +92,7 @@ export function getTableHeaderClickedObject( * Returns whether the column should be right-aligned in a table. * Includes numbers and lat/lon coordinates, but not zip codes, IDs, etc. */ -export function isColumnRightAligned(column: Column) { +export function isColumnRightAligned(column) { // handle remapped columns if (column && column.remapped_to_column) { column = column.remapped_to_column; diff --git a/frontend/src/metabase/visualizations/lib/table_format.js b/frontend/src/metabase/visualizations/lib/table_format.js index 2b743f0285d..104a346e9af 100644 --- a/frontend/src/metabase/visualizations/lib/table_format.js +++ b/frontend/src/metabase/visualizations/lib/table_format.js @@ -7,77 +7,9 @@ const CELL_ALPHA = 0.65; const ROW_ALPHA = 0.2; const GRADIENT_ALPHA = 0.75; -import type { Column } from "metabase-types/types/Dataset"; // for simplicity wheb typing assume all values are numbers, since you can only pick numeric columns -type Value = number; -type Row = Value[]; -type ColumnName = string; -type Color = string; - -type Operator = - | "<" - | ">" - | "<=" - | ">=" - | "=" - | "!=" - | "is-null" - | "not-null" - | "contains" - | "does-not-contain" - | "starts-with" - | "ends-with"; - -type SingleFormat = { - type: "single", - columns: ColumnName[], - color: Color, - operator: Operator, - value: number | string, - highlight_row: boolean, -}; - -type RangeFormat = { - type: "range", - columns: ColumnName[], - colors: Color[], - min_type: null | "all" | "custom", - min_value: number, - max_type: null | "all" | "custom", - max_value: number, -}; - -type Format = SingleFormat | RangeFormat; - -type Settings = { - "table.column_formatting": Format[], - "table.pivot"?: boolean, -}; - -type Formatter = (value: number) => ?Color; -type RowFormatter = (row: number[], colIndexes: ColumnIndexes) => ?Color; - -type FormatterFactory = (value: number | string, color: Color) => Formatter; - -type BackgroundGetter = ( - value: number, - rowIndex: number, - colName: ColumnName, -) => ?Color; - -type ColumnIndexes = { - [key: ColumnName]: number, -}; -type ColumnExtents = { - [key: ColumnName]: [number, number], -}; - -export function makeCellBackgroundGetter( - rows: Row[], - cols: Column[], - settings: Settings, -): BackgroundGetter { +export function makeCellBackgroundGetter(rows, cols, settings) { const formats = settings["table.column_formatting"] || []; const pivot = settings["table.pivot"]; let formatters = {}; @@ -93,7 +25,7 @@ export function makeCellBackgroundGetter( if (Object.keys(formatters).length === 0 && rowFormatters.length === 0) { return () => null; } else { - return function(value: Value, rowIndex: number, colName: ColumnName) { + return function(value, rowIndex, colName) { if (formatters[colName]) { // const value = rows[rowIndex][colIndexes[colName]]; for (let i = 0; i < formatters[colName].length; i++) { @@ -127,9 +59,7 @@ function getColumnIndexesByName(cols) { return colIndexes; } -export const OPERATOR_FORMATTER_FACTORIES: { - [Operator]: FormatterFactory, -} = { +export const OPERATOR_FORMATTER_FACTORIES = { "<": (value, color) => v => typeof value === "number" && v < value ? color : null, "<=": (value, color) => v => @@ -161,11 +91,11 @@ export const OPERATOR_FORMATTER_FACTORIES: { }; export function compileFormatter( - format: Format, - columnName: ?ColumnName, - columnExtents: ?ColumnExtents, - isRowFormatter: boolean = false, -): ?Formatter { + format, + columnName, + columnExtents, + isRowFormatter = false, +) { if (format.type === "single") { let { operator, value, color } = format; color = alpha(color, isRowFormatter ? ROW_ALPHA : CELL_ALPHA); @@ -214,7 +144,7 @@ export function compileFormatter( // NOTE: implement `extent` like this rather than using d3.extent since rows may // be a Java `List` rather than a JavaScript Array when used in Pulse formatting -function extent(rows: Row[], colIndex: number) { +function extent(rows, colIndex) { let min = Infinity; let max = -Infinity; const length = rows.length; @@ -243,7 +173,7 @@ function computeColumnExtents(formats, rows, colIndexes) { return columnExtents; } -function compileFormatters(formats: Format[], columnExtents: ColumnExtents) { +function compileFormatters(formats, columnExtents) { const formatters = {}; formats.forEach(format => { format.columns.forEach(columnName => { @@ -256,7 +186,7 @@ function compileFormatters(formats: Format[], columnExtents: ColumnExtents) { return formatters; } -function compileRowFormatters(formats: Format[]): RowFormatter[] { +function compileRowFormatters(formats) { const rowFormatters = []; formats .filter(format => format.type === "single" && format.highlight_row) diff --git a/frontend/src/metabase/visualizations/lib/tooltip.js b/frontend/src/metabase/visualizations/lib/tooltip.js index 6396e4db6e4..43acb617a3e 100644 --- a/frontend/src/metabase/visualizations/lib/tooltip.js +++ b/frontend/src/metabase/visualizations/lib/tooltip.js @@ -19,7 +19,7 @@ function getParentWithClass(element, className) { } // HACK: This determines the index of the series the provided element belongs to since DC doesn't seem to provide another way -export function determineSeriesIndexFromElement(element, isStacked): number { +export function determineSeriesIndexFromElement(element, isStacked) { if (isStacked) { if (element.classList.contains("dot")) { // .dots are children of dc-tooltip diff --git a/frontend/src/metabase/visualizations/visualizations/Funnel.jsx b/frontend/src/metabase/visualizations/visualizations/Funnel.jsx index cf2bc915018..4f4cb42a476 100644 --- a/frontend/src/metabase/visualizations/visualizations/Funnel.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Funnel.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import PropTypes from "prop-types"; import { t } from "ttag"; @@ -24,7 +25,6 @@ import LegendHeader from "../components/LegendHeader"; import _ from "underscore"; import cx from "classnames"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; import ChartCaption from "metabase/visualizations/components/ChartCaption"; const propTypes = { @@ -32,8 +32,6 @@ const propTypes = { }; export default class Funnel extends Component { - props: VisualizationProps; - static uiName = t`Funnel`; static identifier = "funnel"; static iconName = "funnel"; diff --git a/frontend/src/metabase/visualizations/visualizations/Gauge.jsx b/frontend/src/metabase/visualizations/visualizations/Gauge.jsx index f1d4a6b8ba0..c67b7c59b92 100644 --- a/frontend/src/metabase/visualizations/visualizations/Gauge.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Gauge.jsx @@ -14,8 +14,6 @@ import { columnSettings } from "metabase/visualizations/lib/settings/column"; import ChartSettingGaugeSegments from "metabase/visualizations/components/settings/ChartSettingGaugeSegments"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; - const MAX_WIDTH = 500; const PADDING_BOTTOM = 10; @@ -54,8 +52,6 @@ const degrees = radians => (radians * 180) / Math.PI; const segmentIsValid = s => !isNaN(s.min) && !isNaN(s.max); export default class Gauge extends Component { - props: VisualizationProps; - static uiName = t`Gauge`; static identifier = "gauge"; static iconName = "gauge"; @@ -80,7 +76,7 @@ export default class Gauge extends Component { mounted: false, }; - _label: ?HTMLElement; + _label; static settings = { ...columnSettings({ diff --git a/frontend/src/metabase/visualizations/visualizations/Map.jsx b/frontend/src/metabase/visualizations/visualizations/Map.jsx index afa3bcbdbad..c92a2f14fe9 100644 --- a/frontend/src/metabase/visualizations/visualizations/Map.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Map.jsx @@ -322,7 +322,7 @@ export default class Map extends Component { } } - shouldComponentUpdate(nextProps: any, nextState: any) { + shouldComponentUpdate(nextProps, nextState) { const sameSize = this.props.width === nextProps.width && this.props.height === nextProps.height; diff --git a/frontend/src/metabase/visualizations/visualizations/ObjectDetail.jsx b/frontend/src/metabase/visualizations/visualizations/ObjectDetail.jsx index c51b1724a4e..048bdfe3271 100644 --- a/frontend/src/metabase/visualizations/visualizations/ObjectDetail.jsx +++ b/frontend/src/metabase/visualizations/visualizations/ObjectDetail.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import { connect } from "react-redux"; import { t, jt } from "ttag"; @@ -34,37 +35,6 @@ import { columnSettings } from "metabase/visualizations/lib/settings/column"; import cx from "classnames"; import _ from "underscore"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; -import type { FieldId, Field } from "metabase-types/types/Field"; -import type Table from "metabase-lib/lib/metadata/Table"; - -type ForeignKeyId = number; -type ForeignKey = { - id: ForeignKeyId, - relationship: string, - origin: Field, - origin_id: FieldId, - destination: Field, - destination_id: FieldId, -}; - -type ForeignKeyCountInfo = { - status: number, - value: number, -}; - -type Props = VisualizationProps & { - table: ?Table, - tableForeignKeys: ?(ForeignKey[]), - tableForeignKeyReferences: { [id: ForeignKeyId]: ForeignKeyCountInfo }, - fetchTableFks: () => void, - loadObjectDetailFKReferences: () => void, - fetchTableFks: (id: any) => void, - followForeignKey: (fk: any) => void, - viewNextObjectDetail: () => void, - viewPreviousObjectDetail: () => void, -}; - const mapStateToProps = state => ({ table: getTableMetadata(state), tableForeignKeys: getTableForeignKeys(state), @@ -83,8 +53,6 @@ const mapDispatchToProps = dispatch => ({ }); export class ObjectDetail extends Component { - props: Props; - static uiName = t`Object Detail`; static identifier = "object"; static iconName = "document"; diff --git a/frontend/src/metabase/visualizations/visualizations/PieChart.jsx b/frontend/src/metabase/visualizations/visualizations/PieChart.jsx index 59faf5b1f38..590178a91af 100644 --- a/frontend/src/metabase/visualizations/visualizations/PieChart.jsx +++ b/frontend/src/metabase/visualizations/visualizations/PieChart.jsx @@ -39,10 +39,8 @@ const OTHER_SLICE_MIN_PERCENTAGE = 0.003; const PERCENT_REGEX = /percent/i; -import type { VisualizationProps } from "metabase-types/types/Visualization"; - export default class PieChart extends Component { - constructor(props: VisualizationProps) { + constructor(props) { super(props); this.chartDetail = React.createRef(); @@ -242,7 +240,7 @@ export default class PieChart extends Component { majorWidth: 0, }); - const total: number = rows.reduce((sum, row) => sum + row[metricIndex], 0); + const total = rows.reduce((sum, row) => sum + row[metricIndex], 0); const showPercentInTooltip = !PERCENT_REGEX.test(cols[metricIndex].name) && diff --git a/frontend/src/metabase/visualizations/visualizations/PivotTable.jsx b/frontend/src/metabase/visualizations/visualizations/PivotTable.jsx index 334a5859567..5cce32e330a 100644 --- a/frontend/src/metabase/visualizations/visualizations/PivotTable.jsx +++ b/frontend/src/metabase/visualizations/visualizations/PivotTable.jsx @@ -24,7 +24,6 @@ import { import { formatColumn } from "metabase/lib/formatting"; import { columnSettings } from "metabase/visualizations/lib/settings/column"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; import { findDOMNode } from "react-dom"; const getBgLightColor = () => lighten(color("brand"), 0.65); @@ -62,7 +61,6 @@ const LEFT_HEADER_LEFT_SPACING = 24; const LEFT_HEADER_CELL_WIDTH = 145; export default class PivotTable extends Component { - props: VisualizationProps; static uiName = t`Pivot Table`; static identifier = "pivot"; static iconName = "pivot_table"; diff --git a/frontend/src/metabase/visualizations/visualizations/Progress.jsx b/frontend/src/metabase/visualizations/visualizations/Progress.jsx index 975fc2aad0f..93a4760a3ef 100644 --- a/frontend/src/metabase/visualizations/visualizations/Progress.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Progress.jsx @@ -18,10 +18,8 @@ import cx from "classnames"; const BORDER_RADIUS = 5; const MAX_BAR_HEIGHT = 65; -import type { VisualizationProps } from "metabase-types/types/Visualization"; - export default class Progress extends Component { - constructor(props: VisualizationProps) { + constructor(props) { super(props); this.containerRef = React.createRef(); @@ -140,8 +138,7 @@ export default class Progress extends Component { onVisualizationClick, visualizationIsClickable, } = this.props; - const value: number = - rows[0] && typeof rows[0][0] === "number" ? rows[0][0] : 0; + const value = rows[0] && typeof rows[0][0] === "number" ? rows[0][0] : 0; const column = cols[0]; const goal = settings["progress.goal"] || 0; diff --git a/frontend/src/metabase/visualizations/visualizations/Scalar.jsx b/frontend/src/metabase/visualizations/visualizations/Scalar.jsx index e31439cc456..048c96ac349 100644 --- a/frontend/src/metabase/visualizations/visualizations/Scalar.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Scalar.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import { t } from "ttag"; @@ -12,10 +13,6 @@ import { columnSettings } from "metabase/visualizations/lib/settings/column"; import cx from "classnames"; import _ from "underscore"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; -import type { Column } from "metabase-types/types/Dataset"; -import type { VisualizationSettings } from "metabase-types/types/Card"; - import ScalarValue, { ScalarWrapper, ScalarTitle, @@ -39,8 +36,6 @@ const COMPACT_MIN_LENGTH = 6; // Scalar visualization shows a single number // Multiseries Scalar is transformed to a Funnel export default class Scalar extends Component { - props: VisualizationProps; - static uiName = t`Number`; static identifier = "scalar"; static iconName = "number"; @@ -50,8 +45,6 @@ export default class Scalar extends Component { static minSize = { width: 3, height: 3 }; - _scalar: ?HTMLElement; - static isSensible({ cols, rows }) { return rows.length === 1 && cols.length === 1; } @@ -161,7 +154,7 @@ export default class Scalar extends Component { click_behavior: {}, }; - _getColumnIndex(cols: Column[], settings: VisualizationSettings) { + _getColumnIndex(cols, settings) { const columnIndex = _.findIndex( cols, col => col.name === settings["scalar.field"], diff --git a/frontend/src/metabase/visualizations/visualizations/SmartScalar.jsx b/frontend/src/metabase/visualizations/visualizations/SmartScalar.jsx index c344802e8c5..b122d66b093 100644 --- a/frontend/src/metabase/visualizations/visualizations/SmartScalar.jsx +++ b/frontend/src/metabase/visualizations/visualizations/SmartScalar.jsx @@ -29,8 +29,6 @@ export default class Smart extends React.Component { static noHeader = true; - _scalar: ?HTMLElement; - static settings = { ...columnSettings({ getColumns: ( diff --git a/frontend/src/metabase/visualizations/visualizations/Table.jsx b/frontend/src/metabase/visualizations/visualizations/Table.jsx index 14ae107a404..9846ced0227 100644 --- a/frontend/src/metabase/visualizations/visualizations/Table.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Table.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { Component } from "react"; import TableInteractive from "../components/TableInteractive.jsx"; @@ -33,24 +34,7 @@ import cx from "classnames"; import { getIn } from "icepick"; -import type { DatasetData } from "metabase-types/types/Dataset"; -import type { VisualizationSettings } from "metabase-types/types/Card"; -import type { Series } from "metabase-types/types/Visualization"; -import type { SettingDefs } from "metabase/visualizations/lib/settings"; - -type Props = { - series: Series, - settings: VisualizationSettings, - isDashboard: boolean, -}; -type State = { - data: ?DatasetData, -}; - export default class Table extends Component { - props: Props; - state: State; - static uiName = t`Table`; static identifier = "table"; static iconName = "table"; @@ -96,7 +80,7 @@ export default class Table extends Component { return pivotIndex >= 0 && cellIndex >= 0 && normalIndex >= 0; } - static settings: SettingDefs = { + static settings = { ...columnSettings({ hidden: true }), "table.pivot": { section: t`Columns`, @@ -247,7 +231,7 @@ export default class Table extends Component { }; static columnSettings = column => { - const settings: SettingDefs = { + const settings = { column_title: { title: t`Column title`, widget: "input", @@ -317,7 +301,7 @@ export default class Table extends Component { return settings; }; - constructor(props: Props) { + constructor(props) { super(props); this.state = { @@ -329,7 +313,7 @@ export default class Table extends Component { this._updateData(this.props); } - UNSAFE_componentWillReceiveProps(newProps: Props) { + UNSAFE_componentWillReceiveProps(newProps) { if ( newProps.series !== this.props.series || !_.isEqual(newProps.settings, this.props.settings) @@ -338,13 +322,7 @@ export default class Table extends Component { } } - _updateData({ - series, - settings, - }: { - series: Series, - settings: VisualizationSettings, - }) { + _updateData({ series, settings }) { const [{ data }] = series; if (Table.isPivoted(series, settings)) { @@ -390,7 +368,7 @@ export default class Table extends Component { // shared helpers for table implementations - getColumnTitle = (columnIndex: number): ?string => { + getColumnTitle = columnIndex => { const cols = this.state.data && this.state.data.cols; if (!cols) { return null; diff --git a/frontend/src/metabase/visualizations/visualizations/Text.jsx b/frontend/src/metabase/visualizations/visualizations/Text.jsx index 780a9f3c764..0c17d4a8af9 100644 --- a/frontend/src/metabase/visualizations/visualizations/Text.jsx +++ b/frontend/src/metabase/visualizations/visualizations/Text.jsx @@ -7,13 +7,6 @@ import styles from "./Text.css"; import cx from "classnames"; import { t } from "ttag"; -import type { VisualizationProps } from "metabase-types/types/Visualization"; - -type State = { - isShowingRenderedOutput: boolean, - text: string, -}; - const getSettingsStyle = settings => ({ "align-center": settings["text.align_horizontal"] === "center", "align-end": settings["text.align_horizontal"] === "right", @@ -24,10 +17,7 @@ const getSettingsStyle = settings => ({ const REMARK_PLUGINS = [remarkGfm]; export default class Text extends Component { - props: VisualizationProps; - state: State; - - constructor(props: VisualizationProps) { + constructor(props) { super(props); this.state = { @@ -97,7 +87,7 @@ export default class Text extends Component { }, }; - handleTextChange(text: string) { + handleTextChange(text) { this.props.onUpdateVisualizationSettings({ text: text }); } -- GitLab