@finos/legend-query-builder 4.14.69 → 4.14.71

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 (100) hide show
  1. package/lib/__lib__/QueryBuilderTesting.d.ts +1 -0
  2. package/lib/__lib__/QueryBuilderTesting.d.ts.map +1 -1
  3. package/lib/__lib__/QueryBuilderTesting.js +1 -0
  4. package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
  5. package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  6. package/lib/components/QueryBuilderConstantExpressionPanel.js +2 -1
  7. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  8. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts +1 -0
  9. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
  10. package/lib/components/explorer/QueryBuilderExplorerPanel.js +87 -52
  11. package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
  12. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts +4 -0
  13. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
  14. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +172 -108
  15. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
  16. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  17. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +2 -1
  18. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  19. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  20. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +29 -18
  21. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  22. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
  23. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +13 -4
  24. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
  25. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  26. package/lib/components/filter/QueryBuilderFilterPanel.js +4 -3
  27. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  28. package/lib/components/result/QueryBuilderResultPanel.d.ts +12 -0
  29. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  30. package/lib/components/result/QueryBuilderResultPanel.js +60 -8
  31. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  32. package/lib/components/shared/QueryBuilderFilterHelper.d.ts.map +1 -1
  33. package/lib/components/shared/QueryBuilderFilterHelper.js +3 -0
  34. package/lib/components/shared/QueryBuilderFilterHelper.js.map +1 -1
  35. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts +11 -0
  36. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts.map +1 -1
  37. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js +6 -3
  38. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js.map +1 -1
  39. package/lib/graph-manager/QueryBuilderConfig.d.ts +4 -0
  40. package/lib/graph-manager/QueryBuilderConfig.d.ts.map +1 -1
  41. package/lib/graph-manager/QueryBuilderConfig.js +5 -0
  42. package/lib/graph-manager/QueryBuilderConfig.js.map +1 -1
  43. package/lib/index.css +2 -2
  44. package/lib/index.css.map +1 -1
  45. package/lib/package.json +1 -1
  46. package/lib/stores/QueryBuilderConstantsState.d.ts +1 -0
  47. package/lib/stores/QueryBuilderConstantsState.d.ts.map +1 -1
  48. package/lib/stores/QueryBuilderConstantsState.js +6 -1
  49. package/lib/stores/QueryBuilderConstantsState.js.map +1 -1
  50. package/lib/stores/QueryBuilderResultState.d.ts +11 -3
  51. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  52. package/lib/stores/QueryBuilderResultState.js +47 -4
  53. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  54. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts +4 -0
  55. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts.map +1 -1
  56. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts +3 -1
  57. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
  58. package/lib/stores/explorer/QueryBuilderExplorerState.js +63 -8
  59. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  60. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts +24 -0
  61. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts.map +1 -0
  62. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js +39 -0
  63. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js.map +1 -0
  64. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts +8 -4
  65. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts.map +1 -1
  66. package/lib/stores/explorer/QueryBuilderPropertySearchState.js +204 -114
  67. package/lib/stores/explorer/QueryBuilderPropertySearchState.js.map +1 -1
  68. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  69. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +8 -1
  70. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  71. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
  72. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +12 -1
  73. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
  74. package/lib/stores/filter/QueryBuilderFilterState.d.ts +8 -1
  75. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  76. package/lib/stores/filter/QueryBuilderFilterState.js +27 -10
  77. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  78. package/package.json +8 -8
  79. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  80. package/src/components/QueryBuilderConstantExpressionPanel.tsx +2 -1
  81. package/src/components/explorer/QueryBuilderExplorerPanel.tsx +220 -114
  82. package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +618 -388
  83. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +5 -2
  84. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +78 -44
  85. package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +63 -10
  86. package/src/components/filter/QueryBuilderFilterPanel.tsx +4 -2
  87. package/src/components/result/QueryBuilderResultPanel.tsx +207 -20
  88. package/src/components/shared/QueryBuilderFilterHelper.ts +8 -0
  89. package/src/components/shared/QueryBuilderPropertyInfoTooltip.tsx +13 -3
  90. package/src/graph-manager/QueryBuilderConfig.ts +6 -0
  91. package/src/stores/QueryBuilderConstantsState.ts +16 -1
  92. package/src/stores/QueryBuilderResultState.ts +64 -10
  93. package/src/stores/QueryBuilderValueSpecificationBuilderHelper.ts +5 -0
  94. package/src/stores/explorer/QueryBuilderExplorerState.ts +92 -8
  95. package/src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts +46 -0
  96. package/src/stores/explorer/QueryBuilderPropertySearchState.ts +280 -142
  97. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +8 -1
  98. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +15 -2
  99. package/src/stores/filter/QueryBuilderFilterState.ts +34 -11
  100. package/tsconfig.json +1 -0
