From 80a2e45a1bfd33d6c1cf67e2e2ee0a1555d48a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atte=20Kein=C3=A4nen?= <atte.keinanen@gmail.com> Date: Tue, 13 Jun 2017 11:33:26 -0700 Subject: [PATCH] Fixing flow errors --- frontend/src/metabase-lib/lib/Question.js | 24 ++++++++++++------- .../src/metabase-lib/lib/metadata/Metric.js | 2 +- .../src/metabase-lib/lib/metadata/Table.js | 1 + .../metabase-lib/lib/queries/MultiQuery.js | 6 +++-- .../lib/queries/StructuredQuery.js | 4 ++-- .../DashCardCardParameterMapper.jsx | 4 +++- frontend/src/metabase/meta/types/Card.js | 1 - .../new_query/containers/NewQueryOptions.jsx | 1 + .../src/metabase/query_builder/actions.js | 10 ++------ 9 files changed, 30 insertions(+), 23 deletions(-) diff --git a/frontend/src/metabase-lib/lib/Question.js b/frontend/src/metabase-lib/lib/Question.js index df65715dd34..6940c470dad 100644 --- a/frontend/src/metabase-lib/lib/Question.js +++ b/frontend/src/metabase-lib/lib/Question.js @@ -48,10 +48,12 @@ import type { } from "metabase/meta/types/Visualization"; import { MetabaseApi, CardApi } from "metabase/services"; import { DatetimeFieldDimension } from "metabase-lib/lib/Dimension"; -import { TableId } from "metabase/meta/types/Table"; -import { DatabaseId } from "metabase/meta/types/Database"; import AtomicQuery from "metabase-lib/lib/queries/AtomicQuery"; -import { Dataset } from "metabase/meta/types/Dataset"; + +import type { Dataset } from "metabase/meta/types/Dataset"; +import type { TableId } from "metabase/meta/types/Table"; +import type { DatabaseId } from "metabase/meta/types/Database"; +import { STRUCTURED_QUERY_TEMPLATE } from "metabase-lib/lib/queries/StructuredQuery"; // TODO: move these type DownloadFormat = "csv" | "json" | "xlsx"; @@ -76,7 +78,7 @@ export default class Question { /** * Parameter values mean either the current values of dashboard filters or SQL editor template parameters. - * TODO Atte Keinänen 6/6/17: Why are parameter values considered a part of a Question? + * They are in the grey area between UI state and question state, but having them in Question wrapper is convenient. */ _parameterValues: ParameterValues; @@ -94,19 +96,25 @@ export default class Question { } /** - * TODO: Write a docstring, rename the latter newQuestion instance method + * TODO Atte Keinänen 6/13/17: Discussed with Tom that we could use the default Question constructor instead, + * but it would require changing the constructor signature so that `card` is an optional parameter and has a default value */ - static newQuestion({ + static create({ databaseId, tableId, metadata, parameterValues, ...cardProps }: { databaseId?: DatabaseId, tableId?: TableId, metadata: Metadata, parameterValues?: ParameterValues }) { + const card = { name: cardProps.name || null, display: cardProps.display || "table", visualization_settings: cardProps.visualization_settings || {}, - dataset_query: cardProps.dataset_query || StructuredQuery.newStucturedQuery({ question: this, databaseId, tableId }) + dataset_query: STRUCTURED_QUERY_TEMPLATE // temporary placeholder }; - return new Question(metadata, card, parameterValues); + // $FlowFixMe Passing an incomplete card object + const initialQuestion = new Question(metadata, card, parameterValues); + const query = StructuredQuery.newStucturedQuery({ question: initialQuestion, databaseId, tableId }) + + return initialQuestion.setQuery(query); } /** diff --git a/frontend/src/metabase-lib/lib/metadata/Metric.js b/frontend/src/metabase-lib/lib/metadata/Metric.js index ede67af4ab7..5320a57ec01 100644 --- a/frontend/src/metabase-lib/lib/metadata/Metric.js +++ b/frontend/src/metabase-lib/lib/metadata/Metric.js @@ -5,7 +5,7 @@ import Question from "../Question"; import Database from "./Database"; import Table from "./Table"; import Dimension, { DatetimeFieldDimension } from "metabase-lib/lib/Dimension"; -import { Aggregation } from "metabase/meta/types/Query"; +import type { Aggregation } from "metabase/meta/types/Query"; /** * Wrapper class for a metric. Belongs to a {@link Database} and possibly a {@link Table} diff --git a/frontend/src/metabase-lib/lib/metadata/Table.js b/frontend/src/metabase-lib/lib/metadata/Table.js index a80fe9cc6e7..ee9728e9afd 100644 --- a/frontend/src/metabase-lib/lib/metadata/Table.js +++ b/frontend/src/metabase-lib/lib/metadata/Table.js @@ -22,6 +22,7 @@ export default class Table extends Base { fields: Field[]; + // $FlowFixMe Could be replaced with hydrated database property in selectors/metadata.js (instead / in addition to `db`) get database() { return this.db; } diff --git a/frontend/src/metabase-lib/lib/queries/MultiQuery.js b/frontend/src/metabase-lib/lib/queries/MultiQuery.js index 4d4ee92842c..3993e0df9c0 100644 --- a/frontend/src/metabase-lib/lib/queries/MultiQuery.js +++ b/frontend/src/metabase-lib/lib/queries/MultiQuery.js @@ -16,6 +16,8 @@ import type { DatasetQuery, MultiDatasetQuery } from "metabase/meta/types/Card"; +import AtomicQuery from "metabase-lib/lib/queries/AtomicQuery"; +import Metric from "metabase-lib/lib/metadata/Metric"; export const MULTI_QUERY_TEMPLATE: MultiDatasetQuery = { type: "multi", @@ -206,7 +208,7 @@ export default class MultiQuery extends Query { const breakoutDimension = new DatetimeFieldDimension(compatibleFields[0].dimension(), [sharedDimension.bucketing()]) const metricQuery = StructuredQuery - .newStucturedQuery({ question: this, databaseId: metric.table.db.id, tableId: metric.table.id }) + .newStucturedQuery({ question: this._originalQuestion, databaseId: metric.table.db.id, tableId: metric.table.id }) .addAggregation(metric.aggregationClause()) .addBreakout(breakoutDimension.mbql()); @@ -245,7 +247,7 @@ export default class MultiQuery extends Query { /* Internal methods */ _updateQueries(queries: AtomicQuery[]) { - const datasetQuery: MultiDatasetQuery = this.datasetQuery(); + const datasetQuery: DatasetQuery = this.datasetQuery(); return new MultiQuery(this._originalQuestion, { ...datasetQuery, queries: queries.map((query) => query.datasetQuery()) diff --git a/frontend/src/metabase-lib/lib/queries/StructuredQuery.js b/frontend/src/metabase-lib/lib/queries/StructuredQuery.js index df20f9093b1..0808a110b12 100644 --- a/frontend/src/metabase-lib/lib/queries/StructuredQuery.js +++ b/frontend/src/metabase-lib/lib/queries/StructuredQuery.js @@ -46,11 +46,11 @@ import type Table from "../metadata/Table"; import type { DatabaseEngine, DatabaseId } from "metabase/meta/types/Database"; import type Database from "../metadata/Database"; import type Question from "../Question"; -import { TableId } from "metabase/meta/types/Table"; +import type { TableId } from "metabase/meta/types/Table"; import AtomicQuery from "./AtomicQuery"; import AggregationWrapper from './Aggregation'; -const STRUCTURED_QUERY_TEMPLATE = { +export const STRUCTURED_QUERY_TEMPLATE = { database: null, type: "query", query: { diff --git a/frontend/src/metabase/dashboard/containers/DashCardCardParameterMapper.jsx b/frontend/src/metabase/dashboard/containers/DashCardCardParameterMapper.jsx index c8b56fa32f7..b6d7354131b 100644 --- a/frontend/src/metabase/dashboard/containers/DashCardCardParameterMapper.jsx +++ b/frontend/src/metabase/dashboard/containers/DashCardCardParameterMapper.jsx @@ -26,6 +26,7 @@ import type { Parameter, ParameterId, ParameterMappingUIOption, ParameterTarget import type { DatabaseId } from "metabase/meta/types/Database"; import type { MappingsByParameter } from "../selectors"; +import AtomicQuery from "metabase-lib/lib/queries/AtomicQuery"; const makeMapStateToProps = () => { const getParameterMappingOptions = makeGetParameterMappingOptions() @@ -67,7 +68,8 @@ export default class DashCardCardParameterMapper extends Component { componentDidMount() { const { card } = this.props; - this.props.fetchDatabaseMetadata(card.dataset_query.database); + // Type check for Flow + card.dataset_query instanceof AtomicQuery && this.props.fetchDatabaseMetadata(card.dataset_query.database); } onChange = (option: ?ParameterMappingUIOption) => { diff --git a/frontend/src/metabase/meta/types/Card.js b/frontend/src/metabase/meta/types/Card.js index 110940ac787..b2d027da898 100644 --- a/frontend/src/metabase/meta/types/Card.js +++ b/frontend/src/metabase/meta/types/Card.js @@ -3,7 +3,6 @@ import type { DatabaseId } from "./Database"; import type { StructuredQuery, NativeQuery } from "./Query"; import type { Parameter, ParameterInstance } from "./Parameter"; -import { BreakoutClause, FilterClause } from "metabase/meta/types/Query"; export type CardId = number; diff --git a/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx b/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx index b48b64614c2..118c1d9669a 100644 --- a/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx +++ b/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx @@ -21,6 +21,7 @@ class OptionListItem extends Component { props: { item: any, action: (any) => void, + children?: React$Element<any> } onClick = () => { this.props.action(this.props.item); } diff --git a/frontend/src/metabase/query_builder/actions.js b/frontend/src/metabase/query_builder/actions.js index d6b3f987574..548c38c224a 100644 --- a/frontend/src/metabase/query_builder/actions.js +++ b/frontend/src/metabase/query_builder/actions.js @@ -291,24 +291,18 @@ export const initializeQB = (location, params) => { // NOTE: timeout to allow Parameters widget to set parameterValues setTimeout(() => // TODO Atte Keinänen 5/31/17: Check if it is dangerous to create a question object without metadata - dispatch(runQuestionQuery({ overrideWithCard: card, shouldUpdateUrl: false })) + dispatch(runQuestionQuery({ shouldUpdateUrl: false })) , 0); } - const originalQuestion = originalCard && new Question(getMetadata(getState()), originalCard); // clean up the url and make sure it reflects our card state + const originalQuestion = originalCard && new Question(getMetadata(getState()), originalCard); dispatch(updateUrl(card, { dirty: originalQuestion && question.isDirtyComparedTo(originalQuestion), replaceState: true, preserveParameters })); } - - // if we have loaded up a card that we can run then lets kick that off as well - if (question.canRun()) { - // NOTE: timeout to allow Parameters widget to set parameterValues - setTimeout(() => dispatch(runQuestionQuery({ shouldUpdateUrl: false })), 0); - } }; }; -- GitLab