@sapui5/sap.suite.ui.generic.template 1.136.20 → 1.136.22

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 (25) 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/i18n/i18n_sv.properties +1 -1
  7. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_zh_CN.properties +2 -2
  8. package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
  9. package/src/sap/suite/ui/generic/template/ObjectPage/controller/ControllerImplementation.js +3 -1
  10. package/src/sap/suite/ui/generic/template/ObjectPage/controller/RelatedAppsHandler.js +2 -2
  11. package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +1 -1
  12. package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
  13. package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
  14. package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartFilterBarWrapper.js +32 -20
  15. package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartTableChartCommon.js +7 -0
  16. package/src/sap/suite/ui/generic/template/lib/AppComponent.js +3 -1
  17. package/src/sap/suite/ui/generic/template/lib/Application.js +28 -2
  18. package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +46 -9
  19. package/src/sap/suite/ui/generic/template/lib/CommonUtils.js +7 -7
  20. package/src/sap/suite/ui/generic/template/lib/PageLeaveHandler.js +19 -14
  21. package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +110 -13
  22. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sl.properties +1 -1
  23. package/src/sap/suite/ui/generic/template/lib/insights/InsightsCardHelper.js +24 -4
  24. package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +12 -3
  25. 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.136.20",
3
+ "version": "1.136.22",
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.136.20</version>
10
+ <version>1.136.22</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.136.20"
11
+ "version": "1.136.22"
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.136.20"
11
+ "version": "1.136.22"
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
 
@@ -70,7 +70,7 @@ CANCEL_AND_DISCARD=F\u00F6rkasta utkast?
70
70
 
71
71
  DISCARD_EDIT=F\u00F6rkasta alla \u00E4ndringar?
72
72
 
73
- DISCARD=F\u00F6rkasta
73
+ DISCARD=Kasta
74
74
 
75
75
  DELETE=Radera
76
76
 
@@ -39,7 +39,7 @@ CONTACT_FAX=\u4F20\u771F
39
39
 
40
40
  CONTACT_ADDRESS=\u5730\u5740
41
41
 
42
- MESSAGE_SINGLE_VALUE_L_FORM=\u8FC7\u6EE4\u5668 "{0}" \u4E0E\u6807\u7B7E "{1}" \u65E0\u5173\u3002\u8BBE\u7F6E\u6B64\u8FC7\u6EE4\u5668\u5BF9\u7ED3\u679C\u6CA1\u6709\u5F71\u54CD\u3002
42
+ MESSAGE_SINGLE_VALUE_L_FORM=\u8FC7\u6EE4\u5668\u201C{0}\u201D\u4E0E\u6807\u7B7E\u201C{1}\u201D\u65E0\u5173\u3002\u8BBE\u7F6E\u6B64\u8FC7\u6EE4\u5668\u5BF9\u7ED3\u679C\u6CA1\u6709\u5F71\u54CD\u3002
43
43
 
44
44
  MESSAGE_SINGLE_VALUE_S_FORM=\u65E0\u6CD5\u5728 "{1}" \u6807\u7B7E\u4E0A\u6309 "{0}" \u8FDB\u884C\u8FC7\u6EE4\u3002
45
45
 
@@ -55,7 +55,7 @@ EDIT_REMAINING={1} \u4E2A\u5BF9\u8C61\u4E2D\u6709 {0} \u4E2A\u65E0\u6CD5\u8FDB\u
55
55
 
56
56
  EDIT_REMAINING_PLURAL={1} \u4E2A\u5BF9\u8C61\u4E2D\u6709 {0} \u4E2A\u65E0\u6CD5\u8FDB\u884C\u7F16\u8F91\u3002\u5982\u679C\u6709\u4EBA\u6B63\u5728\u5904\u7406\u8BE5\u5BF9\u8C61\u6216\u4E0D\u5141\u8BB8\u7F16\u8F91\uFF0C\u5C31\u53EF\u80FD\u4F1A\u53D1\u751F\u8FD9\u79CD\u60C5\u51B5\u3002\n\n \u662F\u5426\u8981\u7F16\u8F91\u5176\u4F59 {2} \u4E2A\u5BF9\u8C61\uFF1F
57
57
 
58
- MESSAGE_MULTIPLE_VALUES_L_FORM=\u67D0\u4E9B\u8FC7\u6EE4\u5668\u4E0E\u6807\u7B7E "{1}" \u65E0\u5173 ({0})\u3002\u8BBE\u7F6E\u8FD9\u4E9B\u8FC7\u6EE4\u5668\u5BF9\u7ED3\u679C\u6CA1\u6709\u5F71\u54CD\u3002
58
+ MESSAGE_MULTIPLE_VALUES_L_FORM=\u67D0\u4E9B\u8FC7\u6EE4\u5668\u4E0E\u6807\u7B7E\u201C{1}\u201D\u65E0\u5173 ({0})\u3002\u8BBE\u7F6E\u8FD9\u4E9B\u8FC7\u6EE4\u5668\u5BF9\u7ED3\u679C\u6CA1\u6709\u5F71\u54CD\u3002
59
59
 
60
60
  MESSAGE_MULTIPLE_VALUES_S_FORM=\u65E0\u6CD5\u5728 "{1}" \u6807\u7B7E\u4E0A\u4F7F\u7528\u4EE5\u4E0B\u8FC7\u6EE4\u5668\uFF1A"{0}"\u3002
61
61
 
@@ -8,7 +8,7 @@
8
8
  "i18n": "i18n/i18n.properties",
9
9
  "applicationVersion": {
10
10
  "__comment": "applicationVersion oder componentversion??",
11
- "version": "1.136.20"
11
+ "version": "1.136.22"
12
12
  },
13
13
  "title": "{{TITLE}}",
14
14
  "description": "{{DESCRIPTION}}",
