@finos/legend-query-builder 0.3.1 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. package/lib/components/QueryBuilder.d.ts.map +1 -1
  2. package/lib/components/QueryBuilder.js +24 -20
  3. package/lib/components/QueryBuilder.js.map +1 -1
  4. package/lib/components/QueryBuilderParametersPanel.d.ts.map +1 -1
  5. package/lib/components/QueryBuilderParametersPanel.js +4 -8
  6. package/lib/components/QueryBuilderParametersPanel.js.map +1 -1
  7. package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts.map +1 -1
  8. package/lib/components/QueryBuilderPropertyExpressionEditor.js +2 -2
  9. package/lib/components/QueryBuilderPropertyExpressionEditor.js.map +1 -1
  10. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  11. package/lib/components/QueryBuilderResultPanel.js +4 -2
  12. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  13. package/lib/components/QueryBuilderTextEditor.d.ts.map +1 -1
  14. package/lib/components/QueryBuilderTextEditor.js +4 -4
  15. package/lib/components/QueryBuilderTextEditor.js.map +1 -1
  16. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
  17. package/lib/components/explorer/QueryBuilderExplorerPanel.js +5 -5
  18. package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
  19. package/lib/components/explorer/QueryBuilderMilestoningEditor.d.ts.map +1 -1
  20. package/lib/components/explorer/QueryBuilderMilestoningEditor.js +6 -6
  21. package/lib/components/explorer/QueryBuilderMilestoningEditor.js.map +1 -1
  22. package/lib/components/fetch-structure/QueryBuilderOlapGroupByPanel.d.ts.map +1 -1
  23. package/lib/components/fetch-structure/QueryBuilderOlapGroupByPanel.js +6 -6
  24. package/lib/components/fetch-structure/QueryBuilderOlapGroupByPanel.js.map +1 -1
  25. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
  26. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +3 -3
  27. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  28. package/lib/components/shared/LambdaEditor.d.ts.map +1 -1
  29. package/lib/components/shared/LambdaEditor.js +3 -3
  30. package/lib/components/shared/LambdaEditor.js.map +1 -1
  31. package/lib/components/shared/LambdaParameterValuesEditor.d.ts.map +1 -1
  32. package/lib/components/shared/LambdaParameterValuesEditor.js +3 -3
  33. package/lib/components/shared/LambdaParameterValuesEditor.js.map +1 -1
  34. package/lib/components/watermark/QueryBuilderWatermark.d.ts +23 -0
  35. package/lib/components/watermark/QueryBuilderWatermark.d.ts.map +1 -0
  36. package/lib/components/watermark/QueryBuilderWatermark.js +67 -0
  37. package/lib/components/watermark/QueryBuilderWatermark.js.map +1 -0
  38. package/lib/graphManager/QueryBuilderHashUtils.d.ts +1 -0
  39. package/lib/graphManager/QueryBuilderHashUtils.d.ts.map +1 -1
  40. package/lib/graphManager/QueryBuilderHashUtils.js +2 -0
  41. package/lib/graphManager/QueryBuilderHashUtils.js.map +1 -1
  42. package/lib/graphManager/QueryBuilderSupportedFunctions.d.ts +1 -0
  43. package/lib/graphManager/QueryBuilderSupportedFunctions.d.ts.map +1 -1
  44. package/lib/graphManager/QueryBuilderSupportedFunctions.js +2 -0
  45. package/lib/graphManager/QueryBuilderSupportedFunctions.js.map +1 -1
  46. package/lib/graphManager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.d.ts.map +1 -1
  47. package/lib/graphManager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js +4 -1
  48. package/lib/graphManager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js.map +1 -1
  49. package/lib/graphManager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.d.ts +1 -0
  50. package/lib/graphManager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.d.ts.map +1 -1
  51. package/lib/graphManager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.js +29 -2
  52. package/lib/graphManager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.js.map +1 -1
  53. package/lib/index.css +2 -2
  54. package/lib/index.css.map +1 -1
  55. package/lib/package.json +1 -1
  56. package/lib/stores/QueryBuilderState.d.ts +4 -0
  57. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  58. package/lib/stores/QueryBuilderState.js +12 -0
  59. package/lib/stores/QueryBuilderState.js.map +1 -1
  60. package/lib/stores/QueryBuilderStateBuilder.d.ts.map +1 -1
  61. package/lib/stores/QueryBuilderStateBuilder.js +12 -1
  62. package/lib/stores/QueryBuilderStateBuilder.js.map +1 -1
  63. package/lib/stores/QueryBuilderValueSpecificationBuilder.d.ts.map +1 -1
  64. package/lib/stores/QueryBuilderValueSpecificationBuilder.js +7 -1
  65. package/lib/stores/QueryBuilderValueSpecificationBuilder.js.map +1 -1
  66. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.d.ts.map +1 -1
  67. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.js +2 -1
  68. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.js.map +1 -1
  69. package/lib/stores/watermark/QueryBuilderWatermarkState.d.ts +31 -0
  70. package/lib/stores/watermark/QueryBuilderWatermarkState.d.ts.map +1 -0
  71. package/lib/stores/watermark/QueryBuilderWatermarkState.js +69 -0
  72. package/lib/stores/watermark/QueryBuilderWatermarkState.js.map +1 -0
  73. package/lib/stores/watermark/QueryBuilderWatermarkStateBuilder.d.ts +19 -0
  74. package/lib/stores/watermark/QueryBuilderWatermarkStateBuilder.d.ts.map +1 -0
  75. package/lib/stores/watermark/QueryBuilderWatermarkStateBuilder.js +30 -0
  76. package/lib/stores/watermark/QueryBuilderWatermarkStateBuilder.js.map +1 -0
  77. package/lib/stores/watermark/QueryBuilderWatermarkValueSpecificationBuilder.d.ts +19 -0
  78. package/lib/stores/watermark/QueryBuilderWatermarkValueSpecificationBuilder.d.ts.map +1 -0
  79. package/lib/stores/watermark/QueryBuilderWatermarkValueSpecificationBuilder.js +30 -0
  80. package/lib/stores/watermark/QueryBuilderWatermarkValueSpecificationBuilder.js.map +1 -0
  81. package/package.json +4 -4
  82. package/src/components/QueryBuilder.tsx +141 -109
  83. package/src/components/QueryBuilderParametersPanel.tsx +27 -35
  84. package/src/components/QueryBuilderPropertyExpressionEditor.tsx +16 -11
  85. package/src/components/QueryBuilderResultPanel.tsx +18 -0
  86. package/src/components/QueryBuilderTextEditor.tsx +22 -17
  87. package/src/components/explorer/QueryBuilderExplorerPanel.tsx +20 -13
  88. package/src/components/explorer/QueryBuilderMilestoningEditor.tsx +27 -18
  89. package/src/components/fetch-structure/QueryBuilderOlapGroupByPanel.tsx +22 -18
  90. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +11 -9
  91. package/src/components/shared/LambdaEditor.tsx +20 -17
  92. package/src/components/shared/LambdaParameterValuesEditor.tsx +17 -10
  93. package/src/components/watermark/QueryBuilderWatermark.tsx +185 -0
  94. package/src/graphManager/QueryBuilderHashUtils.ts +3 -0
  95. package/src/graphManager/QueryBuilderSupportedFunctions.ts +2 -0
  96. package/src/graphManager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.ts +14 -0
  97. package/src/graphManager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.ts +76 -0
  98. package/src/stores/QueryBuilderState.ts +14 -0
  99. package/src/stores/QueryBuilderStateBuilder.ts +17 -1
  100. package/src/stores/QueryBuilderValueSpecificationBuilder.ts +11 -1
  101. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.ts +2 -1
  102. package/src/stores/watermark/QueryBuilderWatermarkState.ts +114 -0
  103. package/src/stores/watermark/QueryBuilderWatermarkStateBuilder.ts +50 -0
  104. package/src/stores/watermark/QueryBuilderWatermarkValueSpecificationBuilder.ts +46 -0
  105. package/tsconfig.json +4 -0
