diff --git a/packages/legend-application-data-cube/src/application/LegendDataCubePluginManager.ts b/packages/legend-application-data-cube/src/application/LegendDataCubePluginManager.ts index 6d233f628f..cd576ec5ac 100644 --- a/packages/legend-application-data-cube/src/application/LegendDataCubePluginManager.ts +++ b/packages/legend-application-data-cube/src/application/LegendDataCubePluginManager.ts @@ -34,6 +34,7 @@ export class LegendDataCubePluginManager private constructor() { super(); } + registerPureProtocolProcessorPlugin( plugin: PureProtocolProcessorPlugin, ): void { diff --git a/packages/legend-application-data-cube/src/components/LegendDataCubeLandingPage.tsx b/packages/legend-application-data-cube/src/components/LegendDataCubeLandingPage.tsx index fc71ac6678..581bf45e56 100644 --- a/packages/legend-application-data-cube/src/components/LegendDataCubeLandingPage.tsx +++ b/packages/legend-application-data-cube/src/components/LegendDataCubeLandingPage.tsx @@ -16,10 +16,12 @@ import { observer, useLocalObservable } from 'mobx-react-lite'; import { useLegendDataCubeBaseStore } from './LegendDataCubeFrameworkProvider.js'; -import { createContext, useContext } from 'react'; +import { createContext, useContext, useEffect } from 'react'; import { DataCube, DataCubeSettingKey, + FormBadge_WIP, + DataCubeLayoutManager, type DataCubeState, } from '@finos/legend-data-cube'; import { formatDate, guaranteeNonNullable } from '@finos/legend-shared'; @@ -30,6 +32,7 @@ import { DropdownMenuItem, useDropdownMenu, } from '@finos/legend-art'; +import { LegendDataCubeNewQueryBuilder } from './LegendDataCubeNewQueryBuilder.js'; // const CreateQueryDialog = observer( // (props: { view: LegendCubeViewer; store: LegendDataCubeBaseStore }) => { @@ -100,88 +103,6 @@ import { // }, // ); -// export const LegendDataCubeLandingPage = observer(() => { -// const store = useLegendDataCubeBaseStore(); -// const sourceSelector = store.sourceSelector; - -// useEffect(() => { -// store.context.initialize(); -// }, [store]); -// return ( -// <> -//
-//
-//
-//
-//
-//
-//
Legend Data Cube
-//
-//
-//
-//
-// -//
-//
-//
-//
-//
-// {/* {dataCubeStore.cubeViewer ? ( -// <> -//
-//
-// -//
-//
-// -//
-//
-// -// ) : ( -// <> -//
sourceSelector.openModal()} -// className="bg-white shadow" -// > -//
-//
-// -// Add Source -//
-//
-//
-// -// )} */} -//
-// {sourceSelector.open && ( -// -// )} -// {store.cubeViewer && store.saveModal && ( -// -// )} -// -// ); -// }); - const LegendDataCubeLandingPageStoreContext = createContext< LegendDataCubeLandingPageStore | undefined >(undefined); @@ -216,90 +137,128 @@ const withLegendDataCubeLandingPageStore = (WrappedComponent: React.FC) => ); }; -const LegendDataCubeHeader = observer((props: { dataCube: DataCubeState }) => { - return null; +const LegendDataCubeLandingPageHeader = observer( + (props: { dataCube?: DataCubeState | undefined }) => { + const store = useLegendDataCubeLandingPageStore(); + const { dataCube } = props; + + return ( +
+ + + +
+ ); + }, +); + +const LegendDataCubeLandingPageBlank = observer(() => { + const store = useLegendDataCubeLandingPageStore(); + const application = store.application; + const [openMenuDropdown, closeMenuDropdown, menuDropdownProps] = + useDropdownMenu(); + + return ( +
+
+
+ +
{`[ Legend DataCube ]`}
+
+
+ + + + { + const url = application.documentationService.url; + if (url) { + application.navigationService.navigator.visitAddress(url); + } + closeMenuDropdown(); + }} + disabled={true} // TODO: enable when we set up the documentation website + > + See Documentation + + + +
+
+
+
Create a new query to start
+ +
+
+
+ +
+ +
+
+
+
+ + +
+ ); }); export const LegendDataCubeLandingPage = withLegendDataCubeLandingPageStore( observer(() => { const store = useLegendDataCubeLandingPageStore(); const application = store.application; - const [openMenuDropdown, closeMenuDropdown, menuDropdownProps] = - useDropdownMenu(); if (!store.query) { - return ( -
-
-
- -
{`[ Legend DataCube ]`}
-
-
- - - { - const url = application.documentationService.url; - if (url) { - application.navigationService.navigator.visitAddress(url); - } - closeMenuDropdown(); - }} - disabled={true} // TODO: enable when we set up the documentation website - > - See Documentation - - -
-
{' '} -
-
Create a new query to start
- -
-
-
- -
- -
-
-
-
-
- ); + return ; } - return ( ( - + ), }} /> diff --git a/packages/legend-application-data-cube/src/components/LegendDataCubeNewQueryBuilder.tsx b/packages/legend-application-data-cube/src/components/LegendDataCubeNewQueryBuilder.tsx new file mode 100644 index 0000000000..30dc579f9a --- /dev/null +++ b/packages/legend-application-data-cube/src/components/LegendDataCubeNewQueryBuilder.tsx @@ -0,0 +1,97 @@ +/** + * 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 { observer } from 'mobx-react-lite'; +import { type LegendDataCubeNewQueryState } from '../stores/LegendDataCubeNewQueryState.js'; +import { LegendDataCubeSourceBuilderType } from '../stores/source/LegendDataCubeSourceBuilderState.js'; +import { + Dialog, + Modal, + PanelLoadingIndicator, + TimesIcon, + cn, +} from '@finos/legend-art'; +import { SavedQuerySourceEditor } from './source/SavedQuerySourceBuilder.js'; +import { LegendQueryDataCubeSourceBuilderState } from '../stores/source/LegendQueryDataCubeSourceBuilderState.js'; + +export const LegendDataCubeNewQueryBuilder = observer( + (props: { state: LegendDataCubeNewQueryState }) => { + const { state } = props; + const sourceState = state.sourceBuilder; + const tabs = Object.values(LegendDataCubeSourceBuilderType); + const selectedTab = sourceState.label; + + return ( +
+ +
+ + +
+ {tabs.map((tab) => ( + + ))} +
+
+
+ {sourceState instanceof + LegendQueryDataCubeSourceBuilderState && ( + + )} +
+
+
+
+ + +
+
+
+ ); + }, +); diff --git a/packages/legend-application-data-cube/src/components/source/DataCubeSourceEditor.tsx b/packages/legend-application-data-cube/src/components/source/DataCubeSourceEditor.tsx deleted file mode 100644 index 1239762798..0000000000 --- a/packages/legend-application-data-cube/src/components/source/DataCubeSourceEditor.tsx +++ /dev/null @@ -1,130 +0,0 @@ -/** - * 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 { observer } from 'mobx-react-lite'; -import { type LegendDataCubeSourceBuilder } from '../../stores/source/LegendDataCubeSourceBuilder.js'; -import { DataCubeSourceType } from '../../stores/source/CubeInputSourceLoader.js'; -import { - Dialog, - Modal, - PanelLoadingIndicator, - TimesIcon, - cn, -} from '@finos/legend-art'; -import { SavedQuerySourceEditor } from './SavedQuerySourceEditor.js'; -import { SavedQueryInputSourceState } from '../../stores/source/SavedQueryInputSourceState.js'; -import { useLegendDataCubeBaseStore } from '../LegendDataCubeFrameworkProvider.js'; - -export const DataCubeSourceEditor = observer( - (props: { sourceBuilder: LegendDataCubeSourceBuilder }) => { - const { sourceBuilder } = props; - const store = useLegendDataCubeBaseStore(); - const sourceState = sourceBuilder.sourceState; - const tabs = Object.values(DataCubeSourceType); - const selectedTab = sourceState.label; - const closeModal = (): void => sourceBuilder.close(); - - return ( - - -
-
-
- Data Cube Source -
-
-
- -
-
-
- - -
- {tabs.map((tab) => ( - - ))} -
-
-
- {sourceState instanceof SavedQueryInputSourceState && ( - - )} -
-
-
-
- {/* - */} -
-
-
- ); - }, -); diff --git a/packages/legend-application-data-cube/src/components/source/SavedQuerySourceEditor.tsx b/packages/legend-application-data-cube/src/components/source/SavedQuerySourceBuilder.tsx similarity index 68% rename from packages/legend-application-data-cube/src/components/source/SavedQuerySourceEditor.tsx rename to packages/legend-application-data-cube/src/components/source/SavedQuerySourceBuilder.tsx index 3770f7b709..5eb7a7a8e8 100644 --- a/packages/legend-application-data-cube/src/components/source/SavedQuerySourceEditor.tsx +++ b/packages/legend-application-data-cube/src/components/source/SavedQuerySourceBuilder.tsx @@ -16,46 +16,46 @@ import { observer } from 'mobx-react-lite'; import { QueryLoader } from '@finos/legend-query-builder'; -import type { SavedQueryInputSourceState } from '../../stores/source/SavedQueryInputSourceState.js'; +import type { LegendQueryDataCubeSourceBuilderState } from '../../stores/source/LegendQueryDataCubeSourceBuilderState.js'; import { generateGAVCoordinates } from '@finos/legend-storage'; export const SavedQuerySourceEditor = observer( - (props: { savedQueryInputSourceState: SavedQueryInputSourceState }) => { - const { savedQueryInputSourceState } = props; - const savedQuery = savedQueryInputSourceState.query; + (props: { sourceBuilder: LegendQueryDataCubeSourceBuilderState }) => { + const { sourceBuilder } = props; + const query = sourceBuilder.query; return (
- {savedQuery ? ( + {query ? (
Saved Query
Name:
-
{savedQuery.name}
+
{query.name}
Project:
{generateGAVCoordinates( - savedQuery.groupId, - savedQuery.artifactId, - savedQuery.versionId, + query.groupId, + query.artifactId, + query.versionId, )}
Owner:
-
{savedQuery.owner}
+
{query.owner}
) : ( - <> - // + // TODO: we could customize this loader to have a different styling + )}
); diff --git a/packages/legend-application-data-cube/src/stores/LegendDataCubeBaseStore.ts b/packages/legend-application-data-cube/src/stores/LegendDataCubeBaseStore.ts index 4e0234276c..3ca07eb28a 100644 --- a/packages/legend-application-data-cube/src/stores/LegendDataCubeBaseStore.ts +++ b/packages/legend-application-data-cube/src/stores/LegendDataCubeBaseStore.ts @@ -33,6 +33,7 @@ import { guaranteeNonNullable, } from '@finos/legend-shared'; import { LegendDataCubeDataCubeEngine } from './LegendDataCubeDataCubeEngine.js'; +import { LayoutManagerState } from '@finos/legend-data-cube'; export type LegendDataCubeApplicationStore = ApplicationStore< LegendDataCubeApplicationConfig, @@ -46,6 +47,7 @@ export class LegendDataCubeBaseStore { readonly pluginManager: LegendDataCubePluginManager; readonly depotServerClient: DepotServerClient; readonly graphManagerState: GraphManagerState; + readonly layout = new LayoutManagerState(); readonly startTime = Date.now(); readonly initState = ActionState.create(); @@ -75,12 +77,14 @@ export class LegendDataCubeBaseStore { async initialize() { this.initState.inProgress(); + try { this.application.identityService.setCurrentUser( await getCurrentUserIDFromEngineServer( this.application.config.engineServerUrl, ), ); + this.application.telemetryService.setup(); } catch (error) { assertErrorThrown(error); this.application.logService.error( diff --git a/packages/legend-application-data-cube/src/stores/LegendDataCubeDataCubeEngine.ts b/packages/legend-application-data-cube/src/stores/LegendDataCubeDataCubeEngine.ts index c6c52e87e7..fd093e8795 100644 --- a/packages/legend-application-data-cube/src/stores/LegendDataCubeDataCubeEngine.ts +++ b/packages/legend-application-data-cube/src/stores/LegendDataCubeDataCubeEngine.ts @@ -15,9 +15,6 @@ */ import { - SUPPORTED_FUNCTIONS, - V1_AppliedFunction, - V1_Lambda, RawLambda, RelationalExecutionActivities, TDSExecutionResult, @@ -25,32 +22,28 @@ import { V1_deserializeValueSpecification, V1_RawLambda, V1_serializeValueSpecification, + type V1_Lambda, type GraphManagerState, type PureModel, type V1_ValueSpecification, - type ParameterValue, - BasicGraphManagerState, - AbstractPureGraphManager, + type AbstractPureGraphManager, } from '@finos/legend-graph'; import { _elementPtr, - _functionName, DataCubeEngine, DataCubeSource, - type RelationType, - DataCubeQuery, + type DataCubeRelationType, type CompletionItem, _function, DataCubeFunction, } from '@finos/legend-data-cube'; import { - DocumentationEntry, guaranteeType, isNonNullable, LogEvent, - LogService, UnsupportedOperationError, type PlainObject, + type DocumentationEntry, } from '@finos/legend-shared'; import type { LegendDataCubeApplicationStore } from './LegendDataCubeBaseStore.js'; import { @@ -152,6 +145,44 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine { // return query; // } + // async buildCubeEngine(): Promise { + // this.buildCubeEngineState.inProgress(); + // const queryInfo = await this.context.graphManager.graphManager.getQueryInfo( + // guaranteeNonNullable(this.query).id, + // ); + // const execConext = + // (await this.context.graphManager.graphManager.resolveQueryInfoExecutionContext( + // queryInfo, + // () => + // this.context.depotServerClient.getVersionEntities( + // queryInfo.groupId, + // queryInfo.artifactId, + // queryInfo.versionId, + // ), + // )) as { mapping: string | undefined; runtime: string }; + // const lambda = + // (await this.context.graphManager.graphManager.pureCodeToLambda( + // queryInfo.content, + // )) as unknown as RawLambda; + // this.context.graphManager.graph.setOrigin( + // new LegendSDLC( + // queryInfo.groupId, + // queryInfo.artifactId, + // resolveVersion(queryInfo.versionId), + // ), + // ); + // // TODO: we should be able to call engine and convert lambda to relation if not one. + // const engine = new LegendDataCubeDataCubeEngine( + // lambda, + // undefined, + // execConext.mapping, + // execConext.runtime, + // this.context.graphManager, + // ); + // this.buildCubeEngineState.complete(); + // return engine; + // } + private buildRawLambdaFromValueSpec(query: V1_Lambda): RawLambda { const json = guaranteeType( V1_deserializeRawValueSpecification( @@ -162,7 +193,9 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine { return new RawLambda(json.parameters, json.body); } - private async getRelationalType(query: RawLambda): Promise { + private async getRelationalType( + query: RawLambda, + ): Promise { const relationType = await this.graphManager.getLambdaRelationType( query, this.graph, diff --git a/packages/legend-application-data-cube/src/stores/LegendDataCubeLandingPageStore.ts b/packages/legend-application-data-cube/src/stores/LegendDataCubeLandingPageStore.ts index 06fd15b830..88f644d71c 100644 --- a/packages/legend-application-data-cube/src/stores/LegendDataCubeLandingPageStore.ts +++ b/packages/legend-application-data-cube/src/stores/LegendDataCubeLandingPageStore.ts @@ -20,11 +20,13 @@ import type { LegendDataCubeBaseStore, } from './LegendDataCubeBaseStore.js'; import { type DataCubeQuery } from '@finos/legend-data-cube'; +import { LegendDataCubeNewQueryState } from './LegendDataCubeNewQueryState.js'; export class LegendDataCubeLandingPageStore { readonly application: LegendDataCubeApplicationStore; readonly baseStore: LegendDataCubeBaseStore; + readonly newQueryState: LegendDataCubeNewQueryState; query?: DataCubeQuery | undefined; constructor(baseStore: LegendDataCubeBaseStore) { @@ -35,6 +37,7 @@ export class LegendDataCubeLandingPageStore { this.application = baseStore.application; this.baseStore = baseStore; + this.newQueryState = new LegendDataCubeNewQueryState(baseStore); } setQuery(val: DataCubeQuery | undefined): void { diff --git a/packages/legend-application-data-cube/src/stores/LegendDataCubeNewQueryState.tsx b/packages/legend-application-data-cube/src/stores/LegendDataCubeNewQueryState.tsx new file mode 100644 index 0000000000..bda4d61938 --- /dev/null +++ b/packages/legend-application-data-cube/src/stores/LegendDataCubeNewQueryState.tsx @@ -0,0 +1,117 @@ +/** + * 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, computed, makeObservable, observable } from 'mobx'; +import { + IllegalStateError, + UnsupportedOperationError, +} from '@finos/legend-shared'; +import { LegendQueryDataCubeSourceBuilderState } from './source/LegendQueryDataCubeSourceBuilderState.js'; +import type { + LegendDataCubeApplicationStore, + LegendDataCubeBaseStore, +} from './LegendDataCubeBaseStore.js'; +import type { GraphManagerState } from '@finos/legend-graph'; +import { + LegendDataCubeSourceBuilderType, + type LegendDataCubeSourceBuilderState, +} from './source/LegendDataCubeSourceBuilderState.js'; +import { DataCubeQuery, type DisplayState } from '@finos/legend-data-cube'; +import type { LegendDataCubeDataCubeEngine } from './LegendDataCubeDataCubeEngine.js'; +import { LegendDataCubeNewQueryBuilder } from '../components/LegendDataCubeNewQueryBuilder.js'; + +export class LegendDataCubeNewQueryState { + readonly application: LegendDataCubeApplicationStore; + readonly baseStore: LegendDataCubeBaseStore; + readonly graphManagerState: GraphManagerState; + readonly engine: LegendDataCubeDataCubeEngine; + readonly display: DisplayState; + + sourceBuilder: LegendDataCubeSourceBuilderState; + + constructor(baseStore: LegendDataCubeBaseStore) { + makeObservable(this, { + sourceBuilder: observable, + currentSourceBuilderOption: computed, + changeSourceBuilder: action, + }); + + this.application = baseStore.application; + this.baseStore = baseStore; + this.graphManagerState = baseStore.graphManagerState; + this.engine = baseStore.engine; + this.display = this.engine.layout.newDisplay('New Query', () => ( + + )); + + this.sourceBuilder = this.createSourceBuilder( + LegendDataCubeSourceBuilderType.LEGEND_QUERY, + ); + } + + get sourceBuilderOptions(): LegendDataCubeSourceBuilderType[] { + return Object.values(LegendDataCubeSourceBuilderType); + } + + get currentSourceBuilderOption(): LegendDataCubeSourceBuilderType { + return this.sourceBuilder.label; + } + + changeSourceBuilder(type: LegendDataCubeSourceBuilderType): void { + if (this.sourceBuilder.label !== type) { + switch (type) { + case LegendDataCubeSourceBuilderType.LEGEND_QUERY: { + this.sourceBuilder = new LegendQueryDataCubeSourceBuilderState( + this.baseStore, + ); + break; + } + default: + throw new UnsupportedOperationError( + `Can't change source to unsupported type '${type}'`, + ); + } + this.sourceBuilder = this.createSourceBuilder(type); + } + } + + private createSourceBuilder( + type: LegendDataCubeSourceBuilderType, + ): LegendDataCubeSourceBuilderState { + switch (type) { + case LegendDataCubeSourceBuilderType.LEGEND_QUERY: + return new LegendQueryDataCubeSourceBuilderState(this.baseStore); + default: + throw new UnsupportedOperationError( + `Can't build source state for unsupported type '${type}'`, + ); + } + } + + async generateQuery(): Promise { + if (!this.sourceBuilder.isValid) { + throw new IllegalStateError(`Can't generate query: source is not valid`); + } + + const source = await this.sourceBuilder.build(); + const query = new DataCubeQuery(); + const processedSource = await this.engine.processQuerySource(source); + query.source = source; + query.query = `~[${processedSource.columns.map((column) => `'${column.name}'`)}]->select()`; + + return query; + } +} diff --git a/packages/legend-application-data-cube/src/stores/model/LegendQueryDataCubeSource.ts b/packages/legend-application-data-cube/src/stores/model/LegendQueryDataCubeSource.ts index f6ba8edc89..5c46e5db60 100644 --- a/packages/legend-application-data-cube/src/stores/model/LegendQueryDataCubeSource.ts +++ b/packages/legend-application-data-cube/src/stores/model/LegendQueryDataCubeSource.ts @@ -15,16 +15,22 @@ */ import { DataCubeSource } from '@finos/legend-data-cube'; +import type { Query, RawLambda } from '@finos/legend-graph'; import { SerializationFactory, usingConstantValueSchema, + type PlainObject, } from '@finos/legend-shared'; import { createModelSchema, primitive } from 'serializr'; export const LEGEND_QUERY_DATA_CUBE_SOURCE_TYPE = 'legendQuery'; export class LegendQueryDataCubeSource extends DataCubeSource { - queryId!: string; + savedQuery!: Query; + lambda!: RawLambda; + mappingPath!: string; + runtimePath!: string; + model!: PlainObject; } export class RawLegendQueryDataCubeSource { diff --git a/packages/legend-application-data-cube/src/stores/source/CubeInputSource.ts b/packages/legend-application-data-cube/src/stores/source/CubeInputSource.ts deleted file mode 100644 index 8a0e572183..0000000000 --- a/packages/legend-application-data-cube/src/stores/source/CubeInputSource.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * 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 type { VersionedProjectData } from '@finos/legend-server-depot'; - -export abstract class LegendDepotSavedSource { - project!: VersionedProjectData; -} - -export class LegendDepotService extends LegendDepotSavedSource { - service!: string; -} - -export class LegendDepotFunction extends LegendDepotSavedSource { - _function!: string; -} - -export class LegendDepotTable extends LegendDepotSavedSource { - database!: string; - schema!: string; - table!: string; - runtime!: string; -} diff --git a/packages/legend-application-data-cube/src/stores/source/CubeInputSourceLoader.ts b/packages/legend-application-data-cube/src/stores/source/CubeInputSourceLoader.ts deleted file mode 100644 index 75ad9ae33e..0000000000 --- a/packages/legend-application-data-cube/src/stores/source/CubeInputSourceLoader.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * 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 { ActionState, UnsupportedOperationError } from '@finos/legend-shared'; -import type { DataCubeEngine } from '@finos/legend-data-cube'; -// import type { DataCubeGenericSource } from '../model/DataCubeGenericSource.js'; - -export enum DataCubeSourceType { - LEGEND_QUERY = 'Legend Query', - REPL_QUERY = 'Repl Query', -} - -export abstract class LegendDataCubeInputSourceState { - buildCubeEngineState = ActionState.create(); - - setupActionState = ActionState.create(); - - // readonly context: LegendDataCubeStoreContext; - - // constructor(context: LegendDataCubeStoreContext) { - // this.context = context; - // } - abstract get label(): DataCubeSourceType; - - async setup(): Promise { - this.setupActionState.complete(); - } - - abstract buildCubeEngine(): Promise; - - // abstract process(): DataCubeGenericSource; - - abstract get isValid(): boolean; - - get openActionable(): boolean { - return true; - } - - // static builder( - // context: LegendDataCubeStoreContext, - // ): LegendDataCubeInputSourceState { - // throw new UnsupportedOperationError('No builder'); - // } -} diff --git a/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilder.ts b/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilder.ts deleted file mode 100644 index dfca2b9fb9..0000000000 --- a/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilder.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * 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 { flow, makeObservable, observable } from 'mobx'; -import { - DataCubeSourceType, - type LegendDataCubeInputSourceState, -} from './CubeInputSourceLoader.js'; -import { - UnsupportedOperationError, - assertErrorThrown, - assertTrue, - guaranteeNonNullable, - type GeneratorFn, -} from '@finos/legend-shared'; -import type { DataCubeEngine } from '@finos/legend-data-cube'; - -export class LegendDataCubeSourceBuilder { - open = false; - sourceState: LegendDataCubeInputSourceState; - - constructor() { - makeObservable(this, { - open: observable, - sourceState: observable, - - // inputSource: flow, - }); - this.sourceState = this.buildSource(guaranteeNonNullable(this.options[0])); - } - - get options(): DataCubeSourceType[] { - return Object.values(DataCubeSourceType); - } - - get currentOption(): DataCubeSourceType { - throw new UnsupportedOperationError(''); - } - - openModal(): void { - this.open = true; - } - - close(): void { - this.open = false; - } - - changeSource(source: DataCubeSourceType): void { - if (this.sourceState.label !== source) { - this.sourceState = this.buildSource(source); - } - } - - buildSource(source: DataCubeSourceType): LegendDataCubeInputSourceState { - // if (source === DataCubeSourceType.LEGEND_QUERY) { - // return SavedQueryInputSourceState.builder(this.context); - // } - throw new UnsupportedOperationError('Not supported'); - } - - // *inputSource( - // callback: (source: DataCubeGenericSource, engine: DataCubeEngine) => void, - // ): GeneratorFn { - // try { - // assertTrue( - // this.sourceState.isValid, - // 'Source State is in a valid state to input', - // ); - // const engine = - // (yield this.sourceState.buildCubeEngine()) as DataCubeEngine; - // const source = this.sourceState.process(); - // callback(source, engine); - // this.close(); - // } catch (error) { - // assertErrorThrown(error); - // // this.context.application.notificationService.notifyError( - // // `Unable to import: ${this.sourceState.label}: ${error.message}`, - // // ); - // } - // } -} diff --git a/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilderState.ts b/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilderState.ts new file mode 100644 index 0000000000..06b425df66 --- /dev/null +++ b/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilderState.ts @@ -0,0 +1,45 @@ +/** + * 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 { ActionState, type PlainObject } from '@finos/legend-shared'; +import type { + LegendDataCubeApplicationStore, + LegendDataCubeBaseStore, +} from '../LegendDataCubeBaseStore.js'; +import type { GraphManagerState } from '@finos/legend-graph'; + +export enum LegendDataCubeSourceBuilderType { + LEGEND_QUERY = 'Legend Query', + ADHOC_QUERY = 'Ad hoc Query', +} + +export abstract class LegendDataCubeSourceBuilderState { + readonly application: LegendDataCubeApplicationStore; + readonly baseStore: LegendDataCubeBaseStore; + readonly graphManagerState: GraphManagerState; + + readonly buildState = ActionState.create(); + + constructor(baseStore: LegendDataCubeBaseStore) { + this.application = baseStore.application; + this.baseStore = baseStore; + this.graphManagerState = baseStore.graphManagerState; + } + + abstract get label(): LegendDataCubeSourceBuilderType; + abstract get isValid(): boolean; + abstract build(): Promise; +} diff --git a/packages/legend-application-data-cube/src/stores/source/LegendQueryDataCubeSourceBuilderState.ts b/packages/legend-application-data-cube/src/stores/source/LegendQueryDataCubeSourceBuilderState.ts new file mode 100644 index 0000000000..32192fe538 --- /dev/null +++ b/packages/legend-application-data-cube/src/stores/source/LegendQueryDataCubeSourceBuilderState.ts @@ -0,0 +1,84 @@ +/** + * 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 { IllegalStateError, isNonNullable } from '@finos/legend-shared'; +import { QuerySearchSpecification, type LightQuery } from '@finos/legend-graph'; +import { + QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT, + QueryLoaderState, +} from '@finos/legend-query-builder'; +import { action, makeObservable, observable } from 'mobx'; +import { + LegendDataCubeSourceBuilderState, + LegendDataCubeSourceBuilderType, +} from './LegendDataCubeSourceBuilderState.js'; +import type { LegendDataCubeBaseStore } from '../LegendDataCubeBaseStore.js'; +import { RawLegendQueryDataCubeSource } from '../model/LegendQueryDataCubeSource.js'; + +export class LegendQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBuilderState { + readonly queryLoaderState: QueryLoaderState; + + query?: LightQuery | undefined; + + constructor(baseStore: LegendDataCubeBaseStore) { + super(baseStore); + + makeObservable(this, { + query: observable, + setQuery: action, + }); + + this.queryLoaderState = new QueryLoaderState( + this.application, + this.graphManagerState, + { + loadQuery: (query: LightQuery): void => { + this.setQuery(query); + }, + decorateSearchSpecification: (val) => val, + fetchDefaultQueries: async (): Promise => { + const searchSpecification = new QuerySearchSpecification(); + searchSpecification.limit = QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT; + return this.graphManagerState.graphManager.searchQueries( + QuerySearchSpecification.createDefault(undefined), + ); + }, + isReadOnly: true, + }, + ); + } + + setQuery(query: LightQuery): void { + this.query = query; + } + + override get label(): LegendDataCubeSourceBuilderType { + return LegendDataCubeSourceBuilderType.LEGEND_QUERY; + } + + override get isValid(): boolean { + return isNonNullable(this.query); + } + + override async build() { + if (!this.query) { + throw new IllegalStateError('Query is missing'); + } + const source = new RawLegendQueryDataCubeSource(); + source.queryId = this.query.id; + return RawLegendQueryDataCubeSource.serialization.toJson(source); + } +} diff --git a/packages/legend-application-data-cube/src/stores/source/SavedQueryInputSourceState.ts b/packages/legend-application-data-cube/src/stores/source/SavedQueryInputSourceState.ts deleted file mode 100644 index e542707974..0000000000 --- a/packages/legend-application-data-cube/src/stores/source/SavedQueryInputSourceState.ts +++ /dev/null @@ -1,142 +0,0 @@ -/** - * 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 { - assertTrue, - guaranteeNonNullable, - isNonNullable, -} from '@finos/legend-shared'; -import { - LegendDataCubeInputSourceState, - DataCubeSourceType, -} from './CubeInputSourceLoader.js'; -import type { DataCubeEngine } from '@finos/legend-data-cube'; -import { - LegendSDLC, - QuerySearchSpecification, - type RawLambda, - type LightQuery, -} from '@finos/legend-graph'; -import { resolveVersion } from '@finos/legend-server-depot'; -import { LegendDataCubeDataCubeEngine } from '../LegendDataCubeDataCubeEngine.js'; -import { - QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT, - QueryLoaderState, -} from '@finos/legend-query-builder'; -import { action, makeObservable, observable } from 'mobx'; - -export class SavedQueryInputSourceState extends LegendDataCubeInputSourceState { - query: LightQuery | undefined; - // queryLoaderState: QueryLoaderState; - - constructor() { - super(); - makeObservable(this, { - query: observable, - buildCubeEngineState: observable, - setQuery: action, - }); - // this.queryLoaderState = new QueryLoaderState( - // this.context.application, - // this.context.graphManager, - // { - // loadQuery: (query: LightQuery): void => { - // this.setQuery(query); - // }, - // decorateSearchSpecification: (val) => val, - // fetchDefaultQueries: async (): Promise => { - // const searchSpecification = new QuerySearchSpecification(); - // searchSpecification.limit = QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT; - // return this.context.graphManager.graphManager.searchQueries( - // QuerySearchSpecification.createDefault(undefined), - // ); - // }, - // isReadOnly: true, - // }, - // ); - } - - setQuery(query: LightQuery): void { - this.query = query; - } - - // override process(): DataCubeGenericSource { - // assertTrue(this.isValid); - // return new LegendQueryDataCubeSource(guaranteeNonNullable(this.query).id); - // } - - override get openActionable(): boolean { - return false; - } - - // static override builder( - // context: LegendDataCubeStoreContext, - // ): LegendDataCubeInputSourceState { - // return new SavedQueryInputSourceState(context); - // } - override get label(): DataCubeSourceType { - return DataCubeSourceType.LEGEND_QUERY; - } - override setup(): Promise { - throw new Error('Method not implemented.'); - } - - override buildCubeEngine(): Promise { - throw new Error('Method not implemented.'); - } - - // async buildCubeEngine(): Promise { - // this.buildCubeEngineState.inProgress(); - // const queryInfo = await this.context.graphManager.graphManager.getQueryInfo( - // guaranteeNonNullable(this.query).id, - // ); - // const execConext = - // (await this.context.graphManager.graphManager.resolveQueryInfoExecutionContext( - // queryInfo, - // () => - // this.context.depotServerClient.getVersionEntities( - // queryInfo.groupId, - // queryInfo.artifactId, - // queryInfo.versionId, - // ), - // )) as { mapping: string | undefined; runtime: string }; - // const lambda = - // (await this.context.graphManager.graphManager.pureCodeToLambda( - // queryInfo.content, - // )) as unknown as RawLambda; - // this.context.graphManager.graph.setOrigin( - // new LegendSDLC( - // queryInfo.groupId, - // queryInfo.artifactId, - // resolveVersion(queryInfo.versionId), - // ), - // ); - // // TODO: we should be able to call engine and convert lambda to relation if not one. - // const engine = new LegendDataCubeDataCubeEngine( - // lambda, - // undefined, - // execConext.mapping, - // execConext.runtime, - // this.context.graphManager, - // ); - // this.buildCubeEngineState.complete(); - // return engine; - // } - - override get isValid(): boolean { - return isNonNullable(this.query); - } -} diff --git a/packages/legend-application-data-cube/style/_query-loader.scss b/packages/legend-application-data-cube/style/_query-loader.scss new file mode 100644 index 0000000000..34473c2f9f --- /dev/null +++ b/packages/legend-application-data-cube/style/_query-loader.scss @@ -0,0 +1,351 @@ +/** + * 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. + */ + +@use 'mixins' as *; + +.query-loader { + height: 100%; + + &__header { + padding: 1rem; + height: 9.2rem; + border-bottom: 0.1rem solid var(--color-dark-grey-200); + } + + &__filter { + height: 2.8rem; + margin-top: 1rem; + + &__toggler { + @include flexVCenter; + } + + &__extra__filters { + display: flex; + margin-left: 0.5rem; + } + + &__toggler__btn { + @include flexCenter; + + height: 2.8rem; + align-self: flex-start; + border-radius: 0.2rem; + padding: 0 0.5rem; + font-size: 1.2rem; + border: 0.1rem solid var(--color-dark-grey-200); + color: var(--color-light-grey-400); + line-height: 2rem; + cursor: pointer; + + & + & { + margin-left: 0.5rem; + } + + &:hover { + border-color: var(--color-dark-grey-250); + background: var(--color-dark-grey-100); + } + + &--toggled:hover, + &--toggled { + border-color: var(--color-blue-200); + color: var(--color-light-grey-50); + } + } + } + + &__search { + @include flexCenter; + + position: relative; + + &__input { + height: 3.4rem; + padding-right: 2.8rem; + padding-left: 1rem; + width: 100%; + background: var(--color-dark-grey-85); + border-radius: 0.2rem; + border: 0.1rem solid var(--color-dark-grey-200); + + &__container { + @include flexCenter; + + position: relative; + height: 3.4rem; + width: 100%; + } + + &--searching { + padding-right: 5.6rem; + } + + &__search__icon { + @include flexCenter; + + position: absolute; + right: 0.2rem; + height: 2.8rem; + width: 2.8rem; + + svg { + color: var(--color-light-shade-100); + } + } + + &__clear-btn { + @include flexCenter; + + position: absolute; + right: 0.2rem; + height: 2.8rem; + width: 2.8rem; + + svg { + color: var(--color-dark-grey-400); + } + + &:hover svg { + color: var(--color-dark-grey-500); + } + } + } + } + + &__content { + height: calc(100% - 9.2rem); + position: relative; + } + + &__results { + padding: 0.5rem; + height: 100%; + overflow-y: overlay; + + &__summary { + @include flexVCenter; + + justify-content: space-between; + font-size: 1.2rem; + height: 2.5rem; + margin-bottom: 0.5rem; + color: var(--color-dark-grey-400); + padding: 0 0.5rem; + user-select: none; + } + + &__summary__info { + font-size: 1.2rem; + margin-left: 0.5rem; + } + + &__sort-by { + @include flexVCenter; + + height: 2rem; + + &__name { + font-size: 1.2rem; + font-weight: 500; + color: var(--color-dark-grey-400); + } + + &__selector { + width: 11rem; + margin-left: 0.5rem; + } + } + } + + &__result { + display: flex; + width: 100%; + height: 5.4rem; + padding: 0.5rem 0; + border-radius: 0.2rem; + cursor: pointer; + border: 0.1rem solid var(--color-dark-grey-200); + background: var(--color-dark-grey-100); + + &:hover { + background: var(--color-dark-grey-200); + } + + & + & { + margin-top: 0.5rem; + } + } + + &__result__content { + width: calc(100% - 5rem); + text-align: start; + } + + &__result__title { + @include ellipsisTextOverflow; + + height: 2.2rem; + line-height: 2.2rem; + width: 80%; + padding: 0 1rem; + color: var(--color-light-grey-300); + font-weight: 500; + } + + &__result__title__editor { + display: flex; + padding: 0 1rem; + + &__input { + width: 80%; + padding: 0.5rem; + height: 2.2rem; + } + + &__actions { + display: flex; + margin-left: 0.5rem; + } + + &__save-btn, + &__cancel-btn { + font-size: 1.2rem; + height: 2.2rem; + + &[disabled] { + cursor: not-allowed; + } + } + + &__cancel-btn { + background: var(--color-dark-grey-100); + border: 0.1rem solid var(--color-dark-grey-300); + + &:hover { + background: var(--color-dark-grey-250); + } + } + } + + &__result__description { + @include flexVCenter; + + padding: 0 1rem; + height: 2.2rem; + color: var(--color-dark-grey-500); + + &__date__icon svg { + display: flex; + font-size: 1.2rem; + } + + &__date { + margin-right: 1rem; + font-size: 1.1rem; + min-width: 10.5rem; + margin-left: 0.5rem; + } + + &__author__icon { + display: flex; + + svg { + font-size: 1rem; + } + } + + &__author__name { + margin-left: 0.5rem; + color: var(--color-light-grey-500); + font-size: 1.1rem; + } + + &__owner { + @include flexCenter; + + padding: 0 0.5rem; + height: 1.4rem; + font-size: 1rem; + font-weight: 500; + color: var(--color-light-grey-50); + border-radius: 0.2rem; + background: var(--color-blue-50); + } + } + + &__result__actions-menu { + @include flexCenter; + + height: 100%; + width: 2.5rem; + cursor: pointer; + color: var(--color-dark-grey-300); + + svg { + font-size: 1.6rem; + } + + &:hover svg { + color: var(--color-dark-grey-400); + } + } + + &__result__arrow { + @include flexCenter; + + height: 100%; + width: 2.5rem; + color: var(--color-dark-grey-280); + } + + &__dialog { + margin: 2vh 0; + + &__container { + @include flexCenter; + + height: 100%; + width: 100%; + } + + &__body { + height: 100%; + width: 60rem; + } + + &__body__content { + height: 100%; + overflow: hidden; + } + + &__header { + @include flexVCenter; + + justify-content: space-between; + height: 3.4rem; + padding: 0 1rem; + } + + &__header__close-btn { + color: var(--color-light-grey-300); + } + + &__content { + height: calc(100% - 3.4rem); + } + } +} diff --git a/packages/legend-application-data-cube/style/index.scss b/packages/legend-application-data-cube/style/index.scss index ba2e9f1625..6bbcb9d1f9 100644 --- a/packages/legend-application-data-cube/style/index.scss +++ b/packages/legend-application-data-cube/style/index.scss @@ -15,8 +15,178 @@ */ @forward 'query-editor'; +@forward 'query-loader'; @forward 'query-editor-light'; +:root { + --color-white: #fff; + --color-light-grey-0: #fafafa; + --color-light-grey-50: #f3f3f3; + --color-light-grey-100: #efefef; + --color-light-grey-150: #e6e6e6; + --color-light-grey-180: #dcdcdc; + --color-light-grey-200: #ddd; + --color-light-grey-250: #d4d4d4; // vscode + --color-light-grey-300: #cecece; + --color-light-grey-400: #bbb; + --color-black: #000; + --color-dark-grey-50: #1e1e1e; // vscode + --color-dark-grey-80: #252525; + --color-dark-grey-85: #272727; + --color-dark-grey-100: #2d2d2d; + --color-dark-grey-200: #353535; + --color-dark-grey-250: #3e3e3e; + --color-dark-grey-280: #404040; // vscode + --color-dark-grey-300: #595959; + --color-dark-grey-350: #606060; // vscode + --color-dark-grey-400: #737373; + --color-dark-grey-500: #9a9a9a; + --color-navy-300: #45456b; + --color-navy-500: #34345f; + --color-navy-600: #c2c2e3; + --color-purple-0: #d3bee0; + --color-purple-50: #af90c3; + --color-purple-100: #8a58ab; + --color-purple-200: #804090; + --color-purple-400: #5d3b73; + --color-magenta-30: #c585c0; // vscode + --color-magenta-50: #d06c99; + --color-magenta-70: #f152b1; + --color-magenta-100: #bb619b; + --color-magenta-300: #8c4268; + --color-pink-0: #ffc0cb; + --color-pink-100: #ffa7c4; + --color-pink-200: #f05577; + --color-pink-300: #d14664; + --color-pink-380: #c5375f; + --color-pink-400: #b33659; + --color-pink-500: #af2a5b; + --color-red-50: #ff958c; + --color-red-100: #f5584b; + --color-red-150: #f95252; + --color-red-180: #ea4646; // vscode + --color-red-200: #bf2f22; + --color-red-300: #be1100; + --color-red-400: #800404; + --color-red-500: #5a1d1d; + --color-carmine-200: #af3e34; + --color-skin-100: #f1b47f; + --color-skin-200: #ce9178; // vscode + --color-orange-50: #f90; + --color-orange-100: #e97f49; + --color-orange-150: #ca663a; + --color-orange-200: #c95f03; + --color-orange-250: #bb5803; + --color-orange-400: #8a4628; + --color-orange-500: #6c3f2b; + --color-yellow-0: #ffffe0; + --color-yellow-50: #dcdcaa; // vscode + --color-yellow-80: #d7ba7d; // vscode + --color-yellow-100: #ffca34; + --color-yellow-200: #fbbc05; + --color-yellow-300: #e2a700; + --color-yellow-400: #dc9d2a; + --color-yellow-500: #c58105; + --color-dark-yellow-500: #342a18; + --color-green-80: #65d081; + --color-green-100: #34a853; + --color-green-200: #1e8a53; + --color-lime-50: #a5ea81; + --color-lime-75: #aad468; + --color-lime-150: #6a9955; // vscode + --color-green-neon-100: #2cca72; + --color-medium-green-0: #7bffc8; + --color-medium-green-100: #39cca2; + --color-medium-green-150: #40c8ae; // vscode + --color-medium-green-180: #4ec9b0; // vscode + --color-medium-green-450: #139077; + --color-medium-green-500: #11846d; + --color-teal-50: #16b8bf; + --color-light-blue-0: #deebff; + --color-light-blue-10: #9cddfe; // vscode + --color-light-blue-20: #7fdbff; + --color-light-blue-50: #6391d0; + --color-light-blue-200: #477cc5; + --color-light-blue-400: #2c4f80; + --color-light-blue-450: #264f77; // vscode + --color-blue-40: #40a6ff; // vscode + --color-blue-50: #1c89d2; + --color-blue-100: #007acc; + --color-blue-150: #0a73b9; + --color-blue-180: #0c6bab; + --color-blue-200: #08629e; + --color-blue-300: #014a7b; + --color-blue-500: #002f4f; + --color-light-shade-50: #ffffff12; + --color-light-shade-100: #ffffff2e; + --color-light-shade-150: #fff3; + --color-dark-shade-0: #00000008; + --color-dark-shade-50: #00000014; + --color-dark-shade-100: #0000002e; + --color-dark-shade-200: #00000030; + --color-dark-shade-230: #0000003d; + --color-dark-shade-250: #00000045; + --color-dark-shade-280: #0000004f; + --color-dark-shade-300: #00000061; + --color-dark-shade-800: #000000a6; + --color-dark-shade-900: #000000c4; + --color-dark-blue-shade-100: #7f7ab124; + --color-dark-red-shade-50: #ff00000d; + --color-dark-red-shade-100: #ff00001a; + + // misc + --color-eminence: #68217a; // vscode + --color-mauve: #7685b9; + --color-mauve-50: #7695ff; + --color-purple-TEMP: #bfbcff; + --color-orange-TEMP: #ffeed3; + --color-navy-TEMP: #3f51b5; + --color-yellow-TEMP: #f4b400; + --color-yellow-TEMP-2: #c19033; + --color-medium-green-TEMP-2: #43849c; + --color-dnd__overlay: #63636394; + --color-dnd__overlay-light: #d5d5d594; + --color-app-header: var(--color-navy-500); + --color-panel-border: var(--color-light-grey-100); + --color-text-label: var(--color-light-grey-100); + --color-required-label: var(--color-yellow-200); + --color-input: var(--color-white); + --color-input-border: var(--color-light-grey-200); + --color-input-border--hover: var(--color-light-grey-400); + --color-input-border--focus: var(--color-light-blue-200); + --color-input-border--dark: var(--color-dark-grey-100); + --color-test: var(--color-pink-200); + --color-test--passed: var(--color-green-100); + --color-test--failed: var(--color-orange-100); + --color-test--error: var(--color-red-100); + --color-test--skipped: var(--color-dark-grey-400); + --color-conflict: var(--color-orange-150); + --color-merge--current: var(--color-medium-green-150); + --color-merge--base: var(--color-dark-grey-350); + --color-merge--incoming: var(--color-blue-40); + --color-warning: var(--color-yellow-100); + // font + --font-entity-label: 'Roboto Condensed'; + --color-legacylight-light-grey-100: #edf0f1; + --color-legacylight-light-grey-200: #dce2e4; + --color-legacylight-light-grey-300: #b5bec4; + --color-legacylight-light-grey-400: #95a0a8; + --color-legacylight-dark-grey-200: #29323a; + --color-legacylight-dark-grey-400: #4e5364; + --color-legacylight-light-blue-50: #def3ff; + --color-legacylight-light-blue-100: #7399c6; + --color-legacylight-light-blue-200: #6a8db6; + --color-legacylight-light-blue-250: #687b93; + --color-legacylight-light-blue-270: #597089; + --color-legacylight-light-blue-300: #4d6f9c; + --color-legacylight-light-blue-350: #475b72; + --color-legacylight-light-blue-400: #1b4c8c; + --color-legacylight-light-blue-600: #2d3d51; + --color-legacylight-green-100: #5cb65c; + --color-legacylight-orange-100: #f68f1e; + --color-legacylight-orange-150: #ea8212; +} + // ---------------------------------------- NORMALIZE ---------------------------------------- html { diff --git a/packages/legend-application-repl/src/components/LegendREPLDataCubeHeader.tsx b/packages/legend-application-repl/src/components/LegendREPLDataCubeHeader.tsx index 7fcad3d017..9e587c79a3 100644 --- a/packages/legend-application-repl/src/components/LegendREPLDataCubeHeader.tsx +++ b/packages/legend-application-repl/src/components/LegendREPLDataCubeHeader.tsx @@ -43,7 +43,7 @@ export const LegendREPLDataCubeHeader = observer( .publishDataCube(dataCube) .catch((error) => dataCube.engine.logUnhandledError(error)); }} - className="w-20 border border-neutral-400 bg-neutral-300 px-2 hover:brightness-95 disabled:cursor-not-allowed disabled:border-neutral-300 disabled:text-neutral-400 disabled:hover:brightness-100" + className="flex h-5 w-20 items-center justify-center border border-neutral-400 bg-neutral-300 px-2 text-sm hover:brightness-95 disabled:cursor-not-allowed disabled:border-neutral-300 disabled:text-neutral-400 disabled:hover:brightness-100" > Publish diff --git a/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx b/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx index 7d4d330f1a..1ec7161249 100644 --- a/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx +++ b/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx @@ -58,7 +58,7 @@ export class LegendREPLBaseStore { makeObservable(this, { query: observable, - initialize: action, + setQuery: action, }); this.application = application; this.client = new LegendREPLServerClient( @@ -75,17 +75,27 @@ export class LegendREPLBaseStore { this.engine = new LegendREPLDataCubeEngine(this); } + setQuery(query: DataCubeQuery | undefined): void { + this.query = query; + } + async initialize() { this.initState.inProgress(); try { const info = await this.client.getInfrastructureInfo(); this.currentUser = info.currentUser; + if (info.currentUser) { + this.application.identityService.setCurrentUser(info.currentUser); + } + this.application.telemetryService.setup(); + this.queryServerBaseUrl = info.queryServerBaseUrl; this.hostedApplicationBaseUrl = info.hostedApplicationBaseUrl; this.gridClientLicense = info.gridClientLicense; - this.query = DataCubeQuery.serialization.fromJson( - await this.client.getBaseQuery(), + this.setQuery( + DataCubeQuery.serialization.fromJson(await this.client.getBaseQuery()), ); + this.initState.pass(); } catch (error) { assertErrorThrown(error); diff --git a/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts b/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts index 603a59e751..0983742fd8 100644 --- a/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts +++ b/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts @@ -35,6 +35,8 @@ import { type V1_ValueSpecification, V1_buildEngineError, V1_EngineError, + V1_RelationType, + V1_getGenericTypeFullPath, } from '@finos/legend-graph'; import { assertErrorThrown, @@ -135,9 +137,17 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { query: V1_Lambda, source: DataCubeSource, ) { - return this.client.getQueryRelationReturnType({ - query: V1_serializeValueSpecification(query, []), - }); + const relationType = V1_RelationType.serialization.fromJson( + await this.client.getQueryRelationReturnType({ + query: V1_serializeValueSpecification(query, []), + }), + ); + return { + columns: relationType.columns.map((column) => ({ + name: column.name, + type: V1_getGenericTypeFullPath(column.genericType), + })), + }; } override async getQueryCodeRelationReturnType( @@ -146,10 +156,18 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { source: DataCubeSource, ) { try { - return await this.client.getQueryCodeRelationReturnType({ - code, - baseQuery: V1_serializeValueSpecification(baseQuery, []), - }); + const relationType = V1_RelationType.serialization.fromJson( + await this.client.getQueryCodeRelationReturnType({ + code, + baseQuery: V1_serializeValueSpecification(baseQuery, []), + }), + ); + return { + columns: relationType.columns.map((column) => ({ + name: column.name, + type: V1_getGenericTypeFullPath(column.genericType), + })), + }; } catch (error) { assertErrorThrown(error); if ( diff --git a/packages/legend-application-repl/src/stores/LegendREPLServerClient.ts b/packages/legend-application-repl/src/stores/LegendREPLServerClient.ts index cb46c0835f..14b959b245 100644 --- a/packages/legend-application-repl/src/stores/LegendREPLServerClient.ts +++ b/packages/legend-application-repl/src/stores/LegendREPLServerClient.ts @@ -24,9 +24,9 @@ import { import { type DataCubeQuery, type CompletionItem, - type RelationType, } from '@finos/legend-data-cube'; import { + type V1_RelationType, type PersistentDataCubeQuery, type V1_Lambda, type V1_ValueSpecification, @@ -128,7 +128,7 @@ export class LegendREPLServerClient { async getQueryRelationReturnType( input: GetQueryRelationReturnTypeInput, - ): Promise { + ): Promise> { return this.networkClient.post( `${this.dataCube}/getRelationReturnType`, input, @@ -137,7 +137,7 @@ export class LegendREPLServerClient { async getQueryCodeRelationReturnType( input: GetQueryCodeRelationReturnTypeInput, - ): Promise { + ): Promise> { return this.networkClient.post( `${this.dataCube}/getRelationReturnType/code`, input, diff --git a/packages/legend-application-studio/src/components/editor/editor-group/service-editor/ServiceEditor.tsx b/packages/legend-application-studio/src/components/editor/editor-group/service-editor/ServiceEditor.tsx index 71b21bbb99..12b81dd9dc 100644 --- a/packages/legend-application-studio/src/components/editor/editor-group/service-editor/ServiceEditor.tsx +++ b/packages/legend-application-studio/src/components/editor/editor-group/service-editor/ServiceEditor.tsx @@ -526,8 +526,7 @@ const ServiceGeneralEditor = observer(() => { >
- Service requires at least {MINIMUM_SERVICE_OWNERS}{' '} - owners + {`Service requires at least ${MINIMUM_SERVICE_OWNERS} owners`}
)} diff --git a/packages/legend-application-studio/src/stores/editor/data-cube/LegendStudioDataCubeHelper.ts b/packages/legend-application-studio/src/stores/editor/data-cube/LegendStudioDataCubeHelper.ts index 181e59d767..e151ee53e2 100644 --- a/packages/legend-application-studio/src/stores/editor/data-cube/LegendStudioDataCubeHelper.ts +++ b/packages/legend-application-studio/src/stores/editor/data-cube/LegendStudioDataCubeHelper.ts @@ -107,7 +107,7 @@ export const openDataCube = async ( } try { - await engine.getRelationalType(engine.selectInitialQuery); + await engine.getRelationType(engine.selectInitialQuery); } catch (error) { assertErrorThrown(error); throw new UnsupportedOperationError( diff --git a/packages/legend-data-cube/src/components/DataCube.tsx b/packages/legend-data-cube/src/components/DataCube.tsx index e3dcf821d5..249cbff490 100644 --- a/packages/legend-data-cube/src/components/DataCube.tsx +++ b/packages/legend-data-cube/src/components/DataCube.tsx @@ -31,6 +31,7 @@ import { DataCubeState } from '../stores/DataCubeState.js'; import { type DataCubeOptions } from '../stores/DataCubeOptions.js'; import { DataCubeContextProvider, useDataCube } from './DataCubeProvider.js'; import type { DataCubeQuery } from '../stores/core/models/DataCubeQuery.js'; +import { FormBadge_WIP } from './core/DataCubeFormUtils.js'; const DataCubeTitleBar = observer(() => { const dataCube = useDataCube(); @@ -60,7 +61,7 @@ const DataCubeTitleBar = observer(() => { transformOrigin: { vertical: 'top', horizontal: 'left' }, classes: { paper: 'rounded-none mt-[1px]', - list: 'w-36 p-0 rounded-none border border-neutral-400 bg-white max-h-40 overflow-y-auto py-0.5', + list: 'w-40 p-0 rounded-none border border-neutral-400 bg-white max-h-40 overflow-y-auto py-0.5', }, }} > @@ -76,6 +77,7 @@ const DataCubeTitleBar = observer(() => { disabled={true} // TODO: enable when we set up the documentation website > See Documentation +
; + ): Promise; abstract getQueryCodeRelationReturnType( code: string, baseQuery: V1_ValueSpecification, source: DataCubeSource, - ): Promise; + ): Promise; abstract executeQuery( query: V1_Lambda, diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQueryBuilder.ts b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQueryBuilder.ts index 1e7ff9ff4e..249455aec4 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQueryBuilder.ts +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQueryBuilder.ts @@ -21,6 +21,7 @@ import { type V1_AppliedFunction, V1_GenericType, V1_RelationType, + V1_getGenericTypeFullPath, } from '@finos/legend-graph'; import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; import { @@ -109,7 +110,12 @@ function _addCountAggColumnToPivot( ).rawType, V1_RelationType, ).columns.map((column) => - _colSpec(column.name, undefined, undefined, column.type), + _colSpec( + column.name, + undefined, + undefined, + V1_getGenericTypeFullPath(column.genericType), + ), ); uniq( castColumns diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.ts index dec1fc645b..2d771b8537 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.ts @@ -163,6 +163,7 @@ import { V1_CompleteCodeInput } from './compilation/V1_CompleteCodeInput.js'; import { CodeCompletionResult } from '../../../../action/compilation/Completion.js'; import { DeploymentResult } from '../../../../action/DeploymentResult.js'; import { PersistentDataCubeQuery } from '../../../../action/query/PersistentDataCubeQuery.js'; +import { V1_getGenericTypeFullPath } from '../helpers/V1_DomainHelper.js'; class V1_RemoteEngineConfig extends TEMPORARY__AbstractEngineConfig { private engine: V1_RemoteEngine; @@ -727,7 +728,11 @@ export class V1_RemoteEngine implements V1_GraphManagerEngine { ); const result = new RelationTypeMetadata(); result.columns = res.columns.map( - (e) => new RelationTypeColumnMetadata(e.type, e.name), + (column) => + new RelationTypeColumnMetadata( + V1_getGenericTypeFullPath(column.genericType), + column.name, + ), ); return result; } diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/helpers/V1_DomainHelper.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/helpers/V1_DomainHelper.ts index 5caae6859c..5a61c2ea8d 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/helpers/V1_DomainHelper.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/helpers/V1_DomainHelper.ts @@ -36,7 +36,7 @@ export const V1_getGenericTypeFullPath = (val: V1_GenericType): string => { return val.rawType.fullPath; } throw new UnsupportedOperationError( - 'Failed to get full path from generic type', + `Can't extract type path from generic type`, ); }; @@ -152,6 +152,6 @@ export function V1_createRelationTypeColumn( ): V1_RelationTypeColumn { const column = new V1_RelationTypeColumn(); column.name = name; - column.type = type; + column.genericType = V1_createGenericTypeWithElementPath(type); return column; } diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/type/V1_RelationType.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/type/V1_RelationType.ts index c7e93cd5b9..c6f51a75ee 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/type/V1_RelationType.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/type/V1_RelationType.ts @@ -20,23 +20,54 @@ import { usingModelSchema, type Hashable, } from '@finos/legend-shared'; -import { createModelSchema, list, primitive } from 'serializr'; +import { + createModelSchema, + custom, + list, + primitive, + serialize, +} from 'serializr'; import type { V1_Type } from './V1_Type.js'; import { CORE_HASH_STRUCTURE } from '../../../../../../../graph/Core_HashUtils.js'; +import type { V1_GenericType } from './V1_GenericType.js'; +import { + V1_deserializeGenericType, + V1_GenericTypeModelSchema, +} from '../../../transformation/pureProtocol/serializationHelpers/V1_TypeSerializationHelper.js'; export class V1_RelationTypeColumn implements Hashable { name!: string; - type!: string; + genericType!: V1_GenericType; static readonly serialization = new SerializationFactory( createModelSchema(V1_RelationTypeColumn, { name: primitive(), - type: primitive(), + genericType: custom( + (val) => serialize(V1_GenericTypeModelSchema, val), + (val) => V1_deserializeGenericType(val), + { + beforeDeserialize: function (callback, jsonValue, jsonParentValue) { + /** @backwardCompatibility */ + if ( + jsonParentValue.type !== undefined && + jsonParentValue.genericType === undefined + ) { + callback(null, jsonParentValue.type); + } else { + callback(null, jsonParentValue.genericType); + } + }, + }, + ), }), ); get hashCode(): string { - return hashArray([CORE_HASH_STRUCTURE.RELATION_TYPE, this.name, this.type]); + return hashArray([ + CORE_HASH_STRUCTURE.RELATION_TYPE, + this.name, + this.genericType, + ]); } } diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/from/V1_ValueSpecificationTransformer.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/from/V1_ValueSpecificationTransformer.ts index 9c41566555..0f4a94b735 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/from/V1_ValueSpecificationTransformer.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/from/V1_ValueSpecificationTransformer.ts @@ -89,7 +89,7 @@ import { V1_CByteArray } from '../../../model/valueSpecification/raw/V1_CByteArr import type { ColSpecArrayInstance } from '../../../../../../../graph/metamodel/pure/valueSpecification/RelationValueSpecification.js'; import { V1_ColSpecArray } from '../../../model/valueSpecification/raw/classInstance/relation/V1_ColSpecArray.js'; import { V1_ColSpec } from '../../../model/valueSpecification/raw/classInstance/relation/V1_ColSpec.js'; -import { Relation_RelationalColumn } from '../../../../../../../graph/metamodel/pure/packageableElements/relation/Relation_RelationType.js'; +import { RelationColumn } from '../../../../../../../graph/metamodel/pure/packageableElements/relation/RelationType.js'; import { V1_createGenericTypeWithElementPath } from '../../../helpers/V1_DomainHelper.js'; class V1_ValueSpecificationTransformer @@ -134,7 +134,7 @@ class V1_ValueSpecificationTransformer valueSpecification: FunctionExpression, ): V1_ValueSpecification { // handle relational column - if (valueSpecification.func instanceof Relation_RelationalColumn) { + if (valueSpecification.func instanceof RelationColumn) { const _property = new V1_AppliedProperty(); _property.property = valueSpecification.func.name; _property.parameters = valueSpecification.parametersValues.map((value) => diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_ValueSpecificationBuilderHelper.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_ValueSpecificationBuilderHelper.ts index fcfe03f72a..7ae250b79b 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_ValueSpecificationBuilderHelper.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_ValueSpecificationBuilderHelper.ts @@ -109,7 +109,7 @@ import { import { V1_SubTypeGraphFetchTree } from '../../../../model/valueSpecification/raw/classInstance/graph/V1_SubTypeGraphFetchTree.js'; import { findMappingLocalProperty } from '../../../../../../../../graph/helpers/DSL_Mapping_Helper.js'; import { getRelationTypeGenericType } from '../../../../../../../../graph/helpers/ValueSpecificationHelper.js'; -import { Relation_RelationType } from '../../../../../../../../graph/metamodel/pure/packageableElements/relation/Relation_RelationType.js'; +import { RelationType } from '../../../../../../../../graph/metamodel/pure/packageableElements/relation/RelationType.js'; import { V1_getGenericTypeFullPath, V1_createGenericTypeWithElementPath, @@ -585,7 +585,7 @@ export function V1_processProperty( EnumValueExplicitReference.create(getEnumValue(inferredType, property)), ]; return enumValueInstanceValue; - } else if (inferredType instanceof Relation_RelationType) { + } else if (inferredType instanceof RelationType) { const col = guaranteeNonNullable( inferredType.columns.find((e) => property === e.name), `Can't find property ${property} in relation`, diff --git a/packages/legend-graph/src/graph/helpers/ValueSpecificationHelper.ts b/packages/legend-graph/src/graph/helpers/ValueSpecificationHelper.ts index 29a578b7e9..e77b372ae7 100644 --- a/packages/legend-graph/src/graph/helpers/ValueSpecificationHelper.ts +++ b/packages/legend-graph/src/graph/helpers/ValueSpecificationHelper.ts @@ -27,9 +27,9 @@ import { } from '../metamodel/pure/valueSpecification/InstanceValue.js'; import { GenericType } from '../metamodel/pure/packageableElements/domain/GenericType.js'; import { PrimitiveType } from '../metamodel/pure/packageableElements/domain/PrimitiveType.js'; -import { Relation_Relation } from '../metamodel/pure/packageableElements/relation/Relation_Relation.js'; +import { Relation } from '../metamodel/pure/packageableElements/relation/Relation.js'; import { guaranteeNonNullable, guaranteeType } from '@finos/legend-shared'; -import { Relation_RelationType } from '../metamodel/pure/packageableElements/relation/Relation_RelationType.js'; +import { RelationType } from '../metamodel/pure/packageableElements/relation/RelationType.js'; import { AbstractPropertyExpression, SimpleFunctionExpression, @@ -45,7 +45,7 @@ const getRelationGenericType = ( val: ValueSpecification, ): GenericType | undefined => { const genType = val.genericType?.value; - if (genType?.rawType === Relation_Relation.INSTANCE) { + if (genType?.rawType === Relation.INSTANCE) { return genType; } return undefined; @@ -53,7 +53,7 @@ const getRelationGenericType = ( export const getRelationTypeGenericType = ( val: ValueSpecification, -): Relation_RelationType | undefined => { +): RelationType | undefined => { const relationGenType = getRelationGenericType(val); if (relationGenType) { const typeArg = guaranteeNonNullable( @@ -62,7 +62,7 @@ export const getRelationTypeGenericType = ( ); return guaranteeType( typeArg.value.rawType, - Relation_RelationType, + RelationType, 'Relation expected to have type arugments of type RelationType', ); } diff --git a/packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/Relation_Relation.ts b/packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/Relation.ts similarity index 95% rename from packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/Relation_Relation.ts rename to packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/Relation.ts index e204812ff9..8a077d4d86 100644 --- a/packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/Relation_Relation.ts +++ b/packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/Relation.ts @@ -18,6 +18,6 @@ import { Class } from '../domain/Class.js'; const RELATION_NAME = 'Relation'; -export class Relation_Relation { +export class Relation { static readonly INSTANCE = new Class(RELATION_NAME); } diff --git a/packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/Relation_RelationType.ts b/packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/RelationType.ts similarity index 88% rename from packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/Relation_RelationType.ts rename to packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/RelationType.ts index 490be8e162..bc0e80b05c 100644 --- a/packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/Relation_RelationType.ts +++ b/packages/legend-graph/src/graph/metamodel/pure/packageableElements/relation/RelationType.ts @@ -18,12 +18,14 @@ import { Type } from '../domain/Type.js'; import type { PackageableElementVisitor } from '../PackageableElement.js'; import { Function } from '../domain/Function.js'; -export class Relation_RelationalColumn extends Function { +export class RelationColumn extends Function { type: Type; + constructor(name: string, type: Type) { super(name); this.type = type; } + override accept_PackageableElementVisitor( visitor: PackageableElementVisitor, ): T { @@ -31,9 +33,9 @@ export class Relation_RelationalColumn extends Function { } } -export class Relation_RelationType extends Type { +export class RelationType extends Type { static ID = 'NO_ID'; - columns: Relation_RelationalColumn[] = []; + columns: RelationColumn[] = []; override accept_PackageableElementVisitor( visitor: PackageableElementVisitor, diff --git a/packages/legend-graph/src/index.ts b/packages/legend-graph/src/index.ts index 83352cbb13..8c95ca3443 100644 --- a/packages/legend-graph/src/index.ts +++ b/packages/legend-graph/src/index.ts @@ -597,11 +597,11 @@ export * from './graph-manager/extensions/DSL_Mapping_PureGraphManagerPlugin_Ext export { INTERNAL__UnknownSetImplementation } from './graph/metamodel/pure/packageableElements/mapping/INTERNAL__UnknownSetImplementation.js'; export { INTERNAL__UnknownPropertyMapping } from './graph/metamodel/pure/packageableElements/mapping/INTERNAL__UnknownPropertyMapping.js'; export { INTERNAL__UnknownConnection } from './graph/metamodel/pure/packageableElements/connection/INTERNAL__UnknownConnection.js'; -export { Relation_Relation } from './graph/metamodel/pure/packageableElements/relation/Relation_Relation.js'; +export { Relation } from './graph/metamodel/pure/packageableElements/relation/Relation.js'; export { - Relation_RelationType, - Relation_RelationalColumn, -} from './graph/metamodel/pure/packageableElements/relation/Relation_RelationType.js'; + RelationType, + RelationColumn, +} from './graph/metamodel/pure/packageableElements/relation/RelationType.js'; export { Store } from './graph/metamodel/pure/packageableElements/store/Store.js'; export { Mapping } from './graph/metamodel/pure/packageableElements/mapping/Mapping.js'; diff --git a/packages/legend-query-builder/src/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.ts b/packages/legend-query-builder/src/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.ts index d739e537fd..0409e6627c 100644 --- a/packages/legend-query-builder/src/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.ts +++ b/packages/legend-query-builder/src/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.ts @@ -63,10 +63,10 @@ import { ColSpecArrayInstance, ColSpecArray, ColSpec, - Relation_RelationType, - Relation_RelationalColumn, + RelationType, + RelationColumn, getValueSpecificationReturnType, - Relation_Relation, + Relation, } from '@finos/legend-graph'; import { QUERY_BUILDER_PURE_PATH, @@ -663,7 +663,7 @@ const V1_buildTypedProjectFunctionExpression = ( const processedExpression = new ColSpecArrayInstance(Multiplicity.ONE); const processedColSpecArray = new ColSpecArray(); processedExpression.values = [processedColSpecArray]; - const relationType = new Relation_RelationType(Relation_RelationType.ID); + const relationType = new RelationType(RelationType.ID); processedColSpecArray.colSpecs = specArray.colSpecs.map((colSpec) => { const pColSpec = new ColSpec(); let lambda: ValueSpecification; @@ -691,9 +691,7 @@ const V1_buildTypedProjectFunctionExpression = ( pColSpec.name = colSpec.name; const returnType = getValueSpecificationReturnType(lambda); if (returnType) { - relationType.columns.push( - new Relation_RelationalColumn(colSpec.name, returnType), - ); + relationType.columns.push(new RelationColumn(colSpec.name, returnType)); } else { throw new UnsupportedOperationError( 'Unable to get return type for current lambda', @@ -707,7 +705,7 @@ const V1_buildTypedProjectFunctionExpression = ( functionName, compileContext, ); - const relationGenericType = new GenericType(Relation_Relation.INSTANCE); + const relationGenericType = new GenericType(Relation.INSTANCE); const relationTypeGenericType = new GenericType(relationType); relationGenericType.typeArguments = [ GenericTypeExplicitReference.create(relationTypeGenericType), diff --git a/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeEngine.ts b/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeEngine.ts index 0a95e59001..c815a4ba1b 100644 --- a/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeEngine.ts +++ b/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeEngine.ts @@ -37,7 +37,7 @@ import { DataCubeSource, _function, DataCubeFunction, - type RelationType, + type DataCubeRelationType, type CompletionItem, _functionName, DataCubeQuery, @@ -71,6 +71,7 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { graphManagerState: GraphManagerState, ) { super(); + this.graphState = graphManagerState; this.selectInitialQuery = selectQuery; this.mappingPath = mappingPath; @@ -117,7 +118,7 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { if (this.runtimePath) { fromFuncExp.parameters.push(_elementPtr(this.runtimePath)); } - const columns = (await this.getRelationalType(this.selectInitialQuery)) + const columns = (await this.getRelationType(this.selectInitialQuery)) .columns; const query = new DataCubeQuery(); query.query = `~[${columns.map((e) => `'${e.name}'`)}]->select()`; @@ -132,7 +133,7 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { const srcFuncExp = this.getSourceFunctionExpression(); const source = new QueryBuilderDataCubeSource(); source.columns = ( - await this.getRelationalType(this.selectInitialQuery) + await this.getRelationType(this.selectInitialQuery) ).columns; source.mapping = this.mappingPath; source.runtime = this.runtimePath; @@ -185,7 +186,7 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { ); } - async getValueSpecificationCode( + override async getValueSpecificationCode( value: V1_ValueSpecification, pretty?: boolean | undefined, ) { @@ -195,7 +196,7 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { ); } - async getRelationalType(query: RawLambda): Promise { + async getRelationType(query: RawLambda) { const relationType = await this.graphState.graphManager.getLambdaRelationType( query, @@ -204,9 +205,12 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { return relationType; } - async getQueryRelationType(query: V1_Lambda, source: DataCubeSource) { + override async getQueryRelationType( + query: V1_Lambda, + source: DataCubeSource, + ) { const lambda = this.buildRawLambdaFromValueSpec(query); - return this.getRelationalType(lambda); + return this.getRelationType(lambda); } override async getQueryCodeRelationReturnType( @@ -219,7 +223,7 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { V1_serializeValueSpecification(baseQuery, []), ); const fullQuery = queryString + code; - return this.getRelationalType( + return this.getRelationType( await this.graphState.graphManager.pureCodeToLambda(fullQuery), ); } diff --git a/packages/legend-query-builder/src/stores/fetch-structure/tds/projection/QueryBuilderRelationProjectValueSpecBuidler.ts b/packages/legend-query-builder/src/stores/fetch-structure/tds/projection/QueryBuilderRelationProjectValueSpecBuidler.ts index 914b1abfa3..abe34fce45 100644 --- a/packages/legend-query-builder/src/stores/fetch-structure/tds/projection/QueryBuilderRelationProjectValueSpecBuidler.ts +++ b/packages/legend-query-builder/src/stores/fetch-structure/tds/projection/QueryBuilderRelationProjectValueSpecBuidler.ts @@ -28,9 +28,9 @@ import { V1_GraphTransformerContextBuilder, GenericType, GenericTypeExplicitReference, - Relation_Relation, - Relation_RelationalColumn, - Relation_RelationType, + Relation, + RelationColumn, + RelationType, } from '@finos/legend-graph'; import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../../../graph/QueryBuilderMetaModelConst.js'; import { @@ -64,7 +64,7 @@ export const buildRelationProjection = ( const colSepcArray = new ColSpecArray(); instanceVal.values = [colSepcArray]; - const relationType = new Relation_RelationType(Relation_RelationType.ID); + const relationType = new RelationType(RelationType.ID); tdsState.projectionColumns.forEach((projectionColumnState) => { const colSpec = new ColSpec(); @@ -118,14 +118,11 @@ export const buildRelationProjection = ( `Can't create value spec for projection column ${projectionColumnState.columnName}`, ); relationType.columns.push( - new Relation_RelationalColumn( - projectionColumnState.columnName, - returnType, - ), + new RelationColumn(projectionColumnState.columnName, returnType), ); }); projectFunction.parametersValues = [precedingExpression, instanceVal]; - const relationGenericType = new GenericType(Relation_Relation.INSTANCE); + const relationGenericType = new GenericType(Relation.INSTANCE); const relationTypeGenericType = new GenericType(relationType); relationGenericType.typeArguments = [ GenericTypeExplicitReference.create(relationTypeGenericType), diff --git a/packages/legend-vscode-extension-dependencies/src/index.ts b/packages/legend-vscode-extension-dependencies/src/index.ts index a11c733dc3..9e7f91d5b1 100644 --- a/packages/legend-vscode-extension-dependencies/src/index.ts +++ b/packages/legend-vscode-extension-dependencies/src/index.ts @@ -294,7 +294,7 @@ export { type DataCubeAPI, type DataCubeConfiguration, type DataCubeExecutionResult, - type RelationType, + type DataCubeRelationType, _elementPtr, _function, _functionName,