@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.
Files changed (231) hide show
  1. package/package.json +3 -2
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AnnotationHelper.js +377 -405
  4. package/src/sap/fe/core/AnnotationHelper.ts +385 -0
  5. package/src/sap/fe/core/AppComponent.js +3 -2
  6. package/src/sap/fe/core/AppStateHandler.js +229 -181
  7. package/src/sap/fe/core/AppStateHandler.ts +171 -0
  8. package/src/sap/fe/core/BaseController.js +3 -2
  9. package/src/sap/fe/core/BusyLocker.js +105 -121
  10. package/src/sap/fe/core/BusyLocker.ts +98 -0
  11. package/src/sap/fe/core/CommonUtils.js +2073 -2399
  12. package/src/sap/fe/core/CommonUtils.ts +2078 -0
  13. package/src/sap/fe/core/ExtensionAPI.js +3 -2
  14. package/src/sap/fe/core/PageController.js +84 -125
  15. package/src/sap/fe/core/PageController.ts +101 -0
  16. package/src/sap/fe/core/RouterProxy.js +986 -823
  17. package/src/sap/fe/core/RouterProxy.ts +838 -0
  18. package/src/sap/fe/core/Synchronization.js +51 -35
  19. package/src/sap/fe/core/Synchronization.ts +29 -0
  20. package/src/sap/fe/core/TemplateComponent.js +173 -164
  21. package/src/sap/fe/core/TemplateComponent.ts +166 -0
  22. package/src/sap/fe/core/TemplateModel.js +97 -54
  23. package/src/sap/fe/core/TemplateModel.ts +63 -0
  24. package/src/sap/fe/core/TransactionHelper.js +1576 -1664
  25. package/src/sap/fe/core/TransactionHelper.ts +1706 -0
  26. package/src/sap/fe/core/actions/draft.js +559 -608
  27. package/src/sap/fe/core/actions/draft.ts +593 -0
  28. package/src/sap/fe/core/actions/messageHandling.js +545 -514
  29. package/src/sap/fe/core/actions/messageHandling.ts +532 -0
  30. package/src/sap/fe/core/actions/nonDraft.js +17 -19
  31. package/src/sap/fe/core/actions/nonDraft.ts +12 -0
  32. package/src/sap/fe/core/actions/operations.js +1074 -1215
  33. package/src/sap/fe/core/actions/operations.ts +1162 -0
  34. package/src/sap/fe/core/actions/sticky.js +102 -105
  35. package/src/sap/fe/core/actions/sticky.ts +102 -0
  36. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +3 -2
  37. package/src/sap/fe/core/controllerextensions/EditFlow.js +54 -211
  38. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +3 -2
  39. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +279 -11
  40. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +8 -6
  41. package/src/sap/fe/core/controllerextensions/InternalRouting.js +47 -45
  42. package/src/sap/fe/core/controllerextensions/KPIManagement.js +2 -3
  43. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +29 -26
  44. package/src/sap/fe/core/controllerextensions/MassEdit.js +101 -8
  45. package/src/sap/fe/core/controllerextensions/MessageHandler.js +17 -8
  46. package/src/sap/fe/core/controllerextensions/PageReady.js +2 -2
  47. package/src/sap/fe/core/controllerextensions/PageReady.ts +12 -8
  48. package/src/sap/fe/core/controllerextensions/Paginator.js +3 -2
  49. package/src/sap/fe/core/controllerextensions/Placeholder.js +3 -2
  50. package/src/sap/fe/core/controllerextensions/Routing.js +9 -4
  51. package/src/sap/fe/core/controllerextensions/RoutingListener.js +3 -2
  52. package/src/sap/fe/core/controllerextensions/Share.js +3 -2
  53. package/src/sap/fe/core/controllerextensions/SideEffects.js +3 -3
  54. package/src/sap/fe/core/controllerextensions/SideEffects.ts +18 -18
  55. package/src/sap/fe/core/controllerextensions/ViewState.js +3 -2
  56. package/src/sap/fe/core/controls/CommandExecution.js +3 -2
  57. package/src/sap/fe/core/controls/ConditionalWrapper.js +3 -2
  58. package/src/sap/fe/core/controls/CustomQuickViewPage.js +3 -2
  59. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +3 -2
  60. package/src/sap/fe/core/controls/FieldWrapper.js +11 -22
  61. package/src/sap/fe/core/controls/FilterBar.js +3 -2
  62. package/src/sap/fe/core/controls/FormElementWrapper.js +3 -2
  63. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +3 -2
  64. package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +1 -0
  65. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +3 -2
  66. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +5 -4
  67. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +3 -2
  68. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +3 -2
  69. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +3 -2
  70. package/src/sap/fe/core/converters/ConverterContext.js +2 -2
  71. package/src/sap/fe/core/converters/ConverterContext.ts +4 -3
  72. package/src/sap/fe/core/converters/ManifestSettings.js +1 -1
  73. package/src/sap/fe/core/converters/ManifestSettings.ts +1 -0
  74. package/src/sap/fe/core/converters/ManifestWrapper.js +39 -26
  75. package/src/sap/fe/core/converters/ManifestWrapper.ts +9 -0
  76. package/src/sap/fe/core/converters/MetaModelConverter.js +11 -8
  77. package/src/sap/fe/core/converters/MetaModelConverter.ts +16 -16
  78. package/src/sap/fe/core/converters/TemplateConverter.js +1 -1
  79. package/src/sap/fe/core/converters/TemplateConverter.ts +2 -2
  80. package/src/sap/fe/core/converters/common/AnnotationConverter.js +17 -13
  81. package/src/sap/fe/core/converters/controls/Common/Action.js +2 -2
  82. package/src/sap/fe/core/converters/controls/Common/Action.ts +2 -2
  83. package/src/sap/fe/core/converters/controls/Common/Chart.js +5 -3
  84. package/src/sap/fe/core/converters/controls/Common/Chart.ts +11 -3
  85. package/src/sap/fe/core/converters/controls/Common/DataVisualization.js +3 -3
  86. package/src/sap/fe/core/converters/controls/Common/DataVisualization.ts +2 -2
  87. package/src/sap/fe/core/converters/controls/Common/Form.js +4 -2
  88. package/src/sap/fe/core/converters/controls/Common/Form.ts +16 -2
  89. package/src/sap/fe/core/converters/controls/Common/Table.js +250 -146
  90. package/src/sap/fe/core/converters/controls/Common/Table.ts +300 -167
  91. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +115 -56
  92. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +120 -74
  93. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +467 -32
  94. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +483 -54
  95. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +6 -6
  96. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +9 -15
  97. package/src/sap/fe/core/converters/helpers/Aggregation.js +13 -5
  98. package/src/sap/fe/core/converters/helpers/Aggregation.ts +20 -5
  99. package/src/sap/fe/core/converters/helpers/IssueManager.js +4 -1
  100. package/src/sap/fe/core/converters/helpers/IssueManager.ts +3 -0
  101. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +4 -4
  102. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +3 -3
  103. package/src/sap/fe/core/converters/templates/ListReportConverter.js +13 -6
  104. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +26 -15
  105. package/src/sap/fe/core/designtime/AppComponent.designtime.js +3 -2
  106. package/src/sap/fe/core/formatters/CriticalityFormatter.js +1 -1
  107. package/src/sap/fe/core/formatters/CriticalityFormatter.ts +1 -1
  108. package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
  109. package/src/sap/fe/core/formatters/FPMFormatter.ts +4 -10
  110. package/src/sap/fe/core/formatters/KPIFormatter.js +1 -1
  111. package/src/sap/fe/core/formatters/KPIFormatter.ts +3 -1
  112. package/src/sap/fe/core/formatters/TableFormatter.js +39 -28
  113. package/src/sap/fe/core/formatters/TableFormatter.ts +43 -28
  114. package/src/sap/fe/core/formatters/ValueFormatter.js +1 -1
  115. package/src/sap/fe/core/formatters/ValueFormatter.ts +7 -6
  116. package/src/sap/fe/core/fpm/Component.js +3 -2
  117. package/src/sap/fe/core/helpers/AppStartupHelper.js +2 -2
  118. package/src/sap/fe/core/helpers/AppStartupHelper.ts +7 -4
  119. package/src/sap/fe/core/helpers/BindingExpression.js +314 -355
  120. package/src/sap/fe/core/helpers/BindingExpression.ts +317 -391
  121. package/src/sap/fe/core/helpers/ClassSupport.js +27 -15
  122. package/src/sap/fe/core/helpers/ClassSupport.ts +31 -20
  123. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +63 -59
  124. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.ts +56 -0
  125. package/src/sap/fe/core/helpers/EditState.js +81 -84
  126. package/src/sap/fe/core/helpers/EditState.ts +81 -0
  127. package/src/sap/fe/core/helpers/ExcelFormatHelper.js +62 -48
  128. package/src/sap/fe/core/helpers/ExcelFormatHelper.ts +49 -0
  129. package/src/sap/fe/core/helpers/FPMHelper.js +52 -56
  130. package/src/sap/fe/core/helpers/FPMHelper.ts +62 -0
  131. package/src/sap/fe/core/helpers/KeepAliveHelper.js +3 -4
  132. package/src/sap/fe/core/helpers/KeepAliveHelper.ts +9 -9
  133. package/src/sap/fe/core/helpers/MassEditHelper.js +27 -18
  134. package/src/sap/fe/core/helpers/ModelHelper.js +229 -225
  135. package/src/sap/fe/core/helpers/ModelHelper.ts +227 -0
  136. package/src/sap/fe/core/helpers/PasteHelper.js +210 -132
  137. package/src/sap/fe/core/helpers/PasteHelper.ts +196 -0
  138. package/src/sap/fe/core/helpers/SemanticDateOperators.js +332 -313
  139. package/src/sap/fe/core/helpers/SemanticDateOperators.ts +330 -0
  140. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +66 -67
  141. package/src/sap/fe/core/helpers/SemanticKeyHelper.ts +73 -0
  142. package/src/sap/fe/core/helpers/StableIdHelper.js +4 -7
  143. package/src/sap/fe/core/helpers/StableIdHelper.ts +2 -6
  144. package/src/sap/fe/core/jsx-runtime/jsx.js +1 -1
  145. package/src/sap/fe/core/jsx-runtime/jsx.ts +1 -1
  146. package/src/sap/fe/core/library.js +4 -3
  147. package/src/sap/fe/core/library.support.js +3 -2
  148. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +1 -1
  149. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +1 -1
  150. package/src/sap/fe/core/messagebundle.properties +23 -10
  151. package/src/sap/fe/core/messagebundle_ar.properties +9 -0
  152. package/src/sap/fe/core/messagebundle_bg.properties +9 -0
  153. package/src/sap/fe/core/messagebundle_ca.properties +9 -0
  154. package/src/sap/fe/core/messagebundle_cs.properties +10 -1
  155. package/src/sap/fe/core/messagebundle_cy.properties +9 -0
  156. package/src/sap/fe/core/messagebundle_da.properties +9 -0
  157. package/src/sap/fe/core/messagebundle_de.properties +9 -0
  158. package/src/sap/fe/core/messagebundle_el.properties +9 -0
  159. package/src/sap/fe/core/messagebundle_en.properties +9 -0
  160. package/src/sap/fe/core/messagebundle_en_GB.properties +9 -0
  161. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +9 -0
  162. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +9 -0
  163. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +9 -0
  164. package/src/sap/fe/core/messagebundle_es.properties +9 -0
  165. package/src/sap/fe/core/messagebundle_es_MX.properties +9 -0
  166. package/src/sap/fe/core/messagebundle_et.properties +9 -0
  167. package/src/sap/fe/core/messagebundle_fi.properties +9 -0
  168. package/src/sap/fe/core/messagebundle_fr.properties +13 -4
  169. package/src/sap/fe/core/messagebundle_fr_CA.properties +15 -6
  170. package/src/sap/fe/core/messagebundle_hi.properties +15 -6
  171. package/src/sap/fe/core/messagebundle_hr.properties +15 -6
  172. package/src/sap/fe/core/messagebundle_hu.properties +9 -0
  173. package/src/sap/fe/core/messagebundle_id.properties +10 -1
  174. package/src/sap/fe/core/messagebundle_it.properties +9 -0
  175. package/src/sap/fe/core/messagebundle_iw.properties +9 -0
  176. package/src/sap/fe/core/messagebundle_ja.properties +9 -0
  177. package/src/sap/fe/core/messagebundle_kk.properties +15 -6
  178. package/src/sap/fe/core/messagebundle_ko.properties +9 -0
  179. package/src/sap/fe/core/messagebundle_lt.properties +9 -0
  180. package/src/sap/fe/core/messagebundle_lv.properties +15 -6
  181. package/src/sap/fe/core/messagebundle_ms.properties +14 -5
  182. package/src/sap/fe/core/messagebundle_nl.properties +9 -0
  183. package/src/sap/fe/core/messagebundle_no.properties +9 -0
  184. package/src/sap/fe/core/messagebundle_pl.properties +9 -0
  185. package/src/sap/fe/core/messagebundle_pt.properties +9 -0
  186. package/src/sap/fe/core/messagebundle_pt_PT.properties +9 -0
  187. package/src/sap/fe/core/messagebundle_ro.properties +9 -0
  188. package/src/sap/fe/core/messagebundle_ru.properties +9 -0
  189. package/src/sap/fe/core/messagebundle_sh.properties +11 -2
  190. package/src/sap/fe/core/messagebundle_sk.properties +9 -0
  191. package/src/sap/fe/core/messagebundle_sl.properties +15 -6
  192. package/src/sap/fe/core/messagebundle_sv.properties +9 -0
  193. package/src/sap/fe/core/messagebundle_th.properties +9 -0
  194. package/src/sap/fe/core/messagebundle_tr.properties +9 -0
  195. package/src/sap/fe/core/messagebundle_uk.properties +9 -0
  196. package/src/sap/fe/core/messagebundle_vi.properties +9 -0
  197. package/src/sap/fe/core/messagebundle_zh_CN.properties +9 -0
  198. package/src/sap/fe/core/messagebundle_zh_TW.properties +15 -6
  199. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +1 -1
  200. package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +3 -1
  201. package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +269 -202
  202. package/src/sap/fe/core/services/CacheHandlerServiceFactory.ts +212 -0
  203. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +1 -1
  204. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +7 -6
  205. package/src/sap/fe/core/services/NavigationServiceFactory.js +406 -300
  206. package/src/sap/fe/core/services/NavigationServiceFactory.ts +316 -0
  207. package/src/sap/fe/core/services/ResourceModelServiceFactory.js +149 -81
  208. package/src/sap/fe/core/services/ResourceModelServiceFactory.ts +80 -0
  209. package/src/sap/fe/core/services/RoutingServiceFactory.js +987 -899
  210. package/src/sap/fe/core/services/RoutingServiceFactory.ts +898 -0
  211. package/src/sap/fe/core/services/ShellServicesFactory.js +1 -1
  212. package/src/sap/fe/core/services/ShellServicesFactory.ts +15 -10
  213. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +35 -81
  214. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +46 -94
  215. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +461 -487
  216. package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +453 -0
  217. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +10 -8
  218. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.ts +8 -0
  219. package/src/sap/fe/core/support/AnnotationIssue.support.js +15 -3
  220. package/src/sap/fe/core/support/AnnotationIssue.support.ts +16 -2
  221. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.js +2 -2
  222. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.ts +1 -1
  223. package/src/sap/fe/core/templating/FieldControlHelper.js +8 -8
  224. package/src/sap/fe/core/templating/FieldControlHelper.ts +25 -7
  225. package/src/sap/fe/core/templating/FilterHelper.js +138 -72
  226. package/src/sap/fe/core/templating/FilterHelper.ts +139 -71
  227. package/src/sap/fe/core/templating/UIFormatters.js +31 -1
  228. package/src/sap/fe/core/templating/UIFormatters.ts +33 -2
  229. package/src/sap/fe/core/type/Email.js +1 -1
  230. package/src/sap/fe/core/type/Email.ts +4 -6
  231. package/ui5.yaml +0 -3
