UNPKG

@finos/legend-data-cube

Version:
181 lines 9.61 kB
import { jsx as _jsx } from "react/jsx-runtime"; /** * Copyright (c) 2020-present, Goldman Sachs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { action, makeObservable, observable } from 'mobx'; import { DataCubeEditorSortsPanelState } from './DataCubeEditorSortsPanelState.js'; import { DataCubeSnapshotController } from '../../services/DataCubeSnapshotService.js'; import {} from '../../core/DataCubeSnapshot.js'; import { _findCol, _toCol, } from '../../core/model/DataCubeColumn.js'; import { ActionState, assertErrorThrown, guaranteeNonNullable, } from '@finos/legend-shared'; import { DataCubeEditorGeneralPropertiesPanelState } from './DataCubeEditorGeneralPropertiesPanelState.js'; import { DataCubeEditorColumnPropertiesPanelState } from './DataCubeEditorColumnPropertiesPanelState.js'; import { DataCubeEditorColumnsPanelState } from './DataCubeEditorColumnsPanelState.js'; import { DataCubeConfiguration } from '../../core/model/DataCubeConfiguration.js'; import { DataCubeEditorVerticalPivotsPanelState } from './DataCubeEditorVerticalPivotsPanelState.js'; import { DataCubeEditor } from '../../../components/view/editor/DataCubeEditor.js'; import { DataCubeEditorHorizontalPivotsPanelState } from './DataCubeEditorHorizontalPivotsPanelState.js'; import { DataCubeEditorPivotLayoutPanelState } from './DataCubeEditorPivotLayoutPanelState.js'; import { _lambda } from '../../core/DataCubeQueryBuilderUtils.js'; import { EngineError } from '@finos/legend-graph'; import { DataCubeEditorDimensionsPanelState } from './DataCubeEditorDimensionsPanelState.js'; export var DataCubeEditorTab; (function (DataCubeEditorTab) { DataCubeEditorTab["GENERAL_PROPERTIES"] = "General Properties"; DataCubeEditorTab["COLUMN_PROPERTIES"] = "Column Properties"; DataCubeEditorTab["COLUMNS"] = "Columns"; DataCubeEditorTab["VERTICAL_PIVOTS"] = "Vertical Pivots"; DataCubeEditorTab["DIMENSIONS"] = "Dimensions"; DataCubeEditorTab["HORIZONTAL_PIVOTS"] = "Horizontal Pivots"; DataCubeEditorTab["SORTS"] = "Sorts"; })(DataCubeEditorTab || (DataCubeEditorTab = {})); /** * This query editor state backs the main form editor of data cube. It supports * batching changes before engine, i.e. allowing user to make multiple edits before * applying and propgating them. * * NOTE: It allows almost FULL 1-1 control over the data cube query state. * It could also host other form editor states like filter editors, but due to ergonomic * reasons, those have been separated out into their own respective query editor states. */ export class DataCubeEditorState extends DataCubeSnapshotController { view; display; finalizationState = ActionState.create(); generalProperties; pivotLayout; columnProperties; columns; horizontalPivots; verticalPivots; dimensions; sorts; currentTab = DataCubeEditorTab.GENERAL_PROPERTIES; sourceColumns = []; leafExtendColumns = []; groupExtendColumns = []; constructor(view) { super(view.engine, view.settingService, view.snapshotService); makeObservable(this, { currentTab: observable, setCurrentTab: action, sourceColumns: observable.ref, leafExtendColumns: observable.ref, groupExtendColumns: observable.ref, applySnapshot: action, applyChanges: action, }); this.view = view; this.display = this.view.dataCube.layoutService.newDisplay('Properties', () => _jsx(DataCubeEditor, { view: this.view })); this.generalProperties = new DataCubeEditorGeneralPropertiesPanelState(this); this.pivotLayout = new DataCubeEditorPivotLayoutPanelState(this); this.columnProperties = new DataCubeEditorColumnPropertiesPanelState(this); this.dimensions = new DataCubeEditorDimensionsPanelState(this); this.columns = new DataCubeEditorColumnsPanelState(this); this.horizontalPivots = new DataCubeEditorHorizontalPivotsPanelState(this); this.verticalPivots = new DataCubeEditorVerticalPivotsPanelState(this); this.sorts = new DataCubeEditorSortsPanelState(this); } setCurrentTab(val) { this.currentTab = val; } async applySnapshot(snapshot, previousSnapshot) { this.sourceColumns = snapshot.data.sourceColumns; this.leafExtendColumns = snapshot.data.leafExtendedColumns; this.groupExtendColumns = snapshot.data.groupExtendedColumns; const configuration = DataCubeConfiguration.serialization.fromJson(snapshot.data.configuration); this.generalProperties.applySnaphot(snapshot, configuration); this.pivotLayout.applySnaphot(snapshot, configuration); this.columnProperties.applySnaphot(snapshot, configuration); this.dimensions.applySnaphot(snapshot, configuration); this.columns.applySnaphot(snapshot, configuration); this.horizontalPivots.applySnaphot(snapshot, configuration); this.verticalPivots.applySnaphot(snapshot, configuration); this.sorts.applySnaphot(snapshot, configuration); } getSnapshotSubscriberName() { return 'editor'; } //TODO: for dimensional grid, we need to reload the grid when we apply changes async applyChanges(options) { this.finalizationState.inProgress(); const baseSnapshot = guaranteeNonNullable(this.getLatestSnapshot()); const newSnapshot = baseSnapshot.clone(); // grid configuration must be processed before processing columns' configuration // to properly generate the container configuration this.generalProperties.buildSnapshot(newSnapshot, baseSnapshot); this.pivotLayout.buildSnapshot(newSnapshot, baseSnapshot); this.columnProperties.buildSnapshot(newSnapshot, baseSnapshot); this.dimensions.buildSnapshot(newSnapshot, baseSnapshot); // NOTE: column selection must be processed first since the snapshot // processing of other parts of the query can be affected by column selection. this.columns.buildSnapshot(newSnapshot, baseSnapshot); this.horizontalPivots.buildSnapshot(newSnapshot, baseSnapshot); this.verticalPivots.buildSnapshot(newSnapshot, baseSnapshot); this.sorts.buildSnapshot(newSnapshot, baseSnapshot); // finalize newSnapshot.finalize(); if (newSnapshot.hashCode !== baseSnapshot.hashCode) { const task = this.view.taskService.newTask('Validating query...'); // NOTE: Compile the query to validate. This is a helpful check for a lot of different scenarios // where the consistency of the query might be thrown off by changes from various parts that the // editor does not have full control over (i.e. extended columns, pivot cast columns, etc.) // e.g. when a column that group-level extended columns' expressions depend on has been unselected. const tempSnapshot = newSnapshot.clone(); // NOTE: in order to obtain the actual pivot result columns information, we need to execute // the query which is expensive in certain cases, so here, we just compute the "optimistic" set // of pivot result columns for casting to guarantee validation is not thronn off. if (tempSnapshot.data.pivot) { tempSnapshot.data.pivot.castColumns = this.sorts.selector.availableColumns .filter((col) => !_findCol(tempSnapshot.data.groupExtendedColumns, col.name)) .map(_toCol); } const codePrefix = `->`; const code = await this.view.engine.getPartialQueryCode(tempSnapshot, true); try { await this.view.engine.getQueryCodeRelationReturnType(codePrefix + code, _lambda([], [this.view.source.query]), this.view.source); } catch (error) { assertErrorThrown(error); if (error instanceof EngineError) { this.view.dataCube.alertService.alertCodeCheckError(error, code, codePrefix, { message: `Query Validation Failure: Can't safely apply changes. Check the query code below for more details.`, text: `Error: ${error.message}`, }); } else { this.view.dataCube.alertService.alertError(error, { message: `Query Validation Failure: Can't safely apply changes.`, text: `Error: ${error.message}`, }); } return; } finally { this.view.taskService.endTask(task); this.finalizationState.complete(); } this.publishSnapshot(newSnapshot); } else { this.finalizationState.complete(); } if (options?.closeAfterApply) { this.display.close(); } } } //# sourceMappingURL=DataCubeEditorState.js.map