@finos/legend-query-builder 3.2.0 → 3.2.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.
- package/lib/__lib__/QueryBuilderColorTheme.d.ts +23 -0
- package/lib/__lib__/QueryBuilderColorTheme.d.ts.map +1 -0
- package/lib/__lib__/QueryBuilderColorTheme.js +24 -0
- package/lib/__lib__/QueryBuilderColorTheme.js.map +1 -0
- package/lib/components/QueryBuilder.d.ts.map +1 -1
- package/lib/components/QueryBuilder.js +17 -15
- package/lib/components/QueryBuilder.js.map +1 -1
- package/lib/components/QueryBuilder_LegendApplicationPlugin.d.ts.map +1 -1
- package/lib/components/QueryBuilder_LegendApplicationPlugin.js +3 -0
- package/lib/components/QueryBuilder_LegendApplicationPlugin.js.map +1 -1
- package/lib/components/QueryLoader.d.ts.map +1 -1
- package/lib/components/QueryLoader.js +6 -2
- package/lib/components/QueryLoader.js.map +1 -1
- package/lib/components/data-access/DataAccessOverview.d.ts +23 -0
- package/lib/components/data-access/DataAccessOverview.d.ts.map +1 -0
- package/lib/components/data-access/DataAccessOverview.js +146 -0
- package/lib/components/data-access/DataAccessOverview.js.map +1 -0
- package/lib/components/execution-plan/ExecutionPlanViewer.d.ts.map +1 -1
- package/lib/components/execution-plan/ExecutionPlanViewer.js +3 -3
- package/lib/components/execution-plan/ExecutionPlanViewer.js.map +1 -1
- package/lib/components/execution-plan/SQLExecutionNodeViewer.js +1 -1
- package/lib/components/execution-plan/SQLExecutionNodeViewer.js.map +1 -1
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +1 -1
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts +0 -18
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +34 -36
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
- package/lib/components/shared/LambdaEditor.d.ts.map +1 -1
- package/lib/components/shared/LambdaEditor.js +7 -19
- package/lib/components/shared/LambdaEditor.js.map +1 -1
- package/lib/index.css +1 -17
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/package.json +4 -2
- package/lib/stores/QueryBuilderState.d.ts +3 -3
- package/lib/stores/QueryBuilderState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderState.js +34 -18
- package/lib/stores/QueryBuilderState.js.map +1 -1
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts +9 -0
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts.map +1 -1
- package/lib/stores/data-access/DataAccessState.d.ts +56 -0
- package/lib/stores/data-access/DataAccessState.d.ts.map +1 -0
- package/lib/stores/data-access/DataAccessState.js +212 -0
- package/lib/stores/data-access/DataAccessState.js.map +1 -0
- package/lib/stores/entitlements/QueryBuilderCheckEntitlementsState.d.ts +4 -2
- package/lib/stores/entitlements/QueryBuilderCheckEntitlementsState.d.ts.map +1 -1
- package/lib/stores/entitlements/QueryBuilderCheckEntitlementsState.js +20 -6
- package/lib/stores/entitlements/QueryBuilderCheckEntitlementsState.js.map +1 -1
- package/package.json +12 -10
- package/src/__lib__/QueryBuilderColorTheme.ts +23 -0
- package/src/components/QueryBuilder.tsx +63 -47
- package/src/components/QueryBuilder_LegendApplicationPlugin.ts +4 -0
- package/src/components/QueryLoader.tsx +4 -1
- package/src/components/data-access/DataAccessOverview.tsx +308 -0
- package/src/components/execution-plan/ExecutionPlanViewer.tsx +1 -3
- package/src/components/execution-plan/SQLExecutionNodeViewer.tsx +1 -1
- package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +1 -1
- package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +99 -102
- package/src/components/shared/LambdaEditor.tsx +4 -21
- package/src/index.ts +4 -0
- package/src/stores/QueryBuilderState.ts +65 -19
- package/src/stores/QueryBuilder_LegendApplicationPlugin_Extension.ts +10 -0
- package/src/stores/data-access/DataAccessState.ts +322 -0
- package/src/stores/entitlements/QueryBuilderCheckEntitlementsState.ts +53 -6
- package/tsconfig.json +3 -0
@@ -0,0 +1,308 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) 2020-present, Goldman Sachs
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
import { useEffect } from 'react';
|
18
|
+
import { observer } from 'mobx-react-lite';
|
19
|
+
import { useApplicationStore } from '@finos/legend-application';
|
20
|
+
import type {
|
21
|
+
DataAccessState,
|
22
|
+
DatasetAccessInfo,
|
23
|
+
} from '../../stores/data-access/DataAccessState.js';
|
24
|
+
import {
|
25
|
+
CheckCircleIcon,
|
26
|
+
ExclamationCircleIcon,
|
27
|
+
MinusCircleIcon,
|
28
|
+
PanelLoadingIndicator,
|
29
|
+
RefreshIcon,
|
30
|
+
TimesCircleIcon,
|
31
|
+
clsx,
|
32
|
+
} from '@finos/legend-art';
|
33
|
+
import {
|
34
|
+
DataGrid,
|
35
|
+
type DataGridCellRendererParams,
|
36
|
+
} from '@finos/legend-lego/data-grid';
|
37
|
+
import {
|
38
|
+
DatasetEntitlementAccessApprovedReport,
|
39
|
+
DatasetEntitlementAccessGrantedReport,
|
40
|
+
DatasetEntitlementAccessNotGrantedReport,
|
41
|
+
DatasetEntitlementAccessRequestedReport,
|
42
|
+
DatasetEntitlementUnsupportedReport,
|
43
|
+
} from '@finos/legend-graph';
|
44
|
+
import { Doughnut } from 'react-chartjs-2';
|
45
|
+
import { getNullableFirstEntry } from '@finos/legend-shared';
|
46
|
+
import type { QueryBuilder_LegendApplicationPlugin_Extension } from '../../stores/QueryBuilder_LegendApplicationPlugin_Extension.js';
|
47
|
+
|
48
|
+
const DataAccessOverviewChart = observer(
|
49
|
+
(props: { dataAccessState: DataAccessState }) => {
|
50
|
+
const { dataAccessState } = props;
|
51
|
+
const applicationStore = useApplicationStore();
|
52
|
+
const entitlementCheckInfo = dataAccessState.entitlementCheckInfo;
|
53
|
+
const total = entitlementCheckInfo.total;
|
54
|
+
const accessGrantedCount =
|
55
|
+
getNullableFirstEntry(entitlementCheckInfo.data)?.count ?? 0;
|
56
|
+
const accessGrantedPercentage =
|
57
|
+
getNullableFirstEntry(entitlementCheckInfo.data)?.percentage ?? 0;
|
58
|
+
|
59
|
+
return (
|
60
|
+
<div className="data-access-overview__chart">
|
61
|
+
<div className="data-access-overview__chart__actions">
|
62
|
+
<button
|
63
|
+
className="data-access-overview__chart__actions__refresh-btn btn--dark"
|
64
|
+
tabIndex={-1}
|
65
|
+
title="Refresh"
|
66
|
+
onClick={() => {
|
67
|
+
dataAccessState
|
68
|
+
.refresh()
|
69
|
+
.catch(applicationStore.alertUnhandledError);
|
70
|
+
}}
|
71
|
+
>
|
72
|
+
<RefreshIcon />
|
73
|
+
</button>
|
74
|
+
</div>
|
75
|
+
<div className="data-access-overview__chart__container">
|
76
|
+
<Doughnut
|
77
|
+
data={{
|
78
|
+
labels: entitlementCheckInfo.data.map((item) => item.label),
|
79
|
+
datasets: [
|
80
|
+
{
|
81
|
+
data: entitlementCheckInfo.data.map((item) => item.count),
|
82
|
+
backgroundColor: entitlementCheckInfo.data.map(
|
83
|
+
(item) => item.color,
|
84
|
+
),
|
85
|
+
hoverBorderWidth: 0,
|
86
|
+
borderWidth: 0,
|
87
|
+
},
|
88
|
+
],
|
89
|
+
}}
|
90
|
+
options={{
|
91
|
+
responsive: true,
|
92
|
+
resizeDelay: 0,
|
93
|
+
maintainAspectRatio: false,
|
94
|
+
cutout: '75%',
|
95
|
+
plugins: {
|
96
|
+
tooltip: {
|
97
|
+
enabled: total !== 0,
|
98
|
+
usePointStyle: false,
|
99
|
+
boxPadding: 5,
|
100
|
+
callbacks: {
|
101
|
+
labelPointStyle: () => ({
|
102
|
+
pointStyle: 'rectRounded',
|
103
|
+
rotation: 0,
|
104
|
+
}),
|
105
|
+
},
|
106
|
+
},
|
107
|
+
},
|
108
|
+
}}
|
109
|
+
/>
|
110
|
+
<div className="data-access-overview__chart__stats">
|
111
|
+
<div className="data-access-overview__chart__stats__percentage">
|
112
|
+
{accessGrantedPercentage}%
|
113
|
+
</div>
|
114
|
+
<div className="data-access-overview__chart__stats__tally">
|
115
|
+
{total === 0 ? 0 : accessGrantedCount}/{total}
|
116
|
+
</div>
|
117
|
+
</div>
|
118
|
+
</div>
|
119
|
+
</div>
|
120
|
+
);
|
121
|
+
},
|
122
|
+
);
|
123
|
+
|
124
|
+
const AccessStatusCellRenderer = observer(
|
125
|
+
(
|
126
|
+
params: DataGridCellRendererParams<DatasetAccessInfo> & {
|
127
|
+
dataAccessState: DataAccessState;
|
128
|
+
},
|
129
|
+
) => {
|
130
|
+
const { data } = params;
|
131
|
+
const applicationStore = useApplicationStore();
|
132
|
+
|
133
|
+
if (!data) {
|
134
|
+
return null;
|
135
|
+
}
|
136
|
+
|
137
|
+
if (
|
138
|
+
data.entitlementReport instanceof DatasetEntitlementAccessGrantedReport
|
139
|
+
) {
|
140
|
+
return (
|
141
|
+
<div className="data-access-overview__grid__access-status-cell">
|
142
|
+
<div className="data-access-overview__grid__access-status-cell__content">
|
143
|
+
<div className="data-access-overview__grid__access-status-cell__icon data-access-overview__grid__access-status-cell__icon--access-granted">
|
144
|
+
<CheckCircleIcon />
|
145
|
+
</div>
|
146
|
+
<div className="data-access-overview__grid__access-status-cell__text">
|
147
|
+
Access Granted
|
148
|
+
</div>
|
149
|
+
</div>
|
150
|
+
</div>
|
151
|
+
);
|
152
|
+
} else if (
|
153
|
+
data.entitlementReport instanceof DatasetEntitlementAccessApprovedReport
|
154
|
+
) {
|
155
|
+
return (
|
156
|
+
<div className="data-access-overview__grid__access-status-cell">
|
157
|
+
<div className="data-access-overview__grid__access-status-cell__content">
|
158
|
+
<div className="data-access-overview__grid__access-status-cell__icon data-access-overview__grid__access-status-cell__icon--access-approved">
|
159
|
+
<MinusCircleIcon />
|
160
|
+
</div>
|
161
|
+
<div className="data-access-overview__grid__access-status-cell__text">
|
162
|
+
Access Approved
|
163
|
+
</div>
|
164
|
+
</div>
|
165
|
+
</div>
|
166
|
+
);
|
167
|
+
} else if (
|
168
|
+
data.entitlementReport instanceof DatasetEntitlementAccessRequestedReport
|
169
|
+
) {
|
170
|
+
return (
|
171
|
+
<div className="data-access-overview__grid__access-status-cell">
|
172
|
+
<div className="data-access-overview__grid__access-status-cell__content">
|
173
|
+
<div className="data-access-overview__grid__access-status-cell__icon data-access-overview__grid__access-status-cell__icon--access-requested">
|
174
|
+
<ExclamationCircleIcon />
|
175
|
+
</div>
|
176
|
+
<div className="data-access-overview__grid__access-status-cell__text">
|
177
|
+
Access Requested
|
178
|
+
</div>
|
179
|
+
</div>
|
180
|
+
</div>
|
181
|
+
);
|
182
|
+
} else if (
|
183
|
+
data.entitlementReport instanceof DatasetEntitlementAccessNotGrantedReport
|
184
|
+
) {
|
185
|
+
const plugins = applicationStore.pluginManager
|
186
|
+
.getApplicationPlugins()
|
187
|
+
.flatMap(
|
188
|
+
(plugin) =>
|
189
|
+
(
|
190
|
+
plugin as QueryBuilder_LegendApplicationPlugin_Extension
|
191
|
+
).getExtraDatasetEntitlementAccessNotGrantedReportActionConfigurations?.() ??
|
192
|
+
[],
|
193
|
+
);
|
194
|
+
let action: React.ReactNode | undefined;
|
195
|
+
for (const plugin of plugins) {
|
196
|
+
action = plugin.renderer(data);
|
197
|
+
if (action) {
|
198
|
+
break;
|
199
|
+
}
|
200
|
+
}
|
201
|
+
return (
|
202
|
+
<div className="data-access-overview__grid__access-status-cell">
|
203
|
+
<div className="data-access-overview__grid__access-status-cell__content">
|
204
|
+
<div className="data-access-overview__grid__access-status-cell__icon data-access-overview__grid__access-status-cell__icon--access-not-granted">
|
205
|
+
<TimesCircleIcon />
|
206
|
+
</div>
|
207
|
+
<div className="data-access-overview__grid__access-status-cell__text">
|
208
|
+
Access Not Granted
|
209
|
+
</div>
|
210
|
+
</div>
|
211
|
+
{action && (
|
212
|
+
<div className="data-access-overview__grid__access-status-cell__action">
|
213
|
+
{action}
|
214
|
+
</div>
|
215
|
+
)}
|
216
|
+
</div>
|
217
|
+
);
|
218
|
+
} else if (
|
219
|
+
data.entitlementReport instanceof DatasetEntitlementUnsupportedReport
|
220
|
+
) {
|
221
|
+
return (
|
222
|
+
<div className="data-access-overview__grid__empty-cell">
|
223
|
+
(unsupported)
|
224
|
+
</div>
|
225
|
+
);
|
226
|
+
}
|
227
|
+
|
228
|
+
return null;
|
229
|
+
},
|
230
|
+
);
|
231
|
+
|
232
|
+
const DataAccessOverviewGrid = observer(
|
233
|
+
(props: { dataAccessState: DataAccessState }) => {
|
234
|
+
const { dataAccessState } = props;
|
235
|
+
|
236
|
+
return (
|
237
|
+
<div className="data-access-overview__grid ag-theme-balham-dark">
|
238
|
+
<DataGrid
|
239
|
+
rowData={dataAccessState.datasets}
|
240
|
+
gridOptions={{
|
241
|
+
suppressScrollOnNewData: true,
|
242
|
+
getRowId: (rowData) => rowData.data.uuid,
|
243
|
+
}}
|
244
|
+
columnDefs={[
|
245
|
+
{
|
246
|
+
minWidth: 50,
|
247
|
+
sortable: true,
|
248
|
+
resizable: true,
|
249
|
+
field: 'specification.name',
|
250
|
+
headerName: 'Dataset',
|
251
|
+
flex: 1,
|
252
|
+
},
|
253
|
+
{
|
254
|
+
minWidth: 50,
|
255
|
+
sortable: true,
|
256
|
+
resizable: true,
|
257
|
+
field: 'specification.type',
|
258
|
+
headerName: 'Type',
|
259
|
+
flex: 1,
|
260
|
+
},
|
261
|
+
{
|
262
|
+
minWidth: 50,
|
263
|
+
sortable: true,
|
264
|
+
resizable: true,
|
265
|
+
headerName: 'Access Status',
|
266
|
+
cellRendererParams: {
|
267
|
+
dataAccessState,
|
268
|
+
},
|
269
|
+
cellRenderer: AccessStatusCellRenderer,
|
270
|
+
flex: 1,
|
271
|
+
},
|
272
|
+
]}
|
273
|
+
/>
|
274
|
+
</div>
|
275
|
+
);
|
276
|
+
},
|
277
|
+
);
|
278
|
+
|
279
|
+
export const DataAccessOverview = observer(
|
280
|
+
(props: {
|
281
|
+
dataAccessState: DataAccessState;
|
282
|
+
compact?: boolean | undefined;
|
283
|
+
}) => {
|
284
|
+
const { dataAccessState, compact } = props;
|
285
|
+
const applicationStore = useApplicationStore();
|
286
|
+
|
287
|
+
useEffect(() => {
|
288
|
+
dataAccessState.intialize().catch(applicationStore.alertUnhandledError);
|
289
|
+
}, [applicationStore, dataAccessState]);
|
290
|
+
|
291
|
+
return (
|
292
|
+
<div
|
293
|
+
className={clsx('data-access-overview', {
|
294
|
+
'data-access-overview--compact': Boolean(compact),
|
295
|
+
})}
|
296
|
+
>
|
297
|
+
<PanelLoadingIndicator
|
298
|
+
isLoading={
|
299
|
+
dataAccessState.surveyDatasetsState.isInProgress ||
|
300
|
+
dataAccessState.checkEntitlementsState.isInProgress
|
301
|
+
}
|
302
|
+
/>
|
303
|
+
<DataAccessOverviewChart dataAccessState={dataAccessState} />
|
304
|
+
<DataAccessOverviewGrid dataAccessState={dataAccessState} />
|
305
|
+
</div>
|
306
|
+
);
|
307
|
+
},
|
308
|
+
);
|
@@ -380,7 +380,7 @@ const ExecutionPlanViewPanel = observer(
|
|
380
380
|
inputValue={displayData}
|
381
381
|
isReadOnly={true}
|
382
382
|
language={CODE_EDITOR_LANGUAGE.JSON}
|
383
|
-
|
383
|
+
hideMinimap={true}
|
384
384
|
/>
|
385
385
|
)}
|
386
386
|
{executionPlanState.viewMode ===
|
@@ -462,7 +462,6 @@ const ExecutionPlanViewerContent = observer(
|
|
462
462
|
inputValue={JSON.stringify(rawPlan, undefined, DEFAULT_TAB_SIZE)}
|
463
463
|
isReadOnly={true}
|
464
464
|
language={CODE_EDITOR_LANGUAGE.JSON}
|
465
|
-
showMiniMap={true}
|
466
465
|
/>
|
467
466
|
)}
|
468
467
|
</div>
|
@@ -523,7 +522,6 @@ export const ExecutionPlanViewer = observer(
|
|
523
522
|
inputValue={executionPlanState.debugText}
|
524
523
|
isReadOnly={true}
|
525
524
|
language={CODE_EDITOR_LANGUAGE.TEXT}
|
526
|
-
showMiniMap={true}
|
527
525
|
/>
|
528
526
|
</PanelContent>
|
529
527
|
</div>
|
@@ -39,8 +39,8 @@ import {
|
|
39
39
|
CalendarIcon,
|
40
40
|
CalendarClockIcon,
|
41
41
|
CustomSelectorInput,
|
42
|
-
PURE_FunctionIcon,
|
43
42
|
PanelEntryDropZonePlaceholder,
|
43
|
+
FunctionIcon,
|
44
44
|
} from '@finos/legend-art';
|
45
45
|
import {
|
46
46
|
type QueryBuilderExplorerTreeDragSource,
|
@@ -102,62 +102,6 @@ import { getPropertyChainName } from '../../stores/QueryBuilderPropertyEditorSta
|
|
102
102
|
import { generateDefaultValueForPrimitiveType } from '../../stores/QueryBuilderValueSpecificationHelper.js';
|
103
103
|
import { QUERY_BUILDER_CALENDAR_TYPE } from '../../graph-manager/QueryBuilderConst.js';
|
104
104
|
|
105
|
-
export type CalendarFunctionOption = {
|
106
|
-
label: string | React.ReactNode;
|
107
|
-
value: QueryBuilderAggregateCalendarFunction;
|
108
|
-
};
|
109
|
-
|
110
|
-
export const buildCalendarFunctionOption = (
|
111
|
-
calendarFunction: QueryBuilderAggregateCalendarFunction,
|
112
|
-
): CalendarFunctionOption => ({
|
113
|
-
label: (
|
114
|
-
<div
|
115
|
-
className="query-builder__projection__calendar__function__label"
|
116
|
-
title={calendarFunction.getLabel()}
|
117
|
-
>
|
118
|
-
<PURE_FunctionIcon />
|
119
|
-
<div className="query-builder__projection__calendar__function__label__title">
|
120
|
-
{calendarFunction.getLabel()}
|
121
|
-
</div>
|
122
|
-
</div>
|
123
|
-
),
|
124
|
-
value: calendarFunction,
|
125
|
-
});
|
126
|
-
|
127
|
-
export type CalendarFunctionDateColumnOption = {
|
128
|
-
label: string;
|
129
|
-
value: AbstractPropertyExpression;
|
130
|
-
};
|
131
|
-
|
132
|
-
export const buildCalendarFunctionDateColumnOption = (
|
133
|
-
dateColumn: Property | AbstractPropertyExpression,
|
134
|
-
parameter: VariableExpression,
|
135
|
-
humanizeLabel: boolean,
|
136
|
-
): CalendarFunctionDateColumnOption => {
|
137
|
-
if (dateColumn instanceof Property) {
|
138
|
-
const propertyExpression = new AbstractPropertyExpression('');
|
139
|
-
propertyExpression_setFunc(
|
140
|
-
propertyExpression,
|
141
|
-
PropertyExplicitReference.create(guaranteeNonNullable(dateColumn)),
|
142
|
-
);
|
143
|
-
propertyExpression.parametersValues = [parameter];
|
144
|
-
return {
|
145
|
-
label: getPropertyChainName(propertyExpression, humanizeLabel),
|
146
|
-
value: propertyExpression,
|
147
|
-
};
|
148
|
-
} else {
|
149
|
-
return {
|
150
|
-
label: getPropertyChainName(dateColumn, humanizeLabel),
|
151
|
-
value: dateColumn,
|
152
|
-
};
|
153
|
-
}
|
154
|
-
};
|
155
|
-
|
156
|
-
export type CalendarTypeOption = {
|
157
|
-
label: string;
|
158
|
-
value: QUERY_BUILDER_CALENDAR_TYPE;
|
159
|
-
};
|
160
|
-
|
161
105
|
const QueryBuilderProjectionColumnContextMenu = observer(
|
162
106
|
forwardRef<
|
163
107
|
HTMLDivElement,
|
@@ -304,6 +248,76 @@ const QueryBuilderDerivationProjectionColumnEditor = observer(
|
|
304
248
|
},
|
305
249
|
);
|
306
250
|
|
251
|
+
type CalendarFunctionOption = {
|
252
|
+
label: string | React.ReactNode;
|
253
|
+
value: QueryBuilderAggregateCalendarFunction;
|
254
|
+
};
|
255
|
+
|
256
|
+
const buildCalendarFunctionOption = (
|
257
|
+
calendarFunction: QueryBuilderAggregateCalendarFunction,
|
258
|
+
): CalendarFunctionOption => ({
|
259
|
+
label: (
|
260
|
+
<div
|
261
|
+
className="query-builder__projection__calendar__function__label"
|
262
|
+
title={calendarFunction.getLabel()}
|
263
|
+
>
|
264
|
+
<FunctionIcon className="query-builder__projection__calendar__function__label__icon" />
|
265
|
+
<div className="query-builder__projection__calendar__function__label__title">
|
266
|
+
{calendarFunction.getLabel()}
|
267
|
+
</div>
|
268
|
+
</div>
|
269
|
+
),
|
270
|
+
value: calendarFunction,
|
271
|
+
});
|
272
|
+
|
273
|
+
type CalendarFunctionDateColumnOption = {
|
274
|
+
label: React.ReactNode;
|
275
|
+
value: AbstractPropertyExpression;
|
276
|
+
};
|
277
|
+
|
278
|
+
const buildCalendarFunctionDateColumnOption = (
|
279
|
+
dateColumn: Property | AbstractPropertyExpression,
|
280
|
+
parameter: VariableExpression,
|
281
|
+
humanizeLabel: boolean,
|
282
|
+
): CalendarFunctionDateColumnOption => {
|
283
|
+
if (dateColumn instanceof Property) {
|
284
|
+
const propertyExpression = new AbstractPropertyExpression('');
|
285
|
+
propertyExpression_setFunc(
|
286
|
+
propertyExpression,
|
287
|
+
PropertyExplicitReference.create(guaranteeNonNullable(dateColumn)),
|
288
|
+
);
|
289
|
+
propertyExpression.parametersValues = [parameter];
|
290
|
+
return {
|
291
|
+
label: getPropertyChainName(propertyExpression, humanizeLabel),
|
292
|
+
value: propertyExpression,
|
293
|
+
};
|
294
|
+
} else {
|
295
|
+
return {
|
296
|
+
label: getPropertyChainName(dateColumn, humanizeLabel),
|
297
|
+
value: dateColumn,
|
298
|
+
};
|
299
|
+
}
|
300
|
+
};
|
301
|
+
|
302
|
+
type CalendarTypeOption = {
|
303
|
+
label: React.ReactNode;
|
304
|
+
value: QUERY_BUILDER_CALENDAR_TYPE;
|
305
|
+
};
|
306
|
+
|
307
|
+
const buildCalendarTypeOption = (
|
308
|
+
val: QUERY_BUILDER_CALENDAR_TYPE,
|
309
|
+
): CalendarTypeOption => ({
|
310
|
+
label: (
|
311
|
+
<div className="query-builder__projection__calendar__type__option">
|
312
|
+
<CalendarIcon className="query-builder__projection__calendar__type__option__icon" />
|
313
|
+
<div className="query-builder__projection__calendar__type__option__title">
|
314
|
+
{val}
|
315
|
+
</div>
|
316
|
+
</div>
|
317
|
+
),
|
318
|
+
value: val,
|
319
|
+
});
|
320
|
+
|
307
321
|
const QueryBuilderProjectionColumnEditor = observer(
|
308
322
|
(props: { projectionColumnState: QueryBuilderProjectionColumnState }) => {
|
309
323
|
const handleRef = useRef<HTMLDivElement>(null);
|
@@ -369,31 +383,13 @@ const QueryBuilderProjectionColumnEditor = observer(
|
|
369
383
|
),
|
370
384
|
);
|
371
385
|
const calendarTypeOptions = Object.values(QUERY_BUILDER_CALENDAR_TYPE).map(
|
372
|
-
|
373
|
-
label: (
|
374
|
-
<div className="query-builder__projection__calendar__type__option">
|
375
|
-
<CalendarIcon />
|
376
|
-
<div className="query-builder__projection__calendar__type__option__title">
|
377
|
-
{ct}
|
378
|
-
</div>
|
379
|
-
</div>
|
380
|
-
),
|
381
|
-
value: ct,
|
382
|
-
}),
|
386
|
+
buildCalendarTypeOption,
|
383
387
|
);
|
384
388
|
const selectedCalendarTypeOption = aggregateColumnState?.calendarFunction
|
385
389
|
?.calendarType
|
386
|
-
?
|
387
|
-
|
388
|
-
|
389
|
-
<CalendarIcon />
|
390
|
-
<div className="query-builder__projection__calendar__type__option__title">
|
391
|
-
{aggregateColumnState.calendarFunction.calendarType}
|
392
|
-
</div>
|
393
|
-
</div>
|
394
|
-
),
|
395
|
-
value: aggregateColumnState.calendarFunction.calendarType,
|
396
|
-
}
|
390
|
+
? buildCalendarTypeOption(
|
391
|
+
aggregateColumnState.calendarFunction.calendarType,
|
392
|
+
)
|
397
393
|
: null;
|
398
394
|
const onCalendarTypeOptionChange = (option: CalendarTypeOption): void => {
|
399
395
|
if (
|
@@ -661,13 +657,15 @@ const QueryBuilderProjectionColumnEditor = observer(
|
|
661
657
|
aggregateColumnState &&
|
662
658
|
aggregateCalendarFunctions.length > 0 && (
|
663
659
|
<div
|
664
|
-
className={
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
660
|
+
className={clsx(
|
661
|
+
'query-builder__projection__column__aggregate__calendar__toggler',
|
662
|
+
{
|
663
|
+
'query-builder__projection__column__aggregate__calendar__toggler--active':
|
664
|
+
!aggregateColumnState.hideCalendarColumnState,
|
665
|
+
},
|
666
|
+
)}
|
669
667
|
onClick={toggleHideCalendarColumnState}
|
670
|
-
title="
|
668
|
+
title="Toggle calendar aggregation"
|
671
669
|
>
|
672
670
|
<CalendarClockIcon />
|
673
671
|
</div>
|
@@ -749,21 +747,19 @@ const QueryBuilderProjectionColumnEditor = observer(
|
|
749
747
|
},
|
750
748
|
)}
|
751
749
|
>
|
752
|
-
<
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
/>
|
766
|
-
</div>
|
750
|
+
<CustomSelectorInput
|
751
|
+
className="query-builder__projection__calendar__function"
|
752
|
+
options={calendarFunctionOptions}
|
753
|
+
onChange={onCalendarFunctionOptionChange}
|
754
|
+
value={selectedCalendarFunctionOption}
|
755
|
+
placeholder="Select Calendar Function"
|
756
|
+
isClearable={true}
|
757
|
+
escapeClearsValue={true}
|
758
|
+
darkMode={
|
759
|
+
!applicationStore.layoutService
|
760
|
+
.TEMPORARY__isLightColorThemeEnabled
|
761
|
+
}
|
762
|
+
/>
|
767
763
|
<div className="query-builder__projection__calendar__value">
|
768
764
|
<BasicValueSpecificationEditor
|
769
765
|
valueSpecification={
|
@@ -807,7 +803,7 @@ const QueryBuilderProjectionColumnEditor = observer(
|
|
807
803
|
</div>
|
808
804
|
</div>
|
809
805
|
) : (
|
810
|
-
<div className="query-
|
806
|
+
<div className="query-builder__projection__calendar__date__column__placeholder">
|
811
807
|
Drag and drop date column here
|
812
808
|
</div>
|
813
809
|
)}
|
@@ -818,7 +814,8 @@ const QueryBuilderProjectionColumnEditor = observer(
|
|
818
814
|
options={calendarTypeOptions}
|
819
815
|
onChange={onCalendarTypeOptionChange}
|
820
816
|
value={selectedCalendarTypeOption ?? calendarTypeOptions[0]}
|
821
|
-
placeholder=
|
817
|
+
placeholder="Select calendar type"
|
818
|
+
disabled={!aggregateColumnState.calendarFunction}
|
822
819
|
darkMode={
|
823
820
|
!applicationStore.layoutService
|
824
821
|
.TEMPORARY__isLightColorThemeEnabled
|
@@ -23,7 +23,6 @@ import {
|
|
23
23
|
LongArrowAltDownIcon,
|
24
24
|
LongArrowAltUpIcon,
|
25
25
|
Dialog,
|
26
|
-
useResizeDetector,
|
27
26
|
Modal,
|
28
27
|
ModalBody,
|
29
28
|
ModalFooter,
|
@@ -154,13 +153,6 @@ const LambdaEditorInline = observer(
|
|
154
153
|
}
|
155
154
|
};
|
156
155
|
|
157
|
-
const { ref, width, height } = useResizeDetector<HTMLDivElement>();
|
158
|
-
useEffect(() => {
|
159
|
-
if (width !== undefined && height !== undefined) {
|
160
|
-
editor?.layout({ width, height });
|
161
|
-
}
|
162
|
-
}, [editor, width, height]);
|
163
|
-
|
164
156
|
useEffect(() => {
|
165
157
|
if (!editor && textInputRef.current) {
|
166
158
|
const element = textInputRef.current;
|
@@ -187,8 +179,8 @@ const LambdaEditorInline = observer(
|
|
187
179
|
language: CODE_EDITOR_LANGUAGE.PURE,
|
188
180
|
theme: applicationStore.layoutService
|
189
181
|
.TEMPORARY__isLightColorThemeEnabled
|
190
|
-
? CODE_EDITOR_THEME.
|
191
|
-
: CODE_EDITOR_THEME.
|
182
|
+
? CODE_EDITOR_THEME.BUILT_IN__VSCODE_LIGHT
|
183
|
+
: CODE_EDITOR_THEME.DEFAULT_DARK,
|
192
184
|
...lambdaEditorOptions,
|
193
185
|
});
|
194
186
|
setEditor(_editor);
|
@@ -341,7 +333,6 @@ const LambdaEditorInline = observer(
|
|
341
333
|
})}
|
342
334
|
>
|
343
335
|
<div
|
344
|
-
ref={ref}
|
345
336
|
data-testid={QUERY_BUILDER_TEST_ID.LAMBDA_EDITOR__EDITOR_INPUT}
|
346
337
|
className="lambda-editor__editor__input"
|
347
338
|
>
|
@@ -451,13 +442,6 @@ const LambdaEditorPopUp = observer(
|
|
451
442
|
transformLambdaToString(true),
|
452
443
|
);
|
453
444
|
|
454
|
-
const { ref, width, height } = useResizeDetector<HTMLDivElement>();
|
455
|
-
useEffect(() => {
|
456
|
-
if (width !== undefined && height !== undefined) {
|
457
|
-
editor?.layout({ width, height });
|
458
|
-
}
|
459
|
-
}, [editor, width, height]);
|
460
|
-
|
461
445
|
const onEnter = (): void => {
|
462
446
|
if (!editor && textInputRef.current) {
|
463
447
|
const element = textInputRef.current;
|
@@ -466,8 +450,8 @@ const LambdaEditorPopUp = observer(
|
|
466
450
|
language: CODE_EDITOR_LANGUAGE.PURE,
|
467
451
|
theme: applicationStore.layoutService
|
468
452
|
.TEMPORARY__isLightColorThemeEnabled
|
469
|
-
? CODE_EDITOR_THEME.
|
470
|
-
: CODE_EDITOR_THEME.
|
453
|
+
? CODE_EDITOR_THEME.BUILT_IN__VSCODE_LIGHT
|
454
|
+
: CODE_EDITOR_THEME.DEFAULT_DARK,
|
471
455
|
});
|
472
456
|
setEditor(_editor);
|
473
457
|
}
|
@@ -613,7 +597,6 @@ const LambdaEditorPopUp = observer(
|
|
613
597
|
<ModalBody>
|
614
598
|
<div className={clsx('lambda-editor__popup__content', className)}>
|
615
599
|
<div
|
616
|
-
ref={ref}
|
617
600
|
data-testid={QUERY_BUILDER_TEST_ID.LAMBDA_EDITOR__EDITOR_INPUT}
|
618
601
|
className="lambda-editor__editor__input"
|
619
602
|
>
|
package/src/index.ts
CHANGED
@@ -70,6 +70,10 @@ export * from './stores/shared/ValueSpecificationEditorHelper.js';
|
|
70
70
|
|
71
71
|
export * from './components/execution-plan/ExecutionPlanViewer.js';
|
72
72
|
export * from './stores/execution-plan/ExecutionPlanState.js';
|
73
|
+
|
73
74
|
export * from './components/QueryLoader.js';
|
74
75
|
export * from './stores/QueryLoaderState.js';
|
75
76
|
export * from './stores/QueryBuilder_LegendApplicationPlugin_Extension.js';
|
77
|
+
|
78
|
+
export * from './stores/data-access/DataAccessState.js';
|
79
|
+
export * from './components/data-access/DataAccessOverview.js';
|