@sapui5/sap.fe.core 1.98.0 → 1.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/sap/fe/core/.library +1 -1
- package/src/sap/fe/core/AnnotationHelper.js +377 -405
- package/src/sap/fe/core/AnnotationHelper.ts +385 -0
- package/src/sap/fe/core/AppComponent.js +3 -2
- package/src/sap/fe/core/AppStateHandler.js +229 -181
- package/src/sap/fe/core/AppStateHandler.ts +171 -0
- package/src/sap/fe/core/BaseController.js +3 -2
- package/src/sap/fe/core/BusyLocker.js +105 -121
- package/src/sap/fe/core/BusyLocker.ts +98 -0
- package/src/sap/fe/core/CommonUtils.js +2073 -2399
- package/src/sap/fe/core/CommonUtils.ts +2078 -0
- package/src/sap/fe/core/ExtensionAPI.js +3 -2
- package/src/sap/fe/core/PageController.js +84 -125
- package/src/sap/fe/core/PageController.ts +101 -0
- package/src/sap/fe/core/RouterProxy.js +986 -823
- package/src/sap/fe/core/RouterProxy.ts +838 -0
- package/src/sap/fe/core/Synchronization.js +51 -35
- package/src/sap/fe/core/Synchronization.ts +29 -0
- package/src/sap/fe/core/TemplateComponent.js +173 -164
- package/src/sap/fe/core/TemplateComponent.ts +166 -0
- package/src/sap/fe/core/TemplateModel.js +97 -54
- package/src/sap/fe/core/TemplateModel.ts +63 -0
- package/src/sap/fe/core/TransactionHelper.js +1576 -1664
- package/src/sap/fe/core/TransactionHelper.ts +1706 -0
- package/src/sap/fe/core/actions/draft.js +559 -608
- package/src/sap/fe/core/actions/draft.ts +593 -0
- package/src/sap/fe/core/actions/messageHandling.js +545 -514
- package/src/sap/fe/core/actions/messageHandling.ts +532 -0
- package/src/sap/fe/core/actions/nonDraft.js +17 -19
- package/src/sap/fe/core/actions/nonDraft.ts +12 -0
- package/src/sap/fe/core/actions/operations.js +1074 -1215
- package/src/sap/fe/core/actions/operations.ts +1162 -0
- package/src/sap/fe/core/actions/sticky.js +102 -105
- package/src/sap/fe/core/actions/sticky.ts +102 -0
- package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +3 -2
- package/src/sap/fe/core/controllerextensions/EditFlow.js +54 -211
- package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +3 -2
- package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +279 -11
- package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +8 -6
- package/src/sap/fe/core/controllerextensions/InternalRouting.js +47 -45
- package/src/sap/fe/core/controllerextensions/KPIManagement.js +2 -3
- package/src/sap/fe/core/controllerextensions/KPIManagement.ts +29 -26
- package/src/sap/fe/core/controllerextensions/MassEdit.js +101 -8
- package/src/sap/fe/core/controllerextensions/MessageHandler.js +17 -8
- package/src/sap/fe/core/controllerextensions/PageReady.js +2 -2
- package/src/sap/fe/core/controllerextensions/PageReady.ts +12 -8
- package/src/sap/fe/core/controllerextensions/Paginator.js +3 -2
- package/src/sap/fe/core/controllerextensions/Placeholder.js +3 -2
- package/src/sap/fe/core/controllerextensions/Routing.js +9 -4
- package/src/sap/fe/core/controllerextensions/RoutingListener.js +3 -2
- package/src/sap/fe/core/controllerextensions/Share.js +3 -2
- package/src/sap/fe/core/controllerextensions/SideEffects.js +3 -3
- package/src/sap/fe/core/controllerextensions/SideEffects.ts +18 -18
- package/src/sap/fe/core/controllerextensions/ViewState.js +3 -2
- package/src/sap/fe/core/controls/CommandExecution.js +3 -2
- package/src/sap/fe/core/controls/ConditionalWrapper.js +3 -2
- package/src/sap/fe/core/controls/CustomQuickViewPage.js +3 -2
- package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +3 -2
- package/src/sap/fe/core/controls/FieldWrapper.js +11 -22
- package/src/sap/fe/core/controls/FilterBar.js +3 -2
- package/src/sap/fe/core/controls/FormElementWrapper.js +3 -2
- package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +3 -2
- package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +1 -0
- package/src/sap/fe/core/controls/filterbar/FilterContainer.js +3 -2
- package/src/sap/fe/core/controls/filterbar/VisualFilter.js +5 -4
- package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +3 -2
- package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +3 -2
- package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +3 -2
- package/src/sap/fe/core/converters/ConverterContext.js +2 -2
- package/src/sap/fe/core/converters/ConverterContext.ts +4 -3
- package/src/sap/fe/core/converters/ManifestSettings.js +1 -1
- package/src/sap/fe/core/converters/ManifestSettings.ts +1 -0
- package/src/sap/fe/core/converters/ManifestWrapper.js +39 -26
- package/src/sap/fe/core/converters/ManifestWrapper.ts +9 -0
- package/src/sap/fe/core/converters/MetaModelConverter.js +11 -8
- package/src/sap/fe/core/converters/MetaModelConverter.ts +16 -16
- package/src/sap/fe/core/converters/TemplateConverter.js +1 -1
- package/src/sap/fe/core/converters/TemplateConverter.ts +2 -2
- package/src/sap/fe/core/converters/common/AnnotationConverter.js +17 -13
- package/src/sap/fe/core/converters/controls/Common/Action.js +2 -2
- package/src/sap/fe/core/converters/controls/Common/Action.ts +2 -2
- package/src/sap/fe/core/converters/controls/Common/Chart.js +5 -3
- package/src/sap/fe/core/converters/controls/Common/Chart.ts +11 -3
- package/src/sap/fe/core/converters/controls/Common/DataVisualization.js +3 -3
- package/src/sap/fe/core/converters/controls/Common/DataVisualization.ts +2 -2
- package/src/sap/fe/core/converters/controls/Common/Form.js +4 -2
- package/src/sap/fe/core/converters/controls/Common/Form.ts +16 -2
- package/src/sap/fe/core/converters/controls/Common/Table.js +250 -146
- package/src/sap/fe/core/converters/controls/Common/Table.ts +300 -167
- package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +115 -56
- package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +120 -74
- package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +467 -32
- package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +483 -54
- package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +6 -6
- package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +9 -15
- package/src/sap/fe/core/converters/helpers/Aggregation.js +13 -5
- package/src/sap/fe/core/converters/helpers/Aggregation.ts +20 -5
- package/src/sap/fe/core/converters/helpers/IssueManager.js +4 -1
- package/src/sap/fe/core/converters/helpers/IssueManager.ts +3 -0
- package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +4 -4
- package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +3 -3
- package/src/sap/fe/core/converters/templates/ListReportConverter.js +13 -6
- package/src/sap/fe/core/converters/templates/ListReportConverter.ts +26 -15
- package/src/sap/fe/core/designtime/AppComponent.designtime.js +3 -2
- package/src/sap/fe/core/formatters/CriticalityFormatter.js +1 -1
- package/src/sap/fe/core/formatters/CriticalityFormatter.ts +1 -1
- package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
- package/src/sap/fe/core/formatters/FPMFormatter.ts +4 -10
- package/src/sap/fe/core/formatters/KPIFormatter.js +1 -1
- package/src/sap/fe/core/formatters/KPIFormatter.ts +3 -1
- package/src/sap/fe/core/formatters/TableFormatter.js +39 -28
- package/src/sap/fe/core/formatters/TableFormatter.ts +43 -28
- package/src/sap/fe/core/formatters/ValueFormatter.js +1 -1
- package/src/sap/fe/core/formatters/ValueFormatter.ts +7 -6
- package/src/sap/fe/core/fpm/Component.js +3 -2
- package/src/sap/fe/core/helpers/AppStartupHelper.js +2 -2
- package/src/sap/fe/core/helpers/AppStartupHelper.ts +7 -4
- package/src/sap/fe/core/helpers/BindingExpression.js +314 -355
- package/src/sap/fe/core/helpers/BindingExpression.ts +317 -391
- package/src/sap/fe/core/helpers/ClassSupport.js +27 -15
- package/src/sap/fe/core/helpers/ClassSupport.ts +31 -20
- package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +63 -59
- package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.ts +56 -0
- package/src/sap/fe/core/helpers/EditState.js +81 -84
- package/src/sap/fe/core/helpers/EditState.ts +81 -0
- package/src/sap/fe/core/helpers/ExcelFormatHelper.js +62 -48
- package/src/sap/fe/core/helpers/ExcelFormatHelper.ts +49 -0
- package/src/sap/fe/core/helpers/FPMHelper.js +52 -56
- package/src/sap/fe/core/helpers/FPMHelper.ts +62 -0
- package/src/sap/fe/core/helpers/KeepAliveHelper.js +3 -4
- package/src/sap/fe/core/helpers/KeepAliveHelper.ts +9 -9
- package/src/sap/fe/core/helpers/MassEditHelper.js +27 -18
- package/src/sap/fe/core/helpers/ModelHelper.js +229 -225
- package/src/sap/fe/core/helpers/ModelHelper.ts +227 -0
- package/src/sap/fe/core/helpers/PasteHelper.js +210 -132
- package/src/sap/fe/core/helpers/PasteHelper.ts +196 -0
- package/src/sap/fe/core/helpers/SemanticDateOperators.js +332 -313
- package/src/sap/fe/core/helpers/SemanticDateOperators.ts +330 -0
- package/src/sap/fe/core/helpers/SemanticKeyHelper.js +66 -67
- package/src/sap/fe/core/helpers/SemanticKeyHelper.ts +73 -0
- package/src/sap/fe/core/helpers/StableIdHelper.js +4 -7
- package/src/sap/fe/core/helpers/StableIdHelper.ts +2 -6
- package/src/sap/fe/core/jsx-runtime/jsx.js +1 -1
- package/src/sap/fe/core/jsx-runtime/jsx.ts +1 -1
- package/src/sap/fe/core/library.js +4 -3
- package/src/sap/fe/core/library.support.js +3 -2
- package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +1 -1
- package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +1 -1
- package/src/sap/fe/core/messagebundle.properties +23 -10
- package/src/sap/fe/core/messagebundle_ar.properties +9 -0
- package/src/sap/fe/core/messagebundle_bg.properties +9 -0
- package/src/sap/fe/core/messagebundle_ca.properties +9 -0
- package/src/sap/fe/core/messagebundle_cs.properties +10 -1
- package/src/sap/fe/core/messagebundle_cy.properties +9 -0
- package/src/sap/fe/core/messagebundle_da.properties +9 -0
- package/src/sap/fe/core/messagebundle_de.properties +9 -0
- package/src/sap/fe/core/messagebundle_el.properties +9 -0
- package/src/sap/fe/core/messagebundle_en.properties +9 -0
- package/src/sap/fe/core/messagebundle_en_GB.properties +9 -0
- package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +9 -0
- package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +9 -0
- package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +9 -0
- package/src/sap/fe/core/messagebundle_es.properties +9 -0
- package/src/sap/fe/core/messagebundle_es_MX.properties +9 -0
- package/src/sap/fe/core/messagebundle_et.properties +9 -0
- package/src/sap/fe/core/messagebundle_fi.properties +9 -0
- package/src/sap/fe/core/messagebundle_fr.properties +13 -4
- package/src/sap/fe/core/messagebundle_fr_CA.properties +15 -6
- package/src/sap/fe/core/messagebundle_hi.properties +15 -6
- package/src/sap/fe/core/messagebundle_hr.properties +15 -6
- package/src/sap/fe/core/messagebundle_hu.properties +9 -0
- package/src/sap/fe/core/messagebundle_id.properties +10 -1
- package/src/sap/fe/core/messagebundle_it.properties +9 -0
- package/src/sap/fe/core/messagebundle_iw.properties +9 -0
- package/src/sap/fe/core/messagebundle_ja.properties +9 -0
- package/src/sap/fe/core/messagebundle_kk.properties +15 -6
- package/src/sap/fe/core/messagebundle_ko.properties +9 -0
- package/src/sap/fe/core/messagebundle_lt.properties +9 -0
- package/src/sap/fe/core/messagebundle_lv.properties +15 -6
- package/src/sap/fe/core/messagebundle_ms.properties +14 -5
- package/src/sap/fe/core/messagebundle_nl.properties +9 -0
- package/src/sap/fe/core/messagebundle_no.properties +9 -0
- package/src/sap/fe/core/messagebundle_pl.properties +9 -0
- package/src/sap/fe/core/messagebundle_pt.properties +9 -0
- package/src/sap/fe/core/messagebundle_pt_PT.properties +9 -0
- package/src/sap/fe/core/messagebundle_ro.properties +9 -0
- package/src/sap/fe/core/messagebundle_ru.properties +9 -0
- package/src/sap/fe/core/messagebundle_sh.properties +11 -2
- package/src/sap/fe/core/messagebundle_sk.properties +9 -0
- package/src/sap/fe/core/messagebundle_sl.properties +15 -6
- package/src/sap/fe/core/messagebundle_sv.properties +9 -0
- package/src/sap/fe/core/messagebundle_th.properties +9 -0
- package/src/sap/fe/core/messagebundle_tr.properties +9 -0
- package/src/sap/fe/core/messagebundle_uk.properties +9 -0
- package/src/sap/fe/core/messagebundle_vi.properties +9 -0
- package/src/sap/fe/core/messagebundle_zh_CN.properties +9 -0
- package/src/sap/fe/core/messagebundle_zh_TW.properties +15 -6
- package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +1 -1
- package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +3 -1
- package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +269 -202
- package/src/sap/fe/core/services/CacheHandlerServiceFactory.ts +212 -0
- package/src/sap/fe/core/services/EnvironmentServiceFactory.js +1 -1
- package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +7 -6
- package/src/sap/fe/core/services/NavigationServiceFactory.js +406 -300
- package/src/sap/fe/core/services/NavigationServiceFactory.ts +316 -0
- package/src/sap/fe/core/services/ResourceModelServiceFactory.js +149 -81
- package/src/sap/fe/core/services/ResourceModelServiceFactory.ts +80 -0
- package/src/sap/fe/core/services/RoutingServiceFactory.js +987 -899
- package/src/sap/fe/core/services/RoutingServiceFactory.ts +898 -0
- package/src/sap/fe/core/services/ShellServicesFactory.js +1 -1
- package/src/sap/fe/core/services/ShellServicesFactory.ts +15 -10
- package/src/sap/fe/core/services/SideEffectsServiceFactory.js +35 -81
- package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +46 -94
- package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +461 -487
- package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +453 -0
- package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +10 -8
- package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.ts +8 -0
- package/src/sap/fe/core/support/AnnotationIssue.support.js +15 -3
- package/src/sap/fe/core/support/AnnotationIssue.support.ts +16 -2
- package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.js +2 -2
- package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.ts +1 -1
- package/src/sap/fe/core/templating/FieldControlHelper.js +8 -8
- package/src/sap/fe/core/templating/FieldControlHelper.ts +25 -7
- package/src/sap/fe/core/templating/FilterHelper.js +138 -72
- package/src/sap/fe/core/templating/FilterHelper.ts +139 -71
- package/src/sap/fe/core/templating/UIFormatters.js +31 -1
- package/src/sap/fe/core/templating/UIFormatters.ts +33 -2
- package/src/sap/fe/core/type/Email.js +1 -1
- package/src/sap/fe/core/type/Email.ts +4 -6
- package/ui5.yaml +0 -3
|
@@ -0,0 +1,1706 @@
|
|
|
1
|
+
import draft from "sap/fe/core/actions/draft";
|
|
2
|
+
import sticky from "sap/fe/core/actions/sticky";
|
|
3
|
+
import operations from "sap/fe/core/actions/operations";
|
|
4
|
+
import JSONModel from "sap/ui/model/json/JSONModel";
|
|
5
|
+
import Popover from "sap/m/Popover";
|
|
6
|
+
import VBox from "sap/m/VBox";
|
|
7
|
+
import CheckBox from "sap/m/CheckBox";
|
|
8
|
+
import Text from "sap/m/Text";
|
|
9
|
+
import Button from "sap/m/Button";
|
|
10
|
+
import MessageToast from "sap/m/MessageToast";
|
|
11
|
+
import Dialog from "sap/m/Dialog";
|
|
12
|
+
import Log from "sap/base/Log";
|
|
13
|
+
import CommonUtils from "sap/fe/core/CommonUtils";
|
|
14
|
+
import BusyLocker from "sap/fe/core/BusyLocker";
|
|
15
|
+
import XMLPreprocessor from "sap/ui/core/util/XMLPreprocessor";
|
|
16
|
+
import XMLTemplateProcessor from "sap/ui/core/XMLTemplateProcessor";
|
|
17
|
+
import Fragment from "sap/ui/core/Fragment";
|
|
18
|
+
import MessageBox from "sap/m/MessageBox";
|
|
19
|
+
import ModelHelper, { InternalModelContext } from "sap/fe/core/helpers/ModelHelper";
|
|
20
|
+
import FELibrary, { ProgrammingModel as ProgrammingModelType } from "sap/fe/core/library";
|
|
21
|
+
import coreLibrary from "sap/ui/core/library";
|
|
22
|
+
import messageHandling from "sap/fe/core/actions/messageHandling";
|
|
23
|
+
import { AppComponent } from "sap/fe/core";
|
|
24
|
+
import ResourceBundle from "sap/base/i18n/ResourceBundle";
|
|
25
|
+
import ODataMetaModel from "sap/ui/model/odata/v4/ODataMetaModel";
|
|
26
|
+
import View from "sap/ui/core/mvc/View";
|
|
27
|
+
import FPMHelper from "sap/fe/core/helpers/FPMHelper";
|
|
28
|
+
|
|
29
|
+
const CreationMode = FELibrary.CreationMode;
|
|
30
|
+
const ProgrammingModel = FELibrary.ProgrammingModel;
|
|
31
|
+
const ValueState = coreLibrary.ValueState;
|
|
32
|
+
/* Make sure that the mParameters is not the oEvent */
|
|
33
|
+
function getParameters(mParameters: any) {
|
|
34
|
+
if (mParameters && mParameters.getMetadata && mParameters.getMetadata().getName() === "sap.ui.base.Event") {
|
|
35
|
+
mParameters = {};
|
|
36
|
+
}
|
|
37
|
+
return mParameters || {};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
class TransactionHelper {
|
|
41
|
+
_oAppComponent: AppComponent;
|
|
42
|
+
oLockObject: any;
|
|
43
|
+
sProgrammingModel?: ProgrammingModelType;
|
|
44
|
+
_bIsModified: boolean = false;
|
|
45
|
+
_bCreateMode: boolean = false;
|
|
46
|
+
_bContinueDiscard: boolean = false;
|
|
47
|
+
_oPopover!: Popover;
|
|
48
|
+
constructor(oAppComponent: AppComponent, oLockObject: any) {
|
|
49
|
+
this._oAppComponent = oAppComponent;
|
|
50
|
+
this.oLockObject = oLockObject;
|
|
51
|
+
}
|
|
52
|
+
getProgrammingModel(oContext: any) {
|
|
53
|
+
if (!this.sProgrammingModel && oContext) {
|
|
54
|
+
let sPath;
|
|
55
|
+
if (oContext.isA("sap.ui.model.odata.v4.Context")) {
|
|
56
|
+
sPath = oContext.getPath();
|
|
57
|
+
} else {
|
|
58
|
+
sPath = oContext.isRelative() ? oContext.getResolvedPath() : oContext.getPath();
|
|
59
|
+
}
|
|
60
|
+
if (ModelHelper.isDraftSupported(oContext.getModel().getMetaModel(), sPath)) {
|
|
61
|
+
this.sProgrammingModel = ProgrammingModel.Draft;
|
|
62
|
+
} else if (ModelHelper.isStickySessionSupported(oContext.getModel().getMetaModel())) {
|
|
63
|
+
this.sProgrammingModel = ProgrammingModel.Sticky;
|
|
64
|
+
} else {
|
|
65
|
+
// as the transaction helper is a singleton we don't store the non draft as the user could
|
|
66
|
+
// start with a non draft child page and navigates back to a draft enabled one
|
|
67
|
+
return ProgrammingModel.NonDraft;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return this.sProgrammingModel;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Validates a document.
|
|
75
|
+
*
|
|
76
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
77
|
+
* @static
|
|
78
|
+
* @param {sap.ui.model.odata.v4.Context} oContext Context of the document to be validated
|
|
79
|
+
* @param {object} [mParameters] Can contain the following attributes:
|
|
80
|
+
* * @param {object} [mParameters.data] A map of data that should be validated
|
|
81
|
+
* * @param {string} [mParameters.customValidationFunction] A string representing the path to the validation function
|
|
82
|
+
* @param {object} oView Contains the object of the current view
|
|
83
|
+
* @returns {Promise} Promise resolves with result of the custom validation function
|
|
84
|
+
* @ui5-restricted
|
|
85
|
+
* @final
|
|
86
|
+
*/
|
|
87
|
+
validateDocument(oContext: any, mParameters: any, oView: View): Promise<any> {
|
|
88
|
+
const sCustomValidationFunction = mParameters && mParameters.customValidationFunction;
|
|
89
|
+
if (sCustomValidationFunction) {
|
|
90
|
+
const sModule = sCustomValidationFunction.substring(0, sCustomValidationFunction.lastIndexOf(".") || -1).replace(/\./gi, "/"),
|
|
91
|
+
sFunctionName = sCustomValidationFunction.substring(
|
|
92
|
+
sCustomValidationFunction.lastIndexOf(".") + 1,
|
|
93
|
+
sCustomValidationFunction.length
|
|
94
|
+
),
|
|
95
|
+
mData = mParameters.data;
|
|
96
|
+
delete mData["@$ui5.context.isTransient"];
|
|
97
|
+
return FPMHelper.validationWrapper(sModule, sFunctionName, mData, oView, oContext);
|
|
98
|
+
}
|
|
99
|
+
return Promise.resolve([]);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Creates a new document.
|
|
104
|
+
*
|
|
105
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
106
|
+
* @static
|
|
107
|
+
* @param {sap.ui.model.odata.v4.ODataListBinding} oMainListBinding OData V4 ListBinding object
|
|
108
|
+
* @param {object} [mInParameters] Optional, can contain the following attributes:
|
|
109
|
+
* @param {map} [mInParameters.data] A map of data that should be sent within the POST
|
|
110
|
+
* @param {string} [mInParameters.busyMode] Global (default), Local, None TODO: to be refactored
|
|
111
|
+
* @param {map} [mInParameters.keepTransientContextOnFailed] If set, the context stays in the list if the POST failed and POST will be repeated with the next change
|
|
112
|
+
* @param oResourceBundle
|
|
113
|
+
* @param messageHandler
|
|
114
|
+
* @param bFromCopyPaste
|
|
115
|
+
* @param oView The current view
|
|
116
|
+
* @returns {Promise} Promise resolves with new binding context
|
|
117
|
+
* @ui5-restricted
|
|
118
|
+
* @final
|
|
119
|
+
*/
|
|
120
|
+
createDocument(
|
|
121
|
+
oMainListBinding: any,
|
|
122
|
+
mInParameters: { data?: any; busyMode?: string | undefined; keepTransientContextOnFailed?: any } | undefined,
|
|
123
|
+
oResourceBundle: any,
|
|
124
|
+
messageHandler: any,
|
|
125
|
+
bFromCopyPaste: any,
|
|
126
|
+
oView: any
|
|
127
|
+
) {
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
129
|
+
const that = this,
|
|
130
|
+
oModel = oMainListBinding.getModel(),
|
|
131
|
+
oMetaModel = oModel.getMetaModel(),
|
|
132
|
+
sMetaPath = oMetaModel.getMetaPath(oMainListBinding.getHeaderContext().getPath()),
|
|
133
|
+
sCreateHash = this._getAppComponent()
|
|
134
|
+
.getRouterProxy()
|
|
135
|
+
.getHash(),
|
|
136
|
+
oComponentData = this._getAppComponent().getComponentData(),
|
|
137
|
+
oStartupParameters = (oComponentData && oComponentData.startupParameters) || {},
|
|
138
|
+
sNewAction = !oMainListBinding.isRelative()
|
|
139
|
+
? this._getNewAction(oStartupParameters, sCreateHash, oMetaModel, sMetaPath)
|
|
140
|
+
: undefined;
|
|
141
|
+
let oCreationPromise;
|
|
142
|
+
const mBindingParameters: any = { "$$patchWithoutSideEffects": true };
|
|
143
|
+
const sMessagesPath = oMetaModel.getObject(sMetaPath + "/@com.sap.vocabularies.Common.v1.Messages/$Path");
|
|
144
|
+
let sBusyPath = "/busy";
|
|
145
|
+
let sFunctionName =
|
|
146
|
+
oMetaModel.getObject(sMetaPath + "@com.sap.vocabularies.Common.v1.DefaultValuesFunction") ||
|
|
147
|
+
oMetaModel.getObject(
|
|
148
|
+
ModelHelper.getTargetEntitySet(oMetaModel.getContext(sMetaPath)) + "@com.sap.vocabularies.Common.v1.DefaultValuesFunction"
|
|
149
|
+
);
|
|
150
|
+
let bFunctionOnNavProp;
|
|
151
|
+
let oNewDocumentContext: any;
|
|
152
|
+
if (sFunctionName) {
|
|
153
|
+
if (
|
|
154
|
+
oMetaModel.getObject(sMetaPath + "@com.sap.vocabularies.Common.v1.DefaultValuesFunction") &&
|
|
155
|
+
ModelHelper.getTargetEntitySet(oMetaModel.getContext(sMetaPath)) !== sMetaPath
|
|
156
|
+
) {
|
|
157
|
+
bFunctionOnNavProp = true;
|
|
158
|
+
} else {
|
|
159
|
+
bFunctionOnNavProp = false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (sMessagesPath) {
|
|
163
|
+
mBindingParameters["$select"] = sMessagesPath;
|
|
164
|
+
}
|
|
165
|
+
const mParameters = getParameters(mInParameters);
|
|
166
|
+
if (!oMainListBinding) {
|
|
167
|
+
return Promise.reject("Binding required for new document creation");
|
|
168
|
+
}
|
|
169
|
+
const sProgrammingModel = this.getProgrammingModel(oMainListBinding);
|
|
170
|
+
if (sProgrammingModel !== ProgrammingModel.Draft && sProgrammingModel !== ProgrammingModel.Sticky) {
|
|
171
|
+
return Promise.reject("Create document only allowed for draft or sticky session supported services");
|
|
172
|
+
}
|
|
173
|
+
if (mParameters.busyMode === "Local") {
|
|
174
|
+
// in case of local busy mode we use the list binding name
|
|
175
|
+
// there's no APY yet so we have to use the .sId TODO provide a public method?
|
|
176
|
+
sBusyPath = "/busyLocal/" + oMainListBinding.sId;
|
|
177
|
+
}
|
|
178
|
+
mParameters.beforeCreateCallBack = bFromCopyPaste ? null : mParameters.beforeCreateCallBack;
|
|
179
|
+
BusyLocker.lock(this.oLockObject, sBusyPath);
|
|
180
|
+
const oResourceBundleCore = sap.ui.getCore().getLibraryResourceBundle("sap.fe.core");
|
|
181
|
+
if (sNewAction) {
|
|
182
|
+
oCreationPromise = this.callAction(
|
|
183
|
+
sNewAction,
|
|
184
|
+
{
|
|
185
|
+
contexts: oMainListBinding.getHeaderContext(),
|
|
186
|
+
showActionParameterDialog: true,
|
|
187
|
+
label: this._getSpecificCreateActionDialogLabel(
|
|
188
|
+
oMetaModel,
|
|
189
|
+
sMetaPath,
|
|
190
|
+
sNewAction,
|
|
191
|
+
oResourceBundleCore as ResourceBundle
|
|
192
|
+
),
|
|
193
|
+
bindingParameters: mBindingParameters,
|
|
194
|
+
parentControl: mParameters.parentControl,
|
|
195
|
+
bIsCreateAction: true
|
|
196
|
+
},
|
|
197
|
+
null,
|
|
198
|
+
messageHandler
|
|
199
|
+
);
|
|
200
|
+
} else {
|
|
201
|
+
const bIsNewPageCreation =
|
|
202
|
+
mParameters.creationMode !== CreationMode.CreationRow && mParameters.creationMode !== CreationMode.Inline;
|
|
203
|
+
const aNonComputedVisibleKeyFields = bIsNewPageCreation
|
|
204
|
+
? CommonUtils.getNonComputedVisibleFields(oMetaModel, sMetaPath, oView)
|
|
205
|
+
: [];
|
|
206
|
+
sFunctionName = bFromCopyPaste ? null : sFunctionName;
|
|
207
|
+
let sFunctionPath, oFunctionContext;
|
|
208
|
+
if (sFunctionName) {
|
|
209
|
+
//bound to the source entity:
|
|
210
|
+
if (bFunctionOnNavProp) {
|
|
211
|
+
sFunctionPath =
|
|
212
|
+
oMainListBinding.getContext() &&
|
|
213
|
+
oMetaModel.getMetaPath(oMainListBinding.getContext().getPath()) + "/" + sFunctionName;
|
|
214
|
+
oFunctionContext = oMainListBinding.getContext();
|
|
215
|
+
} else {
|
|
216
|
+
sFunctionPath =
|
|
217
|
+
oMainListBinding.getHeaderContext() &&
|
|
218
|
+
oMetaModel.getMetaPath(oMainListBinding.getHeaderContext().getPath()) + "/" + sFunctionName;
|
|
219
|
+
oFunctionContext = oMainListBinding.getHeaderContext();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const oFunction = sFunctionPath && oMetaModel.createBindingContext(sFunctionPath);
|
|
223
|
+
if (oFunction && oFunction.getObject() && oFunction.getObject()[0].$IsBound) {
|
|
224
|
+
oCreationPromise = operations.callBoundFunction(sFunctionName, oFunctionContext, oModel);
|
|
225
|
+
} else {
|
|
226
|
+
oCreationPromise = operations.callFunctionImport(sFunctionName, oModel);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
oCreationPromise = oCreationPromise
|
|
230
|
+
.then(function(oContext: any) {
|
|
231
|
+
if (oContext) {
|
|
232
|
+
return oContext.getObject();
|
|
233
|
+
} else {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
.catch(function(oError: any) {
|
|
238
|
+
Log.error("Error while executing the function " + sFunctionName, oError);
|
|
239
|
+
throw oError;
|
|
240
|
+
})
|
|
241
|
+
.then(function(oData: any) {
|
|
242
|
+
mParameters.data = oData ? Object.assign({}, oData, mParameters.data) : mParameters.data;
|
|
243
|
+
if (mParameters.data) {
|
|
244
|
+
delete mParameters.data["@odata.context"];
|
|
245
|
+
}
|
|
246
|
+
if (aNonComputedVisibleKeyFields.length > 0) {
|
|
247
|
+
const oTransientListBinding = oModel.bindList(oMainListBinding.getPath(), oMainListBinding.getContext(), [], [], {
|
|
248
|
+
$$updateGroupId: "submitLater"
|
|
249
|
+
});
|
|
250
|
+
oTransientListBinding.refreshInternal = function() {
|
|
251
|
+
/* */
|
|
252
|
+
};
|
|
253
|
+
oNewDocumentContext = oTransientListBinding.create(mParameters.data, true);
|
|
254
|
+
return that._launchDialogWithKeyFields(
|
|
255
|
+
oMainListBinding,
|
|
256
|
+
oTransientListBinding,
|
|
257
|
+
oNewDocumentContext,
|
|
258
|
+
aNonComputedVisibleKeyFields,
|
|
259
|
+
oModel,
|
|
260
|
+
mParameters,
|
|
261
|
+
messageHandler
|
|
262
|
+
);
|
|
263
|
+
} else {
|
|
264
|
+
let onBeforeCreatePromise;
|
|
265
|
+
if (mParameters.beforeCreateCallBack) {
|
|
266
|
+
onBeforeCreatePromise = mParameters.beforeCreateCallBack({
|
|
267
|
+
contextPath: oMainListBinding && oMainListBinding.getPath()
|
|
268
|
+
});
|
|
269
|
+
} else {
|
|
270
|
+
onBeforeCreatePromise = Promise.resolve();
|
|
271
|
+
}
|
|
272
|
+
return onBeforeCreatePromise.then(function() {
|
|
273
|
+
oNewDocumentContext = oMainListBinding.create(mParameters.data, true, mParameters.createAtEnd);
|
|
274
|
+
return that.onAfterCreateCompletion(oMainListBinding, oNewDocumentContext, mParameters);
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
})
|
|
278
|
+
.catch(function(oError: any) {
|
|
279
|
+
Log.error("Error while creating the new document", oError);
|
|
280
|
+
throw oError;
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return oCreationPromise
|
|
284
|
+
.then(function(oResult: any) {
|
|
285
|
+
if (!oMainListBinding.isRelative()) {
|
|
286
|
+
// the create mode shall currently only be set on creating a root document
|
|
287
|
+
that._bCreateMode = true;
|
|
288
|
+
}
|
|
289
|
+
oNewDocumentContext = oNewDocumentContext || (oResult && oResult.response);
|
|
290
|
+
// TODO: where does this one coming from???
|
|
291
|
+
if (oResult && oResult.bConsiderDocumentModified) {
|
|
292
|
+
that.handleDocumentModifications();
|
|
293
|
+
}
|
|
294
|
+
return messageHandler.showMessageDialog().then(function() {
|
|
295
|
+
return oNewDocumentContext;
|
|
296
|
+
});
|
|
297
|
+
})
|
|
298
|
+
.catch(function(oError: any) {
|
|
299
|
+
return messageHandler.showMessageDialog().then(function() {
|
|
300
|
+
// for instance, on cancel of create dialog, the promise is rejected
|
|
301
|
+
// a return here would restore the promise chain and result in errors while routing
|
|
302
|
+
// solution - reject here as well
|
|
303
|
+
if (oError && oError.bDeleteTransientContext && oNewDocumentContext.isTransient()) {
|
|
304
|
+
// This is a workaround suggested by model as Context.delete results in an error
|
|
305
|
+
// TODO: remove the $direct once model resolves this issue
|
|
306
|
+
// this line shows the expected console error Uncaught (in promise) Error: Request canceled: POST Travel; group: submitLater
|
|
307
|
+
oNewDocumentContext.delete("$direct");
|
|
308
|
+
}
|
|
309
|
+
return Promise.reject(oError);
|
|
310
|
+
});
|
|
311
|
+
})
|
|
312
|
+
.finally(function() {
|
|
313
|
+
BusyLocker.unlock(that.oLockObject, sBusyPath);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Find the active contexts of the documents, only for the draft roots.
|
|
318
|
+
*
|
|
319
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
320
|
+
* @static
|
|
321
|
+
* @param {sap.ui.model.odata.v4.Context[]} aContexts Contexts Either one context or an array with contexts to be deleted
|
|
322
|
+
* @param bFindActiveContexts
|
|
323
|
+
* @returns {Array} Array of the active contexts
|
|
324
|
+
*/
|
|
325
|
+
findActiveDraftRootContexts(aContexts: any[], bFindActiveContexts: any) {
|
|
326
|
+
if (!bFindActiveContexts) {
|
|
327
|
+
return Promise.resolve();
|
|
328
|
+
}
|
|
329
|
+
const activeContexts = aContexts.reduce(function(aResult: any, oContext: any) {
|
|
330
|
+
const oMetaModel = oContext.getModel().getMetaModel();
|
|
331
|
+
const sMetaPath = oMetaModel.getMetaPath(oContext.getPath());
|
|
332
|
+
if (oMetaModel.getObject(sMetaPath + "@com.sap.vocabularies.Common.v1.DraftRoot")) {
|
|
333
|
+
const bIsActiveEntity = oContext.getObject().IsActiveEntity,
|
|
334
|
+
bHasActiveEntity = oContext.getObject().HasActiveEntity;
|
|
335
|
+
if (!bIsActiveEntity && bHasActiveEntity) {
|
|
336
|
+
const oActiveContext = oContext
|
|
337
|
+
.getModel()
|
|
338
|
+
.bindContext(oContext.getPath() + "/SiblingEntity")
|
|
339
|
+
.getBoundContext();
|
|
340
|
+
aResult.push(oActiveContext);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return aResult;
|
|
344
|
+
}, []);
|
|
345
|
+
return Promise.all(
|
|
346
|
+
activeContexts.map(function(oContext: any) {
|
|
347
|
+
return oContext.requestCanonicalPath().then(
|
|
348
|
+
function() {
|
|
349
|
+
return oContext;
|
|
350
|
+
},
|
|
351
|
+
function() {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
})
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
afterDeleteProcess(mParameters: any, checkBox: any, aContexts: any, oResourceBundle: any) {
|
|
359
|
+
const oInternalModelContext = mParameters.internalModelContext;
|
|
360
|
+
if (oInternalModelContext && oInternalModelContext.getProperty("deleteEnabled") != undefined) {
|
|
361
|
+
if (checkBox.isCheckBoxVisible === true && checkBox.isCheckBoxSelected === false) {
|
|
362
|
+
//if unsaved objects are not deleted then we need to set the enabled to true and update the model data for next deletion
|
|
363
|
+
oInternalModelContext.setProperty("deleteEnabled", true);
|
|
364
|
+
const obj = Object.assign(oInternalModelContext.getObject(), {});
|
|
365
|
+
obj.selectedContexts = obj.selectedContexts.filter(function(element: any) {
|
|
366
|
+
return obj.deletableContexts.indexOf(element) === -1;
|
|
367
|
+
});
|
|
368
|
+
obj.deletableContexts = [];
|
|
369
|
+
obj.selectedContexts = [];
|
|
370
|
+
obj.numberOfSelectedContexts = obj.selectedContexts.length;
|
|
371
|
+
oInternalModelContext.setProperty("", obj);
|
|
372
|
+
} else {
|
|
373
|
+
oInternalModelContext.setProperty("deleteEnabled", false);
|
|
374
|
+
oInternalModelContext.setProperty("selectedContexts", []);
|
|
375
|
+
oInternalModelContext.setProperty("numberOfSelectedContexts", 0);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (aContexts.length === 1) {
|
|
379
|
+
MessageToast.show(
|
|
380
|
+
CommonUtils.getTranslatedText(
|
|
381
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_DELETE_TOAST_SINGULAR",
|
|
382
|
+
oResourceBundle,
|
|
383
|
+
null,
|
|
384
|
+
mParameters.entitySetName
|
|
385
|
+
)
|
|
386
|
+
);
|
|
387
|
+
} else {
|
|
388
|
+
MessageToast.show(
|
|
389
|
+
CommonUtils.getTranslatedText(
|
|
390
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_DELETE_TOAST_PLURAL",
|
|
391
|
+
oResourceBundle,
|
|
392
|
+
null,
|
|
393
|
+
mParameters.entitySetName
|
|
394
|
+
)
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Delete one or multiple document(s).
|
|
400
|
+
*
|
|
401
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
402
|
+
* @static
|
|
403
|
+
* @param {sap.ui.model.odata.v4.Context} vContexts Contexts Either one context or an array with contexts to be deleted
|
|
404
|
+
* @param {object} mParameters Optional, can contain the following attributes:
|
|
405
|
+
* @param {string} mParameters.title Title of the object to be deleted
|
|
406
|
+
* @param {string} mParameters.description Description of the object to be deleted
|
|
407
|
+
* @param {integer} mParameters.numberOfSelectedContexts Number of objects selected
|
|
408
|
+
* @param {boolean} mParameters.noDialog To disable the confirmation dialog
|
|
409
|
+
* @param oResourceBundle
|
|
410
|
+
* @param messageHandler
|
|
411
|
+
* @returns {Promise}
|
|
412
|
+
*/
|
|
413
|
+
deleteDocument(vContexts: any, mParameters: any, oResourceBundle: any, messageHandler: any) {
|
|
414
|
+
let fnReject: Function,
|
|
415
|
+
fnResolve: Function,
|
|
416
|
+
aDeletableContexts: any[] = [],
|
|
417
|
+
isCheckBoxVisible = false,
|
|
418
|
+
isLockedTextVisible = false,
|
|
419
|
+
cannotBeDeletedTextVisible = false,
|
|
420
|
+
isCheckBoxSelected: boolean,
|
|
421
|
+
bDialogConfirmed = false;
|
|
422
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
423
|
+
const that = this,
|
|
424
|
+
oResourceBundleCore = sap.ui.getCore().getLibraryResourceBundle("sap.fe.core") as ResourceBundle;
|
|
425
|
+
let aParams;
|
|
426
|
+
let oDeleteMessage: any = {
|
|
427
|
+
title: oResourceBundleCore.getText("C_COMMON_OBJECT_PAGE_DELETE")
|
|
428
|
+
};
|
|
429
|
+
BusyLocker.lock(this.oLockObject);
|
|
430
|
+
if (!Array.isArray(vContexts)) {
|
|
431
|
+
vContexts = [vContexts];
|
|
432
|
+
}
|
|
433
|
+
Promise.resolve(this.getProgrammingModel(vContexts[0]))
|
|
434
|
+
.then(function(sProgrammingModel: any) {
|
|
435
|
+
if (mParameters) {
|
|
436
|
+
if (!mParameters.numberOfSelectedContexts) {
|
|
437
|
+
if (sProgrammingModel === ProgrammingModel.Draft) {
|
|
438
|
+
for (let i = 0; i < vContexts.length; i++) {
|
|
439
|
+
const oContextData = vContexts[i].getObject();
|
|
440
|
+
if (
|
|
441
|
+
oContextData.IsActiveEntity === true &&
|
|
442
|
+
oContextData.HasDraftEntity === true &&
|
|
443
|
+
oContextData.DraftAdministrativeData &&
|
|
444
|
+
oContextData.DraftAdministrativeData.InProcessByUser &&
|
|
445
|
+
!oContextData.DraftAdministrativeData.DraftIsCreatedByMe
|
|
446
|
+
) {
|
|
447
|
+
MessageBox.show(
|
|
448
|
+
CommonUtils.getTranslatedText(
|
|
449
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_SINGLE_OBJECT_LOCKED",
|
|
450
|
+
oResourceBundle
|
|
451
|
+
),
|
|
452
|
+
{
|
|
453
|
+
title: oResourceBundleCore.getText("C_COMMON_OBJECT_PAGE_DELETE"),
|
|
454
|
+
onClose: fnReject
|
|
455
|
+
}
|
|
456
|
+
);
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
mParameters = getParameters(mParameters);
|
|
462
|
+
if (mParameters.title) {
|
|
463
|
+
aParams = [mParameters.title, mParameters.description];
|
|
464
|
+
oDeleteMessage.text = CommonUtils.getTranslatedText(
|
|
465
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTINFO",
|
|
466
|
+
oResourceBundle,
|
|
467
|
+
aParams,
|
|
468
|
+
mParameters.entitySetName
|
|
469
|
+
);
|
|
470
|
+
} else {
|
|
471
|
+
oDeleteMessage.text = CommonUtils.getTranslatedText(
|
|
472
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTTITLE_SINGULAR",
|
|
473
|
+
oResourceBundle
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
aDeletableContexts = vContexts;
|
|
477
|
+
} else {
|
|
478
|
+
oDeleteMessage = {
|
|
479
|
+
title: oResourceBundleCore.getText("C_COMMON_OBJECT_PAGE_DELETE")
|
|
480
|
+
};
|
|
481
|
+
if (mParameters.numberOfSelectedContexts === 1 && mParameters.numberOfSelectedContexts === vContexts.length) {
|
|
482
|
+
aDeletableContexts = vContexts;
|
|
483
|
+
oDeleteMessage.text = CommonUtils.getTranslatedText(
|
|
484
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTTITLE_SINGULAR",
|
|
485
|
+
oResourceBundle,
|
|
486
|
+
null,
|
|
487
|
+
mParameters.entitySetName
|
|
488
|
+
);
|
|
489
|
+
} else if (mParameters.numberOfSelectedContexts === 1 && mParameters.unSavedContexts.length === 1) {
|
|
490
|
+
//only one unsaved object
|
|
491
|
+
aDeletableContexts = mParameters.unSavedContexts;
|
|
492
|
+
const draftAdminData = aDeletableContexts[0].getObject()["DraftAdministrativeData"];
|
|
493
|
+
let sLastChangedByUser = "";
|
|
494
|
+
if (draftAdminData) {
|
|
495
|
+
sLastChangedByUser =
|
|
496
|
+
draftAdminData["LastChangedByUserDescription"] || draftAdminData["LastChangedByUser"] || "";
|
|
497
|
+
}
|
|
498
|
+
aParams = [sLastChangedByUser];
|
|
499
|
+
oDeleteMessage.text = CommonUtils.getTranslatedText(
|
|
500
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_UNSAVED_CHANGES",
|
|
501
|
+
oResourceBundle,
|
|
502
|
+
aParams
|
|
503
|
+
);
|
|
504
|
+
} else if (mParameters.numberOfSelectedContexts === mParameters.unSavedContexts.length) {
|
|
505
|
+
//only multiple unsaved objects
|
|
506
|
+
aDeletableContexts = mParameters.unSavedContexts;
|
|
507
|
+
oDeleteMessage.text = CommonUtils.getTranslatedText(
|
|
508
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_UNSAVED_CHANGES_MULTIPLE_OBJECTS",
|
|
509
|
+
oResourceBundle
|
|
510
|
+
);
|
|
511
|
+
} else if (
|
|
512
|
+
mParameters.numberOfSelectedContexts ===
|
|
513
|
+
vContexts.concat(mParameters.unSavedContexts.concat(mParameters.lockedContexts)).length
|
|
514
|
+
) {
|
|
515
|
+
//only unsaved, locked ,deletable objects but not non-deletable objects
|
|
516
|
+
aDeletableContexts = vContexts.concat(mParameters.unSavedContexts);
|
|
517
|
+
oDeleteMessage.text =
|
|
518
|
+
aDeletableContexts.length === 1
|
|
519
|
+
? CommonUtils.getTranslatedText(
|
|
520
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTTITLE_SINGULAR",
|
|
521
|
+
oResourceBundle,
|
|
522
|
+
null,
|
|
523
|
+
mParameters.entitySetName
|
|
524
|
+
)
|
|
525
|
+
: CommonUtils.getTranslatedText(
|
|
526
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTTITLE_PLURAL",
|
|
527
|
+
oResourceBundle,
|
|
528
|
+
null,
|
|
529
|
+
mParameters.entitySetName
|
|
530
|
+
);
|
|
531
|
+
} else {
|
|
532
|
+
//if non-deletable objects exists along with any of unsaved ,deletable objects
|
|
533
|
+
aDeletableContexts = vContexts.concat(mParameters.unSavedContexts);
|
|
534
|
+
cannotBeDeletedTextVisible = true;
|
|
535
|
+
oDeleteMessage.text =
|
|
536
|
+
aDeletableContexts.length === 1
|
|
537
|
+
? CommonUtils.getTranslatedText(
|
|
538
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTTITLE_SINGULAR_NON_DELETABLE",
|
|
539
|
+
oResourceBundle,
|
|
540
|
+
null,
|
|
541
|
+
mParameters.entitySetName
|
|
542
|
+
)
|
|
543
|
+
: CommonUtils.getTranslatedText(
|
|
544
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTTITLE_PLURAL_NON_DELETABLE",
|
|
545
|
+
oResourceBundle,
|
|
546
|
+
null,
|
|
547
|
+
mParameters.entitySetName
|
|
548
|
+
);
|
|
549
|
+
oDeleteMessage.nonDeletableText = CommonUtils.getTranslatedText(
|
|
550
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTINFO_AND_FEW_OBJECTS_NON_DELETABLE",
|
|
551
|
+
oResourceBundle,
|
|
552
|
+
[
|
|
553
|
+
mParameters.numberOfSelectedContexts - vContexts.concat(mParameters.unSavedContexts).length,
|
|
554
|
+
mParameters.numberOfSelectedContexts
|
|
555
|
+
]
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
if (mParameters.lockedContexts.length == 1) {
|
|
559
|
+
//setting the locked text if locked objects exist
|
|
560
|
+
isLockedTextVisible = true;
|
|
561
|
+
oDeleteMessage.nonDeletableText = CommonUtils.getTranslatedText(
|
|
562
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTINFO_AND_ONE_OBJECT_LOCKED",
|
|
563
|
+
oResourceBundle,
|
|
564
|
+
[mParameters.numberOfSelectedContexts]
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
if (mParameters.lockedContexts.length > 1) {
|
|
568
|
+
//setting the locked text if locked objects exist
|
|
569
|
+
isLockedTextVisible = true;
|
|
570
|
+
oDeleteMessage.nonDeletableText = CommonUtils.getTranslatedText(
|
|
571
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTINFO_AND_FEW_OBJECTS_LOCKED",
|
|
572
|
+
oResourceBundle,
|
|
573
|
+
[mParameters.lockedContexts.length, mParameters.numberOfSelectedContexts]
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
if (
|
|
577
|
+
mParameters.unSavedContexts.length > 0 &&
|
|
578
|
+
mParameters.unSavedContexts.length !== mParameters.numberOfSelectedContexts
|
|
579
|
+
) {
|
|
580
|
+
if (
|
|
581
|
+
(cannotBeDeletedTextVisible || isLockedTextVisible) &&
|
|
582
|
+
aDeletableContexts.length === mParameters.unSavedContexts.length
|
|
583
|
+
) {
|
|
584
|
+
//if only unsaved and either or both of locked and non-deletable objects exist then we hide the check box
|
|
585
|
+
isCheckBoxVisible = false;
|
|
586
|
+
aDeletableContexts = mParameters.unSavedContexts;
|
|
587
|
+
if (mParameters.unSavedContexts.length === 1) {
|
|
588
|
+
oDeleteMessage.text = CommonUtils.getTranslatedText(
|
|
589
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_UNSAVED_AND_FEW_OBJECTS_LOCKED_SINGULAR",
|
|
590
|
+
oResourceBundle
|
|
591
|
+
);
|
|
592
|
+
} else {
|
|
593
|
+
oDeleteMessage.text = CommonUtils.getTranslatedText(
|
|
594
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_UNSAVED_AND_FEW_OBJECTS_LOCKED_PLURAL",
|
|
595
|
+
oResourceBundle
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
} else {
|
|
599
|
+
if (mParameters.unSavedContexts.length === 1) {
|
|
600
|
+
oDeleteMessage.checkBoxText = CommonUtils.getTranslatedText(
|
|
601
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTINFO_AND_FEW_OBJECTS_UNSAVED_SINGULAR",
|
|
602
|
+
oResourceBundle
|
|
603
|
+
);
|
|
604
|
+
} else {
|
|
605
|
+
oDeleteMessage.checkBoxText = CommonUtils.getTranslatedText(
|
|
606
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTINFO_AND_FEW_OBJECTS_UNSAVED_PLURAL",
|
|
607
|
+
oResourceBundle
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
isCheckBoxVisible = true;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (cannotBeDeletedTextVisible && isLockedTextVisible) {
|
|
614
|
+
//if both locked and non-deletable objects exist along with deletable objects
|
|
615
|
+
if (mParameters.unSavedContexts.length > 1) {
|
|
616
|
+
oDeleteMessage.nonDeletableText = CommonUtils.getTranslatedText(
|
|
617
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTINFO_AND_FEW_OBJECTS_LOCKED_AND_NON_DELETABLE",
|
|
618
|
+
oResourceBundle,
|
|
619
|
+
[
|
|
620
|
+
mParameters.numberOfSelectedContexts -
|
|
621
|
+
vContexts.concat(mParameters.unSavedContexts).length -
|
|
622
|
+
mParameters.lockedContexts.length,
|
|
623
|
+
mParameters.lockedContexts.length,
|
|
624
|
+
mParameters.numberOfSelectedContexts
|
|
625
|
+
]
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
if (mParameters.unSavedContexts.length == 1) {
|
|
629
|
+
oDeleteMessage.nonDeletableText = CommonUtils.getTranslatedText(
|
|
630
|
+
"C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTINFO_AND_ONE_OBJECT_LOCKED_AND_NON_DELETABLE",
|
|
631
|
+
oResourceBundle,
|
|
632
|
+
[
|
|
633
|
+
mParameters.numberOfSelectedContexts -
|
|
634
|
+
vContexts.concat(mParameters.unSavedContexts).length -
|
|
635
|
+
mParameters.lockedContexts.length,
|
|
636
|
+
mParameters.numberOfSelectedContexts
|
|
637
|
+
]
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
let oNonDeletableMessageTextControl, oDeleteMessageTextControl;
|
|
644
|
+
const oContent = new VBox({
|
|
645
|
+
items: [
|
|
646
|
+
(oNonDeletableMessageTextControl = new Text({
|
|
647
|
+
text: oDeleteMessage.nonDeletableText,
|
|
648
|
+
visible: isLockedTextVisible || cannotBeDeletedTextVisible
|
|
649
|
+
})),
|
|
650
|
+
(oDeleteMessageTextControl = new Text({
|
|
651
|
+
text: oDeleteMessage.text
|
|
652
|
+
})),
|
|
653
|
+
new CheckBox({
|
|
654
|
+
text: oDeleteMessage.checkBoxText,
|
|
655
|
+
selected: true,
|
|
656
|
+
select: function(oEvent: any) {
|
|
657
|
+
const selected = oEvent.getSource().getSelected();
|
|
658
|
+
if (selected) {
|
|
659
|
+
aDeletableContexts = vContexts.concat(mParameters.unSavedContexts);
|
|
660
|
+
isCheckBoxSelected = true;
|
|
661
|
+
} else {
|
|
662
|
+
aDeletableContexts = vContexts;
|
|
663
|
+
isCheckBoxSelected = false;
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
visible: isCheckBoxVisible
|
|
667
|
+
})
|
|
668
|
+
]
|
|
669
|
+
});
|
|
670
|
+
const sTitle = oResourceBundleCore.getText("C_COMMON_OBJECT_PAGE_DELETE");
|
|
671
|
+
const fnConfirm = function() {
|
|
672
|
+
bDialogConfirmed = true;
|
|
673
|
+
BusyLocker.lock(that.oLockObject);
|
|
674
|
+
const aContexts = aDeletableContexts;
|
|
675
|
+
let onBeforeDeletePromise;
|
|
676
|
+
if (mParameters.beforeDeleteCallBack) {
|
|
677
|
+
onBeforeDeletePromise = mParameters.beforeDeleteCallBack({ contexts: aContexts });
|
|
678
|
+
} else {
|
|
679
|
+
onBeforeDeletePromise = Promise.resolve();
|
|
680
|
+
}
|
|
681
|
+
return onBeforeDeletePromise
|
|
682
|
+
.then(that.findActiveDraftRootContexts.bind(that, aContexts, mParameters.bFindActiveContexts))
|
|
683
|
+
.then(function(activeContexts: any) {
|
|
684
|
+
//make sure to fetch the active contexts before deleting the drafts
|
|
685
|
+
return Promise.all(
|
|
686
|
+
aContexts.map(function(oContext: any) {
|
|
687
|
+
//delete the draft
|
|
688
|
+
return draft.deleteDraft(oContext);
|
|
689
|
+
})
|
|
690
|
+
)
|
|
691
|
+
.catch(function(oError: any) {
|
|
692
|
+
return messageHandler.showMessages().then(function() {
|
|
693
|
+
// re-throw error to enforce rejecting the general promise
|
|
694
|
+
throw oError;
|
|
695
|
+
});
|
|
696
|
+
})
|
|
697
|
+
.then(function() {
|
|
698
|
+
const checkBox = {
|
|
699
|
+
"isCheckBoxVisible": isCheckBoxVisible,
|
|
700
|
+
"isCheckBoxSelected": isCheckBoxSelected
|
|
701
|
+
};
|
|
702
|
+
if (activeContexts && activeContexts.length) {
|
|
703
|
+
return Promise.all(
|
|
704
|
+
activeContexts.map(function(oContext: any) {
|
|
705
|
+
return oContext.delete();
|
|
706
|
+
})
|
|
707
|
+
).then(function() {
|
|
708
|
+
that.afterDeleteProcess(mParameters, checkBox, aContexts, oResourceBundle);
|
|
709
|
+
return messageHandler.showMessageDialog().then(fnResolve);
|
|
710
|
+
});
|
|
711
|
+
} else {
|
|
712
|
+
that.afterDeleteProcess(mParameters, checkBox, aContexts, oResourceBundle);
|
|
713
|
+
return messageHandler.showMessageDialog().then(fnResolve);
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
})
|
|
717
|
+
.catch(function() {
|
|
718
|
+
fnReject();
|
|
719
|
+
})
|
|
720
|
+
.finally(function() {
|
|
721
|
+
BusyLocker.unlock(that.oLockObject);
|
|
722
|
+
});
|
|
723
|
+
};
|
|
724
|
+
const oDialog = new Dialog({
|
|
725
|
+
title: sTitle,
|
|
726
|
+
state: "Warning",
|
|
727
|
+
content: [oContent],
|
|
728
|
+
ariaLabelledBy: oNonDeletableMessageTextControl.getVisible()
|
|
729
|
+
? [oNonDeletableMessageTextControl, oDeleteMessageTextControl]
|
|
730
|
+
: oDeleteMessageTextControl,
|
|
731
|
+
beginButton: new Button({
|
|
732
|
+
text: oResourceBundleCore.getText("C_COMMON_OBJECT_PAGE_DELETE"),
|
|
733
|
+
type: "Emphasized",
|
|
734
|
+
press: function() {
|
|
735
|
+
oDialog.close();
|
|
736
|
+
return fnConfirm();
|
|
737
|
+
}
|
|
738
|
+
}),
|
|
739
|
+
endButton: new Button({
|
|
740
|
+
text: CommonUtils.getTranslatedText("C_COMMON_OBJECT_PAGE_CANCEL", oResourceBundle),
|
|
741
|
+
press: function() {
|
|
742
|
+
oDialog.close();
|
|
743
|
+
}
|
|
744
|
+
}),
|
|
745
|
+
afterClose: function() {
|
|
746
|
+
oDialog.destroy();
|
|
747
|
+
// if dialog is closed unconfirmed (e.g. via "Cancel" or Escape button), ensure to reject promise
|
|
748
|
+
if (!bDialogConfirmed) {
|
|
749
|
+
fnReject();
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
} as any);
|
|
753
|
+
if (mParameters.noDialog) {
|
|
754
|
+
return fnConfirm();
|
|
755
|
+
} else {
|
|
756
|
+
oDialog.addStyleClass("sapUiContentPadding");
|
|
757
|
+
oDialog.open();
|
|
758
|
+
}
|
|
759
|
+
})
|
|
760
|
+
.finally(function() {
|
|
761
|
+
BusyLocker.unlock(that.oLockObject);
|
|
762
|
+
})
|
|
763
|
+
.catch(function() {
|
|
764
|
+
Log.warning("Couldn't get Programming model");
|
|
765
|
+
fnReject();
|
|
766
|
+
});
|
|
767
|
+
return new Promise(function(resolve: (value: any) => void, reject: (reason?: any) => void) {
|
|
768
|
+
fnReject = reject;
|
|
769
|
+
fnResolve = resolve;
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Edits a document.
|
|
774
|
+
*
|
|
775
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
776
|
+
* @static
|
|
777
|
+
* @param {sap.ui.model.odata.v4.Context} oContext Context of the active document
|
|
778
|
+
* @param {boolean} bPrepareOnEdit Also call the 'prepare' action for draft-based documents
|
|
779
|
+
* @param {object} oView Object of current view
|
|
780
|
+
* @param messageHandler
|
|
781
|
+
* @returns {Promise} Promise resolves with the new draft context in case of draft programming model
|
|
782
|
+
* @ui5-restricted
|
|
783
|
+
* @final
|
|
784
|
+
*/
|
|
785
|
+
editDocument(oContext: any, bPrepareOnEdit: boolean, oView: object, messageHandler: any) {
|
|
786
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
787
|
+
const that = this;
|
|
788
|
+
const sProgrammingModel = this.getProgrammingModel(oContext);
|
|
789
|
+
let oEditPromise;
|
|
790
|
+
if (!oContext) {
|
|
791
|
+
return Promise.reject(new Error("Binding context to active document is required"));
|
|
792
|
+
}
|
|
793
|
+
this._bIsModified = false;
|
|
794
|
+
BusyLocker.lock(that.oLockObject);
|
|
795
|
+
// before triggering the edit action we'll have to remove all bound transition messages
|
|
796
|
+
messageHandler.removeTransitionMessages();
|
|
797
|
+
if (sProgrammingModel === ProgrammingModel.Draft) {
|
|
798
|
+
oEditPromise = draft.createDraftFromActiveDocument(oContext, this._getAppComponent(), {
|
|
799
|
+
bPreserveChanges: true,
|
|
800
|
+
bPrepareOnEdit: bPrepareOnEdit,
|
|
801
|
+
oView: oView
|
|
802
|
+
} as any);
|
|
803
|
+
} else if (sProgrammingModel === ProgrammingModel.Sticky) {
|
|
804
|
+
oEditPromise = sticky.editDocumentInStickySession(oContext);
|
|
805
|
+
} else {
|
|
806
|
+
BusyLocker.unlock(that.oLockObject);
|
|
807
|
+
return Promise.reject(new Error("Edit is only allowed for draft or sticky session supported services"));
|
|
808
|
+
}
|
|
809
|
+
return oEditPromise
|
|
810
|
+
.then(function(oNewContext: any) {
|
|
811
|
+
that._bCreateMode = false;
|
|
812
|
+
return messageHandler.showMessageDialog().then(function() {
|
|
813
|
+
return oNewContext;
|
|
814
|
+
});
|
|
815
|
+
})
|
|
816
|
+
.catch(function(err: any) {
|
|
817
|
+
return messageHandler.showMessages().then(function() {
|
|
818
|
+
return Promise.reject(err);
|
|
819
|
+
});
|
|
820
|
+
})
|
|
821
|
+
.finally(function() {
|
|
822
|
+
BusyLocker.unlock(that.oLockObject);
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Cancel 'edit' mode of a document.
|
|
827
|
+
*
|
|
828
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
829
|
+
* @static
|
|
830
|
+
* @param {sap.ui.model.odata.v4.Context} oContext Context of the document to be canceled or deleted
|
|
831
|
+
* @param {object} [mInParameters] Optional, can contain the following attributes:
|
|
832
|
+
* @param {sap.m.Button} mInParameters.cancelButton Cancel Button of the discard popover (mandatory for now)
|
|
833
|
+
* @param {boolean} mInParameters.skipDiscardPopover Optional, supresses the discard popover incase of draft applications while navigating out of OP
|
|
834
|
+
* @param oResourceBundle
|
|
835
|
+
* @param messageHandler
|
|
836
|
+
* @returns {Promise} Promise resolves with ???
|
|
837
|
+
* @ui5-restricted
|
|
838
|
+
* @final
|
|
839
|
+
*/
|
|
840
|
+
cancelDocument(
|
|
841
|
+
oContext: any,
|
|
842
|
+
mInParameters: { cancelButton: any; skipDiscardPopover: boolean } | undefined,
|
|
843
|
+
oResourceBundle: any,
|
|
844
|
+
messageHandler: any
|
|
845
|
+
) {
|
|
846
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
847
|
+
const that = this;
|
|
848
|
+
let sProgrammingModel: ProgrammingModelType;
|
|
849
|
+
//context must always be passed - mandatory parameter
|
|
850
|
+
if (!oContext) {
|
|
851
|
+
return Promise.reject("No context exists. Pass a meaningful context");
|
|
852
|
+
}
|
|
853
|
+
BusyLocker.lock(that.oLockObject);
|
|
854
|
+
const mParameters = getParameters(mInParameters);
|
|
855
|
+
const oParamsContext = oContext,
|
|
856
|
+
oCancelButton = mParameters.cancelButton,
|
|
857
|
+
oModel = oParamsContext.getModel();
|
|
858
|
+
let onBeforeCancelPromise, sCanonicalPath: string;
|
|
859
|
+
return Promise.resolve(this.getProgrammingModel(oContext))
|
|
860
|
+
.then(function(sPModel: any) {
|
|
861
|
+
sProgrammingModel = sPModel;
|
|
862
|
+
if (sPModel === ProgrammingModel.Draft) {
|
|
863
|
+
const draftDataContext = oModel.bindContext(oParamsContext.getPath() + "/DraftAdministrativeData").getBoundContext();
|
|
864
|
+
if (!that._bIsModified) {
|
|
865
|
+
return draftDataContext.requestObject().then(function(draftAdminData: any) {
|
|
866
|
+
if (draftAdminData) {
|
|
867
|
+
that._bIsModified = !(draftAdminData.CreationDateTime === draftAdminData.LastChangeDateTime);
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
})
|
|
873
|
+
.then(function() {
|
|
874
|
+
if (!mParameters.skipDiscardPopover) {
|
|
875
|
+
return that._showDiscardPopover(oCancelButton, that._bIsModified, oResourceBundle);
|
|
876
|
+
} else {
|
|
877
|
+
return Promise.resolve();
|
|
878
|
+
}
|
|
879
|
+
})
|
|
880
|
+
.then(function() {
|
|
881
|
+
if (mParameters.beforeCancelCallBack) {
|
|
882
|
+
onBeforeCancelPromise = mParameters.beforeCancelCallBack({ context: oContext });
|
|
883
|
+
} else {
|
|
884
|
+
onBeforeCancelPromise = Promise.resolve();
|
|
885
|
+
}
|
|
886
|
+
return onBeforeCancelPromise;
|
|
887
|
+
})
|
|
888
|
+
.then(function() {
|
|
889
|
+
// eslint-disable-next-line default-case
|
|
890
|
+
switch (sProgrammingModel) {
|
|
891
|
+
case ProgrammingModel.Draft:
|
|
892
|
+
return oParamsContext.requestObject("HasActiveEntity").then(function(bHasActiveEntity: any) {
|
|
893
|
+
let oDeletePromise;
|
|
894
|
+
if (!bHasActiveEntity) {
|
|
895
|
+
if (oParamsContext && oParamsContext.hasPendingChanges()) {
|
|
896
|
+
oParamsContext.getBinding().resetChanges();
|
|
897
|
+
}
|
|
898
|
+
oDeletePromise = draft.deleteDraft(oParamsContext);
|
|
899
|
+
return oDeletePromise;
|
|
900
|
+
} else {
|
|
901
|
+
let oActiveContext = oModel.bindContext(oParamsContext.getPath() + "/SiblingEntity").getBoundContext();
|
|
902
|
+
return oActiveContext
|
|
903
|
+
.requestCanonicalPath()
|
|
904
|
+
.then(
|
|
905
|
+
function(sPath: any) {
|
|
906
|
+
sCanonicalPath = sPath;
|
|
907
|
+
if (oParamsContext && oParamsContext.hasPendingChanges()) {
|
|
908
|
+
oParamsContext.getBinding().resetChanges();
|
|
909
|
+
}
|
|
910
|
+
oDeletePromise = draft.deleteDraft(oParamsContext);
|
|
911
|
+
return oDeletePromise;
|
|
912
|
+
},
|
|
913
|
+
function() {
|
|
914
|
+
draft.deleteDraft(oParamsContext);
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
)
|
|
918
|
+
.then(function() {
|
|
919
|
+
//oParamsContext.delete() in the previous promise doesnt return anything upon success.
|
|
920
|
+
if (!sCanonicalPath) {
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
if (oActiveContext.getPath() !== sCanonicalPath) {
|
|
924
|
+
// the active context is using the sibling entity - this path is not accessible anymore as we deleted the draft
|
|
925
|
+
// document - therefore we need to create a new context with the canonical path
|
|
926
|
+
oActiveContext = oModel.bindContext(sCanonicalPath).getBoundContext();
|
|
927
|
+
}
|
|
928
|
+
return oActiveContext;
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
case ProgrammingModel.Sticky:
|
|
933
|
+
return sticky.discardDocument(oContext).then(function(oContext: any) {
|
|
934
|
+
if (oContext) {
|
|
935
|
+
if (oContext.hasPendingChanges()) {
|
|
936
|
+
oContext.getBinding().resetChanges();
|
|
937
|
+
}
|
|
938
|
+
if (!that._bCreateMode) {
|
|
939
|
+
oContext.refresh();
|
|
940
|
+
return oContext;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return false;
|
|
944
|
+
});
|
|
945
|
+
default:
|
|
946
|
+
return Promise.reject("Cancel document only allowed for draft or sticky session supported services");
|
|
947
|
+
}
|
|
948
|
+
})
|
|
949
|
+
.then(function(context: any) {
|
|
950
|
+
that._bIsModified = false;
|
|
951
|
+
// remove existing bound transition messages
|
|
952
|
+
messageHandler.removeTransitionMessages();
|
|
953
|
+
// show unbound messages
|
|
954
|
+
return messageHandler.showMessages().then(function() {
|
|
955
|
+
return context;
|
|
956
|
+
});
|
|
957
|
+
})
|
|
958
|
+
.catch(function(err: any) {
|
|
959
|
+
return messageHandler.showMessages().then(function() {
|
|
960
|
+
return Promise.reject(err);
|
|
961
|
+
});
|
|
962
|
+
})
|
|
963
|
+
.finally(function() {
|
|
964
|
+
BusyLocker.unlock(that.oLockObject);
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Saves the document.
|
|
969
|
+
*
|
|
970
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
971
|
+
* @static
|
|
972
|
+
* @param {sap.ui.model.odata.v4.Context} oContext Context of the document to be saved
|
|
973
|
+
* @param oResourceBundle
|
|
974
|
+
* @param bExecuteSideEffectsOnError
|
|
975
|
+
* @param aBindings
|
|
976
|
+
* @param messageHandler
|
|
977
|
+
* @returns {Promise} Promise resolves with ???
|
|
978
|
+
* @ui5-restricted
|
|
979
|
+
* @final
|
|
980
|
+
*/
|
|
981
|
+
saveDocument(oContext: any, oResourceBundle: any, bExecuteSideEffectsOnError: any, aBindings: any, messageHandler: any) {
|
|
982
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
983
|
+
const that = this;
|
|
984
|
+
const sProgrammingModel = this.getProgrammingModel(oContext);
|
|
985
|
+
let oSavePromise;
|
|
986
|
+
if (!oContext) {
|
|
987
|
+
return Promise.reject(new Error("Binding context to draft document is required"));
|
|
988
|
+
}
|
|
989
|
+
// in case of saving / activating the bound transition messages shall be removed before the PATCH/POST
|
|
990
|
+
// is sent to the backend
|
|
991
|
+
messageHandler.removeTransitionMessages();
|
|
992
|
+
BusyLocker.lock(that.oLockObject);
|
|
993
|
+
if (sProgrammingModel === ProgrammingModel.Draft) {
|
|
994
|
+
oSavePromise = draft.activateDocument(oContext, this._getAppComponent(), {});
|
|
995
|
+
} else if (sProgrammingModel === ProgrammingModel.Sticky) {
|
|
996
|
+
oSavePromise = sticky.activateDocument(oContext);
|
|
997
|
+
} else {
|
|
998
|
+
BusyLocker.unlock(that.oLockObject);
|
|
999
|
+
return Promise.reject(new Error("Save is only allowed for draft or sticky session supported services"));
|
|
1000
|
+
}
|
|
1001
|
+
return oSavePromise
|
|
1002
|
+
.then(function(oActiveDocument: any) {
|
|
1003
|
+
const bNewObject =
|
|
1004
|
+
that.sProgrammingModel === ProgrammingModel.Sticky ? that._bCreateMode : !oContext.getObject().HasActiveEntity;
|
|
1005
|
+
MessageToast.show(
|
|
1006
|
+
bNewObject
|
|
1007
|
+
? CommonUtils.getTranslatedText("C_TRANSACTION_HELPER_OBJECT_CREATED", oResourceBundle)
|
|
1008
|
+
: CommonUtils.getTranslatedText("C_TRANSACTION_HELPER_OBJECT_SAVED", oResourceBundle)
|
|
1009
|
+
);
|
|
1010
|
+
that._bIsModified = false;
|
|
1011
|
+
return messageHandler.showMessageDialog().then(function() {
|
|
1012
|
+
return oActiveDocument;
|
|
1013
|
+
});
|
|
1014
|
+
})
|
|
1015
|
+
.catch(function(err: any) {
|
|
1016
|
+
if (aBindings && aBindings.length > 0) {
|
|
1017
|
+
/* The sideEffects are executed only for table items in transient state */
|
|
1018
|
+
aBindings.forEach(function(oListBinding: any) {
|
|
1019
|
+
if (!CommonUtils.hasTransientContext(oListBinding) && bExecuteSideEffectsOnError) {
|
|
1020
|
+
const oAppComponent = that._getAppComponent();
|
|
1021
|
+
oAppComponent.getSideEffectsService().requestSideEffectsForNavigationProperty(oListBinding.getPath(), oContext);
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
return messageHandler.showMessages().then(function() {
|
|
1026
|
+
return Promise.reject(err);
|
|
1027
|
+
});
|
|
1028
|
+
})
|
|
1029
|
+
.finally(function() {
|
|
1030
|
+
BusyLocker.unlock(that.oLockObject);
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Calls a bound or unbound action.
|
|
1035
|
+
*
|
|
1036
|
+
* @function
|
|
1037
|
+
* @static
|
|
1038
|
+
* @name sap.fe.core.TransactionHelper.callAction
|
|
1039
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
1040
|
+
* @param {string} sActionName The name of the action to be called
|
|
1041
|
+
* @param {map} [mParameters] Contains the following attributes:
|
|
1042
|
+
* @param {sap.ui.model.odata.v4.Context} [mParameters.contexts] Mandatory for a bound action: Either one context or an array with contexts for which the action is to be called
|
|
1043
|
+
* @param {sap.ui.model.odata.v4.ODataModel} [mParameters.model] Mandatory for an unbound action: An instance of an OData V4 model
|
|
1044
|
+
* @param {string} [mParameters.invocationGrouping] Mode how actions are to be called: 'ChangeSet' to put all action calls into one changeset, 'Isolated' to put them into separate changesets
|
|
1045
|
+
* @param {string} [mParameters.label] A human-readable label for the action
|
|
1046
|
+
* @param {boolean} [mParameters.bGetBoundContext] If specified, the action promise returns the bound context
|
|
1047
|
+
* @param {object} oView Contains the object of the current view
|
|
1048
|
+
* @param messageHandler
|
|
1049
|
+
* @returns {Promise} Promise resolves with an array of response objects (TODO: to be changed)
|
|
1050
|
+
* @ui5-restricted
|
|
1051
|
+
* @final
|
|
1052
|
+
**/
|
|
1053
|
+
callAction(sActionName: string, mParameters: any, oView: View | null, messageHandler: any) {
|
|
1054
|
+
mParameters = getParameters(mParameters);
|
|
1055
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1056
|
+
const that = this;
|
|
1057
|
+
let oContext, oModel: any, oPromise;
|
|
1058
|
+
const mBindingParameters = mParameters.bindingParameters;
|
|
1059
|
+
if (!sActionName) {
|
|
1060
|
+
return Promise.reject("Provide name of action to be executed");
|
|
1061
|
+
}
|
|
1062
|
+
// action imports are not directly obtained from the metaModel by it is present inside the entityContainer
|
|
1063
|
+
// and the acions it refers to present outside the entitycontainer, hence to obtain kind of the action
|
|
1064
|
+
// split() on its name was required
|
|
1065
|
+
const sName = sActionName.split("/")[1];
|
|
1066
|
+
sActionName = sName || sActionName;
|
|
1067
|
+
oContext = sName ? undefined : mParameters.contexts;
|
|
1068
|
+
//checking whether the context is an array with more than 0 length or not an array(create action)
|
|
1069
|
+
if (oContext && ((Array.isArray(oContext) && oContext.length) || !Array.isArray(oContext))) {
|
|
1070
|
+
oContext = Array.isArray(oContext) ? oContext[0] : oContext;
|
|
1071
|
+
oModel = oContext.getModel();
|
|
1072
|
+
}
|
|
1073
|
+
if (mParameters.model) {
|
|
1074
|
+
oModel = mParameters.model;
|
|
1075
|
+
}
|
|
1076
|
+
if (!oModel) {
|
|
1077
|
+
return Promise.reject("Pass a context for a bound action or pass the model for an unbound action");
|
|
1078
|
+
}
|
|
1079
|
+
// get the binding parameters $select and $expand for the side effect on this action
|
|
1080
|
+
// also gather additional property paths to be requested such as text associations
|
|
1081
|
+
const oAppComponent = that._getAppComponent();
|
|
1082
|
+
const mSideEffectsParameters = oAppComponent.getSideEffectsService().getODataActionSideEffects(sActionName, oContext) || {};
|
|
1083
|
+
if (oContext && oModel) {
|
|
1084
|
+
oPromise = new Promise<void>(function(resolve, reject) {
|
|
1085
|
+
let oApplicableContextDialog: Dialog;
|
|
1086
|
+
const oController = {
|
|
1087
|
+
onClose: function() {
|
|
1088
|
+
// User cancels action
|
|
1089
|
+
oApplicableContextDialog.close();
|
|
1090
|
+
resolve();
|
|
1091
|
+
},
|
|
1092
|
+
onContinue: function() {
|
|
1093
|
+
// Users continues the action with the bound contexts
|
|
1094
|
+
oApplicableContextDialog.close();
|
|
1095
|
+
resolve(mParameters.applicableContext);
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
const fnOpenAndFillDialog = function() {
|
|
1099
|
+
let oDialogContent;
|
|
1100
|
+
const nNotApplicable = mParameters.notApplicableContext.length,
|
|
1101
|
+
aNotApplicableItems = [];
|
|
1102
|
+
for (let i = 0; i < mParameters.notApplicableContext.length; i++) {
|
|
1103
|
+
oDialogContent = mParameters.notApplicableContext[i].getObject();
|
|
1104
|
+
aNotApplicableItems.push(oDialogContent);
|
|
1105
|
+
}
|
|
1106
|
+
const oNotApplicableItemsModel = new JSONModel(aNotApplicableItems);
|
|
1107
|
+
const oTotals = new JSONModel({ total: nNotApplicable, label: mParameters.label });
|
|
1108
|
+
oApplicableContextDialog.setModel(oNotApplicableItemsModel, "notApplicable");
|
|
1109
|
+
oApplicableContextDialog.setModel(oTotals, "totals");
|
|
1110
|
+
oApplicableContextDialog.open();
|
|
1111
|
+
};
|
|
1112
|
+
if (mParameters.notApplicableContext && mParameters.notApplicableContext.length >= 1) {
|
|
1113
|
+
// Show the contexts that are not applicable and will not therefore be processed
|
|
1114
|
+
const sFragmentName = "sap.fe.core.controls.ActionPartial";
|
|
1115
|
+
const oDialogFragment = XMLTemplateProcessor.loadTemplate(sFragmentName, "fragment");
|
|
1116
|
+
const oMetaModel = oModel.getMetaModel();
|
|
1117
|
+
const sCanonicalPath = mParameters.contexts[0].getCanonicalPath();
|
|
1118
|
+
const sEntitySet = sCanonicalPath.substr(0, sCanonicalPath.indexOf("(")) + "/";
|
|
1119
|
+
const oDialogLabelModel = new JSONModel({
|
|
1120
|
+
title: mParameters.label
|
|
1121
|
+
});
|
|
1122
|
+
Promise.resolve(
|
|
1123
|
+
XMLPreprocessor.process(
|
|
1124
|
+
oDialogFragment,
|
|
1125
|
+
{ name: sFragmentName },
|
|
1126
|
+
{
|
|
1127
|
+
bindingContexts: {
|
|
1128
|
+
entityType: oMetaModel.createBindingContext(sEntitySet),
|
|
1129
|
+
label: oDialogLabelModel.createBindingContext("/")
|
|
1130
|
+
},
|
|
1131
|
+
models: {
|
|
1132
|
+
entityType: oMetaModel,
|
|
1133
|
+
metaModel: oMetaModel,
|
|
1134
|
+
label: oDialogLabelModel
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
)
|
|
1138
|
+
)
|
|
1139
|
+
.then(function(oFragment: any) {
|
|
1140
|
+
return Fragment.load({ definition: oFragment, controller: oController });
|
|
1141
|
+
})
|
|
1142
|
+
.then(function(oPopover: any) {
|
|
1143
|
+
oApplicableContextDialog = oPopover;
|
|
1144
|
+
mParameters.parentControl.addDependent(oPopover);
|
|
1145
|
+
fnOpenAndFillDialog();
|
|
1146
|
+
})
|
|
1147
|
+
.catch(reject);
|
|
1148
|
+
} else {
|
|
1149
|
+
resolve(mParameters.contexts);
|
|
1150
|
+
}
|
|
1151
|
+
}).then(function(contextToProcess: any) {
|
|
1152
|
+
if (contextToProcess) {
|
|
1153
|
+
return operations.callBoundAction(sActionName, contextToProcess, oModel, oAppComponent, {
|
|
1154
|
+
invocationGrouping: mParameters.invocationGrouping,
|
|
1155
|
+
label: mParameters.label,
|
|
1156
|
+
showActionParameterDialog: true,
|
|
1157
|
+
mBindingParameters: mBindingParameters,
|
|
1158
|
+
entitySetName: mParameters.entitySetName,
|
|
1159
|
+
additionalSideEffect: mSideEffectsParameters,
|
|
1160
|
+
onSubmitted: function() {
|
|
1161
|
+
messageHandler.removeTransitionMessages();
|
|
1162
|
+
BusyLocker.lock(that.oLockObject);
|
|
1163
|
+
},
|
|
1164
|
+
onResponse: function() {
|
|
1165
|
+
BusyLocker.unlock(that.oLockObject);
|
|
1166
|
+
},
|
|
1167
|
+
parentControl: mParameters.parentControl,
|
|
1168
|
+
internalModelContext: mParameters.internalModelContext,
|
|
1169
|
+
operationAvailableMap: mParameters.operationAvailableMap,
|
|
1170
|
+
bIsCreateAction: mParameters.bIsCreateAction,
|
|
1171
|
+
bGetBoundContext: mParameters.bGetBoundContext,
|
|
1172
|
+
bObjectPage: mParameters.bObjectPage,
|
|
1173
|
+
messageHandler: messageHandler,
|
|
1174
|
+
defaultValuesExtensionFunction: mParameters.defaultValuesExtensionFunction
|
|
1175
|
+
});
|
|
1176
|
+
} else {
|
|
1177
|
+
return null;
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
1180
|
+
} else {
|
|
1181
|
+
// TODO: confirm if action import needs side effects.
|
|
1182
|
+
oPromise = operations.callActionImport(sActionName, oModel, oAppComponent, {
|
|
1183
|
+
label: mParameters.label,
|
|
1184
|
+
showActionParameterDialog: true,
|
|
1185
|
+
bindingParameters: mBindingParameters,
|
|
1186
|
+
entitySetName: mParameters.entitySetName,
|
|
1187
|
+
onSubmitted: function() {
|
|
1188
|
+
BusyLocker.lock(that.oLockObject);
|
|
1189
|
+
},
|
|
1190
|
+
onResponse: function() {
|
|
1191
|
+
BusyLocker.unlock(that.oLockObject);
|
|
1192
|
+
},
|
|
1193
|
+
parentControl: mParameters.parentControl,
|
|
1194
|
+
internalModelContext: mParameters.internalModelContext,
|
|
1195
|
+
operationAvailableMap: mParameters.operationAvailableMap,
|
|
1196
|
+
messageHandler: messageHandler,
|
|
1197
|
+
bObjectPage: mParameters.bObjectPage
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
return oPromise
|
|
1201
|
+
.then(function(oResult: any) {
|
|
1202
|
+
// Succeeded
|
|
1203
|
+
return that._handleActionResponse(messageHandler, mParameters, sActionName).then(function() {
|
|
1204
|
+
return oResult;
|
|
1205
|
+
});
|
|
1206
|
+
})
|
|
1207
|
+
.catch(function(err: any) {
|
|
1208
|
+
return that._handleActionResponse(messageHandler, mParameters, sActionName).then(function() {
|
|
1209
|
+
return Promise.reject(err);
|
|
1210
|
+
});
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Handles messages for action call.
|
|
1215
|
+
*
|
|
1216
|
+
* @function
|
|
1217
|
+
* @name sap.fe.core.TransactionHelper#_handleActionResponse
|
|
1218
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
1219
|
+
* @param messageHandler
|
|
1220
|
+
* @param {object} mParameters Parameters to be considered for the action.
|
|
1221
|
+
* @param {string} sActionName The name of the action to be called
|
|
1222
|
+
* @returns {Promise} Promise after message dialog is opened if required.
|
|
1223
|
+
* @ui5-restricted
|
|
1224
|
+
* @final
|
|
1225
|
+
*/
|
|
1226
|
+
_handleActionResponse(messageHandler: any, mParameters: any, sActionName: string) {
|
|
1227
|
+
const aTransientMessages = messageHandling.getMessages(true, true);
|
|
1228
|
+
if (aTransientMessages.length > 0 && mParameters && mParameters.internalModelContext) {
|
|
1229
|
+
mParameters.internalModelContext.setProperty("sActionName", mParameters.label ? mParameters.label : sActionName);
|
|
1230
|
+
}
|
|
1231
|
+
return messageHandler.showMessages();
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Handles validation errors for the 'discard' action.
|
|
1235
|
+
*
|
|
1236
|
+
* @function
|
|
1237
|
+
* @name sap.fe.core.TransactionHelper#handleValidationError
|
|
1238
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
1239
|
+
* @static
|
|
1240
|
+
* @ui5-restricted
|
|
1241
|
+
* @final
|
|
1242
|
+
*/
|
|
1243
|
+
handleValidationError() {
|
|
1244
|
+
const oMessageManager = (sap.ui.getCore() as any).getMessageManager(),
|
|
1245
|
+
errorToRemove = oMessageManager
|
|
1246
|
+
.getMessageModel()
|
|
1247
|
+
.getData()
|
|
1248
|
+
.filter(function(error: any) {
|
|
1249
|
+
// only needs to handle validation messages, technical and persistent errors needs not to be checked here.
|
|
1250
|
+
if (error.validation) {
|
|
1251
|
+
return error;
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
1254
|
+
oMessageManager.removeMessages(errorToRemove);
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Shows a popover if it needs to be shown.
|
|
1258
|
+
* TODO: Popover is shown if user has modified any data.
|
|
1259
|
+
* TODO: Popover is shown if there's a difference from draft admin data.
|
|
1260
|
+
* @static
|
|
1261
|
+
* @name sap.fe.core.TransactionHelper._showDiscardPopover
|
|
1262
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
1263
|
+
* @param {sap.ui.core.Control} oCancelButton The control which will open the popover
|
|
1264
|
+
* @param bIsModified
|
|
1265
|
+
* @param oResourceBundle
|
|
1266
|
+
* @returns {Promise} Promise resolves if user confirms discard, rejects if otherwise, rejects if no control passed to open popover
|
|
1267
|
+
* @ui5-restricted
|
|
1268
|
+
* @final
|
|
1269
|
+
*/
|
|
1270
|
+
_showDiscardPopover(oCancelButton: any, bIsModified: any, oResourceBundle: any) {
|
|
1271
|
+
// TODO: Implement this popover as a fragment as in v2??
|
|
1272
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1273
|
+
const that = this;
|
|
1274
|
+
that._bContinueDiscard = false;
|
|
1275
|
+
// to be implemented
|
|
1276
|
+
return new Promise<void>(function(resolve, reject) {
|
|
1277
|
+
if (!oCancelButton) {
|
|
1278
|
+
reject("Cancel button not found");
|
|
1279
|
+
}
|
|
1280
|
+
//Show popover only when data is changed.
|
|
1281
|
+
if (bIsModified) {
|
|
1282
|
+
const fnOnAfterDiscard = function() {
|
|
1283
|
+
oCancelButton.setEnabled(true);
|
|
1284
|
+
if (that._bContinueDiscard) {
|
|
1285
|
+
resolve();
|
|
1286
|
+
} else {
|
|
1287
|
+
reject("Discard operation was rejected. Document has not been discarded");
|
|
1288
|
+
}
|
|
1289
|
+
that._oPopover.detachAfterClose(fnOnAfterDiscard);
|
|
1290
|
+
};
|
|
1291
|
+
if (!that._oPopover) {
|
|
1292
|
+
const oText = new Text({
|
|
1293
|
+
//This text is the same as LR v2.
|
|
1294
|
+
//TODO: Display message provided by app developer???
|
|
1295
|
+
text: CommonUtils.getTranslatedText("C_TRANSACTION_HELPER_DRAFT_DISCARD_MESSAGE", oResourceBundle)
|
|
1296
|
+
}),
|
|
1297
|
+
oButton = new Button({
|
|
1298
|
+
text: CommonUtils.getTranslatedText("C_TRANSACTION_HELPER_DRAFT_DISCARD_BUTTON", oResourceBundle),
|
|
1299
|
+
width: "100%",
|
|
1300
|
+
press: function() {
|
|
1301
|
+
that.handleValidationError();
|
|
1302
|
+
that._bContinueDiscard = true;
|
|
1303
|
+
that._oPopover.close();
|
|
1304
|
+
},
|
|
1305
|
+
ariaLabelledBy: oText
|
|
1306
|
+
} as any);
|
|
1307
|
+
that._oPopover = new Popover({
|
|
1308
|
+
showHeader: false,
|
|
1309
|
+
placement: "Top",
|
|
1310
|
+
content: [
|
|
1311
|
+
new VBox({
|
|
1312
|
+
items: [oText, oButton]
|
|
1313
|
+
})
|
|
1314
|
+
],
|
|
1315
|
+
beforeOpen: function() {
|
|
1316
|
+
// make sure to NOT trigger multiple cancel flows
|
|
1317
|
+
oCancelButton.setEnabled(false);
|
|
1318
|
+
that._oPopover.setInitialFocus(oButton);
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
that._oPopover.addStyleClass("sapUiContentPadding");
|
|
1322
|
+
}
|
|
1323
|
+
that._oPopover.attachAfterClose(fnOnAfterDiscard);
|
|
1324
|
+
that._oPopover.openBy(oCancelButton, false);
|
|
1325
|
+
} else {
|
|
1326
|
+
that.handleValidationError();
|
|
1327
|
+
resolve();
|
|
1328
|
+
}
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
/**
|
|
1332
|
+
* Sets the document to modified state on patch event.
|
|
1333
|
+
*
|
|
1334
|
+
* @function
|
|
1335
|
+
* @static
|
|
1336
|
+
* @name sap.fe.core.TransactionHelper.handleDocumentModifications
|
|
1337
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
1338
|
+
* @ui5-restricted
|
|
1339
|
+
* @final
|
|
1340
|
+
*/
|
|
1341
|
+
handleDocumentModifications() {
|
|
1342
|
+
this._bIsModified = true;
|
|
1343
|
+
}
|
|
1344
|
+
/**
|
|
1345
|
+
* Retrieves the owner component.
|
|
1346
|
+
*
|
|
1347
|
+
* @function
|
|
1348
|
+
* @static
|
|
1349
|
+
* @private
|
|
1350
|
+
* @name sap.fe.core.TransactionHelper._getOwnerComponent
|
|
1351
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
1352
|
+
* @returns {sap.fe.core.AppComponent} The app component
|
|
1353
|
+
* @ui5-restricted
|
|
1354
|
+
* @final
|
|
1355
|
+
**/
|
|
1356
|
+
_getAppComponent() {
|
|
1357
|
+
return this._oAppComponent;
|
|
1358
|
+
}
|
|
1359
|
+
_launchDialogWithKeyFields(
|
|
1360
|
+
oListBinding: any,
|
|
1361
|
+
oTransientListBinding: any,
|
|
1362
|
+
oTransientContext: any,
|
|
1363
|
+
mFields: any,
|
|
1364
|
+
oModel: any,
|
|
1365
|
+
mParameters: any,
|
|
1366
|
+
messageHandler: any
|
|
1367
|
+
) {
|
|
1368
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1369
|
+
const that = this;
|
|
1370
|
+
let oDialog: Dialog;
|
|
1371
|
+
const oParentControl = mParameters.parentControl,
|
|
1372
|
+
bSuccess = false;
|
|
1373
|
+
return new Promise(function(resolve: (value: any) => void, reject: (reason?: any) => void) {
|
|
1374
|
+
const sFragmentName = "sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog";
|
|
1375
|
+
const oFragment = XMLTemplateProcessor.loadTemplate(sFragmentName, "fragment"),
|
|
1376
|
+
oResourceBundle = oParentControl.getController().oResourceBundle,
|
|
1377
|
+
oMetaModel = oModel.getMetaModel(),
|
|
1378
|
+
aImmutableFields: any[] = [],
|
|
1379
|
+
oAppComponent = that._getAppComponent(),
|
|
1380
|
+
sPath = oListBinding.isRelative() ? oListBinding.getResolvedPath() : oListBinding.getPath(),
|
|
1381
|
+
oEntitySetContext = oMetaModel.createBindingContext(sPath),
|
|
1382
|
+
sMetaPath = oMetaModel.getMetaPath(sPath);
|
|
1383
|
+
for (const i in mFields) {
|
|
1384
|
+
aImmutableFields.push(oMetaModel.createBindingContext(sMetaPath + "/" + mFields[i]));
|
|
1385
|
+
}
|
|
1386
|
+
const oImmutableCtxModel = new JSONModel(aImmutableFields);
|
|
1387
|
+
const oImmutableCtx = oImmutableCtxModel.createBindingContext("/");
|
|
1388
|
+
return Promise.resolve(
|
|
1389
|
+
XMLPreprocessor.process(
|
|
1390
|
+
oFragment,
|
|
1391
|
+
{ name: sFragmentName },
|
|
1392
|
+
{
|
|
1393
|
+
bindingContexts: {
|
|
1394
|
+
entitySet: oEntitySetContext,
|
|
1395
|
+
fields: oImmutableCtx
|
|
1396
|
+
},
|
|
1397
|
+
models: {
|
|
1398
|
+
entitySet: oEntitySetContext.getModel(),
|
|
1399
|
+
fields: oImmutableCtx.getModel(),
|
|
1400
|
+
metaModel: oMetaModel
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
)
|
|
1404
|
+
).then(function(oFragment: any) {
|
|
1405
|
+
let aFormElements: any[] = [];
|
|
1406
|
+
const mFieldValueMap: any = {};
|
|
1407
|
+
let oCreateButton: Button;
|
|
1408
|
+
const validateRequiredProperties = function() {
|
|
1409
|
+
return Promise.all(
|
|
1410
|
+
aFormElements
|
|
1411
|
+
.map(function(oFormElement: any) {
|
|
1412
|
+
return oFormElement.getFields()[0];
|
|
1413
|
+
})
|
|
1414
|
+
.filter(function(oField: any) {
|
|
1415
|
+
return oField.getRequired();
|
|
1416
|
+
})
|
|
1417
|
+
.map(function(oField: any) {
|
|
1418
|
+
const sFieldId = oField.getId();
|
|
1419
|
+
if (sFieldId in mFieldValueMap) {
|
|
1420
|
+
return Promise.resolve(mFieldValueMap[sFieldId])
|
|
1421
|
+
.then(function(vValue: any) {
|
|
1422
|
+
return vValue;
|
|
1423
|
+
})
|
|
1424
|
+
.catch(function() {
|
|
1425
|
+
return undefined;
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
return oField.getValueState() === ValueState.Error ? undefined : oField.getValue();
|
|
1429
|
+
})
|
|
1430
|
+
)
|
|
1431
|
+
.then(function(aResults: any[]) {
|
|
1432
|
+
return aResults.every(function(vValue: any) {
|
|
1433
|
+
return vValue !== undefined && vValue !== null && vValue !== "";
|
|
1434
|
+
});
|
|
1435
|
+
})
|
|
1436
|
+
.catch(function() {
|
|
1437
|
+
return false;
|
|
1438
|
+
})
|
|
1439
|
+
.then(function(bEnabled: boolean) {
|
|
1440
|
+
oCreateButton.setEnabled(bEnabled);
|
|
1441
|
+
});
|
|
1442
|
+
};
|
|
1443
|
+
const oController = {
|
|
1444
|
+
/*
|
|
1445
|
+
fired on focus out from field or on selecting a value from the valuehelp.
|
|
1446
|
+
the create button is enabled when a value is added.
|
|
1447
|
+
liveChange is not fired when value is added from valuehelp.
|
|
1448
|
+
value validation is not done for create button enablement.
|
|
1449
|
+
*/
|
|
1450
|
+
handleChange: function(oEvent: any) {
|
|
1451
|
+
messageHandler.removeTransitionMessages();
|
|
1452
|
+
const oField = oEvent.getSource();
|
|
1453
|
+
const sFieldId = oEvent.getParameter("id");
|
|
1454
|
+
const oFieldPromise = oEvent.getParameter("promise");
|
|
1455
|
+
if (oFieldPromise) {
|
|
1456
|
+
mFieldValueMap[sFieldId] = oFieldPromise.then(function() {
|
|
1457
|
+
return oField.getValue();
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1460
|
+
validateRequiredProperties();
|
|
1461
|
+
},
|
|
1462
|
+
/*
|
|
1463
|
+
fired on key press. the create button is enabled when a value is added.
|
|
1464
|
+
liveChange is not fired when value is added from valuehelp.
|
|
1465
|
+
value validation is not done for create button enablement.
|
|
1466
|
+
*/
|
|
1467
|
+
handleLiveChange: function(oEvent: any) {
|
|
1468
|
+
const sFieldId = oEvent.getParameter("id");
|
|
1469
|
+
const vValue = oEvent.getParameter("value");
|
|
1470
|
+
mFieldValueMap[sFieldId] = vValue;
|
|
1471
|
+
validateRequiredProperties();
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
return Fragment.load({
|
|
1475
|
+
definition: oFragment,
|
|
1476
|
+
controller: oController
|
|
1477
|
+
}).then(function(oDialogContent: any) {
|
|
1478
|
+
oDialog = new Dialog({
|
|
1479
|
+
title: CommonUtils.getTranslatedText("C_TRANSACTION_HELPER_SAPFE_ACTION_CREATE", oResourceBundle),
|
|
1480
|
+
content: [oDialogContent],
|
|
1481
|
+
beginButton: {
|
|
1482
|
+
text: CommonUtils.getTranslatedText("C_TRANSACTION_HELPER_SAPFE_ACTION_CREATE_BUTTON", oResourceBundle),
|
|
1483
|
+
type: "Emphasized",
|
|
1484
|
+
press: function(oEvent: any) {
|
|
1485
|
+
const oCreateButton = oEvent.getSource();
|
|
1486
|
+
oCreateButton.setEnabled(false);
|
|
1487
|
+
BusyLocker.lock(oDialog);
|
|
1488
|
+
return Promise.all(
|
|
1489
|
+
Object.keys(mFieldValueMap).map(function(sKey: string) {
|
|
1490
|
+
return mFieldValueMap[sKey].then(function(oValue: any) {
|
|
1491
|
+
const oDialogValue: any = {};
|
|
1492
|
+
oDialogValue[sKey] = oValue;
|
|
1493
|
+
return oDialogValue;
|
|
1494
|
+
});
|
|
1495
|
+
})
|
|
1496
|
+
)
|
|
1497
|
+
.then(function(aValues: any[]) {
|
|
1498
|
+
let onBeforeCreatePromise;
|
|
1499
|
+
if (mParameters.beforeCreateCallBack) {
|
|
1500
|
+
onBeforeCreatePromise = mParameters.beforeCreateCallBack({
|
|
1501
|
+
contextPath: oListBinding && oListBinding.getPath(),
|
|
1502
|
+
createParameters: aValues
|
|
1503
|
+
});
|
|
1504
|
+
} else {
|
|
1505
|
+
onBeforeCreatePromise = Promise.resolve();
|
|
1506
|
+
}
|
|
1507
|
+
return onBeforeCreatePromise;
|
|
1508
|
+
})
|
|
1509
|
+
.then(function() {
|
|
1510
|
+
const oPromise = that.onAfterCreateCompletion(
|
|
1511
|
+
oTransientListBinding,
|
|
1512
|
+
oTransientContext,
|
|
1513
|
+
mParameters
|
|
1514
|
+
);
|
|
1515
|
+
oModel.submitBatch("submitLater");
|
|
1516
|
+
return oPromise;
|
|
1517
|
+
})
|
|
1518
|
+
.then(function(oResponse: any) {
|
|
1519
|
+
oDialog.setBindingContext(null as any);
|
|
1520
|
+
oDialog.close();
|
|
1521
|
+
resolve(oResponse);
|
|
1522
|
+
})
|
|
1523
|
+
.catch(function(oError: any) {
|
|
1524
|
+
reject(oError);
|
|
1525
|
+
})
|
|
1526
|
+
.finally(function() {
|
|
1527
|
+
BusyLocker.unlock(oDialog);
|
|
1528
|
+
oCreateButton.setEnabled(true);
|
|
1529
|
+
return messageHandler.showMessages();
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
},
|
|
1533
|
+
endButton: {
|
|
1534
|
+
text: CommonUtils.getTranslatedText("C_COMMON_ACTION_PARAMETER_DIALOG_CANCEL", oResourceBundle),
|
|
1535
|
+
press: function() {
|
|
1536
|
+
oDialog.close();
|
|
1537
|
+
}
|
|
1538
|
+
},
|
|
1539
|
+
afterClose: function() {
|
|
1540
|
+
// show footer as per UX guidelines when dialog is not open
|
|
1541
|
+
(oDialog.getBindingContext("internal") as InternalModelContext)?.setProperty("isCreateDialogOpen", false);
|
|
1542
|
+
oDialog.destroy();
|
|
1543
|
+
if (!bSuccess) {
|
|
1544
|
+
reject({
|
|
1545
|
+
bDeleteTransientContext: true
|
|
1546
|
+
});
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
} as any);
|
|
1550
|
+
aFormElements = oDialogContent
|
|
1551
|
+
.getAggregation("form")
|
|
1552
|
+
.getAggregation("formContainers")[0]
|
|
1553
|
+
.getAggregation("formElements");
|
|
1554
|
+
if (oParentControl && oParentControl.addDependent) {
|
|
1555
|
+
// if there is a parent control specified add the dialog as dependent
|
|
1556
|
+
oParentControl.addDependent(oDialog);
|
|
1557
|
+
}
|
|
1558
|
+
oCreateButton = oDialog.getBeginButton();
|
|
1559
|
+
oDialog.setBindingContext(oTransientContext);
|
|
1560
|
+
return CommonUtils.setUserDefaults(
|
|
1561
|
+
oAppComponent,
|
|
1562
|
+
aImmutableFields,
|
|
1563
|
+
oTransientContext,
|
|
1564
|
+
false,
|
|
1565
|
+
mParameters.createAction,
|
|
1566
|
+
mParameters.data
|
|
1567
|
+
)
|
|
1568
|
+
.then(function() {
|
|
1569
|
+
validateRequiredProperties();
|
|
1570
|
+
// footer must not be visible when the dialog is open as per UX guidelines
|
|
1571
|
+
(oDialog.getBindingContext("internal") as InternalModelContext).setProperty("isCreateDialogOpen", true);
|
|
1572
|
+
oDialog.open();
|
|
1573
|
+
})
|
|
1574
|
+
.catch(function(oError: any) {
|
|
1575
|
+
return messageHandler.showMessages().then(function() {
|
|
1576
|
+
return Promise.reject(oError);
|
|
1577
|
+
});
|
|
1578
|
+
});
|
|
1579
|
+
});
|
|
1580
|
+
});
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1583
|
+
onAfterCreateCompletion(oListBinding: any, oNewDocumentContext: any, mParameters: any) {
|
|
1584
|
+
let fnResolve: Function, fnReject: Function;
|
|
1585
|
+
const oPromise = new Promise(function(resolve, reject) {
|
|
1586
|
+
fnResolve = resolve;
|
|
1587
|
+
fnReject = reject;
|
|
1588
|
+
});
|
|
1589
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1590
|
+
const that = this;
|
|
1591
|
+
// Workaround suggested by OData model v4 colleagues
|
|
1592
|
+
const fnCreateCompleted = function(oEvent: any) {
|
|
1593
|
+
const oContext = oEvent.getParameter("context"),
|
|
1594
|
+
bSuccess = oEvent.getParameter("success");
|
|
1595
|
+
if (oContext === oNewDocumentContext) {
|
|
1596
|
+
oListBinding.detachCreateCompleted(fnCreateCompleted, that);
|
|
1597
|
+
if (!bSuccess) {
|
|
1598
|
+
const oError: any = { bDeleteTransientContext: false };
|
|
1599
|
+
if (!mParameters.keepTransientContextOnFailed) {
|
|
1600
|
+
// the context is deleted
|
|
1601
|
+
oError.bDeleteTransientContext = true;
|
|
1602
|
+
// this is needed to avoid console errors TO be checked with model colleagues
|
|
1603
|
+
oContext
|
|
1604
|
+
.created()
|
|
1605
|
+
.then(undefined, function() {
|
|
1606
|
+
Log.trace("transient creation context deleted");
|
|
1607
|
+
})
|
|
1608
|
+
.catch(function(oError: any) {
|
|
1609
|
+
Log.trace("transient creation context deletion error", oError);
|
|
1610
|
+
});
|
|
1611
|
+
// if current state is transient (...), browser will come back to previous state
|
|
1612
|
+
oError.navigateBackFromTransientState = true;
|
|
1613
|
+
}
|
|
1614
|
+
fnReject(oError);
|
|
1615
|
+
} else {
|
|
1616
|
+
fnResolve();
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
};
|
|
1620
|
+
oListBinding.attachCreateCompleted(fnCreateCompleted, this);
|
|
1621
|
+
return oPromise;
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Retrieves the name of the NewAction to be executed.
|
|
1625
|
+
*
|
|
1626
|
+
* @function
|
|
1627
|
+
* @static
|
|
1628
|
+
* @private
|
|
1629
|
+
* @name sap.fe.core.TransactionHelper._getNewAction
|
|
1630
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
1631
|
+
* @param {object} oStartupParameters Startup parameters of the application
|
|
1632
|
+
* @param {string} sCreateHash Hash to be checked for action type
|
|
1633
|
+
* @param {object} oMetaModel The MetaModel used to check for NewAction parameter
|
|
1634
|
+
* @param {string} sMetaPath The MetaPath
|
|
1635
|
+
* @returns {string} The name of the action
|
|
1636
|
+
* @ui5-restricted
|
|
1637
|
+
* @final
|
|
1638
|
+
**/
|
|
1639
|
+
_getNewAction(oStartupParameters: any, sCreateHash: string, oMetaModel: ODataMetaModel, sMetaPath: string) {
|
|
1640
|
+
let sNewAction;
|
|
1641
|
+
|
|
1642
|
+
if (oStartupParameters && oStartupParameters.preferredMode && sCreateHash.indexOf("i-action=createWith") > -1) {
|
|
1643
|
+
const sPreferredMode = oStartupParameters.preferredMode[0];
|
|
1644
|
+
sNewAction =
|
|
1645
|
+
sPreferredMode.indexOf("createWith:") > -1 ? sPreferredMode.substr(sPreferredMode.lastIndexOf(":") + 1) : undefined;
|
|
1646
|
+
} else {
|
|
1647
|
+
sNewAction =
|
|
1648
|
+
oMetaModel && oMetaModel.getObject !== undefined
|
|
1649
|
+
? oMetaModel.getObject(sMetaPath + "@com.sap.vocabularies.Session.v1.StickySessionSupported/NewAction") ||
|
|
1650
|
+
oMetaModel.getObject(sMetaPath + "@com.sap.vocabularies.Common.v1.DraftRoot/NewAction")
|
|
1651
|
+
: undefined;
|
|
1652
|
+
}
|
|
1653
|
+
return sNewAction;
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* Retrieves the label for the title of a specific create action dialog, e.g. Create Sales Order from Quotation.
|
|
1657
|
+
*
|
|
1658
|
+
* The following priority is applied:
|
|
1659
|
+
* 1. label of line-item annotation.
|
|
1660
|
+
* 2. label annotated in the action.
|
|
1661
|
+
* 3. "Create" as a constant from i18n.
|
|
1662
|
+
*
|
|
1663
|
+
* @function
|
|
1664
|
+
* @static
|
|
1665
|
+
* @private
|
|
1666
|
+
* @name sap.fe.core.TransactionHelper._getSpecificCreateActionDialogLabel
|
|
1667
|
+
* @memberof sap.fe.core.TransactionHelper
|
|
1668
|
+
* @param {object} oMetaModel The MetaModel used to check for the NewAction parameter
|
|
1669
|
+
* @param {string} sMetaPath The MetaPath
|
|
1670
|
+
* @param {string} sNewAction Contains the name of the action to be executed
|
|
1671
|
+
* @param {object} oResourceBundleCore ResourceBundle to access the default Create label
|
|
1672
|
+
* @returns {string} The label for the Create Action Dialog
|
|
1673
|
+
* @ui5-restricted
|
|
1674
|
+
* @final
|
|
1675
|
+
**/
|
|
1676
|
+
_getSpecificCreateActionDialogLabel(
|
|
1677
|
+
oMetaModel: ODataMetaModel,
|
|
1678
|
+
sMetaPath: string,
|
|
1679
|
+
sNewAction: string,
|
|
1680
|
+
oResourceBundleCore: ResourceBundle
|
|
1681
|
+
) {
|
|
1682
|
+
const fnGetLabelFromLineItemAnnotation = function() {
|
|
1683
|
+
if (oMetaModel && oMetaModel.getObject(sMetaPath + "/@com.sap.vocabularies.UI.v1.LineItem")) {
|
|
1684
|
+
const iLineItemIndex = oMetaModel
|
|
1685
|
+
.getObject(sMetaPath + "/@com.sap.vocabularies.UI.v1.LineItem")
|
|
1686
|
+
.findIndex(function(oLineItem: any) {
|
|
1687
|
+
const aLineItemAction = oLineItem.Action ? oLineItem.Action.split("(") : undefined;
|
|
1688
|
+
return aLineItemAction ? aLineItemAction[0] === sNewAction : false;
|
|
1689
|
+
});
|
|
1690
|
+
return iLineItemIndex > -1
|
|
1691
|
+
? oMetaModel.getObject(sMetaPath + "/@com.sap.vocabularies.UI.v1.LineItem")[iLineItemIndex].Label
|
|
1692
|
+
: undefined;
|
|
1693
|
+
} else {
|
|
1694
|
+
return undefined;
|
|
1695
|
+
}
|
|
1696
|
+
};
|
|
1697
|
+
|
|
1698
|
+
return (
|
|
1699
|
+
fnGetLabelFromLineItemAnnotation() ||
|
|
1700
|
+
(oMetaModel && oMetaModel.getObject(sMetaPath + "/" + sNewAction + "@com.sap.vocabularies.Common.v1.Label")) ||
|
|
1701
|
+
(oResourceBundleCore && oResourceBundleCore.getText("C_TRANSACTION_HELPER_SAPFE_ACTION_CREATE"))
|
|
1702
|
+
);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
export default TransactionHelper;
|