@sapui5/sap.fe.controls 1.147.0 → 1.148.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/package.json +1 -1
- package/src/sap/fe/controls/.library +1 -1
- package/src/sap/fe/controls/AiNoticeHelper.js +26 -5
- package/src/sap/fe/controls/AiNoticeHelper.tsx +31 -3
- package/src/sap/fe/controls/easyFilter/EasyFilterBarContainer.js +278 -38
- package/src/sap/fe/controls/easyFilter/EasyFilterBarContainer.tsx +284 -21
- package/src/sap/fe/controls/easyFilter/EasyFilterInput.js +65 -6
- package/src/sap/fe/controls/easyFilter/EasyFilterInput.tsx +77 -7
- package/src/sap/fe/controls/easyFilter/ErrorMessageHandler.js +20 -2
- package/src/sap/fe/controls/easyFilter/ErrorMessageHandler.ts +22 -0
- package/src/sap/fe/controls/easyFilter/utils.js +14 -2
- package/src/sap/fe/controls/easyFilter/utils.ts +11 -1
- package/src/sap/fe/controls/library.js +1 -1
- package/src/sap/fe/controls/messagebundle.properties +17 -3
- package/src/sap/fe/controls/messagebundle_de.properties +1 -1
- package/src/sap/fe/controls/messagebundle_en_US_saprigi.properties +3 -0
- package/src/sap/fe/controls/themes/base/EasyFill.less +25 -1
- package/src/sap/fe/controls/themes/base/EasyFilter.less +8 -4
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Log from "sap/base/Log";
|
|
2
|
+
import encodeXML from "sap/base/security/encodeXML";
|
|
2
3
|
import type { EnhanceWithUI5, StateOf } from "sap/fe/base/ClassSupport";
|
|
3
4
|
import {
|
|
4
5
|
aggregation,
|
|
@@ -50,6 +51,7 @@ import type EasyFilter from "ux/eng/fioriai/reuse/easyfilter/EasyFilter";
|
|
|
50
51
|
import type { EasyFilterMetadata, EasyFilterResult, PropertyMetadata } from "ux/eng/fioriai/reuse/easyfilter/EasyFilter";
|
|
51
52
|
import type { Success } from "ux/eng/fioriai/reuse/shared";
|
|
52
53
|
import type { EventHandler } from "../../../../../../../types/extension_types";
|
|
54
|
+
import ErrorMessageHandler from "./ErrorMessageHandler";
|
|
53
55
|
import { triggerPXIntegration } from "./PXFeedback";
|
|
54
56
|
import EasyFilterUtils from "./utils";
|
|
55
57
|
|
|
@@ -111,8 +113,17 @@ export type NonValueHelpTokenDefinition = {
|
|
|
111
113
|
|
|
112
114
|
export type TokenDefinition = ValueHelpTokenDefinition | NonValueHelpTokenDefinition;
|
|
113
115
|
|
|
116
|
+
export type SortDefinition = {
|
|
117
|
+
key: string;
|
|
118
|
+
descending: boolean;
|
|
119
|
+
};
|
|
120
|
+
|
|
114
121
|
export type TokenSetters = "setSelectedValues";
|
|
115
122
|
|
|
123
|
+
export type GroupLevelDefinition = {
|
|
124
|
+
key: string;
|
|
125
|
+
};
|
|
126
|
+
|
|
116
127
|
export type EasyFilterPropertyMetadata = PropertyMetadata &
|
|
117
128
|
(
|
|
118
129
|
| {
|
|
@@ -184,12 +195,25 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
184
195
|
@event()
|
|
185
196
|
tokensChanged?: EventHandler<UI5Event<{ tokens: TokenDefinition[]; reset: boolean }, EasyFilterBarContainer>>;
|
|
186
197
|
|
|
198
|
+
@event()
|
|
199
|
+
sortersChanged?: EventHandler<UI5Event<{ sorters: SortDefinition[] }, EasyFilterBarContainer>>;
|
|
200
|
+
|
|
201
|
+
@event()
|
|
202
|
+
groupLevelsChanged?: EventHandler<UI5Event<{ groupLevels: GroupLevelDefinition[] }, EasyFilterBarContainer>>;
|
|
203
|
+
|
|
187
204
|
@event()
|
|
188
205
|
queryChanged?: EventHandler<UI5Event<{ query: string }, EasyFilterBarContainer>>;
|
|
189
206
|
|
|
190
207
|
@event()
|
|
191
208
|
showValueHelp?: EventHandler<EasyFilterBarContainer$ShowValueHelpEvent>;
|
|
192
209
|
|
|
210
|
+
@event()
|
|
211
|
+
liveChange?: EventHandler<UI5Event<{ query: string }, EasyFilterBarContainer>>;
|
|
212
|
+
|
|
213
|
+
/** Fires when the user manually removes or edits a filter token. Does not fire when tokens are set by the AI search result. */
|
|
214
|
+
@event()
|
|
215
|
+
tokensChangedByUser?: EventHandler<UI5Event<{ tokens: TokenDefinition[] }, EasyFilterBarContainer>>;
|
|
216
|
+
|
|
193
217
|
@event()
|
|
194
218
|
clearFilters?: EventHandler;
|
|
195
219
|
|
|
@@ -205,6 +229,8 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
205
229
|
protected state: StateOf<{
|
|
206
230
|
showResult: boolean;
|
|
207
231
|
tokens: TokenDefinition[];
|
|
232
|
+
sorters: SortDefinition[];
|
|
233
|
+
groupLevels: GroupLevelDefinition[];
|
|
208
234
|
tokenizerEditable: boolean;
|
|
209
235
|
showSingleValueMessageStrip?: boolean;
|
|
210
236
|
singleValueMessageStripText?: string;
|
|
@@ -217,6 +243,8 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
217
243
|
}> = {
|
|
218
244
|
showResult: false,
|
|
219
245
|
tokens: [] as TokenDefinition[],
|
|
246
|
+
sorters: [] as SortDefinition[],
|
|
247
|
+
groupLevels: [] as GroupLevelDefinition[],
|
|
220
248
|
tokenizerEditable: true,
|
|
221
249
|
showSingleValueMessageStrip: false,
|
|
222
250
|
singleValueMessageStripText: "",
|
|
@@ -257,6 +285,10 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
257
285
|
|
|
258
286
|
private shouldMessageStripRemove = true;
|
|
259
287
|
|
|
288
|
+
private supportsSorting = true;
|
|
289
|
+
|
|
290
|
+
private supportsGrouping = true;
|
|
291
|
+
|
|
260
292
|
constructor(properties: string | ($ControlSettings & PropertiesOf<EasyFilterBarContainer>), others?: $ControlSettings) {
|
|
261
293
|
super(properties as string, others);
|
|
262
294
|
this.initialize();
|
|
@@ -275,7 +307,6 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
275
307
|
this.setProperty("appId", appId, true);
|
|
276
308
|
await this.inputFieldReady;
|
|
277
309
|
this.easyFilterInput.current?.setProperty("appId", appId, true);
|
|
278
|
-
await this.easyFilterInput.current?.initShellHistoryProvider();
|
|
279
310
|
}
|
|
280
311
|
}
|
|
281
312
|
|
|
@@ -405,6 +436,8 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
405
436
|
if (this.easyFilterInput.current?.isHistoryEnabled() ?? false) {
|
|
406
437
|
this.easyFilterInput.current?.addRecentQuery(magicQuery);
|
|
407
438
|
}
|
|
439
|
+
// Set query as successful in the input field
|
|
440
|
+
this.easyFilterInput.current?.setQuerySuccess(magicQuery);
|
|
408
441
|
if (easyFilterResult.data.version === 1) {
|
|
409
442
|
this.handleV1Success(easyFilterResult);
|
|
410
443
|
} else if (easyFilterResult.data.version === 2) {
|
|
@@ -412,10 +445,12 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
412
445
|
}
|
|
413
446
|
} else {
|
|
414
447
|
// error
|
|
448
|
+
this.easyFilterInput.current?.setQueryFailure();
|
|
415
449
|
this.removeNonMandatoryTokens();
|
|
416
450
|
this.setMessageStrip(easyFilterResult.message);
|
|
417
451
|
this.invisibleMessage.announce(this.resourceBundle.getText(easyFilterResult.message), InvisibleMessageMode.Assertive);
|
|
418
452
|
this.state.messageStripType = MessageType.Warning;
|
|
453
|
+
this.state.groupLevels = [];
|
|
419
454
|
Log.error("Error while generating filter criteria: ", easyFilterResult.message);
|
|
420
455
|
}
|
|
421
456
|
|
|
@@ -498,12 +533,162 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
498
533
|
}
|
|
499
534
|
|
|
500
535
|
const updatedTokens = this.verifySingleSelectTokenValues(tokens);
|
|
536
|
+
|
|
537
|
+
// Validate and store sort expressions (applied to table directly, not shown as tokens)
|
|
538
|
+
this.state.sorters = this.supportsSorting ? this.validateSortExpressions(easyFilterResult.data.sorters) : [];
|
|
501
539
|
this.state.showResult = true;
|
|
502
540
|
this.state.thumbButtonEnabled = true;
|
|
503
541
|
this.state.thumbDownButtonPressed = false;
|
|
504
542
|
this.state.thumbUpButtonPressed = false;
|
|
505
543
|
this.state.tokens = updatedTokens;
|
|
506
544
|
}
|
|
545
|
+
|
|
546
|
+
this.state.groupLevels = this.supportsGrouping ? this.applyGroupLevels(easyFilterResult.data.groupLevels) : [];
|
|
547
|
+
|
|
548
|
+
this.showUnsupportedCapabilitiesWarning(easyFilterResult.data.sorters, easyFilterResult.data.groupLevels);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Shows a warning when the app does not support the LLM's sort/group expressions.
|
|
553
|
+
* @param sorters Sort expressions from the LLM.
|
|
554
|
+
* @param groupLevels Group levels from the LLM.
|
|
555
|
+
*/
|
|
556
|
+
private showUnsupportedCapabilitiesWarning(
|
|
557
|
+
sorters: EasyFilter.EasyFilterSortExpression[] | undefined,
|
|
558
|
+
groupLevels: EasyFilter.EasyFilterGroupLevelDefinition[] | undefined
|
|
559
|
+
): void {
|
|
560
|
+
const hasSortersFromLLM = sorters && sorters.length > 0;
|
|
561
|
+
const hasGroupLevelsFromLLM = groupLevels && groupLevels.length > 0;
|
|
562
|
+
const sortingUnsupported = !this.supportsSorting && hasSortersFromLLM;
|
|
563
|
+
const groupingUnsupported = !this.supportsGrouping && hasGroupLevelsFromLLM;
|
|
564
|
+
|
|
565
|
+
if (sortingUnsupported && groupingUnsupported) {
|
|
566
|
+
this.appendMessageStrip(this.resourceBundle.getText("M_EASY_FILTER_SORTING_AND_GROUPING_NOT_SUPPORTED"), MessageType.Warning);
|
|
567
|
+
} else if (sortingUnsupported) {
|
|
568
|
+
this.appendMessageStrip(this.resourceBundle.getText("M_EASY_FILTER_SORTING_NOT_SUPPORTED"), MessageType.Warning);
|
|
569
|
+
} else if (groupingUnsupported) {
|
|
570
|
+
this.appendMessageStrip(this.resourceBundle.getText("M_EASY_FILTER_GROUPING_NOT_SUPPORTED"), MessageType.Warning);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Updates whether the app supports sorting and grouping based on table personalization settings.
|
|
576
|
+
* @param sorting Whether the app supports sorting.
|
|
577
|
+
* @param grouping Whether the app supports grouping.
|
|
578
|
+
*/
|
|
579
|
+
public setPersonalizationSupport(sorting: boolean, grouping: boolean): void {
|
|
580
|
+
this.supportsSorting = sorting;
|
|
581
|
+
this.supportsGrouping = grouping;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Validates and triggers the groupLevelsChanged function, which warns about non-groupable fields.
|
|
586
|
+
* @param groupLevels The group levels to validate and apply
|
|
587
|
+
* @returns GroupLevelDefinition[] An array of valid group level definitions to be applied
|
|
588
|
+
*/
|
|
589
|
+
private applyGroupLevels(groupLevels: GroupLevelDefinition[] | undefined): GroupLevelDefinition[] {
|
|
590
|
+
const metadata = this.filterBarMetadata as EasyFilterPropertyMetadata[];
|
|
591
|
+
|
|
592
|
+
if (!metadata || !groupLevels || groupLevels.length === 0) {
|
|
593
|
+
return [];
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
const resolveField = (groupDef: GroupLevelDefinition): EasyFilterPropertyMetadata | undefined => {
|
|
597
|
+
const propertyName = EasyFilterUtils.resolvePropertyName(groupDef.key);
|
|
598
|
+
const field = metadata.find((f) => f.name === groupDef.key || f.name.endsWith(`/${propertyName}`));
|
|
599
|
+
if (!field) {
|
|
600
|
+
Log.warning(`EasyFilterBarContainer: group key "${groupDef.key}" not found in filter bar metadata, skipping`);
|
|
601
|
+
}
|
|
602
|
+
return field;
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
if (groupLevels.length === 1) {
|
|
606
|
+
const errorHandler = new ErrorMessageHandler();
|
|
607
|
+
const field = resolveField(groupLevels[0]);
|
|
608
|
+
if (!field) return [];
|
|
609
|
+
const isGroupable = errorHandler.isGroupableProperty(field);
|
|
610
|
+
if (errorHandler.hasErrors()) {
|
|
611
|
+
this.appendMessageStrip(encodeXML(errorHandler.getErrorMessage()), MessageType.Warning);
|
|
612
|
+
}
|
|
613
|
+
return isGroupable ? [groupLevels[0]] : [];
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Multiple group levels: find the first valid groupable field
|
|
617
|
+
const errorHandler = new ErrorMessageHandler();
|
|
618
|
+
let firstGroupableDef: GroupLevelDefinition | undefined;
|
|
619
|
+
let firstGroupableLabel: string | undefined;
|
|
620
|
+
|
|
621
|
+
for (const groupDef of groupLevels) {
|
|
622
|
+
const field = resolveField(groupDef);
|
|
623
|
+
if (!field) continue;
|
|
624
|
+
if (errorHandler.isGroupableProperty(field)) {
|
|
625
|
+
if (!firstGroupableDef) {
|
|
626
|
+
firstGroupableDef = groupDef;
|
|
627
|
+
firstGroupableLabel = field.label ?? field.name;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (firstGroupableDef) {
|
|
633
|
+
const warning = this.resourceBundle.getText("M_EASY_FILTER_MULTIPLE_GROUP_WARNING", [firstGroupableLabel]);
|
|
634
|
+
this.appendMessageStrip(encodeXML(warning), MessageType.Warning);
|
|
635
|
+
return [firstGroupableDef];
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// All fields are non-groupable
|
|
639
|
+
if (errorHandler.hasErrors()) {
|
|
640
|
+
this.appendMessageStrip(encodeXML(errorHandler.getErrorMessage()), MessageType.Warning);
|
|
641
|
+
}
|
|
642
|
+
return [];
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Validates sort expressions from the AI result and returns valid sort definitions.
|
|
647
|
+
* @param sortExpressions The sort expressions from the ABAP service.
|
|
648
|
+
* @returns Array of validated sort definitions.
|
|
649
|
+
* @private
|
|
650
|
+
*/
|
|
651
|
+
private validateSortExpressions(sortExpressions?: EasyFilter.EasyFilterSortExpression[]): SortDefinition[] {
|
|
652
|
+
if (!sortExpressions || sortExpressions.length === 0) {
|
|
653
|
+
return [];
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
const nonSortableFields: string[] = [];
|
|
657
|
+
|
|
658
|
+
const validSorters = sortExpressions
|
|
659
|
+
.filter((sortExpression) => {
|
|
660
|
+
// Validate that the field exists in metadata and is sortable
|
|
661
|
+
const fieldMetadata = this.filterBarMetadata?.find((field) => {
|
|
662
|
+
const fieldName = field.name.split("/").pop();
|
|
663
|
+
return fieldName === sortExpression.key || field.name === sortExpression.key;
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
if (!fieldMetadata) {
|
|
667
|
+
return false;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
if (fieldMetadata.sortable === false) {
|
|
671
|
+
nonSortableFields.push(fieldMetadata.label ?? sortExpression.key);
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return true;
|
|
676
|
+
})
|
|
677
|
+
.map((sortExpression) => {
|
|
678
|
+
const propertyName = sortExpression.key.split("/").pop() ?? sortExpression.key;
|
|
679
|
+
return {
|
|
680
|
+
key: propertyName,
|
|
681
|
+
descending: sortExpression.descending
|
|
682
|
+
};
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
// Show warning message for non-sortable fields
|
|
686
|
+
if (nonSortableFields.length > 0) {
|
|
687
|
+
const message = this.resourceBundle.getText("M_EASY_FILTER_NON_SORTABLE", [nonSortableFields.join(", ")]);
|
|
688
|
+
this.appendMessageStrip(message, MessageType.Warning);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
return validSorters;
|
|
507
692
|
}
|
|
508
693
|
|
|
509
694
|
//every single select menu type should have only one value, else splice to one value and update the message strip
|
|
@@ -547,6 +732,21 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
547
732
|
this.state.showMessageStrip = true;
|
|
548
733
|
}
|
|
549
734
|
|
|
735
|
+
setMessageStripWithType(text: string, type: MessageType): void {
|
|
736
|
+
this.setMessageStrip(text);
|
|
737
|
+
this.state.messageStripType = type;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Appends a message to the existing message strip instead of overwriting it.
|
|
742
|
+
* @param text The message text to append.
|
|
743
|
+
* @param type The message type for this message.
|
|
744
|
+
*/
|
|
745
|
+
appendMessageStrip(text: string, type: MessageType): void {
|
|
746
|
+
const combined = this.state.showMessageStrip && this.state.messageStripText ? `${this.state.messageStripText}<br>${text}` : text;
|
|
747
|
+
this.setMessageStripWithType(combined, type);
|
|
748
|
+
}
|
|
749
|
+
|
|
550
750
|
createPopoverForInnerControls(): Popover {
|
|
551
751
|
if (!this.innerControlPopover) {
|
|
552
752
|
this.innerControlPopover = (
|
|
@@ -637,14 +837,26 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
637
837
|
/**
|
|
638
838
|
* The user has acknowledged the message strip and understood the issue.
|
|
639
839
|
* When the tokens are updated next time, displaying the message strip again serves no purpose.
|
|
640
|
-
* Additionally, once the tokens are updated, the input field text
|
|
641
|
-
* rendering the message strip irrelevant. However, the message strip
|
|
840
|
+
* Additionally, once the tokens are updated, the input field text is removed
|
|
841
|
+
* rendering the message strip irrelevant. However, the message strip is displayed again the next time the "Go" button is pressed.
|
|
642
842
|
*/
|
|
643
843
|
this.clearMessageStrip();
|
|
644
844
|
this.clearMessageStripForSingleValue();
|
|
645
845
|
}
|
|
646
846
|
this.shouldMessageStripRemove = true;
|
|
647
847
|
}
|
|
848
|
+
|
|
849
|
+
if (changedProps.includes("sorters")) {
|
|
850
|
+
this.fireEvent("sortersChanged", {
|
|
851
|
+
sorters: this.state.sorters
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
if (changedProps.includes("groupLevels")) {
|
|
856
|
+
this.fireEvent("groupLevelsChanged", {
|
|
857
|
+
groupLevels: this.state.groupLevels
|
|
858
|
+
});
|
|
859
|
+
}
|
|
648
860
|
//Resetting to default values
|
|
649
861
|
this.isMandatoryCheckRequired = false;
|
|
650
862
|
this.shouldTokenChangeEventFired = true;
|
|
@@ -752,6 +964,7 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
752
964
|
}}
|
|
753
965
|
liveChange={(): void => {
|
|
754
966
|
this.state.tokenizerEditable = false;
|
|
967
|
+
this.fireEvent("liveChange", { query: this.getQuery() });
|
|
755
968
|
}}
|
|
756
969
|
/>
|
|
757
970
|
|
|
@@ -797,6 +1010,7 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
797
1010
|
newTokens.splice(tokenIndex, 1);
|
|
798
1011
|
this.state.tokens = newTokens;
|
|
799
1012
|
this.updateFilterInput("tokenUpdated");
|
|
1013
|
+
this.fireEvent("tokensChangedByUser", { tokens: [...this.state.tokens] });
|
|
800
1014
|
}}
|
|
801
1015
|
>
|
|
802
1016
|
{{
|
|
@@ -829,7 +1043,7 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
829
1043
|
/>
|
|
830
1044
|
</FlexBox>
|
|
831
1045
|
</FlexBox>
|
|
832
|
-
<
|
|
1046
|
+
<VBox renderType="Bare" class={"sapUiTinyMarginTop sapFeControlsGap8px"}>
|
|
833
1047
|
<MessageStrip
|
|
834
1048
|
text={bindState(this.state, "singleValueMessageStripText")}
|
|
835
1049
|
showIcon={true}
|
|
@@ -840,26 +1054,29 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
840
1054
|
this.clearMessageStripForSingleValue();
|
|
841
1055
|
}}
|
|
842
1056
|
></MessageStrip>
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
</
|
|
859
|
-
</
|
|
1057
|
+
<FlexBox renderType="Bare" class={"sapFeControlsGap8px"}>
|
|
1058
|
+
<MessageStrip
|
|
1059
|
+
type={bindState(this.state, "messageStripType")}
|
|
1060
|
+
text={bindState(this.state, "messageStripText")}
|
|
1061
|
+
showIcon={true}
|
|
1062
|
+
enableFormattedText={true}
|
|
1063
|
+
showCloseButton={true}
|
|
1064
|
+
close={(): void => {
|
|
1065
|
+
this.clearMessageStrip();
|
|
1066
|
+
}}
|
|
1067
|
+
visible={bindState(this.state, "showMessageStrip")}
|
|
1068
|
+
></MessageStrip>
|
|
1069
|
+
<HBox visible={and(bindState(this.state, "showMessageStrip"), not(bindState(this.state, "showResult")))}>
|
|
1070
|
+
{thumbUpButtonMessageStripe}, {thumbDownButtonMessageStripe}
|
|
1071
|
+
</HBox>
|
|
1072
|
+
</FlexBox>
|
|
1073
|
+
</VBox>
|
|
860
1074
|
</VBox>
|
|
861
1075
|
) as VBox;
|
|
862
1076
|
FESRHelper.setSemanticStepname($topGoBtn.current!, "press", "fe:ai:search");
|
|
1077
|
+
if (this.easyFilterInput.current) {
|
|
1078
|
+
FESRHelper.setSemanticStepname(this.easyFilterInput.current, "enterPressed", "fe:ai:search");
|
|
1079
|
+
}
|
|
863
1080
|
return outVBox;
|
|
864
1081
|
}
|
|
865
1082
|
|
|
@@ -891,10 +1108,12 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
891
1108
|
resetState(clearAllFilters = true, isResettingToDefaultTokens = false): void {
|
|
892
1109
|
if (clearAllFilters) {
|
|
893
1110
|
this.fireEvent("clearFilters");
|
|
1111
|
+
this.state.groupLevels = [];
|
|
894
1112
|
this.isResettingToDefaultTokens = isResettingToDefaultTokens;
|
|
895
1113
|
} else {
|
|
896
1114
|
this.shouldTokenChangeEventFired = false;
|
|
897
1115
|
}
|
|
1116
|
+
this.state.sorters = [];
|
|
898
1117
|
this.state.tokens = this.getDefaultTokens();
|
|
899
1118
|
this.updateFilterInput("tokenReset");
|
|
900
1119
|
this.state.tokenizerEditable = true;
|
|
@@ -903,6 +1122,14 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
903
1122
|
this.tokenizer.current?.getTokens().forEach((token) => token.setProperty("valueState", ValueState.None));
|
|
904
1123
|
this.tokenizer.current?.getTokens().forEach((token) => token.setProperty("valueStateText", null));
|
|
905
1124
|
this.clearMessageStrip(); //clear the message strip for validated filters
|
|
1125
|
+
// Clear query success status
|
|
1126
|
+
this.easyFilterInput.current?.clearQueryStatus();
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
clearFiltersAndTokens(): void {
|
|
1130
|
+
this.fireEvent("clearFilters");
|
|
1131
|
+
this.shouldTokenChangeEventFired = false;
|
|
1132
|
+
this.state.tokens = [];
|
|
906
1133
|
}
|
|
907
1134
|
|
|
908
1135
|
//The below code updates the existing state by fetching the key and selectedValues
|
|
@@ -932,6 +1159,7 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
932
1159
|
this.state.tokens = newTokens as TokenDefinition[];
|
|
933
1160
|
this.state.showResult = newTokens.length > 0;
|
|
934
1161
|
this.updateFilterInput("tokenUpdated");
|
|
1162
|
+
this.fireEvent("tokensChangedByUser", { tokens: [...this.state.tokens] });
|
|
935
1163
|
}
|
|
936
1164
|
}
|
|
937
1165
|
|
|
@@ -958,6 +1186,14 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
958
1186
|
return this.mandatoryKeyMap[key] ? true : false;
|
|
959
1187
|
}
|
|
960
1188
|
|
|
1189
|
+
/**
|
|
1190
|
+
* Checks whether the current state has sort definitions from the easy filter.
|
|
1191
|
+
* @returns True if the current state contains one or more sorters.
|
|
1192
|
+
*/
|
|
1193
|
+
private hasSorters(): boolean {
|
|
1194
|
+
return this.state.sorters.length > 0;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
961
1197
|
removeNonMandatoryTokens(): this {
|
|
962
1198
|
const newToken: TokenDefinition[] = this.state.tokens.filter((token) => {
|
|
963
1199
|
return this.isKeyMandatory(token.key);
|
|
@@ -966,6 +1202,33 @@ export default class EasyFilterBarContainer extends Control {
|
|
|
966
1202
|
return this;
|
|
967
1203
|
}
|
|
968
1204
|
|
|
1205
|
+
hasGroupLevels(): boolean {
|
|
1206
|
+
return this.state.groupLevels.length > 0;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
/**
|
|
1210
|
+
* Notifies the container that an external table state change (sort or group) has been detected.
|
|
1211
|
+
* If the container currently has active sorters or group levels, the filter input is marked dirty
|
|
1212
|
+
* because the external change makes the easy filter result inconsistent.
|
|
1213
|
+
*/
|
|
1214
|
+
notifyExternalTableStateChange(): void {
|
|
1215
|
+
if (this.hasSorters() || this.hasGroupLevels()) {
|
|
1216
|
+
this.updateFilterInput("tokenUpdated");
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
getQuery(): string {
|
|
1221
|
+
return this.easyFilterInput.current?.getValue() ?? "";
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
getTokens(): TokenDefinition[] {
|
|
1225
|
+
return [...this.state.tokens];
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
setQuery(query: string): void {
|
|
1229
|
+
this.easyFilterInput.current?.setValue(query);
|
|
1230
|
+
}
|
|
1231
|
+
|
|
969
1232
|
updateFilterInput(value: string): void {
|
|
970
1233
|
const currValue: string = this.easyFilterInput.current?.getValue() || "";
|
|
971
1234
|
if (value === "tokenUpdated" && currValue !== "") {
|