diff --git a/frontend/src/metabase/containers/AdHocQuestionLoader.jsx b/frontend/src/metabase/containers/AdHocQuestionLoader.jsx index 29e8ae4759849972bfafc70917e058574adb43b9..0517c0df76956bd18801d977ca1f80e63a6a3e12 100644 --- a/frontend/src/metabase/containers/AdHocQuestionLoader.jsx +++ b/frontend/src/metabase/containers/AdHocQuestionLoader.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React from "react"; import { connect } from "react-redux"; @@ -9,30 +10,6 @@ import { getMetadata } from "metabase/selectors/metadata"; import Question from "metabase-lib/lib/Question"; // type annotations -import type Metadata from "metabase-lib/lib/metadata/Metadata"; -import type { Card } from "metabase-types/types/Card"; - -type ChildProps = { - loading: boolean, - error: ?any, - question: ?Question, -}; - -type Props = { - questionHash?: string, - children?: (props: ChildProps) => React.Element, - // provided by redux - loadMetadataForCard: (card: Card) => Promise<void>, - metadata: Metadata, -}; - -type State = { - // the question should be of type Question if it is set - question: ?Question, - card: ?Card, - loading: boolean, - error: ?any, -}; /* * AdHocQuestionLoader @@ -64,9 +41,7 @@ type State = { * without the redux store. */ export class AdHocQuestionLoader extends React.Component { - props: Props; - - state: State = { + state = { // this will store the loaded question question: null, // keep a reference to the card as well to help with re-creating question @@ -81,7 +56,7 @@ export class AdHocQuestionLoader extends React.Component { this._loadQuestion(this.props.questionHash); } - UNSAFE_componentWillReceiveProps(nextProps: Props) { + UNSAFE_componentWillReceiveProps(nextProps) { // if the questionHash changes (this will most likely be the result of a // url change) then we need to load this new question if (nextProps.questionHash !== this.props.questionHash) { @@ -106,7 +81,7 @@ export class AdHocQuestionLoader extends React.Component { * be used * 4. Set the component state to the new Question */ - async _loadQuestion(questionHash: ?string) { + async _loadQuestion(questionHash) { if (!questionHash) { this.setState({ loading: false, diff --git a/frontend/src/metabase/containers/AddToDashSelectDashModal.jsx b/frontend/src/metabase/containers/AddToDashSelectDashModal.jsx index 4c6cf8c0ec0c385af3fe2c627b9546e29a44659d..bfd96102af77850e0768ee2a502ebf28a92d3af7 100644 --- a/frontend/src/metabase/containers/AddToDashSelectDashModal.jsx +++ b/frontend/src/metabase/containers/AddToDashSelectDashModal.jsx @@ -12,9 +12,6 @@ import DashboardPicker from "metabase/containers/DashboardPicker"; import * as Urls from "metabase/lib/urls"; -import type { Dashboard as DashboardType } from "metabase-types/types/Dashboard"; -import type { Card } from "metabase-types/types/Card"; - function mapStateToProps(state) { return { dashboards: state.entities.dashboards, @@ -27,13 +24,6 @@ export default class AddToDashSelectDashModal extends Component { shouldCreateDashboard: false, }; - props: { - card: Card, - onClose: () => void, - onChangeLocation: string => void, - createDashboard: DashboardType => any, - }; - navigateToDashboard = dashboard => { const { card, onChangeLocation } = this.props; diff --git a/frontend/src/metabase/containers/CandidateListLoader.jsx b/frontend/src/metabase/containers/CandidateListLoader.jsx index 778de0405cabac4bd2800c8a075576f43afa3cd2..8bb188d8bda037e23cbc08b263e2f29f762548ad 100644 --- a/frontend/src/metabase/containers/CandidateListLoader.jsx +++ b/frontend/src/metabase/containers/CandidateListLoader.jsx @@ -1,45 +1,22 @@ +/* eslint-disable react/prop-types */ import React from "react"; import _ from "underscore"; import { MetabaseApi, AutoApi } from "metabase/services"; -import type { DatabaseCandidates } from "metabase-types/types/Auto"; - -type Props = { - databaseId: number, - children: (props: RenderProps) => ?React.Element, -}; - -type RenderProps = { - candidates: ?DatabaseCandidates, - sampleCandidates: ?DatabaseCandidates, - isSample: ?boolean, -}; - -type State = { - databaseId: ?number, - isSample: ?boolean, - candidates: ?DatabaseCandidates, - sampleCandidates: ?DatabaseCandidates, -}; - const CANDIDATES_POLL_INTERVAL = 2000; // ensure this is 1 second offset from CANDIDATES_POLL_INTERVAL due to // concurrency issue in candidates endpoint const CANDIDATES_TIMEOUT = 11000; class CandidateListLoader extends React.Component { - props: Props; - state: State = { + state = { databaseId: null, isSample: null, candidates: null, sampleCandidates: null, }; - _sampleTimeout: ?number; - _pollTimer: ?number; - async UNSAFE_componentWillMount() { // If we get passed in a database id, just use that. // Don't fall back to the sample dataset diff --git a/frontend/src/metabase/containers/CollectionItemsLoader.jsx b/frontend/src/metabase/containers/CollectionItemsLoader.jsx index 8f6a2010462895309136e3abc2422b252348d00a..e0b64dfb376d958dcfa1807170b5218dc60f3634 100644 --- a/frontend/src/metabase/containers/CollectionItemsLoader.jsx +++ b/frontend/src/metabase/containers/CollectionItemsLoader.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React from "react"; import Collection from "metabase/entities/collections"; @@ -5,12 +6,7 @@ import Search from "metabase/entities/search"; const PINNED_DASHBOARDS_LOAD_LIMIT = 500; -type Props = { - collectionId: number, - children: () => void, -}; - -const CollectionItemsLoader = ({ collectionId, children, ...props }: Props) => ( +const CollectionItemsLoader = ({ collectionId, children, ...props }) => ( <Collection.Loader {...props} id={collectionId}> {({ object }) => ( <Search.ListLoader diff --git a/frontend/src/metabase/containers/Form.jsx b/frontend/src/metabase/containers/Form.jsx index 731c0e005327be4b8bedbba34abba44b62763804..e0061655283258baf7f96b6217f76a71a07a6e3d 100644 --- a/frontend/src/metabase/containers/Form.jsx +++ b/frontend/src/metabase/containers/Form.jsx @@ -20,78 +20,6 @@ export { CustomFormSection as FormSection, } from "metabase/components/form/CustomForm"; -type FormFieldName = string; -type FormFieldTitle = string; -type FormFieldDescription = string; -type FormFieldType = - | "input" - | "password" - | "select" - | "text" - | "color" - | "hidden" - | "collection" - | "snippetCollection"; - -type FormValue = any; -type FormError = string; -type FormValues = { [name: FormFieldName]: FormValue }; -type FormErrors = { [name: FormFieldName]: FormError }; - -export type FormFieldDefinition = { - name: FormFieldName, - type?: FormFieldType, - title?: FormFieldTitle, - description?: FormFieldDescription, - initial?: FormValue | (() => FormValue), - normalize?: (value: FormValue) => FormValue, - validate?: (value: FormValue, props: FormProps) => ?FormError | boolean, - readOnly?: boolean, -}; - -export type FormDefinition = { - fields: - | ((values: FormValues) => FormFieldDefinition[]) - | FormFieldDefinition[], - initial?: FormValues | (() => FormValues), - normalize?: (values: FormValues) => FormValues, - validate?: (values: FormValues, props: FormProps) => FormErrors, -}; - -type FormObject = { - fields: (values: FormValues) => FormFieldDefinition[], - fieldNames: (values: FormValues) => FormFieldName[], - initial: () => FormValues, - normalize: (values: FormValues) => FormValues, - validate: (values: FormValues, props: FormProps) => FormErrors, - disablePristineSubmit?: boolean, -}; - -type FormProps = { - values?: FormValues, -}; - -type Props = { - form: FormDefinition, - initialValues?: ?FormValues, - formName?: string, - onSubmit: (values: FormValues) => Promise<any>, - onSubmitSuccess: (action: any) => Promise<any>, - formComponent?: React.Component, - dispatch: Function, - values: FormValues, -}; - -type State = { - inlineFields: { [name: FormFieldName]: FormFieldDefinition }, -}; - -type SubmitState = { - submitting: boolean, - failed: boolean, - result: any, -}; - let FORM_ID = 0; // use makeMapStateToProps so each component gets it's own unique formId const makeMapStateToProps = () => { @@ -128,21 +56,13 @@ const ReduxFormComponent = reduxForm()( @connect(makeMapStateToProps) export default class Form extends React.Component { - props: Props; - state: State; - - _state: SubmitState = { + _state = { submitting: false, failed: false, result: undefined, }; - _getFormDefinition: () => FormDefinition; - _getFormObject: () => FormObject; - _getInitialValues: () => FormValues; - _getFieldNames: () => FormFieldName[]; - - constructor(props: Props) { + constructor(props) { super(props); this.state = { @@ -239,7 +159,7 @@ export default class Form extends React.Component { fieldNames: PropTypes.array, }; - componentDidUpdate(prevProps: Props, prevState: State) { + componentDidUpdate(prevProps, prevState) { // HACK: when new fields are added they aren't initialized with their intialValues, so we have to force it here: const newFields = _.difference( Object.keys(this.state.inlineFields), @@ -252,7 +172,7 @@ export default class Form extends React.Component { } } - _registerFormField = (field: FormFieldDefinition) => { + _registerFormField = field => { if (!_.isEqual(this.state.inlineFields[field.name], field)) { this.setState(prevState => assocIn(prevState, ["inlineFields", field.name], field), @@ -260,7 +180,7 @@ export default class Form extends React.Component { } }; - _unregisterFormField = (field: FormFieldDefinition) => { + _unregisterFormField = field => { if (this.state.inlineFields[field.name]) { // this.setState(prevState => // dissocIn(prevState, ["inlineFields", field.name]), @@ -275,7 +195,7 @@ export default class Form extends React.Component { }; } - _validate = (values: FormValues, props: any) => { + _validate = (values, props) => { // HACK: clears failed state for global error if (!this._state.submitting && this._state.failed) { this._state.failed = false; @@ -285,7 +205,7 @@ export default class Form extends React.Component { return formObject.validate(values, props); }; - _onSubmit = async (values: FormValues) => { + _onSubmit = async values => { const formObject = this._getFormObject(); // HACK: clears failed state for global error this._state.submitting = true; @@ -320,7 +240,7 @@ export default class Form extends React.Component { } }; - _handleSubmitSuccess = async (action: any) => { + _handleSubmitSuccess = async action => { if (this.props.onSubmitSuccess) { await this.props.onSubmitSuccess(action); } @@ -329,7 +249,7 @@ export default class Form extends React.Component { ); }; - _handleChangeField = (fieldName: FormFieldName, value: FormValue) => { + _handleChangeField = (fieldName, value) => { return this.props.dispatch(change(this.props.formName, fieldName, value)); }; @@ -370,12 +290,7 @@ export default class Form extends React.Component { // form.fields[0] is { name: "foo", initial: "bar" } // form.fields[0] is { name: "foo", initial: () => "bar" } // -function makeFormMethod( - form: FormObject, - methodName: string, - defaultValues: any = {}, - mergeFn, -) { +function makeFormMethod(form, methodName, defaultValues = {}, mergeFn) { const originalMethod = form[methodName]; form[methodName] = (object, ...args) => { // make a copy @@ -397,10 +312,10 @@ function makeFormMethod( }; } // if the first arg is a function, call it, otherwise return it. -function getValue(fnOrValue, ...args): any { +function getValue(fnOrValue, ...args) { return typeof fnOrValue === "function" ? fnOrValue(...args) : fnOrValue; } -function makeFormObject(formDef: FormDefinition): FormObject { +function makeFormObject(formDef) { const form = { ...formDef, fields: values => getValue(formDef.fields, values), diff --git a/frontend/src/metabase/containers/QuestionAndResultLoader.jsx b/frontend/src/metabase/containers/QuestionAndResultLoader.jsx index c6fc8a6d7afd0aa8e5ff143dfc61c5b666db74d1..7fe65d2085e70a0b7ad8bd1d84dc68b8a98aec3c 100644 --- a/frontend/src/metabase/containers/QuestionAndResultLoader.jsx +++ b/frontend/src/metabase/containers/QuestionAndResultLoader.jsx @@ -1,19 +1,9 @@ +/* eslint-disable react/prop-types */ import React from "react"; import QuestionLoader from "metabase/containers/QuestionLoader"; import QuestionResultLoader from "metabase/containers/QuestionResultLoader"; -import type { ChildProps as QuestionLoaderChildProps } from "./QuestionLoader"; -import type { ChildProps as QuestionResultLoaderChildProps } from "./QuestionResultLoader"; - -type ChildProps = QuestionLoaderChildProps & QuestionResultLoaderChildProps; - -type Props = { - questionId?: ?number, - questionHash?: ?string, - children?: (props: ChildProps) => React.Element, -}; - /* * QuestionAndResultLoader * @@ -32,11 +22,7 @@ type Props = { * </QuestionAndResultLoader> * */ -const QuestionAndResultLoader = ({ - questionId, - questionHash, - children, -}: Props) => ( +const QuestionAndResultLoader = ({ questionId, questionHash, children }) => ( <QuestionLoader questionId={questionId} questionHash={questionHash}> {({ loading: questionLoading, error: questionError, ...questionProps }) => ( <QuestionResultLoader question={questionProps.question}> diff --git a/frontend/src/metabase/containers/QuestionLoader.jsx b/frontend/src/metabase/containers/QuestionLoader.jsx index b1b045ffc50f42de3250ade7ba21a372a2c0ce76..7e15ee4d0091ccc2ef6dfbe1bbb197d22ccd4a4e 100644 --- a/frontend/src/metabase/containers/QuestionLoader.jsx +++ b/frontend/src/metabase/containers/QuestionLoader.jsx @@ -1,25 +1,12 @@ +/* eslint-disable react/prop-types */ import React from "react"; import renderPropToHOC from "metabase/hoc/RenderPropToHOC"; import AdHocQuestionLoader from "metabase/containers/AdHocQuestionLoader"; import SavedQuestionLoader from "metabase/containers/SavedQuestionLoader"; -import Question from "metabase-lib/lib/Question"; import { serializeCardForUrl } from "metabase/lib/card"; -export type ChildProps = { - loading: boolean, - error: ?any, - question: ?Question, -}; - -type Props = { - questionObject?: any, // FIXME: minimal card - questionId?: ?number, - questionHash?: ?string, - children?: (props: ChildProps) => React.Element, -}; - /* * QuestionLoader * @@ -62,7 +49,7 @@ const QuestionLoader = ({ questionId, questionHash, children, -}: Props) => +}) => questionObject != null ? ( <AdHocQuestionLoader questionHash={serializeCardForUrl(questionObject)}> {children} diff --git a/frontend/src/metabase/containers/QuestionResultLoader.jsx b/frontend/src/metabase/containers/QuestionResultLoader.jsx index 943a0ea7894850b2a25aaf65d25d0523c9ff7073..459ef8d87d34553029c37c12e460fd251cf3a8c3 100644 --- a/frontend/src/metabase/containers/QuestionResultLoader.jsx +++ b/frontend/src/metabase/containers/QuestionResultLoader.jsx @@ -1,36 +1,8 @@ +/* eslint-disable react/prop-types */ import React from "react"; import PropTypes from "prop-types"; import { defer } from "metabase/lib/promise"; -import type { Dataset } from "metabase-types/types/Dataset"; -import type { RawSeries } from "metabase-types/types/Visualization"; - -import Question from "metabase-lib/lib/Question"; - -export type ChildProps = { - loading: boolean, - error: ?any, - results: ?(Dataset[]), - result: ?Dataset, - rawSeries: ?RawSeries, - cancel: () => void, - reload: () => void, -}; - -type OnLoadCallback = (results: ?(Dataset[])) => void; - -type Props = { - question: ?Question, - children?: (props: ChildProps) => React.Element, - onLoad?: OnLoadCallback, -}; - -type State = { - results: ?(Dataset[]), - loading: boolean, - error: ?any, -}; - const propTypes = { question: PropTypes.object, children: PropTypes.func, @@ -57,15 +29,12 @@ const propTypes = { * */ export class QuestionResultLoader extends React.Component { - props: Props; - state: State = { + state = { results: null, loading: false, error: null, }; - _cancelDeferred: ?() => void; - UNSAFE_componentWillMount = () => { this._reload(); }; @@ -96,7 +65,7 @@ export class QuestionResultLoader extends React.Component { })); // call apiGetResults and pass our cancel to allow for cancelation - const results: Dataset[] = await question.apiGetResults({ + const results = await question.apiGetResults({ cancelDeferred: this._cancelDeferred, }); diff --git a/frontend/src/metabase/containers/SavedQuestionLoader.jsx b/frontend/src/metabase/containers/SavedQuestionLoader.jsx index c9a1b415b879747e28de0a0abd5ff94280f2112a..4ec739c4d12739f34814023a36d368de1046a859 100644 --- a/frontend/src/metabase/containers/SavedQuestionLoader.jsx +++ b/frontend/src/metabase/containers/SavedQuestionLoader.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React from "react"; import { connect } from "react-redux"; @@ -9,32 +10,6 @@ import { getMetadata } from "metabase/selectors/metadata"; import Question from "metabase-lib/lib/Question"; // type annotations -import type Metadata from "metabase-lib/lib/metadata/Metadata"; -import type { Card } from "metabase-types/types/Card"; - -type ChildProps = { - loading: boolean, - error: ?any, - question: ?Question, -}; - -type Props = { - questionId: ?number, - children?: (props: ChildProps) => React.Element, - // provided by redux - loadMetadataForCard: (card: Card) => Promise<void>, - metadata: Metadata, -}; - -type State = { - // the question should be of type Question if it is set - question: ?Question, - // keep a reference to the card as well to help with re-creating question - // objects if the underlying metadata changes - card: ?Card, - loading: boolean, - error: ?any, -}; /* * SavedQuestionLaoder @@ -65,9 +40,7 @@ type State = { * without the redux store. */ export class SavedQuestionLoader extends React.Component { - props: Props; - - state: State = { + state = { // this will store the loaded question question: null, card: null, @@ -80,7 +53,7 @@ export class SavedQuestionLoader extends React.Component { this._loadQuestion(this.props.questionId); } - UNSAFE_componentWillReceiveProps(nextProps: Props) { + UNSAFE_componentWillReceiveProps(nextProps) { // if the questionId changes (this will most likely be the result of a // url change) then we need to load this new question if (nextProps.questionId !== this.props.questionId) { @@ -105,7 +78,7 @@ export class SavedQuestionLoader extends React.Component { * be used * 4. Set the component state to the new Question */ - async _loadQuestion(questionId: ?number) { + async _loadQuestion(questionId) { if (questionId == null) { this.setState({ loading: false,