@finos/legend-query-builder 4.18.32 → 4.19.1
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.
- package/lib/__lib__/QueryBuilderSetting.d.ts +1 -2
- package/lib/__lib__/QueryBuilderSetting.d.ts.map +1 -1
- package/lib/__lib__/QueryBuilderSetting.js +0 -4
- package/lib/__lib__/QueryBuilderSetting.js.map +1 -1
- package/lib/components/QueryBuilder.d.ts.map +1 -1
- package/lib/components/QueryBuilder.js +3 -7
- package/lib/components/QueryBuilder.js.map +1 -1
- package/lib/components/QueryBuilderUnsupportedQueryEditor.d.ts.map +1 -1
- package/lib/components/QueryBuilderUnsupportedQueryEditor.js +1 -2
- package/lib/components/QueryBuilderUnsupportedQueryEditor.js.map +1 -1
- package/lib/components/QueryLoader.d.ts.map +1 -1
- package/lib/components/QueryLoader.js +215 -92
- package/lib/components/QueryLoader.js.map +1 -1
- package/lib/components/{QueryChat.d.ts → lakehouse/IngestionDefinitionArtifactViewer.d.ts} +7 -5
- package/lib/components/lakehouse/IngestionDefinitionArtifactViewer.d.ts.map +1 -0
- package/lib/components/lakehouse/IngestionDefinitionArtifactViewer.js +122 -0
- package/lib/components/lakehouse/IngestionDefinitionArtifactViewer.js.map +1 -0
- package/lib/components/result/tds/QueryBuilderTDSResultShared.d.ts +2 -1
- package/lib/components/result/tds/QueryBuilderTDSResultShared.d.ts.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSResultShared.js +11 -6
- package/lib/components/result/tds/QueryBuilderTDSResultShared.js.map +1 -1
- package/lib/components/workflows/DataProductQueryBuilder.d.ts.map +1 -1
- package/lib/components/workflows/DataProductQueryBuilder.js +7 -4
- package/lib/components/workflows/DataProductQueryBuilder.js.map +1 -1
- package/lib/data-access-overview.css +1 -1
- package/lib/graph-manager/QueryBuilderConfig.d.ts +0 -8
- package/lib/graph-manager/QueryBuilderConfig.d.ts.map +1 -1
- package/lib/graph-manager/QueryBuilderConfig.js +0 -10
- package/lib/graph-manager/QueryBuilderConfig.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/QueryBuilderState.d.ts +0 -5
- package/lib/stores/QueryBuilderState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderState.js +0 -19
- package/lib/stores/QueryBuilderState.js.map +1 -1
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts +0 -5
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts.map +1 -1
- package/lib/stores/QueryLoaderState.d.ts +39 -3
- package/lib/stores/QueryLoaderState.d.ts.map +1 -1
- package/lib/stores/QueryLoaderState.js +129 -2
- package/lib/stores/QueryLoaderState.js.map +1 -1
- package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.d.ts +6 -0
- package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.d.ts.map +1 -1
- package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.js +6 -3
- package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.js.map +1 -1
- package/package.json +7 -7
- package/src/__lib__/QueryBuilderSetting.ts +0 -4
- package/src/components/QueryBuilder.tsx +0 -31
- package/src/components/QueryBuilderUnsupportedQueryEditor.tsx +0 -7
- package/src/components/QueryLoader.tsx +708 -381
- package/src/components/lakehouse/IngestionDefinitionArtifactViewer.tsx +370 -0
- package/src/components/result/tds/QueryBuilderTDSResultShared.tsx +15 -6
- package/src/components/workflows/DataProductQueryBuilder.tsx +20 -5
- package/src/graph-manager/QueryBuilderConfig.ts +0 -11
- package/src/index.ts +1 -1
- package/src/stores/QueryBuilderState.ts +0 -26
- package/src/stores/QueryBuilder_LegendApplicationPlugin_Extension.ts +0 -9
- package/src/stores/QueryLoaderState.ts +173 -2
- package/src/stores/workflows/dataProduct/DataProductQueryBuilderState.ts +17 -8
- package/tsconfig.json +1 -2
- package/lib/components/QueryChat.d.ts.map +0 -1
- package/lib/components/QueryChat.js +0 -26
- package/lib/components/QueryChat.js.map +0 -1
- package/lib/stores/QueryChatState.d.ts +0 -19
- package/lib/stores/QueryChatState.d.ts.map +0 -1
- package/lib/stores/QueryChatState.js +0 -18
- package/lib/stores/QueryChatState.js.map +0 -1
- package/src/components/QueryChat.tsx +0 -38
- package/src/stores/QueryChatState.ts +0 -19
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2020-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 { observer } from 'mobx-react-lite';
|
|
18
|
+
import { useMemo, useState } from 'react';
|
|
19
|
+
import {
|
|
20
|
+
clsx,
|
|
21
|
+
Dialog,
|
|
22
|
+
Modal,
|
|
23
|
+
ModalBody,
|
|
24
|
+
ModalFooter,
|
|
25
|
+
ModalFooterButton,
|
|
26
|
+
ModalHeader,
|
|
27
|
+
ModalHeaderActions,
|
|
28
|
+
ModalTitle,
|
|
29
|
+
FilledWindowMaximizeIcon,
|
|
30
|
+
CompressIcon,
|
|
31
|
+
ResizablePanel,
|
|
32
|
+
ResizablePanelGroup,
|
|
33
|
+
ResizablePanelSplitter,
|
|
34
|
+
ResizablePanelSplitterLine,
|
|
35
|
+
} from '@finos/legend-art';
|
|
36
|
+
import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
|
|
37
|
+
import { CodeEditor } from '@finos/legend-lego/code-editor';
|
|
38
|
+
import {
|
|
39
|
+
DataGrid,
|
|
40
|
+
type DataGridColumnDefinition,
|
|
41
|
+
} from '@finos/legend-lego/data-grid';
|
|
42
|
+
import {
|
|
43
|
+
InstanceValue,
|
|
44
|
+
type IngestionArtifactMatViewImplementation,
|
|
45
|
+
type IngestionDefinitionArtifact,
|
|
46
|
+
type RelationColumn,
|
|
47
|
+
getMultiplicityPrettyDescription,
|
|
48
|
+
} from '@finos/legend-graph';
|
|
49
|
+
import { isNonNullable } from '@finos/legend-shared';
|
|
50
|
+
import { tryToFormatSql } from '../result/tds/QueryBuilderTDSResultShared.js';
|
|
51
|
+
|
|
52
|
+
enum INGEST_ARTIFACT_VIEW_MODE {
|
|
53
|
+
FORM = 'Form',
|
|
54
|
+
JSON = 'JSON',
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
enum INGEST_ARTIFACT_SQL_TAB {
|
|
58
|
+
VIEW_FUNCTION = 'View Function',
|
|
59
|
+
BARRIER = 'Barrier',
|
|
60
|
+
SELECT = 'Select',
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const getColumnTypeLabel = (column: RelationColumn): string => {
|
|
64
|
+
const typeName = column.genericType.value.rawType.name;
|
|
65
|
+
const typeVariableValues = column.genericType.value.typeVariableValues;
|
|
66
|
+
if (typeVariableValues && typeVariableValues.length > 0) {
|
|
67
|
+
const args = typeVariableValues
|
|
68
|
+
.map((v) => (v instanceof InstanceValue ? v.values[0] : undefined))
|
|
69
|
+
.filter(isNonNullable);
|
|
70
|
+
if (args.length > 0) {
|
|
71
|
+
return `${typeName}(${args.join(', ')})`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return typeName;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const schemaColumnDefs: DataGridColumnDefinition<RelationColumn>[] = [
|
|
78
|
+
{
|
|
79
|
+
headerName: 'Column Name',
|
|
80
|
+
field: 'name',
|
|
81
|
+
flex: 1,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
headerName: 'Column Type',
|
|
85
|
+
flex: 1,
|
|
86
|
+
valueGetter: (params) =>
|
|
87
|
+
params.data ? getColumnTypeLabel(params.data) : '',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
headerName: 'Multiplicity',
|
|
91
|
+
flex: 1,
|
|
92
|
+
valueGetter: (params) =>
|
|
93
|
+
params.data
|
|
94
|
+
? getMultiplicityPrettyDescription(params.data.multiplicity)
|
|
95
|
+
: '',
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
const MatViewSection = observer(
|
|
100
|
+
(props: {
|
|
101
|
+
matView: IngestionArtifactMatViewImplementation;
|
|
102
|
+
darkMode: boolean;
|
|
103
|
+
}) => {
|
|
104
|
+
const { matView, darkMode } = props;
|
|
105
|
+
const [selectedSqlTab, setSelectedSqlTab] =
|
|
106
|
+
useState<INGEST_ARTIFACT_SQL_TAB>(INGEST_ARTIFACT_SQL_TAB.VIEW_FUNCTION);
|
|
107
|
+
|
|
108
|
+
const sqlTabs: {
|
|
109
|
+
label: INGEST_ARTIFACT_SQL_TAB;
|
|
110
|
+
sql: string | undefined;
|
|
111
|
+
}[] = useMemo(
|
|
112
|
+
() => [
|
|
113
|
+
{
|
|
114
|
+
label: INGEST_ARTIFACT_SQL_TAB.VIEW_FUNCTION,
|
|
115
|
+
sql: matView.viewFunctionQuery.sql,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
label: INGEST_ARTIFACT_SQL_TAB.BARRIER,
|
|
119
|
+
sql: matView.barrierQuery?.sql,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
label: INGEST_ARTIFACT_SQL_TAB.SELECT,
|
|
123
|
+
sql: matView.selectQuery?.sql,
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
[matView],
|
|
127
|
+
);
|
|
128
|
+
const currentSql = sqlTabs.find((t) => t.label === selectedSqlTab)?.sql;
|
|
129
|
+
const formattedSql = useMemo(
|
|
130
|
+
() => (currentSql ? tryToFormatSql(currentSql) : ''),
|
|
131
|
+
[currentSql],
|
|
132
|
+
);
|
|
133
|
+
return (
|
|
134
|
+
<div className="ingest-artifact-viewer__matview">
|
|
135
|
+
<div className="ingest-artifact-viewer__matview__summary">
|
|
136
|
+
<div className="ingest-artifact-viewer__matview__summary__name">
|
|
137
|
+
{matView.datasetName}
|
|
138
|
+
</div>
|
|
139
|
+
<div className="ingest-artifact-viewer__matview__summary__meta">
|
|
140
|
+
<span>Refresh: {matView.refreshType}</span>
|
|
141
|
+
<span>Auto Trigger: {String(matView.autoTrigger)}</span>
|
|
142
|
+
{matView.primaryKey.length > 0 && (
|
|
143
|
+
<span>Primary Key: {matView.primaryKey.join(', ')}</span>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
{matView.dependentDatasets.length > 0 && (
|
|
149
|
+
<div className="ingest-artifact-viewer__section">
|
|
150
|
+
<div className="ingest-artifact-viewer__section__title">
|
|
151
|
+
Dependent Datasets
|
|
152
|
+
</div>
|
|
153
|
+
<ul className="ingest-artifact-viewer__section__list">
|
|
154
|
+
{matView.dependentDatasets.map((ds) => (
|
|
155
|
+
<li key={`${ds.schema}.${ds.dataset}`}>
|
|
156
|
+
<code>{`${ds.schema}.${ds.dataset}`}</code>
|
|
157
|
+
{' — '}
|
|
158
|
+
<span>{ds.ingestDefinition.path}</span>
|
|
159
|
+
</li>
|
|
160
|
+
))}
|
|
161
|
+
</ul>
|
|
162
|
+
</div>
|
|
163
|
+
)}
|
|
164
|
+
|
|
165
|
+
{matView.schema && matView.schema.columns.length > 0 && (
|
|
166
|
+
<div className="ingest-artifact-viewer__section">
|
|
167
|
+
<div className="ingest-artifact-viewer__section__title">Schema</div>
|
|
168
|
+
<div
|
|
169
|
+
className={clsx('ingest-artifact-viewer__matview__schema-grid', {
|
|
170
|
+
'ag-theme-balham': !darkMode,
|
|
171
|
+
'ag-theme-balham-dark': darkMode,
|
|
172
|
+
})}
|
|
173
|
+
>
|
|
174
|
+
<DataGrid
|
|
175
|
+
rowData={matView.schema.columns}
|
|
176
|
+
columnDefs={schemaColumnDefs}
|
|
177
|
+
domLayout="autoHeight"
|
|
178
|
+
/>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
)}
|
|
182
|
+
|
|
183
|
+
<div className="ingest-artifact-viewer__matview__sql">
|
|
184
|
+
<div className="ingest-artifact-viewer__tabs">
|
|
185
|
+
{sqlTabs.map((tab) => (
|
|
186
|
+
<button
|
|
187
|
+
key={tab.label}
|
|
188
|
+
className={clsx('ingest-artifact-viewer__tab', {
|
|
189
|
+
'ingest-artifact-viewer__tab--active':
|
|
190
|
+
selectedSqlTab === tab.label,
|
|
191
|
+
'ingest-artifact-viewer__tab--disabled': !tab.sql,
|
|
192
|
+
})}
|
|
193
|
+
disabled={!tab.sql}
|
|
194
|
+
onClick={() => setSelectedSqlTab(tab.label)}
|
|
195
|
+
tabIndex={-1}
|
|
196
|
+
>
|
|
197
|
+
{tab.label}
|
|
198
|
+
</button>
|
|
199
|
+
))}
|
|
200
|
+
</div>
|
|
201
|
+
<div className="ingest-artifact-viewer__matview__sql__editor">
|
|
202
|
+
<CodeEditor
|
|
203
|
+
inputValue={formattedSql}
|
|
204
|
+
isReadOnly={true}
|
|
205
|
+
language={CODE_EDITOR_LANGUAGE.SQL}
|
|
206
|
+
/>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
);
|
|
211
|
+
},
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
const IngestionDefinitionArtifactContent = observer(
|
|
215
|
+
(props: { artifact: IngestionDefinitionArtifact; darkMode: boolean }) => {
|
|
216
|
+
const { artifact, darkMode } = props;
|
|
217
|
+
const [viewMode, setViewMode] = useState<INGEST_ARTIFACT_VIEW_MODE>(
|
|
218
|
+
INGEST_ARTIFACT_VIEW_MODE.FORM,
|
|
219
|
+
);
|
|
220
|
+
const [selectedMatViewIndex, setSelectedMatViewIndex] = useState(0);
|
|
221
|
+
const matViews = artifact.matViewImplementations;
|
|
222
|
+
const selectedMatView = matViews[selectedMatViewIndex];
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
<div className="ingest-artifact-viewer__content">
|
|
226
|
+
<div className="ingest-artifact-viewer__tabs">
|
|
227
|
+
{Object.values(INGEST_ARTIFACT_VIEW_MODE).map((mode) => (
|
|
228
|
+
<button
|
|
229
|
+
key={mode}
|
|
230
|
+
className={clsx('ingest-artifact-viewer__tab', {
|
|
231
|
+
'ingest-artifact-viewer__tab--active': viewMode === mode,
|
|
232
|
+
})}
|
|
233
|
+
onClick={() => setViewMode(mode)}
|
|
234
|
+
tabIndex={-1}
|
|
235
|
+
>
|
|
236
|
+
{mode}
|
|
237
|
+
</button>
|
|
238
|
+
))}
|
|
239
|
+
</div>
|
|
240
|
+
|
|
241
|
+
{viewMode === INGEST_ARTIFACT_VIEW_MODE.FORM && (
|
|
242
|
+
<div className="ingest-artifact-viewer__form">
|
|
243
|
+
{matViews.length === 0 && (
|
|
244
|
+
<div className="ingest-artifact-viewer__empty">
|
|
245
|
+
No materialized view implementations found.
|
|
246
|
+
</div>
|
|
247
|
+
)}
|
|
248
|
+
{matViews.length > 0 && (
|
|
249
|
+
<div className="ingest-artifact-viewer__matviews">
|
|
250
|
+
<ResizablePanelGroup orientation="vertical">
|
|
251
|
+
<ResizablePanel size={240} minSize={160}>
|
|
252
|
+
<div className="ingest-artifact-viewer__matview-explorer">
|
|
253
|
+
<div className="ingest-artifact-viewer__matview-explorer__title">
|
|
254
|
+
Materialized Views
|
|
255
|
+
</div>
|
|
256
|
+
<div className="ingest-artifact-viewer__matview-explorer__list">
|
|
257
|
+
{matViews.map((mv, idx) => (
|
|
258
|
+
<button
|
|
259
|
+
key={mv.datasetName}
|
|
260
|
+
className={clsx(
|
|
261
|
+
'ingest-artifact-viewer__matview-explorer__item',
|
|
262
|
+
{
|
|
263
|
+
'ingest-artifact-viewer__matview-explorer__item--active':
|
|
264
|
+
selectedMatViewIndex === idx,
|
|
265
|
+
},
|
|
266
|
+
)}
|
|
267
|
+
onClick={() => setSelectedMatViewIndex(idx)}
|
|
268
|
+
tabIndex={-1}
|
|
269
|
+
title={mv.datasetName}
|
|
270
|
+
>
|
|
271
|
+
{mv.datasetName}
|
|
272
|
+
</button>
|
|
273
|
+
))}
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
</ResizablePanel>
|
|
277
|
+
<ResizablePanelSplitter>
|
|
278
|
+
<ResizablePanelSplitterLine color="var(--color-border-default)" />
|
|
279
|
+
</ResizablePanelSplitter>
|
|
280
|
+
<ResizablePanel minSize={320}>
|
|
281
|
+
<div className="ingest-artifact-viewer__matview-detail">
|
|
282
|
+
{selectedMatView && (
|
|
283
|
+
<MatViewSection
|
|
284
|
+
matView={selectedMatView}
|
|
285
|
+
darkMode={darkMode}
|
|
286
|
+
/>
|
|
287
|
+
)}
|
|
288
|
+
</div>
|
|
289
|
+
</ResizablePanel>
|
|
290
|
+
</ResizablePanelGroup>
|
|
291
|
+
</div>
|
|
292
|
+
)}
|
|
293
|
+
</div>
|
|
294
|
+
)}
|
|
295
|
+
|
|
296
|
+
{viewMode === INGEST_ARTIFACT_VIEW_MODE.JSON && (
|
|
297
|
+
<div className="ingest-artifact-viewer__json">
|
|
298
|
+
<CodeEditor
|
|
299
|
+
inputValue={JSON.stringify(artifact.content, null, 2)}
|
|
300
|
+
isReadOnly={true}
|
|
301
|
+
language={CODE_EDITOR_LANGUAGE.JSON}
|
|
302
|
+
/>
|
|
303
|
+
</div>
|
|
304
|
+
)}
|
|
305
|
+
</div>
|
|
306
|
+
);
|
|
307
|
+
},
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
export const IngestionDefinitionArtifactViewer = observer(
|
|
311
|
+
(props: {
|
|
312
|
+
artifact: IngestionDefinitionArtifact | undefined;
|
|
313
|
+
onClose: () => void;
|
|
314
|
+
darkMode?: boolean | undefined;
|
|
315
|
+
}) => {
|
|
316
|
+
const { artifact, onClose, darkMode = true } = props;
|
|
317
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
318
|
+
|
|
319
|
+
if (!artifact) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return (
|
|
324
|
+
<Dialog
|
|
325
|
+
open={Boolean(artifact)}
|
|
326
|
+
onClose={onClose}
|
|
327
|
+
classes={{
|
|
328
|
+
root: 'editor-modal__root-container',
|
|
329
|
+
container: 'editor-modal__container',
|
|
330
|
+
paper: 'editor-modal__content',
|
|
331
|
+
}}
|
|
332
|
+
>
|
|
333
|
+
<Modal
|
|
334
|
+
className={clsx('editor-modal ingest-artifact-viewer', {
|
|
335
|
+
'ingest-artifact-viewer--fullscreen': isFullscreen,
|
|
336
|
+
})}
|
|
337
|
+
darkMode={darkMode}
|
|
338
|
+
>
|
|
339
|
+
<ModalHeader>
|
|
340
|
+
<ModalTitle title="Generated Ingest Artifact" />
|
|
341
|
+
<ModalHeaderActions>
|
|
342
|
+
<button
|
|
343
|
+
className="ingest-artifact-viewer__header-btn"
|
|
344
|
+
onClick={() => setIsFullscreen(!isFullscreen)}
|
|
345
|
+
tabIndex={-1}
|
|
346
|
+
title={isFullscreen ? 'Exit full screen' : 'Full screen'}
|
|
347
|
+
>
|
|
348
|
+
{isFullscreen ? <CompressIcon /> : <FilledWindowMaximizeIcon />}
|
|
349
|
+
</button>
|
|
350
|
+
</ModalHeaderActions>
|
|
351
|
+
</ModalHeader>
|
|
352
|
+
<ModalBody className="ingest-artifact-viewer__body">
|
|
353
|
+
<IngestionDefinitionArtifactContent
|
|
354
|
+
artifact={artifact}
|
|
355
|
+
darkMode={darkMode}
|
|
356
|
+
/>
|
|
357
|
+
</ModalBody>
|
|
358
|
+
<ModalFooter>
|
|
359
|
+
<ModalFooterButton
|
|
360
|
+
onClick={onClose}
|
|
361
|
+
text="Close"
|
|
362
|
+
type="secondary"
|
|
363
|
+
darkMode={darkMode}
|
|
364
|
+
/>
|
|
365
|
+
</ModalFooter>
|
|
366
|
+
</Modal>
|
|
367
|
+
</Dialog>
|
|
368
|
+
);
|
|
369
|
+
},
|
|
370
|
+
);
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
InstanceValue,
|
|
34
34
|
RelationalExecutionActivities,
|
|
35
35
|
} from '@finos/legend-graph';
|
|
36
|
-
import { format as formatSQL } from 'sql-formatter';
|
|
36
|
+
import { format as formatSQL, type SqlLanguage } from 'sql-formatter';
|
|
37
37
|
import {
|
|
38
38
|
type ApplicationStore,
|
|
39
39
|
type LegendApplicationConfig,
|
|
@@ -50,6 +50,7 @@ import { forwardRef } from 'react';
|
|
|
50
50
|
import {
|
|
51
51
|
QueryBuilderDerivationProjectionColumnState,
|
|
52
52
|
QueryBuilderProjectionColumnState,
|
|
53
|
+
QueryBuilderRelationColumnProjectionColumnState,
|
|
53
54
|
QueryBuilderSimpleProjectionColumnState,
|
|
54
55
|
} from '../../../stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js';
|
|
55
56
|
import {
|
|
@@ -91,6 +92,7 @@ import {
|
|
|
91
92
|
FilterPropertyExpressionSourceState,
|
|
92
93
|
} from '../../../stores/filter/QueryBuilderFilterState.js';
|
|
93
94
|
import { QueryBuilderAggregateColumnState } from '../../../stores/fetch-structure/tds/aggregation/QueryBuilderAggregationState.js';
|
|
95
|
+
import { QueryBuilderWindowColumnState } from '../../../stores/fetch-structure/tds/window/QueryBuilderWindowState.js';
|
|
94
96
|
import type { QueryBuilderFilterOperator } from '../../../stores/filter/QueryBuilderFilterOperator.js';
|
|
95
97
|
import {
|
|
96
98
|
QueryBuilderFilterOperator_Equal,
|
|
@@ -107,9 +109,12 @@ import {
|
|
|
107
109
|
import type { QueryBuilderState } from '../../../stores/QueryBuilderState.js';
|
|
108
110
|
import type { QueryBuilderPropertyExpressionState } from '../../../stores/QueryBuilderPropertyEditorState.js';
|
|
109
111
|
|
|
110
|
-
export const tryToFormatSql = (
|
|
112
|
+
export const tryToFormatSql = (
|
|
113
|
+
sql: string,
|
|
114
|
+
language: SqlLanguage = 'mysql',
|
|
115
|
+
): string => {
|
|
111
116
|
try {
|
|
112
|
-
const formattedSql = formatSQL(sql, { language
|
|
117
|
+
const formattedSql = formatSQL(sql, { language });
|
|
113
118
|
return formattedSql;
|
|
114
119
|
} catch {
|
|
115
120
|
try {
|
|
@@ -209,7 +214,9 @@ const getExistingPostFilterNode = (
|
|
|
209
214
|
.filter(
|
|
210
215
|
(node) =>
|
|
211
216
|
node.condition.leftConditionValue instanceof
|
|
212
|
-
|
|
217
|
+
QueryBuilderProjectionColumnState ||
|
|
218
|
+
node.condition.leftConditionValue instanceof
|
|
219
|
+
QueryBuilderWindowColumnState,
|
|
213
220
|
)
|
|
214
221
|
.filter(
|
|
215
222
|
(node) =>
|
|
@@ -303,13 +310,13 @@ const generateNewPostFilterConditionNodeData = async (
|
|
|
303
310
|
let postFilterConditionState: PostFilterConditionState;
|
|
304
311
|
try {
|
|
305
312
|
const possibleProjectionColumnState = _cellData.columnName
|
|
306
|
-
? tdsState.projectionColumns
|
|
313
|
+
? (tdsState.projectionColumns
|
|
307
314
|
.filter((c) => c.columnName === _cellData.columnName)
|
|
308
315
|
.concat(
|
|
309
316
|
tdsState.aggregationState.columns
|
|
310
317
|
.filter((c) => c.columnName === _cellData.columnName)
|
|
311
318
|
.map((ag) => ag.projectionColumnState),
|
|
312
|
-
)[0]
|
|
319
|
+
)[0] ?? tdsColState)
|
|
313
320
|
: tdsColState;
|
|
314
321
|
|
|
315
322
|
if (possibleProjectionColumnState) {
|
|
@@ -673,6 +680,8 @@ const filterByOrOutValue = async (
|
|
|
673
680
|
if (
|
|
674
681
|
tdsColState instanceof QueryBuilderDerivationProjectionColumnState ||
|
|
675
682
|
tdsColState instanceof QueryBuilderAggregateColumnState ||
|
|
683
|
+
tdsColState instanceof QueryBuilderWindowColumnState ||
|
|
684
|
+
tdsColState instanceof QueryBuilderRelationColumnProjectionColumnState ||
|
|
676
685
|
(tdsColState instanceof QueryBuilderSimpleProjectionColumnState &&
|
|
677
686
|
isCollectionProperty(
|
|
678
687
|
tdsColState.propertyExpressionState.propertyExpression,
|
|
@@ -116,7 +116,17 @@ export const DataProductQueryBuilderSetupFormContent = observer(
|
|
|
116
116
|
value={queryBuilderState.selectedExecutionIdOption}
|
|
117
117
|
formatOptionLabel={(option: ExecutionIdOption) => (
|
|
118
118
|
<div className="query-builder__setup__config-group__item__selector__option">
|
|
119
|
-
<
|
|
119
|
+
<div className="query-builder__setup__config-group__item__selector__option__label">
|
|
120
|
+
<span>{option.label}</span>
|
|
121
|
+
{option.groupId !== undefined && (
|
|
122
|
+
<span
|
|
123
|
+
className="query-builder__setup__config-group__item__selector__option__subtitle"
|
|
124
|
+
title={`Access Point Group: ${option.groupId}`}
|
|
125
|
+
>
|
|
126
|
+
{option.groupId}
|
|
127
|
+
</span>
|
|
128
|
+
)}
|
|
129
|
+
</div>
|
|
120
130
|
<span className="query-builder__setup__config-group__item__selector__option__tag">
|
|
121
131
|
{option.tag}
|
|
122
132
|
</span>
|
|
@@ -150,15 +160,15 @@ const DataProductQueryBuilderSetupPanelContent = observer(
|
|
|
150
160
|
const applicationStore = useApplicationStore();
|
|
151
161
|
const executionState = queryBuilderState.executionState;
|
|
152
162
|
|
|
153
|
-
// runtime options (only for model access point group)
|
|
163
|
+
// runtime options (only for model access point group / lakehouse)
|
|
154
164
|
const runtimeRequired =
|
|
155
165
|
executionState instanceof ModelAccessPointDataProductExecutionState ||
|
|
156
166
|
executionState instanceof LakehouseDataProductExecutionState;
|
|
157
|
-
const showRuntimeSelector =
|
|
158
|
-
runtimeRequired && executionState.showRuntimeOptions;
|
|
167
|
+
const showRuntimeSelector = runtimeRequired;
|
|
159
168
|
const runtimeOptions = runtimeRequired
|
|
160
169
|
? executionState.compatibleRuntimes.map(buildElementOption)
|
|
161
170
|
: [];
|
|
171
|
+
const noCompatibleRuntimes = runtimeRequired && runtimeOptions.length === 0;
|
|
162
172
|
const selectedRuntimeOption =
|
|
163
173
|
runtimeRequired && executionState.selectedRuntime
|
|
164
174
|
? buildElementOption(executionState.selectedRuntime)
|
|
@@ -193,11 +203,16 @@ const DataProductQueryBuilderSetupPanelContent = observer(
|
|
|
193
203
|
<CustomSelectorInput
|
|
194
204
|
inputId="query-builder__setup__runtime-selector"
|
|
195
205
|
className="panel__content__form__section__dropdown query-builder__setup__config-group__item__selector"
|
|
196
|
-
placeholder=
|
|
206
|
+
placeholder={
|
|
207
|
+
noCompatibleRuntimes
|
|
208
|
+
? 'No compatible runtimes available'
|
|
209
|
+
: 'Choose a runtime...'
|
|
210
|
+
}
|
|
197
211
|
options={runtimeOptions}
|
|
198
212
|
disabled={runtimeOptions.length < 1}
|
|
199
213
|
onChange={onRuntimeOptionChange}
|
|
200
214
|
value={selectedRuntimeOption}
|
|
215
|
+
hasError={noCompatibleRuntimes}
|
|
201
216
|
darkMode={
|
|
202
217
|
!applicationStore.layoutService
|
|
203
218
|
.TEMPORARY__isLightColorThemeEnabled
|
|
@@ -23,20 +23,11 @@ export class QueryBuilderConfig {
|
|
|
23
23
|
*/
|
|
24
24
|
TEMPORARY__enableExportToCube = false;
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
* This flag is to disable query builder chat features
|
|
28
|
-
*/
|
|
29
|
-
TEMPORARY__disableQueryBuilderChat = false;
|
|
30
|
-
|
|
31
26
|
/**
|
|
32
27
|
* This flag is to enable AG-GRID enterprise mode
|
|
33
28
|
*/
|
|
34
29
|
TEMPORARY__enableGridEnterpriseMode = false;
|
|
35
30
|
|
|
36
|
-
/**
|
|
37
|
-
* This is the URL of the LegendAI service
|
|
38
|
-
*/
|
|
39
|
-
legendAIServiceURL = '';
|
|
40
31
|
/**
|
|
41
32
|
* This is the URL of the Legend MCP service
|
|
42
33
|
*/
|
|
@@ -59,10 +50,8 @@ export class QueryBuilderConfig {
|
|
|
59
50
|
|
|
60
51
|
static readonly serialization = new SerializationFactory(
|
|
61
52
|
createModelSchema(QueryBuilderConfig, {
|
|
62
|
-
TEMPORARY__disableQueryBuilderChat: optional(primitive()),
|
|
63
53
|
TEMPORARY__enableExportToCube: optional(primitive()),
|
|
64
54
|
TEMPORARY__enableGridEnterpriseMode: optional(primitive()),
|
|
65
|
-
legendAIServiceURL: optional(primitive()),
|
|
66
55
|
legendMCPServiceURL: optional(primitive()),
|
|
67
56
|
zipkinTraceBaseURL: optional(primitive()),
|
|
68
57
|
enableTypedTDS: optional(primitive()),
|
package/src/index.ts
CHANGED
|
@@ -46,7 +46,6 @@ export {
|
|
|
46
46
|
QueryBuilderExecutionContextState,
|
|
47
47
|
QueryBuilderEmbeddedFromExecutionContextState,
|
|
48
48
|
} from './stores/QueryBuilderExecutionContextState.js';
|
|
49
|
-
export { QueryChatState } from './stores/QueryChatState.js';
|
|
50
49
|
export {
|
|
51
50
|
getTDSColumnDerivedProperyFromType,
|
|
52
51
|
buildTDSSortTypeExpression,
|
|
@@ -146,6 +145,7 @@ export * from './stores/shared/V1_ValueSpecificationEditorHelper.js';
|
|
|
146
145
|
|
|
147
146
|
export * from './components/execution-plan/ExecutionPlanViewer.js';
|
|
148
147
|
export * from './components/lineage/LineageViewer.js';
|
|
148
|
+
export * from './components/lakehouse/IngestionDefinitionArtifactViewer.js';
|
|
149
149
|
|
|
150
150
|
export * from './stores/execution-plan/ExecutionPlanState.js';
|
|
151
151
|
export * from './stores/lineage/LineageState.js';
|
|
@@ -115,10 +115,8 @@ import {
|
|
|
115
115
|
} from './QueryBuilderExecutionContextState.js';
|
|
116
116
|
import type { QueryBuilderConfig } from '../graph-manager/QueryBuilderConfig.js';
|
|
117
117
|
import { QUERY_BUILDER_EVENT } from '../__lib__/QueryBuilderEvent.js';
|
|
118
|
-
import { QUERY_BUILDER_SETTING_KEY } from '../__lib__/QueryBuilderSetting.js';
|
|
119
118
|
import { QueryBuilderChangeHistoryState } from './QueryBuilderChangeHistoryState.js';
|
|
120
119
|
import { type QueryBuilderWorkflowState } from './query-workflow/QueryBuilderWorkFlowState.js';
|
|
121
|
-
import { type QueryChatState } from './QueryChatState.js';
|
|
122
120
|
import type { QueryBuilder_LegendApplicationPlugin_Extension } from './QueryBuilder_LegendApplicationPlugin_Extension.js';
|
|
123
121
|
import { createDataCubeViewerStateFromQueryBuilder } from './data-cube/QueryBuilderDataCubeHelper.js';
|
|
124
122
|
import type { QueryBuilderDataCubeViewerState } from './data-cube/QueryBuilderDataCubeViewerState.js';
|
|
@@ -216,7 +214,6 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
|
216
214
|
textEditorState: QueryBuilderTextEditorState;
|
|
217
215
|
unsupportedQueryState: QueryBuilderUnsupportedQueryState;
|
|
218
216
|
changeHistoryState: QueryBuilderChangeHistoryState;
|
|
219
|
-
isQueryChatOpened: boolean;
|
|
220
217
|
showFunctionsExplorerPanel = false;
|
|
221
218
|
showParametersPanel = false;
|
|
222
219
|
isEditingWatermark = false;
|
|
@@ -233,7 +230,6 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
|
233
230
|
QUERY_BUILDER_SUPPORTED_GET_ALL_FUNCTIONS.GET_ALL;
|
|
234
231
|
executionContextState: QueryBuilderExecutionContextState;
|
|
235
232
|
internalizeState?: QueryBuilderInternalizeState | undefined;
|
|
236
|
-
queryChatState?: QueryChatState | undefined;
|
|
237
233
|
|
|
238
234
|
// NOTE: This property contains information about workflow used
|
|
239
235
|
// to create this state. This should only be used to add additional
|
|
@@ -273,8 +269,6 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
|
273
269
|
changeHistoryState: observable,
|
|
274
270
|
executionContextState: observable,
|
|
275
271
|
sourceElement: observable,
|
|
276
|
-
queryChatState: observable,
|
|
277
|
-
isQueryChatOpened: observable,
|
|
278
272
|
isLocalModeEnabled: observable,
|
|
279
273
|
dataCubeViewerState: observable,
|
|
280
274
|
getAllFunction: observable,
|
|
@@ -298,7 +292,6 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
|
298
292
|
openDataCubeEngine: action,
|
|
299
293
|
setIsCheckingEntitlments: action,
|
|
300
294
|
setSourceElement: action,
|
|
301
|
-
setIsQueryChatOpened: action,
|
|
302
295
|
setIsLocalModeEnabled: action,
|
|
303
296
|
setGetAllFunction: action,
|
|
304
297
|
setLambdaWriteMode: action,
|
|
@@ -311,7 +304,6 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
|
311
304
|
changeMapping: action,
|
|
312
305
|
changeRuntime: action,
|
|
313
306
|
setExecutionContextState: action,
|
|
314
|
-
setQueryChatState: action,
|
|
315
307
|
|
|
316
308
|
rebuildWithQuery: action,
|
|
317
309
|
compileQuery: flow,
|
|
@@ -343,12 +335,6 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
|
343
335
|
this.config = config;
|
|
344
336
|
this.workflowState = workflowState;
|
|
345
337
|
this.sourceInfo = sourceInfo;
|
|
346
|
-
this.isQueryChatOpened =
|
|
347
|
-
(!this.config?.TEMPORARY__disableQueryBuilderChat &&
|
|
348
|
-
this.applicationStore.settingService.getBooleanValue(
|
|
349
|
-
QUERY_BUILDER_SETTING_KEY.SHOW_QUERY_CHAT_PANEL,
|
|
350
|
-
)) ??
|
|
351
|
-
false;
|
|
352
338
|
}
|
|
353
339
|
|
|
354
340
|
TEMPORARY_initializeExecContext(
|
|
@@ -496,14 +482,6 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
|
496
482
|
return undefined;
|
|
497
483
|
}
|
|
498
484
|
|
|
499
|
-
setIsQueryChatOpened(val: boolean): void {
|
|
500
|
-
this.isQueryChatOpened = val;
|
|
501
|
-
this.applicationStore.settingService.persistValue(
|
|
502
|
-
QUERY_BUILDER_SETTING_KEY.SHOW_QUERY_CHAT_PANEL,
|
|
503
|
-
val,
|
|
504
|
-
);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
485
|
setIsLocalModeEnabled(val: boolean): void {
|
|
508
486
|
this.isLocalModeEnabled = val;
|
|
509
487
|
}
|
|
@@ -518,10 +496,6 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
|
518
496
|
this.internalizeState = val;
|
|
519
497
|
}
|
|
520
498
|
|
|
521
|
-
setQueryChatState(val: QueryChatState | undefined): void {
|
|
522
|
-
this.queryChatState = val;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
499
|
setShowFunctionsExplorerPanel(val: boolean): void {
|
|
526
500
|
this.showFunctionsExplorerPanel = val;
|
|
527
501
|
}
|
|
@@ -67,10 +67,6 @@ export type WarehouseEntitlementRender = {
|
|
|
67
67
|
renderer: (dataAccessState: DataAccessState) => React.ReactNode;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
export type QueryChatRenderer = (
|
|
71
|
-
queryBuilderState: QueryBuilderState,
|
|
72
|
-
) => React.ReactNode;
|
|
73
|
-
|
|
74
70
|
export type TemplateQueryPanelContentRenderer = (
|
|
75
71
|
queryBuilderState: QueryBuilderState,
|
|
76
72
|
) => React.ReactNode;
|
|
@@ -135,11 +131,6 @@ export interface QueryBuilder_LegendApplicationPlugin_Extension
|
|
|
135
131
|
*/
|
|
136
132
|
getExtraQueryUsageConfigurations?(): QueryExportUsageConfiguration[];
|
|
137
133
|
|
|
138
|
-
/**
|
|
139
|
-
* Get the list of query chat configurations
|
|
140
|
-
*/
|
|
141
|
-
getExtraQueryChatRenderers?(): QueryChatRenderer[];
|
|
142
|
-
|
|
143
134
|
/**
|
|
144
135
|
* Get the list of template query panel content render
|
|
145
136
|
*/
|