@finos/legend-application-studio 28.21.51 → 28.21.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/lib/components/editor/Editor.d.ts.map +1 -1
  2. package/lib/components/editor/Editor.js +2 -1
  3. package/lib/components/editor/Editor.js.map +1 -1
  4. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.d.ts.map +1 -1
  5. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js +14 -2
  6. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js.map +1 -1
  7. package/lib/components/editor/embedded-cube/EmbeddedCube.d.ts +23 -0
  8. package/lib/components/editor/embedded-cube/EmbeddedCube.d.ts.map +1 -0
  9. package/lib/components/editor/embedded-cube/EmbeddedCube.js +38 -0
  10. package/lib/components/editor/embedded-cube/EmbeddedCube.js.map +1 -0
  11. package/lib/components/editor/embedded-cube/EmbeddedCubeEditor.d.ts +35 -0
  12. package/lib/components/editor/embedded-cube/EmbeddedCubeEditor.d.ts.map +1 -0
  13. package/lib/components/editor/embedded-cube/EmbeddedCubeEditor.js +179 -0
  14. package/lib/components/editor/embedded-cube/EmbeddedCubeEditor.js.map +1 -0
  15. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.d.ts.map +1 -1
  16. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js +4 -0
  17. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js.map +1 -1
  18. package/lib/index.css +1 -1
  19. package/lib/package.json +3 -1
  20. package/lib/stores/editor/EditorStore.d.ts +2 -0
  21. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  22. package/lib/stores/editor/EditorStore.js +6 -1
  23. package/lib/stores/editor/EditorStore.js.map +1 -1
  24. package/lib/stores/editor/embedded-cube/EmbeddedCubeState.d.ts +86 -0
  25. package/lib/stores/editor/embedded-cube/EmbeddedCubeState.d.ts.map +1 -0
  26. package/lib/stores/editor/embedded-cube/EmbeddedCubeState.js +206 -0
  27. package/lib/stores/editor/embedded-cube/EmbeddedCubeState.js.map +1 -0
  28. package/lib/stores/editor/embedded-cube/LegendStudioCubeDataProductCatalog.d.ts +51 -0
  29. package/lib/stores/editor/embedded-cube/LegendStudioCubeDataProductCatalog.d.ts.map +1 -0
  30. package/lib/stores/editor/embedded-cube/LegendStudioCubeDataProductCatalog.js +148 -0
  31. package/lib/stores/editor/embedded-cube/LegendStudioCubeDataProductCatalog.js.map +1 -0
  32. package/lib/stores/editor/embedded-cube/LegendStudioCubeHost.d.ts +39 -0
  33. package/lib/stores/editor/embedded-cube/LegendStudioCubeHost.d.ts.map +1 -0
  34. package/lib/stores/editor/embedded-cube/LegendStudioCubeHost.js +60 -0
  35. package/lib/stores/editor/embedded-cube/LegendStudioCubeHost.js.map +1 -0
  36. package/lib/stores/editor/embedded-cube/LegendStudioCubeIngestCatalog.d.ts +57 -0
  37. package/lib/stores/editor/embedded-cube/LegendStudioCubeIngestCatalog.d.ts.map +1 -0
  38. package/lib/stores/editor/embedded-cube/LegendStudioCubeIngestCatalog.js +148 -0
  39. package/lib/stores/editor/embedded-cube/LegendStudioCubeIngestCatalog.js.map +1 -0
  40. package/lib/stores/editor/embedded-cube/LegendStudioCubeWorkspace.d.ts +58 -0
  41. package/lib/stores/editor/embedded-cube/LegendStudioCubeWorkspace.d.ts.map +1 -0
  42. package/lib/stores/editor/embedded-cube/LegendStudioCubeWorkspace.js +94 -0
  43. package/lib/stores/editor/embedded-cube/LegendStudioCubeWorkspace.js.map +1 -0
  44. package/lib/stores/graph-modifier/DSL_Ingest_GraphModifierHelper.d.ts +57 -0
  45. package/lib/stores/graph-modifier/DSL_Ingest_GraphModifierHelper.d.ts.map +1 -0
  46. package/lib/stores/graph-modifier/DSL_Ingest_GraphModifierHelper.js +151 -0
  47. package/lib/stores/graph-modifier/DSL_Ingest_GraphModifierHelper.js.map +1 -0
  48. package/package.json +13 -11
  49. package/src/components/editor/Editor.tsx +2 -0
  50. package/src/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.tsx +62 -0
  51. package/src/components/editor/embedded-cube/EmbeddedCube.tsx +57 -0
  52. package/src/components/editor/embedded-cube/EmbeddedCubeEditor.tsx +452 -0
  53. package/src/components/extensions/Core_LegendStudioApplicationPlugin.tsx +4 -0
  54. package/src/stores/editor/EditorStore.ts +6 -1
  55. package/src/stores/editor/embedded-cube/EmbeddedCubeState.ts +284 -0
  56. package/src/stores/editor/embedded-cube/LegendStudioCubeDataProductCatalog.ts +242 -0
  57. package/src/stores/editor/embedded-cube/LegendStudioCubeHost.ts +82 -0
  58. package/src/stores/editor/embedded-cube/LegendStudioCubeIngestCatalog.ts +235 -0
  59. package/src/stores/editor/embedded-cube/LegendStudioCubeWorkspace.ts +151 -0
  60. package/src/stores/graph-modifier/DSL_Ingest_GraphModifierHelper.ts +214 -0
  61. package/tsconfig.json +8 -0
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Copyright (c) 2026-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { CubeEngineError, CubeEngineErrorKind, } from '@finos/legend-cube-builder';
17
+ import { LakehouseBaseRuntime, LakehouseRuntime, ModelStore, PrimitiveType, } from '@finos/legend-graph';
18
+ // The project Studio edits, as Legend Cube reads it: its coordinates, the
19
+ // lakehouse runtime its runs use, and the model its typing and runs read,
20
+ // the workspace as it is now. A cube in Studio reads only the project's own
21
+ // ingest definitions and data products, which aren't deployed: they are
22
+ // typed and run on the workspace, as Studio's own queries of them are.
23
+ /** The project's coordinates when Studio has no project configuration, which Cube's sources still name */
24
+ const UNKNOWN_PROJECT = { groupId: 'studio', artifactId: 'workspace' };
25
+ /** The version a cube of the workspace's data products names: the workspace, never a release */
26
+ export const LEGEND_STUDIO_CUBE_WORKSPACE_VERSION = 'workspace';
27
+ export const LEGEND_STUDIO_CUBE_WORKSPACE_MESSAGE = {
28
+ NO_RUNTIME: "Add a lakehouse runtime to the project: a cube runs the project's ingest data sets and data products on it, as Studio's own queries do.",
29
+ NO_ENVIRONMENT: (runtime) => `The project's lakehouse runtime ${runtime} names no environment.`,
30
+ };
31
+ export class LegendStudioCubeWorkspace {
32
+ editorStore;
33
+ constructor(editorStore) {
34
+ this.editorStore = editorStore;
35
+ }
36
+ /** The project's coordinates, which the URNs and models of Cube's sources carry */
37
+ get project() {
38
+ const configuration = this.editorStore.projectConfigurationEditorState.projectConfiguration;
39
+ return configuration
40
+ ? {
41
+ groupId: configuration.groupId,
42
+ artifactId: configuration.artifactId,
43
+ }
44
+ : UNKNOWN_PROJECT;
45
+ }
46
+ /**
47
+ * The lakehouse runtime a run uses: the project's first, as Studio's own
48
+ * queries of an ingest definition or a data product pick
49
+ * (`getCompatibleRuntimesFromAccessorOwner`, `LakehouseDataProductExecutionState`)
50
+ */
51
+ get lakehouseRuntime() {
52
+ return this.editorStore.graphManagerState.usableRuntimes.find((runtime) => runtime.runtimeValue instanceof LakehouseBaseRuntime);
53
+ }
54
+ async resolveRuntime() {
55
+ const runtime = this.lakehouseRuntime;
56
+ if (!runtime) {
57
+ throw new CubeEngineError(CubeEngineErrorKind.UNSUPPORTED_MODEL, LEGEND_STUDIO_CUBE_WORKSPACE_MESSAGE.NO_RUNTIME);
58
+ }
59
+ const value = runtime.runtimeValue;
60
+ if (!value.environment) {
61
+ throw new CubeEngineError(CubeEngineErrorKind.UNSUPPORTED_MODEL, LEGEND_STUDIO_CUBE_WORKSPACE_MESSAGE.NO_ENVIRONMENT(runtime.path));
62
+ }
63
+ return {
64
+ path: runtime.path,
65
+ environment: value.environment,
66
+ label: `${value.environment}, from ${runtime.path}`,
67
+ warehouse: value instanceof LakehouseRuntime ? value.warehouse : undefined,
68
+ };
69
+ }
70
+ /** The environment a data product run's lakehouse runtime names: the project runtime's */
71
+ async resolveEnvironment() {
72
+ return (await this.resolveRuntime()).environment;
73
+ }
74
+ /**
75
+ * The elements a cube's typing and runs read, as protocol JSON: the
76
+ * workspace's own and its dependencies', as Studio's own queries send
77
+ * them, so a definition's materialized views and a data product's access
78
+ * points find what they read
79
+ */
80
+ async getModelElements() {
81
+ const { graph, graphManager } = this.editorStore.graphManagerState;
82
+ return [...graph.allOwnElements, ...graph.dependencyManager.allOwnElements]
83
+ .filter((element) => !(element instanceof PrimitiveType) &&
84
+ !(element instanceof ModelStore))
85
+ .map((element) => graphManager.elementToEntity(element, {
86
+ pruneSourceInformation: true,
87
+ }).content);
88
+ }
89
+ /** The model a cube of the workspace's data products reads them from: the workspace */
90
+ async getProjectModel() {
91
+ return { _type: 'data', elements: await this.getModelElements() };
92
+ }
93
+ }
94
+ //# sourceMappingURL=LegendStudioCubeWorkspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LegendStudioCubeWorkspace.js","sourceRoot":"","sources":["../../../../src/stores/editor/embedded-cube/LegendStudioCubeWorkspace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Copyright (c) 2026-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { type IngestDefinition } from '@finos/legend-graph';
17
+ import { type PlainObject } from '@finos/legend-shared';
18
+ /** The ingest definition's data sets, as its content holds them */
19
+ export declare const getIngestDataSetNames: (ingest: IngestDefinition) => string[];
20
+ /** What a materialized view's data set says besides its name and its query */
21
+ export interface IngestMaterializedViewOptions {
22
+ /** The columns that identify a row, in the order of the view's columns; none for no key */
23
+ readonly primaryKey: readonly string[];
24
+ /** The classification of its data, e.g. `DP10`, as a data product's access points take one */
25
+ readonly sensitivity: string;
26
+ }
27
+ /** A materialized view of an ingest definition, as its content holds it */
28
+ export interface IngestMaterializedView {
29
+ readonly name: string;
30
+ /** Its query, as protocol JSON */
31
+ readonly lambda: PlainObject;
32
+ readonly primaryKey: readonly string[];
33
+ /** The classification of its data; none for a view without one */
34
+ readonly sensitivity: string | undefined;
35
+ }
36
+ /** The materialized views of the ingest definition, as its content holds them */
37
+ export declare const getIngestMaterializedViews: (ingest: IngestDefinition) => IngestMaterializedView[];
38
+ /**
39
+ * Adds a materialized view to the ingest definition: a data set whose rows
40
+ * the lambda (protocol JSON) computes, with its primary key and the
41
+ * classification of its data. It holds every key the engine gives a data
42
+ * set it parses, its lists empty, as the engine reads them all: a view
43
+ * without a `privacyClassification` failed with a NullPointerException.
44
+ * The content is replaced, so the change is seen, and the view is listed
45
+ * for Lineage and View SQL as one read from the definition would be
46
+ */
47
+ export declare const ingestDefinition_addMaterializedView: (ingest: IngestDefinition, name: string, lambda: PlainObject, options: IngestMaterializedViewOptions) => void;
48
+ /**
49
+ * Replaces a materialized view's lambda (protocol JSON) in place: its name,
50
+ * its place among the data sets and its other keys stay, as does its place
51
+ * among the views listed for Lineage and View SQL. A primary key and a
52
+ * classification given replace the view's, and the lists the engine reads
53
+ * that the view lacks, e.g. as Studio wrote a view before it wrote them, are
54
+ * added empty
55
+ */
56
+ export declare const ingestDefinition_updateMaterializedView: (ingest: IngestDefinition, name: string, lambda: PlainObject, options?: IngestMaterializedViewOptions) => void;
57
+ //# sourceMappingURL=DSL_Ingest_GraphModifierHelper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DSL_Ingest_GraphModifierHelper.d.ts","sourceRoot":"","sources":["../../../src/stores/graph-modifier/DSL_Ingest_GraphModifierHelper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAiB5E,mEAAmE;AACnE,eAAO,MAAM,qBAAqB,GAAI,QAAQ,gBAAgB,KAAG,MAAM,EAKlD,CAAC;AAEtB,8EAA8E;AAC9E,MAAM,WAAW,6BAA6B;IAC5C,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,8FAA8F;IAC9F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,2EAA2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,GACrC,QAAQ,gBAAgB,KACvB,sBAAsB,EA2BnB,CAAC;AAEP;;;;;;;;GAQG;AACH,eAAO,MAAM,oCAAoC,WAErC,gBAAgB,QAClB,MAAM,UACJ,WAAW,WACV,6BAA6B,KACrC,IA8BJ,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uCAAuC,WAExC,gBAAgB,QAClB,MAAM,UACJ,WAAW,YACT,6BAA6B,KACtC,IA4DJ,CAAC"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Copyright (c) 2026-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { RawLambda } from '@finos/legend-graph';
17
+ import { isObject, isString } from '@finos/legend-shared';
18
+ import { action } from 'mobx';
19
+ /** The source of a data set whose rows a function computes: a materialized view */
20
+ const MATERIALIZED_VIEW_SOURCE_TYPE = 'FunctionSource';
21
+ /**
22
+ * The lists the engine gives every data set it parses, and reads: a data set
23
+ * Studio writes holds each, empty when it has none
24
+ */
25
+ const DATA_SET_LIST_KEYS = [
26
+ 'ingestPartitionColumns',
27
+ 'preprocessors',
28
+ 'storageLayoutClusterColumns',
29
+ 'storageLayoutPartitionColumns',
30
+ ];
31
+ /** The ingest definition's data sets, as its content holds them */
32
+ export const getIngestDataSetNames = (ingest) => (Array.isArray(ingest.content.datasets) ? ingest.content.datasets : [])
33
+ .map((dataSet) => isObject(dataSet) ? dataSet.name : undefined)
34
+ .filter(isString);
35
+ /** The materialized views of the ingest definition, as its content holds them */
36
+ export const getIngestMaterializedViews = (ingest) => (Array.isArray(ingest.content.datasets) ? ingest.content.datasets : [])
37
+ .filter(isObject)
38
+ .flatMap((dataSet) => {
39
+ const { name, source, primaryKey, privacyClassification } = dataSet;
40
+ const lambda = isObject(source)
41
+ ? source.function
42
+ : undefined;
43
+ const sensitivity = isObject(privacyClassification)
44
+ ? privacyClassification.sensitivity
45
+ : undefined;
46
+ return isString(name) &&
47
+ source?._type ===
48
+ MATERIALIZED_VIEW_SOURCE_TYPE &&
49
+ isObject(lambda)
50
+ ? [
51
+ {
52
+ name,
53
+ lambda: lambda,
54
+ primaryKey: Array.isArray(primaryKey)
55
+ ? primaryKey.filter(isString)
56
+ : [],
57
+ sensitivity: isString(sensitivity) ? sensitivity : undefined,
58
+ },
59
+ ]
60
+ : [];
61
+ });
62
+ /**
63
+ * Adds a materialized view to the ingest definition: a data set whose rows
64
+ * the lambda (protocol JSON) computes, with its primary key and the
65
+ * classification of its data. It holds every key the engine gives a data
66
+ * set it parses, its lists empty, as the engine reads them all: a view
67
+ * without a `privacyClassification` failed with a NullPointerException.
68
+ * The content is replaced, so the change is seen, and the view is listed
69
+ * for Lineage and View SQL as one read from the definition would be
70
+ */
71
+ export const ingestDefinition_addMaterializedView = action((ingest, name, lambda, options) => {
72
+ const dataSets = Array.isArray(ingest.content.datasets)
73
+ ? ingest.content.datasets
74
+ : [];
75
+ ingest.content = {
76
+ ...ingest.content,
77
+ datasets: [
78
+ ...dataSets,
79
+ {
80
+ name,
81
+ primaryKey: [...options.primaryKey],
82
+ privacyClassification: { sensitivity: options.sensitivity },
83
+ source: { _type: MATERIALIZED_VIEW_SOURCE_TYPE, function: lambda },
84
+ ...Object.fromEntries(DATA_SET_LIST_KEYS.map((key) => [key, []])),
85
+ },
86
+ ],
87
+ };
88
+ ingest.TEMPORARY_MATVIEW_FUNCTION_DATA_SETS = [
89
+ ...(ingest.TEMPORARY_MATVIEW_FUNCTION_DATA_SETS ?? []),
90
+ {
91
+ name,
92
+ source: {
93
+ function: new RawLambda(Array.isArray(lambda.parameters) ? lambda.parameters : [], lambda.body),
94
+ },
95
+ },
96
+ ];
97
+ });
98
+ /**
99
+ * Replaces a materialized view's lambda (protocol JSON) in place: its name,
100
+ * its place among the data sets and its other keys stay, as does its place
101
+ * among the views listed for Lineage and View SQL. A primary key and a
102
+ * classification given replace the view's, and the lists the engine reads
103
+ * that the view lacks, e.g. as Studio wrote a view before it wrote them, are
104
+ * added empty
105
+ */
106
+ export const ingestDefinition_updateMaterializedView = action((ingest, name, lambda, options) => {
107
+ const dataSets = Array.isArray(ingest.content.datasets)
108
+ ? ingest.content.datasets
109
+ : [];
110
+ ingest.content = {
111
+ ...ingest.content,
112
+ datasets: dataSets.map((dataSet) => {
113
+ if (!isObject(dataSet)) {
114
+ return dataSet;
115
+ }
116
+ const { name: dataSetName, source, privacyClassification, } = dataSet;
117
+ if (dataSetName !== name ||
118
+ !isObject(source) ||
119
+ source._type !== MATERIALIZED_VIEW_SOURCE_TYPE) {
120
+ return dataSet;
121
+ }
122
+ return {
123
+ ...dataSet,
124
+ ...(options
125
+ ? {
126
+ primaryKey: [...options.primaryKey],
127
+ privacyClassification: {
128
+ ...(isObject(privacyClassification)
129
+ ? privacyClassification
130
+ : {}),
131
+ sensitivity: options.sensitivity,
132
+ },
133
+ }
134
+ : {}),
135
+ source: { ...source, function: lambda },
136
+ ...Object.fromEntries(DATA_SET_LIST_KEYS.filter((key) => !Array.isArray(dataSet[key])).map((key) => [key, []])),
137
+ };
138
+ }),
139
+ };
140
+ ingest.TEMPORARY_MATVIEW_FUNCTION_DATA_SETS =
141
+ ingest.TEMPORARY_MATVIEW_FUNCTION_DATA_SETS?.map((view) => view.name === name
142
+ ? {
143
+ ...view,
144
+ source: {
145
+ ...view.source,
146
+ function: new RawLambda(Array.isArray(lambda.parameters) ? lambda.parameters : [], lambda.body),
147
+ },
148
+ }
149
+ : view);
150
+ });
151
+ //# sourceMappingURL=DSL_Ingest_GraphModifierHelper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DSL_Ingest_GraphModifierHelper.js","sourceRoot":"","sources":["../../../src/stores/graph-modifier/DSL_Ingest_GraphModifierHelper.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finos/legend-application-studio",
3
- "version": "28.21.51",
3
+ "version": "28.21.53",
4
4
  "description": "Legend Studio application core",
5
5
  "keywords": [
6
6
  "legend",
@@ -47,17 +47,19 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@dagrejs/dagre": "1.1.4",
50
- "@finos/legend-application": "16.0.128",
51
- "@finos/legend-art": "7.1.168",
52
- "@finos/legend-code-editor": "2.0.210",
53
- "@finos/legend-data-cube": "0.3.128",
54
- "@finos/legend-extension-dsl-data-product": "0.1.6",
55
- "@finos/legend-extension-dsl-diagram": "8.1.274",
56
- "@finos/legend-graph": "32.7.6",
57
- "@finos/legend-lego": "2.0.230",
58
- "@finos/legend-query-builder": "4.19.19",
50
+ "@finos/legend-application": "16.0.129",
51
+ "@finos/legend-art": "7.1.169",
52
+ "@finos/legend-code-editor": "2.0.211",
53
+ "@finos/legend-cube": "0.0.6",
54
+ "@finos/legend-cube-builder": "0.0.6",
55
+ "@finos/legend-data-cube": "0.3.129",
56
+ "@finos/legend-extension-dsl-data-product": "0.2.1",
57
+ "@finos/legend-extension-dsl-diagram": "8.1.275",
58
+ "@finos/legend-graph": "32.8.0",
59
+ "@finos/legend-lego": "2.0.231",
60
+ "@finos/legend-query-builder": "4.19.20",
59
61
  "@finos/legend-server-depot": "6.1.24",
60
- "@finos/legend-server-lakehouse": "0.3.90",
62
+ "@finos/legend-server-lakehouse": "0.4.0",
61
63
  "@finos/legend-server-sdlc": "5.5.2",
62
64
  "@finos/legend-server-showcase": "0.2.73",
63
65
  "@finos/legend-shared": "11.0.32",
@@ -55,6 +55,7 @@ import { WorkspaceType } from '@finos/legend-server-sdlc';
55
55
  import { WorkspaceSyncConflictResolver } from './side-bar/WorkspaceSyncConflictResolver.js';
56
56
  import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../__lib__/LegendStudioApplicationNavigationContext.js';
57
57
  import { EmbeddedQueryBuilder } from './EmbeddedQueryBuilder.js';
58
+ import { EmbeddedCube } from './embedded-cube/EmbeddedCube.js';
58
59
  import { GRAPH_EDITOR_MODE } from '../../stores/editor/EditorConfig.js';
59
60
  import { QuickInput } from './QuickInput.js';
60
61
  import { ShowcaseManager } from '../ShowcaseManager.js';
@@ -301,6 +302,7 @@ export const Editor = withEditorStore(
301
302
  <WorkspaceSyncConflictResolver />
302
303
  )}
303
304
  <EmbeddedQueryBuilder />
305
+ <EmbeddedCube />
304
306
  {editorStore.embeddedDataCubeViewerState && (
305
307
  <QueryDataCubeViewer
306
308
  state={editorStore.embeddedDataCubeViewerState}
@@ -34,6 +34,11 @@ import {
34
34
  SQLIcon,
35
35
  clsx,
36
36
  PanelLoadingIndicator,
37
+ CubeIcon,
38
+ CaretDownIcon,
39
+ ControlledDropdownMenu,
40
+ MenuContent,
41
+ MenuContentItem,
37
42
  } from '@finos/legend-art';
38
43
  import {
39
44
  INGEST_DEFINITION_TAB,
@@ -53,6 +58,7 @@ import {
53
58
  } from '@finos/legend-query-builder';
54
59
  import type { MatViewDataSet } from '@finos/legend-graph';
55
60
  import { IngestTestableEditor } from './testable/IngestTestableEditor.js';
61
+ import { getIngestMaterializedViews } from '../../../../stores/graph-modifier/DSL_Ingest_GraphModifierHelper.js';
56
62
 
57
63
  export const IngestLineageModal = observer(
58
64
  (props: { ingestDefinitionEditorState: IngestDefinitionEditorState }) => {
@@ -179,6 +185,8 @@ export const IngestDefinitionEditor = observer(() => {
179
185
  IngestDefinitionEditorState,
180
186
  );
181
187
  const ingestDef = ingestDefinitionEditorState.ingest;
188
+ // the views Cube can open to edit (Edit MatView, PLAN §11.18)
189
+ const materializedViews = getIngestMaterializedViews(ingestDef);
182
190
  const isValidForLineage = ingestDefinitionEditorState.validForLineageViewer;
183
191
  const selectedTab = ingestDefinitionEditorState.selectedTab;
184
192
 
@@ -305,6 +313,60 @@ export const IngestDefinitionEditor = observer(() => {
305
313
  </button>
306
314
  </div>
307
315
  )}
316
+ {/* sized to its label, longer than the other buttons' */}
317
+ <div className="btn__dropdown-combo btn__dropdown-combo--primary !w-auto">
318
+ <button
319
+ className="btn__dropdown-combo__label !w-auto"
320
+ onClick={() =>
321
+ editorStore.embeddedCubeState.open(ingestDef)
322
+ }
323
+ tabIndex={-1}
324
+ disabled={ingestDefinitionEditorState.isReadOnly}
325
+ title="Build a materialized view of the project's ingest data sets in Legend Cube"
326
+ >
327
+ <CubeIcon className="btn__dropdown-combo__label__icon" />
328
+ <div className="btn__dropdown-combo__label__title whitespace-nowrap pr-2">
329
+ Create MatView
330
+ </div>
331
+ </button>
332
+ {materializedViews.length > 0 && (
333
+ <ControlledDropdownMenu
334
+ className="btn__dropdown-combo__dropdown-btn"
335
+ title="Edit a materialized view with Cube"
336
+ disabled={ingestDefinitionEditorState.isReadOnly}
337
+ content={
338
+ <MenuContent>
339
+ {materializedViews.map(({ name }) => (
340
+ <MenuContentItem
341
+ key={name}
342
+ className="btn__dropdown-combo__option"
343
+ onClick={() =>
344
+ editorStore.embeddedCubeState.open(
345
+ ingestDef,
346
+ name,
347
+ )
348
+ }
349
+ >
350
+ {`Edit MatView ${name}`}
351
+ </MenuContentItem>
352
+ ))}
353
+ </MenuContent>
354
+ }
355
+ menuProps={{
356
+ anchorOrigin: {
357
+ vertical: 'bottom',
358
+ horizontal: 'right',
359
+ },
360
+ transformOrigin: {
361
+ vertical: 'top',
362
+ horizontal: 'right',
363
+ },
364
+ }}
365
+ >
366
+ <CaretDownIcon />
367
+ </ControlledDropdownMenu>
368
+ )}
369
+ </div>
308
370
  </div>
309
371
  </PanelHeaderActions>
310
372
  </PanelHeader>
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Copyright (c) 2026-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import {
18
+ CubesLoadingIndicator,
19
+ CubesLoadingIndicatorIcon,
20
+ } from '@finos/legend-art';
21
+ import { observer } from 'mobx-react-lite';
22
+ import { lazy, Suspense } from 'react';
23
+ import { useEditorStore } from '../EditorStoreProvider.js';
24
+
25
+ // Loaded on the first opening, so Cube and its host stay out of Studio's
26
+ // main bundle, as Legend Query loads its Cube page (`LegendQueryCubeRoute`)
27
+ const LazyEmbeddedCubeEditor = lazy(() =>
28
+ import('./EmbeddedCubeEditor.js').then((module) => ({
29
+ default: module.EmbeddedCubeEditor,
30
+ })),
31
+ );
32
+
33
+ /**
34
+ * Legend Cube, full screen over the editor, while it is open on an ingest
35
+ * definition (Create MatView); nothing otherwise
36
+ */
37
+ export const EmbeddedCube = observer(() => {
38
+ const { embeddedCubeState } = useEditorStore();
39
+ const { ingest } = embeddedCubeState;
40
+ if (!ingest) {
41
+ return null;
42
+ }
43
+ return (
44
+ <Suspense
45
+ fallback={
46
+ <CubesLoadingIndicator isLoading={true}>
47
+ <CubesLoadingIndicatorIcon />
48
+ </CubesLoadingIndicator>
49
+ }
50
+ >
51
+ <LazyEmbeddedCubeEditor
52
+ embeddedCubeState={embeddedCubeState}
53
+ ingest={ingest}
54
+ />
55
+ </Suspense>
56
+ );
57
+ });