@@ -0,0 +1,1162 @@
1
+ import MessageBox from "sap/m/MessageBox";
2
+ import Dialog from "sap/m/Dialog";
3
+ import JSONModel from "sap/ui/model/json/JSONModel";
4
+ import XMLTemplateProcessor from "sap/ui/core/XMLTemplateProcessor";
5
+ import XMLPreprocessor from "sap/ui/core/util/XMLPreprocessor";
6
+ import Fragment from "sap/ui/core/Fragment";
7
+ import messageHandling from "sap/fe/core/actions/messageHandling";
8
+ import BusyLocker from "sap/fe/core/BusyLocker";
9
+ import CommonUtils from "sap/fe/core/CommonUtils";
10
+ import Log from "sap/base/Log";
11
+ import FELibrary from "sap/fe/core/library";
12
+ import FPMHelper from "sap/fe/core/helpers/FPMHelper";
13
+ import Button from "sap/m/Button";
14
+ import { generate } from "sap/fe/core/helpers/StableIdHelper";
15
+
16
+ const Constants = FELibrary.Constants,
17
+ InvocationGrouping = FELibrary.InvocationGrouping;
18
+ const Action = (MessageBox as any).Action;
19
+
20
+ /**
21
+ * Calls a bound action for one or multiple contexts.
22
+ *
23
+ * @function
24
+ * @static
25
+ * @name sap.fe.core.actions.operations.callBoundAction
26
+ * @memberof sap.fe.core.actions.operations
27
+ * @param {string} sActionName The name of the action to be called
28
+ * @param {sap.ui.model.odata.v4.Context} contexts Either one context or an array with contexts for which the action is to be be called
29
+ * @param {sap.ui.model.odata.v4.Model} oModel OData Model
30
+ * @param {object} oAppComponent The AppComponent
31
+ * @param {map} [mParameters] Optional, can contain the following attributes:
32
+ * @param {map} [mParameters.actionParameters] A map of parameters to be sent for every action call
33
+ * @param {map} [mParameters.mBindingParameters] A map of binding parameters that would be part of $select and $expand coming from side effects for bound actions
34
+ * @param {Array} [mParameters.additionalSideEffect] Array of property paths to be requested in addition to actual target properties of the side effect
35
+ * @param {boolean} [mParameters.showActionParameterDialog] If set and if parameters exist the user retrieves a dialog to fill in parameters, if actionParameters are passed they are shown to the user
36
+ * @param {string} [mParameters.label] A human-readable label for the action
37
+ * @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, defaults to Isolated
38
+ * @param {Function} [mParameters.onSubmitted] Function which is called once the actions are submitted with an array of promises
39
+ * @param {map} [mParameters.defaultParameters] Can contain default parameters from FLP user defaults
40
+ * @param {sap.ui.core.Element} [mParameters.parentControl] If specified the dialogs are added as dependent of the parent control
41
+ * @param {boolean} [mParameters.bGetBoundContext] If specified the action promise returns the bound context
42
+ * @returns {Promise} Promise resolves with an array of response objects (TODO: to be changed)
43
+ * @private
44
+ * @ui5-restricted
45
+ */
46
+ function callBoundAction(sActionName: string, contexts: any, oModel: any, oAppComponent: object, mParameters: any) {
47
+ if (!contexts || contexts.length === 0) {
48
+ //In Freestyle apps bound actions can have no context
49
+ return Promise.reject("Bound actions always requires at least one context");
50
+ }
51
+ // we expect either one context or an array of contexts
52
+ if (Array.isArray(contexts)) {
53
+ mParameters.bReturnAsArray = true;
54
+ } else {
55
+ //action needs to be called on this context from the dependent binding so UI fields are updated with response data
56
+ contexts = [contexts];
57
+ }
58
+ const oMetaModel = oModel.getMetaModel(),
59
+ sActionPath = oMetaModel.getMetaPath(contexts[0].getPath()) + "/" + sActionName,
60
+ oBoundAction = oMetaModel.createBindingContext(sActionPath + "/@$ui5.overload/0");
61
+ mParameters.aContexts = contexts;
62
+ mParameters.isCriticalAction = getIsActionCritical(oMetaModel, sActionPath, contexts, oBoundAction);
63
+ return callAction(sActionName, oModel, oBoundAction, oAppComponent, mParameters);
64
+ }
65
+ /**
66
+ * Calls an action import.
67
+ *
68
+ * @function
69
+ * @static
70
+ * @name sap.fe.core.actions.operations.callActionImport
71
+ * @memberof sap.fe.core.actions.operations
72
+ * @param {string} sActionName The name of the action import to be called
73
+ * @param {sap.ui.model.odata.v4.ODataModel} oModel An instance of an OData v4 model
74
+ * @param {object} oAppComponent The AppComponent
75
+ * @param {map} [mParameters] Optional, can contain the following attributes:
76
+ * @param {map} [mParameters.actionParameters] A map of parameters to be sent with the action import
77
+ * @param {string} [mParameters.label] A human-readable label for the action
78
+ * @param {boolean} [mParameters.showActionParameterDialog] If set and if parameters exist the user retrieves a dialog to fill in parameters, if actionParameters are passed they are shown to the user
79
+ * @param {Function} [mParameters.onSubmitted] Function which is called once the actions are submitted with an array of promises
80
+ * @param {map} [mParameters.defaultParameters] Can contain default parameters from FLP user defaults
81
+ * @returns {Promise} Promise resolves with an array of response objects (TODO: to be changed)
82
+ * @private
83
+ * @ui5-restricted
84
+ */
85
+ function callActionImport(sActionName: string, oModel: any, oAppComponent: object, mParameters: any) {
86
+ if (!oModel) {
87
+ return Promise.reject("Action expects a model/context for execution");
88
+ }
89
+ const oMetaModel = oModel.getMetaModel(),
90
+ sActionPath = oModel.bindContext("/" + sActionName).getPath(),
91
+ oActionImport = oMetaModel.createBindingContext("/" + oMetaModel.createBindingContext(sActionPath).getObject("$Action") + "/0");
92
+ mParameters.isCriticalAction = getIsActionCritical(oMetaModel, sActionPath + "/@$ui5.overload");
93
+ return callAction(sActionName, oModel, oActionImport, oAppComponent, mParameters);
94
+ }
95
+ function callBoundFunction(sFunctionName: string, context: any, oModel: any) {
96
+ if (!context) {
97
+ return Promise.reject("Bound functions always requires a context");
98
+ }
99
+ const oMetaModel = oModel.getMetaModel(),
100
+ sFunctionPath = oMetaModel.getMetaPath(context.getPath()) + "/" + sFunctionName,
101
+ oBoundFunction = oMetaModel.createBindingContext(sFunctionPath);
102
+ return _executeFunction(sFunctionName, oModel, oBoundFunction, context);
103
+ }
104
+ /**
105
+ * Calls a function import.
106
+ *
107
+ * @function
108
+ * @static
109
+ * @name sap.fe.core.actions.operations.callFunctionImport
110
+ * @memberof sap.fe.core.actions.operations
111
+ * @param {string} sFunctionName The name of the function to be called
112
+ * @param {sap.ui.model.odata.v4.ODataModel} oModel An instance of an OData v4 model
113
+ * @returns {Promise} Promise resolves
114
+ * @private
115
+ */
116
+ function callFunctionImport(sFunctionName: string, oModel: any) {
117
+ if (!sFunctionName) {
118
+ return Promise.resolve();
119
+ }
120
+ const oMetaModel = oModel.getMetaModel(),
121
+ sFunctionPath = oModel.bindContext("/" + sFunctionName).getPath(),
122
+ oFunctionImport = oMetaModel.createBindingContext(
123
+ "/" + oMetaModel.createBindingContext(sFunctionPath).getObject("$Function") + "/0"
124
+ );
125
+ return _executeFunction(sFunctionName, oModel, oFunctionImport);
126
+ }
127
+ function _executeFunction(sFunctionName: any, oModel: any, oFunction: any, context?: any) {
128
+ let sGroupId;
129
+ if (!oFunction || !oFunction.getObject()) {
130
+ return Promise.reject(new Error("Function " + sFunctionName + " not found"));
131
+ }
132
+ if (context) {
133
+ oFunction = oModel.bindContext(sFunctionName + "(...)", context);
134
+ sGroupId = "functionGroup";
135
+ } else {
136
+ oFunction = oModel.bindContext("/" + sFunctionName + "(...)");
137
+ sGroupId = "functionImport";
138
+ }
139
+ const oFunctionPromise = oFunction.execute(sGroupId);
140
+ oModel.submitBatch(sGroupId);
141
+ return oFunctionPromise.then(function() {
142
+ return oFunction.getBoundContext();
143
+ });
144
+ }
145
+ function callAction(sActionName: any, oModel: any, oAction: any, oAppComponent: any, mParameters: any) {
146
+ return new Promise(function(resolve: (value: any) => void, reject: (reason?: any) => void) {
147
+ let aActionParameters = mParameters.actionParameters || [];
148
+ let mActionExecutionParameters: any = {};
149
+ let fnDialog;
150
+ let oActionPromise;
151
+ const sActionLabel = mParameters.label;
152
+ let bShowActionParameterDialog = mParameters.showActionParameterDialog;
153
+ const aContexts = mParameters.aContexts;
154
+ const bIsCreateAction = mParameters.bIsCreateAction;
155
+ const bIsCriticalAction = mParameters.isCriticalAction;
156
+ let oMetaModel;
157
+ let sMetaPath;
158
+ let sMessagesPath: any;
159
+ let iMessageSideEffect;
160
+ if (!oAction || !oAction.getObject()) {
161
+ return reject(new Error("Action " + sActionName + " not found"));
162
+ }
163
+ if (bShowActionParameterDialog || aActionParameters.length > 0) {
164
+ aActionParameters = prepareActionParameters(oAction, aActionParameters);
165
+ if (!aActionParameters || aActionParameters.length === 0) {
166
+ bShowActionParameterDialog = false;
167
+ }
168
+ }
169
+ if (bShowActionParameterDialog) {
170
+ fnDialog = showActionParameterDialog;
171
+ } else if (bIsCriticalAction) {
172
+ fnDialog = confirmCriticalAction;
173
+ }
174
+ mActionExecutionParameters = {
175
+ fnOnSubmitted: mParameters.onSubmitted,
176
+ fnOnResponse: mParameters.onResponse,
177
+ actionName: sActionName,
178
+ model: oModel,
179
+ aActionParameters: aActionParameters,
180
+ bGetBoundContext: mParameters.bGetBoundContext,
181
+ defaultValuesExtensionFunction: mParameters.defaultValuesExtensionFunction
182
+ };
183
+ if (oAction.getObject("$IsBound")) {
184
+ if (mParameters.additionalSideEffect && mParameters.additionalSideEffect.pathExpressions) {
185
+ oMetaModel = oModel.getMetaModel();
186
+ sMetaPath = oMetaModel.getMetaPath(aContexts[0].getPath());
187
+ sMessagesPath = oMetaModel.getObject(sMetaPath + "/@com.sap.vocabularies.Common.v1.Messages/$Path");
188
+
189
+ if (sMessagesPath) {
190
+ iMessageSideEffect = mParameters.additionalSideEffect.pathExpressions.findIndex(function(exp: any) {
191
+ return exp.$PropertyPath === sMessagesPath;
192
+ });
193
+
194
+ if (iMessageSideEffect > -1) {
195
+ // the message path is annotated as side effect. As there's no binding for it and the model does currently not allow
196
+ // to add it at a later point of time we have to take care it's part of the $select of the POST, therefore moving it
197
+ mParameters.mBindingParameters = mParameters.mBindingParameters || {};
198
+
199
+ if (
200
+ oAction.getObject("$ReturnType/$Type/" + sMessagesPath) &&
201
+ (!mParameters.mBindingParameters.$select ||
202
+ mParameters.mBindingParameters.$select.split(",").indexOf(sMessagesPath) === -1)
203
+ ) {
204
+ mParameters.mBindingParameters.$select = mParameters.mBindingParameters.$select
205
+ ? mParameters.mBindingParameters.$select + "," + sMessagesPath
206
+ : sMessagesPath;
207
+
208
+ if (mParameters.additionalSideEffect.triggerActions.length === 0) {
209
+ // no trigger action therefore no need to request messages again
210
+ mParameters.additionalSideEffect.pathExpressions.splice(iMessageSideEffect, 1);
211
+ }
212
+ }
213
+ }
214
+ }
215
+ }
216
+
217
+ mActionExecutionParameters.aContexts = aContexts;
218
+ mActionExecutionParameters.mBindingParameters = mParameters.mBindingParameters;
219
+ mActionExecutionParameters.additionalSideEffect = mParameters.additionalSideEffect;
220
+ mActionExecutionParameters.bGrouped = mParameters.invocationGrouping === InvocationGrouping.ChangeSet;
221
+ mActionExecutionParameters.bReturnAsArray = mParameters.bReturnAsArray;
222
+ mActionExecutionParameters.internalModelContext = mParameters.internalModelContext;
223
+ mActionExecutionParameters.operationAvailableMap = mParameters.operationAvailableMap;
224
+ mActionExecutionParameters.bObjectPage = mParameters.bObjectPage;
225
+ }
226
+ if (bIsCreateAction) {
227
+ mActionExecutionParameters.bIsCreateAction = bIsCreateAction;
228
+ }
229
+ if (fnDialog) {
230
+ oActionPromise = fnDialog(
231
+ sActionName,
232
+ oAppComponent,
233
+ sActionLabel,
234
+ mActionExecutionParameters,
235
+ aActionParameters,
236
+ oAction,
237
+ mParameters.parentControl,
238
+ mParameters.entitySetName,
239
+ mParameters.messageHandler
240
+ );
241
+ } else {
242
+ oActionPromise = _executeAction(oAppComponent, mActionExecutionParameters);
243
+ }
244
+ return oActionPromise
245
+ .then(function(oOperationResult: any) {
246
+ resolve(oOperationResult);
247
+ })
248
+ .catch(function(oOperationResult: any) {
249
+ reject(oOperationResult);
250
+ });
251
+ });
252
+ }
253
+ function confirmCriticalAction(
254
+ sActionName: any,
255
+ oAppComponent: any,
256
+ sActionLabel: any,
257
+ mParameters: any,
258
+ aActionParameters: any,
259
+ oActionContext: any,
260
+ oParentControl: any,
261
+ entitySetName: any,
262
+ messageHandler: any
263
+ ) {
264
+ return new Promise<void>((resolve, reject) => {
265
+ let boundActionName = sActionName ? sActionName : null;
266
+ boundActionName =
267
+ boundActionName.indexOf(".") >= 0 ? boundActionName.split(".")[boundActionName.split(".").length - 1] : boundActionName;
268
+ const suffixResourceKey = boundActionName && entitySetName ? entitySetName + "|" + boundActionName : "";
269
+ const oResourceBundle = oParentControl.getController().oResourceBundle;
270
+ const sConfirmationText = CommonUtils.getTranslatedText(
271
+ "C_OPERATIONS_ACTION_CONFIRM_MESSAGE",
272
+ oResourceBundle,
273
+ null,
274
+ suffixResourceKey
275
+ );
276
+
277
+ MessageBox.confirm(sConfirmationText, {
278
+ onClose: function(sAction: any) {
279
+ if (sAction === Action.OK) {
280
+ return _executeAction(oAppComponent, mParameters)
281
+ .then(function(oOperation: any) {
282
+ resolve(oOperation);
283
+ })
284
+ .catch(function(oError: any) {
285
+ messageHandler
286
+ .showMessageDialog()
287
+ .then(function() {
288
+ reject(oError);
289
+ })
290
+ .catch(function() {
291
+ reject(oError);
292
+ });
293
+ });
294
+ } else {
295
+ resolve();
296
+ }
297
+ }
298
+ });
299
+ });
300
+ }
301
+ function showActionParameterDialog(
302
+ sActionName: any,
303
+ oAppComponent: any,
304
+ sActionLabel: any,
305
+ mParameters: any,
306
+ aActionParameters: any,
307
+ oActionContext: any,
308
+ oParentControl: any,
309
+ entitySetName: any,
310
+ messageHandler: any
311
+ ) {
312
+ const sPath = _getPath(oActionContext, sActionName),
313
+ metaModel = oActionContext.getModel().oModel.getMetaModel(),
314
+ entitySetContext = metaModel.createBindingContext(sPath),
315
+ sActionNamePath = oActionContext.getObject("$IsBound")
316
+ ? oActionContext.getPath().split("/@$ui5.overload/0")[0]
317
+ : oActionContext.getPath().split("/0")[0],
318
+ actionNameContext = metaModel.createBindingContext(sActionNamePath),
319
+ sFragmentName = "sap/fe/core/controls/ActionParameterDialog";
320
+ return new Promise(function(resolve: (value: any) => void, reject: (reason?: any) => void) {
321
+ const oFragment = XMLTemplateProcessor.loadTemplate(sFragmentName, "fragment");
322
+ const oParameterModel = new JSONModel({
323
+ $displayMode: {}
324
+ });
325
+ let aFieldInvalid: any[] = [];
326
+ let aFormElements: any[] = [];
327
+ const mFieldValueMap: any = {};
328
+ const validateRequiredProperties = function() {
329
+ return Promise.all(
330
+ aFormElements
331
+ .filter(function(oFormElement: any) {
332
+ const oField = oFormElement.getFields()[0];
333
+ return oField.getRequired() && oField.getValueState() !== "Error";
334
+ })
335
+ .map(function(oFormElement: any) {
336
+ const value = oFormElement.getFields()[0].isA("sap.ui.mdc.MultiValueField")
337
+ ? oFormElement.getFields()[0].getItems()
338
+ : oFormElement.getFields()[0].getValue();
339
+ if (value === undefined || value === null || value === "") {
340
+ return oFormElement.getLabel().getText();
341
+ }
342
+ })
343
+ ).then(function(aResults: any[]) {
344
+ aResults = aResults.filter(function(result: any) {
345
+ return result !== undefined;
346
+ });
347
+ return aResults;
348
+ });
349
+ };
350
+ const _validateMessages = function(aActionParameters: any, aFieldInvalid: any, bClearTarget?: boolean) {
351
+ const oMessageManager = sap.ui.getCore().getMessageManager();
352
+ const aMessages = oMessageManager.getMessageModel().getData();
353
+
354
+ aFieldInvalid = aFieldInvalid || [];
355
+
356
+ aActionParameters.forEach(function(oActionParameters: any) {
357
+ const sParameter = oActionParameters.$Name;
358
+ aMessages.forEach(function(oMessage: any) {
359
+ const sParam = sParameter.replace("-inner", "");
360
+ if (
361
+ oMessage.controlIds.length > 0 &&
362
+ (oMessage.getControlId().includes("APD_::" + sParameter) ||
363
+ (oMessage.getControlId().includes("APD_::" + sParameter + "inner") &&
364
+ aFieldInvalid.indexOf("APD_::" + sParam) < 0))
365
+ ) {
366
+ if (bClearTarget) {
367
+ oMessageManager.removeMessages(oMessage);
368
+ } else {
369
+ aFieldInvalid.push("APD_::" + sParam);
370
+ }
371
+ }
372
+ // Handle messages related to input with invalid token
373
+ if (oMessage.target.includes("APD_::" + sParameter)) {
374
+ aFieldInvalid.push("APD_::" + sParam);
375
+ oMessage.target = bClearTarget ? "" : oMessage.target;
376
+ if (bClearTarget) {
377
+ oMessageManager.removeMessages(oMessage);
378
+ }
379
+ }
380
+ });
381
+ });
382
+ return aFieldInvalid;
383
+ };
384
+ const oController = {
385
+ handleChange: function(oEvent: any) {
386
+ messageHandler.removeTransitionMessages();
387
+ const oField = oEvent.getSource();
388
+ const sFieldId = oEvent.getParameter("id");
389
+ const oFieldPromise = oEvent.getParameter("promise");
390
+ if (oFieldPromise) {
391
+ mFieldValueMap[sFieldId] = oFieldPromise.then(function() {
392
+ return oField.getValue();
393
+ });
394
+ }
395
+ _validateMessages(aActionParameters, aFieldInvalid);
396
+ }
397
+ };
398
+
399
+ return Promise.resolve(
400
+ XMLPreprocessor.process(
401
+ oFragment,
402
+ { name: sFragmentName },
403
+ {
404
+ bindingContexts: {
405
+ action: oActionContext,
406
+ actionName: actionNameContext,
407
+ entitySet: entitySetContext
408
+ },
409
+ models: {
410
+ action: oActionContext.getModel(),
411
+ actionName: actionNameContext.getModel(),
412
+ entitySet: entitySetContext.getModel(),
413
+ metaModel: entitySetContext.getModel()
414
+ }
415
+ }
416
+ )
417
+ )
418
+ .then(function(oFragment: any) {
419
+ // TODO: move the dialog into the fragment and move the handlers to the oController
420
+ let aContexts: any[];
421
+ const aFunctionParams: any[] = [];
422
+ let oOperationBinding: any;
423
+ return CommonUtils.setUserDefaults(oAppComponent, aActionParameters, oParameterModel, true).then(function() {
424
+ // TODO: move the dialog into the fragment and move the handlers to the oController
425
+ return Fragment.load({ definition: oFragment, controller: oController }).then(function(oDialogContent: any) {
426
+ const oResourceBundle = oParentControl.getController().oResourceBundle;
427
+ const oDialog = new Dialog(undefined, {
428
+ title:
429
+ sActionLabel ||
430
+ CommonUtils.getTranslatedText("C_OPERATIONS_ACTION_PARAMETER_DIALOG_TITLE", oResourceBundle),
431
+ content: [oDialogContent],
432
+ escapeHandler: function() {
433
+ oDialog.close();
434
+ messageHandler.removeTransitionMessages();
435
+ reject();
436
+ },
437
+ beginButton: new Button(generate(["fe", "APD_", sActionName, "Action", "Ok"]), {
438
+ text: sActionLabel || CommonUtils.getTranslatedText("C_COMMON_DIALOG_OK", oResourceBundle),
439
+ type: "Emphasized",
440
+ press: function() {
441
+ validateRequiredProperties()
442
+ .then(function(aEmptyMandatoryFields: any[]) {
443
+ if (aEmptyMandatoryFields.length) {
444
+ const oMessages = [];
445
+ for (let i = 0; i < aEmptyMandatoryFields.length; i++) {
446
+ oMessages.push({
447
+ text: CommonUtils.getTranslatedText(
448
+ "C_OPERATIONS_ACTION_PARAMETER_DIALOG_MISSING_MANDATORY_MSG",
449
+ oResourceBundle,
450
+ aEmptyMandatoryFields[i]
451
+ ),
452
+ code: 200,
453
+ type: "Error"
454
+ });
455
+ }
456
+ messageHandler.showMessageDialog({
457
+ customMessages: oMessages
458
+ });
459
+ return;
460
+ }
461
+
462
+ aFieldInvalid = _validateMessages(aActionParameters, aFieldInvalid);
463
+
464
+ if (aFieldInvalid.length > 0) {
465
+ return messageHandling.showUnboundMessages();
466
+ }
467
+ BusyLocker.lock(oDialog);
468
+ return Promise.all(
469
+ Object.keys(mFieldValueMap).map(function(sKey: string) {
470
+ return mFieldValueMap[sKey];
471
+ })
472
+ )
473
+ .then(function() {
474
+ // TODO: due to using the search and value helps on the action dialog transient messages could appear
475
+ // we need an UX design for those to show them to the user - for now remove them before continuing
476
+ messageHandler.removeTransitionMessages();
477
+ // move parameter values from Dialog (SimpleForm) to mParameters.actionParameters so that they are available in the operation bindings for all contexts
478
+ let vParameterValue;
479
+ const oParameterContext = oOperationBinding && oOperationBinding.getParameterContext();
480
+ for (const i in aActionParameters) {
481
+ if (aActionParameters[i].$isCollection) {
482
+ const aMVFContent = oDialog
483
+ .getModel("mvfview")
484
+ .getProperty("/" + aActionParameters[i].$Name),
485
+ aKeyValues = [];
486
+ for (const j in aMVFContent) {
487
+ aKeyValues.push(aMVFContent[j].Key);
488
+ }
489
+ vParameterValue = aKeyValues;
490
+ } else {
491
+ vParameterValue = oParameterContext.getProperty(aActionParameters[i].$Name);
492
+ }
493
+ aActionParameters[i].value = vParameterValue;
494
+ vParameterValue = undefined;
495
+ }
496
+ return _executeAction(oAppComponent, mParameters)
497
+ .then(function(oOperation: any) {
498
+ oDialog.close();
499
+ resolve(oOperation);
500
+ })
501
+ .catch(function(oError: any) {
502
+ throw oError;
503
+ });
504
+ })
505
+ .catch(function() {
506
+ const oMessageManager = sap.ui.getCore().getMessageManager();
507
+ const bHasEtagMessage = messageHandling.modifyETagMessagesOnly(
508
+ oMessageManager,
509
+ oResourceBundle
510
+ );
511
+
512
+ messageHandler.showMessages({
513
+ bHasEtagMessage: bHasEtagMessage,
514
+ context: mParameters.aContexts[0],
515
+ isActionParameterDialogOpen: true,
516
+ messagePageNavigationCallback: function() {
517
+ oDialog.close();
518
+ }
519
+ });
520
+ if (oDialog && bHasEtagMessage) {
521
+ oDialog.close(); //close the action parameter dialog after refresh of the context after etag mismatch
522
+ }
523
+ })
524
+ .finally(function() {
525
+ BusyLocker.unlock(oDialog);
526
+ });
527
+ })
528
+ .catch(function() {
529
+ return messageHandler.showMessageDialog();
530
+ });
531
+ }
532
+ }),
533
+ endButton: new Button(generate(["fe", "APD_", sActionName, "Action", "Cancel"]), {
534
+ text: CommonUtils.getTranslatedText("C_COMMON_ACTION_PARAMETER_DIALOG_CANCEL", oResourceBundle),
535
+ press: function() {
536
+ _validateMessages(aActionParameters, aFieldInvalid, true);
537
+ oDialog.close();
538
+ messageHandler.removeTransitionMessages();
539
+ reject(Constants.CancelActionDialog);
540
+ }
541
+ }),
542
+ beforeOpen: function(oEvent: any) {
543
+ // clone event for actionWrapper as oEvent.oSource gets lost during processing of beforeOpen event handler
544
+ const oCloneEvent = Object.assign({}, oEvent);
545
+
546
+ messageHandler.removeTransitionMessages();
547
+ const getDefaultValuesFunction = function() {
548
+ const oMetaModel = oDialog.getModel().getMetaModel(),
549
+ sActionPath = oActionContext.sPath && oActionContext.sPath.split("/@")[0],
550
+ sDefaultValuesFunction = oMetaModel.getObject(
551
+ sActionPath + "@com.sap.vocabularies.Common.v1.DefaultValuesFunction"
552
+ );
553
+ return sDefaultValuesFunction;
554
+ };
555
+ const fnSetDefaultsAndOpenDialog = function(sBindingParameter?: any) {
556
+ const sBoundFunctionName = getDefaultValuesFunction();
557
+ const prefillParameter = function(sParamName: any, vParamDefaultValue: any) {
558
+ return new Promise(resolve => {
559
+ // Case 1: There is a ParameterDefaultValue annotation
560
+ if (vParamDefaultValue !== undefined) {
561
+ if (aContexts.length > 0 && vParamDefaultValue.$Path) {
562
+ const oPromise = CommonUtils.requestSingletonProperty(
563
+ vParamDefaultValue.$Path,
564
+ oOperationBinding.getModel()
565
+ );
566
+ oPromise
567
+ .then(function(oValue: any) {
568
+ if (oValue === null) {
569
+ return oOperationBinding
570
+ .getParameterContext()
571
+ .requestProperty(vParamDefaultValue.$Path);
572
+ }
573
+ return oValue;
574
+ })
575
+ .then(function(vParamValue: any) {
576
+ if (aContexts.length > 1) {
577
+ // For multi select, need to loop over aContexts (as contexts cannot be retrieved via binding parameter of the operation binding)
578
+ let sPathForContext = vParamDefaultValue.$Path;
579
+ if (sPathForContext.indexOf(sBindingParameter + "/") === 0) {
580
+ sPathForContext = sPathForContext.replace(sBindingParameter + "/", "");
581
+ }
582
+ for (let i = 1; i < aContexts.length; i++) {
583
+ if (aContexts[i].getProperty(sPathForContext) !== vParamValue) {
584
+ // if the values from the contexts are not all the same, do not prefill
585
+ resolve({
586
+ paramName: sParamName,
587
+ value: undefined,
588
+ bNoPossibleValue: true
589
+ });
590
+ }
591
+ }
592
+ }
593
+ resolve({ paramName: sParamName, value: vParamValue });
594
+ })
595
+ .catch(function() {
596
+ // Simply clear parameter default if an error has occurred
597
+ Log.error(
598
+ "Error while reading default action parameter",
599
+ sParamName,
600
+ mParameters.actionName
601
+ );
602
+ resolve({
603
+ paramName: sParamName,
604
+ value: undefined,
605
+ bLatePropertyError: true
606
+ });
607
+ });
608
+ } else {
609
+ // Case 1.2: ParameterDefaultValue defines a fixed string value (i.e. vParamDefaultValue = 'someString')
610
+ resolve({ paramName: sParamName, value: vParamDefaultValue });
611
+ }
612
+ } else {
613
+ // Case 2: There is no ParameterDefaultValue annotation (=> look into the FLP User Defaults)
614
+ if (oParameterModel && (oParameterModel as any).oData[sParamName]) {
615
+ resolve({
616
+ paramName: sParamName,
617
+ value: (oParameterModel as any).oData[sParamName]
618
+ });
619
+ } else {
620
+ resolve({ paramName: sParamName, value: undefined });
621
+ }
622
+ }
623
+ });
624
+ };
625
+
626
+ const getParameterDefaultValue = function(sParamName: any) {
627
+ const oMetaModel = oDialog.getModel().getMetaModel(),
628
+ sActionPath = oActionContext.sPath && oActionContext.sPath.split("/@")[0],
629
+ sActionParameterAnnotationTarget = sActionPath + "/" + sParamName + "@",
630
+ oParameterAnnotations = oMetaModel.getObject(sActionParameterAnnotationTarget),
631
+ oParameterDefaultValue =
632
+ oParameterAnnotations &&
633
+ oParameterAnnotations["@com.sap.vocabularies.UI.v1.ParameterDefaultValue"]; // either { $Path: 'somePath' } or 'someString'
634
+ return oParameterDefaultValue;
635
+ };
636
+
637
+ const aCurrentParamDefaultValue = [];
638
+ let sParamName, vParameterDefaultValue;
639
+ for (const i in aActionParameters) {
640
+ sParamName = aActionParameters[i].$Name;
641
+ vParameterDefaultValue = getParameterDefaultValue(sParamName);
642
+ aCurrentParamDefaultValue.push(prefillParameter(sParamName, vParameterDefaultValue));
643
+ }
644
+
645
+ if (oActionContext.getObject("$IsBound") && aContexts.length > 0) {
646
+ if (sBoundFunctionName && sBoundFunctionName.length > 0 && typeof sBoundFunctionName === "string") {
647
+ for (const i in aContexts) {
648
+ aFunctionParams.push(
649
+ callBoundFunction(sBoundFunctionName, aContexts[i], mParameters.model)
650
+ );
651
+ }
652
+ }
653
+ }
654
+
655
+ const aPrefillParamPromises = Promise.all(aCurrentParamDefaultValue);
656
+ let aExecFunctionPromises: Promise<any[]> = Promise.resolve([]);
657
+ let oExecFunctionFromManifestPromise;
658
+ if (aFunctionParams && aFunctionParams.length > 0) {
659
+ aExecFunctionPromises = Promise.all(aFunctionParams);
660
+ }
661
+ if (mParameters.defaultValuesExtensionFunction) {
662
+ const sModule = mParameters.defaultValuesExtensionFunction
663
+ .substring(0, mParameters.defaultValuesExtensionFunction.lastIndexOf(".") || -1)
664
+ .replace(/\./gi, "/"),
665
+ sFunctionName = mParameters.defaultValuesExtensionFunction.substring(
666
+ mParameters.defaultValuesExtensionFunction.lastIndexOf(".") + 1,
667
+ mParameters.defaultValuesExtensionFunction.length
668
+ );
669
+ oExecFunctionFromManifestPromise = FPMHelper.actionWrapper(oCloneEvent, sModule, sFunctionName, {
670
+ "contexts": aContexts
671
+ });
672
+ }
673
+
674
+ Promise.all([aPrefillParamPromises, aExecFunctionPromises, oExecFunctionFromManifestPromise])
675
+ .then(function(aPromises: [any[], any[], any]) {
676
+ const aCurrentParamDefaultValue: any = aPromises[0];
677
+ const aFunctionParams = aPromises[1];
678
+ const oFunctionParamsFromManifest = aPromises[2];
679
+ let sDialogParamName;
680
+ for (const i in aActionParameters) {
681
+ sDialogParamName = aActionParameters[i].$Name;
682
+ if (
683
+ oFunctionParamsFromManifest &&
684
+ oFunctionParamsFromManifest.hasOwnProperty(sDialogParamName)
685
+ ) {
686
+ oOperationBinding.setParameter(
687
+ aActionParameters[i].$Name,
688
+ oFunctionParamsFromManifest[sDialogParamName]
689
+ );
690
+ } else if (
691
+ aCurrentParamDefaultValue[i] &&
692
+ aCurrentParamDefaultValue[i].value !== undefined
693
+ ) {
694
+ oOperationBinding.setParameter(
695
+ aActionParameters[i].$Name,
696
+ aCurrentParamDefaultValue[i].value
697
+ );
698
+ // if the default value had not been previously determined due to different contexts, we do nothing else
699
+ } else if (sBoundFunctionName && !aCurrentParamDefaultValue[i].bNoPossibleValue) {
700
+ if (aContexts.length > 1) {
701
+ // we check if the function retrieves the same param value for all the contexts:
702
+ let j = 0;
703
+ while (j < aContexts.length - 1) {
704
+ if (
705
+ aFunctionParams[j] &&
706
+ aFunctionParams[j + 1] &&
707
+ aFunctionParams[j].getObject(sDialogParamName) ===
708
+ aFunctionParams[j + 1].getObject(sDialogParamName)
709
+ ) {
710
+ j++;
711
+ } else {
712
+ break;
713
+ }
714
+ }
715
+ //param values are all the same:
716
+ if (j === aContexts.length - 1) {
717
+ oOperationBinding.setParameter(
718
+ aActionParameters[i].$Name,
719
+ aFunctionParams[j].getObject(sDialogParamName)
720
+ );
721
+ }
722
+ } else {
723
+ //Only one context, then the default param values are to be verified from the function:
724
+
725
+ if (aFunctionParams[0] && aFunctionParams[0].getObject(sDialogParamName)) {
726
+ oOperationBinding.setParameter(
727
+ aActionParameters[i].$Name,
728
+ aFunctionParams[0].getObject(sDialogParamName)
729
+ );
730
+ }
731
+ }
732
+ }
733
+ }
734
+ const bErrorFound = aCurrentParamDefaultValue.some(function(oValue: any) {
735
+ if (oValue.bLatePropertyError) {
736
+ return oValue.bLatePropertyError;
737
+ }
738
+ });
739
+ // If at least one Default Property is a Late Property and an eTag error was raised.
740
+ if (bErrorFound) {
741
+ const sText = CommonUtils.getTranslatedText(
742
+ "C_APP_COMPONENT_SAPFE_ETAG_LATE_PROPERTY",
743
+ oResourceBundle
744
+ );
745
+ MessageBox.warning(sText, { contentWidth: "25em" } as any);
746
+ }
747
+ })
748
+ .catch();
749
+ };
750
+
751
+ if (oActionContext.getObject("$IsBound") && aContexts.length > 0) {
752
+ const aParameters = oActionContext.getObject("$Parameter"),
753
+ sBindingParameter = aParameters[0] && aParameters[0].$Name;
754
+ aContexts[0]
755
+ .requestObject()
756
+ .then(function(oContextObject: any) {
757
+ if (oContextObject) {
758
+ oOperationBinding.setParameter(sBindingParameter, oContextObject);
759
+ }
760
+ fnSetDefaultsAndOpenDialog(sBindingParameter);
761
+ })
762
+ .catch(function(oError: any) {
763
+ Log.error("Error while retrieving the parameter", oError);
764
+ });
765
+ } else {
766
+ fnSetDefaultsAndOpenDialog();
767
+ }
768
+ },
769
+ afterClose: function() {
770
+ oDialog.destroy();
771
+ }
772
+ });
773
+ aFormElements = oDialogContent
774
+ .getAggregation("form")
775
+ .getAggregation("formContainers")[0]
776
+ .getAggregation("formElements");
777
+ oDialog.setModel(oActionContext.getModel().oModel);
778
+ oDialog.setModel(oParameterModel, "paramsModel");
779
+ oDialog.bindElement({
780
+ path: "/",
781
+ model: "paramsModel"
782
+ });
783
+ // empty model to add elements dynamically depending on number of MVF fields defined on the dialog
784
+ const oMVFModel = new JSONModel({});
785
+ oDialog.setModel(oMVFModel, "mvfview");
786
+
787
+ let sActionPath = sActionName + "(...)";
788
+ aContexts = mParameters.aContexts || [];
789
+ if (!aContexts.length) {
790
+ sActionPath = "/" + sActionPath;
791
+ }
792
+ oDialog.bindElement({
793
+ path: sActionPath
794
+ });
795
+ if (oParentControl) {
796
+ // if there is a parent control specified add the dialog as dependent
797
+ oParentControl.addDependent(oDialog);
798
+ }
799
+ if (aContexts.length > 0) {
800
+ oDialog.setBindingContext(aContexts[0]); // use context of first selected line item
801
+ }
802
+ oOperationBinding = oDialog.getObjectBinding();
803
+ oDialog.open();
804
+ });
805
+ });
806
+ })
807
+ .catch(reject);
808
+ });
809
+ }
810
+ function prepareActionParameters(oAction: any, aPredefinedParameters: any) {
811
+ // check if parameters exist at all
812
+ const aParameters = getActionParameters(oAction);
813
+ aPredefinedParameters = aPredefinedParameters || [];
814
+
815
+ if (aPredefinedParameters.length > 0) {
816
+ // TODO: merge the predefined once with the real existing one
817
+ }
818
+
819
+ return aParameters;
820
+ }
821
+ function getActionParameters(oAction: any) {
822
+ const aParameters = oAction.getObject("$Parameter") || [];
823
+ if (aParameters && aParameters.length) {
824
+ if (oAction.getObject("$IsBound")) {
825
+ //in case of bound actions, ignore the first parameter and consider the rest
826
+ return aParameters.slice(1, aParameters.length) || [];
827
+ }
828
+ }
829
+ return aParameters;
830
+ }
831
+ function getIsActionCritical(oMetaModel: any, sPath: any, contexts?: any, oBoundAction?: any) {
832
+ const vActionCritical = oMetaModel.getObject(sPath + "@com.sap.vocabularies.Common.v1.IsActionCritical");
833
+ let sCriticalPath = vActionCritical && vActionCritical.$Path;
834
+ if (!sCriticalPath) {
835
+ // the static value scenario for isActionCritical
836
+ return !!vActionCritical;
837
+ }
838
+ const aBindingParams = oBoundAction && oBoundAction.getObject("$Parameter"),
839
+ aPaths = sCriticalPath && sCriticalPath.split("/"),
840
+ bCondition =
841
+ aBindingParams && aBindingParams.length && typeof aBindingParams === "object" && sCriticalPath && contexts && contexts.length;
842
+ if (bCondition) {
843
+ //in case binding patameters are there in path need to remove eg: - _it/isVerified => need to remove _it and the path should be isVerified
844
+ aBindingParams.filter(function(oParams: any) {
845
+ const index = aPaths && aPaths.indexOf(oParams.$Name);
846
+ if (index > -1) {
847
+ aPaths.splice(index, 1);
848
+ }
849
+ });
850
+ sCriticalPath = aPaths.join("/");
851
+ return contexts[0].getObject(sCriticalPath);
852
+ } else if (sCriticalPath) {
853
+ //if scenario is path based return the path value
854
+ return contexts[0].getObject(sCriticalPath);
855
+ }
856
+ }
857
+ function _executeAction(oAppComponent: any, mParameters: any) {
858
+ const aContexts = mParameters.aContexts || [];
859
+ const oModel = mParameters.model;
860
+ const iExistingMessages = messageHandling.getMessages().length || 0;
861
+ const aActionParameters = mParameters.aActionParameters || [];
862
+ const sActionName = mParameters.actionName;
863
+ const fnOnSubmitted = mParameters.fnOnSubmitted;
864
+ const fnOnResponse = mParameters.fnOnResponse;
865
+ const bIsCreateAction = mParameters.bIsCreateAction;
866
+ let bActionParametersExist = false;
867
+ let oAction: any;
868
+
869
+ function fnDifferentiate(promise: any) {
870
+ return promise.then(
871
+ function(response: any) {
872
+ const aMessages = messageHandling.getMessages();
873
+ // Action Dialog must remain open if there are response error-messages, because in the java stack the dialog would be closed immediately.
874
+ if (aMessages.length > iExistingMessages && aMessages[aMessages.length - 1].type === "Error") {
875
+ return { response: response, status: "rejected" };
876
+ }
877
+ return { response: response, status: "resolved" };
878
+ },
879
+ function(response: any) {
880
+ return { response: response, status: "rejected" };
881
+ }
882
+ );
883
+ }
884
+
885
+ function setActionParameterDefaultValue() {
886
+ if (aActionParameters && aActionParameters.length) {
887
+ bActionParametersExist = true;
888
+ for (let j = 0; j < aActionParameters.length; j++) {
889
+ if (!aActionParameters[j].value) {
890
+ switch (aActionParameters[j].$Type) {
891
+ case "Edm.String":
892
+ aActionParameters[j].value = "";
893
+ break;
894
+ case "Edm.Boolean":
895
+ aActionParameters[j].value = false;
896
+ break;
897
+ case "Edm.Byte":
898
+ case "Edm.Int16":
899
+ case "Edm.Int32":
900
+ case "Edm.Int64":
901
+ aActionParameters[j].value = 0;
902
+ break;
903
+ // tbc
904
+ default:
905
+ break;
906
+ }
907
+ }
908
+ oAction.setParameter(aActionParameters[j].$Name, aActionParameters[j].value);
909
+ }
910
+ }
911
+ }
912
+
913
+ if (aContexts.length) {
914
+ return new Promise(function(resolve: (value: any) => void, reject: (reason?: any) => void) {
915
+ const mBindingParameters = mParameters.mBindingParameters;
916
+ const bGrouped = mParameters.bGrouped;
917
+ const bReturnAsArray = mParameters.bReturnAsArray;
918
+ const bGetBoundContext = mParameters.bGetBoundContext;
919
+ const aActionPromises: any[] = [];
920
+ let oActionPromise;
921
+ let i;
922
+ let sGroupId: string;
923
+ const fnExecuteAction = function(oAction: any, index: any, oSideEffect: any) {
924
+ setActionParameterDefaultValue();
925
+ // For invocation grouping "isolated" need batch group per action call
926
+ sGroupId = !bGrouped ? "$auto." + index : oAction.getUpdateGroupId();
927
+ oActionPromise = bGetBoundContext
928
+ ? oAction.execute(sGroupId).then(function() {
929
+ return oAction.getBoundContext();
930
+ })
931
+ : oAction.execute(sGroupId);
932
+ aActionPromises.push(oActionPromise);
933
+ const oSideEffectsService = oAppComponent.getSideEffectsService();
934
+ // trigger actions from side effects
935
+ if (oSideEffect && oSideEffect.triggerActions && oSideEffect.triggerActions.length) {
936
+ oSideEffect.triggerActions.forEach(function(sTriggerAction: any) {
937
+ if (sTriggerAction) {
938
+ oSideEffectsService.executeAction(sTriggerAction, oSideEffect.context, sGroupId);
939
+ }
940
+ });
941
+ }
942
+ // request side effects for this action
943
+ // as we move the messages request to POST $select we need to be prepared for an empty array
944
+ if (oSideEffect && oSideEffect.pathExpressions && oSideEffect.pathExpressions.length > 0) {
945
+ oSideEffectsService
946
+ .requestSideEffects(oSideEffect.pathExpressions, oSideEffect.context, sGroupId)
947
+ .then(function() {
948
+ if (mParameters.operationAvailableMap && mParameters.internalModelContext) {
949
+ CommonUtils.setActionEnablement(
950
+ mParameters.internalModelContext,
951
+ JSON.parse(mParameters.operationAvailableMap),
952
+ mParameters.aContexts
953
+ );
954
+ }
955
+ })
956
+ .catch(function(oError: any) {
957
+ Log.error("Error while requesting side effects", oError);
958
+ });
959
+ }
960
+ };
961
+ const fnExecuteSingleAction = function(oAction: any, index: any, oSideEffect: any) {
962
+ const oPromise = new Promise<void>(resolve => {
963
+ let oLocalPromise;
964
+ const aLocalPromise = [];
965
+ setActionParameterDefaultValue();
966
+ // For invocation grouping "isolated" need batch group per action call
967
+ sGroupId = "apiMode" + index;
968
+ oActionPromise = bGetBoundContext
969
+ ? oAction.execute(sGroupId).then(function() {
970
+ return oAction.getBoundContext();
971
+ })
972
+ : oAction.execute(sGroupId);
973
+
974
+ aActionPromises.push(oActionPromise);
975
+ aLocalPromise.push(oActionPromise);
976
+ const oSideEffectsService = oAppComponent.getSideEffectsService();
977
+ // trigger actions from side effects
978
+ if (oSideEffect && oSideEffect.triggerActions && oSideEffect.triggerActions.length) {
979
+ oSideEffect.triggerActions.forEach(function(sTriggerAction: any) {
980
+ if (sTriggerAction) {
981
+ oLocalPromise = oSideEffectsService.executeAction(sTriggerAction, oSideEffect.context, sGroupId);
982
+ aLocalPromise.push(oLocalPromise);
983
+ }
984
+ });
985
+ }
986
+ // request side effects for this action
987
+ // as we move the messages request to POST $select we need to be prepared for an empty array
988
+ if (oSideEffect && oSideEffect.pathExpressions && oSideEffect.pathExpressions.length > 0) {
989
+ oLocalPromise = oSideEffectsService.requestSideEffects(oSideEffect.pathExpressions, oSideEffect.context, sGroupId);
990
+ aLocalPromise.push(oLocalPromise);
991
+ oLocalPromise
992
+ .then(function() {
993
+ if (mParameters.operationAvailableMap && mParameters.internalModelContext) {
994
+ CommonUtils.setActionEnablement(
995
+ mParameters.internalModelContext,
996
+ JSON.parse(mParameters.operationAvailableMap),
997
+ mParameters.aContexts
998
+ );
999
+ }
1000
+ })
1001
+ .catch(function(oError: any) {
1002
+ Log.error("Error while requesting side effects", oError);
1003
+ });
1004
+ }
1005
+ oModel.submitBatch(sGroupId);
1006
+ Promise.all(aLocalPromise)
1007
+ .then(function() {
1008
+ return resolve();
1009
+ })
1010
+ .catch(function() {
1011
+ return resolve();
1012
+ });
1013
+ });
1014
+ return oPromise;
1015
+ };
1016
+
1017
+ function fnExecuteSequentially(aContexts: any) {
1018
+ // One action and its side effects are completed before the next action is executed
1019
+ (
1020
+ fnOnSubmitted ||
1021
+ function noop() {
1022
+ /**/
1023
+ }
1024
+ )(aActionPromises);
1025
+ function processOneAction(context: any, i: any) {
1026
+ oAction = oModel.bindContext(sActionName + "(...)", context, mBindingParameters);
1027
+ return fnExecuteSingleAction(oAction, i, {
1028
+ context: context,
1029
+ pathExpressions: mParameters.additionalSideEffect && mParameters.additionalSideEffect.pathExpressions,
1030
+ triggerActions: mParameters.additionalSideEffect && mParameters.additionalSideEffect.triggerActions
1031
+ });
1032
+ }
1033
+
1034
+ let oActionAndSideEffectPromise = Promise.resolve();
1035
+ let j = 0;
1036
+ aContexts.forEach(function(context: any) {
1037
+ const id = ++j;
1038
+ oActionAndSideEffectPromise = oActionAndSideEffectPromise.then(function() {
1039
+ return processOneAction(context, id);
1040
+ });
1041
+ });
1042
+ oActionAndSideEffectPromise
1043
+ .then(function() {
1044
+ fnHandleResults();
1045
+ })
1046
+ .catch();
1047
+ }
1048
+
1049
+ if (mParameters.bObjectPage && !bGrouped) {
1050
+ // For invocation grouping "isolated" called from ObjectPage, ensure that each action and matching side effects
1051
+ // are processed before the next set is submitted. Workaround until JSON batch is available.
1052
+ fnExecuteSequentially(aContexts);
1053
+ } else {
1054
+ for (i = 0; i < aContexts.length; i++) {
1055
+ oAction = oModel.bindContext(sActionName + "(...)", aContexts[i], mBindingParameters);
1056
+ fnExecuteAction(oAction, aContexts.length <= 1 ? null : i, {
1057
+ context: aContexts[i],
1058
+ pathExpressions: mParameters.additionalSideEffect && mParameters.additionalSideEffect.pathExpressions,
1059
+ triggerActions: mParameters.additionalSideEffect && mParameters.additionalSideEffect.triggerActions
1060
+ });
1061
+ }
1062
+ (
1063
+ fnOnSubmitted ||
1064
+ function noop() {
1065
+ /**/
1066
+ }
1067
+ )(aActionPromises);
1068
+ fnHandleResults();
1069
+ }
1070
+
1071
+ function fnHandleResults() {
1072
+ Promise.all(aActionPromises.map(fnDifferentiate))
1073
+ .then(function(results: any[]) {
1074
+ const aRejectedItems = [];
1075
+ const aResolvedItems = [];
1076
+ let iResultCount;
1077
+ for (iResultCount = 0; iResultCount < results.length; iResultCount++) {
1078
+ if (results[iResultCount].status === "rejected") {
1079
+ aRejectedItems.push(results[iResultCount].response);
1080
+ }
1081
+ if (results[iResultCount].status === "resolved") {
1082
+ if (bIsCreateAction && bActionParametersExist) {
1083
+ //only used for NewAction
1084
+ results[iResultCount].bConsiderDocumentModified = true;
1085
+ aResolvedItems.push(results[iResultCount]);
1086
+ } else {
1087
+ aResolvedItems.push(results[iResultCount].response);
1088
+ }
1089
+ }
1090
+ }
1091
+ if (!results || (results && results.length === 0)) {
1092
+ reject(true);
1093
+ }
1094
+ if (aRejectedItems.length === 0) {
1095
+ if (bReturnAsArray) {
1096
+ resolve(aResolvedItems);
1097
+ } else {
1098
+ // context is given directly without an array so also no array is expected
1099
+ resolve(aResolvedItems[0]);
1100
+ }
1101
+ } else {
1102
+ reject({
1103
+ resolvedItems: aResolvedItems,
1104
+ rejectedItems: aRejectedItems
1105
+ });
1106
+ }
1107
+ })
1108
+ .catch(reject);
1109
+ }
1110
+ }).finally(function() {
1111
+ (
1112
+ fnOnResponse ||
1113
+ function noop() {
1114
+ /**/
1115
+ }
1116
+ )();
1117
+ });
1118
+ } else {
1119
+ oAction = oModel.bindContext("/" + sActionName + "(...)");
1120
+ setActionParameterDefaultValue();
1121
+ const oActionPromise = oAction.execute("actionImport");
1122
+ oModel.submitBatch("actionImport");
1123
+ // trigger onSubmitted "event"
1124
+ (
1125
+ fnOnSubmitted ||
1126
+ function noop() {
1127
+ /**/
1128
+ }
1129
+ )(oActionPromise);
1130
+ return oActionPromise.finally(function() {
1131
+ (
1132
+ fnOnResponse ||
1133
+ function noop() {
1134
+ /**/
1135
+ }
1136
+ )();
1137
+ });
1138
+ }
1139
+ }
1140
+ function _getPath(oActionContext: any, sActionName: any) {
1141
+ let sPath = oActionContext.getPath();
1142
+ sPath = oActionContext.getObject("$IsBound") ? sPath.split("@$ui5.overload")[0] : sPath.split("/0")[0];
1143
+ return sPath.split("/" + sActionName)[0];
1144
+ }
1145
+
1146
+ /**
1147
+ * Static functions to call OData actions (bound/import) and functions (bound/import)
1148
+ *
1149
+ * @namespace
1150
+ * @alias sap.fe.core.actions.operations
1151
+ * @private
1152
+ * @experimental This module is only for experimental use! <br/><b>This is only a POC and maybe deleted</b>
1153
+ * @since 1.56.0
1154
+ */
1155
+ const operations = {
1156
+ callBoundAction: callBoundAction,
1157
+ callActionImport: callActionImport,
1158
+ callBoundFunction: callBoundFunction,
1159
+ callFunctionImport: callFunctionImport
1160
+ };
1161
+
1162
+ export default operations;