@finos/legend-query-builder 4.0.11 → 4.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  2. package/lib/components/QueryBuilderResultPanel.js +14 -14
  3. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  4. package/lib/components/data-access/DataAccessOverview.d.ts.map +1 -1
  5. package/lib/components/data-access/DataAccessOverview.js +7 -3
  6. package/lib/components/data-access/DataAccessOverview.js.map +1 -1
  7. package/lib/components/execution-plan/SQLExecutionNodeViewer.d.ts.map +1 -1
  8. package/lib/components/execution-plan/SQLExecutionNodeViewer.js +2 -1
  9. package/lib/components/execution-plan/SQLExecutionNodeViewer.js.map +1 -1
  10. package/lib/components/explorer/QueryBuilderMilestoningEditor.d.ts.map +1 -1
  11. package/lib/components/explorer/QueryBuilderMilestoningEditor.js +1 -1
  12. package/lib/components/explorer/QueryBuilderMilestoningEditor.js.map +1 -1
  13. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  14. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +1 -1
  15. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  16. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +1 -1
  17. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
  18. package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -1
  19. package/lib/components/shared/BasicValueSpecificationEditor.js +5 -4
  20. package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -1
  21. package/lib/index.css +17 -1
  22. package/lib/index.css.map +1 -1
  23. package/lib/package.json +6 -6
  24. package/lib/stores/QueryBuilderResultState.js +1 -1
  25. package/package.json +14 -14
  26. package/src/components/QueryBuilderResultPanel.tsx +69 -66
  27. package/src/components/data-access/DataAccessOverview.tsx +16 -2
  28. package/src/components/execution-plan/SQLExecutionNodeViewer.tsx +10 -3
  29. package/src/components/explorer/QueryBuilderMilestoningEditor.tsx +5 -3
  30. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +1 -2
  31. package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +2 -2
  32. package/src/components/shared/BasicValueSpecificationEditor.tsx +11 -7
  33. package/src/stores/QueryBuilderResultState.ts +1 -1
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finos/legend-query-builder",
3
- "version": "4.0.11",
3
+ "version": "4.0.13",
4
4
  "description": "Legend query builder core",
5
5
  "keywords": [
6
6
  "legend",
@@ -50,8 +50,8 @@
50
50
  "@finos/legend-shared": "workspace:*",
51
51
  "@finos/legend-storage": "workspace:*",
52
52
  "@testing-library/react": "14.0.0",
53
- "@types/react": "18.2.12",
54
- "@types/react-dom": "18.2.5",
53
+ "@types/react": "18.2.13",
54
+ "@types/react-dom": "18.2.6",
55
55
  "chart.js": "4.3.0",
56
56
  "mathjs": "11.8.1",
57
57
  "mobx": "6.9.0",
@@ -62,17 +62,17 @@
62
62
  "react-dnd": "16.0.1",
63
63
  "react-dom": "18.2.0",
64
64
  "serializr": "3.0.2",
65
- "sql-formatter": "12.2.2"
65
+ "sql-formatter": "12.2.3"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@finos/legend-dev-utils": "workspace:*",
69
69
  "@jest/globals": "29.5.0",
70
70
  "cross-env": "7.0.3",
71
- "eslint": "8.42.0",
71
+ "eslint": "8.43.0",
72
72
  "jest": "29.5.0",
73
73
  "npm-run-all": "4.1.5",
74
74
  "rimraf": "5.0.1",
75
- "sass": "1.63.3",
75
+ "sass": "1.63.4",
76
76
  "typescript": "5.1.3"
77
77
  },
78
78
  "peerDependencies": {
@@ -200,7 +200,7 @@ export class QueryBuilderResultState {
200
200
  }
201
201
  }
202
202
  catch (error) {
203
- // When user cancels the query by calling the cancelQuery api, it will throw an exeuction failure error.
203
+ // When user cancels the query by calling the cancelQuery api, it will throw an execution failure error.
204
204
  // For now, we don't want to notify users about this failure. Therefore we check to ensure the promise is still the same one.
205
205
  // When cancelled the query, we set the queryRunPromise as undefined.
206
206
  if (this.queryRunPromise === promise) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finos/legend-query-builder",
3
- "version": "4.0.11",
3
+ "version": "4.0.13",
4
4
  "description": "Legend query builder core",
5
5
  "keywords": [
6
6
  "legend",
@@ -42,16 +42,16 @@
42
42
  "test:watch": "jest --watch"
43
43
  },
44
44
  "dependencies": {
45
- "@finos/legend-application": "15.0.22",
46
- "@finos/legend-art": "7.0.22",
47
- "@finos/legend-graph": "30.0.7",
48
- "@finos/legend-lego": "1.0.20",
49
- "@finos/legend-server-depot": "6.0.14",
50
- "@finos/legend-shared": "10.0.13",
51
- "@finos/legend-storage": "3.0.63",
45
+ "@finos/legend-application": "15.0.24",
46
+ "@finos/legend-art": "7.0.24",
47
+ "@finos/legend-graph": "30.0.9",
48
+ "@finos/legend-lego": "1.1.0",
49
+ "@finos/legend-server-depot": "6.0.16",
50
+ "@finos/legend-shared": "10.0.15",
51
+ "@finos/legend-storage": "3.0.65",
52
52
  "@testing-library/react": "14.0.0",
53
- "@types/react": "18.2.12",
54
- "@types/react-dom": "18.2.5",
53
+ "@types/react": "18.2.13",
54
+ "@types/react-dom": "18.2.6",
55
55
  "chart.js": "4.3.0",
56
56
  "mathjs": "11.8.1",
57
57
  "mobx": "6.9.0",
@@ -62,17 +62,17 @@
62
62
  "react-dnd": "16.0.1",
63
63
  "react-dom": "18.2.0",
64
64
  "serializr": "3.0.2",
65
- "sql-formatter": "12.2.2"
65
+ "sql-formatter": "12.2.3"
66
66
  },
67
67
  "devDependencies": {
68
- "@finos/legend-dev-utils": "2.0.67",
68
+ "@finos/legend-dev-utils": "2.0.69",
69
69
  "@jest/globals": "29.5.0",
70
70
  "cross-env": "7.0.3",
71
- "eslint": "8.42.0",
71
+ "eslint": "8.43.0",
72
72
  "jest": "29.5.0",
73
73
  "npm-run-all": "4.1.5",
74
74
  "rimraf": "5.0.1",
75
- "sass": "1.63.3",
75
+ "sass": "1.63.4",
76
76
  "typescript": "5.1.3"
77
77
  },
78
78
  "peerDependencies": {
@@ -126,11 +126,11 @@ const QueryBuilderGridResultContextMenu = observer(
126
126
  forwardRef<
127
127
  HTMLDivElement,
128
128
  {
129
- event: QueryBuilderTDSResultCellData | null;
129
+ data: QueryBuilderTDSResultCellData | null;
130
130
  tdsState: QueryBuilderTDSState;
131
131
  }
132
132
  >(function QueryBuilderResultContextMenu(props, ref) {
133
- const { event, tdsState } = props;
133
+ const { data, tdsState } = props;
134
134
  const applicationStore = useApplicationStore();
135
135
  const postFilterEqualOperator = new QueryBuilderPostFilterOperator_Equal();
136
136
  const postFilterInOperator = new QueryBuilderPostFilterOperator_In();
@@ -145,10 +145,10 @@ const QueryBuilderGridResultContextMenu = observer(
145
145
  const postFilterState = tdsState.postFilterState;
146
146
 
147
147
  const projectionColumnState = tdsState.projectionColumns
148
- .filter((c) => c.columnName === event?.columnName)
148
+ .filter((c) => c.columnName === data?.columnName)
149
149
  .concat(
150
150
  tdsState.aggregationState.columns
151
- .filter((c) => c.columnName === event?.columnName)
151
+ .filter((c) => c.columnName === data?.columnName)
152
152
  .map((ag) => ag.projectionColumnState),
153
153
  )[0];
154
154
  const getExistingPostFilterNode = (
@@ -319,7 +319,7 @@ const QueryBuilderGridResultContextMenu = observer(
319
319
  : (v as InstanceValue).values,
320
320
  )
321
321
  .flat()
322
- .includes(cellData.value ?? event?.value);
322
+ .includes(cellData.value ?? data?.value);
323
323
 
324
324
  if (!doesValueAlreadyExist) {
325
325
  const newValueSpecification = (
@@ -399,7 +399,7 @@ const QueryBuilderGridResultContextMenu = observer(
399
399
 
400
400
  const handleCopyCellValue = applicationStore.guardUnhandledError(() =>
401
401
  applicationStore.clipboardService.copyTextToClipboard(
402
- event?.value?.toString() ?? '',
402
+ data?.value?.toString() ?? '',
403
403
  ),
404
404
  );
405
405
 
@@ -597,7 +597,7 @@ const QueryResultCellRenderer = observer(
597
597
  // NOTE: we only support this functionality for grid result with a projection fetch-structure
598
598
  fetchStructureImplementation instanceof QueryBuilderTDSState ? (
599
599
  <QueryBuilderGridResultContextMenu
600
- event={resultState.mousedOverCell}
600
+ data={resultState.mousedOverCell}
601
601
  tdsState={fetchStructureImplementation}
602
602
  />
603
603
  ) : null
@@ -960,70 +960,73 @@ export const QueryBuilderResultPanel = observer(
960
960
  />
961
961
  </div>
962
962
  )}
963
- {resultState.isRunningQuery ? (
964
- <button
965
- className="query-builder__result__stop-btn"
966
- onClick={cancelQuery}
967
- tabIndex={-1}
968
- disabled={!isQueryValid}
969
- >
970
- <div className="btn--dark btn--caution query-builder__result__stop-btn__label">
971
- <PauseCircleIcon className="query-builder__result__stop-btn__label__icon" />
972
- <div className="query-builder__result__stop-btn__label__title">
973
- Stop
974
- </div>
975
- </div>
976
- </button>
977
- ) : (
978
- <div className="query-builder__result__execute-btn">
963
+
964
+ <div className="query-builder__result__execute-btn btn__dropdown-combo btn__dropdown-combo--primary">
965
+ {resultState.isRunningQuery ? (
979
966
  <button
980
- className="query-builder__result__execute-btn__label"
981
- onClick={runQuery}
967
+ className="btn__dropdown-combo__canceler"
968
+ onClick={cancelQuery}
982
969
  tabIndex={-1}
983
- title={
984
- allValidationIssues.length
985
- ? `Query is not valid:\n${allValidationIssues
986
- .map((issue) => `\u2022 ${issue}`)
987
- .join('\n')}`
988
- : undefined
989
- }
990
- disabled={isRunQueryDisabled}
970
+ disabled={!isQueryValid}
991
971
  >
992
- <PlayIcon className="query-builder__result__execute-btn__label__icon" />
993
- <div className="query-builder__result__execute-btn__label__title">
994
- Run Query
972
+ <div className="btn--dark btn--caution btn__dropdown-combo__canceler__label">
973
+ <PauseCircleIcon className="btn__dropdown-combo__canceler__label__icon" />
974
+ <div className="btn__dropdown-combo__canceler__label__title">
975
+ Stop
976
+ </div>
995
977
  </div>
996
978
  </button>
997
- <DropdownMenu
998
- className="query-builder__result__execute-btn__dropdown-btn"
999
- disabled={isRunQueryDisabled}
1000
- content={
1001
- <MenuContent>
1002
- <MenuContentItem
1003
- className="query-builder__result__execute-btn__option"
1004
- onClick={generatePlan}
1005
- disabled={isRunQueryDisabled}
1006
- >
1007
- Generate Plan
1008
- </MenuContentItem>
1009
- <MenuContentItem
1010
- className="query-builder__result__execute-btn__option"
1011
- onClick={debugPlanGeneration}
1012
- disabled={isRunQueryDisabled}
1013
- >
1014
- Debug
1015
- </MenuContentItem>
1016
- </MenuContent>
1017
- }
1018
- menuProps={{
1019
- anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
1020
- transformOrigin: { vertical: 'top', horizontal: 'right' },
1021
- }}
1022
- >
1023
- <CaretDownIcon />
1024
- </DropdownMenu>
1025
- </div>
1026
- )}
979
+ ) : (
980
+ <>
981
+ <button
982
+ className="btn__dropdown-combo__label"
983
+ onClick={runQuery}
984
+ tabIndex={-1}
985
+ title={
986
+ allValidationIssues.length
987
+ ? `Query is not valid:\n${allValidationIssues
988
+ .map((issue) => `\u2022 ${issue}`)
989
+ .join('\n')}`
990
+ : undefined
991
+ }
992
+ disabled={isRunQueryDisabled}
993
+ >
994
+ <PlayIcon className="btn__dropdown-combo__label__icon" />
995
+ <div className="btn__dropdown-combo__label__title">
996
+ Run Query
997
+ </div>
998
+ </button>
999
+ <DropdownMenu
1000
+ className="btn__dropdown-combo__dropdown-btn"
1001
+ disabled={isRunQueryDisabled}
1002
+ content={
1003
+ <MenuContent>
1004
+ <MenuContentItem
1005
+ className="btn__dropdown-combo__option"
1006
+ onClick={generatePlan}
1007
+ disabled={isRunQueryDisabled}
1008
+ >
1009
+ Generate Plan
1010
+ </MenuContentItem>
1011
+ <MenuContentItem
1012
+ className="btn__dropdown-combo__option"
1013
+ onClick={debugPlanGeneration}
1014
+ disabled={isRunQueryDisabled}
1015
+ >
1016
+ Debug
1017
+ </MenuContentItem>
1018
+ </MenuContent>
1019
+ }
1020
+ menuProps={{
1021
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
1022
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
1023
+ }}
1024
+ >
1025
+ <CaretDownIcon />
1026
+ </DropdownMenu>
1027
+ </>
1028
+ )}
1029
+ </div>
1027
1030
  <DropdownMenu
1028
1031
  className="query-builder__result__export__dropdown"
1029
1032
  title="Export"
@@ -72,6 +72,17 @@ const DataAccessOverviewChart = observer(
72
72
  <RefreshIcon />
73
73
  </button>
74
74
  </div>
75
+ {Boolean(
76
+ dataAccessState.datasets.find(
77
+ (dataset) =>
78
+ dataset.entitlementReport instanceof
79
+ DatasetEntitlementUnsupportedReport,
80
+ ),
81
+ ) && (
82
+ <div className="data-access-overview__chart__warning">
83
+ Use case is not fully supported!
84
+ </div>
85
+ )}
75
86
  <div className="data-access-overview__chart__container">
76
87
  <Doughnut
77
88
  data={{
@@ -109,7 +120,7 @@ const DataAccessOverviewChart = observer(
109
120
  />
110
121
  <div className="data-access-overview__chart__stats">
111
122
  <div className="data-access-overview__chart__stats__percentage">
112
- {accessGrantedPercentage}%
123
+ {total === 0 ? 0 : accessGrantedPercentage}%
113
124
  </div>
114
125
  <div className="data-access-overview__chart__stats__tally">
115
126
  {total === 0 ? 0 : accessGrantedCount}/{total}
@@ -285,7 +296,10 @@ export const DataAccessOverview = observer(
285
296
  const applicationStore = useApplicationStore();
286
297
 
287
298
  useEffect(() => {
288
- dataAccessState.intialize().catch(applicationStore.alertUnhandledError);
299
+ // NOTE: @YannanGao-gs - force refresh for now, let's investigate why the data is empty
300
+ // when we fetched it from cache
301
+ dataAccessState.refresh().catch(applicationStore.alertUnhandledError);
302
+ // dataAccessState.intialize().catch(applicationStore.alertUnhandledError);
289
303
  }, [applicationStore, dataAccessState]);
290
304
 
291
305
  return (
@@ -28,6 +28,10 @@ import {
28
28
  PanelContent,
29
29
  } from '@finos/legend-art';
30
30
  import { tryToFormatSql } from '../QueryBuilderResultPanel.js';
31
+ import {
32
+ CodeEditor,
33
+ CODE_EDITOR_LANGUAGE,
34
+ } from '@finos/legend-lego/code-editor';
31
35
 
32
36
  /**
33
37
  * TODO: Create a new `AbstractPlugin` for this, called `ExecutionPlanViewerPlugin`
@@ -81,9 +85,12 @@ export const SQLExecutionNodeViewer: React.FC<{
81
85
  </div>
82
86
  </PanelListItem>
83
87
  </div>
84
- <PanelListItem className="query-builder__sql__container__item">
85
- <pre>{tryToFormatSql(query)} </pre>
86
- </PanelListItem>
88
+ <div className="query-builder__sql__container__code-editor">
89
+ <CodeEditor
90
+ inputValue={tryToFormatSql(query)}
91
+ language={CODE_EDITOR_LANGUAGE.SQL}
92
+ />
93
+ </div>
87
94
  <PanelDivider />
88
95
  </div>
89
96
  </div>
@@ -271,9 +271,11 @@ export const MilestoningParametersEditor = observer(
271
271
  <ModalHeader title="Milestoning Parameters" />
272
272
  <ModalBody className="query-builder__variables__modal__body">
273
273
  <TemporalMilestoningEditor queryBuilderState={queryBuilderState} />
274
- <div className="panel__content__form__section__header__label">
275
- List of compatible milestoning parameters
276
- </div>
274
+ <PanelFormSection>
275
+ <div className="panel__content__form__section__header__label">
276
+ List of compatible milestoning parameters
277
+ </div>
278
+ </PanelFormSection>
277
279
  <div className="panel__content__form__section__list__items">
278
280
  <VariableSelector
279
281
  queryBuilderState={queryBuilderState}
@@ -1075,8 +1075,7 @@ const QueryBuilderPostFilterPanelContent = observer(
1075
1075
  <QueryBuilderPostFilterTree tdsState={tdsState} />
1076
1076
  </>
1077
1077
  )}
1078
-
1079
- {showDroppableSuggestion && (
1078
+ {showDroppableSuggestion && !postFilterState.isEmpty && (
1080
1079
  <div
1081
1080
  ref={dropTargetConnector}
1082
1081
  className={clsx(
@@ -1186,8 +1186,8 @@ export const QueryBuilderTDSWindowPanel = observer(
1186
1186
  >
1187
1187
  <PanelHeader>
1188
1188
  <div className="panel__header__title">
1189
- <div className="panel__header__title__label">Window Function</div>
1190
- {tdsWindowState.windowValidationIssues.length && (
1189
+ <div className="panel__header__title__label">window function</div>
1190
+ {tdsWindowState.windowValidationIssues.length > 0 && (
1191
1191
  <QueryBuilderPanelIssueCountBadge
1192
1192
  issues={tdsWindowState.windowValidationIssues}
1193
1193
  />
@@ -665,7 +665,8 @@ const CollectionValueInstanceValueEditor = observer(
665
665
  setValueSpecification,
666
666
  obseverContext,
667
667
  } = props;
668
- const inputRef = useRef<HTMLInputElement>(null);
668
+ const inputRef = useRef<HTMLTextAreaElement>(null);
669
+
669
670
  const [text, setText] = useState(stringifyValue(valueSpecification.values));
670
671
  const [editable, setEditable] = useState(false);
671
672
  const [showAdvancedEditorPopover, setShowAdvancedEditorPopover] =
@@ -697,9 +698,7 @@ const CollectionValueInstanceValueEditor = observer(
697
698
  setText(stringifyValue(valueSpecification.values));
698
699
  setValueSpecification(valueSpecification);
699
700
  };
700
- const changeValue: React.ChangeEventHandler<HTMLInputElement> = (event) => {
701
- setText(event.target.value);
702
- };
701
+
703
702
  const changeValueTextArea: React.ChangeEventHandler<HTMLTextAreaElement> = (
704
703
  event,
705
704
  ) => {
@@ -742,15 +741,20 @@ const CollectionValueInstanceValueEditor = observer(
742
741
  </BasePopover>
743
742
  )}
744
743
  <div className={clsx('value-spec-editor', className)}>
745
- <input
744
+ <textarea
746
745
  ref={inputRef}
747
746
  className={clsx(
748
- 'panel__content__form__section__input value-spec-editor__input',
747
+ 'panel__content__form__section__input value-spec-editor__input value-spec-editor__textarea ',
749
748
  )}
750
749
  spellCheck={false}
751
750
  value={text}
752
751
  placeholder={text === '' ? '(empty)' : undefined}
753
- onChange={changeValue}
752
+ onChange={changeValueTextArea}
753
+ onKeyDown={(event): void => {
754
+ if (event.key === 'Enter' && !event.shiftKey) {
755
+ saveEdit();
756
+ }
757
+ }}
754
758
  />
755
759
  <button
756
760
  className="value-spec-editor__list-editor__expand-button btn--dark"
@@ -345,7 +345,7 @@ export class QueryBuilderResultState {
345
345
  );
346
346
  }
347
347
  } catch (error) {
348
- // When user cancels the query by calling the cancelQuery api, it will throw an exeuction failure error.
348
+ // When user cancels the query by calling the cancelQuery api, it will throw an execution failure error.
349
349
  // For now, we don't want to notify users about this failure. Therefore we check to ensure the promise is still the same one.
350
350
  // When cancelled the query, we set the queryRunPromise as undefined.
351
351
  if (this.queryRunPromise === promise) {