@finos/legend-query-builder 2.0.1 → 2.1.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.
Files changed (38) hide show
  1. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  2. package/lib/components/QueryBuilderResultPanel.js +6 -7
  3. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  4. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  5. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +19 -17
  6. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  7. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
  8. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +31 -29
  9. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
  10. package/lib/index.css +2 -2
  11. package/lib/index.css.map +1 -1
  12. package/lib/package.json +2 -2
  13. package/lib/stores/QueryBuilderResultState.d.ts +7 -3
  14. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  15. package/lib/stores/QueryBuilderResultState.js +14 -20
  16. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  17. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts +3 -0
  18. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts.map +1 -1
  19. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js.map +1 -1
  20. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts +10 -1
  21. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
  22. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +36 -1
  23. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
  24. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts +6 -0
  25. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
  26. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +21 -2
  27. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
  28. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThanEqual.js +4 -4
  29. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThanEqual.js.map +1 -1
  30. package/package.json +9 -9
  31. package/src/components/QueryBuilderResultPanel.tsx +18 -20
  32. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +128 -126
  33. package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +254 -251
  34. package/src/stores/QueryBuilderResultState.ts +28 -33
  35. package/src/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.ts +5 -0
  36. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +44 -0
  37. package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +28 -0
  38. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThanEqual.ts +4 -4
@@ -29,7 +29,6 @@ import {
29
29
  clsx,
30
30
  PanelEntryDropZonePlaceholder,
31
31
  ContextMenu,
32
- VerticalDragHandleIcon,
33
32
  TimesIcon,
34
33
  useDragPreviewLayer,
35
34
  SortIcon,
@@ -43,6 +42,8 @@ import {
43
42
  ModalFooter,
44
43
  PanelFormSection,
45
44
  ModalFooterButton,
45
+ PanelDnDEntryDragHandle,
46
+ PanelDnDEntry,
46
47
  } from '@finos/legend-art';
47
48
  import { assertErrorThrown, guaranteeNonNullable } from '@finos/legend-shared';
48
49
  import { observer } from 'mobx-react-lite';
@@ -669,6 +670,8 @@ const QueryBuilderWindowColumnEditor = observer(
669
670
  const operators = windowState.operators;
670
671
  // state
671
672
  const ref = useRef<HTMLDivElement>(null);
673
+ const handleRef = useRef<HTMLDivElement>(null);
674
+
672
675
  const [windowAnchor, setWindowAnchor] = useState<HTMLButtonElement | null>(
673
676
  null,
674
677
  );
@@ -796,7 +799,8 @@ const QueryBuilderWindowColumnEditor = observer(
796
799
  [windowColumnState],
797
800
  );
798
801
  const isBeingDragged = windowColumnState === olapColumnBeingDragged;
799
- dragConnector(dropConnector(ref));
802
+ dragConnector(handleRef);
803
+ dropConnector(ref);
800
804
  useDragPreviewLayer(dragPreviewConnector);
801
805
 
802
806
  const handleOpDrop = (val: QueryBuilderTDSColumnState): void => {
@@ -846,273 +850,272 @@ const QueryBuilderWindowColumnEditor = observer(
846
850
  );
847
851
 
848
852
  return (
849
- <div ref={ref} className="query-builder__olap__column">
850
- <PanelEntryDropZonePlaceholder
851
- showPlaceholder={isBeingDragged}
852
- className="query-builder__dnd__placeholder"
853
+ <PanelDnDEntry
854
+ ref={ref}
855
+ className="query-builder__olap__column"
856
+ showPlaceholder={isBeingDragged}
857
+ >
858
+ <ContextMenu
859
+ content={
860
+ <QueryBuilderWindowColumnContextMenu
861
+ columnState={windowColumnState}
862
+ />
863
+ }
864
+ className={clsx('query-builder__olap__column__context-menu', {
865
+ 'query-builder__olap__column--selected-from-context-menu':
866
+ isSelectedFromContextMenu,
867
+ })}
868
+ menuProps={{ elevation: 7 }}
869
+ onOpen={onContextMenuOpen}
870
+ onClose={onContextMenuClose}
853
871
  >
854
- <ContextMenu
855
- content={
856
- <QueryBuilderWindowColumnContextMenu
857
- columnState={windowColumnState}
858
- />
859
- }
860
- className={clsx('query-builder__olap__column__context-menu', {
861
- 'query-builder__olap__column--selected-from-context-menu':
862
- isSelectedFromContextMenu,
863
- })}
864
- menuProps={{ elevation: 7 }}
865
- onOpen={onContextMenuOpen}
866
- onClose={onContextMenuClose}
867
- >
868
- <div className="query-builder__olap__column__drag-handle__container">
869
- <div className="query-builder__olap__column__drag-handle">
870
- <VerticalDragHandleIcon />
872
+ <PanelDnDEntryDragHandle
873
+ isBeingDragged={isBeingDragged}
874
+ className="query-builder__olap__column__drag-handle__container"
875
+ dropTargetConnector={handleRef}
876
+ />
877
+ <div className="query-builder__olap__column__operation">
878
+ <div className="query-builder__olap__column__operation__operator">
879
+ <div
880
+ className={clsx(
881
+ 'query-builder__olap__column__operation__operator__label',
882
+ {
883
+ 'query-builder__olap__column__operation__operator__label__agg':
884
+ !aggregateColumn,
885
+ },
886
+ )}
887
+ >
888
+ {operationState.operator.getLabel()}
871
889
  </div>
890
+ {aggregateColumn && (
891
+ <TDSColumnReferenceEditor
892
+ tdsColumn={aggregateColumn}
893
+ handleChange={handleOpDrop}
894
+ selectionEditor={{
895
+ options: windowColumnState.possibleReferencedColumns,
896
+ }}
897
+ />
898
+ )}
899
+ <DropdownMenu
900
+ className="query-builder__olap__column__operation__operator__dropdown"
901
+ disabled={!operators.length}
902
+ content={
903
+ <MenuContent>
904
+ {operators.map((op) => (
905
+ <MenuContentItem
906
+ key={op.uuid}
907
+ className="query-builder__olap__column__operation__operator__dropdown__option"
908
+ onClick={changeOperator(op)}
909
+ >
910
+ {op.getLabel()}
911
+ </MenuContentItem>
912
+ ))}
913
+ </MenuContent>
914
+ }
915
+ menuProps={{
916
+ anchorOrigin: { vertical: 'bottom', horizontal: 'left' },
917
+ transformOrigin: { vertical: 'top', horizontal: 'left' },
918
+ elevation: 7,
919
+ }}
920
+ >
921
+ <button
922
+ className="query-builder__olap__column__operation__operator__badge"
923
+ tabIndex={-1}
924
+ title="Choose Window Function Operator..."
925
+ >
926
+ <SigmaIcon />
927
+ </button>
928
+ <button
929
+ className="query-builder__olap__column__operation__operator__dropdown__trigger"
930
+ tabIndex={-1}
931
+ title="Choose Window Function Operator..."
932
+ >
933
+ <CaretDownIcon />
934
+ </button>
935
+ </DropdownMenu>
872
936
  </div>
873
- <div className="query-builder__olap__column__operation">
874
- <div className="query-builder__olap__column__operation__operator">
937
+ </div>
938
+ <div className="query-builder__olap__column__window">
939
+ <button
940
+ ref={dropOpConnector}
941
+ title="Click to edit or drag and drop columns"
942
+ onClick={openWindowPopover}
943
+ className="query-builder__olap__column__window__content"
944
+ >
945
+ <PanelEntryDropZonePlaceholder
946
+ showPlaceholder={isDragOver}
947
+ label="Add"
948
+ className="query-builder__dnd__placeholder"
949
+ >
950
+ <div
951
+ title={`${windowColumnState.windowColumns.length} columns partitioned`}
952
+ className="query-builder__olap__column__window__content__label"
953
+ >
954
+ ({windowColumnState.windowColumns.length})
955
+ </div>
875
956
  <div
876
957
  className={clsx(
877
- 'query-builder__olap__column__operation__operator__label',
878
- {
879
- 'query-builder__olap__column__operation__operator__label__agg':
880
- !aggregateColumn,
881
- },
958
+ 'query-builder__olap__column__window__operator__badge',
882
959
  )}
960
+ tabIndex={-1}
961
+ title="Edit window columns..."
883
962
  >
884
- {operationState.operator.getLabel()}
963
+ <WindowIcon />
885
964
  </div>
886
- {aggregateColumn && (
887
- <TDSColumnReferenceEditor
888
- tdsColumn={aggregateColumn}
889
- handleChange={handleOpDrop}
890
- selectionEditor={{
891
- options: windowColumnState.possibleReferencedColumns,
892
- }}
893
- />
894
- )}
895
- <DropdownMenu
896
- className="query-builder__olap__column__operation__operator__dropdown"
897
- disabled={!operators.length}
898
- content={
899
- <MenuContent>
900
- {operators.map((op) => (
901
- <MenuContentItem
902
- key={op.uuid}
903
- className="query-builder__olap__column__operation__operator__dropdown__option"
904
- onClick={changeOperator(op)}
905
- >
906
- {op.getLabel()}
907
- </MenuContentItem>
908
- ))}
909
- </MenuContent>
910
- }
911
- menuProps={{
912
- anchorOrigin: { vertical: 'bottom', horizontal: 'left' },
913
- transformOrigin: { vertical: 'top', horizontal: 'left' },
914
- elevation: 7,
915
- }}
916
- >
917
- <button
918
- className="query-builder__olap__column__operation__operator__badge"
919
- tabIndex={-1}
920
- title="Choose Window Function Operator..."
921
- >
922
- <SigmaIcon />
923
- </button>
924
- <button
925
- className="query-builder__olap__column__operation__operator__dropdown__trigger"
926
- tabIndex={-1}
927
- title="Choose Window Function Operator..."
928
- >
929
- <CaretDownIcon />
930
- </button>
931
- </DropdownMenu>
932
- </div>
933
- </div>
934
- <div className="query-builder__olap__column__window">
935
- <button
936
- ref={dropOpConnector}
937
- title="Click to edit or drag and drop columns"
938
- onClick={openWindowPopover}
939
- className="query-builder__olap__column__window__content"
940
- >
941
- <PanelEntryDropZonePlaceholder
942
- showPlaceholder={isDragOver}
943
- label="Add"
944
- className="query-builder__dnd__placeholder"
945
- >
946
- <div
947
- title={`${windowColumnState.windowColumns.length} columns partitioned`}
948
- className="query-builder__olap__column__window__content__label"
949
- >
950
- ({windowColumnState.windowColumns.length})
951
- </div>
952
- <div
953
- className={clsx(
954
- 'query-builder__olap__column__window__operator__badge',
955
- )}
956
- tabIndex={-1}
957
- title="Edit window columns..."
958
- >
959
- <WindowIcon />
965
+ </PanelEntryDropZonePlaceholder>
966
+ </button>
967
+ <BasePopover
968
+ open={Boolean(windowAnchor)}
969
+ anchorEl={windowAnchor}
970
+ onClose={closeWindowPopover}
971
+ anchorOrigin={{
972
+ vertical: 'bottom',
973
+ horizontal: 'center',
974
+ }}
975
+ transformOrigin={{
976
+ vertical: 'top',
977
+ horizontal: 'center',
978
+ }}
979
+ >
980
+ <div className="query-builder__olap__column__window__popover">
981
+ <div className="panel__content__form__section__list">
982
+ <div className="panel__content__form__section__list__items">
983
+ {windowColumnState.windowColumns.map((value, idx) => (
984
+ <TDSColumnSelectorEditor
985
+ key={value.uuid}
986
+ colValue={value}
987
+ setColumn={(v: QueryBuilderTDSColumnState) =>
988
+ windowColumnState.changeWindow(v, idx)
989
+ }
990
+ deleteColumn={(v: QueryBuilderTDSColumnState): void =>
991
+ windowColumnState.deleteWindow(v)
992
+ }
993
+ tdsColOptions={windowOptions}
994
+ />
995
+ ))}
960
996
  </div>
961
- </PanelEntryDropZonePlaceholder>
962
- </button>
963
- <BasePopover
964
- open={Boolean(windowAnchor)}
965
- anchorEl={windowAnchor}
966
- onClose={closeWindowPopover}
967
- anchorOrigin={{
968
- vertical: 'bottom',
969
- horizontal: 'center',
970
- }}
971
- transformOrigin={{
972
- vertical: 'top',
973
- horizontal: 'center',
974
- }}
975
- >
976
- <div className="query-builder__olap__column__window__popover">
977
- <div className="panel__content__form__section__list">
978
- <div className="panel__content__form__section__list__items">
979
- {windowColumnState.windowColumns.map((value, idx) => (
980
- <TDSColumnSelectorEditor
981
- key={value.uuid}
982
- colValue={value}
983
- setColumn={(v: QueryBuilderTDSColumnState) =>
984
- windowColumnState.changeWindow(v, idx)
985
- }
986
- deleteColumn={(v: QueryBuilderTDSColumnState): void =>
987
- windowColumnState.deleteWindow(v)
988
- }
989
- tdsColOptions={windowOptions}
990
- />
991
- ))}
992
- </div>
993
- <div className="panel__content__form__section__list__new-item__add">
994
- <button
995
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
996
- disabled={!addWindowOptions.length}
997
- onClick={addWindowValue}
998
- tabIndex={-1}
999
- >
1000
- Add Value
1001
- </button>
1002
- </div>
997
+ <div className="panel__content__form__section__list__new-item__add">
998
+ <button
999
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
1000
+ disabled={!addWindowOptions.length}
1001
+ onClick={addWindowValue}
1002
+ tabIndex={-1}
1003
+ >
1004
+ Add Value
1005
+ </button>
1003
1006
  </div>
1004
1007
  </div>
1005
- </BasePopover>
1006
- </div>
1007
- <div className="query-builder__olap__column__sortby">
1008
- <div className="query-builder__olap__column__sortby__operator">
1009
- {sortByState && (
1010
- <div className="query-builder__olap__column__sortby__operator__label">
1011
- {sortByState.sortType.toLowerCase()}
1012
- </div>
1013
- )}
1014
- {sortByState && (
1015
- <TDSColumnReferenceEditor
1016
- tdsColumn={sortByState.columnState}
1017
- handleChange={handleSortDrop}
1018
- selectionEditor={{
1019
- options: windowColumnState.possibleReferencedColumns,
1020
- }}
1021
- />
1022
- )}
1023
- {!sortByState && (
1024
- <div className="query-builder__olap__column__sortby__none">
1025
- (none)
1026
- </div>
1027
- )}
1028
- <DropdownMenu
1029
- className="query-builder__olap__column__sortby__operator__dropdown"
1030
- content={
1031
- <MenuContent>
1008
+ </div>
1009
+ </BasePopover>
1010
+ </div>
1011
+ <div className="query-builder__olap__column__sortby">
1012
+ <div className="query-builder__olap__column__sortby__operator">
1013
+ {sortByState && (
1014
+ <div className="query-builder__olap__column__sortby__operator__label">
1015
+ {sortByState.sortType.toLowerCase()}
1016
+ </div>
1017
+ )}
1018
+ {sortByState && (
1019
+ <TDSColumnReferenceEditor
1020
+ tdsColumn={sortByState.columnState}
1021
+ handleChange={handleSortDrop}
1022
+ selectionEditor={{
1023
+ options: windowColumnState.possibleReferencedColumns,
1024
+ }}
1025
+ />
1026
+ )}
1027
+ {!sortByState && (
1028
+ <div className="query-builder__olap__column__sortby__none">
1029
+ (none)
1030
+ </div>
1031
+ )}
1032
+ <DropdownMenu
1033
+ className="query-builder__olap__column__sortby__operator__dropdown"
1034
+ content={
1035
+ <MenuContent>
1036
+ <MenuContentItem
1037
+ key="none"
1038
+ className="query-builder__olap__column__sortby__operator__dropdown__option"
1039
+ onClick={changeSortBy(undefined)}
1040
+ >
1041
+ (none)
1042
+ </MenuContentItem>
1043
+
1044
+ {Object.values(COLUMN_SORT_TYPE).map((op) => (
1032
1045
  <MenuContentItem
1033
- key="none"
1046
+ key={op}
1034
1047
  className="query-builder__olap__column__sortby__operator__dropdown__option"
1035
- onClick={changeSortBy(undefined)}
1048
+ onClick={changeSortBy(op)}
1036
1049
  >
1037
- (none)
1050
+ {op.toLowerCase()}
1038
1051
  </MenuContentItem>
1039
-
1040
- {Object.values(COLUMN_SORT_TYPE).map((op) => (
1041
- <MenuContentItem
1042
- key={op}
1043
- className="query-builder__olap__column__sortby__operator__dropdown__option"
1044
- onClick={changeSortBy(op)}
1045
- >
1046
- {op.toLowerCase()}
1047
- </MenuContentItem>
1048
- ))}
1049
- </MenuContent>
1050
- }
1051
- menuProps={{
1052
- anchorOrigin: { vertical: 'bottom', horizontal: 'left' },
1053
- transformOrigin: { vertical: 'top', horizontal: 'left' },
1054
- elevation: 7,
1055
- }}
1056
- >
1057
- <button
1058
- className={clsx(
1059
- 'query-builder__olap__column__sortby__operator__badge',
1060
- {
1061
- 'query-builder__olap__column__sortby__operator__badge--activated':
1062
- Boolean(sortByState),
1063
- },
1064
- )}
1065
- tabIndex={-1}
1066
- title="Choose Window Function SortBy Operator..."
1067
- >
1068
- <SortIcon />
1069
- </button>
1070
- <button
1071
- className="query-builder__olap__column__sortby__operator__dropdown__trigger"
1072
- tabIndex={-1}
1073
- title="Choose Window Function SortBy Operator..."
1074
- >
1075
- <CaretDownIcon />
1076
- </button>
1077
- </DropdownMenu>
1078
- </div>
1079
- </div>
1080
- <div className="query-builder__olap__column__name">
1081
- <InputWithInlineValidation
1082
- className="query-builder__olap__column__name__input input-group__input"
1083
- spellCheck={false}
1084
- value={windowColumnState.columnName}
1085
- onChange={changeColumnName}
1086
- validationErrorMessage={
1087
- isDuplicatedColumnName ? 'Duplicated column' : undefined
1088
- }
1089
- />
1090
- </div>
1091
- <div className="query-builder__olap__column__actions">
1092
- <button
1093
- className="query-builder__olap__column__action"
1094
- tabIndex={-1}
1095
- onClick={editoColumn}
1096
- >
1097
- <EditIcon />
1098
- </button>
1099
- <button
1100
- className="query-builder__olap__column__action"
1101
- tabIndex={-1}
1102
- onClick={removeColumn}
1103
- disabled={isRemovalDisabled}
1104
- title={
1105
- isRemovalDisabled
1106
- ? "This column is used in the post filter and can't be removed"
1107
- : 'Remove'
1052
+ ))}
1053
+ </MenuContent>
1108
1054
  }
1055
+ menuProps={{
1056
+ anchorOrigin: { vertical: 'bottom', horizontal: 'left' },
1057
+ transformOrigin: { vertical: 'top', horizontal: 'left' },
1058
+ elevation: 7,
1059
+ }}
1109
1060
  >
1110
- <TimesIcon />
1111
- </button>
1061
+ <button
1062
+ className={clsx(
1063
+ 'query-builder__olap__column__sortby__operator__badge',
1064
+ {
1065
+ 'query-builder__olap__column__sortby__operator__badge--activated':
1066
+ Boolean(sortByState),
1067
+ },
1068
+ )}
1069
+ tabIndex={-1}
1070
+ title="Choose Window Function SortBy Operator..."
1071
+ >
1072
+ <SortIcon />
1073
+ </button>
1074
+ <button
1075
+ className="query-builder__olap__column__sortby__operator__dropdown__trigger"
1076
+ tabIndex={-1}
1077
+ title="Choose Window Function SortBy Operator..."
1078
+ >
1079
+ <CaretDownIcon />
1080
+ </button>
1081
+ </DropdownMenu>
1112
1082
  </div>
1113
- </ContextMenu>
1114
- </PanelEntryDropZonePlaceholder>
1115
- </div>
1083
+ </div>
1084
+ <div className="query-builder__olap__column__name">
1085
+ <InputWithInlineValidation
1086
+ className="query-builder__olap__column__name__input input-group__input"
1087
+ spellCheck={false}
1088
+ value={windowColumnState.columnName}
1089
+ onChange={changeColumnName}
1090
+ validationErrorMessage={
1091
+ isDuplicatedColumnName ? 'Duplicated column' : undefined
1092
+ }
1093
+ />
1094
+ </div>
1095
+ <div className="query-builder__olap__column__actions">
1096
+ <button
1097
+ className="query-builder__olap__column__action"
1098
+ tabIndex={-1}
1099
+ onClick={editoColumn}
1100
+ >
1101
+ <EditIcon />
1102
+ </button>
1103
+ <button
1104
+ className="query-builder__olap__column__action"
1105
+ tabIndex={-1}
1106
+ onClick={removeColumn}
1107
+ disabled={isRemovalDisabled}
1108
+ title={
1109
+ isRemovalDisabled
1110
+ ? "This column is used in the post filter and can't be removed"
1111
+ : 'Remove'
1112
+ }
1113
+ >
1114
+ <TimesIcon />
1115
+ </button>
1116
+ </div>
1117
+ </ContextMenu>
1118
+ </PanelDnDEntry>
1116
1119
  );
1117
1120
  },
1118
1121
  );
@@ -20,26 +20,26 @@ import {
20
20
  assertErrorThrown,
21
21
  LogEvent,
22
22
  guaranteeNonNullable,
23
- ContentType,
24
- guaranteeType,
23
+ type ContentType,
25
24
  downloadFileUsingDataURI,
26
- UnsupportedOperationError,
27
25
  ActionState,
28
26
  StopWatch,
27
+ getContentTypeFileExtension,
29
28
  } from '@finos/legend-shared';
30
29
  import type { QueryBuilderState } from './QueryBuilderState.js';
31
30
  import {
32
31
  type RawExecutionPlan,
33
32
  type ExecutionResult,
34
33
  type RawLambda,
34
+ type EXECUTION_SERIALIZATION_FORMAT,
35
35
  GRAPH_MANAGER_EVENT,
36
- EXECUTION_SERIALIZATION_FORMAT,
37
36
  RawExecutionResult,
38
37
  buildRawLambdaFromLambdaFunction,
39
38
  reportGraphAnalytics,
39
+ extractExecutionResultValues,
40
40
  } from '@finos/legend-graph';
41
41
  import { buildLambdaFunction } from './QueryBuilderValueSpecificationBuilder.js';
42
- import { ExecutionPlanState } from '@finos/legend-application';
42
+ import { ExecutionPlanState, TAB_SIZE } from '@finos/legend-application';
43
43
  import {
44
44
  buildExecutionParameterValues,
45
45
  getExecutionQueryFromRawLambda,
@@ -50,6 +50,11 @@ import { QUERY_BUILDER_EVENT } from '../application/QueryBuilderEvent.js';
50
50
 
51
51
  const DEFAULT_LIMIT = 1000;
52
52
 
53
+ export interface ExportDataInfo {
54
+ contentType: ContentType;
55
+ serializationFormat?: EXECUTION_SERIALIZATION_FORMAT | undefined;
56
+ }
57
+
53
58
  export class QueryBuilderResultState {
54
59
  readonly queryBuilderState: QueryBuilderState;
55
60
  readonly exportDataState = ActionState.create();
@@ -148,25 +153,21 @@ export class QueryBuilderResultState {
148
153
  return query;
149
154
  }
150
155
 
151
- *exportData(
152
- serializationFormat: EXECUTION_SERIALIZATION_FORMAT,
153
- ): GeneratorFn<void> {
156
+ *exportData(format: string): GeneratorFn<void> {
154
157
  try {
158
+ const exportData =
159
+ this.queryBuilderState.fetchStructureState.implementation.getExportDataInfo(
160
+ format,
161
+ );
162
+ const contentType = exportData.contentType;
163
+ const serializationFormat = exportData.serializationFormat;
155
164
  this.exportDataState.inProgress();
156
- const mapping = guaranteeNonNullable(
157
- this.queryBuilderState.mapping,
158
- 'Mapping is required to execute query',
159
- );
160
- const runtime = guaranteeNonNullable(
161
- this.queryBuilderState.runtimeValue,
162
- `Runtime is required to execute query`,
163
- );
164
165
  const query = this.buildExecutionRawLambda();
165
166
  const result =
166
167
  (yield this.queryBuilderState.graphManagerState.graphManager.runQuery(
167
168
  query,
168
- mapping,
169
- runtime,
169
+ this.queryBuilderState.mapping,
170
+ this.queryBuilderState.runtimeValue,
170
171
  this.queryBuilderState.graphManagerState.graph,
171
172
  {
172
173
  serializationFormat,
@@ -176,23 +177,17 @@ export class QueryBuilderResultState {
176
177
  ),
177
178
  },
178
179
  )) as ExecutionResult;
179
- let contentType: ContentType;
180
- let fileName = 'result';
181
180
  let content: string;
182
- switch (serializationFormat) {
183
- case EXECUTION_SERIALIZATION_FORMAT.CSV:
184
- {
185
- const rawResult = guaranteeType(result, RawExecutionResult);
186
- contentType = ContentType.TEXT_CSV;
187
- fileName = `${fileName}.csv`;
188
- content = rawResult.value;
189
- }
190
- break;
191
- default:
192
- throw new UnsupportedOperationError(
193
- `Can't download file for serialization type: '${serializationFormat}'`,
194
- );
181
+ if (result instanceof RawExecutionResult) {
182
+ content = result.value;
183
+ } else {
184
+ content = JSON.stringify(
185
+ extractExecutionResultValues(result),
186
+ null,
187
+ TAB_SIZE,
188
+ );
195
189
  }
190
+ const fileName = `result.${getContentTypeFileExtension(contentType)}`;
196
191
  downloadFileUsingDataURI(fileName, content, contentType);
197
192
  this.exportDataState.pass();
198
193
  } catch (error) {