@sapui5/sap.suite.ui.generic.template 1.147.1 → 1.148.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.
Files changed (43) hide show
  1. package/package.json +1 -1
  2. package/src/sap/suite/ui/generic/template/.library +1 -1
  3. package/src/sap/suite/ui/generic/template/AnalyticalListPage/controller/ControllerImplementation.js +5 -3
  4. package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_bg.properties +3 -3
  5. package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_da.properties +3 -3
  6. package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_id.properties +2 -2
  7. package/src/sap/suite/ui/generic/template/AnalyticalListPage/manifest.json +1 -1
  8. package/src/sap/suite/ui/generic/template/Canvas/manifest.json +1 -1
  9. package/src/sap/suite/ui/generic/template/ListReport/controller/ControllerImplementation.js +32 -3
  10. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_id.properties +1 -1
  11. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_uk.properties +1 -1
  12. package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
  13. package/src/sap/suite/ui/generic/template/ObjectPage/Component.js +4 -0
  14. package/src/sap/suite/ui/generic/template/ObjectPage/controller/ControllerImplementation.js +57 -25
  15. package/src/sap/suite/ui/generic/template/ObjectPage/i18n/i18n.properties +6 -0
  16. package/src/sap/suite/ui/generic/template/ObjectPage/i18n/i18n_en_US_saprigi.properties +4 -0
  17. package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +6 -1
  18. package/src/sap/suite/ui/generic/template/ObjectPage/templateSpecificPreparationHelper.js +35 -19
  19. package/src/sap/suite/ui/generic/template/ObjectPage/view/fragments/Footer.fragment.xml +103 -42
  20. package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
  21. package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
  22. package/src/sap/suite/ui/generic/template/fragments/EasyFilter.fragment.xml +3 -0
  23. package/src/sap/suite/ui/generic/template/genericUtilities/controlHelper.js +30 -29
  24. package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartFilterBarWrapper.js +15 -0
  25. package/src/sap/suite/ui/generic/template/lib/AppComponent.js +1 -1
  26. package/src/sap/suite/ui/generic/template/lib/CRUDHelper.js +93 -55
  27. package/src/sap/suite/ui/generic/template/lib/CRUDManager.js +7 -0
  28. package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +19 -13
  29. package/src/sap/suite/ui/generic/template/lib/CommonUtils.js +4 -1
  30. package/src/sap/suite/ui/generic/template/lib/ComponentUtils.js +17 -7
  31. package/src/sap/suite/ui/generic/template/lib/StableIdDefinition.js +35 -34
  32. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillHandler.js +853 -130
  33. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/ObjectPageSectionHandler.js +282 -0
  34. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillDialog.fragment.xml +138 -72
  35. package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +409 -22
  36. package/src/sap/suite/ui/generic/template/lib/i18n/i18n.properties +21 -0
  37. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ja.properties +6 -6
  38. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_uk.properties +3 -3
  39. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_CN.properties +6 -6
  40. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_TW.properties +6 -6
  41. package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +1 -1
  42. package/src/sap/suite/ui/generic/template/library.js +25 -2
  43. package/src/sap/suite/ui/generic/template/themes/base/ObjectPage.less +14 -0