@@ -317,7 +317,10 @@ const QueryBuilderPostFilterConditionEditor = observer(
317
317
  const conditionValueType =
318
318
  node.condition.leftConditionValue.getColumnType();
319
319
  if (canDropTypeOntoNodeValue(itemType, node.condition)) {
320
- if (type === QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE) {
320
+ if (
321
+ type === QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE ||
322
+ type === QUERY_BUILDER_WINDOW_COLUMN_DND_TYPE
323
+ ) {
321
324
  const columnState = (item as QueryBuilderProjectionColumnDragSource)
322
325
  .columnState;
323
326
  node.condition.setRightConditionVal(
@@ -1047,7 +1050,7 @@ const QueryBuilderPostFilterPanelContent = observer(
1047
1050
  [applicationStore, handleDrop],
1048
1051
  );
1049
1052
 
1050
- const addPostFilterRef = useRef<HTMLInputElement>(null);
1053
+ const addPostFilterRef = useRef<HTMLDivElement>(null);
1051
1054
  dropTargetConnector(addPostFilterRef);
1052
1055
 
1053
1056
  return (
@@ -119,6 +119,41 @@ import {
119
119
  } from '../shared/QueryBuilderPropertyInfoTooltip.js';
120
120
  import { getNameOfValueSpecification } from '../shared/QueryBuilderVariableSelector.js';
121
121
  import { QueryBuilderAggregateOperator_Percentile } from '../../stores/fetch-structure/tds/aggregation/operators/QueryBuilderAggregateOperator_Percentile.js';
122
+ import {
123
+ getFurthestExistsNodeParent,
124
+ isExistsNodeChild,
125
+ QUERY_BUILDER_FILTER_DND_TYPE,
126
+ QueryBuilderFilterTreeConditionNodeData,
127
+ type QueryBuilderFilterConditionDragSource,
128
+ } from '../../stores/filter/QueryBuilderFilterState.js';
129
+ import { cloneAbstractPropertyExpression } from '../../stores/shared/ValueSpecificationEditorHelper.js';
130
+ import { buildPropertyExpressionFromExistsNode } from '../filter/QueryBuilderFilterPanel.js';
131
+
132
+ const CAN_DROP_MAIN_GROUP_DND_TYPES = [
133
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
134
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
135
+ QUERY_BUILDER_FILTER_DND_TYPE.CONDITION,
136
+ QUERY_BUILDER_FUNCTION_DND_TYPE,
137
+ ];
138
+
139
+ const CAN_DROP_DERIVATION_PROJECTION_COLUMN_DND_TYPES = [
140
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ROOT,
141
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.CLASS_PROPERTY,
142
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
143
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
144
+ QUERY_BUILDER_VARIABLE_DND_TYPE,
145
+ QUERY_BUILDER_FUNCTION_DND_TYPE,
146
+ ];
147
+
148
+ type QueryBuilderTDSPanelDropTarget =
149
+ | QueryBuilderExplorerTreeDragSource
150
+ | QueryBuilderFunctionsExplorerDragSource
151
+ | QueryBuilderFilterConditionDragSource;
152
+
153
+ type QueryBuilderDerivationProjectionColumnDropTarget =
154
+ | QueryBuilderExplorerTreeDragSource
155
+ | QueryBuilderVariableDragSource
156
+ | QueryBuilderFunctionsExplorerDragSource;
122
157
 
123
158
  const QueryBuilderProjectionColumnContextMenu = observer(
124
159
  forwardRef<
@@ -192,10 +227,7 @@ const QueryBuilderDerivationProjectionColumnEditor = observer(
192
227
  };
193
228
  const handleDrop = useCallback(
194
229
  (
195
- item:
196
- | QueryBuilderExplorerTreeDragSource
197
- | QueryBuilderVariableDragSource
198
- | QueryBuilderFunctionsExplorerDragSource,
230
+ item: QueryBuilderDerivationProjectionColumnDropTarget,
199
231
  type: string,
200
232
  ): void => {
201
233
  if (type === QUERY_BUILDER_VARIABLE_DND_TYPE) {
@@ -224,28 +256,18 @@ const QueryBuilderDerivationProjectionColumnEditor = observer(
224
256
  },
225
257
  [projectionColumnState],
226
258
  );
227
- const [, dropConnector] = useDrop<
228
- | QueryBuilderExplorerTreeDragSource
229
- | QueryBuilderVariableDragSource
230
- | QueryBuilderFunctionsExplorerDragSource
231
- >(
232
- () => ({
233
- accept: [
234
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ROOT,
235
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.CLASS_PROPERTY,
236
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
237
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
238
- QUERY_BUILDER_VARIABLE_DND_TYPE,
239
- QUERY_BUILDER_FUNCTION_DND_TYPE,
240
- ],
241
- drop: (item, monitor): void => {
242
- if (!monitor.didDrop()) {
243
- handleDrop(item, monitor.getItemType() as string);
244
- } // prevent drop event propagation to accomondate for nested DnD
245
- },
246
- }),
247
- [handleDrop],
248
- );
259
+ const [, dropConnector] =
260
+ useDrop<QueryBuilderDerivationProjectionColumnDropTarget>(
261
+ () => ({
262
+ accept: CAN_DROP_DERIVATION_PROJECTION_COLUMN_DND_TYPES,
263
+ drop: (item, monitor): void => {
264
+ if (!monitor.didDrop()) {
265
+ handleDrop(item, monitor.getItemType() as string);
266
+ } // prevent drop event propagation to accomondate for nested DnD
267
+ },
268
+ }),
269
+ [handleDrop],
270
+ );
249
271
 
250
272
  return (
251
273
  <div
@@ -1230,12 +1252,7 @@ export const QueryBuilderTDSPanel = observer(
1230
1252
 
1231
1253
  // Drag and Drop
1232
1254
  const handleDrop = useCallback(
1233
- (
1234
- item:
1235
- | QueryBuilderExplorerTreeDragSource
1236
- | QueryBuilderFunctionsExplorerDragSource,
1237
- type: string,
1238
- ): void => {
1255
+ (item: QueryBuilderTDSPanelDropTarget, type: string): void => {
1239
1256
  switch (type) {
1240
1257
  case QUERY_BUILDER_FUNCTION_DND_TYPE: {
1241
1258
  const derivationProjectionColumn =
@@ -1267,6 +1284,30 @@ export const QueryBuilderTDSPanel = observer(
1267
1284
  ),
1268
1285
  );
1269
1286
  break;
1287
+ case QUERY_BUILDER_FILTER_DND_TYPE.CONDITION:
1288
+ if (item.node instanceof QueryBuilderFilterTreeConditionNodeData) {
1289
+ const propertyExpression = isExistsNodeChild(item.node)
1290
+ ? buildPropertyExpressionFromExistsNode(
1291
+ tdsState.queryBuilderState.filterState,
1292
+ guaranteeNonNullable(
1293
+ getFurthestExistsNodeParent(item.node),
1294
+ ),
1295
+ item.node,
1296
+ )
1297
+ : cloneAbstractPropertyExpression(
1298
+ item.node.condition.propertyExpressionState
1299
+ .propertyExpression,
1300
+ tdsState.queryBuilderState.observerContext,
1301
+ );
1302
+ tdsState.addColumn(
1303
+ new QueryBuilderSimpleProjectionColumnState(
1304
+ tdsState,
1305
+ propertyExpression,
1306
+ tdsState.queryBuilderState.explorerState.humanizePropertyName,
1307
+ ),
1308
+ );
1309
+ }
1310
+ break;
1270
1311
  default:
1271
1312
  break;
1272
1313
  }
@@ -1275,17 +1316,12 @@ export const QueryBuilderTDSPanel = observer(
1275
1316
  );
1276
1317
 
1277
1318
  const [{ isDragOver }, dropTargetConnector] = useDrop<
1278
- | QueryBuilderExplorerTreeDragSource
1279
- | QueryBuilderFunctionsExplorerDragSource,
1319
+ QueryBuilderTDSPanelDropTarget,
1280
1320
  void,
1281
1321
  { isDragOver: boolean }
1282
1322
  >(
1283
1323
  () => ({
1284
- accept: [
1285
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
1286
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
1287
- QUERY_BUILDER_FUNCTION_DND_TYPE,
1288
- ],
1324
+ accept: CAN_DROP_MAIN_GROUP_DND_TYPES,
1289
1325
  drop: (item, monitor): void => {
1290
1326
  if (!monitor.didDrop()) {
1291
1327
  handleDrop(item, monitor.getItemType() as string);
@@ -1315,11 +1351,9 @@ export const QueryBuilderTDSPanel = observer(
1315
1351
  const { isDroppable } = useDragLayer((monitor) => ({
1316
1352
  isDroppable:
1317
1353
  monitor.isDragging() &&
1318
- [
1319
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
1320
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
1321
- QUERY_BUILDER_FUNCTION_DND_TYPE,
1322
- ].includes(monitor.getItemType()?.toString() ?? ''),
1354
+ CAN_DROP_MAIN_GROUP_DND_TYPES.includes(
1355
+ monitor.getItemType()?.toString() ?? '',
1356
+ ),
1323
1357
  }));
1324
1358
 
1325
1359
  useEffect(() => {
@@ -48,6 +48,7 @@ import {
48
48
  PanelHeader,
49
49
  PanelHeaderActions,
50
50
  Panel,
51
+ DragPreviewLayer,
51
52
  } from '@finos/legend-art';
52
53
  import {
53
54
  assertErrorThrown,
@@ -57,7 +58,12 @@ import {
57
58
  } from '@finos/legend-shared';
58
59
  import { observer } from 'mobx-react-lite';
59
60
  import { forwardRef, useCallback, useRef, useState } from 'react';
60
- import { type DropTargetMonitor, useDrag, useDrop } from 'react-dnd';
61
+ import {
62
+ type DropTargetMonitor,
63
+ useDrag,
64
+ useDragLayer,
65
+ useDrop,
66
+ } from 'react-dnd';
61
67
  import type { QueryBuilderTDS_WindowOperator } from '../../stores/fetch-structure/tds/window/operators/QueryBuilderTDS_WindowOperator.js';
62
68
  import {
63
69
  type QueryBuilderWindowState,
@@ -75,6 +81,7 @@ import type { QueryBuilderTDSState } from '../../stores/fetch-structure/tds/Quer
75
81
  import { QUERY_BUILDER_TEST_ID } from '../../__lib__/QueryBuilderTesting.js';
76
82
  import { QueryBuilderPanelIssueCountBadge } from '../shared/QueryBuilderPanelIssueCountBadge.js';
77
83
  import { COLUMN_SORT_TYPE } from '../../graph/QueryBuilderMetaModelConst.js';
84
+ import { CAN_DROP_MAIN_GROUP_DND_TYPES } from './QueryBuilderPostFilterPanel.js';
78
85
 
79
86
  // helpers
80
87
  const createWindowColumnState = (
@@ -965,6 +972,10 @@ const QueryBuilderWindowColumnEditor = observer(
965
972
  ref={ref}
966
973
  className="query-builder__olap__column"
967
974
  showPlaceholder={isBeingDragged}
975
+ placeholder={
976
+ <div className="query-builder__olap__column__placeholder" />
977
+ }
978
+ placeholderContainerClassName="query-builder__olap__column__placeholder__container"
968
979
  >
969
980
  <ContextMenu
970
981
  content={
@@ -1236,6 +1247,7 @@ export const QueryBuilderTDSWindowPanel = observer(
1236
1247
  tdsWindowState.setEditColumn(newWindowState);
1237
1248
  }
1238
1249
  };
1250
+
1239
1251
  // Drag and Drop
1240
1252
  const handleDrop = useCallback(
1241
1253
  async (item: QueryBuilderWindowDropTarget): Promise<void> => {
@@ -1253,6 +1265,7 @@ export const QueryBuilderTDSWindowPanel = observer(
1253
1265
  },
1254
1266
  [applicationStore, tdsWindowState],
1255
1267
  );
1268
+
1256
1269
  const [{ isDragOver }, dropTargetConnector] = useDrop<
1257
1270
  QueryBuilderWindowDropTarget,
1258
1271
  void,
@@ -1274,6 +1287,18 @@ export const QueryBuilderTDSWindowPanel = observer(
1274
1287
  }),
1275
1288
  [applicationStore, handleDrop],
1276
1289
  );
1290
+
1291
+ const { isDroppable } = useDragLayer((monitor) => ({
1292
+ isDroppable:
1293
+ monitor.isDragging() &&
1294
+ CAN_DROP_MAIN_GROUP_DND_TYPES.includes(
1295
+ monitor.getItemType()?.toString() ?? '',
1296
+ ),
1297
+ }));
1298
+
1299
+ const addWindowColumnRef = useRef<HTMLDivElement>(null);
1300
+ dropTargetConnector(addWindowColumnRef);
1301
+
1277
1302
  return (
1278
1303
  <Panel>
1279
1304
  <div
@@ -1301,7 +1326,8 @@ export const QueryBuilderTDSWindowPanel = observer(
1301
1326
  </PanelHeader>
1302
1327
  <PanelContent>
1303
1328
  <PanelDropZone
1304
- isDragOver={isDragOver}
1329
+ isDragOver={isDragOver && tdsWindowState.isEmpty}
1330
+ isDroppable={isDroppable && tdsWindowState.isEmpty}
1305
1331
  dropTargetConnector={dropTargetConnector}
1306
1332
  >
1307
1333
  {tdsWindowState.isEmpty && (
@@ -1311,16 +1337,43 @@ export const QueryBuilderTDSWindowPanel = observer(
1311
1337
  />
1312
1338
  )}
1313
1339
  {!tdsWindowState.isEmpty && (
1340
+ <>
1341
+ <DragPreviewLayer
1342
+ labelGetter={(
1343
+ item: QueryBuilderWindowColumnDragSource,
1344
+ ): string =>
1345
+ item.columnState.columnName === ''
1346
+ ? '(unknown)'
1347
+ : item.columnState.columnName
1348
+ }
1349
+ types={[QUERY_BUILDER_WINDOW_COLUMN_DND_TYPE]}
1350
+ />
1351
+ <div
1352
+ data-testid={QUERY_BUILDER_TEST_ID.QUERY_BUILDER_TDS}
1353
+ className="query-builder__olap__columns"
1354
+ >
1355
+ {tdsWindowState.windowColumns.map((col) => (
1356
+ <QueryBuilderWindowColumnEditor
1357
+ windowColumnState={col}
1358
+ key={col.uuid}
1359
+ />
1360
+ ))}
1361
+ </div>
1362
+ </>
1363
+ )}
1364
+ {isDroppable && !tdsWindowState.isEmpty && (
1314
1365
  <div
1315
- data-testid={QUERY_BUILDER_TEST_ID.QUERY_BUILDER_TDS}
1316
- className="query-builder__olap__columns"
1366
+ ref={addWindowColumnRef}
1367
+ className="query-builder__olap__free-drop-zone__container"
1317
1368
  >
1318
- {tdsWindowState.windowColumns.map((col) => (
1319
- <QueryBuilderWindowColumnEditor
1320
- windowColumnState={col}
1321
- key={col.uuid}
1322
- />
1323
- ))}
1369
+ <PanelEntryDropZonePlaceholder
1370
+ isDragOver={isDragOver}
1371
+ isDroppable={isDroppable}
1372
+ className="query-builder__olap__free-drop-zone"
1373
+ label="Add new window function column"
1374
+ >
1375
+ <></>
1376
+ </PanelEntryDropZonePlaceholder>
1324
1377
  </div>
1325
1378
  )}
1326
1379
  </PanelDropZone>
@@ -68,6 +68,7 @@ import {
68
68
  FilterPropertyExpressionStateConditionValueState,
69
69
  isCollectionProperty,
70
70
  type QueryBuilderFilterValueDropTarget,
71
+ isExistsNodeChild,
71
72
  } from '../../stores/filter/QueryBuilderFilterState.js';
72
73
  import { useDrag, useDragLayer, useDrop } from 'react-dnd';
73
74
  import {
@@ -830,6 +831,7 @@ const QueryBuilderFilterConditionEditor = observer(
830
831
  const queryBuilderState = node.condition.filterState.queryBuilderState;
831
832
  const rightConditionValue = node.condition.rightConditionValue;
832
833
  const applicationStore = useApplicationStore();
834
+ const isNodeExistsNodeChild = isExistsNodeChild(node);
833
835
 
834
836
  // Drag and Drop on filter condition value
835
837
  const handleDrop = useCallback(
@@ -845,7 +847,7 @@ const QueryBuilderFilterConditionEditor = observer(
845
847
  type === QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY ||
846
848
  type ===
847
849
  QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY) &&
848
- node.isExistsNodeChild
850
+ isNodeExistsNodeChild
849
851
  ) {
850
852
  throw new UnsupportedOperationError(
851
853
  'Collection filter does not support property for filter condition value.',
@@ -931,8 +933,8 @@ const QueryBuilderFilterConditionEditor = observer(
931
933
  [
932
934
  applicationStore,
933
935
  queryBuilderState,
936
+ isNodeExistsNodeChild,
934
937
  node.condition,
935
- node.isExistsNodeChild,
936
938
  ],
937
939
  );
938
940
 
@@ -44,6 +44,8 @@ import {
44
44
  ReportIcon,
45
45
  CubesLoadingIndicatorIcon,
46
46
  CubesLoadingIndicator,
47
+ InfoCircleIcon,
48
+ ShareBoxIcon,
47
49
  } from '@finos/legend-art';
48
50
  import { observer } from 'mobx-react-lite';
49
51
  import { flowResult } from 'mobx';
@@ -77,6 +79,108 @@ import { QueryBuilderTDSSimpleGridResult } from './tds/QueryBuilderTDSSimpleGrid
77
79
  import { getExecutedSqlFromExecutionResult } from './tds/QueryBuilderTDSResultShared.js';
78
80
  import { QueryBuilderTDSGridResult } from './tds/QueryBuilderTDSGridResult.js';
79
81
  import type { QueryBuilder_LegendApplicationPlugin_Extension } from '../../stores/QueryBuilder_LegendApplicationPlugin_Extension.js';
82
+ import type { QueryBuilderResultState } from '../../stores/QueryBuilderResultState.js';
83
+
84
+ const PERMISSION_ERRORS = ['permission denied', 'invalid user id or password'];
85
+
86
+ export const QueryBuilderExecutionErrorPanel = observer(
87
+ (props: {
88
+ resultState: QueryBuilderResultState;
89
+ executionError: string | Error;
90
+ }) => {
91
+ const { resultState, executionError } = props;
92
+ const queryBuilderState = resultState.queryBuilderState;
93
+ const errorMessage = executionError
94
+ ? queryBuilderState.applicationStore.notificationService.getErrorMessage(
95
+ executionError,
96
+ )
97
+ : '';
98
+ const isPermissionDeniedError = () =>
99
+ Boolean(
100
+ PERMISSION_ERRORS.find((e) => errorMessage?.toLowerCase().includes(e)),
101
+ );
102
+ const openCheckEntitlmentsEditor = (): void => {
103
+ queryBuilderState.checkEntitlementsState.setShowCheckEntitlementsViewer(
104
+ true,
105
+ );
106
+ };
107
+
108
+ return (
109
+ <>
110
+ {isPermissionDeniedError() && (
111
+ <div className="query-builder__result__permission-error">
112
+ <div className="query-builder__result__permission-error__header">
113
+ Entitlement / Authorization error - Please
114
+ </div>
115
+ <button
116
+ className="query-builder__result__permission-error__button"
117
+ disabled={
118
+ (queryBuilderState.isQuerySupported &&
119
+ queryBuilderState.fetchStructureState
120
+ .implementation instanceof QueryBuilderTDSState &&
121
+ queryBuilderState.fetchStructureState.implementation
122
+ .projectionColumns.length === 0) ||
123
+ !queryBuilderState.canBuildQuery
124
+ }
125
+ onClick={openCheckEntitlmentsEditor}
126
+ >
127
+ Click Here to Check Entitlements
128
+ </button>
129
+ </div>
130
+ )}
131
+ <div className="query-builder__result__execution-error">
132
+ <div className="query-builder__result__execution-error__header">
133
+ <span style={{ fontWeight: 'bold' }}>Error Execution Query</span>.
134
+ Please try again later or review options in application`s
135
+ <span style={{ fontWeight: 'bold' }}> Help</span> menu.
136
+ </div>
137
+ <div className="query-builder__result__execution-error__body">
138
+ {errorMessage}
139
+ </div>
140
+ </div>
141
+ </>
142
+ );
143
+ },
144
+ );
145
+
146
+ export const QueryBuilderEmptyExecutionResultPanel = observer(
147
+ (props: { queryBuilderState: QueryBuilderState }) => {
148
+ const { queryBuilderState } = props;
149
+
150
+ const openCheckEntitlmentsEditor = (): void => {
151
+ queryBuilderState.checkEntitlementsState.setShowCheckEntitlementsViewer(
152
+ true,
153
+ );
154
+ };
155
+
156
+ return (
157
+ <div className="query-builder__result__empty-result-warning">
158
+ <div className="query-builder__result__empty-result-warning__header">
159
+ Query returned no data
160
+ </div>
161
+ <div className="query-builder__result__empty-result-warning__body">
162
+ If you believe the query should return data, please
163
+ <button
164
+ className="query-builder__result__permission-error__button"
165
+ disabled={
166
+ (queryBuilderState.isQuerySupported &&
167
+ queryBuilderState.fetchStructureState.implementation instanceof
168
+ QueryBuilderTDSState &&
169
+ queryBuilderState.fetchStructureState.implementation
170
+ .projectionColumns.length === 0) ||
171
+ !queryBuilderState.canBuildQuery
172
+ }
173
+ onClick={openCheckEntitlmentsEditor}
174
+ >
175
+ Click Here to Check Entitlements
176
+ </button>
177
+ or See Help menu for more options
178
+ </div>
179
+ </div>
180
+ );
181
+ },
182
+ );
183
+ import { QueryBuilderBaseInfoTooltip } from '../shared/QueryBuilderPropertyInfoTooltip.js';
80
184
 
81
185
  export const QueryBuilderResultValues = observer(
82
186
  (props: {
@@ -85,20 +189,28 @@ export const QueryBuilderResultValues = observer(
85
189
  }) => {
86
190
  const { executionResult, queryBuilderState } = props;
87
191
  if (executionResult instanceof TDSExecutionResult) {
88
- if (queryBuilderState.config?.TEMPORARY__enableGridEnterpriseMode) {
192
+ if (executionResult.result.rows.length === 0) {
89
193
  return (
90
- <QueryBuilderTDSGridResult
194
+ <QueryBuilderEmptyExecutionResultPanel
91
195
  queryBuilderState={queryBuilderState}
92
- executionResult={executionResult}
93
196
  />
94
197
  );
95
198
  } else {
96
- return (
97
- <QueryBuilderTDSSimpleGridResult
98
- queryBuilderState={queryBuilderState}
99
- executionResult={executionResult}
100
- />
101
- );
199
+ if (queryBuilderState.config?.TEMPORARY__enableGridEnterpriseMode) {
200
+ return (
201
+ <QueryBuilderTDSGridResult
202
+ queryBuilderState={queryBuilderState}
203
+ executionResult={executionResult}
204
+ />
205
+ );
206
+ } else {
207
+ return (
208
+ <QueryBuilderTDSSimpleGridResult
209
+ queryBuilderState={queryBuilderState}
210
+ executionResult={executionResult}
211
+ />
212
+ );
213
+ }
102
214
  }
103
215
  } else if (executionResult instanceof RawExecutionResult) {
104
216
  const inputValue =
@@ -134,6 +246,7 @@ export const QueryBuilderResultPanel = observer(
134
246
  const resultState = queryBuilderState.resultState;
135
247
  const queryParametersState = queryBuilderState.parametersState;
136
248
  const executionResult = resultState.executionResult;
249
+ const resultLimit = resultState.getExecutionResultLimit();
137
250
  const [showSqlModal, setShowSqlModal] = useState(false);
138
251
  const executedSql = executionResult
139
252
  ? getExecutedSqlFromExecutionResult(executionResult, true)
@@ -211,6 +324,7 @@ export const QueryBuilderResultPanel = observer(
211
324
 
212
325
  const runQuery = (): void => {
213
326
  resultState.setSelectedCells([]);
327
+ resultState.setExecutionError(undefined);
214
328
  resultState.pressedRunQuery.inProgress();
215
329
  if (
216
330
  queryParametersState.parameterStates.length &&
@@ -278,8 +392,7 @@ export const QueryBuilderResultPanel = observer(
278
392
  })
279
393
  : undefined;
280
394
  if (_executionResult instanceof TDSExecutionResult) {
281
- const rowLength = _executionResult.result.rows.length;
282
- return `${rowLength} row(s)${
395
+ return `${_executionResult.result.rows.length} row(s)${
283
396
  queryDuration ? ` in ${queryDuration}` : ''
284
397
  }`;
285
398
  }
@@ -419,13 +532,62 @@ export const QueryBuilderResultPanel = observer(
419
532
  Running Query...
420
533
  </div>
421
534
  )}
422
-
423
- <div
424
- data-testid={QUERY_BUILDER_TEST_ID.QUERY_BUILDER_RESULT_ANALYTICS}
425
- className="query-builder__result__analytics"
426
- >
427
- {resultDescription ?? ''}
428
- </div>
535
+ {resultDescription && resultState.executionTraceId && (
536
+ <div
537
+ data-testid={
538
+ QUERY_BUILDER_TEST_ID.QUERY_BUILDER_RESULT_ANALYTICS
539
+ }
540
+ className="query-builder__result__analytics"
541
+ >
542
+ <QueryBuilderBaseInfoTooltip
543
+ title="Execution Result Analytics"
544
+ data={[
545
+ {
546
+ label: 'Trace',
547
+ value: 'available here',
548
+ actionButton: (
549
+ <div className="query-builder__tooltip__item__action">
550
+ <button
551
+ disabled={
552
+ !queryBuilderState.config?.zipkinTraceBaseURL
553
+ }
554
+ title={
555
+ queryBuilderState.config?.zipkinTraceBaseURL
556
+ ? ''
557
+ : 'No zipkin trace URL configured'
558
+ }
559
+ onClick={() => {
560
+ if (
561
+ queryBuilderState.config?.zipkinTraceBaseURL
562
+ ) {
563
+ applicationStore.navigationService.navigator.visitAddress(
564
+ queryBuilderState.config.zipkinTraceBaseURL +
565
+ resultState.executionTraceId,
566
+ );
567
+ }
568
+ }}
569
+ >
570
+ <ShareBoxIcon />
571
+ </button>
572
+ </div>
573
+ ),
574
+ },
575
+ ]}
576
+ >
577
+ <div className="editable-value">{resultDescription}</div>
578
+ </QueryBuilderBaseInfoTooltip>
579
+ </div>
580
+ )}
581
+ {resultDescription && !resultState.executionTraceId && (
582
+ <div
583
+ data-testid={
584
+ QUERY_BUILDER_TEST_ID.QUERY_BUILDER_RESULT_ANALYTICS
585
+ }
586
+ className="query-builder__result__analytics"
587
+ >
588
+ {resultDescription}
589
+ </div>
590
+ )}
429
591
  {executionResult && resultState.checkForStaleResults && (
430
592
  <div className="query-builder__result__stale-status">
431
593
  <div className="query-builder__result__stale-status__icon">
@@ -436,6 +598,25 @@ export const QueryBuilderResultPanel = observer(
436
598
  </div>
437
599
  </div>
438
600
  )}
601
+ {executionResult &&
602
+ executionResult instanceof TDSExecutionResult &&
603
+ resultState.isExecutionResultOverflowing && (
604
+ <div className="query-builder__result__stale-status">
605
+ <div className="query-builder__result__stale-status__icon">
606
+ <ExclamationTriangleIcon />
607
+ </div>
608
+ <div className="query-builder__result__stale-status__label">
609
+ Data below is not complete - query produces more rows than
610
+ the set grid preview limit
611
+ </div>
612
+ <div
613
+ className="query-builder__result__stale-status__icon"
614
+ title={`The preview limit is set to ${resultLimit}. The results in the grid below are being limited by this limit and running query with a higher limit would produce more rows. Export will not apply this limit.`}
615
+ >
616
+ <InfoCircleIcon />
617
+ </div>
618
+ </div>
619
+ )}
439
620
  </div>
440
621
  <div className="panel__header__actions query-builder__result__header__actions">
441
622
  {resultState.exportState.isInProgress && (
@@ -638,12 +819,18 @@ export const QueryBuilderResultPanel = observer(
638
819
  <CubesLoadingIndicator isLoading={isLoading}>
639
820
  <CubesLoadingIndicatorIcon />
640
821
  </CubesLoadingIndicator>
641
- {!executionResult && !isLoading && (
822
+ {!executionResult && !isLoading && !resultState.executionError && (
642
823
  <BlankPanelContent>
643
824
  Build or load a valid query first
644
825
  </BlankPanelContent>
645
826
  )}
646
- {executionResult && !isLoading && (
827
+ {!isLoading && resultState.executionError && (
828
+ <QueryBuilderExecutionErrorPanel
829
+ resultState={resultState}
830
+ executionError={resultState.executionError}
831
+ />
832
+ )}
833
+ {executionResult && !isLoading && !resultState.executionError && (
647
834
  <div className="query-builder__result__values">
648
835
  <QueryBuilderResultValues
649
836
  executionResult={executionResult}
@@ -28,6 +28,10 @@ import {
28
28
  QUERY_BUILDER_VARIABLE_DND_TYPE,
29
29
  type QueryBuilderVariableDragSource,
30
30
  } from './BasicValueSpecificationEditor.js';
31
+ import {
32
+ QUERY_BUILDER_WINDOW_COLUMN_DND_TYPE,
33
+ type QueryBuilderWindowColumnDragSource,
34
+ } from '../../stores/fetch-structure/tds/window/QueryBuilderWindowState.js';
31
35
 
32
36
  export const getDNDItemType = (
33
37
  item: QueryBuilderFilterValueDropTarget,
@@ -45,6 +49,10 @@ export const getDNDItemType = (
45
49
  case QUERY_BUILDER_VARIABLE_DND_TYPE:
46
50
  return (item as QueryBuilderVariableDragSource).variable.genericType
47
51
  ?.value.rawType;
52
+ case QUERY_BUILDER_WINDOW_COLUMN_DND_TYPE:
53
+ return (
54
+ item as QueryBuilderWindowColumnDragSource
55
+ ).columnState.getColumnType();
48
56
  default:
49
57
  return undefined;
50
58
  }