@sapui5/sap.suite.ui.generic.template 1.148.6 → 1.148.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.
Files changed (21) 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/manifest.json +1 -1
  4. package/src/sap/suite/ui/generic/template/Canvas/manifest.json +1 -1
  5. package/src/sap/suite/ui/generic/template/ListReport/AnnotationHelperSmartList.js +1 -1
  6. package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
  7. package/src/sap/suite/ui/generic/template/ObjectPage/controller/ControllerImplementation.js +3 -1
  8. package/src/sap/suite/ui/generic/template/ObjectPage/controller/RelatedAppsHandler.js +1 -1
  9. package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +1 -1
  10. package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
  11. package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
  12. package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartFilterBarWrapper.js +32 -55
  13. package/src/sap/suite/ui/generic/template/lib/AppComponent.js +3 -1
  14. package/src/sap/suite/ui/generic/template/lib/Application.js +15 -2
  15. package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +30 -8
  16. package/src/sap/suite/ui/generic/template/lib/CommonUtils.js +3 -3
  17. package/src/sap/suite/ui/generic/template/lib/PageLeaveHandler.js +19 -14
  18. package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +111 -14
  19. package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterDataFetcherHelper.js +1 -1
  20. package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +1 -1
  21. package/src/sap/suite/ui/generic/template/library.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sapui5/sap.suite.ui.generic.template",
3
- "version": "1.148.6",
3
+ "version": "1.148.8",
4
4
  "description": "SAPUI5 Library sap.suite.ui.generic.template",
5
5
  "keywords": [
6
6
  "sapui5",
@@ -7,7 +7,7 @@
7
7
 
8
8
  (c) Copyright 2009-2015 SAP SE. All rights reserved
9
9
  </copyright>
10
- <version>1.148.6</version>
10
+ <version>1.148.8</version>
11
11
 
12
12
  <documentation>Library with generic Suite UI templates.</documentation>
13
13
 
@@ -8,7 +8,7 @@
8
8
  "i18n": "i18n/i18n.properties",
9
9
  "applicationVersion": {
10
10
  "__comment": "applicationVersion oder componentversion??",
11
- "version": "1.148.6"
11
+ "version": "1.148.8"
12
12
  },
13
13
  "title": "{{TITLE}}",
14
14
  "description": "{{DESCRIPTION}}",
@@ -8,7 +8,7 @@
8
8
  "i18n": "i18n/i18n.properties",
9
9
  "applicationVersion": {
10
10
  "__comment": "applicationVersion oder componentversion??",
11
- "version": "1.148.6"
11
+ "version": "1.148.8"
12
12
  },
13
13
  "title": "Canvas",
14
14
  "description": "Canvas Page",
@@ -108,7 +108,7 @@ sap.ui.define([
108
108
  aCollection.sort(function (oFirstData, oSecondData) {
109
109
  var iFirstDataImportance = getImportance(oFirstData);
110
110
  var iSecondDataImportance = getImportance(oSecondData);
111
- return iFirstDataImportance < iSecondDataImportance ? -1 : 1;
111
+ return iFirstDataImportance < iSecondDataImportance ? -1 : iFirstDataImportance > iSecondDataImportance ? 1 : 0;
112
112
  });
113
113
  }
114
114
 
@@ -8,7 +8,7 @@
8
8
  "i18n": "i18n/i18n.properties",
9
9
  "applicationVersion": {
10
10
  "__comment": "applicationVersion oder componentversion??",
11
- "version": "1.148.6"
11
+ "version": "1.148.8"
12
12
  },
13
13
  "title": "{{TITLE}}",
14
14
  "description": "{{DESCRIPTION}}",
@@ -2770,9 +2770,11 @@ sap.ui.define([
2770
2770
  onDataFieldForIntentBasedNavigation: function (oEvent) {
2771
2771
  oEvent = merge({}, oEvent);
2772
2772
  oTemplateUtils.oServices.oApplication.performAfterSideEffectExecution(function () {
2773
+ var oCustomData = oTemplateUtils.oCommonUtils.getCustomDataFromEvent(oEvent);
2774
+ var oTarget = { semanticObject: oCustomData.SemanticObject, action: oCustomData.Action };
2773
2775
  oTemplateUtils.oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function () {
2774
2776
  oTemplateUtils.oCommonEventHandlers.onDataFieldForIntentBasedNavigation(oEvent, oBase.state);
2775
- }, Function.prototype, "LeaveApp");
2777
+ }, Function.prototype, "LeaveApp", false, oTarget);
2776
2778
  }, true);
2777
2779
  },
2778
2780
  onDataFieldWithIntentBasedNavigation: function (oEvent) {
@@ -25,7 +25,7 @@ sap.ui.define([
25
25
  oTemplateUtils.oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function () {
26
26
  var oContext = oController.getView().getBindingContext();
27
27
  oTemplateUtils.oCommonEventHandlers.onRelatedAppNavigation(oTarget, oContext);
28
- }, Function.prototype, "LeaveApp");
28
+ }, Function.prototype, "LeaveApp", false, oTarget);
29
29
  }
30
30
  }, "buttons");
31
31
  }
@@ -6,7 +6,7 @@
6
6
  "type": "component",