@@ -6,8 +6,9 @@ sap.ui.define([
6
6
  "sap/ui/model/FilterOperator",
7
7
  'sap/ui/model/Filter',
8
8
  'sap/suite/ui/generic/template/js/AnnotationHelper',
9
- "./EasyFilterDataFetcherHelper"
10
- ], function(BaseObject, extend, filterHelper, FeLogger, FilterOperator,Filter,AnnotationHelper,EasyFilterDataFetcherHelper) {
9
+ "./EasyFilterDataFetcherHelper",
10
+ "sap/suite/ui/generic/template/genericUtilities/controlHelper"
11
+ ], function(BaseObject, extend, filterHelper, FeLogger, FilterOperator,Filter,AnnotationHelper,EasyFilterDataFetcherHelper,controlHelper) {
11
12
  'use strict';
12
13
 
13
14
  /*
@@ -25,7 +26,34 @@ sap.ui.define([
25
26
  // used for busyHandling between query triggered and query resolved.
26
27
  var oQueryPromise, oQueryPromiseResolve;
27
28
  var fnValueHelpPromiseResolve;
29
+ // Guard flag to distinguish EasyFilter-initiated state changes from user-initiated ones
30
+ var bApplyingSorting = false;
31
+
32
+ var bApplyingGrouplevels = false;
33
+
28
34
  // fnValueHelpPromiseReject;
35
+ // Tracks the filterMode that was saved in the most recently loaded variant.
36
+ // Used in onFilterSwitch to compare against the current toggle state without
37
+ // relying on getCustomFilterData() which can be overwritten by intermediate
38
+ // beforeVariantFetch calls during the async Go press flow.
39
+ var sLoadedVariantFilterMode = "classic";
40
+ // Set to true when the user manually deletes or modifies a token, reset to false on
41
+ // variant load or Go press result. Used to suppress fnApplyEasyFilterVariantState from
42
+ // overwriting the stale-query (placeholder) state that fnTokensChanged put in place.
43
+ var bTokensModifiedByUser = false;
44
+
45
+ /**
46
+ * Calls setVariantCreationByUserAllowed(bAllowed) on the SmartVariantManagement control
47
+ * that owns the SmartFilterBar. Disabling creation blocks both Save and Save As in the VM
48
+ * popup. Re-enabling restores the default behaviour.
49
+ * @param {boolean} bAllowed
50
+ */
51
+ function fnSetCreationAllowed(bAllowed) {
52
+ var oSmartVariant = oState.oSmartFilterbar.getSmartVariant();
53
+ if (oSmartVariant) {
54
+ oSmartVariant.setVariantCreationByUserAllowed(bAllowed);
55
+ }
56
+ }
29
57
 
30
58
  /**
31
59
  * This method prepares the metadata calculation after the smart filter bar is initialized
@@ -59,8 +87,25 @@ sap.ui.define([
59
87
  var mFilterProperties = {}; // Now also includes 1:1 navigation properties
60
88
  var oEntityType = oTemplateUtils.oCommonUtils.getMetaModelEntityType(sEntitySet);
61
89
 
62
- // Helper to add properties to mFilterProperties, with optional prefix
63
- function addPropertiesFromEntityType(entityType, prefix) {
90
+ // Collect non-sortable properties from SortRestrictions annotation
91
+ var oEntitySetMeta = oSFBMetaModel?.getODataEntitySet && oSFBMetaModel?.getODataEntitySet(sEntitySet);
92
+ var oSortRestrictions = oEntitySetMeta && oEntitySetMeta["Org.OData.Capabilities.V1.SortRestrictions"];
93
+ var bEntitySetSortable = !oSortRestrictions || oSortRestrictions.Sortable !== "false";
94
+ var mNonSortableProperties = {};
95
+ if (oSortRestrictions && oSortRestrictions.NonSortableProperties) {
96
+ oSortRestrictions.NonSortableProperties.forEach(function(oProperty) {
97
+ if (oProperty.PropertyPath) {
98
+ mNonSortableProperties[oProperty.PropertyPath] = true;
99
+ }
100
+ });
101
+ }
102
+
103
+ // Helper to add properties to mFilterProperties, with optional prefix.
104
+ // bOverrideSortable and mOverrideNonSortable allow callers (e.g. nav property processing)
105
+ // to pass entity-set-specific sort restrictions instead of the root entity set's.
106
+ function addPropertiesFromEntityType(entityType, prefix, bOverrideSortable, mOverrideNonSortable) {
107
+ var bEffectiveSortable = (bOverrideSortable !== undefined) ? bOverrideSortable : bEntitySetSortable;
108
+ var mEffectiveNonSortable = mOverrideNonSortable || mNonSortableProperties;
64
109
  entityType.property.forEach(function (oProperty) {
65
110
  var sTokenType = "ValueHelp";
66
111
  if (filterHelper.isPropertyFilterable(oProperty)) {
@@ -90,12 +135,18 @@ sap.ui.define([
90
135
  sTokenType = "Time";
91
136
  }
92
137
  var propName = prefix ? prefix + "." + oProperty.name : oProperty.name;
138
+ // Determine sortability: property is sortable unless entity set is not sortable,
139
+ // property is in NonSortableProperties, or property has sap:sortable="false"
140
+ var bSortable = bEffectiveSortable && !mEffectiveNonSortable[oProperty.name] && oProperty["sap:sortable"] !== "false";
141
+ // Groupable follows the same logic as sortable: a property is groupable if it is sortable
142
+ var bGroupable = bSortable;
93
143
  mFilterProperties[propName] = {
94
144
  name: propName,
95
145
  dataType: oProperty.type,
96
146
  defaultValue : [],
97
147
  filterable: true,
98
- sortable: false,
148
+ sortable: bSortable,
149
+ groupable: bGroupable,
99
150
  codeList : bIsCodeListRequired,
100
151
  type: sTokenType,
101
152
  unit: oProperty["sap:unit"] || "",
@@ -137,7 +188,26 @@ sap.ui.define([
137
188
  //var sShortType = sTargetType.split(".").pop();
138
189
  var oTargetEntityType = oSFBMetaModel.getODataEntityType && oSFBMetaModel.getODataEntityType(sTargetType);
139
190
  if (oTargetEntityType) {
140
- addPropertiesFromEntityType(oTargetEntityType, navProp.name);
191
+ // Resolve SortRestrictions for the navigation target entity set,
192
+ // mirroring the same check EasyFilterBar.tsx (V4) does for nav property bindings.
193
+ var bNavSortable = bEntitySetSortable;
194
+ var mNavNonSortable = {};
195
+ var oAssocSetEnd = oSFBMetaModel.getODataAssociationSetEnd && oSFBMetaModel.getODataAssociationSetEnd(oEntityType, navProp.name);
196
+ var oNavEntitySetMeta = oAssocSetEnd && oAssocSetEnd.entitySet && oSFBMetaModel.getODataEntitySet(oAssocSetEnd.entitySet);
197
+ if (oNavEntitySetMeta) {
198
+ var oNavSortRestrictions = oNavEntitySetMeta["Org.OData.Capabilities.V1.SortRestrictions"];
199
+ if (oNavSortRestrictions) {
200
+ bNavSortable = oNavSortRestrictions.Sortable !== "false";
201
+ if (oNavSortRestrictions.NonSortableProperties) {
202
+ oNavSortRestrictions.NonSortableProperties.forEach(function(oProperty) {
203
+ if (oProperty.PropertyPath) {
204
+ mNavNonSortable[oProperty.PropertyPath] = true;
205
+ }
206
+ });
207
+ }
208
+ }
209
+ }
210
+ addPropertiesFromEntityType(oTargetEntityType, navProp.name, bNavSortable, mNavNonSortable);
141
211
  }
142
212
  }
143
213
  }
@@ -434,6 +504,43 @@ sap.ui.define([
434
504
  return oController.byId("template::easyFilterContainer");
435
505
  }
436
506
 
507
+ /**
508
+ * Applies EasyFilter variant state: sets the filterMode and, if easyFilter mode,
509
+ * restores the query string and triggers AI resolution to rebuild the token display.
510
+ * The SFB selectOptions are already restored by the variant mechanism — this only
511
+ * restores the visual state of the EasyFilter bar.
512
+ * @param {object} oVariantState - { filterMode: string, easyFilter: { query: string } }
513
+ */
514
+ function fnApplyEasyFilterVariantState(oVariantState) {
515
+ if (!oVariantState || !oVariantState.filterMode) {
516
+ return;
517
+ }
518
+ var oTempModel = oTemplateUtils.oComponentUtils.getTemplatePrivateModel();
519
+ var oSmartFilterbar = oState.oSmartFilterbar;
520
+
521
+ oTempModel.setProperty("/listReport/filterMode", oVariantState.filterMode);
522
+
523
+ if (oVariantState.filterMode === "easyFilter") {
524
+ oSmartFilterbar.setVisible(false);
525
+ var sQuery = oVariantState.easyFilter && oVariantState.easyFilter.query;
526
+ if (sQuery) {
527
+ // Tokens have been manually changed — the query in the input is intentionally
528
+ // stale (shown as placeholder). Do not overwrite it with the saved query.
529
+ if (!bTokensModifiedByUser) {
530
+ var oEasyFilterBar = fnGetEasyFilterBar();
531
+ if (oEasyFilterBar) {
532
+ var sCurrentQuery = oEasyFilterBar.getQuery();
533
+ if (!sCurrentQuery || sCurrentQuery === sQuery) {
534
+ oEasyFilterBar.setQuery(sQuery);
535
+ }
536
+ }
537
+ }
538
+ }
539
+ } else {
540
+ oSmartFilterbar.setVisible(true);
541
+ }
542
+ }
543
+
437
544
  /**
438
545
  * This method is used to initialise the EasyFilter control with the metadata from the smart filter bar
439
546
  */
@@ -446,6 +553,46 @@ sap.ui.define([
446
553
  oEasyFilter.setAppId(oController.getOwnerComponent().getAppComponent().getManifestEntry("sap.app").id);
447
554
  oEasyFilter.setFilterBarMetadata(oEasyFilterMetadata.fields);
448
555
  oEasyFilter.easyfilter = oTemplateUtils.oServices.oFioriAIHandler.fioriaiLib.EasyFilter;
556
+
557
+ // Register callbacks on SmartFilterBarWrapper so filterMode and query are
558
+ // included in the genericData bucket when a variant is saved or loaded.
559
+ var sSmartFilterBarId = oState.oSmartFilterbar.getId();
560
+ var oSmartFilterBarWrapper = oTemplateUtils.oCommonUtils.getControlStateWrapperById(sSmartFilterBarId, "SmartFilterBar");
561
+ oSmartFilterBarWrapper.setEasyFilterCallbacks({
562
+ getState: function() {
563
+ var oTMModel = oTemplateUtils.oComponentUtils.getTemplatePrivateModel();
564
+ var oEFBar = fnGetEasyFilterBar();
565
+ return {
566
+ filterMode: oTMModel.getProperty("/listReport/filterMode"),
567
+ easyFilter: {
568
+ query: oEFBar ? oEFBar.getQuery() : undefined
569
+ }
570
+ };
571
+ },
572
+ setState: fnApplyEasyFilterVariantState
573
+ });
574
+
575
+ // Handle INIT timing gap: the "INIT" afterVariantLoad fires before this handler
576
+ // is created. Read whatever the variant already loaded into customFilterData now.
577
+ var oCustomData = oState.oSmartFilterbar.getCustomFilterData();
578
+ var oGenericData = oCustomData && oCustomData["sap.suite.ui.generic.template.genericData"];
579
+ if (oGenericData && oGenericData.filterMode) {
580
+ sLoadedVariantFilterMode = oGenericData.filterMode;
581
+ fnApplyEasyFilterVariantState({
582
+ filterMode: oGenericData.filterMode,
583
+ easyFilter: oGenericData.easyFilter
584
+ });
585
+ // If the default variant has AutoApply checked, trigger Go now.
586
+ // The SFB would have called search() itself (IappStateHandler line ~773),
587
+ // but EasyFilter is hidden so we need onGoPress instead.
588
+ // areDataShownInTable() being true at this point is the same signal
589
+ // the SFB uses to decide whether to auto-search on startup.
590
+ if (oGenericData.filterMode === "easyFilter" &&
591
+ oGenericData.easyFilter && oGenericData.easyFilter.query &&
592
+ oState.oIappStateHandler.areDataShownInTable()) {
593
+ oEasyFilter.onGoPress(oGenericData.easyFilter.query);
594
+ }
595
+ }
449
596
  });
450
597
  }
451
598
 
@@ -470,10 +617,24 @@ sap.ui.define([
470
617
  function fnTokensChanged(oEvent) {
471
618
  //When reset button is clicked no batch call should be triggered
472
619
  if (oEvent.getParameter("reset")) {
620
+ fnSetCreationAllowed(true);
473
621
  return;
474
622
  }
475
623
  var oSmartFilterbar = oState.oSmartFilterbar;
476
624
  var oFiltersFromAI = oEvent.getParameter("tokens");
625
+
626
+ // tokensChanged fires for both AI-resolved tokens (Go press result) and user
627
+ // manual token edits. tokensChangedByUser fires first on a user edit and sets
628
+ // bTokensModifiedByUser — use that to tell the two cases apart.
629
+ if (bTokensModifiedByUser) {
630
+ // User manually edited a token — tokensChangedByUser already disabled
631
+ // Save/SaveAs. Mark the variant dirty and stop; do not trigger search.
632
+ oSmartFilterbar.getSmartVariant() && oSmartFilterbar.getSmartVariant().currentVariantSetModified(true);
633
+ return;
634
+ }
635
+ // AI-resolved result path: reset the user-edit flag and re-enable Save/SaveAs.
636
+ bTokensModifiedByUser = false;
637
+ fnSetCreationAllowed(true);
477
638
  var sSmartFilterBarId = oSmartFilterbar.getId();
478
639
  var oSmartFilterBarWrapper = oTemplateUtils.oCommonUtils.getControlStateWrapperById(sSmartFilterBarId, "SmartFilterBar");
479
640
  var oSmartFilterBarVariant = oSmartFilterBarWrapper.getState();
@@ -505,24 +666,145 @@ sap.ui.define([
505
666
  // If matching property found and has ranges
506
667
  if (matchingSelectOption?.Ranges?.length > 0) {
507
668
  var { Low: value1 = null, High: value2 = null } = matchingSelectOption.Ranges[0];
508
- // Update the semantic date data in the smart filter bar
669
+ // Update the semantic date data in the smart filter bar
509
670
  var dateData = semanticDate.Data;
510
671
  dateData.operation = "DATERANGE";
511
672
  dateData.value1 = value1;
512
673
  dateData.value2 = value2 || value1; // Use value1 if value2 is null/empty
513
- }
674
+ }
514
675
  });
515
676
  }
516
677
 
517
678
  oSmartFilterBarWrapper.setState(oSmartFilterBarVariant);
518
- oSmartFilterbar.getSmartVariant() && oSmartFilterbar.getSmartVariant().currentVariantSetModified(true);
679
+ // currentVariantSetModified intentionally omitted — pressing Go with the same
680
+ // query must not mark the variant as dirty.
681
+ // oSmartFilterbar.getSmartVariant() && oSmartFilterbar.getSmartVariant().currentVariantSetModified(true);
519
682
  oSmartFilterbar.search();
520
683
  }
684
+
685
+ /**
686
+ * Event handler for the EasyFilterBarContainer's tokensChangedByUser event.
687
+ * Fired when the user manually deletes or modifies a token (distinct from AI-resolved tokens).
688
+ * Disables Save/SaveAs in the variant management popup until a fresh Go press resolves new tokens.
689
+ */
690
+ function fnTokensChangedByUser() {
691
+ bTokensModifiedByUser = true;
692
+ fnSetCreationAllowed(false);
693
+ }
694
+
695
+ /**
696
+ /**
697
+ * Event handler for the EasyFilter control's sortersChanged event.
698
+ * Applies the AI-determined sort order to the SmartTable via setUiState,
699
+ * which updates the data binding, column sort indicators, and P13n state
700
+ * through the PersonalizationController.
701
+ * @param {sap.ui.base.Event} oEvent The sortersChanged event containing sort definitions
702
+ */
703
+ function fnSortersChanged(oEvent) {
704
+ try {
705
+ var aSorters = oEvent.getParameter("sorters");
706
+
707
+ var oPresentationControlHandler = oState.oPresentationControlHandler;
708
+ if (!oPresentationControlHandler) {
709
+ oLogger.error("EasyFilterBarHandler.onSortersChanged: PresentationControlHandler not found.");
710
+ return;
711
+ }
712
+
713
+ var oControl = oPresentationControlHandler.getControl();
714
+ if (!oControl) {
715
+ oLogger.error("EasyFilterBarHandler.onSortersChanged: Presentation control not found.");
716
+ return;
717
+ }
718
+
719
+ if (!controlHelper.isSmartTable(oControl)) {
720
+ oLogger.warning("EasyFilterBarHandler.onSortersChanged: Sorting is only supported for SmartTable.");
721
+ return;
722
+ }
723
+
724
+ var oUiState = oControl.getUiState();
725
+ var oPresentationVariant = oUiState.getPresentationVariant();
726
+
727
+ oPresentationVariant.SortOrder = undefined; // Clear existing sort order before applying new one
728
+
729
+ // Set new sort order (empty array clears sorting)
730
+ if (aSorters?.length) {
731
+ const aSortersMapped = aSorters.map(function(oSorter) {
732
+ return {
733
+ Property: oSorter.key,
734
+ Descending: !!oSorter.descending
735
+ };
736
+ });
737
+ oPresentationVariant.SortOrder = aSortersMapped;
738
+ bApplyingSorting = true;
739
+ try {
740
+ oUiState.setPresentationVariant(oPresentationVariant);
741
+ oControl.setUiState(oUiState);
742
+ } finally {
743
+ bApplyingSorting = false;
744
+ }
745
+ }
746
+
747
+ } catch (error) {
748
+ bApplyingSorting = false;
749
+ oLogger.warning("EasyFilterBar: unexpected error while handling sortersChanged", String(error));
750
+ }
751
+ }
752
+
753
+ /**
754
+ * Event handler for the EasyFilter control's groupLevelsChanged event.
755
+ * Applies the AI-determined group levels to the SmartTable via setUiState,
756
+ * which updates the data binding and table grouping state
757
+ * through the PersonalizationController.
758
+ * @param {sap.ui.base.Event} oEvent The groupLevelsChanged event containing group level definitions
759
+ */
760
+ function fnGroupLevelsChanged(oEvent) {
761
+ try {
762
+ var aGroupLevels = oEvent.getParameter("groupLevels");
763
+
764
+ var oPresentationControlHandler = oState.oPresentationControlHandler;
765
+ if (!oPresentationControlHandler) {
766
+ oLogger.error("EasyFilterBarHandler.onGroupLevelsChanged: PresentationControlHandler not found.");
767
+ return;
768
+ }
769
+
770
+ var oControl = oPresentationControlHandler.getControl();
771
+ if (!oControl) {
772
+ oLogger.error("EasyFilterBarHandler.onGroupLevelsChanged: Presentation control not found.");
773
+ return;
774
+ }
775
+
776
+ if (!controlHelper.isSmartTable(oControl)) {
777
+ oLogger.warning("EasyFilterBarHandler.onGroupLevelsChanged: Grouping is only supported for SmartTable.");
778
+ return;
779
+ }
780
+
781
+ var oUiState = oControl.getUiState();
782
+ var oPresentationVariant = oUiState.getPresentationVariant();
783
+
784
+ oPresentationVariant.GroupBy = undefined; // Clear existing group levels before applying new ones
785
+
786
+ // SmartTable supports grouping by only one column at a time,
787
+ // so we take only the first group level even if multiple are provided.
788
+ oPresentationVariant.GroupBy = (aGroupLevels && aGroupLevels.length) ?
789
+ aGroupLevels?.flatMap(aGroup => Object.values(aGroup)) : undefined;
790
+
791
+ bApplyingGrouplevels = true;
792
+ try {
793
+ oControl.setUiState(oUiState);
794
+ } finally {
795
+ bApplyingGrouplevels = false;
796
+ }
797
+ } catch (error) {
798
+ bApplyingGrouplevels = false;
799
+ oLogger.warning("EasyFilterBar: unexpected error while handling groupLevelsChanged", String(error));
800
+ }
801
+ }
802
+
521
803
  /**
522
804
  * Event handler for the EasyFilter control's showValueHelp event.
523
805
  * Identifies the input field for which the value help is requested and triggers the value help opening from SFB.
524
- * @param {*} oEvent
525
- * @param {*} oState
806
+ * @param {*} oEvent
807
+ * @param {*} oState
526
808
  */
527
809
  function fnShowValueHelp(oEvent) {
528
810
  var oSmartFilterbar = oState.oSmartFilterbar;
@@ -540,6 +822,8 @@ sap.ui.define([
540
822
  function fnQueryChanged() {
541
823
  var oSmartFilterbar = oState.oSmartFilterbar;
542
824
  oSmartFilterbar.fireFilterChange();
825
+ // Query string is now part of variant state — mark dirty so user is prompted to save
826
+ oSmartFilterbar.getSmartVariant() && oSmartFilterbar.getSmartVariant().currentVariantSetModified(true);
543
827
  }
544
828
  // function fnUpdateEasyFilterBarTokens() {
545
829
  // // todo : update the easy filter bar tokens with new values from the SFB VHD
@@ -602,18 +886,70 @@ sap.ui.define([
602
886
  }
603
887
 
604
888
  /**
605
- *
606
- * This method is called when the variant is loaded in SFB
607
- * Always set the filterMode to classic when the variant is loaded as the variant filters are not supported in the EasyFilter
608
- * */
889
+ * Called when a variant is loaded in SFB.
890
+ * Restores filterMode and EasyFilter query from the variant's genericData.
891
+ * Only reacts to user-initiated variant switches (context === undefined/null).
892
+ * INIT is handled separately in fnInitialiseEasyFilterBar by reading getCustomFilterData().
893
+ * Other contexts (CANCEL, RESET, SET_VM_ID, DATA_SUITE, KEY_USER) leave filterMode unchanged.
894
+ * @param {object} oEvent - The variant load event
895
+ */
609
896
  function fnHandleVariantLoad(oEvent) {
897
+ var sContext = oEvent.getParameter("context");
898
+
899
+ // Only handle user-initiated variant switch (context is undefined/null)
900
+ if (sContext) {
901
+ return;
902
+ }
903
+
904
+ // A variant switch always resets the "tokens modified" disable state —
905
+ // the incoming variant represents a fresh, valid saved state.
906
+ bTokensModifiedByUser = false;
907
+ fnSetCreationAllowed(true);
908
+
610
909
  var oTempModel = oTemplateUtils.oComponentUtils.getTemplatePrivateModel();
611
- // 'context' is undefined or null when the user switches variant , in this case switch to classic mode
612
- // other values are "CANCEL" , "RESET" , "SET_VM_ID" , "DATA_SUITE" , "INIT" , "KEY_USER" etc : Do not switch filter mode in these cases
613
- if (!oEvent.getParameter("context") && oTempModel.getProperty("/listReport/filterMode") !== "classic") {
614
- var oSmartFilterbar = oState.oSmartFilterbar;
615
- oTempModel.setProperty("/listReport/filterMode", "classic");
616
- oSmartFilterbar.setVisible(true);
910
+ var oCustomData = oState.oSmartFilterbar.getCustomFilterData();
911
+ var oGenericData = oCustomData && oCustomData["sap.suite.ui.generic.template.genericData"];
912
+
913
+ var oEasyFilterBar = fnGetEasyFilterBar();
914
+ if (oGenericData && oGenericData.filterMode === "easyFilter") {
915
+ // Genuine user-initiated variant switch — restore the saved query
916
+ // unconditionally (no getQuery guard needed here, unlike the
917
+ // afterVariantLoad path which fires spuriously from setUiState calls).
918
+ sLoadedVariantFilterMode = "easyFilter";
919
+ oTempModel.setProperty("/listReport/filterMode", "easyFilter");
920
+ oState.oSmartFilterbar.setVisible(false);
921
+ var sQuery = oGenericData.easyFilter && oGenericData.easyFilter.query;
922
+ if (oEasyFilterBar) {
923
+ if (sQuery) {
924
+ oEasyFilterBar.setQuery(sQuery);
925
+ // Only auto-trigger Go if "Apply Automatically" is checked on the variant.
926
+ // If not checked, only the search string is restored — no search triggered.
927
+ var bExecuteOnSelect = oEvent.getParameter("executeOnSelect");
928
+ if (bExecuteOnSelect) {
929
+ oEasyFilterBar.onGoPress(sQuery);
930
+ }
931
+ } else {
932
+ oEasyFilterBar.resetState(false);
933
+ }
934
+ }
935
+ } else if (oGenericData && oGenericData.filterMode) {
936
+ sLoadedVariantFilterMode = oGenericData.filterMode;
937
+ fnApplyEasyFilterVariantState({
938
+ filterMode: oGenericData.filterMode,
939
+ easyFilter: oGenericData.easyFilter
940
+ });
941
+ } else {
942
+ // Variant has no EasyFilter state → implicitly classic
943
+ sLoadedVariantFilterMode = "classic";
944
+ if (oTempModel.getProperty("/listReport/filterMode") !== "classic") {
945
+ oTempModel.setProperty("/listReport/filterMode", "classic");
946
+ oState.oSmartFilterbar.setVisible(true);
947
+ }
948
+ // Clear the EasyFilter input and tokens so the old query is not shown
949
+ // when the user switches back to a classic variant.
950
+ if (oEasyFilterBar) {
951
+ oEasyFilterBar.resetState(false);
952
+ }
617
953
  }
618
954
  }
619
955
 
@@ -621,6 +957,51 @@ sap.ui.define([
621
957
  return EasyFilterDataFetcherHelper.fetchDataForKey(key, keySpecificSelectedResult, oState, oController, oTemplateUtils);
622
958
  }
623
959
 
960
+ /**
961
+ * Handles SmartTable uiStateChange events to detect user-initiated sort/group changes.
962
+ * When the user changes sort/group via column menu or P13n dialog (not triggered by EasyFilter),
963
+ * notifies the EasyFilterBarContainer so it can mark the filter input as dirty.
964
+ */
965
+ function fnOnSmartTableUiStateChange() {
966
+ if (bApplyingSorting || bApplyingGrouplevels) {
967
+ return;
968
+ }
969
+ var oEasyFilter = fnGetEasyFilterBar();
970
+ if (oEasyFilter && typeof oEasyFilter.notifyExternalTableStateChange === "function") {
971
+ oEasyFilter.notifyExternalTableStateChange();
972
+ }
973
+ }
974
+
975
+ /**
976
+ * Attaches the uiStateChange handler to the SmartTable to track external sort/group changes.
977
+ * Should be called after SmartTable is initialized.
978
+ */
979
+ function fnAttachSmartTableStateChangeHandler() {
980
+ var oPresentationControlHandler = oState.oPresentationControlHandler;
981
+ if (!oPresentationControlHandler) {
982
+ return;
983
+ }
984
+ var oSmartTable = oPresentationControlHandler.getControl();
985
+ if (oSmartTable && typeof oSmartTable.attachUiStateChange === "function") {
986
+ oSmartTable.attachUiStateChange(fnOnSmartTableUiStateChange);
987
+ }
988
+ }
989
+
990
+ /**
991
+ * Detaches the uiStateChange handler from the SmartTable.
992
+ * Should be called on cleanup/destroy.
993
+ */
994
+ function fnDetachSmartTableStateChangeHandler() {
995
+ var oPresentationControlHandler = oState.oPresentationControlHandler;
996
+ if (!oPresentationControlHandler) {
997
+ return;
998
+ }
999
+ var oSmartTable = oPresentationControlHandler.getControl();
1000
+ if (oSmartTable && typeof oSmartTable.detachUiStateChange === "function") {
1001
+ oSmartTable.detachUiStateChange(fnOnSmartTableUiStateChange);
1002
+ }
1003
+ }
1004
+
624
1005
  return {
625
1006
  getEasyFilterBar : fnGetEasyFilterBar,
626
1007
  initialiseEasyFilterBar : fnInitialiseEasyFilterBar,
@@ -631,10 +1012,16 @@ sap.ui.define([
631
1012
  onBeforeQueryProcessing: fnBeforeQueryProcessing,
632
1013
  onQueryChanged : fnQueryChanged,
633
1014
  onTokensChanged: fnTokensChanged,
1015
+ onTokensChangedByUser: fnTokensChangedByUser,
1016
+ onSortersChanged: fnSortersChanged,
1017
+ onGroupLevelsChanged: fnGroupLevelsChanged,
634
1018
  onShowValueHelp: fnShowValueHelp,
635
1019
  onFilterChange : fnOnFilterChange,
636
1020
  handleVariantLoad : fnHandleVariantLoad,
637
- onDataFetcher
1021
+ onDataFetcher,
1022
+ getLoadedVariantFilterMode: function() { return sLoadedVariantFilterMode; },
1023
+ attachSmartTableStateChangeHandler: fnAttachSmartTableStateChangeHandler,
1024
+ detachSmartTableStateChangeHandler: fnDetachSmartTableStateChangeHandler
638
1025
  };
639
1026
  }
640
1027
 
@@ -828,3 +828,24 @@ EASYFILL_RESULT_FEEDBACK=Feedback sent
828
828
 
829
829
  # XBUT: EasyFill clear all
830
830
  EASYFILL_CLEAR_ALL=Clear All
831
+
832
+ # XTXT: EasyFill informational message for staged table row updates
833
+ EASY_FILL_TABLE_UPDATES_INFO = Table row updates were detected and will be applied when you confirm.
834
+
835
+ # XBUT: EasyFill table preview previous values segment
836
+ EASY_FILL_TABLE_VIEW_PREVIOUS = Previous
837
+
838
+ # XBUT: EasyFill table preview new values segment
839
+ EASY_FILL_TABLE_VIEW_NEW = New
840
+
841
+ # XTXT: EasyFill table row label used in validation messages
842
+ EASY_FILL_TABLE_ROW_LABEL = Row {0}
843
+
844
+ # XTXT: EasyFill table value-help validation error summary
845
+ EASY_FILL_TABLE_VALIDATION_MESSAGE = Some table values are invalid for value help: {0}. Update your request and try again.
846
+
847
+ # XTXT: EasyFill suffix shown in table preview cells with invalid value-help values
848
+ EASY_FILL_TABLE_INVALID_CELL_SUFFIX = (invalid)
849
+
850
+ # XTIT: EasyFill Section Title
851
+ EASY_FILL_SECTION_HEADER = Header
@@ -263,7 +263,7 @@ UNNAMED_OBJECT=\u540D\u524D\u306E\u306A\u3044\u30AA\u30D6\u30B8\u30A7\u30AF\u30C
263
263
 
264
264
  NOITEMS_SMARTTABLE=\u5229\u7528\u53EF\u80FD\u306A\u30A2\u30A4\u30C6\u30E0\u304C\u3042\u308A\u307E\u305B\u3093
265
265
 
266
- NOITEMS_SMARTTABLE_ILLUSTRATION_TITLE=\u30A8\u30F3\u30C8\u30EA\u304C\u307E\u3060\u3042\u308A\u307E\u305B\u3093\u3002
266
+ NOITEMS_SMARTTABLE_ILLUSTRATION_TITLE=\u30A8\u30F3\u30C8\u30EA\u304C\u307E\u3060\u3042\u308A\u307E\u305B\u3093
267
267
 
268
268
  NOITEMS_SMARTTABLE_ILLUSTRATION_DESCRIPTION=\u3042\u308B\u5834\u5408\u306F\u3001\u3053\u3053\u306B\u8868\u793A\u3055\u308C\u307E\u3059\u3002
269
269
 
@@ -281,7 +281,7 @@ NOITEMS_SMARTTABLE_WITH_FILTER_FOR_SEGMENTEDBUTTON_ILLUSTRATION_DESCRIPTION=\u30
281
281
 
282
282
  NOITEMS_SMARTCHART=\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093\u3002
283
283
 
284
- NOITEMS_SMARTCHART_ILLUSTRATION_TITLE=\u30A8\u30F3\u30C8\u30EA\u306F\u307E\u3060\u3042\u308A\u307E\u305B\u3093\u3002
284
+ NOITEMS_SMARTCHART_ILLUSTRATION_TITLE=\u30A8\u30F3\u30C8\u30EA\u306F\u307E\u3060\u3042\u308A\u307E\u305B\u3093
285
285
 
286
286
  NOITEMS_SMARTCHART_ILLUSTRATION_DESCRIPTION=\u3042\u308B\u5834\u5408\u306F\u3001\u3053\u3053\u306B\u8868\u793A\u3055\u308C\u307E\u3059\u3002
287
287
 
@@ -293,7 +293,7 @@ NOITEMS_LR_SMARTCHART_ILLUSTRATION_DESCRIPTION=\u30D3\u30E5\u30FC\u307E\u305F\u3
293
293
 
294
294
  NOITEMS_SMARTCHART_WITH_FILTER=\u30C7\u30FC\u30BF\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30D5\u30A3\u30EB\u30BF\u30D1\u30E9\u30E1\u30FC\u30BF\u306E\u8ABF\u6574\u3092\u8A66\u3057\u3066\u304F\u3060\u3055\u3044\u3002
295
295
 
296
- NOITEMS_SMARTCHART_WITH_FILTER_ILLUSTRATION_TITLE=\u7D50\u679C\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002
296
+ NOITEMS_SMARTCHART_WITH_FILTER_ILLUSTRATION_TITLE=\u7D50\u679C\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F
297
297
 
298
298
  NOITEMS_SMARTCHART_WITH_FILTER_ILLUSTRATION_DESCRIPTION=\u30D5\u30A3\u30EB\u30BF\u57FA\u6E96\u306E\u5909\u66F4\u3092\u8A66\u3057\u3066\u304F\u3060\u3055\u3044\u3002
299
299
 
@@ -305,7 +305,7 @@ SMARTCHART_INITIAL_NODATA_ILLUSTRATION_DESCRIPTION=\u691C\u7D22\u307E\u305F\u306
305
305
 
306
306
  NOITEMS_LR_SMARTTABLE=\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093\u3002
307
307
 
308
- NOITEMS_LR_SMARTTABLE_ILLUSTRATION_TITLE=\u30A8\u30F3\u30C8\u30EA\u304C\u307E\u3060\u3042\u308A\u307E\u305B\u3093\u3002
308
+ NOITEMS_LR_SMARTTABLE_ILLUSTRATION_TITLE=\u30A8\u30F3\u30C8\u30EA\u304C\u307E\u3060\u3042\u308A\u307E\u305B\u3093
309
309
 
310
310
  NOITEMS_LR_SMARTTABLE_ILLUSTRATION_DESCRIPTION=\u3042\u308B\u5834\u5408\u306F\u3001\u3053\u3053\u306B\u8868\u793A\u3055\u308C\u307E\u3059\u3002
311
311
 
@@ -506,7 +506,7 @@ EASY_FILL_SECOND_LABEL_TEXT=\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u30
506
506
 
507
507
  EASY_FILL_TEXTAREA_PLACEHOLDER=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u4F7F\u7528\u3059\u308B\u304B\u3001\u624B\u52D5\u3067\u3001\u5FC5\u8981\u306A\u60C5\u5831\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002
508
508
 
509
- EASY_FILL_ILLUSTRATION_TITLE_INITIAL=\u4E00\u90E8\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u306B\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002
509
+ EASY_FILL_ILLUSTRATION_TITLE_INITIAL=\u4E00\u90E8\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u306B\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
510
510
 
511
511
  EASY_FILL_ILLUSTRATION_DESCRIPTION_INITIAL=\u6700\u521D\u306B\u5FC5\u8981\u306A\u60C5\u5831\u3092\u5165\u529B\u3059\u308B\u3068\u3001\u7D50\u679C\u304C\u63D0\u6848\u3055\u308C\u3001\u8868\u793A\u3055\u308C\u307E\u3059\u3002
512
512
 
@@ -514,7 +514,7 @@ EASY_FILL_ILLUSTRATION_TITLE_NO_ENTRIES=\u5165\u529B\u3055\u308C\u305F\u30D5\u30
514
514
 
515
515
  EASY_FILL_ILLUSTRATION_DESCRIPTION_NO_ENTRIES=\u30AF\u30A8\u30EA\u304C\u65E2\u5B58\u306E\u3069\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u306B\u3082\u5408\u81F4\u3057\u307E\u305B\u3093\u3067\u3057\u305F\u3002
516
516
 
517
- EASY_FILL_ILLUSTRATION_TITLE_ERROR=\u30D5\u30A3\u30FC\u30EB\u30C9\u306B\u5165\u529B\u3067\u304D\u307E\u305B\u3093\u3002
517
+ EASY_FILL_ILLUSTRATION_TITLE_ERROR=\u30D5\u30A3\u30FC\u30EB\u30C9\u306B\u5165\u529B\u3067\u304D\u307E\u305B\u3093
518
518
 
519
519
  EASY_FILL_ILLUSTRATION_DESCRIPTION_ERROR=\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u305F\u3088\u3046\u3067\u3059\u3002\u518D\u8A66\u884C\u3057\u3001\u305D\u308C\u3067\u3082\u89E3\u6C7A\u3067\u304D\u306A\u3044\u5834\u5408\u306F\u3001\u7BA1\u7406\u8005\u306B\u554F\u3044\u5408\u308F\u305B\u3066\u304F\u3060\u3055\u3044\u3002
520
520
 
@@ -265,7 +265,7 @@ NOITEMS_SMARTTABLE=\u041D\u0435\u043C\u0430\u0454 \u0434\u043E\u0441\u0442\u0443
265
265
 
266
266
  NOITEMS_SMARTTABLE_ILLUSTRATION_TITLE=\u0417\u0430\u043F\u0438\u0441\u0456\u0432 \u0449\u0435 \u043D\u0435\u043C\u0430\u0454
267
267
 
268
- NOITEMS_SMARTTABLE_ILLUSTRATION_DESCRIPTION=\u041E\u0434\u0440\u0430\u0437\u0443 \u043F\u0456\u0441\u043B\u044F \u043F\u043E\u044F\u0432\u0438 \u0432\u0438 \u043F\u043E\u0431\u0430\u0447\u0438\u0442\u0435 \u0457\u0445 \u0442\u0443\u0442.
268
+ NOITEMS_SMARTTABLE_ILLUSTRATION_DESCRIPTION=\u041A\u043E\u043B\u0438 \u0432\u043E\u043D\u0438 \u0437\u2019\u044F\u0432\u043B\u044F\u0442\u044C\u0441\u044F, \u0432\u0438 \u043F\u043E\u0431\u0430\u0447\u0438\u0442\u0435 \u0457\u0445 \u0442\u0443\u0442.
269
269
 
270
270
  NOITEMS_SMARTTABLE_WITH_FILTER=\u041F\u043E\u0437\u0438\u0446\u0456\u0457 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0456. \u0421\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u0441\u043A\u043E\u0440\u0438\u0433\u0443\u0432\u0430\u0442\u0438 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0438 \u043F\u043E\u0448\u0443\u043A\u0443 \u0430\u0431\u043E \u0444\u0456\u043B\u044C\u0442\u0440\u0430\u0446\u0456\u0457
271
271
 
@@ -283,7 +283,7 @@ NOITEMS_SMARTCHART=\u0414\u0430\u043D\u0456 \u043D\u0435 \u0437\u043D\u0430\u043
283
283
 
284
284
  NOITEMS_SMARTCHART_ILLUSTRATION_TITLE=\u0417\u0430\u043F\u0438\u0441\u0456\u0432 \u0449\u0435 \u043D\u0435\u043C\u0430\u0454
285
285
 
286
- NOITEMS_SMARTCHART_ILLUSTRATION_DESCRIPTION=\u041E\u0434\u0440\u0430\u0437\u0443 \u043F\u0456\u0441\u043B\u044F \u043F\u043E\u044F\u0432\u0438 \u0432\u0438 \u043F\u043E\u0431\u0430\u0447\u0438\u0442\u0435 \u0457\u0445 \u0442\u0443\u0442.
286
+ NOITEMS_SMARTCHART_ILLUSTRATION_DESCRIPTION=\u041A\u043E\u043B\u0438 \u0432\u043E\u043D\u0438 \u0437\u2019\u044F\u0432\u043B\u044F\u0442\u044C\u0441\u044F, \u0432\u0438 \u043F\u043E\u0431\u0430\u0447\u0438\u0442\u0435 \u0457\u0445 \u0442\u0443\u0442.
287
287
 
288
288
  NOITEMS_LR_SMARTCHART=\u041D\u0435\u043C\u0430\u0454 \u0434\u0430\u043D\u0438\u0445 \u0434\u043B\u044F \u0432\u0438\u0431\u0440\u0430\u043D\u0438\u0445 \u043A\u0440\u0438\u0442\u0435\u0440\u0456\u0457\u0432 \u0444\u0456\u043B\u044C\u0442\u0440\u0430 \u0456 \u043F\u043E\u0434\u0430\u043D\u043D\u044F \u0434\u0456\u0430\u0433\u0440\u0430\u043C\u0438.
289
289
 
@@ -307,7 +307,7 @@ NOITEMS_LR_SMARTTABLE=\u0414\u0430\u043D\u0456 \u043D\u0435 \u0437\u043D\u0430\u
307
307
 
308
308
  NOITEMS_LR_SMARTTABLE_ILLUSTRATION_TITLE=\u0417\u0430\u043F\u0438\u0441\u0456\u0432 \u0449\u0435 \u043D\u0435\u043C\u0430\u0454
309
309
 
310
- NOITEMS_LR_SMARTTABLE_ILLUSTRATION_DESCRIPTION=\u041E\u0434\u0440\u0430\u0437\u0443 \u043F\u0456\u0441\u043B\u044F \u043F\u043E\u044F\u0432\u0438 \u0432\u0438 \u043F\u043E\u0431\u0430\u0447\u0438\u0442\u0435 \u0457\u0445 \u0442\u0443\u0442.
310
+ NOITEMS_LR_SMARTTABLE_ILLUSTRATION_DESCRIPTION=\u041A\u043E\u043B\u0438 \u0432\u043E\u043D\u0438 \u0437\u2019\u044F\u0432\u043B\u044F\u0442\u044C\u0441\u044F, \u0432\u0438 \u043F\u043E\u0431\u0430\u0447\u0438\u0442\u0435 \u0457\u0445 \u0442\u0443\u0442.
311
311
 
312
312
  NOITEMS_LR_SMARTTABLE_WITH_FILTER=\u0414\u0430\u043D\u0456 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u0456. \u0421\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438 \u043F\u043E\u0448\u0443\u043A \u0430\u0431\u043E \u043A\u0440\u0438\u0442\u0435\u0440\u0456\u0457 \u0444\u0456\u043B\u044C\u0442\u0440\u0430.
313
313