@finos/legend-query-builder 4.14.37 → 4.14.39

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. package/lib/__lib__/QueryBuilderTesting.d.ts +2 -1
  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/QueryBuilder.d.ts.map +1 -1
  6. package/lib/components/QueryBuilder.js +10 -9
  7. package/lib/components/QueryBuilder.js.map +1 -1
  8. package/lib/components/QueryBuilderParametersPanel.js +2 -2
  9. package/lib/components/QueryBuilderParametersPanel.js.map +1 -1
  10. package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts +0 -2
  11. package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts.map +1 -1
  12. package/lib/components/QueryBuilderPropertyExpressionEditor.js +10 -26
  13. package/lib/components/QueryBuilderPropertyExpressionEditor.js.map +1 -1
  14. package/lib/components/QueryBuilderSideBar.d.ts.map +1 -1
  15. package/lib/components/QueryBuilderSideBar.js +3 -3
  16. package/lib/components/QueryBuilderSideBar.js.map +1 -1
  17. package/lib/components/QueryBuilderTextEditor.d.ts.map +1 -1
  18. package/lib/components/QueryBuilderTextEditor.js +17 -3
  19. package/lib/components/QueryBuilderTextEditor.js.map +1 -1
  20. package/lib/components/explorer/QueryBuilderMilestoningEditor.d.ts +5 -0
  21. package/lib/components/explorer/QueryBuilderMilestoningEditor.d.ts.map +1 -1
  22. package/lib/components/explorer/QueryBuilderMilestoningEditor.js +10 -5
  23. package/lib/components/explorer/QueryBuilderMilestoningEditor.js.map +1 -1
  24. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
  25. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +45 -12
  26. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  27. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  28. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +13 -5
  29. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  30. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  31. package/lib/components/filter/QueryBuilderFilterPanel.js +1 -2
  32. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  33. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  34. package/lib/components/result/QueryBuilderResultPanel.js +6 -5
  35. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  36. package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -1
  37. package/lib/components/shared/BasicValueSpecificationEditor.js +49 -8
  38. package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -1
  39. package/lib/components/workflows/ClassQueryBuilder.d.ts.map +1 -1
  40. package/lib/components/workflows/ClassQueryBuilder.js +3 -3
  41. package/lib/components/workflows/ClassQueryBuilder.js.map +1 -1
  42. package/lib/components/workflows/MappingQueryBuilder.d.ts.map +1 -1
  43. package/lib/components/workflows/MappingQueryBuilder.js +3 -3
  44. package/lib/components/workflows/MappingQueryBuilder.js.map +1 -1
  45. package/lib/components/workflows/ServiceQueryBuilder.d.ts.map +1 -1
  46. package/lib/components/workflows/ServiceQueryBuilder.js +3 -3
  47. package/lib/components/workflows/ServiceQueryBuilder.js.map +1 -1
  48. package/lib/index.css +2 -2
  49. package/lib/index.css.map +1 -1
  50. package/lib/package.json +1 -1
  51. package/lib/stores/QueryBuilderTextEditorState.d.ts +4 -1
  52. package/lib/stores/QueryBuilderTextEditorState.d.ts.map +1 -1
  53. package/lib/stores/QueryBuilderTextEditorState.js +19 -2
  54. package/lib/stores/QueryBuilderTextEditorState.js.map +1 -1
  55. package/lib/stores/QueryLoaderState.d.ts +2 -2
  56. package/lib/stores/QueryLoaderState.d.ts.map +1 -1
  57. package/lib/stores/QueryLoaderState.js +3 -3
  58. package/lib/stores/QueryLoaderState.js.map +1 -1
  59. package/lib/stores/explorer/QueryFunctionsExplorerState.d.ts +1 -1
  60. package/lib/stores/explorer/QueryFunctionsExplorerState.d.ts.map +1 -1
  61. package/lib/stores/explorer/QueryFunctionsExplorerState.js +2 -1
  62. package/lib/stores/explorer/QueryFunctionsExplorerState.js.map +1 -1
  63. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts +1 -0
  64. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
  65. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +8 -0
  66. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
  67. package/lib/stores/milestoning/QueryBuilderMilestoningState.d.ts.map +1 -1
  68. package/lib/stores/milestoning/QueryBuilderMilestoningState.js +9 -3
  69. package/lib/stores/milestoning/QueryBuilderMilestoningState.js.map +1 -1
  70. package/lib/stores/watermark/QueryBuilderWatermarkState.d.ts.map +1 -1
  71. package/lib/stores/watermark/QueryBuilderWatermarkState.js +0 -1
  72. package/lib/stores/watermark/QueryBuilderWatermarkState.js.map +1 -1
  73. package/package.json +8 -8
  74. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  75. package/src/components/QueryBuilder.tsx +16 -15
  76. package/src/components/QueryBuilderParametersPanel.tsx +2 -2
  77. package/src/components/QueryBuilderPropertyExpressionEditor.tsx +40 -92
  78. package/src/components/QueryBuilderSideBar.tsx +3 -2
  79. package/src/components/QueryBuilderTextEditor.tsx +46 -11
  80. package/src/components/explorer/QueryBuilderMilestoningEditor.tsx +60 -46
  81. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +78 -34
  82. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +121 -34
  83. package/src/components/filter/QueryBuilderFilterPanel.tsx +0 -11
  84. package/src/components/result/QueryBuilderResultPanel.tsx +21 -23
  85. package/src/components/shared/BasicValueSpecificationEditor.tsx +141 -34
  86. package/src/components/workflows/ClassQueryBuilder.tsx +3 -2
  87. package/src/components/workflows/MappingQueryBuilder.tsx +3 -2
  88. package/src/components/workflows/ServiceQueryBuilder.tsx +7 -3
  89. package/src/stores/QueryBuilderTextEditorState.ts +20 -2
  90. package/src/stores/QueryLoaderState.ts +5 -7
  91. package/src/stores/explorer/QueryFunctionsExplorerState.ts +6 -2
  92. package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +11 -0
  93. package/src/stores/milestoning/QueryBuilderMilestoningState.ts +11 -7
  94. package/src/stores/watermark/QueryBuilderWatermarkState.ts +0 -1