7
7
  "i18n": "i18n/i18n.properties",
8
8
  "applicationVersion": {
9
- "version": "1.148.6"
9
+ "version": "1.148.8"
10
10
  },
11
11
  "title": "{{TITLE}}",
12
12
  "description": "{{DESCRIPTION}}",
@@ -6,7 +6,7 @@
6
6
  "type": "component",
7
7
  "i18n": "i18n/i18n.properties",
8
8
  "applicationVersion": {
9
- "version": "1.148.6"
9
+ "version": "1.148.8"
10
10
  },
11
11
  "title": "{{TITLE}}",
12
12
  "description": "{{DESCRIPTION}}",
@@ -6,7 +6,7 @@
6
6
  "type": "component",
7
7
  "i18n": "i18n/i18n.properties",
8
8
  "applicationVersion": {
9
- "version": "1.148.6"
9
+ "version": "1.148.8"
10
10
  },
11
11
  "title": "{{TITLE}}",
12
12
  "description": "{{DESCRIPTION}}",
@@ -28,6 +28,7 @@ sap.ui.define([
28
28
  var oSmartFilterBar = oControl;
29
29
  var oEasyFilterCallbacks = null;
30
30
  var oPendingEasyFilterState = null;
31
+ var oSVMWrapperCallbacks = null;
31
32
 
32
33
  var oVariantManagementInitializedPromise;
33
34
 
@@ -38,62 +39,15 @@ sap.ui.define([
38
39
  // (which would harm performance). Can only be retrieved in initialized event.
39
40
  oSmartFilterBar.getInitializedPromise().then(function () {
40
41
  aBasicFilters = oSmartFilterBar.getAllFilterItems(true);
41
-
42
- // Cold-start recovery: setSVMWrapperCallbacks registers attachAfterVariantLoad
43
- // after SVM has already fired afterVariantLoad("INIT"), so the _CUSTOM restore
44
- // handler in setSVMWrapperCallbacks is never reached on first page load.
45
- // By this point getInitializedPromise has resolved, setSVMWrapperCallbacks has
46
- // run, and the variant is active — apply the _CUSTOM fallback now if
47
- // getCustomFilterData() is still null (i.e. no beforeVariantFetch has run yet).
48
- if (!oSmartFilterBar.getCustomFilterData()) {
49
- try {
50
- var oSVM = oSmartFilterBar.getSmartVariant();
51
- var sVariantKey = oSVM && (oSVM.getCurrentVariantKey ? oSVM.getCurrentVariantKey() : oSVM.getStandardVariantKey());
52
- var oVariantContent = oSVM && oSVM.getVariantContent(oSmartFilterBar, sVariantKey);
53
- var oFilterBarVariant = oVariantContent && oVariantContent.filterBarVariant && JSON.parse(oVariantContent.filterBarVariant);
54
- var oCustomSection = oFilterBarVariant && oFilterBarVariant._CUSTOM;
55
- var oGenericData = (oCustomSection && oCustomSection[dataPropertyNameGeneric]) || Object.create(null);
56
- var oCustomFiltersState = oGenericData.customFilters || {
57
- editState: oGenericData.editStateFilter,
58
- appExtension: oGenericData.appExtension
59
- };
60
- mParams.oCustomFiltersWrapper.setState(oCustomFiltersState);
61
- } catch (e) {
62
- // Silently skip — absence of _CUSTOM data is a valid state for new variants
63
- }
64
- }
65
42
  });
66
43
 
67
44
  // Initialize variant management promise
68
45
  oVariantManagementInitializedPromise = oSmartFilterBar.getInitializedPromise();
69
- }
70
-
71
- // Attach to variantFetch and variantLoad events to be able to store and restore also custom filters and state of other controls (in case of page VM) with variant.
72
- // Events for storing/restoring are provided by SFB, data to be stored/restored can come from 3 sources:
73
- // - standard filters: handled directly by SFB
74
- // - extension filters: provided from mParams.oCustomFiltersWrapper
75
- // - other controls being part of VM: provided by oSVMWrapperCallbacks (controls with direct connection to VM are skipped in SVM wrapper)
76
- function setSVMWrapperCallbacks(oSVMWrapperCallbacks){
77
- // Before saving the current state as a new variant, we need to provide all state data of controls controlled by VM, but not known to it with setCustomFilterData. From a
78
- // logical point of view, the event (beforeVariantFetch) as well as the method to store the extension data (setCustomFilterData) belong to SVM, but both are implemented
79
- // in SFB. Additionally, beforeVariantSave would actually be the name more logical to the consumer, however that name had been used earlier and was deprecated and
80
- // replaced by the given one. Fetch actually does not mean to fetch variant content from the place variants are stored, but to get the current state from the controls!
81
- oSmartFilterBar.attachBeforeVariantFetch(function(){
82
- var oCustomData = Object.create(null);
83
- oCustomData[dataPropertyNameGeneric] = oSVMWrapperCallbacks.getManagedControlStates();
84
- oCustomData[dataPropertyNameGeneric].customFilters = mParams.oCustomFiltersWrapper.getState();
85
- if (oEasyFilterCallbacks) {
86
- var oEFState = oEasyFilterCallbacks.getState();
87
- oCustomData[dataPropertyNameGeneric].filterMode = oEFState.filterMode;
88
- oCustomData[dataPropertyNameGeneric].easyFilter = oEFState.easyFilter;
89
- }
90
- oSmartFilterBar.setCustomFilterData(oCustomData);
91
- });
92
46
 
93
- // When a variant is loaded, correspondingly we have to get the customData and apply the states to the controls not known to SVM. Again, event and method are implemented
94
- // in SFB instead of SVM where it would make more sense.
95
- // Here the event is afterVariantLoad, as the variant content known to SVM/SFB has first to be applied to the SFB, which will also pass the custom data accordingly. Only
96
- // after this has happened, we can get the custom data from SFB.
47
+ // Attach afterVariantLoad eagerly so custom filter state is restored regardless of
48
+ // when setSVMWrapperCallbacks is called. setManagedControlStates is only called if
49
+ // SVM callbacks are already available; otherwise those controls are restored via the
50
+ // iAppState path (SmartVariantManagementWrapper.fnSetManagedControlStates).
97
51
  oSmartFilterBar.attachAfterVariantLoad(function(){
98
52
  var oCustomData = oSmartFilterBar.getCustomFilterData();
99
53
  var oGenericData;
@@ -101,10 +55,8 @@ sap.ui.define([
101
55
  oGenericData = oCustomData[dataPropertyNameGeneric];
102
56
  } else {
103
57
  // getCustomFilterData() returns null when no beforeVariantFetch has run yet for this
104
- // variant (e.g. a named variant being switched to for the first time in the session).
58
+ // variant (e.g. a named variant being switched to for the first time in the session, or cold-start INIT).
105
59
  // The _CUSTOM section is present in the variant content — fall back to reading it via getVariantContent().
106
- // Note: the cold-start case (INIT event) is handled separately in fnInitialize via
107
- // getInitializedPromise().then(), because this listener is registered after INIT fires.
108
60
  try {
109
61
  var oSVM = oSmartFilterBar.getSmartVariant();
110
62
  // getCurrentVariantId() converts STANDARDVARIANTKEY to "" which _getVariantById can't look up.
@@ -127,7 +79,9 @@ sap.ui.define([
127
79
  };
128
80
  aBasicFilters = oSmartFilterBar.getAllFilterItems(true);
129
81
  mParams.oCustomFiltersWrapper.setState(oCustomFiltersState);
130
- oSVMWrapperCallbacks.setManagedControlStates(oGenericData);
82
+ if (oSVMWrapperCallbacks) {
83
+ oSVMWrapperCallbacks.setManagedControlStates(oGenericData);
84
+ }
131
85
  if (oEasyFilterCallbacks) {
132
86
  oEasyFilterCallbacks.setState({
133
87
  filterMode: oGenericData.filterMode,
@@ -140,7 +94,30 @@ sap.ui.define([
140
94
  };
141
95
  }
142
96
  });
97
+ }
143
98
 
99
+ // Attach to variantFetch and variantLoad events to be able to store and restore also custom filters and state of other controls (in case of page VM) with variant.
100
+ // Events for storing/restoring are provided by SFB, data to be stored/restored can come from 3 sources:
101
+ // - standard filters: handled directly by SFB
102
+ // - extension filters: provided from mParams.oCustomFiltersWrapper
103
+ // - other controls being part of VM: provided by oSVMWrapperCallbacks (controls with direct connection to VM are skipped in SVM wrapper)
104
+ function setSVMWrapperCallbacks(oCallbacks){
105
+ oSVMWrapperCallbacks = oCallbacks;
106
+ // Before saving the current state as a new variant, we need to provide all state data of controls controlled by VM, but not known to it with setCustomFilterData. From a
107
+ // logical point of view, the event (beforeVariantFetch) as well as the method to store the extension data (setCustomFilterData) belong to SVM, but both are implemented
108
+ // in SFB. Additionally, beforeVariantSave would actually be the name more logical to the consumer, however that name had been used earlier and was deprecated and
109
+ // replaced by the given one. Fetch actually does not mean to fetch variant content from the place variants are stored, but to get the current state from the controls!
110
+ oSmartFilterBar.attachBeforeVariantFetch(function(){
111
+ var oCustomData = Object.create(null);
112
+ oCustomData[dataPropertyNameGeneric] = oSVMWrapperCallbacks.getManagedControlStates();
113
+ oCustomData[dataPropertyNameGeneric].customFilters = mParams.oCustomFiltersWrapper.getState();
114
+ if (oEasyFilterCallbacks) {
115
+ var oEFState = oEasyFilterCallbacks.getState();
116
+ oCustomData[dataPropertyNameGeneric].filterMode = oEFState.filterMode;
117
+ oCustomData[dataPropertyNameGeneric].easyFilter = oEFState.easyFilter;
118
+ }
119
+ oSmartFilterBar.setCustomFilterData(oCustomData);
120
+ });
144
121
  }
145
122
 
146
123
  function fnGetState() {
@@ -661,6 +661,7 @@ sap.ui.define([
661
661
 
662
662
  function restore(){
663
663
  oTemplateContract.oBusyHelper.setBusyReason("exiting", false);
664
+ oTemplateContract.oApplicationProxy.resetExternalNavigation();
664
665
  for (var sComponentId in oTemplateContract.componentRegistry){
665
666
  var oRegistryEntry = oTemplateContract.componentRegistry[sComponentId];
666
667
  if (oRegistryEntry.methods.onRestore) {
@@ -942,6 +943,7 @@ sap.ui.define([
942
943
  var fnNormalizePagesMapToArray = testableHelper.testable(fnNormalizePagesMapToArray, "fnNormalizePagesMapToArray");
943
944
  getConfig = testableHelper.testable(getConfig, "getConfig");
944
945
  testableHelper.testable(setLeaveAppPromise, "AppComponent_setLeaveAppPromise");
946
+ testableHelper.testable(restore, "AppComponent_restore");
945
947
  /* eslint-enable */
946
948
 
947
949
  return oMethods;
@@ -959,7 +961,7 @@ sap.ui.define([
959
961
  * @public
960
962
  * @extends sap.ui.core.UIComponent
961
963
  * @author SAP SE
962
- * @version 1.148.6
964
+ * @version 1.148.8
963
965
  * @name sap.suite.ui.generic.template.lib.AppComponent
964
966
  */
965
967
  var oAppComponent = UIComponent.extend("sap.suite.ui.generic.template.lib.AppComponent", {
@@ -82,6 +82,11 @@ sap.ui.define(["sap/ui/base/Object",
82
82
  */
83
83
  function getMethods(oTemplateContract) {
84
84
 
85
+ // Set on first fnNavigateExternal call; blocks re-entry until reset. NavigationHandler.navigate() calls fnOnError
86
+ // on all failure paths and does not call it on the success path (app is leaving). The two valid reset points are
87
+ // therefore fnOnErrorWrapper (navigation failed) and AppComponent.restore() (FLP re-activated this app).
88
+ var bExternalNavigationTriggered = false;
89
+
85
90
  var oFocusHelper = new FocusHelper(oTemplateContract);
86
91
  var oContextBookkeeping = new ContextBookkeeping(oTemplateContract);
87
92
  var mEntitySetToETagInfo = Object.create(null); // maps the name of the entity sets which have been already checked for eTag
@@ -671,8 +676,13 @@ sap.ui.define(["sap/ui/base/Object",
671
676
  if (oCurrentNavigationHandler === GHOSTNAVIGATIONHANDLER){
672
677
  return;
673
678
  }
679
+ if (bExternalNavigationTriggered){
680
+ return;
681
+ }
682
+ bExternalNavigationTriggered = true;
674
683
  oTemplateContract.oNavigationControllerProxy.leave();
675
- var fnOnErrorWrapper = function(){
684
+ var fnOnErrorWrapper = function () {
685
+ bExternalNavigationTriggered = false;
676
686
  oFocusHelper.setNextFocus(Function.prototype); // Do not change focus in case exiting the application fails
677
687
  oTemplateContract.oBusyHelper.setBusyReason("exiting", false); // in error case we are not navigating away
678
688
  if (fnOnError){
@@ -834,7 +844,10 @@ sap.ui.define(["sap/ui/base/Object",
834
844
  removeTransientMessages: fnRemoveTransientMessages,
835
845
  getTransientMessages: getTransientMessages,
836
846
  setNextFocus: oFocusHelper.setNextFocus,
837
- setStates: setStates
847
+ setStates: setStates,
848
+ resetExternalNavigation: function() {
849
+ bExternalNavigationTriggered = false;
850
+ }
838
851
  };
839
852
 
840
853
  return {
@@ -720,7 +720,16 @@ sap.ui.define(["sap/ui/base/Object",
720
720
  }
721
721
 
722
722
  // null object has to be passed as the fourth argument (i.e. for oInnerAppData) to the navigate method as an indicator that the state should not be overwritten
723
- oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
723
+ // Explace outbounds must bypass fnNavigateExternal to avoid setting the app busy and consuming the re-entry guard.
724
+ // getNavigationHandler() returns a ghost stub (no .navigate) when ghostapp=true — guard before calling.
725
+ if (oOutbound.parameters && oOutbound.parameters["sap-ushell-navmode"] === "explace") {
726
+ var oNavHandler = oServices.oApplication.getNavigationHandler();
727
+ if (oNavHandler.navigate) {
728
+ oNavHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError, null, "explace");
729
+ }
730
+ } else {
731
+ oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
732
+ }
724
733
  }
725
734
 
726
735
  function fnNavigateIntentSmartLink(oOutbound, oEventSource) {
@@ -803,9 +812,10 @@ sap.ui.define(["sap/ui/base/Object",
803
812
 
804
813
  function fnOnSemanticObjectLinkNavigationPressed(oEventSource, oEventParameters){
805
814
  var oEventObject = deepExtend({}, oEventSource);
815
+ var sSemanticObject = oEventObject.data('SemanticObject');
816
+ var sAction = oEventObject.data('Action');
817
+ var oTarget = (sSemanticObject && sAction) ? { semanticObject: sSemanticObject, action: sAction } : undefined;
806
818
  oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function() {
807
- var sSemanticObject = oEventObject.data('SemanticObject');
808
- var sAction = oEventObject.data('Action');
809
819
  var sSemanticAttributes = oEventObject.data('SemanticAttributes');
810
820
  if (sSemanticObject && sAction){
811
821
  var oOutbound = {
@@ -818,7 +828,7 @@ sap.ui.define(["sap/ui/base/Object",
818
828
  }
819
829
  fnNavigateIntentSmartLink(oOutbound, oEventObject);
820
830
  }
821
- }, Function.prototype, "LeaveApp");
831
+ }, Function.prototype, "LeaveApp", false, oTarget);
822
832
  }
823
833
 
824
834
  function fnOnSemanticObjectLinkNavigationTargetObtained(sEntitySet, mFieldSemanticObjects, oEventParameters, oState, sTitle) {
@@ -1988,6 +1998,7 @@ sap.ui.define(["sap/ui/base/Object",
1988
1998
  var oContext = oEventSource.getParent().getBindingContext();
1989
1999
  var sSemanticObject = oEventSource.data("SemanticObject");
1990
2000
  var sAction = oEventSource.data("Action");
2001
+ var oTarget = { semanticObject: sSemanticObject, action: sAction };
1991
2002
 
1992
2003
  oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function() {
1993
2004
  var oOutbound = {
@@ -1995,7 +2006,7 @@ sap.ui.define(["sap/ui/base/Object",
1995
2006
  semanticObject: sSemanticObject
1996
2007
  };
1997
2008
  fnNavigateIntent(oOutbound, [oContext], oState.oSmartFilterbar || undefined);
1998
- }, Function.prototype, "LeaveApp");
2009
+ }, Function.prototype, "LeaveApp", false, oTarget);
1999
2010
  }
2000
2011
 
2001
2012
  /*
@@ -2025,13 +2036,15 @@ sap.ui.define(["sap/ui/base/Object",
2025
2036
  if (bRequiresContext && !aSelectedContexts.length) { // not consistent, since contexts missing
2026
2037
  fnShowMessageForInvalidNumberOfSelects(aSelectedContexts.length);
2027
2038
  } else {
2039
+ var oTarget = { semanticObject: oCustomData.SemanticObject, action: oCustomData.Action };
2028
2040
  oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function () {
2029
2041
  onDataFieldForIntentBasedNavigationSelectedContext(oCustomData, aSelectedContexts, oSmartFilterbar);
2030
- }, Function.prototype, "LeaveApp");
2042
+ }, Function.prototype, "LeaveApp", false, oTarget);
2031
2043
  }
2032
2044
  }
2033
2045
 
2034
2046
  function onInlineDataFieldForIntentBasedNavigation(oEventSource, oState){
2047
+ var oTarget = { semanticObject: oEventSource.data("SemanticObject"), action: oEventSource.data("Action") };
2035
2048
  oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function() {
2036
2049
  var oOutbound = {
2037
2050
  semanticObject: oEventSource.data("SemanticObject"),
@@ -2039,7 +2052,7 @@ sap.ui.define(["sap/ui/base/Object",
2039
2052
  };
2040
2053
  var oContext = oEventSource.getParent().getBindingContext();
2041
2054
  fnNavigateIntent(oOutbound, [oContext], oState.oSmartFilterbar);
2042
- }, Function.prototype, "LeaveApp");
2055
+ }, Function.prototype, "LeaveApp", false, oTarget);
2043
2056
  }
2044
2057
 
2045
2058
  function onInlineDataFieldForAction(oEvent) {
@@ -2709,7 +2722,16 @@ sap.ui.define(["sap/ui/base/Object",
2709
2722
  var oSelectionVariant = fnBuildSelectionVariantForNavigation(oOutbound, [], oContext);
2710
2723
  oController.adaptNavigationParameterExtension(oSelectionVariant, oOutbound);
2711
2724
  oCommonUtils.setComponentRefreshBehaviour(oOutbound);
2712
- oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
2725
+ // Explace outbounds must bypass fnNavigateExternal to avoid setting the app busy and consuming the re-entry guard.
2726
+ // getNavigationHandler() returns a ghost stub (no .navigate) when ghostapp=true — guard before calling.
2727
+ if (oOutbound.parameters && oOutbound.parameters["sap-ushell-navmode"] === "explace") {
2728
+ var oNavHandler = oServices.oApplication.getNavigationHandler();
2729
+ if (oNavHandler.navigate) {
2730
+ oNavHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError, null, "explace");
2731
+ }
2732
+ } else {
2733
+ oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
2734
+ }
2713
2735
  }
2714
2736
 
2715
2737
  function onSmartFieldInitialise(oEvent,sViewId){
@@ -845,7 +845,7 @@ sap.ui.define(["sap/ui/base/Object",
845
845
  //indicator that the state should not be overwritten
846
846
  //if draft enabled then passing NavigateExternal else on back button passing LeavePage
847
847
  }
848
- }, Function.prototype, "LeaveApp");
848
+ }, Function.prototype, "LeaveApp", false, { semanticObject: oOutbound.semanticObject, action: oOutbound.action });
849
849
  }
850
850
 
851
851
  function fnGetNavigationKeyProperties(sTargetEntitySet) {
@@ -1369,10 +1369,10 @@ sap.ui.define(["sap/ui/base/Object",
1369
1369
  // "LeaveApp": leave the app via a forward navigation
1370
1370
  // "LeavePage": leave the page via an internal navigation or a backward navigation (which may or may not be internal)
1371
1371
  // Note: if sMode is faulty it will be considered as "LeavePage"
1372
- function fnProcessDataLossOrDraftDiscardConfirmation(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck){
1372
+ function fnProcessDataLossOrDraftDiscardConfirmation(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, oTarget){
1373
1373
  sMode = sMode || "LeavePage";
1374
1374
  if (oComponentUtils.isDraftEnabled()){
1375
- return oServices.oPageLeaveHandler.performAfterDiscardOrKeepDraft(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, false);
1375
+ return oServices.oPageLeaveHandler.performAfterDiscardOrKeepDraft(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, false, oTarget);
1376
1376
  } else {
1377
1377
  return oServices.oDataLossHandler.performIfNoDataLoss(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, false);
1378
1378
  }
@@ -22,19 +22,24 @@ sap.ui.define(["sap/ui/base/Object",
22
22
  firstListItemOption.focus();
23
23
  }
24
24
 
25
- function checkIfNavigationIsExplace() {
25
+ function checkIfNavigationIsExplace(oTarget) {
26
26
  var UShellContainer = sap.ui.require("sap/ushell/Container");
27
27
  if (!UShellContainer) {
28
- return Promise.resolve(false); // No UShell container, assume inplace navigation
28
+ return Promise.resolve(false);
29
29
  }
30
30
 
31
- return UShellContainer.getServiceAsync("FioriElements").then(function(oFioriElementsService) {
32
- if (oFioriElementsService && typeof oFioriElementsService.isExplaceNavigation === "function") {
33
- return oFioriElementsService.isExplaceNavigation();
34
- }
35
- return false; // API not available, default to inplace behavior
36
- }).catch(function() {
37
- return false; // Service not available or error, default to inplace behavior
31
+ return new Promise(function(resolve) {
32
+ sap.ui.require(["sap/ushell/api/FioriElements"], function(FioriElements) {
33
+ FioriElements.isExplaceNavigation(oTarget ? { target: oTarget } : undefined)
34
+ .then(function(bExplace) {
35
+ resolve(bExplace);
36
+ })
37
+ .catch(function() {
38
+ resolve(false);
39
+ });
40
+ }, function() {
41
+ resolve(false);
42
+ });
38
43
  });
39
44
  }
40
45
 
@@ -147,7 +152,7 @@ sap.ui.define(["sap/ui/base/Object",
147
152
  return oDiscardPromise;
148
153
  }
149
154
 
150
- function fnPerformAfterDiscardOrKeepDraftImpl(fnPositive, fnNegative, sMode, bIsTechnical) {
155
+ function fnPerformAfterDiscardOrKeepDraftImpl(fnPositive, fnNegative, sMode, bIsTechnical, oTarget) {
151
156
  var sEnableDiscardDraftConfirmation = oTemplateContract.oNavigationControllerProxy.isDiscardDraftConfirmationNeeded();
152
157
  var bNeedsPopup = ((sEnableDiscardDraftConfirmation === "always" && sMode.startsWith("Leave")) || (sEnableDiscardDraftConfirmation === "restricted" && sMode === "LeavePage")) && isObjectEditable();
153
158
 
@@ -157,7 +162,7 @@ sap.ui.define(["sap/ui/base/Object",
157
162
  }
158
163
 
159
164
  // Check if navigation will be explace and skip popup if so
160
- checkIfNavigationIsExplace().then(function(bIsExplace) {
165
+ checkIfNavigationIsExplace(oTarget).then(function(bIsExplace) {
161
166
  if (bIsExplace) {
162
167
  fnPositive(); // Skip popup for explace navigation
163
168
  } else {
@@ -195,7 +200,7 @@ sap.ui.define(["sap/ui/base/Object",
195
200
  }
196
201
 
197
202
  // Parameter sMode has same possible values as fnProcessDataLossOrDraftDiscardConfirmation in CommonUtils
198
- function fnPerformAfterDiscardOrKeepDraft(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, bIsTechnical) {
203
+ function fnPerformAfterDiscardOrKeepDraft(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, bIsTechnical, oTarget) {
199
204
  var oRet = new Promise(function (fnResolve, fnReject) {
200
205
  var fnPositive = function () {
201
206
  var oRet = fnProcessFunction();
@@ -206,9 +211,9 @@ sap.ui.define(["sap/ui/base/Object",
206
211
  fnReject();
207
212
  };
208
213
  if (bNoBusyCheck) {
209
- fnPerformAfterDiscardOrKeepDraftImpl(fnPositive, fnNegative, sMode, bIsTechnical);
214
+ fnPerformAfterDiscardOrKeepDraftImpl(fnPositive, fnNegative, sMode, bIsTechnical, oTarget);
210
215
  } else {
211
- oTemplateContract.oApplicationProxy.performAfterSideEffectExecution(fnPerformAfterDiscardOrKeepDraftImpl.bind(null, fnPositive, fnNegative, sMode, bIsTechnical), true);
216
+ oTemplateContract.oApplicationProxy.performAfterSideEffectExecution(fnPerformAfterDiscardOrKeepDraftImpl.bind(null, fnPositive, fnNegative, sMode, bIsTechnical, oTarget), true);
212
217
  }
213
218
  });
214
219
  return oRet;
@@ -729,22 +729,119 @@ sap.ui.define([
729
729
  oSmartFilterBarWrapper.setState(oSmartFilterBarVariant);
730
730
  // currentVariantSetModified intentionally omitted — pressing Go with the same
731
731
  // query must not mark the variant as dirty.
732
- // oSmartFilterbar.getSmartVariant() && oSmartFilterbar.getSmartVariant().currentVariantSetModified(true);
733
-
734
- // Apply sorters/groupLevels bundled with tokens after SFB state is set but
735
- // before triggering search, to prevent a premature rebind with incomplete filters.
736
- var aBundledSorters = oEvent.getParameter("sorters");
737
- var aBundledGroupLevels = oEvent.getParameter("groupLevels");
738
- if (aBundledSorters !== undefined) {
739
- fnApplySortersToTable(aBundledSorters);
740
- }
741
- if (aBundledGroupLevels !== undefined) {
742
- fnApplyGroupLevelsToTable(aBundledGroupLevels);
743
- }
732
+
733
+ var aSelectOptionsNeedingInjection = fnGetCustomFieldsNeedingInjection(oSmartFilterbar, oVariantDataFromAI.aSelectOptions);
734
+ fnInjectCustomFiltersOnRebind(aSelectOptionsNeedingInjection);
735
+ fnSyncCustomFieldInputValues(aSelectOptionsNeedingInjection, oSmartFilterbar);
736
+
737
+ // Apply sorters/groupLevels bundled with tokens after SFB state is set but
738
+ // before triggering search, to prevent a premature rebind with incomplete filters.
739
+ var aBundledSorters = oEvent.getParameter("sorters");
740
+ var aBundledGroupLevels = oEvent.getParameter("groupLevels");
741
+ if (aBundledSorters !== undefined) {
742
+ fnApplySortersToTable(aBundledSorters);
743
+ }
744
+ if (aBundledGroupLevels !== undefined) {
745
+ fnApplyGroupLevelsToTable(aBundledGroupLevels);
746
+ }
744
747
 
745
748
  oSmartFilterbar.search();
746
749
  }
747
750
 
751
+ /**
752
+ * Returns the subset of aSelectOptions whose property names landed in SFB's _CUSTOM
753
+ * bucket after setState — meaning SFB could not route them through its standard filter
754
+ * pipeline (plain Input fields with no value-list annotation).
755
+ * @param {object} oSmartFilterbar - The SmartFilterBar control instance
756
+ * @param {Array} aSelectOptions - Select options built from AI tokens
757
+ * @returns {Array} Select options that require direct filter injection
758
+ */
759
+ function fnGetCustomFieldsNeedingInjection(oSmartFilterbar, aSelectOptions) {
760
+ var oFilterData = oSmartFilterbar.getFilterData();
761
+ var oCustomData = oFilterData && oFilterData._CUSTOM;
762
+ return aSelectOptions.filter(function(oSelectOption) {
763
+ return oCustomData && oCustomData.hasOwnProperty(oSelectOption.PropertyName);
764
+ });
765
+ }
766
+
767
+ /**
768
+ * Builds UI5 Filter objects for each _CUSTOM select option and registers a one-shot
769
+ * beforeRebindTable handler on the SmartTable that injects them into bindingParams.filters
770
+ * just before the OData request is built — bypassing SFB's filter pipeline entirely.
771
+ * EQ is remapped to Contains to match Classic SFB substringof behaviour on plain Input fields.
772
+ * @param {Array} aSelectOptionsNeedingInjection - Select options that require direct filter injection
773
+ * @returns {void}
774
+ */
775
+ function fnInjectCustomFiltersOnRebind(aSelectOptionsNeedingInjection) {
776
+ if (aSelectOptionsNeedingInjection.length === 0 || !oState.oPresentationControlHandler) {
777
+ return;
778
+ }
779
+ var oSmartTable = oState.oPresentationControlHandler.getControl();
780
+ if (!oSmartTable || typeof oSmartTable.attachBeforeRebindTable !== 'function') {
781
+ return;
782
+ }
783
+ var aInjectFilters = [];
784
+ aSelectOptionsNeedingInjection.forEach(function(oSelectOption) {
785
+ oSelectOption.Ranges.forEach(function(oRange) {
786
+ var sOp = oRange.Option;
787
+ var sVal = oRange.Low;
788
+ if (sOp === 'CP') {
789
+ aInjectFilters.push(new Filter(oSelectOption.PropertyName, FilterOperator.Contains, sVal.replace(/^\*|\*$/g, '')));
790
+ } else if (sOp === 'EQ') {
791
+ aInjectFilters.push(new Filter(oSelectOption.PropertyName, FilterOperator.Contains, sVal));
792
+ } else if (sOp === 'BT') {
793
+ aInjectFilters.push(new Filter(oSelectOption.PropertyName, FilterOperator.BT, oRange.Low, oRange.High));
794
+ } else if (sOp === 'NB') {
795
+ aInjectFilters.push(new Filter({path: oSelectOption.PropertyName, operator: FilterOperator.BT, value1: oRange.Low, value2: oRange.High, bExclude: true}));
796
+ } else {
797
+ var sMappedOp = FilterOperator[sOp];
798
+ if (!sMappedOp) {
799
+ oLogger.warning("EasyFilterBarHandler: unsupported select-option operator '" + sOp + "' for property '" + oSelectOption.PropertyName + "' — skipping filter injection");
800
+ return;
801
+ }
802
+ aInjectFilters.push(new Filter(oSelectOption.PropertyName, sMappedOp, sVal));
803
+ }
804
+ });
805
+ });
806
+ var fnOnBeforeRebind = function(oRebindEvent) {
807
+ oSmartTable.detachBeforeRebindTable(fnOnBeforeRebind);
808
+ var oBindingParams = oRebindEvent.getParameter('bindingParams');
809
+ oBindingParams.filters = oBindingParams.filters || [];
810
+ var aBindingFilters = oBindingParams.filters;
811
+ // Remove prior easy-filter entries for the same properties to avoid stacking.
812
+ aInjectFilters.forEach(function(oF) {
813
+ for (var i = aBindingFilters.length - 1; i >= 0; i--) {
814
+ if (aBindingFilters[i] && aBindingFilters[i].sPath === oF.sPath) {
815
+ aBindingFilters.splice(i, 1);
816
+ }
817
+ }
818
+ aBindingFilters.push(oF);
819
+ });
820
+ };
821
+ oSmartTable.attachBeforeRebindTable(fnOnBeforeRebind);
822
+ }
823
+
824
+ /**
825
+ * Sets the visible value on the SFB Input control for each _CUSTOM field so the Classic
826
+ * filter tab shows the correct value when the user switches filter modes.
827
+ * Uses setValue only — no fireChange — to avoid triggering SFB's async filter rebuild.
828
+ * @param {Array} aSelectOptionsNeedingInjection - Select options that require direct filter injection
829
+ * @param {object} oSmartFilterbar - The SmartFilterBar control instance
830
+ * @returns {void}
831
+ */
832
+ function fnSyncCustomFieldInputValues(aSelectOptionsNeedingInjection, oSmartFilterbar) {
833
+ aSelectOptionsNeedingInjection.forEach(function(oSelectOption) {
834
+ if (oSelectOption.Ranges.length > 0) {
835
+ var aItems = oSmartFilterbar.getAllFilterItems(true) || [];
836
+ var oItem = aItems.find(function(i) { return i.getName && i.getName() === oSelectOption.PropertyName; });
837
+ var oCtrl = oItem && oItem.getControl && oItem.getControl();
838
+ if (oCtrl && oCtrl.setValue) {
839
+ oCtrl.setValue(oSelectOption.Ranges[0].Low);
840
+ }
841
+ }
842
+ });
843
+ }
844
+
748
845
  /**
749
846
  * Event handler for the EasyFilterBarContainer's tokensChangedByUser event.
750
847
  * Fired when the user manually deletes or modifies a token (distinct from AI-resolved tokens).
@@ -839,8 +936,8 @@ sap.ui.define([
839
936
  /**
840
937
  * Event handler for the EasyFilter control's showValueHelp event.
841
938
  * Identifies the input field for which the value help is requested and triggers the value help opening from SFB.
842
- * @param {*} oEvent
843
- * @param {*} oState
939
+ * @param {sap.ui.base.Event} oEvent - The showValueHelp event fired by the EasyFilter control
940
+ * @param {object} oState - The current controller state object
844
941
  */
845
942
  function fnShowValueHelp(oEvent) {
846
943
  var oSmartFilterbar = oState.oSmartFilterbar;
@@ -287,7 +287,7 @@ sap.ui.define([
287
287
  if (!isValueHelpTableAvailable) {
288
288
  // When there is no valueList associate, just return the original value in CodeList type
289
289
  aFilters.forEach(oFilter => aFinalResponse.push(getkeySpecifiedResultFromFilters(oFilter)));
290
- resolve(aFinalResponse);
290
+ return resolve(aFinalResponse);
291
291
  }
292
292
 
293
293
  // Get value help lists from metadata
@@ -3222,7 +3222,7 @@ sap.ui.define(["sap/ui/base/Object",
3222
3222
  * @param {sap.suite.ui.generic.template.lib.AppComponent} oAppComponent The AppComponent instance
3223
3223
  * @public
3224
3224
  * @extends sap.ui.base.Object
3225
- * @version 1.148.6
3225
+ * @version 1.148.8
3226
3226
  * @since 1.30.0
3227
3227
  * @alias sap.suite.ui.generic.template.lib.NavigationController
3228
3228
  */
@@ -68,7 +68,7 @@ sap.ui.define([
68
68
  interfaces: [],
69
69
  controls: [],
70
70
  elements: [],
71
- version: "1.148.6",
71
+ version: "1.148.8",
72
72
  extensions: {
73
73
  //Configuration used for rule loading of Support Assistant
74
74
  "sap.ui.support": {