@sapui5/sap.suite.ui.generic.template 1.151.0 → 1.151.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/sap/suite/ui/generic/template/.library +1 -1
- package/src/sap/suite/ui/generic/template/AnalyticalListPage/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/Canvas/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/ObjectPage/controller/ControllerImplementation.js +3 -1
- package/src/sap/suite/ui/generic/template/ObjectPage/controller/RelatedAppsHandler.js +1 -1
- package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartTableChartCommon.js +10 -0
- package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartVariantManagementWrapper.js +1 -8
- package/src/sap/suite/ui/generic/template/lib/AppComponent.js +3 -1
- package/src/sap/suite/ui/generic/template/lib/Application.js +28 -2
- package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +47 -10
- package/src/sap/suite/ui/generic/template/lib/CommonUtils.js +7 -7
- package/src/sap/suite/ui/generic/template/lib/PageLeaveHandler.js +19 -14
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +111 -14
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterDataFetcherHelper.js +1 -1
- package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +1 -1
- package/src/sap/suite/ui/generic/template/library.js +1 -1
package/package.json
CHANGED
|
@@ -2804,9 +2804,11 @@ sap.ui.define([
|
|
|
2804
2804
|
onDataFieldForIntentBasedNavigation: function (oEvent) {
|
|
2805
2805
|
oEvent = merge({}, oEvent);
|
|
2806
2806
|
oTemplateUtils.oServices.oApplication.performAfterSideEffectExecution(function () {
|
|
2807
|
+
var oCustomData = oTemplateUtils.oCommonUtils.getCustomDataFromEvent(oEvent);
|
|
2808
|
+
var oTarget = { semanticObject: oCustomData.SemanticObject, action: oCustomData.Action };
|
|
2807
2809
|
oTemplateUtils.oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function () {
|
|
2808
2810
|
oTemplateUtils.oCommonEventHandlers.onDataFieldForIntentBasedNavigation(oEvent, oBase.state);
|
|
2809
|
-
}, Function.prototype, "LeaveApp");
|
|
2811
|
+
}, Function.prototype, "LeaveApp", false, oTarget);
|
|
2810
2812
|
}, true);
|
|
2811
2813
|
},
|
|
2812
2814
|
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
|
}
|
|
@@ -49,6 +49,12 @@ sap.ui.define([
|
|
|
49
49
|
function getControlWrapper(oControl) {
|
|
50
50
|
var bIsApplying = false; // avoid forwarding change event when caused by us applying a state
|
|
51
51
|
function fnGetState() {
|
|
52
|
+
// getCurrentState can iterate a managed control whose view was already torn down (e.g. navigation
|
|
53
|
+
// while an appState write is in flight). Reading state from a destroyed control crashes in
|
|
54
|
+
// getUiState() because its inner aggregation is gone, so skip it.
|
|
55
|
+
if (oControl.isDestroyed()) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
52
58
|
var oControlUiState = oControl.getUiState(); // unfortunately not serializable, but a managed object
|
|
53
59
|
var oStateUiState = {
|
|
54
60
|
oPresentationVariant: oControlUiState.getPresentationVariant(),
|
|
@@ -66,6 +72,10 @@ sap.ui.define([
|
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
function fnSetState(oState) {
|
|
75
|
+
// Symmetric to fnGetState: never apply state to a destroyed control.
|
|
76
|
+
if (oControl.isDestroyed()) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
69
79
|
if (oState) {
|
|
70
80
|
if (!oState.oUiState) {
|
|
71
81
|
// Legacy handling for state without additional level oUiState (created with 1.99.0 - 1.99.3). Could be relevant on LR and OP, and independent of VM
|
|
@@ -85,14 +85,7 @@ sap.ui.define([
|
|
|
85
85
|
setManagedControlStates: function(oState){
|
|
86
86
|
aWrapperInfo.forEach(function(oInfo){
|
|
87
87
|
if (!oInfo.bVMConnection) {
|
|
88
|
-
|
|
89
|
-
// control fires its initialise event and its inner table/chart is created).
|
|
90
|
-
// Without this guard, afterVariantLoad can call setState before SmartTable._oTable
|
|
91
|
-
// exists, causing getUiState() to crash with a null-dereference on getTable().
|
|
92
|
-
var oReady = oInfo.wrapper.oReadyPromise || Promise.resolve();
|
|
93
|
-
oReady.then(function() {
|
|
94
|
-
oInfo.wrapper.setState(oState[oInfo.wrapper.getLocalId()]);
|
|
95
|
-
});
|
|
88
|
+
oInfo.wrapper.setState(oState[oInfo.wrapper.getLocalId()]);
|
|
96
89
|
}
|
|
97
90
|
});
|
|
98
91
|
}
|
|
@@ -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.151.
|
|
964
|
+
* @version 1.151.1
|
|
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){
|
|
@@ -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,
|
|
@@ -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
|
-
|
|
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 (oServices.oApplication.isExplaceNavigation(oOutbound.parameters)) {
|
|
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) {
|
|
@@ -733,7 +742,15 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
733
742
|
oCommonUtils.removePropertiesFromNavigationContext(oSelectionVariant, oEventSource);
|
|
734
743
|
oController.adaptNavigationParameterExtension(oSelectionVariant, oObjectInfo);
|
|
735
744
|
oCommonUtils.setComponentRefreshBehaviour(oOutbound);
|
|
736
|
-
|
|
745
|
+
// SmartLink outbounds have no manifest parameters so sap-ushell-navmode is never set.
|
|
746
|
+
// System-level sap-ushell-next-navmode can still force a new tab — bypass the re-entry guard in that case.
|
|
747
|
+
if (oServices.oApplication.isExplaceNavigation()) {
|
|
748
|
+
if (oNavigationHandler.navigate) {
|
|
749
|
+
oNavigationHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError, null, "explace");
|
|
750
|
+
}
|
|
751
|
+
} else {
|
|
752
|
+
oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
|
|
753
|
+
}
|
|
737
754
|
}
|
|
738
755
|
|
|
739
756
|
function fnHideTitleArea(oSmLiContent,aContactTitleArea) {
|
|
@@ -803,9 +820,10 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
803
820
|
|
|
804
821
|
function fnOnSemanticObjectLinkNavigationPressed(oEventSource, oEventParameters){
|
|
805
822
|
var oEventObject = deepExtend({}, oEventSource);
|
|
823
|
+
var sSemanticObject = oEventObject.data('SemanticObject');
|
|
824
|
+
var sAction = oEventObject.data('Action');
|
|
825
|
+
var oTarget = (sSemanticObject && sAction) ? { semanticObject: sSemanticObject, action: sAction } : undefined;
|
|
806
826
|
oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function() {
|
|
807
|
-
var sSemanticObject = oEventObject.data('SemanticObject');
|
|
808
|
-
var sAction = oEventObject.data('Action');
|
|
809
827
|
var sSemanticAttributes = oEventObject.data('SemanticAttributes');
|
|
810
828
|
if (sSemanticObject && sAction){
|
|
811
829
|
var oOutbound = {
|
|
@@ -818,7 +836,7 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
818
836
|
}
|
|
819
837
|
fnNavigateIntentSmartLink(oOutbound, oEventObject);
|
|
820
838
|
}
|
|
821
|
-
}, Function.prototype, "LeaveApp");
|
|
839
|
+
}, Function.prototype, "LeaveApp", false, oTarget);
|
|
822
840
|
}
|
|
823
841
|
|
|
824
842
|
function fnOnSemanticObjectLinkNavigationTargetObtained(sEntitySet, mFieldSemanticObjects, oEventParameters, oState, sTitle) {
|
|
@@ -1105,8 +1123,15 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
1105
1123
|
// The value "sEntitySet" holds the entity set of an object page or a table.
|
|
1106
1124
|
//
|
|
1107
1125
|
// Sometimes, the SmartLink is located on a field group which belongs to the child entity set of object page.
|
|
1108
|
-
// So, we
|
|
1126
|
+
// So, we try to derive the entity type from the SmartLink's binding context.
|
|
1109
1127
|
var oEntityType = ModelUtil.getEntityTypeFromContext(oControl.getBindingContext());
|
|
1128
|
+
// CS20260013063140: ModelUtil.getEntityTypeFromContext returns null when the SmartLink
|
|
1129
|
+
// is resolved via SmartLinkDelegate, because the binding context is not yet resolvable
|
|
1130
|
+
// to an entity type at that point.
|
|
1131
|
+
// Fall back to deriving the entity type from the enclosing entity set instead.
|
|
1132
|
+
if (!oEntityType) {
|
|
1133
|
+
oEntityType = oMetaModel.getODataEntityType(oEntitySet.entityType);
|
|
1134
|
+
}
|
|
1110
1135
|
var oField = oEntityType.property.find(function (oProperty) { return oProperty.name === sSourceClickedField; });
|
|
1111
1136
|
var sTextArrangement = "descriptionAndId";
|
|
1112
1137
|
if (oField) { // TODO: Need to provide the correct field Object using the entityType and corresponding association (should be handled by a BLI)
|
|
@@ -1988,6 +2013,7 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
1988
2013
|
var oContext = oEventSource.getParent().getBindingContext();
|
|
1989
2014
|
var sSemanticObject = oEventSource.data("SemanticObject");
|
|
1990
2015
|
var sAction = oEventSource.data("Action");
|
|
2016
|
+
var oTarget = { semanticObject: sSemanticObject, action: sAction };
|
|
1991
2017
|
|
|
1992
2018
|
oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function() {
|
|
1993
2019
|
var oOutbound = {
|
|
@@ -1995,7 +2021,7 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
1995
2021
|
semanticObject: sSemanticObject
|
|
1996
2022
|
};
|
|
1997
2023
|
fnNavigateIntent(oOutbound, [oContext], oState.oSmartFilterbar || undefined);
|
|
1998
|
-
}, Function.prototype, "LeaveApp");
|
|
2024
|
+
}, Function.prototype, "LeaveApp", false, oTarget);
|
|
1999
2025
|
}
|
|
2000
2026
|
|
|
2001
2027
|
/*
|
|
@@ -2025,13 +2051,15 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
2025
2051
|
if (bRequiresContext && !aSelectedContexts.length) { // not consistent, since contexts missing
|
|
2026
2052
|
fnShowMessageForInvalidNumberOfSelects(aSelectedContexts.length);
|
|
2027
2053
|
} else {
|
|
2054
|
+
var oTarget = { semanticObject: oCustomData.SemanticObject, action: oCustomData.Action };
|
|
2028
2055
|
oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function () {
|
|
2029
2056
|
onDataFieldForIntentBasedNavigationSelectedContext(oCustomData, aSelectedContexts, oSmartFilterbar);
|
|
2030
|
-
}, Function.prototype, "LeaveApp");
|
|
2057
|
+
}, Function.prototype, "LeaveApp", false, oTarget);
|
|
2031
2058
|
}
|
|
2032
2059
|
}
|
|
2033
2060
|
|
|
2034
2061
|
function onInlineDataFieldForIntentBasedNavigation(oEventSource, oState){
|
|
2062
|
+
var oTarget = { semanticObject: oEventSource.data("SemanticObject"), action: oEventSource.data("Action") };
|
|
2035
2063
|
oCommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(function() {
|
|
2036
2064
|
var oOutbound = {
|
|
2037
2065
|
semanticObject: oEventSource.data("SemanticObject"),
|
|
@@ -2039,7 +2067,7 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
2039
2067
|
};
|
|
2040
2068
|
var oContext = oEventSource.getParent().getBindingContext();
|
|
2041
2069
|
fnNavigateIntent(oOutbound, [oContext], oState.oSmartFilterbar);
|
|
2042
|
-
}, Function.prototype, "LeaveApp");
|
|
2070
|
+
}, Function.prototype, "LeaveApp", false, oTarget);
|
|
2043
2071
|
}
|
|
2044
2072
|
|
|
2045
2073
|
function onInlineDataFieldForAction(oEvent) {
|
|
@@ -2709,7 +2737,16 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
2709
2737
|
var oSelectionVariant = fnBuildSelectionVariantForNavigation(oOutbound, [], oContext);
|
|
2710
2738
|
oController.adaptNavigationParameterExtension(oSelectionVariant, oOutbound);
|
|
2711
2739
|
oCommonUtils.setComponentRefreshBehaviour(oOutbound);
|
|
2712
|
-
|
|
2740
|
+
// Explace outbounds must bypass fnNavigateExternal to avoid setting the app busy and consuming the re-entry guard.
|
|
2741
|
+
// getNavigationHandler() returns a ghost stub (no .navigate) when ghostapp=true — guard before calling.
|
|
2742
|
+
if (oServices.oApplication.isExplaceNavigation(oOutbound.parameters)) {
|
|
2743
|
+
var oNavHandler = oServices.oApplication.getNavigationHandler();
|
|
2744
|
+
if (oNavHandler.navigate) {
|
|
2745
|
+
oNavHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError, null, "explace");
|
|
2746
|
+
}
|
|
2747
|
+
} else {
|
|
2748
|
+
oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, oCommonUtils.handleError);
|
|
2749
|
+
}
|
|
2713
2750
|
}
|
|
2714
2751
|
|
|
2715
2752
|
function onSmartFieldInitialise(oEvent,sViewId){
|
|
@@ -835,17 +835,17 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
835
835
|
|
|
836
836
|
setComponentRefreshBehaviour(oOutbound);
|
|
837
837
|
|
|
838
|
-
// We now
|
|
839
|
-
//
|
|
840
|
-
if (oOutbound.parameters
|
|
841
|
-
oNavigationHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, null, null,
|
|
838
|
+
// We now skip setting the app to busy mode when opening a new tab and bypass the re-entry guard (fnNavigateExternal) for explace navigations:
|
|
839
|
+
// 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.
|
|
840
|
+
if (oServices.oApplication.isExplaceNavigation(oOutbound.parameters)) {
|
|
841
|
+
oNavigationHandler.navigate(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, null, null, "explace");
|
|
842
842
|
} else {
|
|
843
843
|
oServices.oApplication.navigateExternal(oOutbound.semanticObject, oOutbound.action, oSelectionVariant.toJSONString(), null, fnHandleError);
|
|
844
844
|
//null object has to be passed to the NavigationHandler as an
|
|
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);
|
|
28
|
+
return Promise.resolve(false);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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;
|
|
@@ -709,22 +709,119 @@ sap.ui.define([
|
|
|
709
709
|
oSmartFilterBarWrapper.setState(oSmartFilterBarVariant);
|
|
710
710
|
// currentVariantSetModified intentionally omitted — pressing Go with the same
|
|
711
711
|
// query must not mark the variant as dirty.
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
712
|
+
|
|
713
|
+
var aSelectOptionsNeedingInjection = fnGetCustomFieldsNeedingInjection(oSmartFilterbar, oVariantDataFromAI.aSelectOptions);
|
|
714
|
+
fnInjectCustomFiltersOnRebind(aSelectOptionsNeedingInjection);
|
|
715
|
+
fnSyncCustomFieldInputValues(aSelectOptionsNeedingInjection, oSmartFilterbar);
|
|
716
|
+
|
|
717
|
+
// Apply sorters/groupLevels bundled with tokens after SFB state is set but
|
|
718
|
+
// before triggering search, to prevent a premature rebind with incomplete filters.
|
|
719
|
+
var aBundledSorters = oEvent.getParameter("sorters");
|
|
720
|
+
var aBundledGroupLevels = oEvent.getParameter("groupLevels");
|
|
721
|
+
if (aBundledSorters !== undefined) {
|
|
722
|
+
fnApplySortersToTable(aBundledSorters);
|
|
723
|
+
}
|
|
724
|
+
if (aBundledGroupLevels !== undefined) {
|
|
725
|
+
fnApplyGroupLevelsToTable(aBundledGroupLevels);
|
|
726
|
+
}
|
|
724
727
|
|
|
725
728
|
oSmartFilterbar.search();
|
|
726
729
|
}
|
|
727
730
|
|
|
731
|
+
/**
|
|
732
|
+
* Returns the subset of aSelectOptions whose property names landed in SFB's _CUSTOM
|
|
733
|
+
* bucket after setState — meaning SFB could not route them through its standard filter
|
|
734
|
+
* pipeline (plain Input fields with no value-list annotation).
|
|
735
|
+
* @param {object} oSmartFilterbar - The SmartFilterBar control instance
|
|
736
|
+
* @param {Array} aSelectOptions - Select options built from AI tokens
|
|
737
|
+
* @returns {Array} Select options that require direct filter injection
|
|
738
|
+
*/
|
|
739
|
+
function fnGetCustomFieldsNeedingInjection(oSmartFilterbar, aSelectOptions) {
|
|
740
|
+
var oFilterData = oSmartFilterbar.getFilterData();
|
|
741
|
+
var oCustomData = oFilterData && oFilterData._CUSTOM;
|
|
742
|
+
return aSelectOptions.filter(function(oSelectOption) {
|
|
743
|
+
return oCustomData && oCustomData.hasOwnProperty(oSelectOption.PropertyName);
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Builds UI5 Filter objects for each _CUSTOM select option and registers a one-shot
|
|
749
|
+
* beforeRebindTable handler on the SmartTable that injects them into bindingParams.filters
|
|
750
|
+
* just before the OData request is built — bypassing SFB's filter pipeline entirely.
|
|
751
|
+
* EQ is remapped to Contains to match Classic SFB substringof behaviour on plain Input fields.
|
|
752
|
+
* @param {Array} aSelectOptionsNeedingInjection - Select options that require direct filter injection
|
|
753
|
+
* @returns {void}
|
|
754
|
+
*/
|
|
755
|
+
function fnInjectCustomFiltersOnRebind(aSelectOptionsNeedingInjection) {
|
|
756
|
+
if (aSelectOptionsNeedingInjection.length === 0 || !oState.oPresentationControlHandler) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
var oSmartTable = oState.oPresentationControlHandler.getControl();
|
|
760
|
+
if (!oSmartTable || typeof oSmartTable.attachBeforeRebindTable !== 'function') {
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
var aInjectFilters = [];
|
|
764
|
+
aSelectOptionsNeedingInjection.forEach(function(oSelectOption) {
|
|
765
|
+
oSelectOption.Ranges.forEach(function(oRange) {
|
|
766
|
+
var sOp = oRange.Option;
|
|
767
|
+
var sVal = oRange.Low;
|
|
768
|
+
if (sOp === 'CP') {
|
|
769
|
+
aInjectFilters.push(new Filter(oSelectOption.PropertyName, FilterOperator.Contains, sVal.replace(/^\*|\*$/g, '')));
|
|
770
|
+
} else if (sOp === 'EQ') {
|
|
771
|
+
aInjectFilters.push(new Filter(oSelectOption.PropertyName, FilterOperator.Contains, sVal));
|
|
772
|
+
} else if (sOp === 'BT') {
|
|
773
|
+
aInjectFilters.push(new Filter(oSelectOption.PropertyName, FilterOperator.BT, oRange.Low, oRange.High));
|
|
774
|
+
} else if (sOp === 'NB') {
|
|
775
|
+
aInjectFilters.push(new Filter({path: oSelectOption.PropertyName, operator: FilterOperator.BT, value1: oRange.Low, value2: oRange.High, bExclude: true}));
|
|
776
|
+
} else {
|
|
777
|
+
var sMappedOp = FilterOperator[sOp];
|
|
778
|
+
if (!sMappedOp) {
|
|
779
|
+
oLogger.warning("EasyFilterBarHandler: unsupported select-option operator '" + sOp + "' for property '" + oSelectOption.PropertyName + "' — skipping filter injection");
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
aInjectFilters.push(new Filter(oSelectOption.PropertyName, sMappedOp, sVal));
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
});
|
|
786
|
+
var fnOnBeforeRebind = function(oRebindEvent) {
|
|
787
|
+
oSmartTable.detachBeforeRebindTable(fnOnBeforeRebind);
|
|
788
|
+
var oBindingParams = oRebindEvent.getParameter('bindingParams');
|
|
789
|
+
oBindingParams.filters = oBindingParams.filters || [];
|
|
790
|
+
var aBindingFilters = oBindingParams.filters;
|
|
791
|
+
// Remove prior easy-filter entries for the same properties to avoid stacking.
|
|
792
|
+
aInjectFilters.forEach(function(oF) {
|
|
793
|
+
for (var i = aBindingFilters.length - 1; i >= 0; i--) {
|
|
794
|
+
if (aBindingFilters[i] && aBindingFilters[i].sPath === oF.sPath) {
|
|
795
|
+
aBindingFilters.splice(i, 1);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
aBindingFilters.push(oF);
|
|
799
|
+
});
|
|
800
|
+
};
|
|
801
|
+
oSmartTable.attachBeforeRebindTable(fnOnBeforeRebind);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Sets the visible value on the SFB Input control for each _CUSTOM field so the Classic
|
|
806
|
+
* filter tab shows the correct value when the user switches filter modes.
|
|
807
|
+
* Uses setValue only — no fireChange — to avoid triggering SFB's async filter rebuild.
|
|
808
|
+
* @param {Array} aSelectOptionsNeedingInjection - Select options that require direct filter injection
|
|
809
|
+
* @param {object} oSmartFilterbar - The SmartFilterBar control instance
|
|
810
|
+
* @returns {void}
|
|
811
|
+
*/
|
|
812
|
+
function fnSyncCustomFieldInputValues(aSelectOptionsNeedingInjection, oSmartFilterbar) {
|
|
813
|
+
aSelectOptionsNeedingInjection.forEach(function(oSelectOption) {
|
|
814
|
+
if (oSelectOption.Ranges.length > 0) {
|
|
815
|
+
var aItems = oSmartFilterbar.getAllFilterItems(true) || [];
|
|
816
|
+
var oItem = aItems.find(function(i) { return i.getName && i.getName() === oSelectOption.PropertyName; });
|
|
817
|
+
var oCtrl = oItem && oItem.getControl && oItem.getControl();
|
|
818
|
+
if (oCtrl && oCtrl.setValue) {
|
|
819
|
+
oCtrl.setValue(oSelectOption.Ranges[0].Low);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
|
|
728
825
|
/**
|
|
729
826
|
* Event handler for the EasyFilterBarContainer's tokensChangedByUser event.
|
|
730
827
|
* Fired when the user manually deletes or modifies a token (distinct from AI-resolved tokens).
|
|
@@ -819,8 +916,8 @@ sap.ui.define([
|
|
|
819
916
|
/**
|
|
820
917
|
* Event handler for the EasyFilter control's showValueHelp event.
|
|
821
918
|
* Identifies the input field for which the value help is requested and triggers the value help opening from SFB.
|
|
822
|
-
* @param {
|
|
823
|
-
* @param {
|
|
919
|
+
* @param {sap.ui.base.Event} oEvent - The showValueHelp event fired by the EasyFilter control
|
|
920
|
+
* @param {object} oState - The current controller state object
|
|
824
921
|
*/
|
|
825
922
|
function fnShowValueHelp(oEvent) {
|
|
826
923
|
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.151.
|
|
3225
|
+
* @version 1.151.1
|
|
3226
3226
|
* @since 1.30.0
|
|
3227
3227
|
* @alias sap.suite.ui.generic.template.lib.NavigationController
|
|
3228
3228
|
*/
|