@@ -30,6 +30,7 @@ import {
30
30
  CheckIcon,
31
31
  CaretDownIcon,
32
32
  DiffIcon,
33
+ WaterDropIcon,
33
34
  } from '@finos/legend-art';
34
35
  import { QueryBuilderFilterPanel } from './filter/QueryBuilderFilterPanel.js';
35
36
  import { QueryBuilderExplorerPanel } from './explorer/QueryBuilderExplorerPanel.js';
@@ -54,6 +55,7 @@ import { QueryBuilderDiffViewPanel } from './QueryBuilderDiffPanel.js';
54
55
  import { guaranteeType } from '@finos/legend-shared';
55
56
  import { QueryBuilderGraphFetchTreeState } from '../stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js';
56
57
  import { QueryBuilderPostTDSPanel } from './fetch-structure/QueryBuilderPostTDSPanel.js';
58
+ import { QueryBuilderWatermarkEditor } from './watermark/QueryBuilderWatermark.js';
57
59
 
58
60
  export const QUERY_BUILDER_BACKDROP_CONTAINER_ID =
59
61
  'query-builder.backdrop-container';
@@ -200,6 +202,10 @@ export const QueryBuilder = observer(
200
202
  }
201
203
  };
202
204
 
205
+ const openWatermark = (): void => {
206
+ queryBuilderState.watermarkState.setIsEditingWatermark(true);
207
+ };
208
+
203
209
  useCommands(queryBuilderState);
