@finos/legend-application 7.2.0 → 8.0.0
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/components/ActionAlert.js +2 -1
- package/lib/components/ActionAlert.js.map +1 -1
- package/lib/components/ApplicationStoreProvider.d.ts +3 -3
- package/lib/components/ApplicationStoreProvider.d.ts.map +1 -1
- package/lib/components/ApplicationStoreProviderTestUtils.d.ts +1 -1
- package/lib/components/ApplicationStoreProviderTestUtils.js.map +1 -1
- package/lib/components/VirtualAssistant.d.ts.map +1 -1
- package/lib/components/VirtualAssistant.js +21 -12
- package/lib/components/VirtualAssistant.js.map +1 -1
- package/lib/components/shared/CustomDatePicker.d.ts.map +1 -1
- package/lib/components/shared/CustomDatePicker.js +31 -9
- package/lib/components/shared/CustomDatePicker.js.map +1 -1
- package/lib/components/shared/TextSearchAdvancedConfigMenu.d.ts +22 -0
- package/lib/components/shared/TextSearchAdvancedConfigMenu.d.ts.map +1 -0
- package/lib/components/shared/TextSearchAdvancedConfigMenu.js +37 -0
- package/lib/components/shared/TextSearchAdvancedConfigMenu.js.map +1 -0
- package/lib/index.css +2 -2
- 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/stores/ApplicationStore.d.ts +4 -4
- package/lib/stores/ApplicationStore.d.ts.map +1 -1
- package/lib/stores/ApplicationStore.js +7 -4
- package/lib/stores/ApplicationStore.js.map +1 -1
- package/lib/stores/ApplicationStoreTestUtils.d.ts +1 -1
- package/lib/stores/ApplicationStoreTestUtils.js.map +1 -1
- package/lib/stores/ApplicationTelemetry.d.ts +5 -0
- package/lib/stores/ApplicationTelemetry.d.ts.map +1 -1
- package/lib/stores/ApplicationTelemetry.js.map +1 -1
- package/lib/stores/AssistantService.d.ts +10 -2
- package/lib/stores/AssistantService.d.ts.map +1 -1
- package/lib/stores/AssistantService.js +55 -4
- package/lib/stores/AssistantService.js.map +1 -1
- package/lib/stores/LegendApplicationDocumentation.d.ts +19 -0
- package/lib/stores/LegendApplicationDocumentation.d.ts.map +1 -0
- package/lib/stores/LegendApplicationDocumentation.js +20 -0
- package/lib/stores/LegendApplicationDocumentation.js.map +1 -0
- package/lib/stores/PureLanguageSupport.js +3 -3
- package/lib/stores/PureLanguageSupport.js.map +1 -1
- package/lib/stores/shared/LambdaParameterState.d.ts +6 -2
- package/lib/stores/shared/LambdaParameterState.d.ts.map +1 -1
- package/lib/stores/shared/LambdaParameterState.js +26 -2
- package/lib/stores/shared/LambdaParameterState.js.map +1 -1
- package/lib/stores/shared/TextSearchAdvancedConfigState.d.ts +30 -0
- package/lib/stores/shared/TextSearchAdvancedConfigState.d.ts.map +1 -0
- package/lib/stores/shared/TextSearchAdvancedConfigState.js +59 -0
- package/lib/stores/shared/TextSearchAdvancedConfigState.js.map +1 -0
- package/package.json +9 -9
- package/src/components/ActionAlert.tsx +1 -1
- package/src/components/ApplicationStoreProvider.tsx +3 -3
- package/src/components/ApplicationStoreProviderTestUtils.tsx +2 -2
- package/src/components/VirtualAssistant.tsx +127 -76
- package/src/components/shared/CustomDatePicker.tsx +40 -2
- package/src/components/shared/TextSearchAdvancedConfigMenu.tsx +73 -0
- package/src/index.ts +3 -0
- package/src/stores/ApplicationStore.ts +10 -11
- package/src/stores/ApplicationStoreTestUtils.ts +2 -2
- package/src/stores/ApplicationTelemetry.ts +5 -0
- package/src/stores/AssistantService.ts +69 -4
- package/src/stores/LegendApplicationDocumentation.ts +19 -0
- package/src/stores/PureLanguageSupport.ts +3 -3
- package/src/stores/shared/LambdaParameterState.ts +33 -3
- package/src/stores/shared/TextSearchAdvancedConfigState.ts +65 -0
- package/tsconfig.json +3 -0
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
PanelLoadingIndicator,
|
|
37
37
|
BasePopover,
|
|
38
38
|
FaceSadTearIcon,
|
|
39
|
+
CogIcon,
|
|
39
40
|
} from '@finos/legend-art';
|
|
40
41
|
import {
|
|
41
42
|
ContentType,
|
|
@@ -56,6 +57,7 @@ import { useApplicationStore } from './ApplicationStoreProvider.js';
|
|
|
56
57
|
import Draggable from 'react-draggable';
|
|
57
58
|
import { DATE_TIME_FORMAT } from '@finos/legend-graph';
|
|
58
59
|
import { ApplicationTelemetry } from '../stores/ApplicationTelemetry.js';
|
|
60
|
+
import { TextSearchAdvancedConfigMenu } from './shared/TextSearchAdvancedConfigMenu.js';
|
|
59
61
|
|
|
60
62
|
const WIZARD_GREETING = `Bonjour, It's Pierre!`;
|
|
61
63
|
|
|
@@ -222,6 +224,7 @@ const VirtualAssistantContextualSupportPanel = observer(() => {
|
|
|
222
224
|
)}
|
|
223
225
|
</>
|
|
224
226
|
)}
|
|
227
|
+
|
|
225
228
|
{contextualEntry.related.length && (
|
|
226
229
|
<div className="virtual-assistant__contextual-support__relevant-entries">
|
|
227
230
|
<div className="virtual-assistant__contextual-support__relevant-entries__title">
|
|
@@ -245,8 +248,8 @@ const VirtualAssistantContextualSupportPanel = observer(() => {
|
|
|
245
248
|
No contextual documentation found!
|
|
246
249
|
</div>
|
|
247
250
|
<div className="virtual-assistant__panel__placeholder__instruction">
|
|
248
|
-
Keep using the app
|
|
249
|
-
know!
|
|
251
|
+
Keep using the app. When contextual help is available, we will let
|
|
252
|
+
you know!
|
|
250
253
|
</div>
|
|
251
254
|
</div>
|
|
252
255
|
</BlankPanelContent>
|
|
@@ -258,7 +261,10 @@ const VirtualAssistantContextualSupportPanel = observer(() => {
|
|
|
258
261
|
const VirtualAssistantSearchPanel = observer(() => {
|
|
259
262
|
const applicationStore = useApplicationStore();
|
|
260
263
|
const searchInputRef = useRef<HTMLInputElement>(null);
|
|
264
|
+
const searchConfigButtonRef = useRef<HTMLButtonElement>(null);
|
|
261
265
|
const assistantService = applicationStore.assistantService;
|
|
266
|
+
|
|
267
|
+
// search text
|
|
262
268
|
const searchText = assistantService.searchText;
|
|
263
269
|
const debouncedSearch = useMemo(
|
|
264
270
|
() => debounce(() => assistantService.search(), 100),
|
|
@@ -272,13 +278,10 @@ const VirtualAssistantSearchPanel = observer(() => {
|
|
|
272
278
|
};
|
|
273
279
|
const clearSearchText = (): void => {
|
|
274
280
|
assistantService.resetSearch();
|
|
281
|
+
assistantService.currentDocumentationEntry = undefined;
|
|
275
282
|
searchInputRef.current?.focus();
|
|
276
283
|
};
|
|
277
|
-
|
|
278
|
-
const resultCount =
|
|
279
|
-
assistantService.searchResults.length > 99
|
|
280
|
-
? '99+'
|
|
281
|
-
: assistantService.searchResults.length;
|
|
284
|
+
|
|
282
285
|
const downloadDocRegistry = (): void => {
|
|
283
286
|
downloadFileUsingDataURI(
|
|
284
287
|
`documentation-registry_${format(
|
|
@@ -307,6 +310,10 @@ const VirtualAssistantSearchPanel = observer(() => {
|
|
|
307
310
|
ContentType.APPLICATION_JSON,
|
|
308
311
|
);
|
|
309
312
|
};
|
|
313
|
+
const toggleSearchConfigMenu = (): void =>
|
|
314
|
+
assistantService.setShowSearchConfigurationMenu(
|
|
315
|
+
!assistantService.showSearchConfigurationMenu,
|
|
316
|
+
);
|
|
310
317
|
|
|
311
318
|
useEffect(() => {
|
|
312
319
|
searchInputRef.current?.focus();
|
|
@@ -351,94 +358,138 @@ const VirtualAssistantSearchPanel = observer(() => {
|
|
|
351
358
|
className={clsx('virtual-assistant__search__input input--dark', {
|
|
352
359
|
'virtual-assistant__search__input--searching': searchText,
|
|
353
360
|
})}
|
|
361
|
+
spellCheck={false}
|
|
354
362
|
onChange={onSearchTextChange}
|
|
355
363
|
value={searchText}
|
|
356
364
|
placeholder="Ask me a question"
|
|
357
365
|
/>
|
|
366
|
+
{searchText && (
|
|
367
|
+
<div className="virtual-assistant__search__input__search__count">
|
|
368
|
+
{assistantService.searchResults.length +
|
|
369
|
+
(assistantService.isOverSearchLimit ? '+' : '')}
|
|
370
|
+
</div>
|
|
371
|
+
)}
|
|
372
|
+
<button
|
|
373
|
+
ref={searchConfigButtonRef}
|
|
374
|
+
className={clsx('virtual-assistant__search__input__config__trigger', {
|
|
375
|
+
'virtual-assistant__search__input__config__trigger--toggled':
|
|
376
|
+
assistantService.showSearchConfigurationMenu,
|
|
377
|
+
'virtual-assistant__search__input__config__trigger--active':
|
|
378
|
+
assistantService.searchConfigurationState.isAdvancedSearchActive,
|
|
379
|
+
})}
|
|
380
|
+
tabIndex={-1}
|
|
381
|
+
onClick={toggleSearchConfigMenu}
|
|
382
|
+
title={`${
|
|
383
|
+
assistantService.searchConfigurationState.isAdvancedSearchActive
|
|
384
|
+
? 'Advanced search is currently active\n'
|
|
385
|
+
: ''
|
|
386
|
+
}Click to toggle search config menu`}
|
|
387
|
+
>
|
|
388
|
+
<CogIcon />
|
|
389
|
+
</button>
|
|
358
390
|
{!searchText ? (
|
|
359
391
|
<div className="virtual-assistant__search__input__search__icon">
|
|
360
392
|
<SearchIcon />
|
|
361
393
|
</div>
|
|
362
394
|
) : (
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
title="Clear"
|
|
372
|
-
>
|
|
373
|
-
<TimesIcon />
|
|
374
|
-
</button>
|
|
375
|
-
</>
|
|
395
|
+
<button
|
|
396
|
+
className="virtual-assistant__search__input__clear-btn"
|
|
397
|
+
tabIndex={-1}
|
|
398
|
+
onClick={clearSearchText}
|
|
399
|
+
title="Clear"
|
|
400
|
+
>
|
|
401
|
+
<TimesIcon />
|
|
402
|
+
</button>
|
|
376
403
|
)}
|
|
377
404
|
</div>
|
|
378
405
|
<div className="virtual-assistant__search__content">
|
|
379
406
|
<PanelLoadingIndicator
|
|
380
407
|
isLoading={assistantService.searchState.isInProgress}
|
|
381
408
|
/>
|
|
382
|
-
{
|
|
409
|
+
{/* {assistantService.showSearchConfigurationMenu && ( */}
|
|
410
|
+
<div
|
|
411
|
+
className={clsx('virtual-assistant__search__input__config__panel', {
|
|
412
|
+
'virtual-assistant__search__input__config__panel--toggled':
|
|
413
|
+
assistantService.showSearchConfigurationMenu,
|
|
414
|
+
})}
|
|
415
|
+
>
|
|
416
|
+
<TextSearchAdvancedConfigMenu
|
|
417
|
+
configState={assistantService.searchConfigurationState}
|
|
418
|
+
/>
|
|
419
|
+
</div>
|
|
420
|
+
{/* )} */}
|
|
421
|
+
{assistantService.currentDocumentationEntry && (
|
|
383
422
|
<div className="virtual-assistant__search__results">
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
/>
|
|
389
|
-
))}
|
|
423
|
+
<VirtualAssistantDocumentationEntryViewer
|
|
424
|
+
key={assistantService.currentDocumentationEntry.uuid}
|
|
425
|
+
entry={assistantService.currentDocumentationEntry}
|
|
426
|
+
/>
|
|
390
427
|
</div>
|
|
391
428
|
)}
|
|
392
|
-
{
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
<
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
{/*
|
|
403
|
-
NOTE: technically, we don't need to check for the result size here.
|
|
404
|
-
However, since the search results update is slightly delayed compared to
|
|
405
|
-
the search text update, we do this to avoid showing the placeholder too
|
|
406
|
-
early, i.e. when the search results are not yet cleaned
|
|
407
|
-
*/}
|
|
408
|
-
{!searchText && !results.length && (
|
|
409
|
-
<ContextMenu
|
|
410
|
-
className="virtual-assistant__character__container"
|
|
411
|
-
menuProps={{
|
|
412
|
-
elevation: 7,
|
|
413
|
-
classes: {
|
|
414
|
-
root: 'virtual-assistant__context-menu',
|
|
415
|
-
},
|
|
416
|
-
}}
|
|
417
|
-
content={
|
|
418
|
-
<MenuContent>
|
|
419
|
-
<MenuContentItem onClick={downloadDocRegistry}>
|
|
420
|
-
Download documentation registry
|
|
421
|
-
</MenuContentItem>
|
|
422
|
-
<MenuContentItem onClick={downloadContextualDocIndex}>
|
|
423
|
-
Download contextual documentation mapping
|
|
424
|
-
</MenuContentItem>
|
|
425
|
-
</MenuContent>
|
|
426
|
-
}
|
|
427
|
-
>
|
|
428
|
-
<div className="virtual-assistant__character">
|
|
429
|
-
<div className="virtual-assistant__character__figure">
|
|
430
|
-
<WizardHatIcon className="virtual-assistant__character__hat" />
|
|
431
|
-
<SunglassesIcon className="virtual-assistant__character__glasses" />
|
|
432
|
-
<BeardIcon className="virtual-assistant__character__beard" />
|
|
433
|
-
</div>
|
|
434
|
-
<div className="virtual-assistant__character__greeting">
|
|
435
|
-
{WIZARD_GREETING}
|
|
436
|
-
</div>
|
|
437
|
-
<div className="virtual-assistant__character__question">
|
|
438
|
-
How can I help today?
|
|
429
|
+
{!assistantService.currentDocumentationEntry && (
|
|
430
|
+
<>
|
|
431
|
+
{Boolean(assistantService.searchResults.length) && (
|
|
432
|
+
<div className="virtual-assistant__search__results">
|
|
433
|
+
{assistantService.searchResults.map((result) => (
|
|
434
|
+
<VirtualAssistantDocumentationEntryViewer
|
|
435
|
+
key={result.uuid}
|
|
436
|
+
entry={result}
|
|
437
|
+
/>
|
|
438
|
+
))}
|
|
439
439
|
</div>
|
|
440
|
-
|
|
441
|
-
|
|
440
|
+
)}
|
|
441
|
+
{searchText && !assistantService.searchResults.length && (
|
|
442
|
+
<BlankPanelContent>
|
|
443
|
+
<div className="virtual-assistant__panel__placeholder">
|
|
444
|
+
<FaceSadTearIcon className="virtual-assistant__panel__placeholder__icon" />
|
|
445
|
+
<div className="virtual-assistant__panel__placeholder__message">
|
|
446
|
+
No result...
|
|
447
|
+
</div>
|
|
448
|
+
</div>
|
|
449
|
+
</BlankPanelContent>
|
|
450
|
+
)}
|
|
451
|
+
{/*
|
|
452
|
+
NOTE: technically, we don't need to check for the result size here.
|
|
453
|
+
However, since the search results update is slightly delayed compared to
|
|
454
|
+
the search text update, we do this to avoid showing the placeholder too
|
|
455
|
+
early, i.e. when the search results are not yet cleaned
|
|
456
|
+
*/}
|
|
457
|
+
{!searchText && !assistantService.searchResults.length && (
|
|
458
|
+
<ContextMenu
|
|
459
|
+
className="virtual-assistant__character__container"
|
|
460
|
+
menuProps={{
|
|
461
|
+
elevation: 7,
|
|
462
|
+
classes: {
|
|
463
|
+
root: 'virtual-assistant__context-menu',
|
|
464
|
+
},
|
|
465
|
+
}}
|
|
466
|
+
content={
|
|
467
|
+
<MenuContent>
|
|
468
|
+
<MenuContentItem onClick={downloadDocRegistry}>
|
|
469
|
+
Download documentation registry
|
|
470
|
+
</MenuContentItem>
|
|
471
|
+
<MenuContentItem onClick={downloadContextualDocIndex}>
|
|
472
|
+
Download contextual documentation mapping
|
|
473
|
+
</MenuContentItem>
|
|
474
|
+
</MenuContent>
|
|
475
|
+
}
|
|
476
|
+
>
|
|
477
|
+
<div className="virtual-assistant__character">
|
|
478
|
+
<div className="virtual-assistant__character__figure">
|
|
479
|
+
<WizardHatIcon className="virtual-assistant__character__hat" />
|
|
480
|
+
<SunglassesIcon className="virtual-assistant__character__glasses" />
|
|
481
|
+
<BeardIcon className="virtual-assistant__character__beard" />
|
|
482
|
+
</div>
|
|
483
|
+
<div className="virtual-assistant__character__greeting">
|
|
484
|
+
{WIZARD_GREETING}
|
|
485
|
+
</div>
|
|
486
|
+
<div className="virtual-assistant__character__question">
|
|
487
|
+
How can I help today?
|
|
488
|
+
</div>
|
|
489
|
+
</div>
|
|
490
|
+
</ContextMenu>
|
|
491
|
+
)}
|
|
492
|
+
</>
|
|
442
493
|
)}
|
|
443
494
|
</div>
|
|
444
495
|
</div>
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
|
+
type SelectComponent,
|
|
18
19
|
BasePopover,
|
|
19
20
|
BaseRadioGroup,
|
|
20
21
|
CustomSelectorInput,
|
|
@@ -41,9 +42,11 @@ import {
|
|
|
41
42
|
} from '@finos/legend-graph';
|
|
42
43
|
import {
|
|
43
44
|
guaranteeNonNullable,
|
|
45
|
+
parseNumber,
|
|
46
|
+
returnUndefOnError,
|
|
44
47
|
UnsupportedOperationError,
|
|
45
48
|
} from '@finos/legend-shared';
|
|
46
|
-
import { useEffect, useState } from 'react';
|
|
49
|
+
import { useEffect, useRef, useState } from 'react';
|
|
47
50
|
import {
|
|
48
51
|
genericType_setRawType,
|
|
49
52
|
instanceValue_changeValue,
|
|
@@ -682,6 +685,7 @@ const AbsoluteDateValueSpecificationEditor: React.FC<{
|
|
|
682
685
|
setValueSpecification,
|
|
683
686
|
setDatePickerOption,
|
|
684
687
|
} = props;
|
|
688
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
685
689
|
const absoluteDateValue =
|
|
686
690
|
valueSpecification instanceof SimpleFunctionExpression
|
|
687
691
|
? ''
|
|
@@ -717,9 +721,15 @@ const AbsoluteDateValueSpecificationEditor: React.FC<{
|
|
|
717
721
|
),
|
|
718
722
|
);
|
|
719
723
|
};
|
|
724
|
+
|
|
725
|
+
useEffect(() => {
|
|
726
|
+
inputRef.current?.focus();
|
|
727
|
+
}, []);
|
|
728
|
+
|
|
720
729
|
return (
|
|
721
730
|
<div className="value-spec-editor__date-picker__absolute-date">
|
|
722
731
|
<input
|
|
732
|
+
ref={inputRef}
|
|
723
733
|
className="panel__content__form__section__input value-spec-editor__date-picker__absolute-date__input input--dark"
|
|
724
734
|
type="date"
|
|
725
735
|
spellCheck={false}
|
|
@@ -742,6 +752,7 @@ const AbsoluteTimeValueSpecificationEditor: React.FC<{
|
|
|
742
752
|
setValueSpecification,
|
|
743
753
|
setDatePickerOption,
|
|
744
754
|
} = props;
|
|
755
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
745
756
|
const absoluteTimeValue =
|
|
746
757
|
valueSpecification instanceof SimpleFunctionExpression
|
|
747
758
|
? ''
|
|
@@ -777,9 +788,15 @@ const AbsoluteTimeValueSpecificationEditor: React.FC<{
|
|
|
777
788
|
),
|
|
778
789
|
);
|
|
779
790
|
};
|
|
791
|
+
|
|
792
|
+
useEffect(() => {
|
|
793
|
+
inputRef.current?.focus();
|
|
794
|
+
}, []);
|
|
795
|
+
|
|
780
796
|
return (
|
|
781
797
|
<div className="value-spec-editor__date-picker__absolute-date">
|
|
782
798
|
<input
|
|
799
|
+
ref={inputRef}
|
|
783
800
|
className="panel__content__form__section__input value-spec-editor__date-picker__absolute-date__input input--dark"
|
|
784
801
|
// Despite its name this would actually allow us to register time in UTC
|
|
785
802
|
// See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local#setting_timezones
|
|
@@ -804,6 +821,7 @@ const CustomDateInstanceValueEditor: React.FC<{
|
|
|
804
821
|
setValueSpecification,
|
|
805
822
|
setDatePickerOption,
|
|
806
823
|
} = props;
|
|
824
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
807
825
|
const [durationValue, setDurationValue] = useState(
|
|
808
826
|
customDateOptionValue.duration,
|
|
809
827
|
);
|
|
@@ -859,15 +877,22 @@ const CustomDateInstanceValueEditor: React.FC<{
|
|
|
859
877
|
event,
|
|
860
878
|
) => {
|
|
861
879
|
const duration =
|
|
862
|
-
event.target.value !== ''
|
|
880
|
+
event.target.value !== ''
|
|
881
|
+
? returnUndefOnError(() => parseNumber(event.target.value)) ?? 0
|
|
882
|
+
: 0;
|
|
863
883
|
setDurationValue(duration);
|
|
864
884
|
changeValue(duration, unitValue, directionValue, referenceMomentValue);
|
|
865
885
|
};
|
|
866
886
|
|
|
887
|
+
useEffect(() => {
|
|
888
|
+
inputRef.current?.focus();
|
|
889
|
+
}, []);
|
|
890
|
+
|
|
867
891
|
return (
|
|
868
892
|
<div className="value-spec-editor__date-picker__custom-date">
|
|
869
893
|
<div className="value-spec-editor__date-picker__custom-date__input">
|
|
870
894
|
<input
|
|
895
|
+
ref={inputRef}
|
|
871
896
|
className="value-spec-editor__date-picker__custom-date__input-text-editor input--dark"
|
|
872
897
|
spellCheck={false}
|
|
873
898
|
value={durationValue}
|
|
@@ -958,6 +983,7 @@ const CustomFirstDayOfValueSpecificationEditor: React.FC<{
|
|
|
958
983
|
setValueSpecification,
|
|
959
984
|
setDatePickerOption,
|
|
960
985
|
} = props;
|
|
986
|
+
const selectorRef = useRef<SelectComponent>(null);
|
|
961
987
|
const [unitValue, setUnitValue] = useState(
|
|
962
988
|
customDateAdjustOptionValue instanceof CustomFirstDayOfOption
|
|
963
989
|
? (customDateAdjustOptionValue.unit as string)
|
|
@@ -982,10 +1008,15 @@ const CustomFirstDayOfValueSpecificationEditor: React.FC<{
|
|
|
982
1008
|
}
|
|
983
1009
|
};
|
|
984
1010
|
|
|
1011
|
+
useEffect(() => {
|
|
1012
|
+
selectorRef.current?.focus();
|
|
1013
|
+
}, []);
|
|
1014
|
+
|
|
985
1015
|
return (
|
|
986
1016
|
<div className="value-spec-editor__date-picker__custom-date">
|
|
987
1017
|
<div className="value-spec-editor__date-picker__custom-date__input">
|
|
988
1018
|
<CustomSelectorInput
|
|
1019
|
+
ref={selectorRef}
|
|
989
1020
|
placeholder="Choose a unit..."
|
|
990
1021
|
className="value-spec-editor__date-picker__custom-date__input-dropdown value-spec-editor__date-picker__custom-date__input-dropdown--full"
|
|
991
1022
|
options={Object.values(CUSTOM_DATE_FIRST_DAY_OF_UNIT).map((t) => ({
|
|
@@ -1018,6 +1049,7 @@ const CustomPreviousDayOfWeekValueSpecificationEditor: React.FC<{
|
|
|
1018
1049
|
setValueSpecification,
|
|
1019
1050
|
setDatePickerOption,
|
|
1020
1051
|
} = props;
|
|
1052
|
+
const selectorRef = useRef<SelectComponent>(null);
|
|
1021
1053
|
const [dayOfWeekValue, setDayOfWeekValue] = useState(
|
|
1022
1054
|
customDateAdjustOptionValue instanceof CustomPreviousDayOfWeekOption
|
|
1023
1055
|
? (customDateAdjustOptionValue.day as string)
|
|
@@ -1036,10 +1068,15 @@ const CustomPreviousDayOfWeekValueSpecificationEditor: React.FC<{
|
|
|
1036
1068
|
}
|
|
1037
1069
|
};
|
|
1038
1070
|
|
|
1071
|
+
useEffect(() => {
|
|
1072
|
+
selectorRef.current?.focus();
|
|
1073
|
+
}, []);
|
|
1074
|
+
|
|
1039
1075
|
return (
|
|
1040
1076
|
<div className="value-spec-editor__date-picker__custom-date">
|
|
1041
1077
|
<div className="value-spec-editor__date-picker__custom-date__input">
|
|
1042
1078
|
<CustomSelectorInput
|
|
1079
|
+
ref={selectorRef}
|
|
1043
1080
|
placeholder="Choose a day..."
|
|
1044
1081
|
className="value-spec-editor__date-picker__custom-date__input-dropdown value-spec-editor__date-picker__custom-date__input-dropdown--full"
|
|
1045
1082
|
options={Object.values(CUSTOM_DATE_DAY_OF_WEEK).map((t) => ({
|
|
@@ -1241,6 +1278,7 @@ export const CustomDatePicker: React.FC<{
|
|
|
1241
1278
|
}}
|
|
1242
1279
|
>
|
|
1243
1280
|
<BaseRadioGroup
|
|
1281
|
+
className="value-spec-editor__date-picker__options"
|
|
1244
1282
|
value={datePickerOption.value}
|
|
1245
1283
|
onChange={handleDatePickerOptionChange}
|
|
1246
1284
|
row={true}
|
|
@@ -0,0 +1,73 @@
|
|
|
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 { BaseRadioGroup, InfoCircleIcon } from '@finos/legend-art';
|
|
18
|
+
import { observer } from 'mobx-react-lite';
|
|
19
|
+
import { LEGEND_APPLICATION_DOCUMENTATION_KEY } from '../../stores/LegendApplicationDocumentation.js';
|
|
20
|
+
import {
|
|
21
|
+
ADVANCED_TEXT_SEARCH_MODE,
|
|
22
|
+
type TextSearchAdvancedConfigState,
|
|
23
|
+
} from '../../stores/shared/TextSearchAdvancedConfigState.js';
|
|
24
|
+
import { useApplicationStore } from '../ApplicationStoreProvider.js';
|
|
25
|
+
|
|
26
|
+
export const TextSearchAdvancedConfigMenu = observer(
|
|
27
|
+
(props: { configState: TextSearchAdvancedConfigState }) => {
|
|
28
|
+
const { configState } = props;
|
|
29
|
+
const applicationStore = useApplicationStore();
|
|
30
|
+
|
|
31
|
+
const handleSearchMode: React.ChangeEventHandler<HTMLInputElement> = (
|
|
32
|
+
event,
|
|
33
|
+
): void => {
|
|
34
|
+
const searchMode = event.target.value as ADVANCED_TEXT_SEARCH_MODE;
|
|
35
|
+
configState.setCurrentMode(searchMode);
|
|
36
|
+
};
|
|
37
|
+
const seeDocumentation = (): void =>
|
|
38
|
+
applicationStore.assistantService.openDocumentationEntry(
|
|
39
|
+
LEGEND_APPLICATION_DOCUMENTATION_KEY.QUESTION_HOW_TO_USE_ADVANCED_SEARCH_SYNTAX,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="text-search-advanced-config__panel">
|
|
44
|
+
<div className="text-search-advanced-config__panel__header__label">
|
|
45
|
+
search config
|
|
46
|
+
<button
|
|
47
|
+
className="text-search-advanced-config__panel__header__hint"
|
|
48
|
+
tabIndex={-1}
|
|
49
|
+
onClick={seeDocumentation}
|
|
50
|
+
title="Click to see more details on advanced search"
|
|
51
|
+
>
|
|
52
|
+
<InfoCircleIcon />
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
<div>
|
|
56
|
+
<BaseRadioGroup
|
|
57
|
+
className="text-search-advanced-config__options"
|
|
58
|
+
value={configState.currentMode}
|
|
59
|
+
onChange={handleSearchMode}
|
|
60
|
+
row={false}
|
|
61
|
+
options={[
|
|
62
|
+
ADVANCED_TEXT_SEARCH_MODE.STANDARD,
|
|
63
|
+
ADVANCED_TEXT_SEARCH_MODE.INCLUDE,
|
|
64
|
+
ADVANCED_TEXT_SEARCH_MODE.EXACT,
|
|
65
|
+
ADVANCED_TEXT_SEARCH_MODE.INVERSE,
|
|
66
|
+
]}
|
|
67
|
+
size={1}
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
},
|
|
73
|
+
);
|
package/src/index.ts
CHANGED
|
@@ -39,6 +39,9 @@ export * from './stores/AssistantService.js';
|
|
|
39
39
|
export * from './stores/ApplicationNavigationContextService.js';
|
|
40
40
|
export * from './stores/LegendApplicationPlugin.js';
|
|
41
41
|
|
|
42
|
+
export * from './components/shared/TextSearchAdvancedConfigMenu.js';
|
|
43
|
+
export * from './stores/shared/TextSearchAdvancedConfigState.js';
|
|
44
|
+
|
|
42
45
|
export * from './stores/ApplicationStoreTestUtils.js';
|
|
43
46
|
|
|
44
47
|
// ------------------------------------------- Shared components -------------------------------------------
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
isString,
|
|
26
26
|
ApplicationError,
|
|
27
27
|
} from '@finos/legend-shared';
|
|
28
|
-
import {
|
|
28
|
+
import { action, makeObservable, observable } from 'mobx';
|
|
29
29
|
import { APPLICATION_EVENT } from './ApplicationEvent.js';
|
|
30
30
|
import type { LegendApplicationConfig } from '../application/LegendApplicationConfig.js';
|
|
31
31
|
import type { WebApplicationNavigator } from './WebApplicationNavigator.js';
|
|
@@ -105,15 +105,15 @@ export class Notification {
|
|
|
105
105
|
|
|
106
106
|
export type GenericLegendApplicationStore = ApplicationStore<
|
|
107
107
|
LegendApplicationConfig,
|
|
108
|
-
LegendApplicationPlugin
|
|
108
|
+
LegendApplicationPluginManager<LegendApplicationPlugin>
|
|
109
109
|
>;
|
|
110
110
|
|
|
111
111
|
export class ApplicationStore<
|
|
112
112
|
T extends LegendApplicationConfig,
|
|
113
|
-
V extends LegendApplicationPlugin
|
|
113
|
+
V extends LegendApplicationPluginManager<LegendApplicationPlugin>,
|
|
114
114
|
> {
|
|
115
|
-
pluginManager: LegendApplicationPluginManager<V>;
|
|
116
115
|
config: T;
|
|
116
|
+
pluginManager: V;
|
|
117
117
|
|
|
118
118
|
// navigation
|
|
119
119
|
navigator: WebApplicationNavigator;
|
|
@@ -144,13 +144,12 @@ export class ApplicationStore<
|
|
|
144
144
|
*/
|
|
145
145
|
TEMPORARY__isLightThemeEnabled = false;
|
|
146
146
|
|
|
147
|
-
constructor(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
navigator: false,
|
|
147
|
+
constructor(config: T, navigator: WebApplicationNavigator, pluginManager: V) {
|
|
148
|
+
makeObservable(this, {
|
|
149
|
+
notification: observable,
|
|
150
|
+
blockingAlertInfo: observable,
|
|
151
|
+
actionAlertInfo: observable,
|
|
152
|
+
TEMPORARY__isLightThemeEnabled: observable,
|
|
154
153
|
setBlockingAlert: action,
|
|
155
154
|
setActionAlertInfo: action,
|
|
156
155
|
setNotification: action,
|
|
@@ -52,10 +52,10 @@ export const TEST__getGenericApplicationConfig = (
|
|
|
52
52
|
|
|
53
53
|
export const TEST__getTestApplicationStore = <
|
|
54
54
|
T extends LegendApplicationConfig,
|
|
55
|
-
V extends LegendApplicationPlugin
|
|
55
|
+
V extends LegendApplicationPluginManager<LegendApplicationPlugin>,
|
|
56
56
|
>(
|
|
57
57
|
config: T,
|
|
58
|
-
pluginManager:
|
|
58
|
+
pluginManager: V,
|
|
59
59
|
): ApplicationStore<T, V> =>
|
|
60
60
|
new ApplicationStore(
|
|
61
61
|
config,
|
|
@@ -18,6 +18,11 @@ import type { TelemetryService } from '@finos/legend-shared';
|
|
|
18
18
|
import { APPLICATION_EVENT } from './ApplicationEvent.js';
|
|
19
19
|
|
|
20
20
|
type ApplicationLoaded_TelemetryData = {
|
|
21
|
+
application: {
|
|
22
|
+
name: string;
|
|
23
|
+
version: string;
|
|
24
|
+
env: string;
|
|
25
|
+
};
|
|
21
26
|
browser: {
|
|
22
27
|
userAgent: string;
|
|
23
28
|
};
|