@@ -16,7 +16,6 @@
16
16
 
17
17
  import {
18
18
  BlankPanelContent,
19
- PanelLoadingIndicator,
20
19
  PlayIcon,
21
20
  DropdownMenu,
22
21
  MenuContent,
@@ -43,6 +42,8 @@ import {
43
42
  CsvIcon,
44
43
  DebugIcon,
45
44
  ReportIcon,
45
+ CubesLoadingIndicatorIcon,
46
+ CubesLoadingIndicator,
46
47
  } from '@finos/legend-art';
47
48
  import { observer } from 'mobx-react-lite';
48
49
  import { flowResult } from 'mobx';
@@ -334,6 +335,9 @@ export const QueryBuilderResultPanel = observer(
334
335
  </MenuContentItem>
335
336
  ));
336
337
 
338
+ const isLoading =
339
+ resultState.isRunningQuery || resultState.isGeneratingPlan;
340
+
337
341
  return (
338
342
  <div
339
343
  data-testid={QUERY_BUILDER_TEST_ID.QUERY_BUILDER_RESULT_PANEL}
@@ -383,7 +387,7 @@ export const QueryBuilderResultPanel = observer(
383
387
 
384
388
  <div className="panel__header">
385
389
  <div className="panel__header__title">
386
- <div className="panel__header__title__label">result</div>
390
+ <div className="panel__header__title__label">results</div>
387
391
  {executedSql && (
388
392
  <Button
389
393
  onClick={() => setShowSqlModal(true)}
@@ -457,7 +461,7 @@ export const QueryBuilderResultPanel = observer(
457
461
  {allowSettingPreviewLimit && (
458
462
  <div className="query-builder__result__limit">
459
463
  <div className="query-builder__result__limit__label">
460
- preview limit
464
+ preview row limit
461
465
  </div>
462
466
  <input
463
467
  ref={inputRef}
@@ -476,22 +480,20 @@ export const QueryBuilderResultPanel = observer(
476
480
  <div className="query-builder__result__execute-btn btn__dropdown-combo btn__dropdown-combo--primary">
477
481
  {resultState.isRunningQuery ? (
478
482
  <button
479
- className="btn__dropdown-combo__canceler"
483
+ className="btn__dropdown-combo__canceler query-builder__result__execute-btn__btn"
480
484
  onClick={cancelQuery}
481
485
  tabIndex={-1}
482
486
  disabled={!isQueryValid}
483
487
  >
484
- <div className="btn--dark btn--caution btn__dropdown-combo__canceler__label">
485
- <PauseCircleIcon className="btn__dropdown-combo__canceler__label__icon" />
486
- <div className="btn__dropdown-combo__canceler__label__title">
487
- Stop
488
- </div>
488
+ <div className="btn--dark btn--caution btn__dropdown-combo__canceler__label query-builder__result__execute-btn__btn">
489
+ <PauseCircleIcon />
490
+ Stop
489
491
  </div>
490
492
  </button>
491
493
  ) : (
492
494
  <>
493
495
  <button
494
- className="btn__dropdown-combo__label"
496
+ className="btn__dropdown-combo__label query-builder__result__execute-btn__btn query-builder__result__execute-btn__btn--green"
495
497
  onClick={runQuery}
496
498
  tabIndex={-1}
497
499
  title={
@@ -503,13 +505,11 @@ export const QueryBuilderResultPanel = observer(
503
505
  }
504
506
  disabled={isRunQueryDisabled}
505
507
  >
506
- <PlayIcon className="btn__dropdown-combo__label__icon" />
507
- <div className="btn__dropdown-combo__label__title">
508
- Run Query
509
- </div>
508
+ <PlayIcon />
509
+ Run Query
510
510
  </button>
511
511
  <DropdownMenu
512
- className="btn__dropdown-combo__dropdown-btn"
512
+ className="btn__dropdown-combo__dropdown-btn query-builder__result__execute-btn__btn query-builder__result__execute-btn__btn--green"
513
513
  disabled={isRunQueryDisabled}
514
514
  content={
515
515
  <MenuContent>
@@ -617,18 +617,16 @@ export const QueryBuilderResultPanel = observer(
617
617
  ))}
618
618
  </div>
619
619
  </div>
620
- <PanelContent>
621
- <PanelLoadingIndicator
622
- isLoading={
623
- resultState.isRunningQuery || resultState.isGeneratingPlan
624
- }
625
- />
626
- {!executionResult && (
620
+ <PanelContent className="query-builder__result__content">
621
+ <CubesLoadingIndicator isLoading={isLoading}>
622
+ <CubesLoadingIndicatorIcon />
623
+ </CubesLoadingIndicator>
624
+ {!executionResult && !isLoading && (
627
625
  <BlankPanelContent>
628
626
  Build or load a valid query first
629
627
  </BlankPanelContent>
630
628
  )}
631
- {executionResult && (
629
+ {executionResult && !isLoading && (
632
630
  <div className="query-builder__result__values">
633
631
  <QueryBuilderResultValues
634
632
  executionResult={executionResult}
@@ -776,6 +776,98 @@ const setCollectionValue = (
776
776
  instanceValue_setValues(valueSpecification, result, obseverContext);
777
777
  };
778
778
 
779
+ const EnumCollectionInstanceValueEditor = observer(
780
+ (props: {
781
+ valueSpecification: CollectionInstanceValue;
782
+ observerContext: ObserverContext;
783
+ saveEdit: () => void;
784
+ }) => {
785
+ const { valueSpecification, observerContext, saveEdit } = props;
786
+ const applicationStore = useApplicationStore();
787
+ const enumType = guaranteeType(
788
+ valueSpecification.genericType?.value.rawType,
789
+ Enumeration,
790
+ );
791
+
792
+ const [selectedOptions, setSelectedOptions] = useState<
793
+ { label: string; value: Enum }[]
794
+ >(
795
+ (valueSpecification.values as EnumValueInstanceValue[])
796
+ .filter((valueSpec) => valueSpec.values[0]?.value !== undefined)
797
+ .map((valueSpec) => ({
798
+ label: valueSpec.values[0]!.value.name,
799
+ value: valueSpec.values[0]!.value,
800
+ })),
801
+ );
802
+
803
+ const availableOptions = enumType.values
804
+ .filter(
805
+ (value) =>
806
+ !selectedOptions.some(
807
+ (selectedValue) => selectedValue.value.name === value.name,
808
+ ),
809
+ )
810
+ .map((value) => ({
811
+ label: value.name,
812
+ value: value,
813
+ }));
814
+
815
+ const changeValue = (
816
+ newSelectedOptions: { value: Enum; label: string }[],
817
+ ): void => {
818
+ setSelectedOptions(newSelectedOptions);
819
+ };
820
+
821
+ const updateValueSpecAndSaveEdit = (): void => {
822
+ const result = selectedOptions
823
+ .map((value) => {
824
+ const enumValueInstanceValue = new EnumValueInstanceValue(
825
+ GenericTypeExplicitReference.create(new GenericType(enumType)),
826
+ );
827
+ instanceValue_setValues(
828
+ enumValueInstanceValue,
829
+ [EnumValueExplicitReference.create(value.value)],
830
+ observerContext,
831
+ );
832
+ return enumValueInstanceValue;
833
+ })
834
+ .filter(isNonNullable);
835
+ instanceValue_setValues(valueSpecification, result, observerContext);
836
+ saveEdit();
837
+ };
838
+
839
+ return (
840
+ <>
841
+ <CustomSelectorInput
842
+ className="value-spec-editor__enum-collection-selector"
843
+ options={availableOptions}
844
+ isMulti={true}
845
+ onChange={changeValue}
846
+ onBlur={updateValueSpecAndSaveEdit}
847
+ onKeyDown={(event: KeyboardEvent): void => {
848
+ if (event.key === 'Enter' && !event.shiftKey) {
849
+ updateValueSpecAndSaveEdit();
850
+ }
851
+ }}
852
+ value={selectedOptions}
853
+ darkMode={
854
+ !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
855
+ }
856
+ placeholder="Select value"
857
+ autoFocus={true}
858
+ menuIsOpen={true}
859
+ />
860
+ <button
861
+ className="value-spec-editor__list-editor__save-button btn--dark"
862
+ onClick={updateValueSpecAndSaveEdit}
863
+ >
864
+ <SaveIcon />
865
+ </button>
866
+ </>
867
+ );
868
+ },
869
+ );
870
+
779
871
  const COLLECTION_PREVIEW_CHAR_LIMIT = 50;
780
872
 
781
873
  const getPlaceHolder = (expectedType: Type): string => {
@@ -836,6 +928,11 @@ const CollectionValueInstanceValueEditor = observer(
836
928
  if (editable) {
837
929
  setEditable(false);
838
930
  setShowAdvancedEditorPopover(false);
931
+ setValueSpecification(valueSpecification);
932
+ }
933
+ };
934
+ const updateValueSpecAndSaveEdit = (): void => {
935
+ if (editable) {
839
936
  setCollectionValue(
840
937
  valueSpecification,
841
938
  expectedType,
@@ -843,7 +940,7 @@ const CollectionValueInstanceValueEditor = observer(
843
940
  obseverContext,
844
941
  );
845
942
  setText(stringifyValue(valueSpecification.values));
846
- setValueSpecification(valueSpecification);
943
+ saveEdit();
847
944
  }
848
945
  };
849
946
 
@@ -861,7 +958,7 @@ const CollectionValueInstanceValueEditor = observer(
861
958
  (event.relatedTarget as HTMLButtonElement | undefined)?.name !==
862
959
  expandButtonName
863
960
  ) {
864
- saveEdit();
961
+ updateValueSpecAndSaveEdit();
865
962
  }
866
963
  };
867
964
 
@@ -891,7 +988,7 @@ const CollectionValueInstanceValueEditor = observer(
891
988
  onChange={changeValueTextArea}
892
989
  onKeyDown={(event): void => {
893
990
  if (event.key === 'Enter' && !event.shiftKey) {
894
- saveEdit();
991
+ updateValueSpecAndSaveEdit();
895
992
  }
896
993
  }}
897
994
  />
@@ -903,37 +1000,47 @@ const CollectionValueInstanceValueEditor = observer(
903
1000
  </BasePopover>
904
1001
  )}
905
1002
  <div className={clsx('value-spec-editor', className)}>
906
- <textarea
907
- ref={inputRef}
908
- className={clsx(
909
- 'panel__content__form__section__input value-spec-editor__input value-spec-editor__textarea ',
910
- )}
911
- spellCheck={false}
912
- value={text}
913
- placeholder={placeholder}
914
- onChange={changeValueTextArea}
915
- onKeyDown={(event): void => {
916
- if (event.key === 'Enter' && !event.shiftKey) {
917
- saveEdit();
918
- }
919
- }}
920
- onBlur={handleOnBlur}
921
- />
922
- <button
923
- className="value-spec-editor__list-editor__expand-button btn--dark"
924
- onClick={() => setShowAdvancedEditorPopover(true)}
925
- tabIndex={-1}
926
- name={expandButtonName}
927
- title="Expand window..."
928
- >
929
- <FilledWindowMaximizeIcon />
930
- </button>
931
- <button
932
- className="value-spec-editor__list-editor__save-button btn--dark"
933
- onClick={saveEdit}
934
- >
935
- <SaveIcon />
936
- </button>
1003
+ {expectedType instanceof Enumeration ? (
1004
+ <EnumCollectionInstanceValueEditor
1005
+ valueSpecification={valueSpecification}
1006
+ observerContext={obseverContext}
1007
+ saveEdit={saveEdit}
1008
+ />
1009
+ ) : (
1010
+ <>
1011
+ <textarea
1012
+ ref={inputRef}
1013
+ className={clsx(
1014
+ 'panel__content__form__section__input value-spec-editor__input value-spec-editor__textarea ',
1015
+ )}
1016
+ spellCheck={false}
1017
+ value={text}
1018
+ placeholder={placeholder}
1019
+ onChange={changeValueTextArea}
1020
+ onKeyDown={(event): void => {
1021
+ if (event.key === 'Enter' && !event.shiftKey) {
1022
+ updateValueSpecAndSaveEdit();
1023
+ }
1024
+ }}
1025
+ onBlur={handleOnBlur}
1026
+ />
1027
+ <button
1028
+ className="value-spec-editor__list-editor__expand-button btn--dark"
1029
+ onClick={() => setShowAdvancedEditorPopover(true)}
1030
+ tabIndex={-1}
1031
+ name={expandButtonName}
1032
+ title="Expand window..."
1033
+ >
1034
+ <FilledWindowMaximizeIcon />
1035
+ </button>
1036
+ <button
1037
+ className="value-spec-editor__list-editor__save-button btn--dark"
1038
+ onClick={saveEdit}
1039
+ >
1040
+ <SaveIcon />
1041
+ </button>
1042
+ </>
1043
+ )}
937
1044
  <button
938
1045
  className="value-spec-editor__reset-btn"
939
1046
  name="Reset"
@@ -17,6 +17,7 @@
17
17
  import {
18
18
  CustomSelectorInput,
19
19
  PanelHeader,
20
+ compareLabelFn,
20
21
  createFilter,
21
22
  } from '@finos/legend-art';
22
23
  import { observer } from 'mobx-react-lite';
@@ -71,7 +72,7 @@ const ClassQueryBuilderSetupPanelContent = observer(
71
72
  : []
72
73
  )
73
74
  .map(buildElementOption)
74
- .sort((a, b) => a.label.localeCompare(b.label));
75
+ .sort(compareLabelFn);
75
76
  const selectedMappingOption = queryBuilderState.executionContextState
76
77
  .mapping
77
78
  ? buildElementOption(queryBuilderState.executionContextState.mapping)
@@ -107,7 +108,7 @@ const ClassQueryBuilderSetupPanelContent = observer(
107
108
  new RuntimePointer(PackageableElementExplicitReference.create(rt)),
108
109
  )
109
110
  .map(buildRuntimeValueOption)
110
- .sort((a, b) => a.label.localeCompare(b.label));
111
+ .sort(compareLabelFn);
111
112
  const selectedRuntimeOption = queryBuilderState.executionContextState
112
113
  .runtimeValue
113
114
  ? buildRuntimeValueOption(
@@ -17,6 +17,7 @@
17
17
  import {
18
18
  CustomSelectorInput,
19
19
  PanelHeader,
20
+ compareLabelFn,
20
21
  createFilter,
21
22
  } from '@finos/legend-art';
22
23
  import { observer } from 'mobx-react-lite';
@@ -59,7 +60,7 @@ const MappingQueryBuilderSetupPanelContent = observer(
59
60
  // mapping
60
61
  const mappingOptions = queryBuilderState.graphManagerState.usableMappings
61
62
  .map(buildElementOption)
62
- .sort((a, b) => a.label.localeCompare(b.label));
63
+ .sort(compareLabelFn);
63
64
  const selectedMappingOption = queryBuilderState.executionContextState
64
65
  .mapping
65
66
  ? buildElementOption(queryBuilderState.executionContextState.mapping)
@@ -93,7 +94,7 @@ const MappingQueryBuilderSetupPanelContent = observer(
93
94
  new RuntimePointer(PackageableElementExplicitReference.create(rt)),
94
95
  )
95
96
  .map(buildRuntimeValueOption)
96
- .sort((a, b) => a.label.localeCompare(b.label));
97
+ .sort(compareLabelFn);
97
98
  const selectedRuntimeOption = queryBuilderState.executionContextState
98
99
  .runtimeValue
99
100
  ? buildRuntimeValueOption(
@@ -14,7 +14,11 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { CustomSelectorInput, PanelHeader } from '@finos/legend-art';
17
+ import {
18
+ CustomSelectorInput,
19
+ PanelHeader,
20
+ compareLabelFn,
21
+ } from '@finos/legend-art';
18
22
  import { observer } from 'mobx-react-lite';
19
23
  import { getMappingCompatibleClasses, type Service } from '@finos/legend-graph';
20
24
  import { useApplicationStore } from '@finos/legend-application';
@@ -57,7 +61,7 @@ const ServiceQueryBuilderSetupPanelContent = observer(
57
61
  const serviceOptions =
58
62
  queryBuilderState.usableServices
59
63
  ?.map(buildElementOption)
60
- .sort((a, b) => a.label.localeCompare(b.label)) ?? [];
64
+ .sort(compareLabelFn) ?? [];
61
65
  const selectedServiceOption = buildElementOption(queryBuilderState.service);
62
66
  const onServiceOptionChange = (
63
67
  option: PackageableElementOption<Service>,
@@ -71,7 +75,7 @@ const ServiceQueryBuilderSetupPanelContent = observer(
71
75
  // execution context
72
76
  const executionContextOptions = queryBuilderState.executionContexts
73
77
  .map(buildExecutionContextOption)
74
- .sort((a, b) => a.label.localeCompare(b.label));
78
+ .sort(compareLabelFn);
75
79
  const selectedExecutionContextOption =
76
80
  queryBuilderState.selectedExecutionContext
77
81
  ? buildExecutionContextOption(
@@ -67,6 +67,7 @@ export class QueryBuilderTextEditorState extends LambdaEditorState {
67
67
  * TODO: consider moving this to another state if we need to simplify the logic of text-mode
68
68
  */
69
69
  readOnlylambdaJson = '';
70
+ isReadOnly: boolean | undefined;
70
71
 
71
72
  constructor(queryBuilderState: QueryBuilderState) {
72
73
  super('', '');
@@ -75,7 +76,9 @@ export class QueryBuilderTextEditorState extends LambdaEditorState {
75
76
  rawLambdaState: observable,
76
77
  isConvertingLambdaToString: observable,
77
78
  mode: observable,
79
+ isReadOnly: observable,
78
80
  setQueryRawLambdaState: action,
81
+ setIsReadOnly: action,
79
82
  setMode: action,
80
83
  openModal: action,
81
84
  closeModal: flow,
@@ -89,10 +92,23 @@ export class QueryBuilderTextEditorState extends LambdaEditorState {
89
92
  return buildSourceInformationSourceId(['query-builder']);
90
93
  }
91
94
 
95
+ get text(): string | undefined {
96
+ if (this.mode === QueryBuilderTextEditorMode.TEXT) {
97
+ return this.fullLambdaString;
98
+ } else if (this.mode === QueryBuilderTextEditorMode.JSON) {
99
+ return this.readOnlylambdaJson;
100
+ }
101
+ return undefined;
102
+ }
103
+
92
104
  setQueryRawLambdaState(rawLambdaState: QueryBuilderRawLambdaState): void {
93
105
  this.rawLambdaState = rawLambdaState;
94
106
  }
95
107
 
108
+ setIsReadOnly(val: boolean | undefined): void {
109
+ this.isReadOnly = val;
110
+ }
111
+
96
112
  setMode(openModal: QueryBuilderTextEditorMode | undefined): void {
97
113
  this.mode = openModal;
98
114
  }
@@ -170,7 +186,7 @@ export class QueryBuilderTextEditorState extends LambdaEditorState {
170
186
  }
171
187
  }
172
188
 
173
- openModal(mode: QueryBuilderTextEditorMode): void {
189
+ openModal(mode: QueryBuilderTextEditorMode, isReadOnly?: boolean): void {
174
190
  try {
175
191
  const rawLambda = this.queryBuilderState.buildQuery();
176
192
  if (mode === QueryBuilderTextEditorMode.TEXT) {
@@ -190,6 +206,7 @@ export class QueryBuilderTextEditorState extends LambdaEditorState {
190
206
  );
191
207
  }
192
208
  this.setMode(mode);
209
+ this.setIsReadOnly(isReadOnly);
193
210
  } catch (error) {
194
211
  assertErrorThrown(error);
195
212
  this.queryBuilderState.applicationStore.notificationService.notifyError(
@@ -200,7 +217,7 @@ export class QueryBuilderTextEditorState extends LambdaEditorState {
200
217
 
201
218
  *closeModal(): GeneratorFn<void> {
202
219
  this.closingQueryState.inProgress();
203
- if (this.mode === QueryBuilderTextEditorMode.TEXT) {
220
+ if (this.mode === QueryBuilderTextEditorMode.TEXT && !this.isReadOnly) {
204
221
  yield flowResult(this.convertLambdaGrammarStringToObject());
205
222
  if (this.parserError) {
206
223
  this.queryBuilderState.applicationStore.notificationService.notifyError(
@@ -215,6 +232,7 @@ export class QueryBuilderTextEditorState extends LambdaEditorState {
215
232
  }
216
233
  return;
217
234
  }
235
+ this.setIsReadOnly(undefined);
218
236
  this.closingQueryState.complete();
219
237
 
220
238
  this.setMode(undefined);
@@ -65,7 +65,7 @@ export class QueryLoaderState {
65
65
 
66
66
  readonly isReadOnly?: boolean | undefined;
67
67
  readonly onQueryRenamed?: ((query: LightQuery) => void) | undefined;
68
- readonly onQueryDeleted?: ((query: LightQuery) => void) | undefined;
68
+ readonly onQueryDeleted?: ((query: string) => void) | undefined;
69
69
  readonly handleFetchDefaultQueriesFailure?: (() => void) | undefined;
70
70
 
71
71
  queryBuilderState?: QueryBuilderState | undefined;
@@ -100,7 +100,7 @@ export class QueryLoaderState {
100
100
 
101
101
  isReadOnly?: boolean | undefined;
102
102
  onQueryRenamed?: ((query: LightQuery) => void) | undefined;
103
- onQueryDeleted?: ((query: LightQuery) => void) | undefined;
103
+ onQueryDeleted?: ((query: string) => void) | undefined;
104
104
  handleFetchDefaultQueriesFailure?: (() => void) | undefined;
105
105
  },
106
106
  ) {
@@ -304,11 +304,9 @@ export class QueryLoaderState {
304
304
  *deleteQuery(queryId: string): GeneratorFn<void> {
305
305
  this.deleteQueryState.inProgress();
306
306
  try {
307
- const query = (yield this.graphManagerState.graphManager.deleteQuery(
308
- queryId,
309
- )) as Query;
310
- this.onQueryDeleted?.(query);
311
- this.applicationStore.notificationService.notify(
307
+ yield this.graphManagerState.graphManager.deleteQuery(queryId);
308
+ this.onQueryDeleted?.(queryId);
309
+ this.applicationStore.notificationService.notifySuccess(
312
310
  'Deleted query successfully',
313
311
  );
314
312
  this.deleteQueryState.pass();
@@ -30,7 +30,11 @@ import {
30
30
  } from '@finos/legend-shared';
31
31
  import { action, makeObservable, observable } from 'mobx';
32
32
  import type { QueryBuilderState } from '../QueryBuilderState.js';
33
- import type { TreeNodeData, TreeData } from '@finos/legend-art';
33
+ import {
34
+ type TreeNodeData,
35
+ type TreeData,
36
+ compareLabelFn,
37
+ } from '@finos/legend-art';
34
38
 
35
39
  export const QUERY_BUILDER_FUNCTION_DND_TYPE = 'QUERY_BUILDER_FUNCTION';
36
40
 
@@ -206,7 +210,7 @@ export const getFunctionsExplorerTreeNodeChildren = (
206
210
  return node.childrenIds
207
211
  .map((id) => data.nodes.get(id))
208
212
  .filter(isNonNullable)
209
- .sort((a, b) => a.label.localeCompare(b.label))
213
+ .sort(compareLabelFn)
210
214
  .sort(
211
215
  (a, b) =>
212
216
  (b.packageableElement instanceof Package ? 1 : 0) -
@@ -146,6 +146,7 @@ export class QueryBuilderTDSState
146
146
  TEMPORARY__showPostFetchStructurePanel: computed,
147
147
  derivations: computed,
148
148
  hasParserError: computed,
149
+ isQueryOptionsSet: computed,
149
150
  addColumn: action,
150
151
  moveColumn: action,
151
152
  removeAllColumns: action,
@@ -356,6 +357,16 @@ export class QueryBuilderTDSState
356
357
  return fetchStructureValidationIssues;
357
358
  }
358
359
 
360
+ get isQueryOptionsSet(): boolean {
361
+ return (
362
+ this.resultSetModifierState.limit !== undefined ||
363
+ this.queryBuilderState.milestoningState.isMilestonedQuery ||
364
+ this.resultSetModifierState.slice !== undefined ||
365
+ this.resultSetModifierState.sortColumns.length > 0 ||
366
+ this.resultSetModifierState.distinct
367
+ );
368
+ }
369
+
359
370
  get tdsColumns(): QueryBuilderTDSColumnState[] {
360
371
  const aggregationStateCols = this.aggregationState.columns.map(
361
372
  (c) => c.projectionColumnState,
@@ -75,7 +75,7 @@ export class QueryBuilderMilestoningState implements Hashable {
75
75
  startDate: observable,
76
76
  endDate: observable,
77
77
  showMilestoningEditor: observable,
78
- isMilestonedQuery: computed,
78
+
79
79
  setProcessingDate: action,
80
80
  setBusinessDate: action,
81
81
  setStartDate: action,
@@ -87,6 +87,10 @@ export class QueryBuilderMilestoningState implements Hashable {
87
87
  initializeAllVersionsInRangeParameters: action,
88
88
  clearAllVersionsInRangeParameters: action,
89
89
  clearGetAllParameters: action,
90
+
91
+ isAllVersionsEnabled: computed,
92
+ isAllVersionsInRangeEnabled: computed,
93
+ isMilestonedQuery: computed,
90
94
  hashCode: computed,
91
95
  });
92
96
 
@@ -380,9 +384,9 @@ export class QueryBuilderMilestoningState implements Hashable {
380
384
  this.queryBuilderState.parametersState.parameterStates.find(
381
385
  (p) => p.parameter === this.startDate,
382
386
  );
383
- this.queryBuilderState.parametersState.removeParameter(
384
- guaranteeNonNullable(paramState),
385
- );
387
+ if (paramState) {
388
+ this.queryBuilderState.parametersState.removeParameter(paramState);
389
+ }
386
390
  }
387
391
  if (
388
392
  this.endDate instanceof VariableExpression &&
@@ -394,9 +398,9 @@ export class QueryBuilderMilestoningState implements Hashable {
394
398
  this.queryBuilderState.parametersState.parameterStates.find(
395
399
  (p) => p.parameter === this.endDate,
396
400
  );
397
- this.queryBuilderState.parametersState.removeParameter(
398
- guaranteeNonNullable(paramState),
399
- );
401
+ if (paramState) {
402
+ this.queryBuilderState.parametersState.removeParameter(paramState);
403
+ }
400
404
  }
401
405
  this.setStartDate(undefined);
402
406
  this.setEndDate(undefined);
@@ -50,7 +50,6 @@ export class QueryBuilderWatermarkState implements Hashable {
50
50
  ),
51
51
  );
52
52
 
53
- watermarkConstant.values = ['watermarkValue'];
54
53
  return watermarkConstant;
55
54
  }
56
55