204
210
  const toggleShowOlapGroupByPanel = (): void => {
205
211
  if (isTDSState) {
@@ -241,127 +247,153 @@ export const QueryBuilder = observer(
241
247
  <div className="query-builder__body">
242
248
  <div className="query-builder__content">
243
249
  <div className="query-builder__sub-header">
244
- <div className="query-builder__sub-header__actions">
245
- <DropdownMenu
246
- className="query-builder__sub-header__custom-action"
247
- title="Show Advanced Menu..."
248
- content={
249
- <MenuContent>
250
- <MenuContentItem
251
- onClick={toggleShowFunctionPanel}
252
- disabled={!queryBuilderState.isQuerySupported}
253
- >
254
- <MenuContentItemIcon>
255
- {queryBuilderState.showFunctionsExplorerPanel ? (
256
- <CheckIcon />
257
- ) : null}
258
- </MenuContentItemIcon>
259
- <MenuContentItemLabel className="query-builder__sub-header__menu-content">
260
- Show Function(s)
261
- </MenuContentItemLabel>
262
- </MenuContentItem>
263
- {/* TODO?: consider hiding this menu option when the fetch-structure is not TDS */}
264
- {!queryBuilderState.isParameterSupportDisabled && (
250
+ <div className="query-builder__sub-header__content__icons">
251
+ {queryBuilderState.watermarkState.value && (
252
+ <>
253
+ <button
254
+ className="panel__header__action"
255
+ onClick={openWatermark}
256
+ tabIndex={-1}
257
+ title="Edit Watermark"
258
+ >
259
+ <WaterDropIcon />
260
+ </button>
261
+ </>
262
+ )}
263
+ {queryBuilderState.watermarkState.isEditingWatermark && (
264
+ <QueryBuilderWatermarkEditor
265
+ queryBuilderState={queryBuilderState}
266
+ />
267
+ )}
268
+ </div>
269
+ <div className="query-builder__sub-header__content__actions">
270
+ <div className="query-builder__sub-header__actions">
271
+ <DropdownMenu
272
+ className="query-builder__sub-header__custom-action"
273
+ title="Show Advanced Menu..."
274
+ content={
275
+ <MenuContent>
276
+ <MenuContentItem
277
+ onClick={toggleShowFunctionPanel}
278
+ disabled={!queryBuilderState.isQuerySupported}
279
+ >
280
+ <MenuContentItemIcon>
281
+ {queryBuilderState.showFunctionsExplorerPanel ? (
282
+ <CheckIcon />
283
+ ) : null}
284
+ </MenuContentItemIcon>
285
+ <MenuContentItemLabel className="query-builder__sub-header__menu-content">
286
+ Show Function(s)
287
+ </MenuContentItemLabel>
288
+ </MenuContentItem>
289
+ {!queryBuilderState.isParameterSupportDisabled && (
290
+ <MenuContentItem
291
+ onClick={toggleShowParameterPanel}
292
+ disabled={
293
+ !queryBuilderState.isQuerySupported ||
294
+ queryBuilderState.parametersState.parameterStates
295
+ .length > 0
296
+ }
297
+ >
298
+ <MenuContentItemIcon>
299
+ {queryBuilderState.showParametersPanel ? (
300
+ <CheckIcon />
301
+ ) : null}
302
+ </MenuContentItemIcon>
303
+ <MenuContentItemLabel className="query-builder__sub-header__menu-content">
304
+ Show Parameter(s)
305
+ </MenuContentItemLabel>
306
+ </MenuContentItem>
307
+ )}
265
308
  <MenuContentItem
266
- onClick={toggleShowParameterPanel}
309
+ onClick={toggleShowFilterPanel}
267
310
  disabled={
268
311
  !queryBuilderState.isQuerySupported ||
269
- queryBuilderState.parametersState.parameterStates
270
- .length > 0
312
+ Array.from(
313
+ queryBuilderState.filterState.nodes.values(),
314
+ ).length > 0
271
315
  }
272
316
  >
273
317
  <MenuContentItemIcon>
274
- {queryBuilderState.showParametersPanel ? (
318
+ {queryBuilderState.filterState.showPanel ? (
275
319
  <CheckIcon />
276
320
  ) : null}
277
321
  </MenuContentItemIcon>
278
322
  <MenuContentItemLabel className="query-builder__sub-header__menu-content">
279
- Show Parameter(s)
323
+ Show Filter
280
324
  </MenuContentItemLabel>
281
325
  </MenuContentItem>
282
- )}
283
- <MenuContentItem
284
- onClick={toggleShowFilterPanel}
285
- disabled={
286
- !queryBuilderState.isQuerySupported ||
287
- Array.from(
288
- queryBuilderState.filterState.nodes.values(),
289
- ).length > 0
290
- }
291
- >
292
- <MenuContentItemIcon>
293
- {queryBuilderState.filterState.showPanel ? (
294
- <CheckIcon />
295
- ) : null}
296
- </MenuContentItemIcon>
297
- <MenuContentItemLabel className="query-builder__sub-header__menu-content">
298
- Show Filter
299
- </MenuContentItemLabel>
300
- </MenuContentItem>
301
- <MenuContentItem
302
- onClick={toggleShowOlapGroupByPanel}
303
- disabled={
304
- !queryBuilderState.isQuerySupported ||
305
- !(
306
- queryBuilderState.fetchStructureState
307
- .implementation instanceof QueryBuilderTDSState
308
- ) ||
309
- queryBuilderState.fetchStructureState.implementation
310
- .olapGroupByState.olapColumns.length > 0
311
- }
312
- >
313
- <MenuContentItemIcon>
314
- {isTDSState &&
315
- guaranteeType(
316
- queryBuilderState.fetchStructureState
317
- .implementation,
318
- QueryBuilderTDSState,
319
- ).showOlapGroupByPanel ? (
320
- <CheckIcon />
321
- ) : null}
322
- </MenuContentItemIcon>
323
- <MenuContentItemLabel className="query-builder__sub-header__menu-content">
324
- Show OLAP GroupBy
325
- </MenuContentItemLabel>
326
- </MenuContentItem>
327
- <MenuContentItem
328
- onClick={toggleShowPostFilterPanel}
329
- disabled={
330
- !queryBuilderState.isQuerySupported ||
331
- !(
332
- queryBuilderState.fetchStructureState
333
- .implementation instanceof QueryBuilderTDSState
334
- ) ||
335
- Array.from(
336
- queryBuilderState.fetchStructureState.implementation.postFilterState.nodes.values(),
337
- ).length > 0
338
- }
339
- >
340
- <MenuContentItemIcon>
341
- {queryBuilderState.fetchStructureState
342
- .implementation instanceof QueryBuilderTDSState &&
343
- queryBuilderState.fetchStructureState.implementation
344
- .showPostFilterPanel ? (
345
- <CheckIcon />
346
- ) : null}
347
- </MenuContentItemIcon>
348
- <MenuContentItemLabel className="query-builder__sub-header__menu-content">
349
- Show Post-Filter
350
- </MenuContentItemLabel>
351
- </MenuContentItem>
352
- </MenuContent>
353
- }
354
- menuProps={{
355
- anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
356
- transformOrigin: { vertical: 'top', horizontal: 'right' },
357
- elevation: 7,
358
- }}
359
- >
360
- <div className="query-builder__sub-header__custom-action__label">
361
- Advanced
362
- </div>
363
- <CaretDownIcon className="query-builder__sub-header__custom-action__icon" />
364
- </DropdownMenu>
326
+ <MenuContentItem
327
+ onClick={toggleShowOlapGroupByPanel}
328
+ disabled={
329
+ !queryBuilderState.isQuerySupported ||
330
+ !(
331
+ queryBuilderState.fetchStructureState
332
+ .implementation instanceof QueryBuilderTDSState
333
+ ) ||
334
+ queryBuilderState.fetchStructureState.implementation
335
+ .olapGroupByState.olapColumns.length > 0
336
+ }
337
+ >
338
+ <MenuContentItemIcon>
339
+ {isTDSState &&
340
+ guaranteeType(
341
+ queryBuilderState.fetchStructureState
342
+ .implementation,
343
+ QueryBuilderTDSState,
344
+ ).showOlapGroupByPanel ? (
345
+ <CheckIcon />
346
+ ) : null}
347
+ </MenuContentItemIcon>
348
+ <MenuContentItemLabel className="query-builder__sub-header__menu-content">
349
+ Show OLAP GroupBy
350
+ </MenuContentItemLabel>
351
+ </MenuContentItem>
352
+ <MenuContentItem
353
+ onClick={toggleShowPostFilterPanel}
354
+ disabled={
355
+ !queryBuilderState.isQuerySupported ||
356
+ !(
357
+ queryBuilderState.fetchStructureState
358
+ .implementation instanceof QueryBuilderTDSState
359
+ ) ||
360
+ Array.from(
361
+ queryBuilderState.fetchStructureState.implementation.postFilterState.nodes.values(),
362
+ ).length > 0
363
+ }
364
+ >
365
+ <MenuContentItemIcon>
366
+ {queryBuilderState.fetchStructureState
367
+ .implementation instanceof QueryBuilderTDSState &&
368
+ queryBuilderState.fetchStructureState.implementation
369
+ .showPostFilterPanel ? (
370
+ <CheckIcon />
371
+ ) : null}
372
+ </MenuContentItemIcon>
373
+ <MenuContentItemLabel className="query-builder__sub-header__menu-content">
374
+ Show Post-Filter
375
+ </MenuContentItemLabel>
376
+ </MenuContentItem>
377
+ <MenuContentItem onClick={openWatermark}>
378
+ <MenuContentItemIcon>{null}</MenuContentItemIcon>
379
+ <MenuContentItemLabel className="query-builder__sub-header__menu-content">
380
+ Edit Watermark
381
+ </MenuContentItemLabel>
382
+ </MenuContentItem>
383
+ </MenuContent>
384
+ }
385
+ menuProps={{
386
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
387
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
388
+ elevation: 7,
389
+ }}
390
+ >
391
+ <div className="query-builder__sub-header__custom-action__label">
392
+ Advanced
393
+ </div>
394
+ <CaretDownIcon className="query-builder__sub-header__custom-action__icon" />
395
+ </DropdownMenu>
396
+ </div>
365
397
  </div>
366
398
  </div>
367
399
  <div className="query-builder__main">
@@ -25,10 +25,14 @@ import {
25
25
  TimesIcon,
26
26
  DollarIcon,
27
27
  PlusIcon,
28
- InputWithInlineValidation,
29
28
  DragPreviewLayer,
30
29
  useDragPreviewLayer,
31
30
  BlankPanelPlaceholder,
31
+ Modal,
32
+ ModalBody,
33
+ ModalFooter,
34
+ ModalHeader,
35
+ PanelFormTextField,
32
36
  } from '@finos/legend-art';
33
37
  import {
34
38
  type QueryBuilderParameterDragSource,
@@ -81,13 +85,6 @@ const VariableExpressionEditor = observer(
81
85
  ? 'Parameter name already exists'
82
86
  : undefined;
83
87
 
84
- // variable
85
- const changeVariableName: React.ChangeEventHandler<HTMLInputElement> = (
86
- event,
87
- ) => {
88
- variableExpression_setName(varState, event.target.value);
89
- };
90
-
91
88
  // type
92
89
  const stringType =
93
90
  queryBuilderState.graphManagerState.graph.getPrimitiveType(
@@ -164,30 +161,25 @@ const VariableExpressionEditor = observer(
164
161
  paper: 'editor-modal__content',
165
162
  }}
166
163
  >
167
- <div className="modal modal--dark editor-modal query-builder__parameters__modal">
168
- <div className="modal__header">
169
- <div className="modal__title">
170
- {`${isCreating ? 'Create ' : 'Update '}`}Parameter
171
- </div>
172
- </div>
173
- <div className="modal__body query-builder__parameters__modal__body">
164
+ <Modal
165
+ darkMode={true}
166
+ className="editor-modal query-builder__parameters__modal"
167
+ >
168
+ <ModalHeader
169
+ title={`${isCreating ? 'Create Parameter' : 'Update Parameter'}`}
170
+ />
171
+ <ModalBody className="query-builder__parameters__modal__body">
174
172
  <div className="panel__content__form__section">
175
- <div className="panel__content__form__section__header__label">
176
- Parameter Name
177
- </div>
178
- <div className="panel__content__form__section__header__prompt">
179
- Name of the parameter. Should be descriptive of its purpose.
180
- </div>
181
- <div className="query-builder__parameters__parameter__name">
182
- <InputWithInlineValidation
183
- className="query-builder__parameters__parameter__name__input input-group__input"
184
- spellCheck={false}
185
- value={varState.name}
186
- onChange={changeVariableName}
187
- placeholder="Parameter name"
188
- validationErrorMessage={validationMessage}
189
- />
190
- </div>
173
+ <PanelFormTextField
174
+ name="Parameter Name"
175
+ prompt="Name of the parameter. Should be descriptive of its purpose."
176
+ update={(value: string | undefined): void =>
177
+ variableExpression_setName(varState, value ?? '')
178
+ }
179
+ value={varState.name}
180
+ errorMessage={validationMessage}
181
+ isReadOnly={false}
182
+ />
191
183
  </div>
192
184
  <div className="panel__content__form__section">
193
185
  <div className="panel__content__form__section__header__label">
@@ -230,8 +222,8 @@ const VariableExpressionEditor = observer(
230
222
  onChange={changeUpperBound}
231
223
  />
232
224
  </div>
233
- </div>
234
- <div className="modal__footer">
225
+ </ModalBody>
226
+ <ModalFooter>
235
227
  {isCreating && (
236
228
  <button
237
229
  className="btn modal__footer__close-btn btn--dark"
@@ -244,8 +236,8 @@ const VariableExpressionEditor = observer(
244
236
  <button className="btn modal__footer__close-btn" onClick={close}>
245
237
  Close
246
238
  </button>
247
- </div>
248
- </div>
239
+ </ModalFooter>
240
+ </Modal>
249
241
  </Dialog>
250
242
  );
251
243
  },
@@ -21,6 +21,10 @@ import {
21
21
  PanelDropZone,
22
22
  InfoCircleIcon,
23
23
  PanelEntryDropZonePlaceholder,
24
+ Modal,
25
+ ModalHeader,
26
+ ModalBody,
27
+ ModalFooter,
24
28
  } from '@finos/legend-art';
25
29
  import { observer } from 'mobx-react-lite';
26
30
  import {
@@ -218,11 +222,12 @@ export const QueryBuilderPropertyExpressionEditor = observer(
218
222
  paper: 'editor-modal__content',
219
223
  }}
220
224
  >
221
- <div className="modal modal--dark editor-modal query-builder-property-editor">
222
- <div className="modal__header">
223
- <div className="modal__title">Derived Property</div>
224
- </div>
225
- <div className="modal__body query-builder-property-editor__content">
225
+ <Modal
226
+ darkMode={true}
227
+ className="editor-modal query-builder-property-editor"
228
+ >
229
+ <ModalHeader title="Derived Property" />
230
+ <ModalBody className="query-builder-property-editor__content">
226
231
  {propertyExpressionState.derivedPropertyExpressionStates.map(
227
232
  (pe) => (
228
233
  <DerivedPropertyExpressionEditor
@@ -231,7 +236,7 @@ export const QueryBuilderPropertyExpressionEditor = observer(
231
236
  />
232
237
  ),
233
238
  )}
234
- <div className="modal__body query-builder__parameters__modal__body">
239
+ <ModalBody className="query-builder__parameters__modal__body">
235
240
  <div className="panel__content__form__section__header__label">
236
241
  List of available parameters
237
242
  </div>
@@ -250,17 +255,17 @@ export const QueryBuilderPropertyExpressionEditor = observer(
250
255
  ),
251
256
  )}
252
257
  </div>
253
- </div>
254
- </div>
255
- <div className="modal__footer">
258
+ </ModalBody>
259
+ </ModalBody>
260
+ <ModalFooter>
256
261
  <button
257
262
  className="btn modal__footer__close-btn"
258
263
  onClick={handleClose}
259
264
  >
260
265
  Done
261
266
  </button>
262
- </div>
263
- </div>
267
+ </ModalFooter>
268
+ </Modal>
264
269
  </Dialog>
265
270
  );
266
271
  },
@@ -28,6 +28,7 @@ import {
28
28
  PauseCircleIcon,
29
29
  ExclamationTriangleIcon,
30
30
  PanelContent,
31
+ MenuContentDivider,
31
32
  } from '@finos/legend-art';
32
33
  import { observer } from 'mobx-react-lite';
33
34
  import { flowResult } from 'mobx';
@@ -272,6 +273,16 @@ const QueryBuilderGridResultContextMenu = observer(
272
273
  );
273
274
  };
274
275
 
276
+ const handleCopyCellValue = applicationStore.guardUnhandledError(() =>
277
+ applicationStore.copyTextToClipboard(event?.value),
278
+ );
279
+
280
+ const handleCopyRowValue = applicationStore.guardUnhandledError(() =>
281
+ applicationStore.copyTextToClipboard(
282
+ Object.values(event?.data).toString(),
283
+ ),
284
+ );
285
+
275
286
  return (
276
287
  <MenuContent ref={ref}>
277
288
  <MenuContentItem
@@ -288,6 +299,13 @@ const QueryBuilderGridResultContextMenu = observer(
288
299
  >
289
300
  Filter Out
290
301
  </MenuContentItem>
302
+ <MenuContentDivider />
303
+ <MenuContentItem onClick={handleCopyCellValue}>
304
+ Copy Cell Value
305
+ </MenuContentItem>
306
+ <MenuContentItem onClick={handleCopyRowValue}>
307
+ Copy Row Value
308
+ </MenuContentItem>
291
309
  </MenuContent>
292
310
  );
293
311
  }),
@@ -16,7 +16,14 @@
16
16
 
17
17
  import { useEffect } from 'react';
18
18
  import { observer } from 'mobx-react-lite';
19
- import { clsx, Dialog } from '@finos/legend-art';
19
+ import {
20
+ clsx,
21
+ Dialog,
22
+ Modal,
23
+ ModalBody,
24
+ ModalFooter,
25
+ ModalHeader,
26
+ } from '@finos/legend-art';
20
27
  import type { QueryBuilderState } from '../stores/QueryBuilderState.js';
21
28
  import { QueryBuilderTextEditorMode } from '../stores/QueryBuilderTextEditorState.js';
22
29
  import { flowResult } from 'mobx';
@@ -57,25 +64,23 @@ export const QueryBuilderTextEditor = observer(
57
64
  paper: 'editor-modal__content',
58
65
  }}
59
66
  >
60
- <div
61
- className={clsx(
62
- 'modal modal--dark editor-modal query-builder-text-mode__modal',
63
- {
64
- 'query-builder-text-mode__modal--has-error': Boolean(
65
- queryTextEditorState.parserError,
66
- ),
67
- },
68
- )}
67
+ <Modal
68
+ darkMode={true}
69
+ className={clsx('editor-modal query-builder-text-mode__modal', {
70
+ 'query-builder-text-mode__modal--has-error': Boolean(
71
+ queryTextEditorState.parserError,
72
+ ),
73
+ })}
69
74
  >
70
- <div className="modal__header">
75
+ <ModalHeader>
71
76
  <div className="modal__title">Query</div>
72
77
  {queryTextEditorState.parserError && (
73
78
  <div className="modal__title__error-badge">
74
79
  Failed to parse query
75
80
  </div>
76
81
  )}
77
- </div>
78
- <div className="modal__body">
82
+ </ModalHeader>
83
+ <ModalBody>
79
84
  <div
80
85
  className={clsx('query-builder-text-mode__modal__content', {
81
86
  backdrop__element: Boolean(queryTextEditorState.parserError),
@@ -101,8 +106,8 @@ export const QueryBuilderTextEditor = observer(
101
106
  />
102
107
  )}
103
108
  </div>
104
- </div>
105
- <div className="modal__footer">
109
+ </ModalBody>
110
+ <ModalFooter>
106
111
  {mode === QueryBuilderTextEditorMode.TEXT && (
107
112
  <button
108
113
  className="btn btn--dark btn--caution"
@@ -118,8 +123,8 @@ export const QueryBuilderTextEditor = observer(
118
123
  >
119
124
  Close
120
125
  </button>
121
- </div>
122
- </div>
126
+ </ModalFooter>
127
+ </Modal>
123
128
  </Dialog>
124
129
  );
125
130
  },
@@ -48,6 +48,10 @@ import {
48
48
  PanelLoadingIndicator,
49
49
  DragPreviewLayer,
50
50
  useDragPreviewLayer,
51
+ Modal,
52
+ ModalBody,
53
+ ModalFooter,
54
+ ModalHeader,
51
55
  } from '@finos/legend-art';
52
56
  import {
53
57
  type QueryBuilderExplorerTreeDragSource,
@@ -208,13 +212,14 @@ const QueryBuilderExplorerPreviewDataModal = observer(
208
212
  paper: 'editor-modal__content',
209
213
  }}
210
214
  >
211
- <div className="modal modal--dark editor-modal query-builder__explorer__preview-data-modal">
212
- <div className="modal__header">
213
- <div className="modal__title">
214
- {prettyPropertyName(previewDataState.propertyName)}
215
- </div>
216
- </div>
217
- <div className="modal__body query-builder__explorer__preview-data-modal__body">
215
+ <Modal
216
+ darkMode={true}
217
+ className="editor-modal query-builder__explorer__preview-data-modal"
218
+ >
219
+ <ModalHeader
220
+ title={prettyPropertyName(previewDataState.propertyName)}
221
+ />
222
+ <ModalBody className="query-builder__explorer__preview-data-modal__body">
218
223
  {previewDataState.previewData && (
219
224
  <table className="table">
220
225
  <thead>
@@ -242,13 +247,13 @@ const QueryBuilderExplorerPreviewDataModal = observer(
242
247
  </tbody>
243
248
  </table>
244
249
  )}
245
- </div>
246
- <div className="modal__footer">
250
+ </ModalBody>
251
+ <ModalFooter>
247
252
  <button className="btn modal__footer__close-btn" onClick={close}>
248
253
  Close
249
254
  </button>
250
- </div>
251
- </div>
255
+ </ModalFooter>
256
+ </Modal>
252
257
  </Dialog>
253
258
  );
254
259
  },
@@ -435,8 +440,10 @@ const QueryBuilderExplorerTreeNodeContainer = observer(
435
440
  />
436
441
  }
437
442
  disabled={
438
- !(node instanceof QueryBuilderExplorerTreePropertyNodeData) ||
439
- applicationStore.showBackdrop
443
+ !(
444
+ node instanceof QueryBuilderExplorerTreePropertyNodeData ||
445
+ node instanceof QueryBuilderExplorerTreeRootNodeData
446
+ ) || applicationStore.showBackdrop
440
447
  }
441
448
  menuProps={{ elevation: 7 }}
442
449
  onOpen={onContextMenuOpen}