Skip to content
Snippets Groups Projects
Unverified Commit 2b11cfdf authored by Dalton's avatar Dalton Committed by GitHub
Browse files

Remove Question's `update` method & related code (#25531)

* Remove _update from Question

* Update TimeseriesGroupingWidget

* Update ExtendedOptions

* Update SummarizeSidebar

* Update AddAggregationButton and AggreationItem

* Remove update method from MBQLClause

* Update ChartTypeSidebar

* Update GuiQueryEditor

* Update NativeQueryEditor

* Update BulkFilterModal

* Update Notebook

* Update NotebookSteps

* Update NotebookStep

* Update AggregateStep

* Update BreakoutStep

* Update DataStep

* Update ExpressionStep

* Update FilterStep

* Update JoinStep

* Update LimitStep

* Update SortStep

* Update NativeQueryButton

* Update QuestionDataSelector

* Update QuestionFilters

* Update QuestionRowCount

* Update View

* Update random doc

* Ensure we have a 'datasetQuery' in the setDatasetQuery function

* Ensure we have a 'datasetQuery' in the setDatasetQuery action
parent 2485a3cb
No related branches found
No related tags found
No related merge requests found
Showing
with 113 additions and 139 deletions
...@@ -3,11 +3,10 @@ ...@@ -3,11 +3,10 @@
- `setFoo(bar)`: returns clone of the wrapper but with the "foo" attribute to set to `bar` - `setFoo(bar)`: returns clone of the wrapper but with the "foo" attribute to set to `bar`
- `replace(object)`: returns clone of parent wrapper with this object replaced by `object` - `replace(object)`: returns clone of parent wrapper with this object replaced by `object`
- `remove()`: returns clone of the parent wrapper with this object removed - `remove()`: returns clone of the parent wrapper with this object removed
- `update()`: propagates current wrapper update to parent wrapper, recursively
Examples: Examples:
- `question().query().aggregation()[0].setDimension(dimension).update()` - `question().query().aggregation()[0].setDimension(dimension)`
Exceptions: Exceptions:
......
...@@ -82,8 +82,6 @@ import { ...@@ -82,8 +82,6 @@ import {
ALERT_TYPE_TIMESERIES_GOAL, ALERT_TYPE_TIMESERIES_GOAL,
} from "metabase-lib/lib/Alert"; } from "metabase-lib/lib/Alert";
type QuestionUpdateFn = (q: Question) => Promise<void> | null | undefined;
export type QuestionCreatorOpts = { export type QuestionCreatorOpts = {
databaseId?: DatabaseId; databaseId?: DatabaseId;
tableId?: TableId; tableId?: TableId;
...@@ -120,11 +118,6 @@ class QuestionInner { ...@@ -120,11 +118,6 @@ class QuestionInner {
*/ */
_parameterValues: ParameterValues; _parameterValues: ParameterValues;
/**
* Bound update function, if any
*/
_update: QuestionUpdateFn | null | undefined;
/** /**
* Question constructor * Question constructor
*/ */
...@@ -132,7 +125,6 @@ class QuestionInner { ...@@ -132,7 +125,6 @@ class QuestionInner {
card: CardObject, card: CardObject,
metadata?: Metadata, metadata?: Metadata,
parameterValues?: ParameterValues, parameterValues?: ParameterValues,
update?: QuestionUpdateFn | null | undefined,
) { ) {
this._card = card; this._card = card;
this._metadata = this._metadata =
...@@ -146,16 +138,10 @@ class QuestionInner { ...@@ -146,16 +138,10 @@ class QuestionInner {
questions: {}, questions: {},
}); });
this._parameterValues = parameterValues || {}; this._parameterValues = parameterValues || {};
this._update = update;
} }
clone() { clone() {
return new Question( return new Question(this._card, this._metadata, this._parameterValues);
this._card,
this._metadata,
this._parameterValues,
this._update,
);
} }
metadata(): Metadata { metadata(): Metadata {
...@@ -172,27 +158,6 @@ class QuestionInner { ...@@ -172,27 +158,6 @@ class QuestionInner {
return q; return q;
} }
/**
* calls the passed in update function (useful for chaining) or bound update function with the question
* NOTE: this passes Question instead of card, unlike how Query passes dataset_query
*/
update(update?: QuestionUpdateFn, ...args: any[]) {
// TODO: if update returns a new card, create a new Question based on that and return it
if (update) {
update(this, ...args);
} else if (this._update) {
this._update(this, ...args);
} else {
throw new Error("Question update function not provided or bound");
}
}
bindUpdate(update: QuestionUpdateFn) {
const q = this.clone();
q._update = update;
return q;
}
withoutNameAndId() { withoutNameAndId() {
return this.setCard( return this.setCard(
chain(this.card()) chain(this.card())
......
...@@ -9,11 +9,9 @@ import Variable from "metabase-lib/lib/variables/Variable"; ...@@ -9,11 +9,9 @@ import Variable from "metabase-lib/lib/variables/Variable";
import { memoizeClass } from "metabase-lib/lib/utils"; import { memoizeClass } from "metabase-lib/lib/utils";
import DimensionOptions from "metabase-lib/lib/DimensionOptions"; import DimensionOptions from "metabase-lib/lib/DimensionOptions";
type QueryUpdateFn = (datasetQuery: DatasetQuery) => void;
/** /**
* An abstract class for all query types (StructuredQuery & NativeQuery) * An abstract class for all query types (StructuredQuery & NativeQuery)
*/ */
class QueryInner { class QueryInner {
_metadata: Metadata; _metadata: Metadata;
...@@ -119,17 +117,6 @@ class QueryInner { ...@@ -119,17 +117,6 @@ class QueryInner {
setDefaultQuery(): QueryInner { setDefaultQuery(): QueryInner {
return this; return this;
} }
/**
* Helper for updating with functions that expect a DatasetQuery object, or proxy to parent question
*/
update(update?: QueryUpdateFn, ...args: any[]) {
if (update) {
return update(this.datasetQuery(), ...args);
} else {
return this.question().update(undefined, ...args);
}
}
} }
export default class Query extends memoizeClass<QueryInner>("question")( export default class Query extends memoizeClass<QueryInner>("question")(
......
...@@ -49,13 +49,6 @@ export default class MBQLArrayClause extends Array { ...@@ -49,13 +49,6 @@ export default class MBQLArrayClause extends Array {
return this._index; return this._index;
} }
/**
* replaces the previous clause with this one and propagates an update, recursively
*/
update(...args: any) {
return this.replace(this).update(undefined, ...args);
}
parent() { parent() {
return this.replace(this); return this.replace(this);
} }
...@@ -110,13 +103,6 @@ export class MBQLObjectClause { ...@@ -110,13 +103,6 @@ export class MBQLObjectClause {
return this._index; return this._index;
} }
/**
* replaces the previous clause with this one and propagates an update, recursively
*/
update(...args: any) {
return this.replace(this).update(undefined, ...args);
}
parent() { parent() {
return this.replace(this); return this.replace(this);
} }
......
...@@ -11,6 +11,7 @@ import Tables from "metabase/entities/tables"; ...@@ -11,6 +11,7 @@ import Tables from "metabase/entities/tables";
import GuiQueryEditor from "metabase/query_builder/components/GuiQueryEditor"; import GuiQueryEditor from "metabase/query_builder/components/GuiQueryEditor";
import * as Urls from "metabase/lib/urls"; import * as Urls from "metabase/lib/urls";
import Question from "metabase-lib/lib/Question"; import Question from "metabase-lib/lib/Question";
import Query from "metabase-lib/lib/queries/Query";
import withTableMetadataLoaded from "../hoc/withTableMetadataLoaded"; import withTableMetadataLoaded from "../hoc/withTableMetadataLoaded";
...@@ -75,6 +76,10 @@ class PartialQueryBuilder extends Component { ...@@ -75,6 +76,10 @@ class PartialQueryBuilder extends Component {
} }
setDatasetQuery = datasetQuery => { setDatasetQuery = datasetQuery => {
if (datasetQuery instanceof Query) {
datasetQuery = datasetQuery.datasetQuery();
}
this.props.onChange(datasetQuery.query); this.props.onChange(datasetQuery.query);
this.props.updatePreviewSummary(datasetQuery); this.props.updatePreviewSummary(datasetQuery);
}; };
......
...@@ -9,20 +9,16 @@ import TimeGroupingPopover from "metabase/query_builder/components/TimeGroupingP ...@@ -9,20 +9,16 @@ import TimeGroupingPopover from "metabase/query_builder/components/TimeGroupingP
import PopoverWithTrigger from "metabase/components/PopoverWithTrigger"; import PopoverWithTrigger from "metabase/components/PopoverWithTrigger";
import SelectButton from "metabase/core/components/SelectButton"; import SelectButton from "metabase/core/components/SelectButton";
// set the display automatically then run
function updateAndRun(query) {
query.question().setDefaultDisplay().update(null, { run: true });
}
export default class TimeseriesGroupingWidget extends Component { export default class TimeseriesGroupingWidget extends Component {
static propTypes = { static propTypes = {
query: PropTypes.object.isRequired, query: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired,
}; };
_popover; _popover;
render() { render() {
const { query } = this.props; const { query, onChange } = this.props;
if (isStructured(query.datasetQuery())) { if (isStructured(query.datasetQuery())) {
const breakouts = query.breakouts(); const breakouts = query.breakouts();
...@@ -49,9 +45,20 @@ export default class TimeseriesGroupingWidget extends Component { ...@@ -49,9 +45,20 @@ export default class TimeseriesGroupingWidget extends Component {
d.isSameBaseDimension(dimension), d.isSameBaseDimension(dimension),
); );
if (index >= 0) { if (index >= 0) {
updateAndRun(query.updateBreakout(index, dimension.mbql())); const newQuestion = query
.updateBreakout(index, dimension.mbql())
.question()
.setDefaultDisplay();
onChange(newQuestion);
} else { } else {
updateAndRun(query.clearBreakouts().breakout(dimension.mbql())); const newQuestion = query
.clearBreakouts()
.breakout(dimension.mbql())
.question()
.setDefaultDisplay();
onChange(newQuestion);
} }
if (this._popover) { if (this._popover) {
this._popover.close(); this._popover.close();
......
...@@ -13,12 +13,21 @@ import PivotByCategoryDrill from "../drill/PivotByCategoryDrill"; ...@@ -13,12 +13,21 @@ import PivotByCategoryDrill from "../drill/PivotByCategoryDrill";
import PivotByLocationDrill from "../drill/PivotByLocationDrill"; import PivotByLocationDrill from "../drill/PivotByLocationDrill";
const TimeseriesModeFooter = props => { const TimeseriesModeFooter = props => {
const onChange = question => {
const { updateQuestion } = props;
updateQuestion(question, { run: true });
};
return ( return (
<div className="flex layout-centered"> <div className="flex layout-centered">
<span className="mr1">{t`View`}</span> <span className="mr1">{t`View`}</span>
<TimeseriesFilterWidget {...props} card={props.lastRunCard} /> <TimeseriesFilterWidget {...props} card={props.lastRunCard} />
<span className="mx1">{t`by`}</span> <span className="mx1">{t`by`}</span>
<TimeseriesGroupingWidget {...props} card={props.lastRunCard} /> <TimeseriesGroupingWidget
{...props}
onChange={onChange}
card={props.lastRunCard}
/>
</div> </div>
); );
}; };
......
...@@ -18,6 +18,7 @@ import { openUrl } from "metabase/redux/app"; ...@@ -18,6 +18,7 @@ import { openUrl } from "metabase/redux/app";
import Questions from "metabase/entities/questions"; import Questions from "metabase/entities/questions";
import Databases from "metabase/entities/databases"; import Databases from "metabase/entities/databases";
import { fetchAlertsForQuestion } from "metabase/alert/alert"; import { fetchAlertsForQuestion } from "metabase/alert/alert";
import Query from "metabase-lib/lib/queries/Query";
import { trackNewQuestionSaved } from "../../analytics"; import { trackNewQuestionSaved } from "../../analytics";
import { import {
...@@ -160,6 +161,10 @@ export const navigateToNewCardInsideQB = createThunkAction( ...@@ -160,6 +161,10 @@ export const navigateToNewCardInsideQB = createThunkAction(
// DEPRECATED, still used in a couple places // DEPRECATED, still used in a couple places
export const setDatasetQuery = export const setDatasetQuery =
(datasetQuery, options) => (dispatch, getState) => { (datasetQuery, options) => (dispatch, getState) => {
if (datasetQuery instanceof Query) {
datasetQuery = datasetQuery.datasetQuery();
}
const question = getQuestion(getState()); const question = getQuestion(getState());
dispatch(updateQuestion(question.setDatasetQuery(datasetQuery), options)); dispatch(updateQuestion(question.setDatasetQuery(datasetQuery), options));
}; };
......
...@@ -34,9 +34,10 @@ export class ExtendedOptionsPopover extends Component { ...@@ -34,9 +34,10 @@ export class ExtendedOptionsPopover extends Component {
setExpression(name, expression, previousName) { setExpression(name, expression, previousName) {
const { query, setDatasetQuery } = this.props; const { query, setDatasetQuery } = this.props;
query
.updateExpression(name, expression, previousName) const newQuery = query.updateExpression(name, expression, previousName);
.update(setDatasetQuery); setDatasetQuery(newQuery);
this.setState({ editExpression: null }); this.setState({ editExpression: null });
MetabaseAnalytics.trackStructEvent( MetabaseAnalytics.trackStructEvent(
"QueryBuilder", "QueryBuilder",
...@@ -47,7 +48,10 @@ export class ExtendedOptionsPopover extends Component { ...@@ -47,7 +48,10 @@ export class ExtendedOptionsPopover extends Component {
removeExpression(name) { removeExpression(name) {
const { query, setDatasetQuery } = this.props; const { query, setDatasetQuery } = this.props;
query.removeExpression(name).update(setDatasetQuery);
const newQuery = query.removeExpression(name);
setDatasetQuery(newQuery);
this.setState({ editExpression: null }); this.setState({ editExpression: null });
MetabaseAnalytics.trackStructEvent("QueryBuilder", "Remove Expression"); MetabaseAnalytics.trackStructEvent("QueryBuilder", "Remove Expression");
...@@ -55,7 +59,10 @@ export class ExtendedOptionsPopover extends Component { ...@@ -55,7 +59,10 @@ export class ExtendedOptionsPopover extends Component {
setLimit = limit => { setLimit = limit => {
const { query, setDatasetQuery } = this.props; const { query, setDatasetQuery } = this.props;
query.updateLimit(limit).update(setDatasetQuery);
const newQuery = query.setLimit(limit);
setDatasetQuery(newQuery);
MetabaseAnalytics.trackStructEvent("QueryBuilder", "Set Limit", limit); MetabaseAnalytics.trackStructEvent("QueryBuilder", "Set Limit", limit);
if (this.props.onClose) { if (this.props.onClose) {
this.props.onClose(); this.props.onClose();
...@@ -78,9 +85,9 @@ export class ExtendedOptionsPopover extends Component { ...@@ -78,9 +85,9 @@ export class ExtendedOptionsPopover extends Component {
tableMetadata={query.table()} tableMetadata={query.table()}
sort={sort} sort={sort}
fieldOptions={query.sortOptions(sort)} fieldOptions={query.sortOptions(sort)}
removeOrderBy={() => query.removeSort(index).update(setDatasetQuery)} removeOrderBy={() => setDatasetQuery(query.removeSort(index))}
updateOrderBy={orderBy => updateOrderBy={orderBy =>
query.updateSort(index, orderBy).update(setDatasetQuery) setDatasetQuery(query.updateSort(index, orderBy))
} }
/> />
)); ));
...@@ -90,7 +97,7 @@ export class ExtendedOptionsPopover extends Component { ...@@ -90,7 +97,7 @@ export class ExtendedOptionsPopover extends Component {
<AddClauseButton <AddClauseButton
text={t`Pick a field to sort by`} text={t`Pick a field to sort by`}
onClick={() => { onClick={() => {
query.sort(["asc", null]).update(setDatasetQuery); setDatasetQuery(query.sort(["asc", null]));
}} }}
/> />
); );
......
...@@ -94,11 +94,9 @@ export default class GuiQueryEditor extends React.Component { ...@@ -94,11 +94,9 @@ export default class GuiQueryEditor extends React.Component {
<FilterWidgetList <FilterWidgetList
query={query} query={query}
filters={filters} filters={filters}
removeFilter={index => removeFilter={index => setDatasetQuery(query.removeFilter(index))}
query.removeFilter(index).update(setDatasetQuery)
}
updateFilter={(index, filter) => updateFilter={(index, filter) =>
query.updateFilter(index, filter).update(setDatasetQuery) setDatasetQuery(query.updateFilter(index, filter))
} }
/> />
); );
...@@ -135,9 +133,7 @@ export default class GuiQueryEditor extends React.Component { ...@@ -135,9 +133,7 @@ export default class GuiQueryEditor extends React.Component {
<FilterPopover <FilterPopover
isNew isNew
query={query} query={query}
onChangeFilter={filter => onChangeFilter={filter => setDatasetQuery(query.filter(filter))}
query.filter(filter).update(setDatasetQuery)
}
onClose={() => this.filterPopover.current.close()} onClose={() => this.filterPopover.current.close()}
/> />
</PopoverWithTrigger> </PopoverWithTrigger>
...@@ -178,10 +174,8 @@ export default class GuiQueryEditor extends React.Component { ...@@ -178,10 +174,8 @@ export default class GuiQueryEditor extends React.Component {
query={query} query={query}
onChangeAggregation={aggregation => onChangeAggregation={aggregation =>
aggregation aggregation
? query ? setDatasetQuery(query.updateAggregation(index, aggregation))
.updateAggregation(index, aggregation) : setDatasetQuery(query.removeAggregation(index))
.update(setDatasetQuery)
: query.removeAggregation(index).update(setDatasetQuery)
} }
showMetrics={false} showMetrics={false}
showRawData showRawData
...@@ -241,8 +235,8 @@ export default class GuiQueryEditor extends React.Component { ...@@ -241,8 +235,8 @@ export default class GuiQueryEditor extends React.Component {
breakoutOptions={query.breakoutOptions(breakout)} breakoutOptions={query.breakoutOptions(breakout)}
onChangeBreakout={breakout => onChangeBreakout={breakout =>
breakout breakout
? query.updateBreakout(index, breakout).update(setDatasetQuery) ? setDatasetQuery(query.updateBreakout(index, breakout))
: query.removeBreakout(index).update(setDatasetQuery) : setDatasetQuery(query.removeBreakout(index))
} }
> >
{this.renderAdd(index === 0 ? t`Add a grouping` : null)} {this.renderAdd(index === 0 ? t`Add a grouping` : null)}
......
...@@ -423,14 +423,15 @@ class NativeQueryEditor extends Component { ...@@ -423,14 +423,15 @@ class NativeQueryEditor extends Component {
}, AUTOCOMPLETE_DEBOUNCE_DURATION); }, AUTOCOMPLETE_DEBOUNCE_DURATION);
onChange() { onChange() {
const { query } = this.props; const { query, setDatasetQuery } = this.props;
if (this._editor && !this._localUpdate) { if (this._editor && !this._localUpdate) {
this._updateSize(); this._updateSize();
if (query.queryText() !== this._editor.getValue()) { if (query.queryText() !== this._editor.getValue()) {
query setDatasetQuery(
.setQueryText(this._editor.getValue()) query
.updateSnippetsWithIds(this.props.snippets) .setQueryText(this._editor.getValue())
.update(this.props.setDatasetQuery); .updateSnippetsWithIds(this.props.snippets),
);
} }
} }
...@@ -443,12 +444,9 @@ class NativeQueryEditor extends Component { ...@@ -443,12 +444,9 @@ class NativeQueryEditor extends Component {
/// Change the Database we're currently editing a query for. /// Change the Database we're currently editing a query for.
setDatabaseId = databaseId => { setDatabaseId = databaseId => {
const { query } = this.props; const { query, setDatasetQuery } = this.props;
if (query.databaseId() !== databaseId) { if (query.databaseId() !== databaseId) {
query setDatasetQuery(query.setDatabaseId(databaseId).setDefaultCollection());
.setDatabaseId(databaseId)
.setDefaultCollection()
.update(this.props.setDatasetQuery);
if (this._editor && !this.props.readOnly) { if (this._editor && !this.props.readOnly) {
// HACK: the cursor doesn't blink without this intended small delay // HACK: the cursor doesn't blink without this intended small delay
setTimeout(() => this._editor.focus(), 50); setTimeout(() => this._editor.focus(), 50);
...@@ -458,18 +456,16 @@ class NativeQueryEditor extends Component { ...@@ -458,18 +456,16 @@ class NativeQueryEditor extends Component {
setTableId = tableId => { setTableId = tableId => {
// TODO: push more of this into metabase-lib? // TODO: push more of this into metabase-lib?
const { query } = this.props; const { query, setDatasetQuery } = this.props;
const table = query.metadata().table(tableId); const table = query.metadata().table(tableId);
if (table?.name !== query.collection()) { if (table?.name !== query.collection()) {
query.setCollectionName(table.name).update(this.props.setDatasetQuery); setDatasetQuery(query.setCollectionName(table.name));
} }
}; };
setParameterIndex = (parameterId, parameterIndex) => { setParameterIndex = (parameterId, parameterIndex) => {
const { query, setDatasetQuery } = this.props; const { query, setDatasetQuery } = this.props;
query setDatasetQuery(query.setParameterIndex(parameterId, parameterIndex));
.setParameterIndex(parameterId, parameterIndex)
.update(setDatasetQuery);
}; };
handleFilterButtonClick = () => { handleFilterButtonClick = () => {
...@@ -492,6 +488,7 @@ class NativeQueryEditor extends Component { ...@@ -492,6 +488,7 @@ class NativeQueryEditor extends Component {
snippetCollections = [], snippetCollections = [],
resizable, resizable,
requireWriteback = false, requireWriteback = false,
setDatasetQuery,
} = this.props; } = this.props;
const parameters = query.question().parameters(); const parameters = query.question().parameters();
...@@ -568,9 +565,7 @@ class NativeQueryEditor extends Component { ...@@ -568,9 +565,7 @@ class NativeQueryEditor extends Component {
<SnippetModal <SnippetModal
onSnippetUpdate={(newSnippet, oldSnippet) => { onSnippetUpdate={(newSnippet, oldSnippet) => {
if (newSnippet.name !== oldSnippet.name) { if (newSnippet.name !== oldSnippet.name) {
query setDatasetQuery(query.updateSnippetNames([newSnippet]));
.updateSnippetNames([newSnippet])
.update(this.props.setDatasetQuery);
} }
}} }}
snippet={this.props.modalSnippet} snippet={this.props.modalSnippet}
......
...@@ -54,6 +54,11 @@ class QueryModals extends React.Component { ...@@ -54,6 +54,11 @@ class QueryModals extends React.Component {
} }
}; };
onQueryChange = query => {
const question = query.question();
this.props.updateQuestion(question, { run: true });
};
render() { render() {
const { const {
modal, modal,
...@@ -166,7 +171,11 @@ class QueryModals extends React.Component { ...@@ -166,7 +171,11 @@ class QueryModals extends React.Component {
</Modal> </Modal>
) : modal === MODAL_TYPES.FILTERS ? ( ) : modal === MODAL_TYPES.FILTERS ? (
<Modal fit onClose={onCloseModal}> <Modal fit onClose={onCloseModal}>
<BulkFilterModal question={question} onClose={onCloseModal} /> <BulkFilterModal
question={question}
onQueryChange={this.onQueryChange}
onClose={onCloseModal}
/>
</Modal> </Modal>
) : modal === MODAL_TYPES.HISTORY ? ( ) : modal === MODAL_TYPES.HISTORY ? (
<Modal onClose={onCloseModal}> <Modal onClose={onCloseModal}>
......
...@@ -36,12 +36,14 @@ import { fixBetweens, getSearchHits } from "./utils"; ...@@ -36,12 +36,14 @@ import { fixBetweens, getSearchHits } from "./utils";
export interface BulkFilterModalProps { export interface BulkFilterModalProps {
question: Question; question: Question;
onQueryChange: (query: StructuredQuery) => void;
onClose?: () => void; onClose?: () => void;
} }
const BulkFilterModal = ({ const BulkFilterModal = ({
question, question,
onClose, onClose,
onQueryChange,
}: BulkFilterModalProps): JSX.Element | null => { }: BulkFilterModalProps): JSX.Element | null => {
const [query, setQuery] = useState(getQuery(question)); const [query, setQuery] = useState(getQuery(question));
const [isChanged, setIsChanged] = useState(false); const [isChanged, setIsChanged] = useState(false);
...@@ -87,9 +89,9 @@ const BulkFilterModal = ({ ...@@ -87,9 +89,9 @@ const BulkFilterModal = ({
const handleApplyQuery = useCallback(() => { const handleApplyQuery = useCallback(() => {
const preCleanedQuery = fixBetweens(query); const preCleanedQuery = fixBetweens(query);
preCleanedQuery.clean().update(undefined, { run: true }); onQueryChange(preCleanedQuery.clean());
onClose?.(); onClose?.();
}, [query, onClose]); }, [query, onClose, onQueryChange]);
const clearFilters = () => { const clearFilters = () => {
setQuery(query.clearFilters()); setQuery(query.clearFilters());
......
...@@ -16,6 +16,7 @@ export default function Notebook({ className, ...props }) { ...@@ -16,6 +16,7 @@ export default function Notebook({ className, ...props }) {
isResultDirty, isResultDirty,
runQuestionQuery, runQuestionQuery,
setQueryBuilderMode, setQueryBuilderMode,
updateQuestion,
hasVisualizeButton = true, hasVisualizeButton = true,
} = props; } = props;
...@@ -26,7 +27,8 @@ export default function Notebook({ className, ...props }) { ...@@ -26,7 +27,8 @@ export default function Notebook({ className, ...props }) {
if (cleanQuestion.display() === "table") { if (cleanQuestion.display() === "table") {
cleanQuestion = cleanQuestion.setDefaultDisplay(); cleanQuestion = cleanQuestion.setDefaultDisplay();
} }
await cleanQuestion.update();
await updateQuestion(cleanQuestion);
} }
// vizualize switches the view to the question's visualization. // vizualize switches the view to the question's visualization.
......
...@@ -166,7 +166,7 @@ export default class NotebookStep extends React.Component { ...@@ -166,7 +166,7 @@ export default class NotebookStep extends React.Component {
name="close" name="close"
className="ml-auto cursor-pointer text-light text-medium-hover hover-child" className="ml-auto cursor-pointer text-light text-medium-hover hover-child"
tooltip={t`Remove`} tooltip={t`Remove`}
onClick={() => step.revert(step.query).update(updateQuery)} onClick={() => updateQuery(step.revert(step.query))}
data-testid="remove-step" data-testid="remove-step"
/> />
</StepHeader> </StepHeader>
......
...@@ -38,7 +38,7 @@ export default class NotebookSteps extends React.Component { ...@@ -38,7 +38,7 @@ export default class NotebookSteps extends React.Component {
}; };
render() { render() {
const { question, className } = this.props; const { question, className, updateQuestion } = this.props;
const { openSteps, lastOpenedStep } = this.state; const { openSteps, lastOpenedStep } = this.state;
if (!question) { if (!question) {
...@@ -51,8 +51,10 @@ export default class NotebookSteps extends React.Component { ...@@ -51,8 +51,10 @@ export default class NotebookSteps extends React.Component {
<div className={cx(className, "pt3")}> <div className={cx(className, "pt3")}>
{steps.map((step, index) => { {steps.map((step, index) => {
// pass a version of updateQuery that cleans subsequent steps etc // pass a version of updateQuery that cleans subsequent steps etc
const updateQuery = async datasetQuery => { const updateQuery = async query => {
await step.update(datasetQuery).update(); const datasetQuery = query.datasetQuery();
const updatedQuery = step.update(datasetQuery);
await updateQuestion(updatedQuery.question());
// mark the step as "closed" since we can assume it's been added or removed by the updateQuery // mark the step as "closed" since we can assume it's been added or removed by the updateQuery
this.closeStep(step.id); this.closeStep(step.id);
}; };
......
...@@ -36,13 +36,13 @@ export default function AggregateStep({ ...@@ -36,13 +36,13 @@ export default function AggregateStep({
aggregation={aggregation} aggregation={aggregation}
onChangeAggregation={newAggregation => onChangeAggregation={newAggregation =>
aggregation aggregation
? aggregation.replace(newAggregation).update(updateQuery) ? updateQuery(aggregation.replace(newAggregation))
: query.aggregate(newAggregation).update(updateQuery) : updateQuery(query.aggregate(newAggregation))
} }
/> />
)} )}
isLastOpened={isLastOpened} isLastOpened={isLastOpened}
onRemove={aggregation => aggregation.remove().update(updateQuery)} onRemove={aggregation => updateQuery(aggregation.remove())}
canRemove={aggregation => aggregation.canRemove()} canRemove={aggregation => aggregation.canRemove()}
/> />
); );
......
...@@ -36,13 +36,13 @@ export default function BreakoutStep({ ...@@ -36,13 +36,13 @@ export default function BreakoutStep({
breakout={breakout} breakout={breakout}
onChangeBreakout={newBreakout => onChangeBreakout={newBreakout =>
breakout breakout
? breakout.replace(newBreakout).update(updateQuery) ? updateQuery(breakout.replace(newBreakout))
: query.breakout(newBreakout).update(updateQuery) : updateQuery(query.breakout(newBreakout))
} }
/> />
)} )}
isLastOpened={isLastOpened} isLastOpened={isLastOpened}
onRemove={breakout => breakout.remove().update(updateQuery)} onRemove={breakout => updateQuery(breakout.remove())}
/> />
); );
} }
...@@ -54,7 +54,7 @@ function DataStep({ color, query, updateQuery }) { ...@@ -54,7 +54,7 @@ function DataStep({ color, query, updateQuery }) {
selectedDatabaseId={query.databaseId()} selectedDatabaseId={query.databaseId()}
selectedTableId={query.tableId()} selectedTableId={query.tableId()}
setSourceTableFn={tableId => setSourceTableFn={tableId =>
query.setTableId(tableId).setDefaultQuery().update(updateQuery) updateQuery(query.setTableId(tableId).setDefaultQuery())
} }
isInitiallyOpen={!query.tableId()} isInitiallyOpen={!query.tableId()}
triggerElement={ triggerElement={
...@@ -80,12 +80,12 @@ const DataFieldsPicker = ({ query, updateQuery, ...props }) => { ...@@ -80,12 +80,12 @@ const DataFieldsPicker = ({ query, updateQuery, ...props }) => {
const fields = query.fields(); const fields = query.fields();
const handleSelectNone = () => { const handleSelectNone = () => {
query updateQuery(
.setFields([ query.setFields([
dimensions[0].mbql(), dimensions[0].mbql(),
...expressionDimensions.map(d => d.mbql()), ...expressionDimensions.map(d => d.mbql()),
]) ]),
.update(updateQuery); );
}; };
const handleToggleDimension = dimension => { const handleToggleDimension = dimension => {
...@@ -99,7 +99,7 @@ const DataFieldsPicker = ({ query, updateQuery, ...props }) => { ...@@ -99,7 +99,7 @@ const DataFieldsPicker = ({ query, updateQuery, ...props }) => {
}) })
.map(d => d.mbql()); .map(d => d.mbql());
query.setFields(newFields).update(updateQuery); updateQuery(query.setFields(newFields));
}; };
const hasOneColumnSelected = fields.filter(isLocalField).length === 1; const hasOneColumnSelected = fields.filter(isLocalField).length === 1;
...@@ -110,7 +110,7 @@ const DataFieldsPicker = ({ query, updateQuery, ...props }) => { ...@@ -110,7 +110,7 @@ const DataFieldsPicker = ({ query, updateQuery, ...props }) => {
dimensions={dimensions} dimensions={dimensions}
selectedDimensions={selectedDimensions} selectedDimensions={selectedDimensions}
isAll={!fields || fields.length === 0} isAll={!fields || fields.length === 0}
onSelectAll={() => query.clearFields().update(updateQuery)} onSelectAll={() => updateQuery(query.clearFields())}
onSelectNone={handleSelectNone} onSelectNone={handleSelectNone}
disableSelected={hasOneColumnSelected} disableSelected={hasOneColumnSelected}
onToggleDimension={handleToggleDimension} onToggleDimension={handleToggleDimension}
......
...@@ -23,16 +23,16 @@ export default function ExpressionStep({ ...@@ -23,16 +23,16 @@ export default function ExpressionStep({
expression={expression} expression={expression}
onChangeExpression={(newName, newExpression) => onChangeExpression={(newName, newExpression) =>
expression expression
? query ? updateQuery(
.updateExpression(newName, newExpression, name) query.updateExpression(newName, newExpression, name),
.update(updateQuery) )
: query.addExpression(newName, newExpression).update(updateQuery) : updateQuery(query.addExpression(newName, newExpression))
} }
/> />
)} )}
isLastOpened={isLastOpened} isLastOpened={isLastOpened}
onRemove={([name, expression]) => onRemove={([name, expression]) =>
query.removeExpression(name).update(updateQuery) updateQuery(query.removeExpression(name))
} }
/> />
); );
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment