@finos/legend-query-builder 4.0.10 → 4.0.12

Sign up to get free protection for your applications and to get access to all the features.
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finos/legend-query-builder",
3
- "version": "4.0.10",
3
+ "version": "4.0.12",
4
4
  "description": "Legend query builder core",
5
5
  "keywords": [
6
6
  "legend",
@@ -50,10 +50,10 @@
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.9",
54
- "@types/react-dom": "18.2.4",
53
+ "@types/react": "18.2.12",
54
+ "@types/react-dom": "18.2.5",
55
55
  "chart.js": "4.3.0",
56
- "mathjs": "11.8.0",
56
+ "mathjs": "11.8.1",
57
57
  "mobx": "6.9.0",
58
58
  "mobx-react-lite": "3.4.3",
59
59
  "monaco-editor": "0.39.0",
@@ -62,7 +62,7 @@
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:*",
@@ -72,7 +72,7 @@
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.10",
3
+ "version": "4.0.12",
4
4
  "description": "Legend query builder core",
5
5
  "keywords": [
6
6
  "legend",
@@ -42,18 +42,18 @@
42
42
  "test:watch": "jest --watch"
43
43
  },
44
44
  "dependencies": {
45
- "@finos/legend-application": "15.0.21",
46
- "@finos/legend-art": "7.0.21",
47
- "@finos/legend-graph": "30.0.6",
48
- "@finos/legend-lego": "1.0.19",
49
- "@finos/legend-server-depot": "6.0.13",
50
- "@finos/legend-shared": "10.0.12",
51
- "@finos/legend-storage": "3.0.62",
45
+ "@finos/legend-application": "15.0.23",
46
+ "@finos/legend-art": "7.0.23",
47
+ "@finos/legend-graph": "30.0.8",
48
+ "@finos/legend-lego": "1.0.21",
49
+ "@finos/legend-server-depot": "6.0.15",
50
+ "@finos/legend-shared": "10.0.14",
51
+ "@finos/legend-storage": "3.0.64",
52
52
  "@testing-library/react": "14.0.0",
53
- "@types/react": "18.2.9",
54
- "@types/react-dom": "18.2.4",
53
+ "@types/react": "18.2.12",
54
+ "@types/react-dom": "18.2.5",
55
55
  "chart.js": "4.3.0",
56
- "mathjs": "11.8.0",
56
+ "mathjs": "11.8.1",
57
57
  "mobx": "6.9.0",
58
58
  "mobx-react-lite": "3.4.3",
59
59
  "monaco-editor": "0.39.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.66",
68
+ "@finos/legend-dev-utils": "2.0.68",
69
69
  "@jest/globals": "29.5.0",
70
70
  "cross-env": "7.0.3",
71
71
  "eslint": "8.42.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>
@@ -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(
@@ -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) {