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 (
- <>
-
-
- {/* {dataCubeStore.cubeViewer ? (
- <>
-
-
-
-
-
-
-
-
- >
- ) : (
- <>
-
sourceSelector.openModal()}
- className="bg-white shadow"
- >
-
-
- >
- )} */}
-
- {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 (
+// <>
+//
+//
+// {/* {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