@@ -2581,9 +2581,11 @@ sap.ui.define([
2581
2581
  onDataFieldForIntentBasedNavigation: function (oEvent) {
2582
2582
  oEvent = merge({}, oEvent);
2583
2583
  oTemplateUtils.oServices.oApplication.performAfterSideEffectExecution(function () {
2584
+ var oCustomData = oTemplateUtils.oCommonUtils.getCustomDataFromEvent(oEvent);
2585
+ var oTarget = { semanticObject: oCustomData.SemanticObject, action: oCustomData.Action };
2584
2586
  oTemplateUtils.oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function () {
2585
2587
  oTemplateUtils.oCommonEventHandlers.onDataFieldForIntentBasedNavigation(oEvent, oBase.state);
2586
- }, Function.prototype, "LeaveApp");
2588
+ }, Function.prototype, "LeaveApp", false, oTarget);
2587
2589
  }, true);
2588
2590
  },
2589
2591
  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
  }
@@ -109,7 +109,7 @@ sap.ui.define([
109
109
  if (bHasRelatedAppSettings) {
110
110
  // Iterate through oRelatedAppSettings and add all related apps into the set
111
111
  for (const sKey in oRelatedAppsSettings) {
112
- if (oRelatedAppsSettings.hasOwnProperty(sKey)) {
112
+ if (sKey && oRelatedAppsSettings.hasOwnProperty(sKey)) {
113
113
  const sSemanticObject = oRelatedAppsSettings[sKey].semanticObject;
114
114
  aSemanticObjects.push(sSemanticObject);
115
115
  }
@@ -6,7 +6,7 @@
6
6
  "type": "component",
7
7
  "i18n": "i18n/i18n.properties",
8
8
  "applicationVersion": {
9
- "version": "1.136.20"
9
+ "version": "1.136.22"
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.136.20"
9
+ "version": "1.136.22"
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.136.20"
9
+ "version": "1.136.22"
10
10
  },
11
11
  "title": "{{TITLE}}",
12
12
  "description": "{{DESCRIPTION}}",
@@ -26,6 +26,12 @@ sap.ui.define([
26
26
  var bIsApplying = false;
27
27
  var aBasicFilters = [];
28
28
  var oSmartFilterBar = oControl;
29
+ // Holds SVM callbacks once setSVMWrapperCallbacks is called. The afterVariantLoad handler
30
+ // is attached eagerly (in fnInitialize) so it fires even when setSVMWrapperCallbacks has
31
+ // not yet been called (race condition on second navigation: bAllControlsInitialized=true
32
+ // causes fnApplyVariantState to run synchronously, triggering afterVariantLoad before the
33
+ // Promise.all in SmartVariantManagementWrapper resolves and calls setSVMWrapperCallbacks).
34
+ var oSVMWrapperCallbacks = null;
29
35
 
30
36
  var oVariantManagementInitializedPromise;
31
37
 
@@ -40,14 +46,39 @@ sap.ui.define([
40
46
 
41
47
  // Initialize variant management promise
42
48
  oVariantManagementInitializedPromise = oSmartFilterBar.getInitializedPromise();
49
+
50
+ // Attach afterVariantLoad eagerly so custom filter state is restored regardless of
51
+ // when setSVMWrapperCallbacks is called. setManagedControlStates is only called if
52
+ // SVM callbacks are already available; otherwise those controls are restored via the
53
+ // iAppState path (SmartVariantManagementWrapper.fnSetManagedControlStates).
54
+ oSmartFilterBar.attachAfterVariantLoad(function(){
55
+ var oCustomData = oSmartFilterBar.getCustomFilterData();
56
+ // variant stored with 1.103 or later: all customFilter data stored in property customFilters
57
+ // legacy variant stored with 1.102 or earlier: customFilters (from storing point of view) separated according to their origin
58
+ var oCustomFiltersState = oCustomData[dataPropertyNameGeneric].customFilters || {
59
+ editState: oCustomData[dataPropertyNameGeneric].editStateFilter,
60
+ appExtension: oCustomData[dataPropertyNameCustom],
61
+ adaptationExtensions: oCustomData[dataPropertyNameExtension]
62
+ };
63
+
64
+ mParams.oCustomFiltersWrapper.setState(oCustomFiltersState);
65
+ if (oSVMWrapperCallbacks) {
66
+ oSVMWrapperCallbacks.setManagedControlStates(oCustomData[dataPropertyNameGeneric]);
67
+ }
68
+ });
43
69
  }
44
70
 
71
+ // 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
72
+ // in SFB instead of SVM where it would make more sense.
73
+ // 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
74
+ // after this has happened, we can get the custom data from SFB.
45
75
  // 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.
46
76
  // Events for storing/restoring are provided by SFB, data to be stored/restored can come from 3 sources:
47
77
  // - standard filters: handled directly by SFB
48
78
  // - extension filters: provided from mParams.oCustomFiltersWrapper
49
79
  // - other controls being part of VM: provided by oSVMWrapperCallbacks (controls with direct connection to VM are skipped in SVM wrapper)
50
- function setSVMWrapperCallbacks(oSVMWrapperCallbacks){
80
+ function setSVMWrapperCallbacks(oCallbacks){
81
+ oSVMWrapperCallbacks = oCallbacks;
51
82
  // 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
52
83
  // 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
53
84
  // 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
@@ -58,25 +89,6 @@ sap.ui.define([
58
89
  oCustomData[dataPropertyNameGeneric].customFilters = mParams.oCustomFiltersWrapper.getState();
59
90
  oSmartFilterBar.setCustomFilterData(oCustomData);
60
91
  });
61
-
62
- // 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
63
- // in SFB instead of SVM where it would make more sense.
64
- // 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
65
- // after this has happened, we can get the custom data from SFB.
66
- oSmartFilterBar.attachAfterVariantLoad(function(){
67
- var oCustomData = oSmartFilterBar.getCustomFilterData();
68
- // variant stored with 1.103 or later: all customFilter data stored in property customFilters
69
- // legacy variant stored with 1.102 or earlier: customFilters (from storing point of view) separated according to their origin
70
- var oCustomFiltersState = oCustomData[dataPropertyNameGeneric].customFilters || {
71
- editState: oCustomData[dataPropertyNameGeneric].editStateFilter,
72
- appExtension: oCustomData[dataPropertyNameCustom],
73
- adaptationExtensions: oCustomData[dataPropertyNameExtension]
74
- };
75
-
76
- mParams.oCustomFiltersWrapper.setState(oCustomFiltersState);
77
- oSVMWrapperCallbacks.setManagedControlStates(oCustomData[dataPropertyNameGeneric]);
78
- });
79
-
80
92
  }
81
93
 
82
94
  function fnGetState() {
@@ -153,6 +153,13 @@ sap.ui.define([
153
153
  oState.variantId = oState.sVariantId;
154
154
  }
155
155
 
156
+ // Compare current passed and control states. If states are same, setting state make no change, but trigger table refresh.
157
+ // For performance reason we compare object stringified versions. Object key order should not change as it only get applied at runtime.
158
+ var oControlState = bVariantManagementActive ? oVariantManagementStateWrapper.getState() : oSmartControlStateWrapper.getState();
159
+ if (JSON.stringify(oState) === JSON.stringify(oControlState)) {
160
+ return;
161
+ }
162
+
156
163
  if (bVariantManagementActive) {
157
164
  // In case VariantManagement is configured
158
165
  oVariantManagementStateWrapper.setState(oState);
@@ -666,6 +666,7 @@ sap.ui.define([
666
666
 
667
667
  function restore(){
668
668
  oTemplateContract.oBusyHelper.setBusyReason("exiting", false);
669
+ oTemplateContract.oApplicationProxy.resetExternalNavigation();
669
670
  for (var sComponentId in oTemplateContract.componentRegistry){
670
671
  var oRegistryEntry = oTemplateContract.componentRegistry[sComponentId];
671
672
  if (oRegistryEntry.methods.onRestore) {
@@ -947,6 +948,7 @@ sap.ui.define([
947
948
  var fnNormalizePagesMapToArray = testableHelper.testable(fnNormalizePagesMapToArray, "fnNormalizePagesMapToArray");
948
949
  getConfig = testableHelper.testable(getConfig, "getConfig");
949
950
  testableHelper.testable(setLeaveAppPromise, "AppComponent_setLeaveAppPromise");
951
+ testableHelper.testable(restore, "AppComponent_restore");
950
952
  /* eslint-enable */
951
953
 
952
954
  return oMethods;
@@ -964,7 +966,7 @@ sap.ui.define([
964
966
  * @public
965
967
  * @extends sap.ui.core.UIComponent
966
968
  * @author SAP SE
967
- * @version 1.136.20
969
+ * @version 1.136.22
968
970
  * @name sap.suite.ui.generic.template.lib.AppComponent
969
971
  */
970
972
  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){
@@ -800,6 +810,18 @@ sap.ui.define(["sap/ui/base/Object",
800
810
  return oTemplateContract.oNavigationControllerProxy.preloadComponent(sRouteName);
801
811
  }
802
812
 
813
+ // Returns true when a navigation call will open in a new tab rather than replacing the current app.
814
+ // sap-ushell-navmode (manifest-level) takes priority; sap-ushell-next-navmode (FLP startup parameter,
815
+ // system-level) is the fallback — mirroring how NavigationHandler itself determines explace.
816
+ function fnIsExplaceNavigation(oOutboundParameters) {
817
+ if (oOutboundParameters && oOutboundParameters["sap-ushell-navmode"] === "explace") {
818
+ return true;
819
+ }
820
+ var oComponentData = oTemplateContract.oAppComponent.getComponentData && oTemplateContract.oAppComponent.getComponentData();
821
+ var oStartupParams = oComponentData && oComponentData.startupParameters;
822
+ return !!(oStartupParams && oStartupParams["sap-ushell-next-navmode"] && oStartupParams["sap-ushell-next-navmode"][0] === "explace");
823
+ }
824
+
803
825
  oTemplateContract.oApplicationProxy = { // inject own api for AppComponent into the Template Contract. Other classes (NavigationController, BusyHelper) will call these functions accordingly.
804
826
  createDraftSiblingPromise: oContextBookkeeping.createDraftSiblingPromise,
805
827
  getDraftSiblingPromise: oContextBookkeeping.getDraftSiblingPromise,
@@ -834,7 +856,10 @@ sap.ui.define(["sap/ui/base/Object",
834
856
  removeTransientMessages: fnRemoveTransientMessages,
835
857
  getTransientMessages: getTransientMessages,
836
858
  setNextFocus: oFocusHelper.setNextFocus,
837
- setStates: setStates
859
+ setStates: setStates,
860
+ resetExternalNavigation: function() {
861
+ bExternalNavigationTriggered = false;
862
+ }
838
863
  };
839
864
 
840
865
  return {
@@ -903,6 +928,7 @@ sap.ui.define(["sap/ui/base/Object",
903
928
  mustRequireRequestsCanonical: mustRequireRequestsCanonical,
904
929
  getNavigationHandler: getNavigationHandler,
905
930
  navigateExternal: fnNavigateExternal,
931
+ isExplaceNavigation: fnIsExplaceNavigation,
906
932
  getStatePreservationMode: getStatePreservationMode,
907
933
  setObjectInEditMode: fnSetObjectInEditMode,
908
934
  getObjectInEditMode: fnGetObjectInEditMode,
@@ -714,7 +714,16 @@ sap.ui.define(["sap/ui/base/Object",
714
714
  }
715
715
 
716
716
  // 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
717
- oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
717
+ // Explace outbounds must bypass fnNavigateExternal to avoid setting the app busy and consuming the re-entry guard.
718
+ // getNavigationHandler() returns a ghost stub (no .navigate) when ghostapp=true — guard before calling.
719
+ if (oServices.oApplication.isExplaceNavigation(oOutbound.parameters)) {
720
+ var oNavHandler = oServices.oApplication.getNavigationHandler();
721
+ if (oNavHandler.navigate) {
722
+ oNavHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError, null, "explace");
723
+ }
724
+ } else {
725
+ oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
726
+ }
718
727
  }
719
728
 
720
729
  function fnNavigateIntentSmartLink(oOutbound, oEventSource) {
@@ -727,7 +736,15 @@ sap.ui.define(["sap/ui/base/Object",
727
736
  oCommonUtils.removePropertiesFromNavigationContext(oSelectionVariant, oEventSource);
728
737
  oController.adaptNavigationParameterExtension(oSelectionVariant, oObjectInfo);
729
738
  oCommonUtils.setComponentRefreshBehaviour(oOutbound);
730
- oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
739
+ // SmartLink outbounds have no manifest parameters so sap-ushell-navmode is never set.
740
+ // System-level sap-ushell-next-navmode can still force a new tab — bypass the re-entry guard in that case.
741
+ if (oServices.oApplication.isExplaceNavigation()) {
742
+ if (oNavigationHandler.navigate) {
743
+ oNavigationHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError, null, "explace");
744
+ }
745
+ } else {
746
+ oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
747
+ }
731
748
  }
732
749
 
733
750
  function fnHideTitleArea(oSmLiContent,aContactTitleArea) {
@@ -797,9 +814,10 @@ sap.ui.define(["sap/ui/base/Object",
797
814
 
798
815
  function fnOnSemanticObjectLinkNavigationPressed(oEventSource, oEventParameters){
799
816
  var oEventObject = deepExtend({}, oEventSource);
817
+ var sSemanticObject = oEventObject.data('SemanticObject');
818
+ var sAction = oEventObject.data('Action');
819
+ var oTarget = (sSemanticObject && sAction) ? { semanticObject: sSemanticObject, action: sAction } : undefined;
800
820
  oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function() {
801
- var sSemanticObject = oEventObject.data('SemanticObject');
802
- var sAction = oEventObject.data('Action');
803
821
  var sSemanticAttributes = oEventObject.data('SemanticAttributes');
804
822
  if (sSemanticObject && sAction){
805
823
  var oOutbound = {
@@ -812,7 +830,7 @@ sap.ui.define(["sap/ui/base/Object",
812
830
  }
813
831
  fnNavigateIntentSmartLink(oOutbound, oEventObject);
814
832
  }
815
- }, Function.prototype, "LeaveApp");
833
+ }, Function.prototype, "LeaveApp", false, oTarget);
816
834
  }
817
835
 
818
836
  function fnOnSemanticObjectLinkNavigationTargetObtained(sEntitySet, mFieldSemanticObjects, oEventParameters, oState, sTitle) {
@@ -1101,6 +1119,13 @@ sap.ui.define(["sap/ui/base/Object",
1101
1119
  // Sometimes, the SmartLink is located on a field group which belongs to the child entity set of object page.
1102
1120
  // So, we have to always derive the entity type from the smart link's binding context.
1103
1121
  var oEntityType = ModelUtil.getEntityTypeFromContext(oControl.getBindingContext());
1122
+ // CS20260013063140: ModelUtil.getEntityTypeFromContext returns null when the SmartLink
1123
+ // is resolved via SmartLinkDelegate, because the binding context is not yet resolvable
1124
+ // to an entity type at that point.
1125
+ // Fall back to deriving the entity type from the enclosing entity set instead.
1126
+ if (!oEntityType) {
1127
+ oEntityType = oMetaModel.getODataEntityType(oEntitySet.entityType);
1128
+ }
1104
1129
  var oField = oEntityType.property.find(function (oProperty) { return oProperty.name === sSourceClickedField; });
1105
1130
  var sTextArrangement = "descriptionAndId";
1106
1131
  if (oField) { // TODO: Need to provide the correct field Object using the entityType and corresponding association (should be handled by a BLI)
@@ -1901,6 +1926,7 @@ sap.ui.define(["sap/ui/base/Object",
1901
1926
  var oContext = oEventSource.getParent().getBindingContext();
1902
1927
  var sSemanticObject = oEventSource.data("SemanticObject");
1903
1928
  var sAction = oEventSource.data("Action");
1929
+ var oTarget = { semanticObject: sSemanticObject, action: sAction };
1904
1930
 
1905
1931
  oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function() {
1906
1932
  var oOutbound = {
@@ -1908,7 +1934,7 @@ sap.ui.define(["sap/ui/base/Object",
1908
1934
  semanticObject: sSemanticObject
1909
1935
  };
1910
1936
  fnNavigateIntent(oOutbound, [oContext], oState.oSmartFilterbar || undefined);
1911
- }, Function.prototype, "LeaveApp");
1937
+ }, Function.prototype, "LeaveApp", false, oTarget);
1912
1938
  }
1913
1939
 
1914
1940
  /*
@@ -1938,13 +1964,15 @@ sap.ui.define(["sap/ui/base/Object",
1938
1964
  if (bRequiresContext && !aSelectedContexts.length) { // not consistent, since contexts missing
1939
1965
  fnShowMessageForInvalidNumberOfSelects(aSelectedContexts.length);
1940
1966
  } else {
1967
+ var oTarget = { semanticObject: oCustomData.SemanticObject, action: oCustomData.Action };
1941
1968
  oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function () {
1942
1969
  onDataFieldForIntentBasedNavigationSelectedContext(oCustomData, aSelectedContexts, oSmartFilterbar);
1943
- }, Function.prototype, "LeaveApp");
1970
+ }, Function.prototype, "LeaveApp", false, oTarget);
1944
1971
  }
1945
1972
  }
1946
1973
 
1947
1974
  function onInlineDataFieldForIntentBasedNavigation(oEventSource, oState){
1975
+ var oTarget = { semanticObject: oEventSource.data("SemanticObject"), action: oEventSource.data("Action") };
1948
1976
  oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function() {
1949
1977
  var oOutbound = {
1950
1978
  semanticObject: oEventSource.data("SemanticObject"),
@@ -1952,7 +1980,7 @@ sap.ui.define(["sap/ui/base/Object",
1952
1980
  };
1953
1981
  var oContext = oEventSource.getParent().getBindingContext();
1954
1982
  fnNavigateIntent(oOutbound, [oContext], oState.oSmartFilterbar);
1955
- }, Function.prototype, "LeaveApp");
1983
+ }, Function.prototype, "LeaveApp", false, oTarget);
1956
1984
  }
1957
1985
 
1958
1986
  function onInlineDataFieldForAction(oEvent) {
@@ -2620,7 +2648,16 @@ sap.ui.define(["sap/ui/base/Object",
2620
2648
  var oSelectionVariant = fnBuildSelectionVariantForNavigation(oOutbound, [], oContext);
2621
2649
  oController.adaptNavigationParameterExtension(oSelectionVariant, oOutbound);
2622
2650
  oCommonUtils.setComponentRefreshBehaviour(oOutbound);
2623
- oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
2651
+ // Explace outbounds must bypass fnNavigateExternal to avoid setting the app busy and consuming the re-entry guard.
2652
+ // getNavigationHandler() returns a ghost stub (no .navigate) when ghostapp=true — guard before calling.
2653
+ if (oServices.oApplication.isExplaceNavigation(oOutbound.parameters)) {
2654
+ var oNavHandler = oServices.oApplication.getNavigationHandler();
2655
+ if (oNavHandler.navigate) {
2656
+ oNavHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError, null, "explace");
2657
+ }
2658
+ } else {
2659
+ oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
2660
+ }
2624
2661
  }
2625
2662
 
2626
2663
  function onSmartFieldInitialise(oEvent,sViewId){
@@ -788,17 +788,17 @@ sap.ui.define(["sap/ui/base/Object",
788
788
 
789
789
  setComponentRefreshBehaviour(oOutbound);
790
790
 
791
- // We now ensure that the 'sap-ushell-navmode' parameter is passed to the NavigationHandler.navigate method
792
- // and skip setting the app to busy mode when opening a new tab
793
- if (oOutbound.parameters["sap-ushell-navmode"] === "explace") {
794
- oNavigationHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, null, null, oOutbound.parameters["sap-ushell-navmode"]);
791
+ // We now skip setting the app to busy mode when opening a new tab and bypass the re-entry guard (fnNavigateExternal) for explace navigations:
792
+ // the source app stays alive when a new tab is opened, so without the bypass AppComponent.restore() is never called and the guard is never reset.
793
+ if (oServices.oApplication.isExplaceNavigation(oOutbound.parameters)) {
794
+ oNavigationHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, null, null, "explace");
795
795
  } else {
796
796
  oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, fnHandleError);
797
797
  //null object has to be passed to the NavigationHandler as an
798
798
  //indicator that the state should not be overwritten
799
799
  //if draft enabled then passing NavigateExternal else on back button passing LeavePage
800
800
  }
801
- }, Function.prototype, "LeaveApp");
801
+ }, Function.prototype, "LeaveApp", false, { semanticObject: oOutbound.semanticObject, action: oOutbound.action });
802
802
  }
803
803
 
804
804
  function fnGetNavigationKeyProperties(sTargetEntitySet) {
@@ -1313,10 +1313,10 @@ sap.ui.define(["sap/ui/base/Object",
1313
1313
  // "LeaveApp": leave the app via a forward navigation
1314
1314
  // "LeavePage": leave the page via an internal navigation or a backward navigation (which may or may not be internal)
1315
1315
  // Note: if sMode is faulty it will be considered as "LeavePage"
1316
- function fnProcessDataLossOrDraftDiscardConfirmation(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck){
1316
+ function fnProcessDataLossOrDraftDiscardConfirmation(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, oTarget){
1317
1317
  sMode = sMode || "LeavePage";
1318
1318
  if (oComponentUtils.isDraftEnabled()){
1319
- return oServices.oPageLeaveHandler.performAfterDiscardOrKeepDraft(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, false);
1319
+ return oServices.oPageLeaveHandler.performAfterDiscardOrKeepDraft(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, false, oTarget);
1320
1320
  } else {
1321
1321
  return oServices.oDataLossHandler.performIfNoDataLoss(fnProcessFunction, fnCancelFunction, sMode, bNoBusyCheck, false);
1322
1322
  }
@@ -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;
@@ -58,10 +58,43 @@ sap.ui.define([
58
58
 
59
59
  var mFilterProperties = {}; // todo : Add the properties from navigation entites
60
60
  var oEntityType = oTemplateUtils.oCommonUtils.getMetaModelEntityType(sEntitySet);
61
- oEntityType.property.map(function (oProperty) {
62
- var sTokenType = "ValueHelp"; // Other values are "Calendar" | "Time" | "MenuWithCheckBox" | "MenuWithSingleSelect"
63
- if (filterHelper.isPropertyFilterable(oProperty)) {
64
61
 
62
+ // Capabilities.FilterRestrictions takes priority over sap:filterable (matches SFB behaviour).
63
+ var oEntitySetMeta = oSFBMetaModel.getODataEntitySet(sEntitySet);
64
+ var oCapFilterRestrictions = oEntitySetMeta &&
65
+ oEntitySetMeta["Org.OData.Capabilities.V1.FilterRestrictions"];
66
+ var bEntityNonFilterable = !!oCapFilterRestrictions &&
67
+ oCapFilterRestrictions.Filterable === "false";
68
+ var mCapNonFilterable = {};
69
+ if (oCapFilterRestrictions && oCapFilterRestrictions.NonFilterableProperties) {
70
+ oCapFilterRestrictions.NonFilterableProperties.forEach(function(oEntry) {
71
+ if (oEntry.PropertyPath) {
72
+ mCapNonFilterable[oEntry.PropertyPath] = true;
73
+ }
74
+ });
75
+ }
76
+
77
+ // Helper: add properties from a 1:1 nav property's entity type into mFilterProperties,
78
+ // applying Capabilities.FilterRestrictions from the nav entity-set metadata.
79
+ function addNavPropertiesFromEntityType(entityType, prefix, oNavEntitySetMeta) {
80
+ var oNavCapFilterRestrictions = oNavEntitySetMeta &&
81
+ oNavEntitySetMeta["Org.OData.Capabilities.V1.FilterRestrictions"];
82
+ var bNavEntityNonFilterable = !!oNavCapFilterRestrictions &&
83
+ oNavCapFilterRestrictions.Filterable === "false";
84
+ var mNavCapNonFilterable = {};
85
+ if (oNavCapFilterRestrictions && oNavCapFilterRestrictions.NonFilterableProperties) {
86
+ oNavCapFilterRestrictions.NonFilterableProperties.forEach(function(oEntry) {
87
+ if (oEntry.PropertyPath) {
88
+ mNavCapNonFilterable[oEntry.PropertyPath] = true;
89
+ }
90
+ });
91
+ }
92
+ entityType.property && entityType.property.forEach(function(oProperty) {
93
+ var bFilterable = filterHelper.isPropertyFilterable(oProperty);
94
+ if (oNavCapFilterRestrictions) {
95
+ bFilterable = !bNavEntityNonFilterable && !mNavCapNonFilterable[oProperty.name];
96
+ }
97
+ var sTokenType = "ValueHelp";
65
98
  var bIsCodeListRequired;
66
99
  oProperty.extensions && oProperty.extensions.forEach(function(oExtension) {
67
100
  if (oExtension.name === "value-list" && oExtension.value === "fixed-values") {
@@ -69,31 +102,95 @@ sap.ui.define([
69
102
  bIsCodeListRequired = true;
70
103
  }
71
104
  });
72
-
73
- // Calculate the token type based on the property type and display format
74
- // It will be better if this is done at the control level
75
105
  if ((oProperty.type === "Edm.DateTime" && oProperty["sap:display-format"] === "Date") ||
76
106
  (oProperty.type === "Edm.String" && oProperty["com.sap.vocabularies.Common.v1.IsCalendarDate"] && oProperty["com.sap.vocabularies.Common.v1.IsCalendarDate"].Bool === "true")) {
77
107
  sTokenType = "Calendar";
78
108
  } else if (oProperty.type === "Edm.DateTimeOffset") {
79
109
  sTokenType = "Time";
80
110
  }
81
-
82
- mFilterProperties[oProperty.name] = {
83
- name: oProperty.name,
84
- //label: oProperty.label, Name is added from the filter item control
111
+ var propName = prefix + "." + oProperty.name;
112
+ mFilterProperties[propName] = {
113
+ name: propName,
85
114
  dataType: oProperty.type,
86
- defaultValue : [], // Fill values from FLP user defaults , SV or other sources
87
- filterable: true,
115
+ defaultValue: [],
116
+ filterable: bFilterable,
88
117
  sortable: false,
89
- codeList : bIsCodeListRequired,
118
+ codeList: bIsCodeListRequired,
90
119
  type: sTokenType,
91
120
  unit: oProperty["sap:unit"] || "",
92
121
  required: oProperty["sap:required-in-filter"] === "true" ? true : false
93
122
  };
123
+ });
124
+ }
125
+
126
+ oEntityType.property.map(function (oProperty) {
127
+ var sTokenType = "ValueHelp"; // Other values are "Calendar" | "Time" | "MenuWithCheckBox" | "MenuWithSingleSelect"
128
+ var bFilterable = filterHelper.isPropertyFilterable(oProperty);
129
+
130
+ // When Capabilities.FilterRestrictions is present, its answer is authoritative.
131
+ // A property absent from NonFilterableProperties is filterable even if sap:filterable="false".
132
+ if (oCapFilterRestrictions) {
133
+ bFilterable = !bEntityNonFilterable && !mCapNonFilterable[oProperty.name];
134
+ }
135
+
136
+ var bIsCodeListRequired;
137
+ oProperty.extensions && oProperty.extensions.forEach(function(oExtension) {
138
+ if (oExtension.name === "value-list" && oExtension.value === "fixed-values") {
139
+ sTokenType = "MenuWithCheckBox";
140
+ bIsCodeListRequired = true;
141
+ }
142
+ });
143
+
144
+ // Calculate the token type based on the property type and display format
145
+ // It will be better if this is done at the control level
146
+ if ((oProperty.type === "Edm.DateTime" && oProperty["sap:display-format"] === "Date") ||
147
+ (oProperty.type === "Edm.String" && oProperty["com.sap.vocabularies.Common.v1.IsCalendarDate"] && oProperty["com.sap.vocabularies.Common.v1.IsCalendarDate"].Bool === "true")) {
148
+ sTokenType = "Calendar";
149
+ } else if (oProperty.type === "Edm.DateTimeOffset") {
150
+ sTokenType = "Time";
94
151
  }
152
+
153
+ mFilterProperties[oProperty.name] = {
154
+ name: oProperty.name,
155
+ //label: oProperty.label, Name is added from the filter item control
156
+ dataType: oProperty.type,
157
+ defaultValue : [], // Fill values from FLP user defaults , SV or other sources
158
+ filterable: bFilterable,
159
+ sortable: false,
160
+ codeList : bIsCodeListRequired,
161
+ type: sTokenType,
162
+ unit: oProperty["sap:unit"] || "",
163
+ required: oProperty["sap:required-in-filter"] === "true" ? true : false
164
+ };
95
165
  });
96
166
 
167
+ // Add 1:1 navigation properties' properties
168
+ if (oEntityType.navigationProperty) {
169
+ oEntityType.navigationProperty.forEach(function(navProp) {
170
+ var oAssocEnd = null;
171
+ var oAssoc = null;
172
+ if (oSFBMetaModel && navProp.relationship) {
173
+ oAssoc = oSFBMetaModel.getODataAssociationEnd && oSFBMetaModel.getODataAssociationEnd(oEntityType, navProp.name);
174
+ oAssocEnd = oAssoc;
175
+ }
176
+ var isOneToOne = false;
177
+ if (oAssocEnd && oAssocEnd.multiplicity && (oAssocEnd.multiplicity === "0..1" || oAssocEnd.multiplicity === "1")) {
178
+ isOneToOne = true;
179
+ }
180
+ if (isOneToOne) {
181
+ var sTargetType = navProp.type || (oAssocEnd && oAssocEnd.type);
182
+ if (sTargetType) {
183
+ var oTargetEntityType = oSFBMetaModel.getODataEntityType && oSFBMetaModel.getODataEntityType(sTargetType);
184
+ if (oTargetEntityType) {
185
+ var oAssocSetEnd = oSFBMetaModel.getODataAssociationSetEnd && oSFBMetaModel.getODataAssociationSetEnd(oEntityType, navProp.name);
186
+ var oNavEntitySetMeta = oAssocSetEnd && oAssocSetEnd.entitySet && oSFBMetaModel.getODataEntitySet(oAssocSetEnd.entitySet);
187
+ addNavPropertiesFromEntityType(oTargetEntityType, navProp.name, oNavEntitySetMeta);
188
+ }
189
+ }
190
+ }
191
+ });
192
+ }
193
+
97
194
  oEasyFilterMetadata = {
98
195
  version: 1,
99
196
  entitySet: sEntitySet,
@@ -182,7 +182,7 @@ ST_GENERIC_ERROR_NAVIGATION_PROPERTY_NOT_CORRECT=Lastnost navigacije {0} v pripo
182
182
 
183
183
  ST_GENERIC_FCL_FULLSCREEN=Celotni ekran
184
184
 
185
- ST_GENERIC_FCL_EXIT_FULLSCREEN=Izhod iz modusa celotnega ekrana
185
+ ST_GENERIC_FCL_EXIT_FULLSCREEN=Izhod iz celozaslonskega na\u010Dina
186
186
 
187
187
  ST_GENERIC_FCL_CLOSE_COLUMN=Zapri
188
188
 
@@ -50,6 +50,7 @@ sap.ui.define(["sap/suite/ui/generic/template/genericUtilities/metadataAnalyser"
50
50
  var oAppComponent = oComponent.getAppComponent();
51
51
  var oUIManifest = oAppComponent.getManifestEntry("sap.ui");
52
52
  var oAppManifest = oAppComponent.getManifestEntry("sap.app");
53
+ var oOutbounds = oAppManifest && oAppManifest["crossNavigation"] && oAppManifest["crossNavigation"]["outbounds"];
53
54
  if (oAppManifest && oAppManifest["crossNavigation"]) {
54
55
  delete oAppManifest["crossNavigation"];
55
56
  }
@@ -57,7 +58,7 @@ sap.ui.define(["sap/suite/ui/generic/template/genericUtilities/metadataAnalyser"
57
58
  oAppManifest.id = InsightsCardHelper.getCardId(oAppComponent);
58
59
  oManifest["sap.app"] = fnCreateManifestSapApp(oAppManifest);
59
60
  oManifest["sap.ui"] = oUIManifest;
60
- oManifest["sap.card"] = fnCreateManifestSapCard(oCardDefinition);
61
+ oManifest["sap.card"] = fnCreateManifestSapCard(oCardDefinition, oOutbounds);
61
62
  oManifest["sap.insights"] = fnCreateManifestSapInsight(oCardDefinition);
62
63
  oManifest["sap.ui5"] = fnCreateSapui5();
63
64
  return oManifest;
@@ -91,7 +92,7 @@ sap.ui.define(["sap/suite/ui/generic/template/genericUtilities/metadataAnalyser"
91
92
  return oManifestAppData;
92
93
  };
93
94
 
94
- var fnCreateManifestSapCard = function (oCardDefinition) {
95
+ var fnCreateManifestSapCard = function (oCardDefinition, oOutbounds) {
95
96
  var oCardConfig = {};
96
97
  var sComponentName = oCardDefinition['component'].getMetadata().getName();
97
98
  oCardConfig["type"] = getCardType(sComponentName);
@@ -104,7 +105,7 @@ sap.ui.define(["sap/suite/ui/generic/template/genericUtilities/metadataAnalyser"
104
105
  } else {
105
106
  oCardConfig["content"] = InsightsCardHelper.fnCreateManifestSapTableCardContent(oCardDefinition, oCardConfig);
106
107
  }
107
- InsightsCardHelper.getCardActions(oCardDefinition, oCardConfig);
108
+ InsightsCardHelper.getCardActions(oCardDefinition, oCardConfig, oOutbounds);
108
109
  return oCardConfig;
109
110
  };
110
111
 
@@ -693,7 +694,7 @@ sap.ui.define(["sap/suite/ui/generic/template/genericUtilities/metadataAnalyser"
693
694
  return aDimensions;
694
695
  };
695
696
 
696
- InsightsCardHelper.getCardActions = function (oCardDefinition, oSapCard) {
697
+ InsightsCardHelper.getCardActions = function (oCardDefinition, oSapCard, oOutbounds) {
697
698
  var sHash = window.hasher.getHash(), aSemanticObjAction = sHash.split('&/')[0], sAppVarId;
698
699
 
699
700
  if (aSemanticObjAction.includes('?')) {
@@ -725,6 +726,10 @@ sap.ui.define(["sap/suite/ui/generic/template/genericUtilities/metadataAnalyser"
725
726
  }];
726
727
 
727
728
  var oContentParams = JSON.parse(JSON.stringify(oHeaderParams));
729
+ var oRowOutbound = fnGetRowNavigationOutbound(oOutbounds, aSemanticObjAction[0]);
730
+ if (oRowOutbound) {
731
+ oContentParams.ibnTarget = oRowOutbound;
732
+ }
728
733
 
729
734
  var oContentParameterValue = [{
730
735
  "type": "Navigation",
@@ -747,6 +752,21 @@ sap.ui.define(["sap/suite/ui/generic/template/genericUtilities/metadataAnalyser"
747
752
  }
748
753
  };
749
754
 
755
+ var fnGetRowNavigationOutbound = function (oOutbounds, sSemanticObject) {
756
+ if (!oOutbounds || !sSemanticObject) {
757
+ return null;
758
+ }
759
+ var oResult = null;
760
+ Object.keys(oOutbounds).some(function (sKey) {
761
+ var oOutbound = oOutbounds[sKey];
762
+ if (oOutbound && oOutbound.semanticObject === sSemanticObject && oOutbound.action) {
763
+ oResult = { semanticObject: oOutbound.semanticObject, action: oOutbound.action };
764
+ return oOutbound.action === "displayFactSheet";
765
+ }
766
+ });
767
+ return oResult;
768
+ };
769
+
750
770
  var fnGetLineItemAnnotation = function (oCardDefinition) {
751
771
  var oEntityType = oCardDefinition['entityType'];
752
772
  var aCustomData = oCardDefinition['currentControlHandler'].getControl().getCustomData();
@@ -2429,7 +2429,7 @@ sap.ui.define(["sap/ui/base/Object",
2429
2429
  };
2430
2430
  for (var oHistoricHash = oCurrentHash; oHistoricHash.iHashChangeCount > 0; oHistoricHash = aPreviousHashes[oHistoricHash.backTarget]){
2431
2431
  var oIdentity = (oHistoricHash === oCurrentHash) ? oCurrentIdentity : oHistoricHash.identity;
2432
- var oReducedIdentity = oIdentity.treeNode && {
2432
+ var oReducedIdentity = oIdentity && oIdentity.treeNode && {
2433
2433
  sRouteName: oIdentity.treeNode.sRouteName,
2434
2434
  keys: oIdentity.keys,
2435
2435
  appStates: oIdentity.appStates
@@ -3109,6 +3109,7 @@ sap.ui.define(["sap/ui/base/Object",
3109
3109
  var fnPrepareHostView = testableHelper.testable(fnPrepareHostView, "prepareHostView");
3110
3110
  var fnPreloadComponent = testableHelper.testable(fnPreloadComponent, "preloadComponent");
3111
3111
  var fnGetRouteInfoByHash = testableHelper.testable(fnGetRouteInfoByHash, "getRouteInfoByHash");
3112
+ var fnUpdateHistoryState = testableHelper.testable(fnUpdateHistoryState, "updateHistoryState");
3112
3113
 
3113
3114
  // Note: Function createHostView will be added by routingHelper.
3114
3115
  // Allow to mock this by unit tests
@@ -3119,8 +3120,16 @@ sap.ui.define(["sap/ui/base/Object",
3119
3120
  testableHelper.testable(function(fnPrepareHostViewStub){
3120
3121
  fnPrepareHostView = fnPrepareHostViewStub;
3121
3122
  }, "setPrepareHostView");
3122
- /* eslint-enable */
3123
3123
 
3124
+ testableHelper.testable(function(oCurrentHashParam, aPreviousHashesParam, oCurrentIdentityParam, oHistoryStateParam){
3125
+ oCurrentHash = oCurrentHashParam;
3126
+ aPreviousHashes = aPreviousHashesParam;
3127
+ oCurrentIdentity = oCurrentIdentityParam;
3128
+ if (oHistoryStateParam !== undefined){
3129
+ oHistoryState = oHistoryStateParam;
3130
+ }
3131
+ }, "setInternalNavigationState");
3132
+ /* eslint-enable */
3124
3133
 
3125
3134
  oTemplateContract.oBusyHelper.setBusy((getParsedShellHashFromFLP() || Promise.resolve()).then(function(oResults){
3126
3135
  var oParsedUrl = oResults && oResults.parseParameters(document.location.search);
@@ -3206,7 +3215,7 @@ sap.ui.define(["sap/ui/base/Object",
3206
3215
  * @param {sap.suite.ui.generic.template.lib.AppComponent} oAppComponent The AppComponent instance
3207
3216
  * @public
3208
3217
  * @extends sap.ui.base.Object
3209
- * @version 1.136.20
3218
+ * @version 1.136.22
3210
3219
  * @since 1.30.0
3211
3220
  * @alias sap.suite.ui.generic.template.lib.NavigationController
3212
3221
  */
@@ -66,7 +66,7 @@ sap.ui.define([
66
66
  interfaces: [],
67
67
  controls: [],
68
68
  elements: [],
69
- version: "1.136.20",
69
+ version: "1.136.22",
70
70
  extensions: {
71
71
  //Configuration used for rule loading of Support Assistant
72
72
  "sap.ui.support": {