diff --git a/.changeset/clean-swans-pretend.md b/.changeset/clean-swans-pretend.md new file mode 100644 index 0000000000..358df64414 --- /dev/null +++ b/.changeset/clean-swans-pretend.md @@ -0,0 +1,14 @@ +--- +'@finos/legend-application-data-cube-deployment': patch +'@finos/legend-application-data-cube-bootstrap': patch +'@finos/legend-vscode-extension-dependencies': patch +'@finos/legend-application-data-cube': patch +'@finos/legend-application-pure-ide': patch +'@finos/legend-application-studio': patch +'@finos/legend-application-query': patch +'@finos/legend-application-repl': patch +'@finos/legend-query-builder': patch +'@finos/legend-application': patch +'@finos/legend-data-cube': patch +'@finos/legend-graph': patch +--- diff --git a/.changeset/loud-eagles-sip.md b/.changeset/loud-eagles-sip.md new file mode 100644 index 0000000000..019ddf6ea7 --- /dev/null +++ b/.changeset/loud-eagles-sip.md @@ -0,0 +1,12 @@ +--- +'@finos/legend-application-data-cube-deployment': patch +'@finos/legend-application-data-cube-bootstrap': patch +'@finos/legend-application-data-cube': patch +'@finos/legend-application-pure-ide': patch +'@finos/legend-application-studio': patch +'@finos/legend-application-query': patch +'@finos/legend-application-repl': patch +'@finos/legend-query-builder': patch +'@finos/legend-application': patch +'@finos/legend-data-cube': patch +--- diff --git a/packages/legend-application-data-cube-bootstrap/README.md b/packages/legend-application-data-cube-bootstrap/README.md index 0aa94a2e63..eace447700 100644 --- a/packages/legend-application-data-cube-bootstrap/README.md +++ b/packages/legend-application-data-cube-bootstrap/README.md @@ -1,3 +1,3 @@ # @finos/legend-application-data-cube-bootstrap -Legend Data Cube application bootstrap +Legend DataCube application bootstrap diff --git a/packages/legend-application-data-cube-bootstrap/package.json b/packages/legend-application-data-cube-bootstrap/package.json index 5995342aa0..fdf3c1792f 100644 --- a/packages/legend-application-data-cube-bootstrap/package.json +++ b/packages/legend-application-data-cube-bootstrap/package.json @@ -1,7 +1,7 @@ { "name": "@finos/legend-application-data-cube-bootstrap", "version": "12.87.0", - "description": "Legend Data Cube application bootstrap", + "description": "Legend DataCube application bootstrap", "keywords": [ "legend", "legend-application", @@ -46,6 +46,7 @@ "dependencies": { "@finos/legend-application": "workspace:*", "@finos/legend-application-data-cube": "workspace:*", + "@finos/legend-data-cube": "workspace:*", "@finos/legend-extension-dsl-data-space": "workspace:*", "@finos/legend-shared": "workspace:*", "@types/react": "19.0.2", diff --git a/packages/legend-application-data-cube-bootstrap/src/index.tsx b/packages/legend-application-data-cube-bootstrap/src/index.tsx index 6dd1490d58..f5d8c11597 100644 --- a/packages/legend-application-data-cube-bootstrap/src/index.tsx +++ b/packages/legend-application-data-cube-bootstrap/src/index.tsx @@ -39,7 +39,6 @@ export class LegendDataCubeWebApplication { .setup({ baseAddress: baseUrl }) .withPresets(LegendDataCubeWebApplication.getPresetCollection()) .withPlugins(LegendDataCubeWebApplication.getPluginCollection()) - .withDownloadHelper() .start() .catch((e: unknown) => { throw e; diff --git a/packages/legend-application-data-cube-bootstrap/style/index.scss b/packages/legend-application-data-cube-bootstrap/style/index.scss index 4ff7133b18..3101ddde56 100644 --- a/packages/legend-application-data-cube-bootstrap/style/index.scss +++ b/packages/legend-application-data-cube-bootstrap/style/index.scss @@ -14,36 +14,12 @@ * limitations under the License. */ -@import url('@finos/legend-art/lib/normalize.css'); -@import url('@finos/legend-art/lib/index.css'); -@import url('@finos/legend-application/lib/index.css'); -@import url('@finos/legend-lego/lib/index.css'); +@import url('@finos/legend-art/lib/fonts.css'); @import url('@finos/legend-data-cube/lib/index.css'); @import url('@finos/legend-application-data-cube/lib/index.css'); -@import url('@finos/legend-query-builder/lib/index.css'); -// NOTE: the following styles are temporary so we can have a poor-man version of -// theming for Legend Query. The reason why we put the code here is that this is -// where we essentially do all the overriding for everything from every extensions. -// In other words, this is the only place where we can exhaustively and correctly -// override native dark theme with light them colors. -:root { - --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; +html { + box-sizing: border-box; + font-family: Roboto, sans-serif; + overflow-y: hidden; } diff --git a/packages/legend-application-data-cube-bootstrap/tsconfig.build.json b/packages/legend-application-data-cube-bootstrap/tsconfig.build.json index 312991cabe..e0b410bbd6 100644 --- a/packages/legend-application-data-cube-bootstrap/tsconfig.build.json +++ b/packages/legend-application-data-cube-bootstrap/tsconfig.build.json @@ -7,6 +7,7 @@ "exclude": ["src/**/__tests__/**/*.*", "src/**/__mocks__/**/*.*"], "references": [ { "path": "../legend-shared/tsconfig.build.json" }, + { "path": "../legend-data-cube/tsconfig.build.json" }, { "path": "../legend-application/tsconfig.build.json" }, { "path": "../legend-application-data-cube/tsconfig.build.json" }, { "path": "../legend-extension-dsl-data-space/tsconfig.build.json" } diff --git a/packages/legend-application-data-cube-bootstrap/tsconfig.json b/packages/legend-application-data-cube-bootstrap/tsconfig.json index e21edf4216..c0c0e1d1c9 100644 --- a/packages/legend-application-data-cube-bootstrap/tsconfig.json +++ b/packages/legend-application-data-cube-bootstrap/tsconfig.json @@ -9,6 +9,7 @@ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.json"], "references": [ { "path": "../legend-shared" }, + { "path": "../legend-data-cube" }, { "path": "../legend-application" }, { "path": "../legend-application-data-cube" }, { "path": "../legend-extension-dsl-data-space" } diff --git a/packages/legend-application-data-cube-deployment/README.md b/packages/legend-application-data-cube-deployment/README.md index 521823f092..2869a6c9d1 100644 --- a/packages/legend-application-data-cube-deployment/README.md +++ b/packages/legend-application-data-cube-deployment/README.md @@ -1,6 +1,6 @@ # @finos/legend-application-data-cube-deployment -This is the `Legend Data Cube` web application deployment. This is used for development locally and publishing of image [finos/legend-data-cube](https://hub.docker.com/r/finos/legend-data-cube) on [Docker Hub](https://hub.docker.com/). +This is the `Legend DataCube` web application deployment. This is used for development locally and publishing of image [finos/legend-data-cube](https://hub.docker.com/r/finos/legend-data-cube) on [Docker Hub](https://hub.docker.com/). ## Getting started diff --git a/packages/legend-application-data-cube-deployment/package.json b/packages/legend-application-data-cube-deployment/package.json index ff5aa17129..d7387f3ef2 100644 --- a/packages/legend-application-data-cube-deployment/package.json +++ b/packages/legend-application-data-cube-deployment/package.json @@ -2,7 +2,7 @@ "name": "@finos/legend-application-data-cube-deployment", "version": "12.87.0", "private": true, - "description": "Legend Data Cube web application deployment", + "description": "Legend DataCube web application deployment", "keywords": [ "legend", "legend-application", diff --git a/packages/legend-application-data-cube-deployment/src/index.html b/packages/legend-application-data-cube-deployment/src/index.html index 5496f5f907..4885d86929 100644 --- a/packages/legend-application-data-cube-deployment/src/index.html +++ b/packages/legend-application-data-cube-deployment/src/index.html @@ -1,7 +1,7 @@ - Legend Data Cube + ⊞ Legend DataCube { - return generatePath(LEGEND_DATA_CUBE_ROUTE_PATTERN.VIEW_EXISTING_QUERY, { + return generatePath(LEGEND_DATA_CUBE_ROUTE_PATTERN.EDIT_EXISTING_QUERY, { id, }); }; diff --git a/packages/legend-application-data-cube/src/application/LegendDataCube.tsx b/packages/legend-application-data-cube/src/application/LegendDataCube.tsx index 693c883e77..6581b455f9 100644 --- a/packages/legend-application-data-cube/src/application/LegendDataCube.tsx +++ b/packages/legend-application-data-cube/src/application/LegendDataCube.tsx @@ -55,6 +55,7 @@ export class LegendDataCube extends LegendApplication { ): Promise { return new LegendDataCubeApplicationConfig(input); } + async loadApplication( applicationStore: ApplicationStore< LegendApplicationConfig, diff --git a/packages/legend-application-data-cube/src/components/DataCubeEditor.tsx b/packages/legend-application-data-cube/src/components/DataCubeEditor.tsx deleted file mode 100644 index a09a73a890..0000000000 --- a/packages/legend-application-data-cube/src/components/DataCubeEditor.tsx +++ /dev/null @@ -1,190 +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 { - Dialog, - Modal, - ModalBody, - ModalFooter, - ModalFooterButton, - ModalHeader, - PanelListItem, - PanelLoadingIndicator, - QuestionIcon, - clsx, -} from '@finos/legend-art'; -import { useLegendDataCubeBaseStore } from './LegendDataCubeFrameworkProvider.js'; -import { DataCubeSourceEditor } from './source/DataCubeSourceEditor.js'; -import { useEffect, useRef, useState } from 'react'; -import { DataCube } from '@finos/legend-data-cube'; -import type { LegendDataCubeStore } from '../stores/LegendDataCubeEditorStore.js'; -import type { LegendCubeViewer } from '../stores/source/LegendCubeViewer.js'; -import { flowResult } from 'mobx'; - -const CreateQueryDialog = observer( - (props: { view: LegendCubeViewer; store: LegendDataCubeStore }) => { - const { store } = props; - const close = (): void => store.setSaveModal(false); - const [queryName, setQueryName] = useState(''); - const create = (): void => { - flowResult(store.saveQuery(queryName)).catch( - store.applicationStore.alertUnhandledError, - ); - }; - const isEmptyName = !queryName; - // name - const nameInputRef = useRef(null); - const setFocus = (): void => { - nameInputRef.current?.focus(); - }; - - const changeName: React.ChangeEventHandler = (event) => { - setQueryName(event.target.value); - }; - - useEffect(() => { - setTimeout(() => setFocus(), 1); - }, []); - return ( - - - - - - -
- -
-
-
- - - -
-
- ); - }, -); - -export const DataCubeEditor = observer(() => { - const dataCubeStore = useLegendDataCubeBaseStore(); - const sourceSelector = dataCubeStore.sourceSelector; - - useEffect(() => { - dataCubeStore.context.initialize(); - }, [dataCubeStore]); - return ( - <> -
-
-
-
-
-
-
Legend Data Cube
-
-
-
-
- -
-
-
-
-
- {/* {dataCubeStore.cubeViewer ? ( - <> -
-
- -
-
- -
-
- - ) : ( - <> -
sourceSelector.openModal()} - className="bg-white shadow" - > -
-
- - Add Source -
-
-
- - )} */} -
- {sourceSelector.open && ( - - )} - {dataCubeStore.cubeViewer && dataCubeStore.saveModal && ( - - )} - - ); -}); diff --git a/packages/legend-application-data-cube/src/components/source/ExistingDataCubeQuery.tsx b/packages/legend-application-data-cube/src/components/ExistingDataCubeQueryEditor.tsx similarity index 82% rename from packages/legend-application-data-cube/src/components/source/ExistingDataCubeQuery.tsx rename to packages/legend-application-data-cube/src/components/ExistingDataCubeQueryEditor.tsx index 2ac4383098..39c9e6ea8e 100644 --- a/packages/legend-application-data-cube/src/components/source/ExistingDataCubeQuery.tsx +++ b/packages/legend-application-data-cube/src/components/ExistingDataCubeQueryEditor.tsx @@ -15,7 +15,7 @@ */ import { observer } from 'mobx-react-lite'; -import { useLegendDataCubeBaseStore } from '../LegendDataCubeFrameworkProvider.js'; +import { useLegendDataCubeBaseStore } from './LegendDataCubeFrameworkProvider.js'; import { useEffect } from 'react'; import { QuestionIcon } from '@finos/legend-art'; import { useParams } from '@finos/legend-application/browser'; @@ -23,22 +23,22 @@ import { DataCube } from '@finos/legend-data-cube'; import { guaranteeNonNullable } from '@finos/legend-shared'; import { LEGEND_DATA_CUBE_ROUTE_PATTERN_TOKEN, - type ExistingDataCubeViewerPathParams, -} from '../../__lib__/LegendDataCubeNavigation.js'; + type EditExistingQueryPathParams, +} from '../__lib__/LegendDataCubeNavigation.js'; import { flowResult } from 'mobx'; -export const ExistingDataCubeQuery = observer(() => { +export const ExistingDataCubeQueryEditor = observer(() => { const dataCubeStore = useLegendDataCubeBaseStore(); - const params = useParams(); - const sourceSelector = dataCubeStore.sourceSelector; - const queryId = guaranteeNonNullable( - params[LEGEND_DATA_CUBE_ROUTE_PATTERN_TOKEN.DATA_CUBE_QUERY_ID], - ); - useEffect(() => { - flowResult(dataCubeStore.initialize(queryId)).catch( - dataCubeStore.applicationStore.alertUnhandledError, - ); - }, [dataCubeStore, queryId]); + const params = useParams(); + // const sourceSelector = dataCubeStore.sourceSelector; + // const queryId = guaranteeNonNullable( + // params[LEGEND_DATA_CUBE_ROUTE_PATTERN_TOKEN.QUERY_ID], + // ); + // useEffect(() => { + // flowResult(dataCubeStore.initialize(queryId)).catch( + // dataCubeStore.application.alertUnhandledError, + // ); + // }, [dataCubeStore, queryId]); return ( <> @@ -48,7 +48,7 @@ export const ExistingDataCubeQuery = observer(() => {
-
Legend Data Cube
+
Legend DataCube
diff --git a/packages/legend-application-data-cube/src/components/LegendDataCubeFrameworkProvider.tsx b/packages/legend-application-data-cube/src/components/LegendDataCubeFrameworkProvider.tsx index a2e6f5ffff..79d20298bd 100644 --- a/packages/legend-application-data-cube/src/components/LegendDataCubeFrameworkProvider.tsx +++ b/packages/legend-application-data-cube/src/components/LegendDataCubeFrameworkProvider.tsx @@ -24,7 +24,7 @@ import { } from '@finos/legend-application'; import type { LegendDataCubeApplicationConfig } from '../application/LegendDataCubeApplicationConfig.js'; import type { LegendDataCubePluginManager } from '../application/LegendDataCubePluginManager.js'; -import { LegendDataCubeStore } from '../stores/LegendDataCubeEditorStore.js'; +import { LegendDataCubeBaseStore } from '../stores/LegendDataCubeBaseStore.js'; export const useLegendDataCubeApplicationStore = (): ApplicationStore< LegendDataCubeApplicationConfig, @@ -36,15 +36,15 @@ export const useLegendDataCubeApplicationStore = (): ApplicationStore< >(); const LegendDataCubeBaseStoreContext = createContext< - LegendDataCubeStore | undefined + LegendDataCubeBaseStore | undefined >(undefined); const LegendDataCubeBaseStoreProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { - const applicationStore = useLegendDataCubeApplicationStore(); + const application = useLegendDataCubeApplicationStore(); const store = useLocalObservable( - () => new LegendDataCubeStore(applicationStore), + () => new LegendDataCubeBaseStore(application), ); return ( @@ -53,16 +53,16 @@ const LegendDataCubeBaseStoreProvider: React.FC<{ ); }; -export const useLegendDataCubeBaseStore = (): LegendDataCubeStore => +export const useLegendDataCubeBaseStore = (): LegendDataCubeBaseStore => guaranteeNonNullable( useContext(LegendDataCubeBaseStoreContext), - `Can't find Legend Data Cube base store in context`, + `Can't find Legend DataCube base store in context`, ); export const LegendDataCubeFrameworkProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => ( - + {children} diff --git a/packages/legend-application-data-cube/src/components/LegendDataCubeLandingPage.tsx b/packages/legend-application-data-cube/src/components/LegendDataCubeLandingPage.tsx new file mode 100644 index 0000000000..fc71ac6678 --- /dev/null +++ b/packages/legend-application-data-cube/src/components/LegendDataCubeLandingPage.tsx @@ -0,0 +1,338 @@ +/** + * 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, useLocalObservable } from 'mobx-react-lite'; +import { useLegendDataCubeBaseStore } from './LegendDataCubeFrameworkProvider.js'; +import { createContext, useContext } from 'react'; +import { + DataCube, + DataCubeSettingKey, + type DataCubeState, +} from '@finos/legend-data-cube'; +import { formatDate, guaranteeNonNullable } from '@finos/legend-shared'; +import { LegendDataCubeLandingPageStore } from '../stores/LegendDataCubeLandingPageStore.js'; +import { + DataCubeIcon, + DropdownMenu, + DropdownMenuItem, + useDropdownMenu, +} from '@finos/legend-art'; + +// const CreateQueryDialog = observer( +// (props: { view: LegendCubeViewer; store: LegendDataCubeBaseStore }) => { +// const { store } = props; +// const close = (): void => store.setSaveModal(false); +// const [queryName, setQueryName] = useState(''); +// const create = (): void => { +// flowResult(store.saveQuery(queryName)).catch( +// store.application.alertUnhandledError, +// ); +// }; +// const isEmptyName = !queryName; +// // name +// const nameInputRef = useRef(null); +// const setFocus = (): void => { +// nameInputRef.current?.focus(); +// }; + +// const changeName: React.ChangeEventHandler = (event) => { +// setQueryName(event.target.value); +// }; + +// useEffect(() => { +// setTimeout(() => setFocus(), 1); +// }, []); +// return ( +// +// +// +// +// +// +//
+// +//
+//
+//
+// +// +// +//
+//
+// ); +// }, +// ); + +// 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); + +const LegendDataCubeLandingPageStoreProvider = (props: { + children: React.ReactNode; +}) => { + const { children } = props; + const baseStore = useLegendDataCubeBaseStore(); + const store = useLocalObservable( + () => new LegendDataCubeLandingPageStore(baseStore), + ); + return ( + + {children} + + ); +}; + +const useLegendDataCubeLandingPageStore = () => + guaranteeNonNullable( + useContext(LegendDataCubeLandingPageStoreContext), + `Can't find editor store in context`, + ); + +const withLegendDataCubeLandingPageStore = (WrappedComponent: React.FC) => + function WithLegendDataCubeLandingPageStore() { + return ( + + + + ); + }; + +const LegendDataCubeHeader = observer((props: { dataCube: DataCubeState }) => { + return null; +}); + +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 ( + ( + + ), + }} + /> + ); + }), +); diff --git a/packages/legend-application-data-cube/src/components/LegendDataCubeWebApplication.tsx b/packages/legend-application-data-cube/src/components/LegendDataCubeWebApplication.tsx index a9fff1608d..e50b54033f 100644 --- a/packages/legend-application-data-cube/src/components/LegendDataCubeWebApplication.tsx +++ b/packages/legend-application-data-cube/src/components/LegendDataCubeWebApplication.tsx @@ -14,24 +14,62 @@ * limitations under the License. */ -import { BrowserEnvironmentProvider } from '@finos/legend-application'; +import { + APPLICATION_EVENT, + BrowserEnvironmentProvider, + useApplicationStore, +} from '@finos/legend-application'; import { Route, Routes } from '@finos/legend-application/browser'; -import { LegendDataCubeFrameworkProvider } from './LegendDataCubeFrameworkProvider.js'; +import { + LegendDataCubeFrameworkProvider, + useLegendDataCubeBaseStore, +} from './LegendDataCubeFrameworkProvider.js'; import { observer } from 'mobx-react-lite'; -import { DataCubeEditor } from './DataCubeEditor.js'; -import { ExistingDataCubeQuery } from './source/ExistingDataCubeQuery.js'; +import { LegendDataCubeLandingPage } from './LegendDataCubeLandingPage.js'; +import { ExistingDataCubeQueryEditor } from './ExistingDataCubeQueryEditor.js'; import { LEGEND_DATA_CUBE_ROUTE_PATTERN } from '../__lib__/LegendDataCubeNavigation.js'; +import { LogEvent } from '@finos/legend-shared'; +import { useEffect } from 'react'; const LegendDataCubeWebApplicationRouter = observer(() => { + const application = useApplicationStore(); + const store = useLegendDataCubeBaseStore(); + + useEffect(() => { + store + .initialize() + .catch((error) => store.application.alertUnhandledError(error)); + }, [store]); + + useEffect(() => { + application.navigationService.navigator.blockNavigation( + // Only block navigation in production + // eslint-disable-next-line no-process-env + [() => process.env.NODE_ENV === 'production'], + undefined, + () => { + application.logService.warn( + LogEvent.create(APPLICATION_EVENT.NAVIGATION_BLOCKED), + `Navigation from the application is blocked`, + ); + }, + ); + return (): void => { + application.navigationService.navigator.unblockNavigation(); + }; + }, [application]); + return ( -
- - } - /> - } /> - +
+ {store.initState.hasSucceeded && ( + + } + /> + } /> + + )}
); }); diff --git a/packages/legend-application-data-cube/src/components/source/DataCubeSourceEditor.tsx b/packages/legend-application-data-cube/src/components/source/DataCubeSourceEditor.tsx index ea96ffe9a7..1239762798 100644 --- a/packages/legend-application-data-cube/src/components/source/DataCubeSourceEditor.tsx +++ b/packages/legend-application-data-cube/src/components/source/DataCubeSourceEditor.tsx @@ -27,9 +27,6 @@ import { import { SavedQuerySourceEditor } from './SavedQuerySourceEditor.js'; import { SavedQueryInputSourceState } from '../../stores/source/SavedQueryInputSourceState.js'; import { useLegendDataCubeBaseStore } from '../LegendDataCubeFrameworkProvider.js'; -import { flowResult } from 'mobx'; -import type { DataCubeEngine } from '@finos/legend-data-cube'; -import type { DataCubeGenericSource } from '../../stores/model/DataCubeGenericSource.js'; export const DataCubeSourceEditor = observer( (props: { sourceBuilder: LegendDataCubeSourceBuilder }) => { @@ -105,7 +102,7 @@ export const DataCubeSourceEditor = observer(
- + */}
diff --git a/packages/legend-application-data-cube/src/components/source/SavedQuerySourceEditor.tsx b/packages/legend-application-data-cube/src/components/source/SavedQuerySourceEditor.tsx index 4efdd00de3..3770f7b709 100644 --- a/packages/legend-application-data-cube/src/components/source/SavedQuerySourceEditor.tsx +++ b/packages/legend-application-data-cube/src/components/source/SavedQuerySourceEditor.tsx @@ -51,10 +51,11 @@ export const SavedQuerySourceEditor = observer(
) : ( - + <> + // )} ); diff --git a/packages/legend-application-data-cube/src/stores/LegendDataCubeBaseStore.ts b/packages/legend-application-data-cube/src/stores/LegendDataCubeBaseStore.ts new file mode 100644 index 0000000000..4e0234276c --- /dev/null +++ b/packages/legend-application-data-cube/src/stores/LegendDataCubeBaseStore.ts @@ -0,0 +1,125 @@ +/** + * 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 { + APPLICATION_EVENT, + DEFAULT_TAB_SIZE, + type ApplicationStore, +} from '@finos/legend-application'; +import type { LegendDataCubePluginManager } from '../application/LegendDataCubePluginManager.js'; +import { DepotServerClient } from '@finos/legend-server-depot'; +import type { LegendDataCubeApplicationConfig } from '../application/LegendDataCubeApplicationConfig.js'; +import { + getCurrentUserIDFromEngineServer, + GraphManagerState, +} from '@finos/legend-graph'; +import { + ActionState, + LogEvent, + assertErrorThrown, + guaranteeNonNullable, +} from '@finos/legend-shared'; +import { LegendDataCubeDataCubeEngine } from './LegendDataCubeDataCubeEngine.js'; + +export type LegendDataCubeApplicationStore = ApplicationStore< + LegendDataCubeApplicationConfig, + LegendDataCubePluginManager +>; + +declare const AG_GRID_LICENSE: string | undefined; + +export class LegendDataCubeBaseStore { + readonly application: LegendDataCubeApplicationStore; + readonly pluginManager: LegendDataCubePluginManager; + readonly depotServerClient: DepotServerClient; + readonly graphManagerState: GraphManagerState; + + readonly startTime = Date.now(); + readonly initState = ActionState.create(); + + private _engine?: LegendDataCubeDataCubeEngine | undefined; + gridClientLicense?: string | undefined; + + constructor(application: LegendDataCubeApplicationStore) { + this.application = application; + this.pluginManager = application.pluginManager; + this.depotServerClient = new DepotServerClient({ + serverUrl: this.application.config.depotServerUrl, + }); + this.depotServerClient.setTracerService(application.tracerService); + this.graphManagerState = new GraphManagerState( + this.application.pluginManager, + this.application.logService, + ); + } + + get engine(): LegendDataCubeDataCubeEngine { + return guaranteeNonNullable( + this._engine, + 'Engine has not been initialized', + ); + } + + async initialize() { + this.initState.inProgress(); + try { + this.application.identityService.setCurrentUser( + await getCurrentUserIDFromEngineServer( + this.application.config.engineServerUrl, + ), + ); + } catch (error) { + assertErrorThrown(error); + this.application.logService.error( + LogEvent.create(APPLICATION_EVENT.IDENTITY_AUTO_FETCH__FAILURE), + error, + ); + } + + this._engine = new LegendDataCubeDataCubeEngine( + this.application, + this.graphManagerState, + ); + + try { + this.gridClientLicense = AG_GRID_LICENSE; + + await this.graphManagerState.graphManager.initialize( + { + env: this.application.config.env, + tabSize: DEFAULT_TAB_SIZE, + clientConfig: { + baseUrl: this.application.config.engineServerUrl, + queryBaseUrl: this.application.config.engineQueryServerUrl, + enableCompression: true, + }, + }, + { + tracerService: this.application.tracerService, + }, + ); + this.initState.pass(); + } catch (error) { + assertErrorThrown(error); + this.application.logService.error( + LogEvent.create(APPLICATION_EVENT.APPLICATION_LOAD__FAILURE), + `Can't initialize Legend DataCube`, + error, + ); + this.initState.fail(); + } + } +} diff --git a/packages/legend-application-data-cube/src/stores/LegendDataCubeDataCubeEngine.ts b/packages/legend-application-data-cube/src/stores/LegendDataCubeDataCubeEngine.ts new file mode 100644 index 0000000000..c6c52e87e7 --- /dev/null +++ b/packages/legend-application-data-cube/src/stores/LegendDataCubeDataCubeEngine.ts @@ -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. + */ + +import { + SUPPORTED_FUNCTIONS, + V1_AppliedFunction, + V1_Lambda, + RawLambda, + RelationalExecutionActivities, + TDSExecutionResult, + V1_deserializeRawValueSpecification, + V1_deserializeValueSpecification, + V1_RawLambda, + V1_serializeValueSpecification, + type GraphManagerState, + type PureModel, + type V1_ValueSpecification, + type ParameterValue, + BasicGraphManagerState, + AbstractPureGraphManager, +} from '@finos/legend-graph'; +import { + _elementPtr, + _functionName, + DataCubeEngine, + DataCubeSource, + type RelationType, + DataCubeQuery, + type CompletionItem, + _function, + DataCubeFunction, +} from '@finos/legend-data-cube'; +import { + DocumentationEntry, + guaranteeType, + isNonNullable, + LogEvent, + LogService, + UnsupportedOperationError, + type PlainObject, +} from '@finos/legend-shared'; +import type { LegendDataCubeApplicationStore } from './LegendDataCubeBaseStore.js'; +import { + APPLICATION_EVENT, + shouldDisplayVirtualAssistantDocumentationEntry, +} from '@finos/legend-application'; + +class QueryBuilderDataCubeSource extends DataCubeSource { + mapping?: string | undefined; + runtime!: string; +} + +export class LegendDataCubeDataCubeEngine extends DataCubeEngine { + readonly application: LegendDataCubeApplicationStore; + readonly graphManagerState: GraphManagerState; + readonly graphManager: AbstractPureGraphManager; + readonly graph: PureModel; + // readonly logService = new LogService(); + // readonly graphState: GraphManagerState; + // readonly selectInitialQuery: RawLambda; + // readonly mappingPath: string | undefined; + // readonly parameterValues: ParameterValue[] | undefined; + // readonly runtimePath: string; + // _parameters: object | undefined; + + constructor( + application: LegendDataCubeApplicationStore, + graphManagerState: GraphManagerState, + ) { + super(); + + this.application = application; + this.graphManagerState = graphManagerState; + this.graphManager = graphManagerState.graphManager; + this.graph = graphManagerState.graph; + } + + // ---------------------------------- IMPLEMENTATION ---------------------------------- + + // constructor( + // selectQuery: RawLambda, + // parameterValues: ParameterValue[] | undefined, + // mappingPath: string | undefined, + // runtimePath: string, + // graphManagerState: GraphManagerState, + // ) { + // super(); + // this.graphState = graphManagerState; + // this.selectInitialQuery = selectQuery; + // this.mappingPath = mappingPath; + // this.runtimePath = runtimePath; + // this.parameterValues = parameterValues; + // } + + // get sourceLabel(): string { + // return `Query Builder Report`; + // } + + // get graph(): PureModel { + // return this.graphState.graph; + // } + + // private getSourceFunctionExpression() { + // let srcFuncExp = V1_deserializeValueSpecification( + // this.graphManager.serializeRawValueSpecification( + // this.selectInitialQuery, + // ), + // [], + // ); + // // We could do a further check here to ensure the experssion is an applied funciton + // // this is because data cube expects an expression to be able to built further upon the queery + // if ( + // srcFuncExp instanceof V1_Lambda && + // srcFuncExp.body.length === 1 && + // srcFuncExp.body[0] + // ) { + // srcFuncExp = srcFuncExp.body[0]; + // } + // return srcFuncExp; + // } + + // async getBaseQuery() { + // const srcFuncExp = this.getSourceFunctionExpression(); + // this._parameters = this.selectInitialQuery.parameters; + // const fromFuncExp = new V1_AppliedFunction(); + // fromFuncExp.function = _functionName(SUPPORTED_FUNCTIONS.FROM); + // fromFuncExp.parameters = [srcFuncExp]; + // if (this.mappingPath) { + // fromFuncExp.parameters.push(_elementPtr(this.mappingPath)); + // } + // if (this.runtimePath) { + // fromFuncExp.parameters.push(_elementPtr(this.runtimePath)); + // } + // const columns = (await this.getRelationalType(this.selectInitialQuery)) + // .columns; + // const query = new DataCubeQuery(); + // query.query = `~[${columns.map((e) => `'${e.name}'`)}]->select()`; + + // return query; + // } + + private buildRawLambdaFromValueSpec(query: V1_Lambda): RawLambda { + const json = guaranteeType( + V1_deserializeRawValueSpecification( + V1_serializeValueSpecification(query, []), + ), + V1_RawLambda, + ); + return new RawLambda(json.parameters, json.body); + } + + private async getRelationalType(query: RawLambda): Promise { + const relationType = await this.graphManager.getLambdaRelationType( + query, + this.graph, + ); + return relationType; + } + + override async processQuerySource( + value: PlainObject, + ): Promise { + switch (value._type) { + default: + throw new UnsupportedOperationError( + `Can't process query source of type '${value._type}'`, + ); + } + } + + override async getQueryTypeahead( + code: string, + baseQuery: V1_Lambda, + source: DataCubeSource, + ) { + const lambda = this.buildRawLambdaFromValueSpec(baseQuery); + const queryString = await this.graphManager.lambdaToPureCode(lambda); + let codeBlock = queryString + code; + if (codeBlock[0] === '|') { + codeBlock = codeBlock.substring(1); + } + const result = await this.graphManager.getCodeComplete( + codeBlock, + this.graph, + undefined, + ); + return result.completions as CompletionItem[]; + } + + override async parseValueSpecification( + code: string, + returnSourceInformation?: boolean, + ) { + return V1_deserializeValueSpecification( + await this.graphManager.pureCodeToValueSpecification( + code, + returnSourceInformation, + ), + [], + ); + } + + override async getValueSpecificationCode( + value: V1_ValueSpecification, + pretty?: boolean | undefined, + ) { + return this.graphManager.valueSpecificationToPureCode( + V1_serializeValueSpecification(value, []), + pretty, + ); + } + + override async getQueryRelationType( + query: V1_Lambda, + source: DataCubeSource, + ) { + const lambda = this.buildRawLambdaFromValueSpec(query); + return this.getRelationalType(lambda); + } + + override async getQueryCodeRelationReturnType( + code: string, + baseQuery: V1_ValueSpecification, + source: DataCubeSource, + ) { + const queryString = await this.graphManager.valueSpecificationToPureCode( + V1_serializeValueSpecification(baseQuery, []), + ); + const fullQuery = queryString + code; + return this.getRelationalType( + await this.graphManager.pureCodeToLambda(fullQuery), + ); + } + + override async executeQuery(query: V1_Lambda, source: DataCubeSource) { + const lambda = this.buildRawLambdaFromValueSpec(query); + // lambda.parameters = this._parameters; + const [executionWithMetadata, queryString] = await Promise.all([ + this.graphManager.runQuery(lambda, undefined, undefined, this.graph, { + // parameterValues: this.parameterValues ?? [], + }), + this.graphManager.lambdaToPureCode(lambda), + ]); + const expectedTDS = guaranteeType( + executionWithMetadata.executionResult, + TDSExecutionResult, + 'Query returned expected to be of tabular data set', + ); + const sql = + expectedTDS.activities?.[0] instanceof RelationalExecutionActivities + ? expectedTDS.activities[0].sql + : undefined; + if (!sql) { + throw new Error(`Can't generate SQL for query`); + } + return { + result: expectedTDS, + executedQuery: queryString, + executedSQL: sql, + }; + } + + override buildExecutionContext(source: DataCubeSource) { + if (source instanceof QueryBuilderDataCubeSource) { + return _function( + DataCubeFunction.FROM, + [ + source.mapping ? _elementPtr(source.mapping) : undefined, + _elementPtr(source.runtime), + ].filter(isNonNullable), + ); + } + return undefined; + } + + // ---------------------------------- APPLICATION ---------------------------------- + + override getDocumentationURL(): string | undefined { + return this.application.documentationService.url; + } + + override getDocumentationEntry(key: string) { + return this.application.documentationService.getDocEntry(key); + } + + override shouldDisplayDocumentationEntry(entry: DocumentationEntry) { + return shouldDisplayVirtualAssistantDocumentationEntry(entry); + } + + override openLink(url: string) { + this.application.navigationService.navigator.visitAddress(url); + } + + override sendTelemetry(event: string, data: PlainObject) { + this.application.telemetryService.logEvent(event, data); + } + + override logDebug(message: string, ...data: unknown[]) { + this.application.logService.debug( + LogEvent.create(APPLICATION_EVENT.DEBUG), + message, + ...data, + ); + } + + override debugProcess(processName: string, ...data: [string, unknown][]) { + this.application.logService.debug( + LogEvent.create(APPLICATION_EVENT.DEBUG), + `\n------ START DEBUG PROCESS: ${processName} ------`, + ...data.flatMap(([key, value]) => [`\n[${key.toUpperCase()}]:`, value]), + `\n------- END DEBUG PROCESS: ${processName} -------\n\n`, + ); + } + + override logInfo(event: LogEvent, ...data: unknown[]) { + this.application.logService.info(event, ...data); + } + + override logWarning(event: LogEvent, ...data: unknown[]) { + this.application.logService.warn(event, ...data); + } + + override logError(event: LogEvent, ...data: unknown[]) { + this.application.logService.error(event, ...data); + } + + override logUnhandledError(error: Error) { + this.application.logUnhandledError(error); + } + + override logIllegalStateError(message: string, error?: Error) { + this.logError( + LogEvent.create(APPLICATION_EVENT.ILLEGAL_APPLICATION_STATE_OCCURRED), + message, + error, + ); + } +} diff --git a/packages/legend-application-data-cube/src/stores/LegendDataCubeEditorStore.ts b/packages/legend-application-data-cube/src/stores/LegendDataCubeEditorStore.ts deleted file mode 100644 index 4406459ff4..0000000000 --- a/packages/legend-application-data-cube/src/stores/LegendDataCubeEditorStore.ts +++ /dev/null @@ -1,237 +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 { - DEFAULT_TAB_SIZE, - type ApplicationStore, -} from '@finos/legend-application'; -import type { LegendDataCubePluginManager } from '../application/LegendDataCubePluginManager.js'; -import { DepotServerClient, resolveVersion } from '@finos/legend-server-depot'; -import type { LegendDataCubeApplicationConfig } from '../application/LegendDataCubeApplicationConfig.js'; -import { - GraphManagerState, - LegendSDLC, - PersistentDataCubeQuery, - type QueryInfo, - type RawLambda, -} from '@finos/legend-graph'; -import { LegendDataCubeSourceBuilder } from './source/LegendDataCubeSourceBuilder.js'; -import { - ActionState, - UnsupportedOperationError, - assertErrorThrown, - guaranteeNonNullable, - uuid, - type GeneratorFn, -} from '@finos/legend-shared'; -import { action, flow, flowResult, makeObservable, observable } from 'mobx'; -import { LegendCubeViewer } from './source/LegendCubeViewer.js'; -import type { DataCubeEngine } from '@finos/legend-data-cube'; -import type { DataCubeGenericSource } from './model/DataCubeGenericSource.js'; -import { - createQueryBuilderContent, - deserializeDataCubeQueryConent, - serializeDataCubeQueryConent, -} from './model/DataCubeGenericSourceHelper.js'; -import { LegendSavedQuerySource } from './model/LegendSavedQuerySource.js'; -import { LegendExecutionDataCubeEngine } from './engine/LegendExecutionDataCubeEngine.js'; -import { generatedSavedQueryUrl } from '../__lib__/LegendDataCubeNavigation.js'; - -export type LegendDataCubeApplicationStore = ApplicationStore< - LegendDataCubeApplicationConfig, - LegendDataCubePluginManager ->; - -export class LegendDataCubeStoreContext { - readonly applicationStore: LegendDataCubeApplicationStore; - readonly depotServerClient: DepotServerClient; - readonly graphManagerState: GraphManagerState; - initState = ActionState.create(); - - constructor(applicationStore: LegendDataCubeApplicationStore) { - makeObservable(this, { - initialize: flow, - initState: observable, - }); - // server - this.depotServerClient = new DepotServerClient({ - serverUrl: applicationStore.config.depotServerUrl, - }); - this.depotServerClient.setTracerService(applicationStore.tracerService); - this.graphManagerState = new GraphManagerState( - applicationStore.pluginManager, - applicationStore.logService, - ); - this.applicationStore = applicationStore; - } - - *initialize(): GeneratorFn { - if (!this.initState.isInInitialState) { - return; - } - - try { - this.initState.inProgress(); - // TODO: when we genericize the way to initialize an application page - this.applicationStore.assistantService.setIsHidden(true); - - // initialize the graph manager - yield this.graphManagerState.graphManager.initialize( - { - env: this.applicationStore.config.env, - tabSize: DEFAULT_TAB_SIZE, - clientConfig: { - baseUrl: this.applicationStore.config.engineServerUrl, - queryBaseUrl: this.applicationStore.config.engineQueryServerUrl, - enableCompression: true, - }, - }, - { - tracerService: this.applicationStore.tracerService, - }, - ); - this.initState.pass(); - } catch (error) { - assertErrorThrown(error); - this.applicationStore.notificationService.notifyError(error); - this.initState.fail(); - } - } -} - -export class LegendDataCubeStore { - readonly applicationStore: LegendDataCubeApplicationStore; - readonly context: LegendDataCubeStoreContext; - readonly pluginManager: LegendDataCubePluginManager; - - sourceSelector: LegendDataCubeSourceBuilder; - cubeViewer: LegendCubeViewer | undefined; - saveModal = false; - saveModalState = ActionState.create(); - savedQuery: PersistentDataCubeQuery | undefined; - - constructor(applicationStore: LegendDataCubeApplicationStore) { - makeObservable(this, { - cubeViewer: observable, - sourceSelector: observable, - saveModal: observable, - setSaveModal: observable, - saveModalState: observable, - savedQuery: observable, - initializeView: action, - initialize: flow, - saveQuery: flow, - }); - this.applicationStore = applicationStore; - this.pluginManager = applicationStore.pluginManager; - this.context = new LegendDataCubeStoreContext(applicationStore); - this.sourceSelector = new LegendDataCubeSourceBuilder(this.context); - } - - setSaveModal(val: boolean): void { - this.saveModal = val; - } - - initializeView(source: DataCubeGenericSource, engine: DataCubeEngine): void { - this.cubeViewer = new LegendCubeViewer(source, engine); - } - - *initialize(id: string): GeneratorFn { - try { - yield flowResult(this.context.initialize()); - const query = - (yield this.context.graphManagerState.graphManager.getDataCubeQuery( - id, - )) as unknown as PersistentDataCubeQuery; - this.savedQuery = query; - const source = deserializeDataCubeQueryConent(query.content).source; - if (source instanceof LegendSavedQuerySource) { - const queryInfo = - (yield this.context.graphManagerState.graphManager.getQueryInfo( - source.id, - )) as unknown as QueryInfo; - const execConext = - (yield this.context.graphManagerState.graphManager.resolveQueryInfoExecutionContext( - queryInfo, - () => - this.context.depotServerClient.getVersionEntities( - queryInfo.groupId, - queryInfo.artifactId, - queryInfo.versionId, - ), - )) as { mapping: string | undefined; runtime: string }; - const lambda = - (yield this.context.graphManagerState.graphManager.pureCodeToLambda( - queryInfo.content, - )) as unknown as RawLambda; - this.context.graphManagerState.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 LegendExecutionDataCubeEngine( - lambda, - undefined, - execConext.mapping, - execConext.runtime, - this.context.graphManagerState, - ); - this.initializeView(source, engine); - } else { - throw new UnsupportedOperationError('not supported'); - } - } catch (error) { - assertErrorThrown(error); - this.applicationStore.notificationService.notifyError( - `Unable to initialie query with id '${id}'`, - ); - } - } - - *saveQuery(name: string): GeneratorFn { - try { - this.saveModalState.inProgress(); - const view = guaranteeNonNullable(this.cubeViewer); - const content = serializeDataCubeQueryConent( - createQueryBuilderContent(view.source), - ); - const cubeQuery = new PersistentDataCubeQuery(); - cubeQuery.content = content; - cubeQuery.name = name; - cubeQuery.id = uuid(); - const querySaved = - (yield this.context.graphManagerState.graphManager.createQueryDataCube( - cubeQuery, - )) as unknown as PersistentDataCubeQuery; - this.savedQuery = querySaved; - // TODO: fix reload - this.applicationStore.navigationService.navigator.goToLocation( - generatedSavedQueryUrl(querySaved.id), - ); - this.setSaveModal(false); - this.saveModalState.complete(); - } catch (error) { - assertErrorThrown(error); - this.saveModalState.fail(); - this.applicationStore.notificationService.notifyError( - `Unable to save query`, - ); - } - } -} diff --git a/packages/legend-application-data-cube/src/stores/model/LegendSavedQuerySource.ts b/packages/legend-application-data-cube/src/stores/LegendDataCubeExistingQueryEditorStore.ts similarity index 60% rename from packages/legend-application-data-cube/src/stores/model/LegendSavedQuerySource.ts rename to packages/legend-application-data-cube/src/stores/LegendDataCubeExistingQueryEditorStore.ts index 0b3351b58c..54d47a0ec6 100644 --- a/packages/legend-application-data-cube/src/stores/model/LegendSavedQuerySource.ts +++ b/packages/legend-application-data-cube/src/stores/LegendDataCubeExistingQueryEditorStore.ts @@ -14,13 +14,17 @@ * limitations under the License. */ -import { DataCubeGenericSource } from './DataCubeGenericSource.js'; +import type { + LegendDataCubeApplicationStore, + LegendDataCubeBaseStore, +} from './LegendDataCubeBaseStore.js'; -export class LegendSavedQuerySource extends DataCubeGenericSource { - id: string; +export class LegendDataCubeExistingQueryEditorStore { + readonly application: LegendDataCubeApplicationStore; + readonly baseStore: LegendDataCubeBaseStore; - constructor(id: string) { - super(); - this.id = id; + constructor(baseStore: LegendDataCubeBaseStore) { + this.application = baseStore.application; + this.baseStore = baseStore; } } diff --git a/packages/legend-application-data-cube/src/stores/LegendDataCubeLandingPageStore.ts b/packages/legend-application-data-cube/src/stores/LegendDataCubeLandingPageStore.ts new file mode 100644 index 0000000000..06fd15b830 --- /dev/null +++ b/packages/legend-application-data-cube/src/stores/LegendDataCubeLandingPageStore.ts @@ -0,0 +1,150 @@ +/** + * 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 type { + LegendDataCubeApplicationStore, + LegendDataCubeBaseStore, +} from './LegendDataCubeBaseStore.js'; +import { type DataCubeQuery } from '@finos/legend-data-cube'; + +export class LegendDataCubeLandingPageStore { + readonly application: LegendDataCubeApplicationStore; + readonly baseStore: LegendDataCubeBaseStore; + + query?: DataCubeQuery | undefined; + + constructor(baseStore: LegendDataCubeBaseStore) { + makeObservable(this, { + query: observable, + setQuery: action, + }); + + this.application = baseStore.application; + this.baseStore = baseStore; + } + + setQuery(val: DataCubeQuery | undefined): void { + this.query = val; + } +} + +// sourceSelector: LegendDataCubeSourceBuilder; +// cubeViewer: LegendCubeViewer | undefined; +// saveModal = false; +// saveModalState = ActionState.create(); +// savedQuery: PersistentDataCubeQuery | undefined; +// cubeViewer: observable, +// sourceSelector: observable, +// saveModal: observable, +// setSaveModal: observable, +// saveModalState: observable, +// savedQuery: observable, +// initializeView: action, +// initialize: flow, +// saveQuery: flow, + +// setSaveModal(val: boolean): void { +// this.saveModal = val; +// } + +// initializeView(source: DataCubeGenericSource, engine: DataCubeEngine): void { +// this.cubeViewer = new LegendCubeViewer(source, engine); +// } + +// *initialize(id: string): GeneratorFn { +// try { +// yield flowResult(this.context.initialize()); +// const query = +// (yield this.context.graphManagerState.graphManager.getDataCubeQuery( +// id, +// )) as unknown as PersistentDataCubeQuery; +// this.savedQuery = query; +// const source = deserializeDataCubeQueryConent(query.content).source; +// if (source instanceof LegendSavedQuerySource) { +// const queryInfo = +// (yield this.context.graphManagerState.graphManager.getQueryInfo( +// source.id, +// )) as unknown as QueryInfo; +// const execConext = +// (yield this.context.graphManagerState.graphManager.resolveQueryInfoExecutionContext( +// queryInfo, +// () => +// this.context.depotServerClient.getVersionEntities( +// queryInfo.groupId, +// queryInfo.artifactId, +// queryInfo.versionId, +// ), +// )) as { mapping: string | undefined; runtime: string }; +// const lambda = +// (yield this.context.graphManagerState.graphManager.pureCodeToLambda( +// queryInfo.content, +// )) as unknown as RawLambda; +// this.context.graphManagerState.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.graphManagerState, +// ); +// this.initializeView(source, engine); +// } else { +// throw new UnsupportedOperationError('not supported'); +// } +// } catch (error) { +// assertErrorThrown(error); +// this.application.notificationService.notifyError( +// `Unable to initialie query with id '${id}'`, +// ); +// } +// } + +// *saveQuery(name: string): GeneratorFn { +// try { +// this.saveModalState.inProgress(); +// const view = guaranteeNonNullable(this.cubeViewer); +// const content = serializeDataCubeQueryConent( +// createQueryBuilderContent(view.source), +// ); +// const cubeQuery = new PersistentDataCubeQuery(); +// cubeQuery.content = content; +// cubeQuery.name = name; +// cubeQuery.id = uuid(); +// const querySaved = +// (yield this.context.graphManagerState.graphManager.createQueryDataCube( +// cubeQuery, +// )) as unknown as PersistentDataCubeQuery; +// this.savedQuery = querySaved; +// // TODO: fix reload +// this.application.navigationService.navigator.goToLocation( +// generatedSavedQueryUrl(querySaved.id), +// ); +// this.setSaveModal(false); +// this.saveModalState.complete(); +// } catch (error) { +// assertErrorThrown(error); +// this.saveModalState.fail(); +// this.application.notificationService.notifyError(`Unable to save query`); +// } +// } diff --git a/packages/legend-application-data-cube/src/stores/engine/LegendExecutionDataCubeEngine.ts b/packages/legend-application-data-cube/src/stores/engine/LegendExecutionDataCubeEngine.ts deleted file mode 100644 index d2814b851c..0000000000 --- a/packages/legend-application-data-cube/src/stores/engine/LegendExecutionDataCubeEngine.ts +++ /dev/null @@ -1,267 +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 { - SUPPORTED_FUNCTIONS, - V1_AppliedFunction, - V1_Lambda, - RawLambda, - RelationalExecutionActivities, - TDSExecutionResult, - V1_deserializeRawValueSpecification, - V1_deserializeValueSpecification, - V1_RawLambda, - V1_serializeValueSpecification, - type GraphManagerState, - type PureModel, - type V1_ValueSpecification, - type ParameterValue, -} from '@finos/legend-graph'; -import { - _elementPtr, - _functionName, - DataCubeEngine, - DataCubeSource, - type RelationType, - DataCubeQuery, - type CompletionItem, - _function, - DataCubeFunction, -} from '@finos/legend-data-cube'; -import { - guaranteeType, - isNonNullable, - LogService, - type PlainObject, -} from '@finos/legend-shared'; - -class QueryBuilderDataCubeSource extends DataCubeSource { - mapping?: string | undefined; - runtime!: string; -} - -export class LegendExecutionDataCubeEngine extends DataCubeEngine { - readonly logService = new LogService(); - readonly graphState: GraphManagerState; - readonly selectInitialQuery: RawLambda; - readonly mappingPath: string | undefined; - readonly parameterValues: ParameterValue[] | undefined; - readonly runtimePath: string; - _parameters: object | undefined; - - constructor( - selectQuery: RawLambda, - parameterValues: ParameterValue[] | undefined, - mappingPath: string | undefined, - runtimePath: string, - graphManagerState: GraphManagerState, - ) { - super(); - this.graphState = graphManagerState; - this.selectInitialQuery = selectQuery; - this.mappingPath = mappingPath; - this.runtimePath = runtimePath; - this.parameterValues = parameterValues; - } - - get sourceLabel(): string { - return `Query Builder Report`; - } - - get graph(): PureModel { - return this.graphState.graph; - } - - private getSourceFunctionExpression() { - let srcFuncExp = V1_deserializeValueSpecification( - this.graphState.graphManager.serializeRawValueSpecification( - this.selectInitialQuery, - ), - [], - ); - // We could do a further check here to ensure the experssion is an applied funciton - // this is because data cube expects an expression to be able to built further upon the queery - if ( - srcFuncExp instanceof V1_Lambda && - srcFuncExp.body.length === 1 && - srcFuncExp.body[0] - ) { - srcFuncExp = srcFuncExp.body[0]; - } - return srcFuncExp; - } - - async getBaseQuery() { - const srcFuncExp = this.getSourceFunctionExpression(); - this._parameters = this.selectInitialQuery.parameters; - const fromFuncExp = new V1_AppliedFunction(); - fromFuncExp.function = _functionName(SUPPORTED_FUNCTIONS.FROM); - fromFuncExp.parameters = [srcFuncExp]; - if (this.mappingPath) { - fromFuncExp.parameters.push(_elementPtr(this.mappingPath)); - } - if (this.runtimePath) { - fromFuncExp.parameters.push(_elementPtr(this.runtimePath)); - } - const columns = (await this.getRelationalType(this.selectInitialQuery)) - .columns; - const query = new DataCubeQuery(); - query.query = `~[${columns.map((e) => `'${e.name}'`)}]->select()`; - - return query; - } - - async processQuerySource(value: PlainObject) { - const srcFuncExp = this.getSourceFunctionExpression(); - const columns = (await this.getRelationalType(this.selectInitialQuery)) - .columns; - const source = new QueryBuilderDataCubeSource(); - source.columns = columns; - source.mapping = this.mappingPath; - source.runtime = this.runtimePath; - source.query = srcFuncExp; - return source; - } - - private buildRawLambdaFromValueSpec(query: V1_Lambda): RawLambda { - const json = guaranteeType( - V1_deserializeRawValueSpecification( - V1_serializeValueSpecification(query, []), - ), - V1_RawLambda, - ); - return new RawLambda(json.parameters, json.body); - } - - async getQueryTypeahead( - code: string, - baseQuery: V1_Lambda, - source: DataCubeSource, - ) { - const lambda = this.buildRawLambdaFromValueSpec(baseQuery); - const queryString = - await this.graphState.graphManager.lambdaToPureCode(lambda); - let codeBlock = queryString + code; - if (codeBlock[0] === '|') { - codeBlock = codeBlock.substring(1); - } - const result = await this.graphState.graphManager.getCodeComplete( - codeBlock, - this.graph, - undefined, - ); - return result.completions as CompletionItem[]; - } - - async parseValueSpecification( - code: string, - returnSourceInformation?: boolean, - ) { - return V1_deserializeValueSpecification( - await this.graphState.graphManager.pureCodeToValueSpecification( - code, - returnSourceInformation, - ), - [], - ); - } - - async getValueSpecificationCode( - value: V1_ValueSpecification, - pretty?: boolean | undefined, - ) { - return this.graphState.graphManager.valueSpecificationToPureCode( - V1_serializeValueSpecification(value, []), - pretty, - ); - } - - private async getRelationalType(query: RawLambda): Promise { - const relationType = - await this.graphState.graphManager.getLambdaRelationType( - query, - this.graph, - ); - return relationType; - } - - async getQueryRelationType(query: V1_Lambda, source: DataCubeSource) { - const lambda = this.buildRawLambdaFromValueSpec(query); - return this.getRelationalType(lambda); - } - - async getQueryCodeRelationReturnType( - code: string, - baseQuery: V1_ValueSpecification, - source: DataCubeSource, - ) { - const queryString = - await this.graphState.graphManager.valueSpecificationToPureCode( - V1_serializeValueSpecification(baseQuery, []), - ); - const fullQuery = queryString + code; - return this.getRelationalType( - await this.graphState.graphManager.pureCodeToLambda(fullQuery), - ); - } - - async executeQuery(query: V1_Lambda, source: DataCubeSource) { - const lambda = this.buildRawLambdaFromValueSpec(query); - lambda.parameters = this._parameters; - const [executionWithMetadata, queryString] = await Promise.all([ - this.graphState.graphManager.runQuery( - lambda, - undefined, - undefined, - this.graph, - { - parameterValues: this.parameterValues ?? [], - }, - ), - this.graphState.graphManager.lambdaToPureCode(lambda), - ]); - const expectedTDS = guaranteeType( - executionWithMetadata.executionResult, - TDSExecutionResult, - 'Query returned expected to be of tabular data set', - ); - const sql = expectedTDS.activities?.[0]; - let sqlString = '### NO SQL FOUND'; - if (sql instanceof RelationalExecutionActivities) { - sqlString = sql.sql; - } - return { - result: expectedTDS, - executedQuery: queryString, - executedSQL: sqlString, - }; - } - - buildExecutionContext( - source: DataCubeSource, - ): V1_AppliedFunction | undefined { - if (source instanceof QueryBuilderDataCubeSource) { - return _function( - DataCubeFunction.FROM, - [ - source.mapping ? _elementPtr(source.mapping) : undefined, - _elementPtr(source.runtime), - ].filter(isNonNullable), - ); - } - return undefined; - } -} diff --git a/packages/legend-application-data-cube/src/stores/model/DataCubeGenericSource.ts b/packages/legend-application-data-cube/src/stores/model/DataCubeGenericSource.ts deleted file mode 100644 index 36fea2e4a9..0000000000 --- a/packages/legend-application-data-cube/src/stores/model/DataCubeGenericSource.ts +++ /dev/null @@ -1,17 +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. - */ - -export abstract class DataCubeGenericSource {} diff --git a/packages/legend-application-data-cube/src/stores/model/DataCubeGenericSourceHelper.ts b/packages/legend-application-data-cube/src/stores/model/DataCubeGenericSourceHelper.ts deleted file mode 100644 index 65268f3923..0000000000 --- a/packages/legend-application-data-cube/src/stores/model/DataCubeGenericSourceHelper.ts +++ /dev/null @@ -1,97 +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 { - UnsupportedOperationError, - optionalCustom, - usingConstantValueSchema, - type PlainObject, -} from '@finos/legend-shared'; -import type { DataCubeGenericSource } from './DataCubeGenericSource.js'; -import { LegendSavedQuerySource } from './LegendSavedQuerySource.js'; -import { - createModelSchema, - primitive, - deserialize, - serialize, - optional, - raw, -} from 'serializr'; -import { DataCubeQueryConent } from './DataCubeQueryContent.js'; - -enum SavedDataCubeQueryType { - LEGEND_QUERY = 'LegendQuery', -} - -export const legendSavedQuerySourceModelSchema = createModelSchema( - LegendSavedQuerySource, - { - _type: usingConstantValueSchema(SavedDataCubeQueryType.LEGEND_QUERY), - id: primitive(), - }, -); - -const deserializeDataCubeGenericSource = ( - content: PlainObject, -): DataCubeGenericSource => { - switch (content._type) { - case SavedDataCubeQueryType.LEGEND_QUERY: - return deserialize(legendSavedQuerySourceModelSchema, content); - default: - } - throw new UnsupportedOperationError( - `Can't de serialize saved data cube`, - content._type, - ); -}; - -const serializeDataCubeGenericSource = ( - genericSource: DataCubeGenericSource, -): PlainObject => { - if (genericSource instanceof LegendSavedQuerySource) { - return serialize(legendSavedQuerySourceModelSchema, genericSource); - } - throw new UnsupportedOperationError(`Can't serialize saved data cube`); -}; - -const dataCubeQueryConentModelSchema = createModelSchema(DataCubeQueryConent, { - query: optional(primitive()), - configuration: optional(raw()), - source: optionalCustom( - (val) => serializeDataCubeGenericSource(val), - (val) => deserializeDataCubeGenericSource(val), - ), -}); - -export const createQueryBuilderContent = ( - source: DataCubeGenericSource, -): DataCubeQueryConent => { - const content = new DataCubeQueryConent(); - content.source = source; - return content; -}; - -export const serializeDataCubeQueryConent = ( - content: DataCubeQueryConent, -): PlainObject => { - return serialize(dataCubeQueryConentModelSchema, content); -}; - -export const deserializeDataCubeQueryConent = ( - content: PlainObject, -): DataCubeQueryConent => { - return deserialize(dataCubeQueryConentModelSchema, content); -}; diff --git a/packages/legend-application-data-cube/src/stores/model/DataCubeQueryContent.ts b/packages/legend-application-data-cube/src/stores/model/DataCubeQueryContent.ts deleted file mode 100644 index 333eaff8ab..0000000000 --- a/packages/legend-application-data-cube/src/stores/model/DataCubeQueryContent.ts +++ /dev/null @@ -1,24 +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 { PlainObject } from '@finos/legend-shared'; -import type { DataCubeGenericSource } from './DataCubeGenericSource.js'; - -export class DataCubeQueryConent { - query: string | undefined; - configuration: PlainObject | undefined; - source!: DataCubeGenericSource; -} diff --git a/packages/legend-application-data-cube/src/stores/model/LegendQueryDataCubeSource.ts b/packages/legend-application-data-cube/src/stores/model/LegendQueryDataCubeSource.ts new file mode 100644 index 0000000000..f6ba8edc89 --- /dev/null +++ b/packages/legend-application-data-cube/src/stores/model/LegendQueryDataCubeSource.ts @@ -0,0 +1,39 @@ +/** + * 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 { DataCubeSource } from '@finos/legend-data-cube'; +import { + SerializationFactory, + usingConstantValueSchema, +} 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; +} + +export class RawLegendQueryDataCubeSource { + queryId!: string; + + static readonly serialization = new SerializationFactory( + createModelSchema(RawLegendQueryDataCubeSource, { + _type: usingConstantValueSchema(LEGEND_QUERY_DATA_CUBE_SOURCE_TYPE), + queryId: primitive(), + }), + ); +} diff --git a/packages/legend-application-data-cube/src/stores/source/CubeInputSourceLoader.ts b/packages/legend-application-data-cube/src/stores/source/CubeInputSourceLoader.ts index d2a8f7e806..75ad9ae33e 100644 --- a/packages/legend-application-data-cube/src/stores/source/CubeInputSourceLoader.ts +++ b/packages/legend-application-data-cube/src/stores/source/CubeInputSourceLoader.ts @@ -16,24 +16,23 @@ import { ActionState, UnsupportedOperationError } from '@finos/legend-shared'; import type { DataCubeEngine } from '@finos/legend-data-cube'; -import type { LegendDataCubeStoreContext } from '../LegendDataCubeEditorStore.js'; -import type { DataCubeGenericSource } from '../model/DataCubeGenericSource.js'; +// import type { DataCubeGenericSource } from '../model/DataCubeGenericSource.js'; export enum DataCubeSourceType { LEGEND_QUERY = 'Legend Query', REPL_QUERY = 'Repl Query', } -export abstract class CubeInputSourceState { +export abstract class LegendDataCubeInputSourceState { buildCubeEngineState = ActionState.create(); setupActionState = ActionState.create(); - readonly context: LegendDataCubeStoreContext; + // readonly context: LegendDataCubeStoreContext; - constructor(context: LegendDataCubeStoreContext) { - this.context = context; - } + // constructor(context: LegendDataCubeStoreContext) { + // this.context = context; + // } abstract get label(): DataCubeSourceType; async setup(): Promise { @@ -42,7 +41,7 @@ export abstract class CubeInputSourceState { abstract buildCubeEngine(): Promise; - abstract process(): DataCubeGenericSource; + // abstract process(): DataCubeGenericSource; abstract get isValid(): boolean; @@ -50,7 +49,9 @@ export abstract class CubeInputSourceState { return true; } - static builder(context: LegendDataCubeStoreContext): CubeInputSourceState { - throw new UnsupportedOperationError('No builder'); - } + // static builder( + // context: LegendDataCubeStoreContext, + // ): LegendDataCubeInputSourceState { + // throw new UnsupportedOperationError('No builder'); + // } } diff --git a/packages/legend-application-data-cube/src/stores/source/LegendCubeViewer.ts b/packages/legend-application-data-cube/src/stores/source/LegendCubeViewer.ts deleted file mode 100644 index 705f408e10..0000000000 --- a/packages/legend-application-data-cube/src/stores/source/LegendCubeViewer.ts +++ /dev/null @@ -1,28 +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 { DataCubeEngine } from '@finos/legend-data-cube'; -import type { DataCubeGenericSource } from '../model/DataCubeGenericSource.js'; - -export class LegendCubeViewer { - source: DataCubeGenericSource; - engine: DataCubeEngine; - - constructor(source: DataCubeGenericSource, engine: DataCubeEngine) { - this.source = source; - this.engine = engine; - } -} diff --git a/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilder.ts b/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilder.ts index e1c5ae7f6a..dfca2b9fb9 100644 --- a/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilder.ts +++ b/packages/legend-application-data-cube/src/stores/source/LegendDataCubeSourceBuilder.ts @@ -17,10 +17,8 @@ import { flow, makeObservable, observable } from 'mobx'; import { DataCubeSourceType, - type CubeInputSourceState, + type LegendDataCubeInputSourceState, } from './CubeInputSourceLoader.js'; -import { SavedQueryInputSourceState } from './SavedQueryInputSourceState.js'; -import type { LegendDataCubeStoreContext } from '../LegendDataCubeEditorStore.js'; import { UnsupportedOperationError, assertErrorThrown, @@ -29,20 +27,18 @@ import { type GeneratorFn, } from '@finos/legend-shared'; import type { DataCubeEngine } from '@finos/legend-data-cube'; -import type { DataCubeGenericSource } from '../model/DataCubeGenericSource.js'; export class LegendDataCubeSourceBuilder { - readonly context: LegendDataCubeStoreContext; open = false; - sourceState: CubeInputSourceState; + sourceState: LegendDataCubeInputSourceState; - constructor(context: LegendDataCubeStoreContext) { + constructor() { makeObservable(this, { open: observable, sourceState: observable, - inputSource: flow, + + // inputSource: flow, }); - this.context = context; this.sourceState = this.buildSource(guaranteeNonNullable(this.options[0])); } @@ -68,31 +64,31 @@ export class LegendDataCubeSourceBuilder { } } - buildSource(source: DataCubeSourceType): CubeInputSourceState { - if (source === DataCubeSourceType.LEGEND_QUERY) { - return SavedQueryInputSourceState.builder(this.context); - } + 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.applicationStore.notificationService.notifyError( - `Unable to import: ${this.sourceState.label}: ${error.message}`, - ); - } - } + // *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/SavedQueryInputSourceState.ts b/packages/legend-application-data-cube/src/stores/source/SavedQueryInputSourceState.ts index 2a7f6d141d..e542707974 100644 --- a/packages/legend-application-data-cube/src/stores/source/SavedQueryInputSourceState.ts +++ b/packages/legend-application-data-cube/src/stores/source/SavedQueryInputSourceState.ts @@ -20,7 +20,7 @@ import { isNonNullable, } from '@finos/legend-shared'; import { - CubeInputSourceState, + LegendDataCubeInputSourceState, DataCubeSourceType, } from './CubeInputSourceLoader.js'; import type { DataCubeEngine } from '@finos/legend-data-cube'; @@ -31,65 +31,62 @@ import { type LightQuery, } from '@finos/legend-graph'; import { resolveVersion } from '@finos/legend-server-depot'; -import { LegendExecutionDataCubeEngine } from '../engine/LegendExecutionDataCubeEngine.js'; -import type { LegendDataCubeStoreContext } from '../LegendDataCubeEditorStore.js'; +import { LegendDataCubeDataCubeEngine } from '../LegendDataCubeDataCubeEngine.js'; import { QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT, QueryLoaderState, } from '@finos/legend-query-builder'; import { action, makeObservable, observable } from 'mobx'; -import type { DataCubeGenericSource } from '../model/DataCubeGenericSource.js'; -import { LegendSavedQuerySource } from '../model/LegendSavedQuerySource.js'; -export class SavedQueryInputSourceState extends CubeInputSourceState { +export class SavedQueryInputSourceState extends LegendDataCubeInputSourceState { query: LightQuery | undefined; - queryLoaderState: QueryLoaderState; + // queryLoaderState: QueryLoaderState; - constructor(context: LegendDataCubeStoreContext) { - super(context); + constructor() { + super(); makeObservable(this, { query: observable, buildCubeEngineState: observable, setQuery: action, }); - this.queryLoaderState = new QueryLoaderState( - this.context.applicationStore, - this.context.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.context.graphManagerState.graphManager.searchQueries( - QuerySearchSpecification.createDefault(undefined), - ); - }, - isReadOnly: true, - }, - ); + // 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 LegendSavedQuerySource(guaranteeNonNullable(this.query).id); - } + // override process(): DataCubeGenericSource { + // assertTrue(this.isValid); + // return new LegendQueryDataCubeSource(guaranteeNonNullable(this.query).id); + // } override get openActionable(): boolean { return false; } - static override builder( - context: LegendDataCubeStoreContext, - ): CubeInputSourceState { - return new SavedQueryInputSourceState(context); - } + // static override builder( + // context: LegendDataCubeStoreContext, + // ): LegendDataCubeInputSourceState { + // return new SavedQueryInputSourceState(context); + // } override get label(): DataCubeSourceType { return DataCubeSourceType.LEGEND_QUERY; } @@ -97,45 +94,48 @@ export class SavedQueryInputSourceState extends CubeInputSourceState { throw new Error('Method not implemented.'); } - async buildCubeEngine(): Promise { - this.buildCubeEngineState.inProgress(); - const queryInfo = - await this.context.graphManagerState.graphManager.getQueryInfo( - guaranteeNonNullable(this.query).id, - ); - const execConext = - (await this.context.graphManagerState.graphManager.resolveQueryInfoExecutionContext( - queryInfo, - () => - this.context.depotServerClient.getVersionEntities( - queryInfo.groupId, - queryInfo.artifactId, - queryInfo.versionId, - ), - )) as { mapping: string | undefined; runtime: string }; - const lambda = - (await this.context.graphManagerState.graphManager.pureCodeToLambda( - queryInfo.content, - )) as unknown as RawLambda; - this.context.graphManagerState.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 LegendExecutionDataCubeEngine( - lambda, - undefined, - execConext.mapping, - execConext.runtime, - this.context.graphManagerState, - ); - this.buildCubeEngineState.complete(); - return engine; + 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/_more.scss b/packages/legend-application-data-cube/style/_query-editor-light.scss similarity index 100% rename from packages/legend-application-data-cube/style/_more.scss rename to packages/legend-application-data-cube/style/_query-editor-light.scss diff --git a/packages/legend-application-data-cube/style/index.scss b/packages/legend-application-data-cube/style/index.scss index 2e95aa227e..ba2e9f1625 100644 --- a/packages/legend-application-data-cube/style/index.scss +++ b/packages/legend-application-data-cube/style/index.scss @@ -15,4 +15,17 @@ */ @forward 'query-editor'; -@forward 'more'; +@forward 'query-editor-light'; + +// ---------------------------------------- NORMALIZE ---------------------------------------- + +html { + box-sizing: border-box; + font-family: Roboto, sans-serif; + overscroll-behavior: none; +} + +body { + // default font size is 12px everywhere to make the app more compact + font-size: 12px; +} diff --git a/packages/legend-application-pure-ide/src/components/PureIDEStoreProvider.tsx b/packages/legend-application-pure-ide/src/components/PureIDEStoreProvider.tsx index 8e3b0f236c..8a68c962a1 100644 --- a/packages/legend-application-pure-ide/src/components/PureIDEStoreProvider.tsx +++ b/packages/legend-application-pure-ide/src/components/PureIDEStoreProvider.tsx @@ -22,7 +22,7 @@ import { useApplicationStore } from '@finos/legend-application'; import type { LegendPureIDEApplicationConfig } from '../application/LegendPureIDEApplicationConfig.js'; import type { LegendPureIDEPluginManager } from '../application/LegendPureIDEPluginManager.js'; -const EditorStoreContext = createContext(undefined); +const PureIDEStoreContext = createContext(undefined); export const PureIDEStoreProvider = (props: { children: React.ReactNode }) => { const { children } = props; @@ -32,15 +32,15 @@ export const PureIDEStoreProvider = (props: { children: React.ReactNode }) => { >(); const store = useLocalObservable(() => new PureIDEStore(applicationStore)); return ( - + {children} - + ); }; export const usePureIDEStore = (): PureIDEStore => guaranteeNonNullable( - useContext(EditorStoreContext), + useContext(PureIDEStoreContext), `Can't find editor store in context`, ); diff --git a/packages/legend-application-query/src/stores/LegendQueryBaseStore.ts b/packages/legend-application-query/src/stores/LegendQueryBaseStore.ts index c53355706b..035c865bfa 100644 --- a/packages/legend-application-query/src/stores/LegendQueryBaseStore.ts +++ b/packages/legend-application-query/src/stores/LegendQueryBaseStore.ts @@ -26,10 +26,10 @@ import { ActionState, assertErrorThrown, LogEvent, - NetworkClient, type GeneratorFn, } from '@finos/legend-shared'; import { flow, makeObservable } from 'mobx'; +import { getCurrentUserIDFromEngineServer } from '@finos/legend-graph'; export type LegendQueryApplicationStore = ApplicationStore< LegendQueryApplicationConfig, @@ -71,8 +71,8 @@ export class LegendQueryBaseStore { try { this.applicationStore.identityService.setCurrentUser( - (yield new NetworkClient().get( - `${this.applicationStore.config.engineServerUrl}/server/v1/currentUser`, + (yield getCurrentUserIDFromEngineServer( + this.applicationStore.config.engineServerUrl, )) as string, ); } catch (error) { diff --git a/packages/legend-application-repl/src/application/LegendREPL.tsx b/packages/legend-application-repl/src/application/LegendREPL.tsx index 0ba75c79c5..67d5380dd3 100644 --- a/packages/legend-application-repl/src/application/LegendREPL.tsx +++ b/packages/legend-application-repl/src/application/LegendREPL.tsx @@ -28,7 +28,7 @@ import { LegendREPLApplicationConfig, type LegendREPLApplicationConfigData, } from './LegendREPLApplicationConfig.js'; -import { LegendREPLWebApplication } from '../components/LegendREPLApplication.js'; +import { LegendREPLWebApplication } from '../components/LegendREPLWebApplication.js'; import type { LegendREPLApplicationStore } from './LegendREPLApplicationStore.js'; export class LegendREPL extends LegendApplication { diff --git a/packages/legend-application-repl/src/application/LegendREPLNavigation.ts b/packages/legend-application-repl/src/application/LegendREPLNavigation.ts index 9bda6545d9..dd2c82273b 100644 --- a/packages/legend-application-repl/src/application/LegendREPLNavigation.ts +++ b/packages/legend-application-repl/src/application/LegendREPLNavigation.ts @@ -15,7 +15,7 @@ */ /** - * @external_application_navigation This depends on Legend Data Cube routing and is hardcoded so it's potentially brittle + * @external_application_navigation This depends on Legend DataCube routing and is hardcoded so it's potentially brittle */ export const EXTERNAL_APPLICATION_NAVIGATION__generateDataCubeViewUrl = ( hostedApplicationBaseUrl: string, diff --git a/packages/legend-application-repl/src/components/LegendREPLDataCubeHeader.tsx b/packages/legend-application-repl/src/components/LegendREPLDataCubeHeader.tsx index 96917ba3bc..7fcad3d017 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="h- 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="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" > Publish diff --git a/packages/legend-application-repl/src/components/LegendREPLFramworkProvider.tsx b/packages/legend-application-repl/src/components/LegendREPLFramworkProvider.tsx index ce8e0df930..5babc949cc 100644 --- a/packages/legend-application-repl/src/components/LegendREPLFramworkProvider.tsx +++ b/packages/legend-application-repl/src/components/LegendREPLFramworkProvider.tsx @@ -33,13 +33,11 @@ const LegendREPLBaseStoreContext = createContext< const LegendREPLBaseStoreProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { - const applicationStore = useApplicationStore< + const application = useApplicationStore< LegendREPLApplicationConfig, LegendApplicationPluginManager >(); - const store = useLocalObservable( - () => new LegendREPLBaseStore(applicationStore), - ); + const store = useLocalObservable(() => new LegendREPLBaseStore(application)); return ( {children} diff --git a/packages/legend-application-repl/src/components/LegendREPLApplication.tsx b/packages/legend-application-repl/src/components/LegendREPLWebApplication.tsx similarity index 91% rename from packages/legend-application-repl/src/components/LegendREPLApplication.tsx rename to packages/legend-application-repl/src/components/LegendREPLWebApplication.tsx index 03c4f8efa5..63930f054d 100644 --- a/packages/legend-application-repl/src/components/LegendREPLApplication.tsx +++ b/packages/legend-application-repl/src/components/LegendREPLWebApplication.tsx @@ -20,9 +20,8 @@ import { Routes, } from '@finos/legend-application/browser'; import { observer } from 'mobx-react-lite'; -import { useEffect, useMemo } from 'react'; +import { useEffect } from 'react'; import { formatDate, LogEvent } from '@finos/legend-shared'; -import { LegendREPLDataCubeEngine } from '../stores/LegendREPLDataCubeEngine.js'; import { DataCube, DataCubeSettingKey, @@ -39,31 +38,30 @@ import { const LegendREPLDataCube = observer((props: { query: DataCubeQuery }) => { const { query } = props; const store = useLegendREPLBaseStore(); - const engine = useMemo(() => new LegendREPLDataCubeEngine(store), [store]); const application = store.application; useEffect(() => { - engine.blockNavigation( + application.navigationService.navigator.blockNavigation( // Only block navigation in production // eslint-disable-next-line no-process-env [() => process.env.NODE_ENV === 'production'], undefined, () => { - engine.logWarning( + application.logService.warn( LogEvent.create(APPLICATION_EVENT.NAVIGATION_BLOCKED), `Navigation from the application is blocked`, ); }, ); return (): void => { - engine.unblockNavigation(); + application.navigationService.navigator.unblockNavigation(); }; - }, [engine]); + }, [application]); return ( { ); }, onSettingChanged(key, value) { - engine.persistSettingValue(key, value); + application.settingService.persistValue(key, value); }, enableDebugMode: application.settingService.getBooleanValue( DataCubeSettingKey.ENABLE_DEBUG_MODE, diff --git a/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx b/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx index b6723eb8a7..7d4d330f1a 100644 --- a/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx +++ b/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx @@ -38,10 +38,12 @@ import { PersistentDataCubeQuery } from '@finos/legend-graph'; import { LegendREPLPublishDataCubeAlert } from '../components/LegendREPLPublishDataCubeAlert.js'; import { APPLICATION_EVENT } from '@finos/legend-application'; import { action, makeObservable, observable } from 'mobx'; +import { LegendREPLDataCubeEngine } from './LegendREPLDataCubeEngine.js'; export class LegendREPLBaseStore { readonly application: LegendREPLApplicationStore; readonly client: LegendREPLServerClient; + readonly engine: LegendREPLDataCubeEngine; readonly initState = ActionState.create(); readonly publishState = ActionState.create(); @@ -54,7 +56,7 @@ export class LegendREPLBaseStore { constructor(application: LegendREPLApplicationStore) { makeObservable(this, { - query: observable.ref, + query: observable, initialize: action, }); @@ -70,6 +72,7 @@ export class LegendREPLBaseStore { : application.config.replUrl, }), ); + this.engine = new LegendREPLDataCubeEngine(this); } async initialize() { diff --git a/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts b/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts index 910857622d..603a59e751 100644 --- a/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts +++ b/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts @@ -71,32 +71,9 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { this.client = baseStore.client; } - blockNavigation( - blockCheckers: (() => boolean)[], - onBlock?: ((onProceed: () => void) => void) | undefined, - onNativePlatformNavigationBlock?: (() => void) | undefined, - ) { - this.application.navigationService.navigator.blockNavigation( - blockCheckers, - onBlock, - onNativePlatformNavigationBlock, - ); - } - - unblockNavigation() { - this.application.navigationService.navigator.unblockNavigation(); - } - - persistSettingValue( - key: string, - value: string | number | boolean | object | undefined, - ): void { - this.application.settingService.persistValue(key, value); - } - // ---------------------------------- IMPLEMENTATION ---------------------------------- - async processQuerySource(value: PlainObject) { + override async processQuerySource(value: PlainObject) { if (value._type !== REPL_DATA_CUBE_SOURCE_TYPE) { throw new Error( `Can't deserialize query source of type '${value._type}'. Only type(s) '${REPL_DATA_CUBE_SOURCE_TYPE}' are supported.`, @@ -120,7 +97,7 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { return source; } - async parseValueSpecification( + override async parseValueSpecification( code: string, returnSourceInformation?: boolean, ) { @@ -133,7 +110,7 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { ); } - override getValueSpecificationCode( + override async getValueSpecificationCode( value: V1_ValueSpecification, pretty?: boolean, ) { @@ -143,7 +120,7 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { }); } - async getQueryTypeahead( + override async getQueryTypeahead( code: string, baseQuery: V1_Lambda, source: DataCubeSource, @@ -154,13 +131,16 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { }); } - async getQueryRelationType(query: V1_Lambda, source: DataCubeSource) { + override async getQueryRelationType( + query: V1_Lambda, + source: DataCubeSource, + ) { return this.client.getQueryRelationReturnType({ query: V1_serializeValueSpecification(query, []), }); } - async getQueryCodeRelationReturnType( + override async getQueryCodeRelationReturnType( code: string, baseQuery: V1_ValueSpecification, source: DataCubeSource, @@ -186,7 +166,7 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { } } - async executeQuery( + override async executeQuery( query: V1_Lambda, source: DataCubeSource, api: DataCubeAPI, @@ -222,6 +202,8 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { return undefined; } + // ---------------------------------- APPLICATION ---------------------------------- + override getDocumentationURL(): string | undefined { return this.application.documentationService.url; } diff --git a/packages/legend-application-studio/src/stores/LegendStudioBaseStore.ts b/packages/legend-application-studio/src/stores/LegendStudioBaseStore.ts index 2874d9e66e..4cdb5e4653 100644 --- a/packages/legend-application-studio/src/stores/LegendStudioBaseStore.ts +++ b/packages/legend-application-studio/src/stores/LegendStudioBaseStore.ts @@ -22,7 +22,6 @@ import { ActionState, LogEvent, assertErrorThrown, - NetworkClient, } from '@finos/legend-shared'; import { type ApplicationStore, @@ -48,6 +47,7 @@ import type { LegendStudioApplicationConfig } from '../application/LegendStudioA import { LegendStudioEventHelper } from '../__lib__/LegendStudioEventHelper.js'; import { LEGEND_STUDIO_SDLC_BYPASSED_ROUTE_PATTERN } from '../__lib__/LegendStudioNavigation.js'; import { ShowcaseManagerState } from './ShowcaseManagerState.js'; +import { getCurrentUserIDFromEngineServer } from '@finos/legend-graph'; export type LegendStudioApplicationStore = ApplicationStore< LegendStudioApplicationConfig, @@ -168,8 +168,8 @@ export class LegendStudioBaseStore { if (this.applicationStore.identityService.isAnonymous) { try { this.applicationStore.identityService.setCurrentUser( - (yield new NetworkClient().get( - `${this.applicationStore.config.engineServerUrl}/server/v1/currentUser`, + (yield getCurrentUserIDFromEngineServer( + this.applicationStore.config.engineServerUrl, )) as string, ); } catch (error) { diff --git a/packages/legend-data-cube/README.md b/packages/legend-data-cube/README.md index 20ec69973b..cbdc6e91b8 100644 --- a/packages/legend-data-cube/README.md +++ b/packages/legend-data-cube/README.md @@ -1,3 +1,3 @@ # @finos/legend-data-cube -Legend Data Cube +Legend DataCube core diff --git a/packages/legend-data-cube/package.json b/packages/legend-data-cube/package.json index 4cfed59a19..afd60f764d 100644 --- a/packages/legend-data-cube/package.json +++ b/packages/legend-data-cube/package.json @@ -1,7 +1,7 @@ { "name": "@finos/legend-data-cube", "version": "0.0.35", - "description": "Legend Data Cube", + "description": "Legend DataCube", "keywords": [ "legend", "legend-data-cube", diff --git a/packages/legend-data-cube/src/stores/DataCubeState.tsx b/packages/legend-data-cube/src/stores/DataCubeState.tsx index f07d33dfbc..18e55dfbdf 100644 --- a/packages/legend-data-cube/src/stores/DataCubeState.tsx +++ b/packages/legend-data-cube/src/stores/DataCubeState.tsx @@ -160,7 +160,9 @@ export class DataCubeState implements DataCubeAPI { this.initState.inProgress(); try { - await this.engine.initialize(); + await this.engine.initialize({ + gridClientLicense: this.settings.gridClientLicense, + }); this.initState.pass(); } catch (error) { assertErrorThrown(error); diff --git a/packages/legend-data-cube/src/stores/view/DataCubeViewState.ts b/packages/legend-data-cube/src/stores/view/DataCubeViewState.ts index 7b81538736..eca635742f 100644 --- a/packages/legend-data-cube/src/stores/view/DataCubeViewState.ts +++ b/packages/legend-data-cube/src/stores/view/DataCubeViewState.ts @@ -57,7 +57,6 @@ class DataCubeTask { export class DataCubeViewState { readonly dataCube: DataCubeState; readonly engine: DataCubeEngine; - readonly snapshotManager: DataCubeQuerySnapshotManager; readonly info: DataCubeInfoState; @@ -72,7 +71,7 @@ export class DataCubeViewState { constructor(dataCube: DataCubeState) { makeObservable(this, { - _source: observable.ref, + _source: observable, source: computed, isSourceProcessed: computed, diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridState.ts b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridState.ts index 34791c8b4b..84b451afe0 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridState.ts +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridState.ts @@ -73,7 +73,7 @@ export class DataCubeGridState extends DataCubeQuerySnapshotController { makeObservable(this, { clientDataSource: observable, - queryConfiguration: observable.ref, + queryConfiguration: observable, rowLimit: observable, diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.ts index 35e72d6ca5..144b1d9a46 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.ts @@ -21,6 +21,7 @@ import { type ServerClientConfig, type TraceData, HttpHeader, + NetworkClient, } from '@finos/legend-shared'; import type { V1_PureModelContextData } from '../model/context/V1_PureModelContextData.js'; import type { @@ -164,6 +165,15 @@ const getEngineSerializationFormat = ( } }; +// eslint-disable-next-line @finos/legend/enforce-protocol-export-prefix +export async function getCurrentUserIDFromEngineServer( + engineServerUrl: string, +) { + return (await new NetworkClient().get( + `${engineServerUrl}/server/v1/currentUser`, + )) as string; +} + export class V1_EngineServerClient extends AbstractServerClient { currentUserId?: string | undefined; private env?: string | undefined; diff --git a/packages/legend-graph/src/index.ts b/packages/legend-graph/src/index.ts index 8634cda760..83352cbb13 100644 --- a/packages/legend-graph/src/index.ts +++ b/packages/legend-graph/src/index.ts @@ -417,6 +417,7 @@ export * from './graph-manager/protocol/pure/v1/transformation/pureGraph/from/V1 export { type V1_GrammarParserBatchInputEntry, V1_EngineServerClient, + getCurrentUserIDFromEngineServer, } from './graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.js'; export { type V1_GraphManagerEngine } from './graph-manager/protocol/pure/v1/engine/V1_GraphManagerEngine.js'; export { V1_RemoteEngine } from './graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.js'; diff --git a/yarn.lock b/yarn.lock index 87c631f287..87d2259f66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2155,6 +2155,7 @@ __metadata: dependencies: "@finos/legend-application": "workspace:*" "@finos/legend-application-data-cube": "workspace:*" + "@finos/legend-data-cube": "workspace:*" "@finos/legend-dev-utils": "workspace:*" "@finos/legend-extension-dsl-data-space": "workspace:*" "@finos/legend-shared": "workspace:*"