@finos/legend-application-query 12.0.7 → 12.0.8
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__/LegendQueryEvent.d.ts +3 -1
- package/lib/__lib__/LegendQueryEvent.d.ts.map +1 -1
- package/lib/__lib__/LegendQueryEvent.js +2 -0
- package/lib/__lib__/LegendQueryEvent.js.map +1 -1
- package/lib/__lib__/LegendQueryTelemetryHelper.d.ts +2 -0
- package/lib/__lib__/LegendQueryTelemetryHelper.d.ts.map +1 -1
- package/lib/__lib__/LegendQueryTelemetryHelper.js +6 -0
- package/lib/__lib__/LegendQueryTelemetryHelper.js.map +1 -1
- package/lib/application/LegendQueryDocumentation.d.ts +19 -0
- package/lib/application/LegendQueryDocumentation.d.ts.map +1 -0
- package/lib/application/LegendQueryDocumentation.js +20 -0
- package/lib/application/LegendQueryDocumentation.js.map +1 -0
- package/lib/components/CloneQueryServiceSetup.d.ts.map +1 -1
- package/lib/components/CloneQueryServiceSetup.js +1 -2
- package/lib/components/CloneQueryServiceSetup.js.map +1 -1
- package/lib/components/CreateMappingQuerySetup.d.ts.map +1 -1
- package/lib/components/CreateMappingQuerySetup.js +1 -2
- package/lib/components/CreateMappingQuerySetup.js.map +1 -1
- package/lib/components/LegendQueryWebApplication.d.ts +0 -1
- package/lib/components/LegendQueryWebApplication.d.ts.map +1 -1
- package/lib/components/QueryEditor.d.ts +0 -1
- package/lib/components/QueryEditor.d.ts.map +1 -1
- package/lib/components/QueryEditor.js +113 -28
- package/lib/components/QueryEditor.js.map +1 -1
- package/lib/components/QuerySetup.d.ts +1 -1
- package/lib/components/QuerySetup.d.ts.map +1 -1
- package/lib/components/QuerySetup.js +13 -4
- package/lib/components/QuerySetup.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/package.json +4 -4
- package/lib/stores/LegendQueryApplicationPlugin.d.ts +15 -5
- package/lib/stores/LegendQueryApplicationPlugin.d.ts.map +1 -1
- package/lib/stores/LegendQueryApplicationPlugin.js.map +1 -1
- package/lib/stores/QueryEditorStore.d.ts +52 -11
- package/lib/stores/QueryEditorStore.d.ts.map +1 -1
- package/lib/stores/QueryEditorStore.js +228 -21
- package/lib/stores/QueryEditorStore.js.map +1 -1
- package/package.json +11 -11
- package/src/__lib__/LegendQueryEvent.ts +3 -0
- package/src/__lib__/LegendQueryTelemetryHelper.ts +15 -0
- package/src/application/LegendQueryDocumentation.ts +19 -0
- package/src/components/CloneQueryServiceSetup.tsx +1 -5
- package/src/components/CreateMappingQuerySetup.tsx +1 -5
- package/src/components/QueryEditor.tsx +332 -73
- package/src/components/QuerySetup.tsx +17 -5
- package/src/index.ts +1 -1
- package/src/stores/LegendQueryApplicationPlugin.ts +22 -5
- package/src/stores/QueryEditorStore.ts +315 -31
- package/tsconfig.json +1 -0
@@ -18,7 +18,6 @@ import {
|
|
18
18
|
type SelectComponent,
|
19
19
|
Dialog,
|
20
20
|
PanelLoadingIndicator,
|
21
|
-
SaveIcon,
|
22
21
|
BlankPanelContent,
|
23
22
|
clsx,
|
24
23
|
SearchIcon,
|
@@ -43,10 +42,15 @@ import {
|
|
43
42
|
ManageSearchIcon,
|
44
43
|
LightBulbIcon,
|
45
44
|
EmptyLightBulbIcon,
|
45
|
+
SaveCurrIcon,
|
46
|
+
SaveAsIcon,
|
47
|
+
ExclamationTriangleIcon,
|
48
|
+
PanelListItem,
|
49
|
+
Button,
|
46
50
|
} from '@finos/legend-art';
|
47
51
|
import { debounce } from '@finos/legend-shared';
|
48
52
|
import { observer } from 'mobx-react-lite';
|
49
|
-
import { Fragment, useEffect, useMemo, useRef, useState } from 'react';
|
53
|
+
import React, { Fragment, useEffect, useMemo, useRef, useState } from 'react';
|
50
54
|
import {
|
51
55
|
type MappingQueryCreatorPathParams,
|
52
56
|
type ExistingQueryEditorPathParams,
|
@@ -58,10 +62,11 @@ import {
|
|
58
62
|
} from '../__lib__/LegendQueryNavigation.js';
|
59
63
|
import {
|
60
64
|
type QueryEditorStore,
|
61
|
-
|
62
|
-
QueryExportState,
|
65
|
+
QuerySaveAsState,
|
63
66
|
createViewProjectHandler,
|
64
67
|
createViewSDLCProjectHandler,
|
68
|
+
QuerySaveState,
|
69
|
+
QueryRenameState,
|
65
70
|
} from '../stores/QueryEditorStore.js';
|
66
71
|
import {
|
67
72
|
LEGEND_APPLICATION_COLOR_THEME,
|
@@ -82,68 +87,105 @@ import {
|
|
82
87
|
QueryBuilderNavigationBlocker,
|
83
88
|
type QueryBuilderState,
|
84
89
|
} from '@finos/legend-query-builder';
|
90
|
+
import type { QueryEditorHelpMenuEntry } from '../stores/LegendQueryApplicationPlugin.js';
|
91
|
+
import { QUERY_DOCUMENTATION_KEY } from '../application/LegendQueryDocumentation.js';
|
92
|
+
import { LegendQueryTelemetryHelper } from '../__lib__/LegendQueryTelemetryHelper.js';
|
85
93
|
|
86
|
-
const
|
87
|
-
(props: {
|
88
|
-
const {
|
94
|
+
const QuerySaveAsDialogContent = observer(
|
95
|
+
(props: { saveAsState: QuerySaveAsState }) => {
|
96
|
+
const { saveAsState } = props;
|
89
97
|
const applicationStore = useApplicationStore();
|
90
|
-
const
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
);
|
98
|
+
const create = (): void => {
|
99
|
+
flowResult(saveAsState.createQuery(true)).catch(
|
100
|
+
applicationStore.alertUnhandledError,
|
101
|
+
);
|
102
|
+
};
|
103
|
+
|
104
|
+
const isExistingQueryName = saveAsState.editorStore.existingQueryName;
|
98
105
|
|
99
106
|
// name
|
100
107
|
const nameInputRef = useRef<HTMLInputElement>(null);
|
101
|
-
|
102
|
-
|
108
|
+
|
109
|
+
const debouncedLoadQueries = useMemo(
|
110
|
+
() =>
|
111
|
+
debounce((input: string): void => {
|
112
|
+
flowResult(
|
113
|
+
saveAsState.editorStore.searchExistingQueryName(input),
|
114
|
+
).catch(applicationStore.alertUnhandledError);
|
115
|
+
}, 500),
|
116
|
+
[applicationStore, saveAsState.editorStore],
|
117
|
+
);
|
118
|
+
|
119
|
+
const changeName: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
120
|
+
saveAsState.setQueryName(event.target.value);
|
121
|
+
};
|
103
122
|
|
104
123
|
useEffect(() => {
|
105
124
|
nameInputRef.current?.focus();
|
106
125
|
}, []);
|
107
126
|
|
127
|
+
useEffect(() => {
|
128
|
+
const searchText = saveAsState.queryName;
|
129
|
+
debouncedLoadQueries.cancel();
|
130
|
+
debouncedLoadQueries(searchText);
|
131
|
+
}, [
|
132
|
+
saveAsState.queryName,
|
133
|
+
debouncedLoadQueries,
|
134
|
+
saveAsState.editorStore.queryLoaderState.queries,
|
135
|
+
]);
|
136
|
+
|
108
137
|
return (
|
109
138
|
<>
|
110
139
|
<ModalBody>
|
111
140
|
<PanelLoadingIndicator
|
112
|
-
isLoading={
|
113
|
-
/>
|
114
|
-
<input
|
115
|
-
ref={nameInputRef}
|
116
|
-
className="input input--dark"
|
117
|
-
spellCheck={false}
|
118
|
-
value={exportState.queryName}
|
119
|
-
onChange={changeName}
|
141
|
+
isLoading={saveAsState.createQueryState.isInProgress}
|
120
142
|
/>
|
143
|
+
<PanelListItem>
|
144
|
+
<div className="input--with-validation">
|
145
|
+
<input
|
146
|
+
ref={nameInputRef}
|
147
|
+
className={clsx('input input--dark', {
|
148
|
+
'input--caution': isExistingQueryName,
|
149
|
+
})}
|
150
|
+
spellCheck={false}
|
151
|
+
value={saveAsState.queryName}
|
152
|
+
onChange={changeName}
|
153
|
+
/>
|
154
|
+
{isExistingQueryName && (
|
155
|
+
<div
|
156
|
+
className="input--with-validation__caution"
|
157
|
+
title={`Query named '${isExistingQueryName}' already exists`}
|
158
|
+
>
|
159
|
+
<ExclamationTriangleIcon className="input--with-validation__caution__indicator" />
|
160
|
+
</div>
|
161
|
+
)}
|
162
|
+
</div>
|
163
|
+
</PanelListItem>
|
121
164
|
</ModalBody>
|
122
165
|
<ModalFooter>
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
166
|
+
<ModalFooterButton
|
167
|
+
text="Create Query"
|
168
|
+
title={
|
169
|
+
!saveAsState.allowPersist
|
170
|
+
? `Cannot create new query`
|
171
|
+
: 'Create new query'
|
172
|
+
}
|
129
173
|
onClick={create}
|
130
|
-
|
131
|
-
Create
|
132
|
-
</button>
|
174
|
+
/>
|
133
175
|
</ModalFooter>
|
134
176
|
</>
|
135
177
|
);
|
136
178
|
},
|
137
179
|
);
|
138
180
|
|
139
|
-
const
|
181
|
+
const QuerySaveDialog = observer(() => {
|
140
182
|
const editorStore = useQueryEditorStore();
|
141
|
-
const
|
142
|
-
const close = (): void => editorStore.
|
183
|
+
const saveAsState = editorStore.saveAsState;
|
184
|
+
const close = (): void => editorStore.setSaveAsState(undefined);
|
143
185
|
|
144
186
|
return (
|
145
187
|
<Dialog
|
146
|
-
open={Boolean(
|
188
|
+
open={Boolean(saveAsState)}
|
147
189
|
onClose={close}
|
148
190
|
classes={{
|
149
191
|
root: 'editor-modal__root-container',
|
@@ -152,8 +194,8 @@ const QueryExport = observer(() => {
|
|
152
194
|
}}
|
153
195
|
>
|
154
196
|
<Modal darkMode={true} className="query-export">
|
155
|
-
<ModalHeader title=
|
156
|
-
{
|
197
|
+
<ModalHeader title={'Create New Query'} />
|
198
|
+
{saveAsState && <QuerySaveAsDialogContent saveAsState={saveAsState} />}
|
157
199
|
</Modal>
|
158
200
|
</Dialog>
|
159
201
|
);
|
@@ -166,6 +208,7 @@ const QueryLoader = observer(
|
|
166
208
|
}) => {
|
167
209
|
const { editorStore, queryBuilderState } = props;
|
168
210
|
const applicationStore = useApplicationStore();
|
211
|
+
|
169
212
|
const queryFinderRef = useRef<SelectComponent>(null);
|
170
213
|
const searchInputRef = useRef<HTMLInputElement>(null);
|
171
214
|
const [selectedQueryID, setSelectedQueryID] = useState('');
|
@@ -372,10 +415,22 @@ const QueryLoader = observer(
|
|
372
415
|
},
|
373
416
|
);
|
374
417
|
|
418
|
+
const HelpMenuContentItemRenderer = (
|
419
|
+
props: QueryEditorHelpMenuEntry,
|
420
|
+
): React.ReactElement => (
|
421
|
+
<MenuContentItem title={props.title ?? ''} onClick={props.onClick}>
|
422
|
+
{props.icon && <MenuContentItemIcon>{props.icon}</MenuContentItemIcon>}
|
423
|
+
<MenuContentItemLabel className="query-builder__sub-header__menu-content">
|
424
|
+
{props.label}
|
425
|
+
</MenuContentItemLabel>
|
426
|
+
</MenuContentItem>
|
427
|
+
);
|
428
|
+
|
375
429
|
const QueryEditorHeaderContent = observer(
|
376
430
|
(props: { queryBuilderState: QueryBuilderState }) => {
|
377
431
|
const { queryBuilderState } = props;
|
378
432
|
const editorStore = useQueryEditorStore();
|
433
|
+
const renameState = editorStore.renameState;
|
379
434
|
const applicationStore = useLegendQueryApplicationStore();
|
380
435
|
|
381
436
|
// actions
|
@@ -383,6 +438,9 @@ const QueryEditorHeaderContent = observer(
|
|
383
438
|
editorStore.queryLoaderState.setIsQueryLoaderOpen(true);
|
384
439
|
};
|
385
440
|
const viewProject = (): void => {
|
441
|
+
LegendQueryTelemetryHelper.logEvent_QueryViewProjectLaunched(
|
442
|
+
editorStore.applicationStore.telemetryService,
|
443
|
+
);
|
386
444
|
const { groupId, artifactId, versionId } = editorStore.getProjectInfo();
|
387
445
|
createViewProjectHandler(applicationStore)(
|
388
446
|
groupId,
|
@@ -392,6 +450,9 @@ const QueryEditorHeaderContent = observer(
|
|
392
450
|
);
|
393
451
|
};
|
394
452
|
const viewSDLCProject = (): void => {
|
453
|
+
LegendQueryTelemetryHelper.logEvent_QueryViewSdlcProjectLaunched(
|
454
|
+
editorStore.applicationStore.telemetryService,
|
455
|
+
);
|
395
456
|
const { groupId, artifactId } = editorStore.getProjectInfo();
|
396
457
|
createViewSDLCProjectHandler(
|
397
458
|
applicationStore,
|
@@ -408,11 +469,58 @@ const QueryEditorHeaderContent = observer(
|
|
408
469
|
{ persist: true },
|
409
470
|
);
|
410
471
|
};
|
472
|
+
|
473
|
+
const renameRef = useRef<HTMLInputElement>(null);
|
474
|
+
|
475
|
+
const updateQuery = (): void => {
|
476
|
+
queryBuilderState
|
477
|
+
.saveQuery(async (lambda: RawLambda) => {
|
478
|
+
editorStore.setRenameState(
|
479
|
+
new QueryRenameState(
|
480
|
+
editorStore,
|
481
|
+
queryBuilderState,
|
482
|
+
lambda,
|
483
|
+
await editorStore.getExportConfiguration(lambda, {
|
484
|
+
update: true,
|
485
|
+
}),
|
486
|
+
),
|
487
|
+
);
|
488
|
+
})
|
489
|
+
.then(() => {
|
490
|
+
renameRef.current?.select();
|
491
|
+
})
|
492
|
+
.catch(applicationStore.alertUnhandledError);
|
493
|
+
};
|
494
|
+
|
495
|
+
const renameQuery = applicationStore.guardUnhandledError(async () => {
|
496
|
+
await renameState?.renameQuery();
|
497
|
+
});
|
498
|
+
|
411
499
|
const saveQuery = (): void => {
|
412
500
|
queryBuilderState
|
413
501
|
.saveQuery(async (lambda: RawLambda) => {
|
414
|
-
editorStore.
|
415
|
-
new
|
502
|
+
editorStore.setSaveState(
|
503
|
+
new QuerySaveState(
|
504
|
+
editorStore,
|
505
|
+
queryBuilderState,
|
506
|
+
lambda,
|
507
|
+
await editorStore.getExportConfiguration(lambda, {
|
508
|
+
update: true,
|
509
|
+
}),
|
510
|
+
),
|
511
|
+
);
|
512
|
+
flowResult(editorStore.saveState?.saveQuery()).catch(
|
513
|
+
applicationStore.alertUnhandledError,
|
514
|
+
);
|
515
|
+
})
|
516
|
+
.catch(applicationStore.alertUnhandledError);
|
517
|
+
};
|
518
|
+
|
519
|
+
const saveAsQuery = (): void => {
|
520
|
+
queryBuilderState
|
521
|
+
.saveQuery(async (lambda: RawLambda) => {
|
522
|
+
editorStore.setSaveAsState(
|
523
|
+
new QuerySaveAsState(
|
416
524
|
editorStore,
|
417
525
|
queryBuilderState,
|
418
526
|
lambda,
|
@@ -423,26 +531,123 @@ const QueryEditorHeaderContent = observer(
|
|
423
531
|
.catch(applicationStore.alertUnhandledError);
|
424
532
|
};
|
425
533
|
|
534
|
+
const toggleAssistant = (): void =>
|
535
|
+
applicationStore.assistantService.toggleAssistant();
|
536
|
+
|
537
|
+
const queryDocEntry = applicationStore.documentationService.getDocEntry(
|
538
|
+
QUERY_DOCUMENTATION_KEY.TUTORIAL_QUERY_BUILDER,
|
539
|
+
);
|
540
|
+
|
541
|
+
const openQueryTutorial = (): void => {
|
542
|
+
if (queryDocEntry?.url) {
|
543
|
+
applicationStore.navigationService.navigator.visitAddress(
|
544
|
+
queryDocEntry.url,
|
545
|
+
);
|
546
|
+
}
|
547
|
+
};
|
548
|
+
|
549
|
+
const changeQueryName: React.ChangeEventHandler<HTMLInputElement> = (
|
550
|
+
event,
|
551
|
+
) => renameState?.setQueryName(event.target.value);
|
552
|
+
|
553
|
+
const onEnter: React.KeyboardEventHandler<HTMLInputElement> = (event) => {
|
554
|
+
if (event.code === 'Enter') {
|
555
|
+
renameQuery();
|
556
|
+
}
|
557
|
+
};
|
558
|
+
|
559
|
+
const debouncedLoadQueries = useMemo(
|
560
|
+
() =>
|
561
|
+
debounce((input: string): void => {
|
562
|
+
flowResult(
|
563
|
+
renameState?.editorStore.searchExistingQueryName(input),
|
564
|
+
).catch(applicationStore.alertUnhandledError);
|
565
|
+
}, 500),
|
566
|
+
[applicationStore, renameState?.editorStore],
|
567
|
+
);
|
568
|
+
|
569
|
+
useEffect(() => {
|
570
|
+
if (renameState && renameState.queryName !== editorStore.title) {
|
571
|
+
const searchText = renameState.queryName;
|
572
|
+
debouncedLoadQueries.cancel();
|
573
|
+
debouncedLoadQueries(searchText);
|
574
|
+
}
|
575
|
+
}, [
|
576
|
+
renameState,
|
577
|
+
debouncedLoadQueries,
|
578
|
+
editorStore.title,
|
579
|
+
renameState?.queryName,
|
580
|
+
]);
|
581
|
+
|
582
|
+
const isExistingQueryName = renameState?.editorStore.existingQueryName;
|
583
|
+
|
584
|
+
const extraHelpMenuContentItems = applicationStore.pluginManager
|
585
|
+
.getApplicationPlugins()
|
586
|
+
.flatMap((plugin) => plugin.getExtraQueryEditorHelpMenuEntries?.() ?? [])
|
587
|
+
.map((item) => <>{HelpMenuContentItemRenderer(item)}</>);
|
588
|
+
|
426
589
|
return (
|
427
590
|
<div className="query-editor__header__content">
|
428
|
-
|
591
|
+
{renameState ? (
|
592
|
+
<div className="query-editor__header__content__main query-editor__header__content__title">
|
593
|
+
<PanelListItem>
|
594
|
+
<div className="input--with-validation">
|
595
|
+
<input
|
596
|
+
title="Query title rename"
|
597
|
+
ref={renameRef}
|
598
|
+
className={clsx('input input--dark', {
|
599
|
+
'input--caution': isExistingQueryName,
|
600
|
+
})}
|
601
|
+
onChange={changeQueryName}
|
602
|
+
onKeyDown={onEnter}
|
603
|
+
value={renameState.queryName}
|
604
|
+
placeholder="Search"
|
605
|
+
/>
|
606
|
+
{isExistingQueryName && (
|
607
|
+
<div
|
608
|
+
className="input--with-validation__caution"
|
609
|
+
title={`Query named '${isExistingQueryName}' already exists`}
|
610
|
+
>
|
611
|
+
<ExclamationTriangleIcon className="input--with-validation__caution__indicator" />
|
612
|
+
</div>
|
613
|
+
)}
|
614
|
+
</div>
|
615
|
+
<button
|
616
|
+
className={clsx('input__btn', {
|
617
|
+
'btn--icon__caution': isExistingQueryName,
|
618
|
+
})}
|
619
|
+
onClick={renameQuery}
|
620
|
+
title="Rename Query"
|
621
|
+
>
|
622
|
+
<CheckIcon />
|
623
|
+
</button>
|
624
|
+
</PanelListItem>
|
625
|
+
</div>
|
626
|
+
) : (
|
627
|
+
<div
|
628
|
+
className="query-editor__header__content__main query-editor__header__content__title"
|
629
|
+
title="Query title"
|
630
|
+
>
|
631
|
+
{editorStore.title}
|
632
|
+
</div>
|
633
|
+
)}
|
634
|
+
|
429
635
|
<div className="query-editor__header__actions">
|
430
|
-
{
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
(
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
.
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
<
|
636
|
+
{applicationStore.pluginManager
|
637
|
+
.getApplicationPlugins()
|
638
|
+
.flatMap(
|
639
|
+
(plugin) =>
|
640
|
+
plugin.getExtraQueryEditorActionConfigurations?.(editorStore) ??
|
641
|
+
[],
|
642
|
+
)
|
643
|
+
.map((actionConfig) => (
|
644
|
+
<Fragment key={actionConfig.key}>
|
645
|
+
{actionConfig.renderer(editorStore, queryBuilderState)}
|
646
|
+
</Fragment>
|
647
|
+
))}
|
648
|
+
|
649
|
+
<Button
|
444
650
|
className="query-editor__header__action btn--dark"
|
445
|
-
tabIndex={-1}
|
446
651
|
onClick={openQueryLoader}
|
447
652
|
title="Load query..."
|
448
653
|
>
|
@@ -450,22 +655,69 @@ const QueryEditorHeaderContent = observer(
|
|
450
655
|
<div className="query-editor__header__action__label">
|
451
656
|
Load Query
|
452
657
|
</div>
|
453
|
-
</
|
658
|
+
</Button>
|
454
659
|
|
455
|
-
<
|
660
|
+
<Button
|
456
661
|
className="query-editor__header__action btn--dark"
|
457
|
-
|
458
|
-
|
662
|
+
disabled={
|
663
|
+
editorStore.isSaveActionDisabled ||
|
664
|
+
!editorStore.title ||
|
665
|
+
queryBuilderState.saveQueryProgressState.isInProgress
|
666
|
+
}
|
459
667
|
onClick={saveQuery}
|
460
668
|
title="Save query"
|
461
669
|
>
|
462
|
-
<
|
463
|
-
|
670
|
+
<SaveCurrIcon />
|
671
|
+
<div className="query-editor__header__action__label">Save</div>
|
672
|
+
</Button>
|
673
|
+
<Button
|
674
|
+
className="query-editor__header__action btn--dark"
|
675
|
+
disabled={editorStore.isSaveActionDisabled}
|
676
|
+
onClick={saveAsQuery}
|
677
|
+
title="Save as new query"
|
678
|
+
>
|
679
|
+
<SaveAsIcon />
|
464
680
|
<div className="query-editor__header__action__label">
|
465
|
-
Save
|
681
|
+
Save As...
|
466
682
|
</div>
|
467
|
-
</
|
683
|
+
</Button>
|
684
|
+
|
685
|
+
<DropdownMenu
|
686
|
+
className="query-editor__header__action btn--dark"
|
687
|
+
disabled={editorStore.isViewProjectActionDisabled}
|
688
|
+
content={
|
689
|
+
<MenuContent>
|
690
|
+
{extraHelpMenuContentItems}
|
691
|
+
{queryDocEntry && (
|
692
|
+
<MenuContentItem onClick={openQueryTutorial}>
|
693
|
+
<MenuContentItemIcon>{null}</MenuContentItemIcon>
|
694
|
+
<MenuContentItemLabel className="query-builder__sub-header__menu-content">
|
695
|
+
Open Documentation
|
696
|
+
</MenuContentItemLabel>
|
697
|
+
</MenuContentItem>
|
698
|
+
)}
|
468
699
|
|
700
|
+
<MenuContentItem onClick={toggleAssistant}>
|
701
|
+
<MenuContentItemIcon>
|
702
|
+
{!applicationStore.assistantService.isHidden ? (
|
703
|
+
<CheckIcon />
|
704
|
+
) : null}
|
705
|
+
</MenuContentItemIcon>
|
706
|
+
<MenuContentItemLabel className="query-builder__sub-header__menu-content">
|
707
|
+
Show Virtual Assistant
|
708
|
+
</MenuContentItemLabel>
|
709
|
+
</MenuContentItem>
|
710
|
+
</MenuContent>
|
711
|
+
}
|
712
|
+
>
|
713
|
+
<div
|
714
|
+
className=" query-editor__header__action__label"
|
715
|
+
title="See more options"
|
716
|
+
>
|
717
|
+
Help
|
718
|
+
</div>
|
719
|
+
<CaretDownIcon />
|
720
|
+
</DropdownMenu>
|
469
721
|
{editorStore.queryLoaderState.isQueryLoaderOpen && (
|
470
722
|
<QueryLoader
|
471
723
|
editorStore={editorStore}
|
@@ -499,14 +751,21 @@ const QueryEditorHeaderContent = observer(
|
|
499
751
|
disabled={editorStore.isViewProjectActionDisabled}
|
500
752
|
onClick={viewProject}
|
501
753
|
>
|
502
|
-
Project
|
754
|
+
Go to Project
|
503
755
|
</MenuContentItem>
|
504
756
|
<MenuContentItem
|
505
757
|
className="query-editor__header__action__options"
|
506
758
|
disabled={editorStore.isViewProjectActionDisabled}
|
507
759
|
onClick={viewSDLCProject}
|
508
760
|
>
|
509
|
-
SDLC project
|
761
|
+
Go to SDLC project
|
762
|
+
</MenuContentItem>
|
763
|
+
<MenuContentItem
|
764
|
+
className="query-editor__header__action__options"
|
765
|
+
onClick={updateQuery}
|
766
|
+
disabled={!editorStore.title}
|
767
|
+
>
|
768
|
+
Rename Query
|
510
769
|
</MenuContentItem>
|
511
770
|
</MenuContent>
|
512
771
|
}
|
@@ -515,12 +774,12 @@ const QueryEditorHeaderContent = observer(
|
|
515
774
|
className="query-editor__header__action__label"
|
516
775
|
title="See more options"
|
517
776
|
>
|
518
|
-
|
777
|
+
More Actions...
|
519
778
|
</div>
|
520
779
|
<CaretDownIcon />
|
521
780
|
</DropdownMenu>
|
522
781
|
|
523
|
-
{editorStore.
|
782
|
+
{editorStore.saveAsState && <QuerySaveDialog />}
|
524
783
|
</div>
|
525
784
|
</div>
|
526
785
|
);
|
@@ -574,15 +833,15 @@ export const QueryEditor = observer(() => {
|
|
574
833
|
}}
|
575
834
|
content={
|
576
835
|
<MenuContent>
|
836
|
+
<MenuContentItem onClick={goToQuerySetup}>
|
837
|
+
Back to query setup
|
838
|
+
</MenuContentItem>
|
577
839
|
<MenuContentItem
|
578
840
|
disabled={!appDocUrl}
|
579
841
|
onClick={goToDocumentation}
|
580
842
|
>
|
581
843
|
See Documentation
|
582
844
|
</MenuContentItem>
|
583
|
-
<MenuContentItem onClick={goToQuerySetup}>
|
584
|
-
Back to query setup
|
585
|
-
</MenuContentItem>
|
586
845
|
<MenuContentDivider />
|
587
846
|
<MenuContentItem disabled={true}>Settings</MenuContentItem>
|
588
847
|
<MenuContentItem
|
@@ -40,7 +40,11 @@ import {
|
|
40
40
|
QuerySetupLandingPageStore,
|
41
41
|
type BaseQuerySetupStore,
|
42
42
|
} from '../stores/QuerySetupStore.js';
|
43
|
-
import
|
43
|
+
import {
|
44
|
+
MASTER_SNAPSHOT_ALIAS,
|
45
|
+
SNAPSHOT_VERSION_ALIAS,
|
46
|
+
type StoreProjectData,
|
47
|
+
} from '@finos/legend-server-depot';
|
44
48
|
import { useApplicationStore } from '@finos/legend-application';
|
45
49
|
import { useLegendQueryApplicationStore } from './LegendQueryFrameworkProvider.js';
|
46
50
|
import type { QuerySetupActionConfiguration } from '../stores/LegendQueryApplicationPlugin.js';
|
@@ -54,10 +58,18 @@ export const buildProjectOption = (
|
|
54
58
|
});
|
55
59
|
|
56
60
|
export type VersionOption = { label: string; value: string };
|
57
|
-
export const buildVersionOption = (version: string): VersionOption =>
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
+
export const buildVersionOption = (version: string): VersionOption => {
|
62
|
+
if (version === MASTER_SNAPSHOT_ALIAS) {
|
63
|
+
return {
|
64
|
+
label: SNAPSHOT_VERSION_ALIAS,
|
65
|
+
value: version,
|
66
|
+
};
|
67
|
+
}
|
68
|
+
return {
|
69
|
+
label: version,
|
70
|
+
value: version,
|
71
|
+
};
|
72
|
+
};
|
61
73
|
|
62
74
|
const QuerySetupLandingPageStoreContext = createContext<
|
63
75
|
QuerySetupLandingPageStore | undefined
|
package/src/index.ts
CHANGED
@@ -19,7 +19,10 @@ import type { Query } from '@finos/legend-graph';
|
|
19
19
|
import type { QueryBuilderState } from '@finos/legend-query-builder';
|
20
20
|
import type React from 'react';
|
21
21
|
import type { LegendQueryPluginManager } from '../application/LegendQueryPluginManager.js';
|
22
|
-
import type {
|
22
|
+
import type {
|
23
|
+
ExistingQueryEditorStore,
|
24
|
+
QueryEditorStore,
|
25
|
+
} from './QueryEditorStore.js';
|
23
26
|
import type { QuerySetupLandingPageStore } from './QuerySetupStore.js';
|
24
27
|
|
25
28
|
export enum QuerySetupActionTag {
|
@@ -53,14 +56,21 @@ export type ExistingQueryEditorStateBuilder = (
|
|
53
56
|
editorStore: ExistingQueryEditorStore,
|
54
57
|
) => QueryBuilderState | undefined;
|
55
58
|
|
56
|
-
export type
|
59
|
+
export type QueryEditorActionConfiguration = {
|
57
60
|
key: string;
|
58
61
|
renderer: (
|
59
|
-
editorStore:
|
62
|
+
editorStore: QueryEditorStore,
|
60
63
|
queryBuilderState: QueryBuilderState,
|
61
64
|
) => React.ReactNode | undefined;
|
62
65
|
};
|
63
66
|
|
67
|
+
export type QueryEditorHelpMenuEntry = {
|
68
|
+
title?: string;
|
69
|
+
label: string;
|
70
|
+
onClick: () => void;
|
71
|
+
icon?: React.ReactNode;
|
72
|
+
};
|
73
|
+
|
64
74
|
export abstract class LegendQueryApplicationPlugin extends LegendApplicationPlugin {
|
65
75
|
/**
|
66
76
|
* This helps to better type-check for this empty abtract type
|
@@ -77,13 +87,20 @@ export abstract class LegendQueryApplicationPlugin extends LegendApplicationPlug
|
|
77
87
|
*/
|
78
88
|
getExtraQuerySetupActionConfigurations?(): QuerySetupActionConfiguration[];
|
79
89
|
|
90
|
+
/**
|
91
|
+
* Get the list of help items for query.
|
92
|
+
*/
|
93
|
+
getExtraQueryEditorHelpMenuEntries?(): QueryEditorHelpMenuEntry[];
|
94
|
+
|
80
95
|
/**
|
81
96
|
* Get the list of existing query editor state builders.
|
82
97
|
*/
|
83
98
|
getExtraExistingQueryEditorStateBuilders?(): ExistingQueryEditorStateBuilder[];
|
84
99
|
|
85
100
|
/**
|
86
|
-
* Get the list of
|
101
|
+
* Get the list of query editor action renderer configurations.
|
87
102
|
*/
|
88
|
-
|
103
|
+
getExtraQueryEditorActionConfigurations?(
|
104
|
+
editorStore: QueryEditorStore,
|
105
|
+
): QueryEditorActionConfiguration[];
|
89
106
|
}
|