@sapui5/sap.fe.core 1.97.0 → 1.100.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 (306) hide show
  1. package/package.json +7 -4
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AnnotationHelper.js +309 -405
  4. package/src/sap/fe/core/AnnotationHelper.ts +315 -0
  5. package/src/sap/fe/core/AppComponent.js +389 -397
  6. package/src/sap/fe/core/AppComponent.ts +403 -0
  7. package/src/sap/fe/core/AppStateHandler.js +198 -181
  8. package/src/sap/fe/core/AppStateHandler.ts +171 -0
  9. package/src/sap/fe/core/BaseController.js +83 -58
  10. package/src/sap/fe/core/BaseController.ts +68 -0
  11. package/src/sap/fe/core/BusyLocker.js +105 -121
  12. package/src/sap/fe/core/BusyLocker.ts +98 -0
  13. package/src/sap/fe/core/CommonUtils.js +2164 -2379
  14. package/src/sap/fe/core/CommonUtils.ts +2177 -0
  15. package/src/sap/fe/core/ExtensionAPI.js +279 -266
  16. package/src/sap/fe/core/ExtensionAPI.ts +250 -0
  17. package/src/sap/fe/core/PageController.js +218 -125
  18. package/src/sap/fe/core/PageController.ts +129 -0
  19. package/src/sap/fe/core/RouterProxy.js +924 -807
  20. package/src/sap/fe/core/RouterProxy.ts +840 -0
  21. package/src/sap/fe/core/Synchronization.js +41 -35
  22. package/src/sap/fe/core/Synchronization.ts +29 -0
  23. package/src/sap/fe/core/TemplateComponent.js +173 -155
  24. package/src/sap/fe/core/TemplateComponent.ts +173 -0
  25. package/src/sap/fe/core/TemplateModel.js +79 -54
  26. package/src/sap/fe/core/TemplateModel.ts +63 -0
  27. package/src/sap/fe/core/TransactionHelper.js +1560 -1579
  28. package/src/sap/fe/core/TransactionHelper.ts +1717 -0
  29. package/src/sap/fe/core/actions/collaboration/ActivitySync.js +392 -0
  30. package/src/sap/fe/core/actions/collaboration/ActivitySync.ts +355 -0
  31. package/src/sap/fe/core/actions/collaboration/CollaborationCommon.js +136 -0
  32. package/src/sap/fe/core/actions/collaboration/CollaborationCommon.ts +119 -0
  33. package/src/sap/fe/core/actions/collaboration/Manage.js +262 -0
  34. package/src/sap/fe/core/actions/collaboration/Manage.ts +244 -0
  35. package/src/sap/fe/core/actions/collaboration/ManageDialog.fragment.xml +103 -0
  36. package/src/sap/fe/core/actions/collaboration/UserDetails.fragment.xml +13 -0
  37. package/src/sap/fe/core/actions/draft.js +521 -581
  38. package/src/sap/fe/core/actions/draft.ts +566 -0
  39. package/src/sap/fe/core/actions/messageHandling.js +564 -511
  40. package/src/sap/fe/core/actions/messageHandling.ts +552 -0
  41. package/src/sap/fe/core/actions/nonDraft.js +17 -19
  42. package/src/sap/fe/core/actions/nonDraft.ts +12 -0
  43. package/src/sap/fe/core/actions/operations.js +1093 -1211
  44. package/src/sap/fe/core/actions/operations.ts +1192 -0
  45. package/src/sap/fe/core/actions/sticky.js +114 -104
  46. package/src/sap/fe/core/actions/sticky.ts +119 -0
  47. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +70 -66
  48. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.ts +65 -0
  49. package/src/sap/fe/core/controllerextensions/EditFlow.js +1594 -1701
  50. package/src/sap/fe/core/controllerextensions/EditFlow.ts +1672 -0
  51. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +80 -54
  52. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.ts +61 -0
  53. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +719 -505
  54. package/src/sap/fe/core/controllerextensions/InternalEditFlow.ts +783 -0
  55. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +797 -813
  56. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.ts +803 -0
  57. package/src/sap/fe/core/controllerextensions/InternalRouting.js +1005 -973
  58. package/src/sap/fe/core/controllerextensions/InternalRouting.ts +978 -0
  59. package/src/sap/fe/core/controllerextensions/KPIManagement.js +530 -476
  60. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +137 -46
  61. package/src/sap/fe/core/controllerextensions/MassEdit.js +144 -0
  62. package/src/sap/fe/core/controllerextensions/MassEdit.ts +156 -0
  63. package/src/sap/fe/core/controllerextensions/MessageHandler.js +234 -232
  64. package/src/sap/fe/core/controllerextensions/MessageHandler.ts +225 -0
  65. package/src/sap/fe/core/controllerextensions/PageReady.js +302 -337
  66. package/src/sap/fe/core/controllerextensions/PageReady.ts +23 -17
  67. package/src/sap/fe/core/controllerextensions/Paginator.js +189 -148
  68. package/src/sap/fe/core/controllerextensions/Paginator.ts +163 -0
  69. package/src/sap/fe/core/controllerextensions/Placeholder.js +158 -146
  70. package/src/sap/fe/core/controllerextensions/Placeholder.ts +151 -0
  71. package/src/sap/fe/core/controllerextensions/Routing.js +145 -106
  72. package/src/sap/fe/core/controllerextensions/Routing.ts +132 -0
  73. package/src/sap/fe/core/controllerextensions/RoutingListener.js +8 -6
  74. package/src/sap/fe/core/controllerextensions/RoutingListener.ts +3 -0
  75. package/src/sap/fe/core/controllerextensions/Share.js +220 -244
  76. package/src/sap/fe/core/controllerextensions/Share.ts +231 -0
  77. package/src/sap/fe/core/controllerextensions/SideEffects.js +593 -634
  78. package/src/sap/fe/core/controllerextensions/SideEffects.ts +29 -27
  79. package/src/sap/fe/core/controllerextensions/ViewState.js +789 -806
  80. package/src/sap/fe/core/controllerextensions/ViewState.ts +805 -0
  81. package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +4 -3
  82. package/src/sap/fe/core/controls/ActionPartial.fragment.xml +2 -2
  83. package/src/sap/fe/core/controls/CommandExecution.js +68 -66
  84. package/src/sap/fe/core/controls/CommandExecution.ts +72 -0
  85. package/src/sap/fe/core/controls/ConditionalWrapper.js +91 -75
  86. package/src/sap/fe/core/controls/ConditionalWrapper.ts +83 -0
  87. package/src/sap/fe/core/controls/CustomQuickViewPage.js +131 -125
  88. package/src/sap/fe/core/controls/CustomQuickViewPage.ts +126 -0
  89. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +105 -110
  90. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.ts +101 -0
  91. package/src/sap/fe/core/controls/FieldWrapper.js +122 -140
  92. package/src/sap/fe/core/controls/FieldWrapper.ts +115 -0
  93. package/src/sap/fe/core/controls/FilterBar.js +163 -159
  94. package/src/sap/fe/core/controls/FilterBar.ts +143 -0
  95. package/src/sap/fe/core/controls/FormElementWrapper.js +46 -44
  96. package/src/sap/fe/core/controls/FormElementWrapper.ts +40 -0
  97. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +38 -42
  98. package/src/sap/fe/core/controls/MultiValueParameterDelegate.ts +31 -0
  99. package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +2 -1
  100. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +127 -116
  101. package/src/sap/fe/core/controls/filterbar/FilterContainer.ts +98 -0
  102. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +242 -255
  103. package/src/sap/fe/core/controls/filterbar/VisualFilter.ts +245 -0
  104. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +151 -141
  105. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.ts +125 -0
  106. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +336 -322
  107. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.ts +337 -0
  108. package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +106 -0
  109. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +79 -0
  110. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.ts +70 -0
  111. package/src/sap/fe/core/converters/ConverterContext.js +348 -367
  112. package/src/sap/fe/core/converters/ConverterContext.ts +33 -19
  113. package/src/sap/fe/core/converters/ManifestSettings.js +12 -1
  114. package/src/sap/fe/core/converters/ManifestSettings.ts +16 -1
  115. package/src/sap/fe/core/converters/ManifestWrapper.js +354 -354
  116. package/src/sap/fe/core/converters/ManifestWrapper.ts +34 -6
  117. package/src/sap/fe/core/converters/MetaModelConverter.js +72 -9
  118. package/src/sap/fe/core/converters/MetaModelConverter.ts +75 -16
  119. package/src/sap/fe/core/converters/TemplateConverter.js +1 -1
  120. package/src/sap/fe/core/converters/TemplateConverter.ts +4 -3
  121. package/src/sap/fe/core/converters/annotations/DataField.js +28 -14
  122. package/src/sap/fe/core/converters/annotations/DataField.ts +38 -14
  123. package/src/sap/fe/core/converters/common/AnnotationConverter.js +33 -21
  124. package/src/sap/fe/core/converters/controls/Common/Action.js +11 -2
  125. package/src/sap/fe/core/converters/controls/Common/Action.ts +8 -2
  126. package/src/sap/fe/core/converters/controls/Common/Chart.js +5 -3
  127. package/src/sap/fe/core/converters/controls/Common/Chart.ts +11 -3
  128. package/src/sap/fe/core/converters/controls/Common/DataVisualization.js +3 -3
  129. package/src/sap/fe/core/converters/controls/Common/DataVisualization.ts +2 -2
  130. package/src/sap/fe/core/converters/controls/Common/Form.js +21 -11
  131. package/src/sap/fe/core/converters/controls/Common/Form.ts +28 -6
  132. package/src/sap/fe/core/converters/controls/Common/KPI.js +69 -4
  133. package/src/sap/fe/core/converters/controls/Common/KPI.ts +75 -2
  134. package/src/sap/fe/core/converters/controls/Common/Table.js +507 -408
  135. package/src/sap/fe/core/converters/controls/Common/Table.ts +618 -500
  136. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +592 -0
  137. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +718 -0
  138. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +465 -59
  139. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +462 -72
  140. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +2 -2
  141. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +1 -1
  142. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +17 -9
  143. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +24 -9
  144. package/src/sap/fe/core/converters/helpers/Aggregation.js +118 -121
  145. package/src/sap/fe/core/converters/helpers/Aggregation.ts +28 -5
  146. package/src/sap/fe/core/converters/helpers/BindingHelper.js +20 -6
  147. package/src/sap/fe/core/converters/helpers/BindingHelper.ts +16 -4
  148. package/src/sap/fe/core/converters/helpers/ConfigurableObject.js +12 -1
  149. package/src/sap/fe/core/converters/helpers/ConfigurableObject.ts +11 -0
  150. package/src/sap/fe/core/converters/helpers/IssueManager.js +7 -1
  151. package/src/sap/fe/core/converters/helpers/IssueManager.ts +6 -0
  152. package/src/sap/fe/core/converters/helpers/Key.js +42 -57
  153. package/src/sap/fe/core/converters/helpers/Key.ts +1 -1
  154. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +28 -7
  155. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +23 -6
  156. package/src/sap/fe/core/converters/templates/ListReportConverter.js +20 -7
  157. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +36 -14
  158. package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +7 -5
  159. package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +5 -1
  160. package/src/sap/fe/core/designtime/AppComponent.designtime.js +93 -90
  161. package/src/sap/fe/core/designtime/AppComponent.designtime.ts +91 -0
  162. package/src/sap/fe/core/formatters/CollaborationFormatter.js +104 -0
  163. package/src/sap/fe/core/formatters/CollaborationFormatter.ts +60 -0
  164. package/src/sap/fe/core/formatters/CriticalityFormatter.js +1 -1
  165. package/src/sap/fe/core/formatters/CriticalityFormatter.ts +1 -1
  166. package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
  167. package/src/sap/fe/core/formatters/FPMFormatter.ts +4 -10
  168. package/src/sap/fe/core/formatters/KPIFormatter.js +1 -1
  169. package/src/sap/fe/core/formatters/KPIFormatter.ts +3 -1
  170. package/src/sap/fe/core/formatters/TableFormatter.js +91 -29
  171. package/src/sap/fe/core/formatters/TableFormatter.ts +94 -28
  172. package/src/sap/fe/core/formatters/ValueFormatter.js +30 -5
  173. package/src/sap/fe/core/formatters/ValueFormatter.ts +30 -7
  174. package/src/sap/fe/core/fpm/Component.js +51 -54
  175. package/src/sap/fe/core/fpm/Component.ts +48 -0
  176. package/src/sap/fe/core/helpers/AppStartupHelper.js +373 -0
  177. package/src/sap/fe/core/helpers/AppStartupHelper.ts +417 -0
  178. package/src/sap/fe/core/helpers/BindingExpression.js +489 -442
  179. package/src/sap/fe/core/helpers/BindingExpression.ts +486 -469
  180. package/src/sap/fe/core/helpers/ClassSupport.js +212 -76
  181. package/src/sap/fe/core/helpers/ClassSupport.ts +198 -71
  182. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +64 -59
  183. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.ts +52 -0
  184. package/src/sap/fe/core/helpers/EditState.js +81 -84
  185. package/src/sap/fe/core/helpers/EditState.ts +81 -0
  186. package/src/sap/fe/core/helpers/ExcelFormatHelper.js +62 -48
  187. package/src/sap/fe/core/helpers/ExcelFormatHelper.ts +49 -0
  188. package/src/sap/fe/core/helpers/FPMHelper.js +52 -56
  189. package/src/sap/fe/core/helpers/FPMHelper.ts +62 -0
  190. package/src/sap/fe/core/helpers/KeepAliveHelper.js +4 -5
  191. package/src/sap/fe/core/helpers/KeepAliveHelper.ts +10 -10
  192. package/src/sap/fe/core/helpers/MassEditHelper.js +604 -0
  193. package/src/sap/fe/core/helpers/MassEditHelper.ts +699 -0
  194. package/src/sap/fe/core/helpers/ModelHelper.js +253 -225
  195. package/src/sap/fe/core/helpers/ModelHelper.ts +250 -0
  196. package/src/sap/fe/core/helpers/PasteHelper.js +210 -132
  197. package/src/sap/fe/core/helpers/PasteHelper.ts +196 -0
  198. package/src/sap/fe/core/helpers/SemanticDateOperators.js +336 -313
  199. package/src/sap/fe/core/helpers/SemanticDateOperators.ts +334 -0
  200. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +66 -67
  201. package/src/sap/fe/core/helpers/SemanticKeyHelper.ts +73 -0
  202. package/src/sap/fe/core/helpers/StableIdHelper.js +4 -7
  203. package/src/sap/fe/core/helpers/StableIdHelper.ts +2 -6
  204. package/src/sap/fe/core/jsx-runtime/jsx.js +1 -1
  205. package/src/sap/fe/core/jsx-runtime/jsx.ts +1 -1
  206. package/src/sap/fe/core/library.js +427 -425
  207. package/src/sap/fe/core/library.support.js +23 -27
  208. package/src/sap/fe/core/library.support.ts +23 -0
  209. package/src/sap/fe/core/library.ts +420 -0
  210. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +64 -0
  211. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +69 -0
  212. package/src/sap/fe/core/messagebundle.properties +78 -13
  213. package/src/sap/fe/core/messagebundle_ar.properties +58 -7
  214. package/src/sap/fe/core/messagebundle_bg.properties +58 -7
  215. package/src/sap/fe/core/messagebundle_ca.properties +58 -7
  216. package/src/sap/fe/core/messagebundle_cs.properties +59 -8
  217. package/src/sap/fe/core/messagebundle_cy.properties +58 -7
  218. package/src/sap/fe/core/messagebundle_da.properties +58 -7
  219. package/src/sap/fe/core/messagebundle_de.properties +58 -7
  220. package/src/sap/fe/core/messagebundle_el.properties +58 -7
  221. package/src/sap/fe/core/messagebundle_en.properties +57 -6
  222. package/src/sap/fe/core/messagebundle_en_GB.properties +57 -6
  223. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +61 -6
  224. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +58 -7
  225. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +58 -7
  226. package/src/sap/fe/core/messagebundle_es.properties +58 -7
  227. package/src/sap/fe/core/messagebundle_es_MX.properties +58 -7
  228. package/src/sap/fe/core/messagebundle_et.properties +58 -7
  229. package/src/sap/fe/core/messagebundle_fi.properties +60 -9
  230. package/src/sap/fe/core/messagebundle_fr.properties +64 -13
  231. package/src/sap/fe/core/messagebundle_fr_CA.properties +59 -8
  232. package/src/sap/fe/core/messagebundle_hi.properties +58 -7
  233. package/src/sap/fe/core/messagebundle_hr.properties +58 -7
  234. package/src/sap/fe/core/messagebundle_hu.properties +59 -8
  235. package/src/sap/fe/core/messagebundle_id.properties +61 -10
  236. package/src/sap/fe/core/messagebundle_it.properties +58 -7
  237. package/src/sap/fe/core/messagebundle_iw.properties +58 -7
  238. package/src/sap/fe/core/messagebundle_ja.properties +58 -7
  239. package/src/sap/fe/core/messagebundle_kk.properties +58 -7
  240. package/src/sap/fe/core/messagebundle_ko.properties +58 -7
  241. package/src/sap/fe/core/messagebundle_lt.properties +58 -7
  242. package/src/sap/fe/core/messagebundle_lv.properties +59 -8
  243. package/src/sap/fe/core/messagebundle_ms.properties +58 -7
  244. package/src/sap/fe/core/messagebundle_nl.properties +58 -7
  245. package/src/sap/fe/core/messagebundle_no.properties +58 -7
  246. package/src/sap/fe/core/messagebundle_pl.properties +58 -7
  247. package/src/sap/fe/core/messagebundle_pt.properties +59 -8
  248. package/src/sap/fe/core/messagebundle_pt_PT.properties +58 -7
  249. package/src/sap/fe/core/messagebundle_ro.properties +58 -7
  250. package/src/sap/fe/core/messagebundle_ru.properties +58 -7
  251. package/src/sap/fe/core/messagebundle_sh.properties +58 -7
  252. package/src/sap/fe/core/messagebundle_sk.properties +58 -7
  253. package/src/sap/fe/core/messagebundle_sl.properties +58 -7
  254. package/src/sap/fe/core/messagebundle_sv.properties +59 -8
  255. package/src/sap/fe/core/messagebundle_th.properties +58 -7
  256. package/src/sap/fe/core/messagebundle_tr.properties +60 -9
  257. package/src/sap/fe/core/messagebundle_uk.properties +58 -7
  258. package/src/sap/fe/core/messagebundle_vi.properties +58 -7
  259. package/src/sap/fe/core/messagebundle_zh_CN.properties +58 -7
  260. package/src/sap/fe/core/messagebundle_zh_TW.properties +58 -7
  261. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +45 -71
  262. package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +3 -1
  263. package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +231 -202
  264. package/src/sap/fe/core/services/CacheHandlerServiceFactory.ts +212 -0
  265. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +67 -92
  266. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +10 -6
  267. package/src/sap/fe/core/services/NavigationServiceFactory.js +351 -300
  268. package/src/sap/fe/core/services/NavigationServiceFactory.ts +313 -0
  269. package/src/sap/fe/core/services/ResourceModelServiceFactory.js +114 -81
  270. package/src/sap/fe/core/services/ResourceModelServiceFactory.ts +83 -0
  271. package/src/sap/fe/core/services/RoutingServiceFactory.js +927 -1152
  272. package/src/sap/fe/core/services/RoutingServiceFactory.ts +898 -0
  273. package/src/sap/fe/core/services/ShellServicesFactory.js +649 -707
  274. package/src/sap/fe/core/services/ShellServicesFactory.ts +52 -15
  275. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +569 -637
  276. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +78 -102
  277. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +429 -478
  278. package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +460 -0
  279. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +10 -8
  280. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.ts +8 -0
  281. package/src/sap/fe/core/support/AnnotationIssue.support.js +15 -3
  282. package/src/sap/fe/core/support/AnnotationIssue.support.ts +16 -2
  283. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.js +2 -2
  284. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.ts +1 -1
  285. package/src/sap/fe/core/support/CommonHelper.js +1 -1
  286. package/src/sap/fe/core/support/CommonHelper.ts +1 -1
  287. package/src/sap/fe/core/support/Diagnostics.js +36 -48
  288. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.js +38 -0
  289. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.ts +18 -0
  290. package/src/sap/fe/core/templating/DataModelPathHelper.js +97 -127
  291. package/src/sap/fe/core/templating/DataModelPathHelper.ts +112 -135
  292. package/src/sap/fe/core/templating/DisplayModeFormatter.js +114 -0
  293. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +86 -0
  294. package/src/sap/fe/core/templating/FieldControlHelper.js +8 -8
  295. package/src/sap/fe/core/templating/FieldControlHelper.ts +25 -7
  296. package/src/sap/fe/core/templating/FilterHelper.js +140 -78
  297. package/src/sap/fe/core/templating/FilterHelper.ts +149 -78
  298. package/src/sap/fe/core/templating/PropertyHelper.js +3 -3
  299. package/src/sap/fe/core/templating/PropertyHelper.ts +2 -2
  300. package/src/sap/fe/core/templating/UIFormatters.js +76 -135
  301. package/src/sap/fe/core/templating/UIFormatters.ts +76 -99
  302. package/src/sap/fe/core/type/Email.js +1 -1
  303. package/src/sap/fe/core/type/Email.ts +4 -6
  304. package/ui5.yaml +0 -3
  305. package/src/sap/fe/core/controls/filterbar.d.js +0 -8
  306. package/src/sap/fe/core/controls/filterbar.d.ts +0 -0
@@ -0,0 +1,1672 @@
1
+ import ControllerExtension from "sap/ui/core/mvc/ControllerExtension";
2
+ import OverrideExecution from "sap/ui/core/mvc/OverrideExecution";
3
+ import Log from "sap/base/Log";
4
+ import CommonUtils from "sap/fe/core/CommonUtils";
5
+ import BusyLocker from "sap/fe/core/BusyLocker";
6
+ import FELibrary from "sap/fe/core/library";
7
+ import ODataListBinding from "sap/ui/model/odata/v4/ODataListBinding";
8
+ import SemanticKeyHelper from "sap/fe/core/helpers/SemanticKeyHelper";
9
+ import EditState from "sap/fe/core/helpers/EditState";
10
+ import Message from "sap/ui/core/message/Message";
11
+ import coreLibrary from "sap/ui/core/library";
12
+ import ModelHelper, { InternalModelContext } from "sap/fe/core/helpers/ModelHelper";
13
+ import { Extensible, Final, Public, UI5Class } from "sap/fe/core/helpers/ClassSupport";
14
+ import ControllerExtensionMetadata from "sap/fe/core/controllerextensions/ControllerExtensionMetadata";
15
+ import PageController from "sap/fe/core/PageController";
16
+ import ODataMetaModel from "sap/ui/model/odata/v4/ODataMetaModel";
17
+ import Table from "sap/ui/mdc/Table";
18
+ import Context from "sap/ui/model/odata/v4/Context";
19
+ import ResourceBundle from "sap/base/i18n/ResourceBundle";
20
+ import Control from "sap/ui/core/Control";
21
+ import { send } from "sap/fe/core/actions/collaboration/ActivitySync";
22
+ import { Activity } from "sap/fe/core/actions/collaboration/CollaborationCommon";
23
+ import ODataModel from "sap/ui/model/odata/v4/ODataModel";
24
+ import FlexibleColumnLayout from "sap/f/FlexibleColumnLayout";
25
+ import NavContainer from "sap/m/NavContainer";
26
+
27
+ const CreationMode = FELibrary.CreationMode,
28
+ ProgrammingModel = FELibrary.ProgrammingModel,
29
+ Constants = FELibrary.Constants,
30
+ DraftStatus = FELibrary.DraftStatus,
31
+ EditMode = FELibrary.EditMode,
32
+ MessageType = coreLibrary.MessageType;
33
+ /**
34
+ * A controller extension offering hooks into the edit flow of the application
35
+ *
36
+ * @hideconstructor
37
+ * @public
38
+ * @since 1.90.0
39
+ */
40
+ @UI5Class("sap.fe.core.controllerextensions.EditFlow", ControllerExtensionMetadata)
41
+ class EditFlow extends ControllerExtension {
42
+ private base!: PageController;
43
+
44
+ //////////////////////////////////////
45
+ // Public methods
46
+ //////////////////////////////////////
47
+
48
+ private fnDirtyStateProvider?: Function;
49
+ private fnHandleSessionTimeout?: Function;
50
+ private mPatchPromises?: any;
51
+ private _fnStickyDiscardAfterNavigation?: Function;
52
+
53
+ /**
54
+ * Creates a draft document for an existing active document.
55
+ *
56
+ * @memberof sap.fe.core.controllerextensions.EditFlow
57
+ * @param {object} oContext Context of the active document
58
+ * @returns {Promise} Promise resolves once the editable document is available
59
+ * @alias sap.fe.core.controllerextensions.EditFlow#editDocument
60
+ * @public
61
+ * @since 1.90.0
62
+ */
63
+ @Public
64
+ @Final
65
+ editDocument(oContext: Context): Promise<any> {
66
+ const bDraftNavigation = true;
67
+ const transactionHelper = this._getTransactionHelper();
68
+
69
+ return this.base.editFlow
70
+ .onBeforeEdit({ context: oContext })
71
+ .then(transactionHelper.editDocument.bind(transactionHelper, oContext, this.getView(), this._getMessageHandler()))
72
+ .then((oNewDocumentContext: any) => {
73
+ const sProgrammingModel = this._getProgrammingModel(oContext);
74
+
75
+ if (sProgrammingModel === ProgrammingModel.Sticky) {
76
+ this._getInternalModel().setProperty("/sessionOn", true);
77
+ }
78
+ if (oNewDocumentContext) {
79
+ this._setEditMode(EditMode.Editable, false);
80
+ this._getMessageHandler().showMessageDialog();
81
+
82
+ if (oNewDocumentContext !== oContext) {
83
+ return this._handleNewContext(oNewDocumentContext, true, false, bDraftNavigation, true).then(() => {
84
+ if (sProgrammingModel === ProgrammingModel.Sticky) {
85
+ // The stickyOn handler must be set after the navigation has been done,
86
+ // as the URL may change in the case of FCL
87
+ this._handleStickyOn(oNewDocumentContext);
88
+ }
89
+ });
90
+ }
91
+ }
92
+ })
93
+ .catch(function(oError: any) {
94
+ Log.error("Error while editing the document", oError);
95
+ });
96
+ }
97
+ @Public
98
+ @Final
99
+ deleteMultipleDocuments(aContexts: any, mParameters: any) {
100
+ if (mParameters) {
101
+ mParameters.beforeDeleteCallBack = this.base.editFlow.onBeforeDelete;
102
+ } else {
103
+ mParameters = {
104
+ beforeDeleteCallBack: this.base.editFlow.onBeforeDelete
105
+ };
106
+ }
107
+ return (this.base.getView().getController() as PageController)._editFlow.deleteMultipleDocuments(aContexts, mParameters);
108
+ }
109
+
110
+ /**
111
+ * Updates the draft status and displays the error messages if there are errors during an update.
112
+ *
113
+ * @memberof sap.fe.core.controllerextensions.EditFlow
114
+ * @param {object} oContext Context of the updated field
115
+ * @param {object} oPromise Promise to determine when the update operation is completed. The promise should be resolved when the update operation is completed, so the draft status can be updated.
116
+ * @returns {Promise} Promise resolves once draft status has been updated
117
+ * @alias sap.fe.core.controllerextensions.EditFlow#updateDocument
118
+ * @public
119
+ * @since 1.90.0
120
+ */
121
+ @Public
122
+ @Final
123
+ updateDocument(oContext: object, oPromise: Promise<any>): Promise<void> {
124
+ const transactionHelper = this._getTransactionHelper(),
125
+ oBindingContext = this.getView().getBindingContext(),
126
+ bIsDraft = this._getProgrammingModel(oContext) === ProgrammingModel.Draft;
127
+
128
+ this._getMessageHandler().removeTransitionMessages();
129
+ return this._syncTask(() => {
130
+ if (oBindingContext) {
131
+ transactionHelper.handleDocumentModifications();
132
+ EditState.setEditStateDirty();
133
+
134
+ if (bIsDraft) {
135
+ this._setDraftStatus(DraftStatus.Saving);
136
+ }
137
+ }
138
+ this._getMessageHandler().removeTransitionMessages();
139
+
140
+ return oPromise
141
+ .then(
142
+ () => {
143
+ if (bIsDraft && oBindingContext) {
144
+ const oMetaModel = oBindingContext.getModel().getMetaModel() as ODataMetaModel,
145
+ sEntitySetName = (oMetaModel as any).getMetaContext(oBindingContext.getPath()).getObject("@sapui.name"),
146
+ aSemanticKeys = SemanticKeyHelper.getSemanticKeys(oMetaModel, sEntitySetName);
147
+ if (aSemanticKeys && aSemanticKeys.length) {
148
+ const oCurrentSemanticMapping = (this.base.getAppComponent() as any)
149
+ .getRoutingService()
150
+ .getLastSemanticMapping(),
151
+ sCurrentSemanticPath = oCurrentSemanticMapping && oCurrentSemanticMapping.semanticPath,
152
+ sChangedPath = SemanticKeyHelper.getSemanticPath(oBindingContext, true);
153
+
154
+ if (sCurrentSemanticPath !== sChangedPath) {
155
+ return this._handleNewContext(oBindingContext, true, false, true).then(() => {
156
+ this._setDraftStatus(DraftStatus.Saved);
157
+ });
158
+ } else {
159
+ this._setDraftStatus(DraftStatus.Saved);
160
+ }
161
+ } else {
162
+ this._setDraftStatus(DraftStatus.Saved);
163
+ }
164
+ }
165
+ },
166
+ () => {
167
+ if (bIsDraft && oBindingContext) {
168
+ this._setDraftStatus(DraftStatus.Clear);
169
+ }
170
+ }
171
+ )
172
+ .catch(function(oError: any) {
173
+ Log.error("Error while updating the document", oError);
174
+ })
175
+ .finally(() => {
176
+ this._getMessageHandler().showMessages();
177
+ });
178
+ });
179
+ }
180
+
181
+ // Internal only params ---
182
+ // * @param {string} mParameters.creationMode The creation mode using one of the following:
183
+ // * Sync - the creation is triggered and once the document is created, the navigation is done
184
+ // * Async - the creation and the navigation to the instance are done in parallel
185
+ // * Deferred - the creation is done on the target page
186
+ // * CreationRow - The creation is done inline async so the user is not blocked
187
+ // mParameters.creationRow Instance of the creation row - (TODO: get rid but use list bindings only)
188
+
189
+ // eslint-disable-next-line jsdoc/require-param
190
+ /**
191
+ * Creates a new document.
192
+ *
193
+ * @memberof sap.fe.core.controllerextensions.EditFlow
194
+ * @param {sap.ui.model.odata.v4.ODataListBinding|string} vListBinding ODataListBinding object or the binding path for a temporary list binding
195
+ * @param {map} mInParameters Contains the following attributes:
196
+ * @param {string} mInParameters.creationMode The creation mode using one of the following:
197
+ * NewPage - the created document is shown in a new page, depending on whether metadata 'Sync', 'Async' or 'Deferred' is used
198
+ * Inline - The creation is done inline (in a table)
199
+ * External - The creation is done in a different application specified via the parameter 'outbound'
200
+ * @param {string} mInParameters.outbound The navigation target where the document is created in case of creationMode 'External'
201
+ * @param {boolean} mInParameters.createAtEnd Specifies if the new entry should be created at the top or bottom of a table in case of creationMode 'Inline'
202
+ * @returns {Promise} Promise resolves once the object has been created
203
+ * @alias sap.fe.core.controllerextensions.EditFlow#createDocument
204
+ * @public
205
+ * @since 1.90.0
206
+ */
207
+ @Public
208
+ @Final
209
+ createDocument(
210
+ vListBinding: ODataListBinding | string,
211
+ mInParameters: {
212
+ creationMode: string;
213
+ outbound?: string;
214
+ createAtEnd?: boolean;
215
+ }
216
+ ): Promise<void> {
217
+ const transactionHelper = this._getTransactionHelper(),
218
+ oLockObject = this._getGlobalUIModel();
219
+ let oTable: Table;
220
+ let iCountTableItems = 0;
221
+ let mParameters: any = mInParameters;
222
+ const oResourceBundle = (this.getView().getController() as any).oResourceBundle;
223
+ const bShouldBusyLock =
224
+ !mParameters ||
225
+ (mParameters.creationMode !== CreationMode.Inline &&
226
+ mParameters.creationMode !== CreationMode.CreationRow &&
227
+ mParameters.creationMode !== CreationMode.External);
228
+ let oExecCustomValidation = Promise.resolve([]);
229
+ const oAppComponent = CommonUtils.getAppComponent(this.getView());
230
+ oAppComponent.getRouterProxy().removeIAppStateKey();
231
+
232
+ if (mParameters.creationMode === CreationMode.External) {
233
+ // Create by navigating to an external target
234
+ // TODO: Call appropriate function (currently using the same as for outbound chevron nav, and without any context - 3rd param)
235
+ return this._syncTask().then(() => {
236
+ const oController = this.getView().getController(),
237
+ sCreatePath = ModelHelper.getAbsoluteMetaPathForListBinding(this.getView(), vListBinding);
238
+
239
+ (oController as any).handlers.onChevronPressNavigateOutBound(oController, mParameters.outbound, undefined, sCreatePath);
240
+ });
241
+ }
242
+
243
+ if (mParameters.creationMode === CreationMode.CreationRow && mParameters.creationRow) {
244
+ const oCreationRowObjects = mParameters.creationRow.getBindingContext().getObject();
245
+ delete oCreationRowObjects["@$ui5.context.isTransient"];
246
+ oTable = mParameters.creationRow.getParent();
247
+ oExecCustomValidation = transactionHelper.validateDocument(
248
+ oTable.getBindingContext(),
249
+ {
250
+ data: oCreationRowObjects,
251
+ customValidationFunction: (oTable.getCreationRow() as any).data("customValidationFunction")
252
+ },
253
+ this.base.getView()
254
+ );
255
+
256
+ // disableAddRowButtonForEmptyData is set to false in manifest converter (Table.ts) if customValidationFunction exists
257
+ if ((oTable.getCreationRow() as any).data("disableAddRowButtonForEmptyData") === "true") {
258
+ const oInternalModelContext = oTable.getBindingContext("internal") as InternalModelContext;
259
+ oInternalModelContext.setProperty("creationRowFieldValidity", {});
260
+ }
261
+ }
262
+
263
+ if (mParameters.creationMode === CreationMode.Inline && mParameters.tableId) {
264
+ oTable = this.getView().byId(mParameters.tableId) as Table;
265
+ }
266
+
267
+ /**
268
+ * @param {sap.ui.model.odata.v4.ODataListBinding} oListBinding
269
+ * @param {object} oCreationPromise
270
+ */
271
+ const handleSideEffects = (oListBinding: any, oCreationPromise: Promise<Context>) => {
272
+ oCreationPromise
273
+ .then(function(oNewContext: any) {
274
+ // transient contexts are reliably removed once oNewContext.created() is resolved
275
+ return oNewContext.created();
276
+ })
277
+ .then(() => {
278
+ const oBindingContext = this.getView().getBindingContext() as Context;
279
+ // if there are transient contexts, we must avoid requesting side effects
280
+ // this is avoid a potential list refresh, there could be a side effect that refreshes the list binding
281
+ // if list binding is refreshed, transient contexts might be lost
282
+ if (!CommonUtils.hasTransientContext(oListBinding)) {
283
+ const oAppComponent = CommonUtils.getAppComponent(this.getView());
284
+ oAppComponent
285
+ .getSideEffectsService()
286
+ .requestSideEffectsForNavigationProperty(oListBinding.getPath(), oBindingContext);
287
+ }
288
+ })
289
+ .catch(function(oError: any) {
290
+ Log.error("Error while creating the document", oError);
291
+ });
292
+ };
293
+
294
+ /**
295
+ * @param {Array} aValidationMessages Error messages from custom validation function
296
+ */
297
+ const createCustomValidationMessages = (aValidationMessages: any[]) => {
298
+ const sCustomValidationFunction = oTable && (oTable.getCreationRow() as any).data("customValidationFunction");
299
+ const mCustomValidity = oTable && oTable.getBindingContext("internal")?.getProperty("creationRowCustomValidity");
300
+ const oMessageManager = sap.ui.getCore().getMessageManager();
301
+ const aCustomMessages: any[] = [];
302
+ let oFieldControl;
303
+ let sTarget: string;
304
+
305
+ // Remove existing CustomValidation message
306
+ oMessageManager
307
+ .getMessageModel()
308
+ .getData()
309
+ .forEach(function(oMessage: any) {
310
+ if (oMessage.code === sCustomValidationFunction) {
311
+ oMessageManager.removeMessages(oMessage);
312
+ }
313
+ });
314
+
315
+ aValidationMessages.forEach((oValidationMessage: any) => {
316
+ // Handle Bound CustomValidation message
317
+ if (oValidationMessage.messageTarget) {
318
+ oFieldControl = sap.ui.getCore().getControl(mCustomValidity[oValidationMessage.messageTarget].fieldId) as Control;
319
+ sTarget = oFieldControl.getBindingContext()?.getPath() + "/" + oFieldControl.getBindingPath("value");
320
+ // Add validation message if still not exists
321
+ if (
322
+ oMessageManager
323
+ .getMessageModel()
324
+ .getData()
325
+ .filter(function(oMessage: any) {
326
+ return oMessage.target === sTarget;
327
+ }).length === 0
328
+ ) {
329
+ oMessageManager.addMessages(
330
+ new Message({
331
+ message: oValidationMessage.messageText,
332
+ processor: this.getView().getModel(),
333
+ type: MessageType.Error,
334
+ code: sCustomValidationFunction,
335
+ technical: false,
336
+ persistent: false,
337
+ target: sTarget
338
+ })
339
+ );
340
+ }
341
+ // Add controlId in order to get the focus handling of the error popover runable
342
+ const aExistingValidationMessages = oMessageManager
343
+ .getMessageModel()
344
+ .getData()
345
+ .filter(function(oMessage: any) {
346
+ return oMessage.target === sTarget;
347
+ });
348
+ aExistingValidationMessages[0].addControlId(mCustomValidity[oValidationMessage.messageTarget].fieldId);
349
+
350
+ // Handle Unbound CustomValidation message
351
+ } else {
352
+ aCustomMessages.push({
353
+ code: sCustomValidationFunction,
354
+ text: oValidationMessage.messageText,
355
+ persistent: true,
356
+ type: MessageType.Error
357
+ });
358
+ }
359
+ });
360
+
361
+ if (aCustomMessages.length > 0) {
362
+ this._getMessageHandler().showMessageDialog({
363
+ customMessages: aCustomMessages
364
+ });
365
+ }
366
+ };
367
+
368
+ bShouldBusyLock && BusyLocker.lock(oLockObject);
369
+ return this._syncTask(oExecCustomValidation)
370
+ .then((aValidationMessages: any) => {
371
+ if (aValidationMessages.length > 0) {
372
+ createCustomValidationMessages(aValidationMessages);
373
+ Log.error("Custom Validation failed");
374
+ // if custom validation fails, we leave the method immediately
375
+ return;
376
+ }
377
+
378
+ let sProgrammingModel: string;
379
+ let oListBinding: any;
380
+
381
+ mParameters = mParameters || {};
382
+
383
+ if (vListBinding && typeof vListBinding === "object") {
384
+ // we already get a list binding use this one
385
+ oListBinding = vListBinding;
386
+ } else if (typeof vListBinding === "string") {
387
+ oListBinding = new (ODataListBinding as any)(this.getView().getModel(), vListBinding);
388
+ mParameters.creationMode = CreationMode.Sync;
389
+ delete mParameters.createAtEnd;
390
+ } else {
391
+ throw new Error("Binding object or path expected");
392
+ }
393
+
394
+ const oModel = oListBinding.getModel();
395
+ iCountTableItems = oListBinding.iMaxLength || 0;
396
+ const sCreationMode = mParameters.creationMode;
397
+
398
+ return Promise.resolve(this._getProgrammingModel(oListBinding))
399
+ .then((programmingModel: any) => {
400
+ sProgrammingModel = programmingModel;
401
+ if (sCreationMode && sCreationMode !== CreationMode.NewPage) {
402
+ // use the passed creation mode
403
+ return sCreationMode;
404
+ } else {
405
+ const oMetaModel = oModel.getMetaModel();
406
+ // NewAction is not yet supported for NavigationProperty collection
407
+ if (!oListBinding.isRelative()) {
408
+ const sPath = oListBinding.getPath(),
409
+ // if NewAction with parameters is present, then creation is 'Deferred'
410
+ // in the absence of NewAction or NewAction with parameters, creation is async
411
+ sNewAction =
412
+ sProgrammingModel === ProgrammingModel.Draft
413
+ ? oMetaModel.getObject(sPath + "@com.sap.vocabularies.Common.v1.DraftRoot/NewAction")
414
+ : oMetaModel.getObject(
415
+ sPath + "@com.sap.vocabularies.Session.v1.StickySessionSupported/NewAction"
416
+ );
417
+ if (sNewAction) {
418
+ const aParameters = oMetaModel.getObject("/" + sNewAction + "/@$ui5.overload/0/$Parameter") || [];
419
+ // binding parameter (eg: _it) is not considered
420
+ if (aParameters.length > 1) {
421
+ return CreationMode.Deferred;
422
+ }
423
+ }
424
+ }
425
+ const sMetaPath = oMetaModel.getMetaPath(oListBinding.getHeaderContext().getPath());
426
+ const aNonComputedVisibleKeyFields = CommonUtils.getNonComputedVisibleFields(
427
+ oMetaModel,
428
+ sMetaPath,
429
+ this.getView()
430
+ );
431
+ if (aNonComputedVisibleKeyFields.length > 0) {
432
+ return CreationMode.Deferred;
433
+ }
434
+ return CreationMode.Async;
435
+ }
436
+ })
437
+ .then((sCreationMode: any) => {
438
+ let oCreation: any;
439
+ let mArgs: any;
440
+ const oCreationRow = mParameters.creationRow;
441
+ let oCreationRowContext: any;
442
+ let oValidationCheck = Promise.resolve();
443
+ let oPayload: any;
444
+ let sMetaPath: string;
445
+ const oMetaModel = oModel.getMetaModel();
446
+ const oRoutingListener = this._getRoutingListener();
447
+
448
+ if (sCreationMode !== CreationMode.Deferred) {
449
+ if (sCreationMode === CreationMode.CreationRow) {
450
+ oCreationRowContext = oCreationRow.getBindingContext();
451
+ sMetaPath = oMetaModel.getMetaPath(oCreationRowContext.getPath());
452
+ // prefill data from creation row
453
+ oPayload = oCreationRowContext.getObject();
454
+ mParameters.data = {};
455
+ Object.keys(oPayload).forEach(function(sPropertyPath: string) {
456
+ const oProperty = oMetaModel.getObject(sMetaPath + "/" + sPropertyPath);
457
+ // ensure navigation properties are not part of the payload, deep create not supported
458
+ if (oProperty && oProperty.$kind === "NavigationProperty") {
459
+ return;
460
+ }
461
+ mParameters.data[sPropertyPath] = oPayload[sPropertyPath];
462
+ });
463
+ oValidationCheck = this._checkForValidationErrors(/*oCreationRowContext*/);
464
+ }
465
+ if (sCreationMode === CreationMode.CreationRow || sCreationMode === CreationMode.Inline) {
466
+ mParameters.keepTransientContextOnFailed = false; // currently not fully supported
467
+ // busy handling shall be done locally only
468
+ mParameters.busyMode = "Local";
469
+
470
+ // take care on message handling, draft indicator (in case of draft)
471
+ // Attach the create sent and create completed event to the object page binding so that we can react
472
+ this._handleCreateEvents(oListBinding);
473
+ }
474
+
475
+ oCreation = oValidationCheck.then(() => {
476
+ if (!mParameters.parentControl) {
477
+ mParameters.parentControl = this.getView();
478
+ }
479
+ mParameters.beforeCreateCallBack = this.base.editFlow.onBeforeCreate;
480
+ return transactionHelper.createDocument(
481
+ oListBinding,
482
+ mParameters,
483
+ oResourceBundle,
484
+ this._getMessageHandler(),
485
+ false,
486
+ this.getView()
487
+ );
488
+ });
489
+ }
490
+
491
+ let oNavigation;
492
+ switch (sCreationMode) {
493
+ case CreationMode.Deferred:
494
+ oNavigation = oRoutingListener.navigateForwardToContext(oListBinding, {
495
+ bDeferredContext: true,
496
+ editable: true,
497
+ bForceFocus: true
498
+ });
499
+ break;
500
+ case CreationMode.Async:
501
+ oNavigation = oRoutingListener.navigateForwardToContext(oListBinding, {
502
+ asyncContext: oCreation,
503
+ editable: true,
504
+ bForceFocus: true
505
+ });
506
+ break;
507
+ case CreationMode.Sync:
508
+ mArgs = {
509
+ editable: true,
510
+ bForceFocus: true
511
+ };
512
+ if (sProgrammingModel == ProgrammingModel.Sticky || mParameters.createAction) {
513
+ mArgs.transient = true;
514
+ }
515
+ oNavigation = oCreation.then(function(oNewDocumentContext: any) {
516
+ if (!oNewDocumentContext) {
517
+ const oResourceBundle = sap.ui.getCore().getLibraryResourceBundle("sap.fe.core") as ResourceBundle;
518
+ return oRoutingListener.navigateToMessagePage(
519
+ oResourceBundle.getText("C_COMMON_SAPFE_DATA_RECEIVED_ERROR"),
520
+ {
521
+ title: oResourceBundle.getText("C_COMMON_SAPFE_ERROR"),
522
+ description: oResourceBundle.getText("C_EDITFLOW_SAPFE_CREATION_FAILED_DESCRIPTION")
523
+ }
524
+ );
525
+ } else {
526
+ return oRoutingListener.navigateForwardToContext(oNewDocumentContext, mArgs);
527
+ }
528
+ });
529
+ break;
530
+ case CreationMode.Inline:
531
+ handleSideEffects(oListBinding, oCreation);
532
+ this._syncTask(oCreation);
533
+ break;
534
+ case CreationMode.CreationRow:
535
+ // the creation row shall be cleared once the validation check was successful and
536
+ // therefore the POST can be sent async to the backend
537
+ oNavigation = oValidationCheck
538
+ .then(function() {
539
+ const oCreationRowListBinding = oCreationRowContext.getBinding();
540
+
541
+ if (!mParameters.bSkipSideEffects) {
542
+ handleSideEffects(oListBinding, oCreation);
543
+ }
544
+
545
+ const oNewTransientContext = oCreationRowListBinding.create();
546
+ oCreationRow.setBindingContext(oNewTransientContext);
547
+
548
+ // this is needed to avoid console errors TO be checked with model colleagues
549
+ oNewTransientContext.created().catch(function() {
550
+ Log.trace("transient fast creation context deleted");
551
+ });
552
+ return oCreationRowContext.delete("$direct");
553
+ })
554
+ .catch((oError: any) => {
555
+ // Reset busy indicator after a validation error
556
+ if (BusyLocker.isLocked(this.getView().getModel("ui"))) {
557
+ BusyLocker.unlock(this.getView().getModel("ui"));
558
+ }
559
+ Log.error("CreationRow navigation error: ", oError);
560
+ });
561
+ break;
562
+ default:
563
+ oNavigation = Promise.reject("Unhandled creationMode " + sCreationMode);
564
+ break;
565
+ }
566
+
567
+ if (sProgrammingModel === ProgrammingModel.Sticky) {
568
+ this._getInternalModel().setProperty("/sessionOn", true);
569
+ }
570
+ const bIsNewPageCreation =
571
+ mParameters.creationMode !== CreationMode.CreationRow && mParameters.creationMode !== CreationMode.Inline;
572
+ if (oCreation) {
573
+ return Promise.all([oCreation, oNavigation])
574
+ .then((aParams: [any, any]) => {
575
+ if (bIsNewPageCreation) {
576
+ this._setEditMode(EditMode.Editable, bIsNewPageCreation);
577
+ } else {
578
+ this._setEditMode(EditMode.Editable);
579
+ }
580
+ const oNewDocumentContext = aParams[0];
581
+ if (oNewDocumentContext) {
582
+ EditState.setEditStateDirty();
583
+ send(this.getView(), Activity.Create, oNewDocumentContext);
584
+ if (sProgrammingModel === ProgrammingModel.Sticky) {
585
+ this._handleStickyOn(oNewDocumentContext);
586
+ }
587
+ }
588
+ })
589
+ .catch(function(oError: any) {
590
+ if (oError && (oError.navigateBackFromTransientState || oError == Constants.CancelActionDialog)) {
591
+ oRoutingListener.navigateBackFromTransientState();
592
+ }
593
+
594
+ return Promise.reject(oError);
595
+ });
596
+ }
597
+ });
598
+ })
599
+ .finally(function() {
600
+ if (oTable && oTable.isA("sap.ui.mdc.Table")) {
601
+ const fnFocusOrScroll =
602
+ mParameters.creationMode === CreationMode.Inline ? oTable.focusRow.bind(oTable) : oTable.scrollToIndex.bind(oTable);
603
+ oTable.getRowBinding().attachEventOnce("change", function() {
604
+ switch (mParameters.createAtEnd) {
605
+ case true:
606
+ if (oTable.data("tableType") === "ResponsiveTable" && oTable.getThreshold()) {
607
+ fnFocusOrScroll(oTable.getThreshold(), true);
608
+ } else {
609
+ fnFocusOrScroll(iCountTableItems, true);
610
+ }
611
+ break;
612
+ case false:
613
+ fnFocusOrScroll(0, true);
614
+ break;
615
+ }
616
+ });
617
+ }
618
+ bShouldBusyLock && BusyLocker.unlock(oLockObject);
619
+ });
620
+ }
621
+
622
+ /**
623
+ * This function can be used to intercept the 'Save' action. You can execute custom coding in this function.
624
+ * The framework waits for the returned promise to be resolved before continuing the 'Save' action.
625
+ * If you reject the promise, the 'Save' action is stopped and the user stays in edit mode.
626
+ *
627
+ * This function is meant to be individually overridden by consuming controllers, but not to be called directly.
628
+ * The override execution is: {@link sap.ui.core.mvc.OverrideExecution.After}.
629
+ * @param {object} mParameters Object containing the parameters passed to onBeforeSave
630
+ * @param {sap.ui.model.odata.v4.Context} mParameters.context Page context that is going to be saved.
631
+ * @returns {Promise} A promise to be returned by the overridden method. If resolved, the 'Save' action is triggered. If rejected, the 'Save' action is not triggered and the user stays in edit mode.
632
+ * @memberof sap.fe.core.controllerextensions.EditFlow
633
+ * @alias sap.fe.core.controllerextensions.EditFlow#onBeforeSave
634
+ * @public
635
+ * @experimental As of version 1.90.0
636
+ * @since 1.90.0
637
+ */
638
+ @Public
639
+ @Extensible(OverrideExecution.After)
640
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
641
+ onBeforeSave(mParameters?: { context?: Context }): Promise<void> {
642
+ // to be overridden
643
+ return Promise.resolve();
644
+ }
645
+ /**
646
+ * This function can be used to intercept the 'Create' action. You can execute custom coding in this function.
647
+ * The framework waits for the returned promise to be resolved before continuing the 'Create' action.
648
+ * If you reject the promise, the 'Create' action is stopped.
649
+ *
650
+ * This function is meant to be individually overridden by consuming controllers, but not to be called directly.
651
+ * The override execution is: {@link sap.ui.core.mvc.OverrideExecution.After}.
652
+ * @param {map} mParameters Object containing the parameters passed to onBeforeCreate
653
+ * @param {string} mParameters.contextPath Path pointing to the context on which Create action is triggered
654
+ * @param {Array} mParameters.createParameters Array of values that are filled in the Action Parameter Dialog
655
+ * @returns {Promise} A promise to be returned by the overridden method. If resolved, the 'Create' action is triggered. If rejected, the 'Create' action is not triggered.
656
+ * @memberof sap.fe.core.controllerextensions.EditFlow
657
+ * @alias sap.fe.core.controllerextensions.EditFlow#onBeforeCreate
658
+ * @public
659
+ * @experimental As of version 1.98.0
660
+ * @since 1.98.0
661
+ */
662
+ @Public
663
+ @Extensible(OverrideExecution.After)
664
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
665
+ onBeforeCreate(mParameters?: { contextPath?: string; createParameters?: any[] }): Promise<void> {
666
+ // to be overridden
667
+ return Promise.resolve();
668
+ }
669
+ /**
670
+ * This function can be used to intercept the 'Edit' action. You can execute custom coding in this function.
671
+ * The framework waits for the returned promise to be resolved before continuing the 'Edit' action.
672
+ * If you reject the promise, the 'Edit' action is stopped and the user stays in display mode.
673
+ *
674
+ * This function is meant to be individually overridden by consuming controllers, but not to be called directly.
675
+ * The override execution is: {@link sap.ui.core.mvc.OverrideExecution.After}.
676
+ * @param {object} mParameters Object containing the parameters passed to onBeforeEdit
677
+ * @param {sap.ui.model.odata.v4.Context} mParameters.context Page context that is going to be edited.
678
+ * @returns {Promise} A promise to be returned by the overridden method. If resolved, the 'Edit' action is triggered. If rejected, the 'Edit' action is not triggered and the user stays in display mode.
679
+ * @memberof sap.fe.core.controllerextensions.EditFlow
680
+ * @alias sap.fe.core.controllerextensions.EditFlow#onBeforeEdit
681
+ * @public
682
+ * @experimental As of version 1.98.0
683
+ * @since 1.98.0
684
+ */
685
+ @Public
686
+ @Extensible(OverrideExecution.After)
687
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
688
+ onBeforeEdit(mParameters?: { context?: Context }): Promise<void> {
689
+ // to be overridden
690
+ return Promise.resolve();
691
+ }
692
+ /**
693
+ * This function can be used to intercept the 'Discard' action. You can execute custom coding in this function.
694
+ * The framework waits for the returned promise to be resolved before continuing the 'Discard' action.
695
+ * If you reject the promise, the 'Discard' action is stopped and the user stays in edit mode.
696
+ *
697
+ * This function is meant to be individually overridden by consuming controllers, but not to be called directly.
698
+ * The override execution is: {@link sap.ui.core.mvc.OverrideExecution.After}.
699
+ * @param {object} mParameters Object containing the parameters passed to onBeforeDiscard
700
+ * @param {sap.ui.model.odata.v4.Context} mParameters.context Page context that is going to be discarded.
701
+ * @returns {Promise} A promise to be returned by the overridden method. If resolved, the 'Discard' action is triggered. If rejected, the 'Discard' action is not triggered and the user stays in edit mode.
702
+ * @memberof sap.fe.core.controllerextensions.EditFlow
703
+ * @alias sap.fe.core.controllerextensions.EditFlow#onBeforeDiscard
704
+ * @public
705
+ * @experimental As of version 1.98.0
706
+ * @since 1.98.0
707
+ */
708
+ @Public
709
+ @Extensible(OverrideExecution.After)
710
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
711
+ onBeforeDiscard(mParameters?: { context?: Context }): Promise<void> {
712
+ // to be overridden
713
+ return Promise.resolve();
714
+ }
715
+ /**
716
+ * This function can be used to intercept the 'Delete' action. You can execute custom coding in this function.
717
+ * The framework waits for the returned promise to be resolved before continuing the 'Delete' action.
718
+ * If you reject the promise, the 'Delete' action is stopped.
719
+ *
720
+ * This function is meant to be individually overridden by consuming controllers, but not to be called directly.
721
+ * The override execution is: {@link sap.ui.core.mvc.OverrideExecution.After}.
722
+ * @param {object} mParameters Object containing the parameters passed to onBeforeDelete
723
+ * @param {Array} mParameters.contexts An array of contexts that are going to be deleted
724
+ * @returns {Promise} A promise to be returned by the overridden method. If resolved, the 'Delete' action is triggered. If rejected, the 'Delete' action is not triggered.
725
+ * @memberof sap.fe.core.controllerextensions.EditFlow
726
+ * @alias sap.fe.core.controllerextensions.EditFlow#onBeforeDelete
727
+ * @public
728
+ * @experimental As of version 1.98.0
729
+ * @since 1.98.0
730
+ */
731
+ @Public
732
+ @Extensible(OverrideExecution.After)
733
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
734
+ onBeforeDelete(mParameters?: { contexts?: Context[] }): Promise<void> {
735
+ // to be overridden
736
+ return Promise.resolve();
737
+ }
738
+
739
+ // Internal only params ---
740
+ // @param {boolean} mParameters.bExecuteSideEffectsOnError Indicates whether SideEffects need to be ignored when user clicks on Save during an Inline creation
741
+ // @param {object} mParameters.bindings List bindings of the tables in the view.
742
+ // Both of the above parameters are for the same purpose. User can enter some information in the creation row(s) but does not 'Add row', instead clicks Save.
743
+ // There can be more than one in the view.
744
+
745
+ // eslint-disable-next-line jsdoc/require-param
746
+ /**
747
+ * Saves a new document after checking it.
748
+ *
749
+ * @memberof sap.fe.core.controllerextensions.EditFlow
750
+ * @param {object} oContext Context of the editable document
751
+ * @returns {Promise} Promise resolves once save is complete
752
+ * @alias sap.fe.core.controllerextensions.EditFlow#saveDocument
753
+ * @public
754
+ * @since 1.90.0
755
+ */
756
+ @Public
757
+ @Final
758
+ saveDocument(oContext: Context, mParameters: any): Promise<void> {
759
+ mParameters = mParameters || {};
760
+ const bExecuteSideEffectsOnError = mParameters.bExecuteSideEffectsOnError || undefined;
761
+ const bDraftNavigation = true;
762
+ const transactionHelper = this._getTransactionHelper();
763
+ const oResourceBundle = (this.getView().getController() as any).oResourceBundle;
764
+ const aBindings = mParameters.bindings;
765
+ // first of all wait until all key-match-requests are done
766
+ return (
767
+ this._syncTask()
768
+ // submit any open changes if there any (although there are validation/parse errors)
769
+ .then(this._submitOpenChanges.bind(this, oContext))
770
+ // check if there are any validation/parse errors
771
+ .then(this._checkForValidationErrors.bind(this, oContext))
772
+ .then(this.base.editFlow.onBeforeSave.bind(this, { context: oContext }))
773
+ // and finally if all user changes are submitted and valid save the document
774
+ .then(
775
+ transactionHelper.saveDocument.bind(
776
+ transactionHelper,
777
+ oContext,
778
+ oResourceBundle,
779
+ bExecuteSideEffectsOnError,
780
+ aBindings,
781
+ this._getMessageHandler()
782
+ )
783
+ )
784
+ .then((oActiveDocumentContext: any) => {
785
+ const sProgrammingModel = this._getProgrammingModel(oContext);
786
+
787
+ this._removeContextsFromPages();
788
+ if (sProgrammingModel === ProgrammingModel.Sticky) {
789
+ this._getInternalModel().setProperty("/sessionOn", false);
790
+ this._handleStickyOff(/*oContext*/);
791
+ }
792
+
793
+ send(this.getView(), Activity.Activate, oActiveDocumentContext);
794
+
795
+ this._setEditMode(EditMode.Display, false);
796
+ this._getMessageHandler().showMessageDialog();
797
+
798
+ if (oActiveDocumentContext !== oContext) {
799
+ this._handleNewContext(oActiveDocumentContext, false, false, bDraftNavigation, true);
800
+ }
801
+ })
802
+ .catch(function(oError: any) {
803
+ Log.error("Error while saving the document", oError);
804
+ return Promise.reject(oError);
805
+ })
806
+ );
807
+ }
808
+ @Public
809
+ @Final
810
+ toggleDraftActive(oContext: any) {
811
+ const oContextData = oContext.getObject();
812
+ let bEditable: boolean;
813
+ const bIsDraft = oContext && this._getProgrammingModel(oContext) === ProgrammingModel.Draft;
814
+ const oToggleContext = oContext
815
+ .getModel()
816
+ .bindContext(oContext.getPath() + "/SiblingEntity")
817
+ .getBoundContext();
818
+
819
+ //toggle between draft and active document is only available for edit drafts and active documents with draft)
820
+ if (
821
+ !bIsDraft ||
822
+ !(
823
+ (!oContextData.IsActiveEntity && oContextData.HasActiveEntity) ||
824
+ (oContextData.IsActiveEntity && oContextData.HasDraftEntity)
825
+ )
826
+ ) {
827
+ return;
828
+ }
829
+
830
+ if (!oContextData.IsActiveEntity && oContextData.HasActiveEntity) {
831
+ //start Point: edit draft
832
+ bEditable = false;
833
+ } else if (oContextData.IsActiveEntity && oContextData.HasDraftEntity) {
834
+ // start point active document
835
+ bEditable = true;
836
+ }
837
+ oToggleContext
838
+ .requestCanonicalPath()
839
+ .then(function(sCanonicalPath: any) {
840
+ // We use the canonical path for the navigation instead of the semantic path, as the
841
+ // semantic key values may have changed between the draft and the active version (BCP 2170216142)
842
+ return oToggleContext
843
+ .getModel()
844
+ .bindContext(sCanonicalPath)
845
+ .getBoundContext();
846
+ })
847
+ .then((oToggleContext: any) => {
848
+ this._setEditMode(bEditable ? EditMode.Editable : EditMode.Display, false); //switch to edit mode only if a draft is available
849
+ this._handleNewContext(oToggleContext, bEditable, true, true, true);
850
+ })
851
+ .catch(function(err: any) {
852
+ return Promise.reject("Error in EditFlow.toggleDraftActive:" + err);
853
+ });
854
+ }
855
+
856
+ // Internal only params ---
857
+ // @param {sap.m.Button} mParameters.cancelButton - Currently this is passed as cancelButton internally (replaced by mParameters.control in the JSDoc below). Currently it is also mandatory.
858
+ // Plan - This should not be mandatory. If not provided, we should have a default that can act as reference control for the discard popover OR we can show a dialog instead of a popover.
859
+
860
+ /**
861
+ * Discard the editable document.
862
+ *
863
+ * @memberof sap.fe.core.controllerextensions.EditFlow
864
+ * @param {object} oContext Context of the editable document
865
+ * @param {map} mParameters Can contain the following attributes:
866
+ * @param {object} mParameters.control This is the control used to open the discard popover
867
+ * @param {boolean} mParameters.skipDiscardPopover Optional, supresses the discard popover and allows custom handling
868
+ * @returns {Promise} Promise resolves once editable document has been discarded
869
+ * @alias sap.fe.core.controllerextensions.EditFlow#cancelDocument
870
+ * @public
871
+ * @since 1.90.0
872
+ */
873
+ @Public
874
+ @Final
875
+ cancelDocument(oContext: object, mParameters: { control: object; skipDiscardPopover?: boolean }): Promise<void> {
876
+ const transactionHelper = this._getTransactionHelper(),
877
+ oResourceBundle = (this.getView().getController() as any).oResourceBundle;
878
+ const mInParameters: any = mParameters;
879
+ mInParameters.cancelButton = mParameters.control || mInParameters.cancelButton;
880
+ mInParameters.beforeCancelCallBack = this.base.editFlow.onBeforeDiscard;
881
+ return this._syncTask()
882
+ .then(
883
+ transactionHelper.cancelDocument.bind(transactionHelper, oContext, mParameters, oResourceBundle, this._getMessageHandler())
884
+ )
885
+ .then((oActiveDocumentContext: any) => {
886
+ const bDraftNavigation = true,
887
+ sProgrammingModel = this._getProgrammingModel(oContext);
888
+
889
+ this._removeContextsFromPages();
890
+ if (sProgrammingModel === ProgrammingModel.Sticky) {
891
+ this._getInternalModel().setProperty("/sessionOn", false);
892
+ this._handleStickyOff(/*oContext*/);
893
+ }
894
+
895
+ send(this.getView(), Activity.Discard, oActiveDocumentContext);
896
+
897
+ this._setEditMode(EditMode.Display, false);
898
+ this._setDraftStatus(DraftStatus.Clear);
899
+
900
+ //in case of a new document, the value of hasActiveEntity is returned. navigate back.
901
+ if (!oActiveDocumentContext) {
902
+ EditState.setEditStateDirty();
903
+ return mInParameters.skipBackNavigation ? undefined : this._getRoutingListener().navigateBackFromContext(oContext);
904
+ } else if (sProgrammingModel === ProgrammingModel.Draft) {
905
+ // We need to load the semantic keys of the active context, as we need them
906
+ // for the navigation
907
+ return this._fetchSemanticKeyValues(oActiveDocumentContext).then(() => {
908
+ // We force the recreation of the context, so that it's created and bound in the same microtask,
909
+ // so that all properties are loaded together by autoExpandSelect, so that when switching back to Edit mode
910
+ // $$inheritExpandSelect takes all loaded properties into account (BCP 2070462265)
911
+ if (mInParameters.skipBindingToView) {
912
+ return oActiveDocumentContext;
913
+ } else {
914
+ return this._handleNewContext(oActiveDocumentContext, false, true, bDraftNavigation, true);
915
+ }
916
+ });
917
+ } else {
918
+ //active context is returned in case of cancel of existing document
919
+ return this._handleNewContext(oActiveDocumentContext, false, false, bDraftNavigation, true);
920
+ }
921
+ })
922
+ .catch(function(oError: any) {
923
+ Log.error("Error while discarding the document", oError);
924
+ });
925
+ }
926
+
927
+ // Internal only params ---
928
+ // @param {string} mParameters.entitySetName Name of the EntitySet to which the object belongs
929
+
930
+ /**
931
+ * Deletes the document.
932
+ *
933
+ * @memberof sap.fe.core.controllerextensions.EditFlow
934
+ * @param {object} oContext Context of the document
935
+ * @param {object} mInParameters Can contain the following attributes:
936
+ * @param {string} mInParameters.title Title of the object being deleted
937
+ * @param {string} mInParameters.description Description of the object being deleted
938
+ * @returns {Promise} Promise resolves once document has been deleted
939
+ * @alias sap.fe.core.controllerextensions.EditFlow#deleteDocument
940
+ * @public
941
+ * @since 1.90.0
942
+ */
943
+ @Public
944
+ @Final
945
+ deleteDocument(oContext: Context, mInParameters: { title: string; description: string }): Promise<void> {
946
+ const oAppComponent = CommonUtils.getAppComponent(this.getView());
947
+ const sPath = oContext.getPath();
948
+ let mParameters: any = mInParameters;
949
+ if (!mParameters) {
950
+ mParameters = {
951
+ bFindActiveContexts: false
952
+ };
953
+ } else {
954
+ mParameters.bFindActiveContexts = false;
955
+ }
956
+ mParameters.beforeDeleteCallBack = this.base.editFlow.onBeforeDelete;
957
+ return this._deleteDocumentTransaction(oContext, mParameters)
958
+ .then(() => {
959
+ // Single objet deletion is triggered from an OP header button (not from a list)
960
+ // --> Mark UI dirty and navigate back to dismiss the OP
961
+ EditState.setEditStateDirty();
962
+
963
+ send(this.getView(), Activity.Delete, sPath);
964
+
965
+ this._getRoutingListener().navigateBackFromContext(oContext);
966
+ // After delete is successfull, we need to dettch the setBackNavigation Methods
967
+ if (oAppComponent) {
968
+ oAppComponent.getShellServices().setBackNavigation();
969
+ }
970
+ })
971
+ .catch(function(oError: any) {
972
+ Log.error("Error while deleting the document", oError);
973
+ });
974
+ }
975
+
976
+ /**
977
+ * Submit the current set of changes and navigate back.
978
+ *
979
+ * @memberof sap.fe.core.controllerextensions.EditFlow
980
+ * @param {object} oContext Context of the document
981
+ * @returns {Promise} Promise resolves once the changes have been saved
982
+ * @alias sap.fe.core.controllerextensions.EditFlow#applyDocument
983
+ * @public
984
+ * @since 1.90.0
985
+ */
986
+ @Public
987
+ @Final
988
+ applyDocument(oContext: object): Promise<void> {
989
+ const oLockObject = this._getGlobalUIModel();
990
+ BusyLocker.lock(oLockObject);
991
+ return (
992
+ this._submitOpenChanges(oContext)
993
+ // check if there are any validation/parse errors
994
+ .then(this._checkForValidationErrors.bind(this, oContext))
995
+ .then(() => {
996
+ this._getMessageHandler().showMessageDialog();
997
+ this._getRoutingListener().navigateBackFromContext(oContext);
998
+ return true;
999
+ })
1000
+ .finally(function() {
1001
+ if (BusyLocker.isLocked(oLockObject)) {
1002
+ BusyLocker.unlock(oLockObject);
1003
+ }
1004
+ })
1005
+ );
1006
+ }
1007
+
1008
+ // Internal only params ---
1009
+ // @param {boolean} [mParameters.bStaticAction] Boolean value for static action, undefined for other actions
1010
+ // @param {boolean} [mParameters.isNavigable] Boolean value indicating whether navigation is required after the action has been executed
1011
+ // Currently the parameter isNavigable is used internally and should be changed to requiresNavigation as it is a more apt name for this param
1012
+
1013
+ /**
1014
+ * Invokes an action (bound or unbound) and tracks the changes so that other pages can be refreshed and show the updated data upon navigation.
1015
+ *
1016
+ * @memberof sap.fe.core.controllerextensions.EditFlow
1017
+ * @param {string} sActionName The name of the action to be called
1018
+ * @param {object} mInParameters Contains the following attributes:
1019
+ * @param {sap.ui.model.odata.v4.Context} mInParameters.contexts For a bound action, a context or an array with contexts for which the action is to be called must be provided
1020
+ * @param {sap.ui.model.odata.v4.ODataModel} mInParameters.model For an unbound action, an instance of an OData V4 model must be provided
1021
+ * @param {boolean} mInParameters.requiresNavigation Boolean value indicating whether navigation is required after the action has been executed. Navigation takes place to the context returned by the action
1022
+ * @param {string} mInParameters.label A human-readable label for the action. This is needed in case the action has a parameter and a parameter dialog is shown to the user. The label will be used for the title of the dialog and for the confirmation button
1023
+ * @param {string} mInParameters.invocationGrouping Mode how actions are to be called: 'ChangeSet' to put all action calls into one changeset, 'Isolated' to put them into separate changesets
1024
+ * @param {object} mExtraParams PRIVATE
1025
+ * @returns {Promise}
1026
+ * @alias sap.fe.core.controllerextensions.EditFlow#invokeAction
1027
+ * @public
1028
+ * @since 1.90.0
1029
+ * @final
1030
+ **/
1031
+ @Public
1032
+ @Final
1033
+ invokeAction(
1034
+ sActionName: string,
1035
+ mInParameters?: {
1036
+ contexts?: Context | Context[];
1037
+ model?: ODataModel;
1038
+ requiresNavigation?: boolean;
1039
+ label?: string;
1040
+ invocationGrouping?: string;
1041
+ },
1042
+ mExtraParams?: any
1043
+ ): Promise<void> {
1044
+ let oControl: any;
1045
+ const transactionHelper = this._getTransactionHelper();
1046
+ let oCurrentControl;
1047
+ let oBindingContext;
1048
+ let aParts;
1049
+ let sOverloadEntityType;
1050
+ let oCurrentActionCallBacks: any;
1051
+ const oView = this.getView();
1052
+
1053
+ let mParameters: any = mInParameters || {};
1054
+
1055
+ // Due to a mistake the invokeAction in the extensionAPI had a different API than this one.
1056
+ // The one from the extensionAPI doesn't exist anymore as we expose the full edit flow now but
1057
+ // due to compatibility reasons we still need to support the old signature
1058
+ if ((mParameters.isA && mParameters.isA("sap.ui.model.odata.v4.Context")) || Array.isArray(mParameters) || arguments.length === 3) {
1059
+ const contexts = mParameters;
1060
+ mParameters = mExtraParams || {};
1061
+ if (contexts) {
1062
+ mParameters.contexts = contexts;
1063
+ } else {
1064
+ mParameters.model = this.getView().getModel();
1065
+ }
1066
+ }
1067
+
1068
+ mParameters.isNavigable = mParameters.requiresNavigation || mParameters.isNavigable;
1069
+
1070
+ if (!mParameters.parentControl) {
1071
+ mParameters.parentControl = this.getView();
1072
+ }
1073
+
1074
+ if (mParameters.controlId) {
1075
+ oControl = this.getView().byId(mParameters.controlId);
1076
+ if (oControl) {
1077
+ // TODO: currently this selected contexts update is done within the operation, should be moved out
1078
+ mParameters.internalModelContext = oControl.getBindingContext("internal");
1079
+ }
1080
+ } else {
1081
+ mParameters.internalModelContext = oView.getBindingContext("internal");
1082
+ }
1083
+
1084
+ if (sActionName && sActionName.indexOf("(") > -1) {
1085
+ // get entity type of action overload and remove it from the action path
1086
+ // Example sActionName = "<ActionName>(Collection(<OverloadEntityType>))"
1087
+ // sActionName = aParts[0] --> <ActionName>
1088
+ // sOverloadEntityType = aParts[2] --> <OverloadEntityType>
1089
+ aParts = sActionName.split("(");
1090
+ sActionName = aParts[0];
1091
+ sOverloadEntityType = (aParts[aParts.length - 1] as any).replaceAll(")", "");
1092
+ }
1093
+
1094
+ if (mParameters.bStaticAction) {
1095
+ if (oControl.isTableBound()) {
1096
+ mParameters.contexts = oControl.getRowBinding().getHeaderContext();
1097
+ } else {
1098
+ const sBindingPath = oControl.data("rowsBindingInfo").path,
1099
+ oListBinding = new (ODataListBinding as any)(this.getView().getModel(), sBindingPath);
1100
+ mParameters.contexts = oListBinding.getHeaderContext();
1101
+ }
1102
+
1103
+ if (sOverloadEntityType) {
1104
+ const sTableContextEntityType = mParameters.contexts
1105
+ .getModel()
1106
+ .getMetaModel()
1107
+ .getMetaContext(mParameters.contexts.getPath())
1108
+ .getObject("$Type");
1109
+ if (sOverloadEntityType !== sTableContextEntityType) {
1110
+ // search for context in control tree hierarchy
1111
+ oCurrentControl = oControl;
1112
+ while (oCurrentControl) {
1113
+ oBindingContext = oCurrentControl.getBindingContext();
1114
+ if (
1115
+ oBindingContext &&
1116
+ oBindingContext
1117
+ .getModel()
1118
+ .getMetaModel()
1119
+ .getMetaContext(oBindingContext.getPath())
1120
+ .getObject("$Type") === sOverloadEntityType
1121
+ ) {
1122
+ mParameters.contexts = oBindingContext;
1123
+ break;
1124
+ } else {
1125
+ // check parent
1126
+ oCurrentControl = oCurrentControl.getParent();
1127
+ }
1128
+ }
1129
+ // context was not found in UI hierarchy going straight upwards - try to find it in SubSections
1130
+ if (!oCurrentControl) {
1131
+ const oActionOverloadContext = this._getActionOverloadContextFromSubSections(oControl, sOverloadEntityType);
1132
+ if (oActionOverloadContext !== undefined) {
1133
+ mParameters.contexts = oActionOverloadContext;
1134
+ }
1135
+ }
1136
+
1137
+ if (!mParameters.contexts) {
1138
+ return Promise.reject("Context not found for entity type " + sOverloadEntityType);
1139
+ }
1140
+ }
1141
+ }
1142
+
1143
+ if (mParameters.enableAutoScroll) {
1144
+ oCurrentActionCallBacks = this._createActionPromise(sActionName, oControl.sId);
1145
+ }
1146
+ }
1147
+
1148
+ if (mParameters.isNavigable) {
1149
+ mParameters.bGetBoundContext = false;
1150
+ } else {
1151
+ mParameters.bGetBoundContext = true;
1152
+ }
1153
+ // Need to know that the action is called from ObjectPage for changeSet Isolated workaround
1154
+ mParameters.bObjectPage = (oView.getViewData() as any).converterType === "ObjectPage";
1155
+ return this._syncTask()
1156
+ .then(transactionHelper.callAction.bind(transactionHelper, sActionName, mParameters, this.getView(), this._getMessageHandler()))
1157
+ .then((oResponse: any) => {
1158
+ // if the returned context for the bound action is different than the context on which action was called,
1159
+ // refresh the corresponding list binding
1160
+ if (mParameters.contexts) {
1161
+ return this._refreshListIfRequired(
1162
+ this._getActionResponseDataAndKeys(sActionName, oResponse),
1163
+ mParameters.contexts[0]
1164
+ ).then(function() {
1165
+ return oResponse;
1166
+ });
1167
+ }
1168
+ })
1169
+ .then((oResponse: any) => {
1170
+ send(this.getView(), Activity.Action, mParameters.contexts);
1171
+
1172
+ if (oCurrentActionCallBacks) {
1173
+ oCurrentActionCallBacks.fResolver(oResponse);
1174
+ }
1175
+ /*
1176
+ We set the (upper) pages to dirty after an execution of an action
1177
+ TODO: get rid of this workaround
1178
+ This workaround is only needed as long as the model does not support the synchronization.
1179
+ Once this is supported we don't need to set the pages to dirty anymore as the context itself
1180
+ is already refreshed (it's just not reflected in the object page)
1181
+ we explicitly don't call this method from the list report but only call it from the object page
1182
+ as if it is called in the list report it's not needed - as we anyway will remove this logic
1183
+ we can live with this
1184
+ we need a context to set the upper pages to dirty - if there are more than one we use the
1185
+ first one as they are anyway siblings
1186
+ */
1187
+ if (mParameters.contexts) {
1188
+ EditState.setEditStateDirty();
1189
+ this._getInternalModel().setProperty("/sCustomAction", sActionName);
1190
+ }
1191
+ if (mParameters.isNavigable) {
1192
+ let vContext = oResponse;
1193
+ if (Array.isArray(vContext) && vContext.length === 1) {
1194
+ vContext = vContext[0];
1195
+ }
1196
+ if (vContext && !Array.isArray(vContext)) {
1197
+ const oMetaModel = oView.getModel().getMetaModel() as ODataMetaModel;
1198
+ const sContextMetaPath = oMetaModel.getMetaPath(vContext.getPath());
1199
+ const oActionContext = Array.isArray(mParameters.contexts) ? mParameters.contexts[0] : mParameters.contexts;
1200
+ const sActionContextMetaPath = oActionContext && oMetaModel.getMetaPath(oActionContext.getPath());
1201
+ if (sContextMetaPath != undefined && sContextMetaPath === sActionContextMetaPath) {
1202
+ if (oActionContext.getPath() !== vContext.getPath()) {
1203
+ this._getRoutingListener().navigateForwardToContext(vContext, {
1204
+ noHistoryEntry: false
1205
+ });
1206
+ } else {
1207
+ Log.info("Navigation to the same context is not allowed");
1208
+ }
1209
+ }
1210
+ }
1211
+ }
1212
+ })
1213
+ .catch(function(err: any) {
1214
+ if (oCurrentActionCallBacks) {
1215
+ oCurrentActionCallBacks.fRejector();
1216
+ }
1217
+ if (err == Constants.CancelActionDialog) {
1218
+ return Promise.reject("Dialog cancelled.");
1219
+ } else {
1220
+ return Promise.reject("Error in EditFlow.invokeAction:" + err);
1221
+ }
1222
+ });
1223
+ }
1224
+
1225
+ /**
1226
+ * Secured execution of the given function. Ensures that the function is only executed when certain conditions are fulfilled.
1227
+ *
1228
+ * @memberof sap.fe.core.controllerextensions.EditFlow
1229
+ * @param {Function} fnFunction The function to be executed. Should return a promise that is settled after completion of the execution. If nothing is returned, immediate completion is assumed.
1230
+ * @param {object} mParameters Definitions of the preconditions to be checked before execution
1231
+ * @param {object} mParameters.busy Defines the busy indicator
1232
+ * @param {boolean} mParameters.busy.set Triggers a busy indicator when the function is executed.
1233
+ * @param {boolean} mParameters.busy.check Executes function only if application isn't busy.
1234
+ * @param {boolean} mParameters.updatesDocument This operation updates the current document without using the bound model and context. As a result, the draft status is updated if a draft document exists, and the user has to confirm the cancellation of the editing process.
1235
+ * @returns {Promise} A promise that is rejected if the execution is prohibited and resolved by the promise returned by the fnFunction.
1236
+ * @alias sap.fe.core.controllerextensions.EditFlow#securedExecution
1237
+ * @public
1238
+ * @experimental As of version 1.90.0
1239
+ * @since 1.90.0
1240
+ */
1241
+ @Public
1242
+ @Final
1243
+ securedExecution(
1244
+ fnFunction: Function,
1245
+ mParameters?: {
1246
+ busy?: {
1247
+ set?: boolean;
1248
+ check?: boolean;
1249
+ };
1250
+ updatesDocument?: boolean;
1251
+ }
1252
+ ): Promise<void> {
1253
+ const bBusySet = mParameters && mParameters.busy && mParameters.busy.set !== undefined ? mParameters.busy.set : true,
1254
+ bBusyCheck = mParameters && mParameters.busy && mParameters.busy.check !== undefined ? mParameters.busy.check : true,
1255
+ bUpdatesDocument = (mParameters && (mParameters as any).updatesDocument) || false,
1256
+ oLockObject = this._getGlobalUIModel(),
1257
+ oContext = this.base.getView().getBindingContext(),
1258
+ bIsDraft = oContext && this._getProgrammingModel(oContext) === ProgrammingModel.Draft;
1259
+
1260
+ if (bBusyCheck && BusyLocker.isLocked(oLockObject)) {
1261
+ return Promise.reject("Application already busy therefore execution rejected");
1262
+ }
1263
+
1264
+ // we have to set busy and draft indicator immediately also the function might be executed later in queue
1265
+ if (bBusySet) {
1266
+ BusyLocker.lock(oLockObject);
1267
+ }
1268
+ if (bUpdatesDocument && bIsDraft) {
1269
+ this._setDraftStatus(DraftStatus.Saving);
1270
+ }
1271
+
1272
+ this._getMessageHandler().removeTransitionMessages();
1273
+
1274
+ return this._syncTask(fnFunction)
1275
+ .then(() => {
1276
+ if (bUpdatesDocument) {
1277
+ this._getTransactionHelper().handleDocumentModifications();
1278
+ EditState.setEditStateDirty();
1279
+ if (bIsDraft) {
1280
+ this._setDraftStatus(DraftStatus.Saved);
1281
+ }
1282
+ }
1283
+ })
1284
+ .catch((oError: any) => {
1285
+ if (bUpdatesDocument && bIsDraft) {
1286
+ this._setDraftStatus(DraftStatus.Clear);
1287
+ }
1288
+ return Promise.reject(oError);
1289
+ })
1290
+ .finally(() => {
1291
+ if (bBusySet) {
1292
+ BusyLocker.unlock(oLockObject);
1293
+ }
1294
+ return this._getMessageHandler().showMessageDialog();
1295
+ });
1296
+ }
1297
+
1298
+ /**
1299
+ * Handles the patchSent event: register document modification.
1300
+ *
1301
+ * @param oEvent
1302
+ */
1303
+ @Public
1304
+ handlePatchSent(oEvent: any) {
1305
+ this.mPatchPromises = this.mPatchPromises ? this.mPatchPromises : {};
1306
+ // do this for every unique object (eg: every table) so that each associated promise is fulfilled at the end
1307
+ const oPatchPromise = new Promise((resolve, reject) => {
1308
+ this.mPatchPromises[oEvent.getSource()] = {
1309
+ resolvePatchPromise: resolve,
1310
+ rejectPatchPromise: reject
1311
+ };
1312
+ });
1313
+ this.updateDocument(oEvent.getSource(), oPatchPromise);
1314
+ }
1315
+
1316
+ /**
1317
+ * Handles the patchCompleted event: resolves or rejects document modification.
1318
+ *
1319
+ * @param oEvent
1320
+ */
1321
+ @Public
1322
+ handlePatchCompleted(oEvent: any) {
1323
+ const bSuccess = oEvent.getParameter("success");
1324
+ if (bSuccess) {
1325
+ this.mPatchPromises[oEvent.getSource()].resolvePatchPromise();
1326
+ } else {
1327
+ this.mPatchPromises[oEvent.getSource()].rejectPatchPromise();
1328
+ }
1329
+ delete this.mPatchPromises[oEvent.getSource()];
1330
+ }
1331
+
1332
+ //////////////////////////////////////
1333
+ // Private methods
1334
+ //////////////////////////////////////
1335
+
1336
+ /*
1337
+ TO BE CHECKED / DISCUSSED
1338
+ _createMultipleDocuments and deleteMultiDocument - couldn't we combine them with create and delete document?
1339
+ _createActionPromise and deleteCurrentActionPromise -> next step
1340
+
1341
+ */
1342
+
1343
+ _setEditMode(sEditMode: any, bCreationMode?: boolean) {
1344
+ (this.base.getView().getController() as PageController)._editFlow.setEditMode(sEditMode, bCreationMode);
1345
+ }
1346
+
1347
+ _setDraftStatus(sDraftState: any) {
1348
+ (this.base.getView().getController() as PageController)._editFlow.setDraftStatus(sDraftState);
1349
+ }
1350
+
1351
+ _getRoutingListener() {
1352
+ return (this.base.getView().getController() as PageController)._editFlow.getRoutingListener();
1353
+ }
1354
+
1355
+ _getGlobalUIModel() {
1356
+ return (this.base.getView().getController() as PageController)._editFlow.getGlobalUIModel();
1357
+ }
1358
+ _syncTask(vTask?: any) {
1359
+ return (this.base.getView().getController() as PageController)._editFlow.syncTask(vTask);
1360
+ }
1361
+
1362
+ _getProgrammingModel(oContext: any) {
1363
+ return (this.base.getView().getController() as PageController)._editFlow.getProgrammingModel(oContext);
1364
+ }
1365
+
1366
+ _deleteDocumentTransaction(oContext: any, mParameters: any) {
1367
+ return (this.base.getView().getController() as PageController)._editFlow.deleteDocumentTransaction(oContext, mParameters);
1368
+ }
1369
+
1370
+ _handleCreateEvents(oBinding: any) {
1371
+ (this.base.getView().getController() as PageController)._editFlow.handleCreateEvents(oBinding);
1372
+ }
1373
+
1374
+ _getTransactionHelper() {
1375
+ return (this.base.getView().getController() as PageController)._editFlow.getTransactionHelper();
1376
+ }
1377
+
1378
+ _getInternalModel() {
1379
+ return (this.base.getView().getController() as PageController)._editFlow.getInternalModel();
1380
+ }
1381
+
1382
+ /**
1383
+ * Creates a new promise to wait for an action to be executed
1384
+ *
1385
+ * @function
1386
+ * @name _createActionPromise
1387
+ * @memberof sap.fe.core.controllerextensions.EditFlow
1388
+ *
1389
+ * @returns {Function} The resolver function which can be used to externally resolve the promise
1390
+ */
1391
+
1392
+ _createActionPromise(sActionName: any, sControlId: any) {
1393
+ return (this.base.getView().getController() as PageController)._editFlow.createActionPromise(sActionName, sControlId);
1394
+ }
1395
+
1396
+ _getCurrentActionPromise() {
1397
+ return (this.base.getView().getController() as PageController)._editFlow.getCurrentActionPromise();
1398
+ }
1399
+
1400
+ _deleteCurrentActionPromise() {
1401
+ return (this.base.getView().getController() as PageController)._editFlow.deleteCurrentActionPromise();
1402
+ }
1403
+
1404
+ _getMessageHandler() {
1405
+ return (this.base.getView().getController() as PageController)._editFlow.getMessageHandler();
1406
+ }
1407
+
1408
+ /**
1409
+ * @function
1410
+ * @name _getActionResponseDataAndKeys
1411
+ * @memberof sap.fe.core.controllerextensions.EditFlow
1412
+ * @param {string} sActionName The name of the action that is executed
1413
+ * @param {object} oResponse The bound action's response data or response context
1414
+ * @returns {object} Object with data and names of the key fields of the response
1415
+ */
1416
+ _getActionResponseDataAndKeys(sActionName: string, oResponse: object) {
1417
+ return (this.base.getView().getController() as PageController)._editFlow.getActionResponseDataAndKeys(sActionName, oResponse);
1418
+ }
1419
+
1420
+ _submitOpenChanges(oContext: any) {
1421
+ const oModel = oContext.getModel(),
1422
+ oLockObject = this._getGlobalUIModel();
1423
+ //Currently we are using only 1 updateGroupId, hence submitting the batch directly here
1424
+ return oModel
1425
+ .submitBatch("$auto")
1426
+ .then(function() {
1427
+ if (oModel.hasPendingChanges("$auto")) {
1428
+ // the submit was not successful
1429
+ return Promise.reject("submit of open changes failed");
1430
+ }
1431
+ })
1432
+ .finally(function() {
1433
+ if (BusyLocker.isLocked(oLockObject)) {
1434
+ BusyLocker.unlock(oLockObject);
1435
+ }
1436
+ });
1437
+ }
1438
+
1439
+ _handleStickyOn(oContext: Context) {
1440
+ return (this.base.getView().getController() as PageController)._editFlow.handleStickyOn(oContext);
1441
+ }
1442
+
1443
+ _handleStickyOff() {
1444
+ return (this.base.getView().getController() as PageController)._editFlow.handleStickyOff();
1445
+ }
1446
+
1447
+ _onBackNavigationInSession() {
1448
+ return (this.base.getView().getController() as PageController)._editFlow.onBackNavigationInSession();
1449
+ }
1450
+
1451
+ _discardStickySession(oContext: Context) {
1452
+ return (this.base.getView().getController() as PageController)._editFlow.discardStickySession(oContext);
1453
+ }
1454
+
1455
+ _handleNewContext(oContext: any, bEditable: boolean, bRecreateContext: boolean, bDraftNavigation: boolean, bForceFocus?: boolean) {
1456
+ EditState.setEditStateDirty();
1457
+
1458
+ return this._getRoutingListener().navigateToContext(oContext, {
1459
+ checkNoHashChange: true,
1460
+ editable: bEditable,
1461
+ bPersistOPScroll: true,
1462
+ bRecreateContext: bRecreateContext,
1463
+ bDraftNavigation: bDraftNavigation,
1464
+ showPlaceholder: false,
1465
+ bForceFocus: bForceFocus
1466
+ });
1467
+ }
1468
+
1469
+ /**
1470
+ * Checks if there are validation (parse) errors for controls bound to a given context
1471
+ *
1472
+ * @function
1473
+ * @name _checkForValidationErrors
1474
+ * @memberof sap.fe.core.controllerextensions.EditFlow
1475
+ * @returns {Promise} Promise resolves if there are no validation errors, and rejects if there are validation errors
1476
+ */
1477
+
1478
+ _checkForValidationErrors() {
1479
+ return this._syncTask().then(() => {
1480
+ const sViewId = this.base.getView().getId();
1481
+ const aMessages = sap.ui
1482
+ .getCore()
1483
+ .getMessageManager()
1484
+ .getMessageModel()
1485
+ .getData();
1486
+ let oControl;
1487
+ let oMessage;
1488
+
1489
+ if (!aMessages.length) {
1490
+ return Promise.resolve("No validation errors found");
1491
+ }
1492
+
1493
+ for (let i = 0; i < aMessages.length; i++) {
1494
+ oMessage = aMessages[i];
1495
+ if (oMessage.validation) {
1496
+ oControl = sap.ui.getCore().byId(oMessage.getControlId());
1497
+ while (oControl) {
1498
+ if (oControl.getId() === sViewId) {
1499
+ return Promise.reject("validation errors exist");
1500
+ }
1501
+ oControl = oControl.getParent();
1502
+ }
1503
+ }
1504
+ }
1505
+ });
1506
+ }
1507
+
1508
+ /**
1509
+ * @function
1510
+ * @name _refreshListIfRequired
1511
+ * @memberof sap.fe.core.controllerextensions.EditFlow
1512
+ * @param {object} oResponse The response of the bound action and the names of the key fields
1513
+ * @param {sap.ui.model.odata.v4.Context} oContext The bound context on which the action was executed
1514
+ * @returns {Promise} Always resolves to param oResponse
1515
+ */
1516
+ _refreshListIfRequired(oResponse: any, oContext: Context) {
1517
+ if (!oContext || !oResponse || !oResponse.oData) {
1518
+ return Promise.resolve();
1519
+ }
1520
+ const oBinding = oContext.getBinding();
1521
+ // refresh only lists
1522
+ if (oBinding && oBinding.isA("sap.ui.model.odata.v4.ODataListBinding")) {
1523
+ const oContextData = oResponse.oData;
1524
+ const aKeys = oResponse.keys;
1525
+ const oCurrentData = oContext.getObject();
1526
+ let bReturnedContextIsSame = true;
1527
+ // ensure context is in the response
1528
+ if (Object.keys(oContextData).length) {
1529
+ // check if context in response is different than the bound context
1530
+ bReturnedContextIsSame = aKeys.every(function(sKey: any) {
1531
+ return oCurrentData[sKey] === oContextData[sKey];
1532
+ });
1533
+ if (!bReturnedContextIsSame) {
1534
+ return new Promise<void>(resolve => {
1535
+ if ((oBinding as any).isRoot()) {
1536
+ oBinding.attachEventOnce("dataReceived", function() {
1537
+ resolve();
1538
+ });
1539
+ oBinding.refresh();
1540
+ } else {
1541
+ const oAppComponent = CommonUtils.getAppComponent(this.getView());
1542
+ oAppComponent
1543
+ .getSideEffectsService()
1544
+ .requestSideEffects([{ $NavigationPropertyPath: oBinding.getPath() }], oBinding.getContext() as Context)
1545
+ .then(
1546
+ function() {
1547
+ resolve();
1548
+ },
1549
+ function() {
1550
+ Log.error("Error while refreshing the table");
1551
+ resolve();
1552
+ }
1553
+ )
1554
+ .catch(function(e: any) {
1555
+ Log.error("Error while refreshing the table", e);
1556
+ });
1557
+ }
1558
+ });
1559
+ }
1560
+ }
1561
+ }
1562
+ // resolve with oResponse to not disturb the promise chain afterwards
1563
+ return Promise.resolve();
1564
+ }
1565
+
1566
+ _fetchSemanticKeyValues(oContext: any) {
1567
+ const oMetaModel = oContext.getModel().getMetaModel(),
1568
+ sEntitySetName = oMetaModel.getMetaContext(oContext.getPath()).getObject("@sapui.name"),
1569
+ aSemanticKeys = SemanticKeyHelper.getSemanticKeys(oMetaModel, sEntitySetName);
1570
+
1571
+ if (aSemanticKeys && aSemanticKeys.length) {
1572
+ const aRequestPromises = aSemanticKeys.map(function(oKey: any) {
1573
+ return oContext.requestObject(oKey.$PropertyPath);
1574
+ });
1575
+
1576
+ return Promise.all(aRequestPromises);
1577
+ } else {
1578
+ return Promise.resolve();
1579
+ }
1580
+ }
1581
+
1582
+ // Ugly Workaround to overcome mdc field issue, we remove the binding context before
1583
+ // switching to display mode to avoid the field reads additional values for non existing
1584
+ // drafts or sticky sessions in the backend
1585
+ _removeContextsFromPages() {
1586
+ let aPages: any[] = [];
1587
+ const oAppComponent = CommonUtils.getAppComponent(this.getView());
1588
+
1589
+ if (oAppComponent._isFclEnabled()) {
1590
+ const oFCL = oAppComponent.getRootContainer() as FlexibleColumnLayout;
1591
+ aPages = aPages.concat(oFCL.getMidColumnPages() || []);
1592
+ aPages = aPages.concat(oFCL.getEndColumnPages() || []);
1593
+ } else {
1594
+ const oNavContainer = oAppComponent.getRootContainer() as NavContainer;
1595
+ aPages = oNavContainer.getPages() || [];
1596
+ }
1597
+
1598
+ aPages.forEach(function(oPage: any) {
1599
+ if (oPage.isA("sap.ui.core.ComponentContainer")) {
1600
+ oPage = oPage.getComponentInstance(); // The binding context is set at the component level, not the component container
1601
+ }
1602
+
1603
+ if (oPage.getBindingContext()) {
1604
+ oPage.setBindingContext(null);
1605
+ }
1606
+ });
1607
+ }
1608
+
1609
+ _getActionOverloadContextFromSubSections(oControl: any, sOverloadEntityType: string) {
1610
+ let oCurrentControl: any;
1611
+
1612
+ function _checkActions(aActions: Array<object>) {
1613
+ let oActionBindingContext: any;
1614
+ try {
1615
+ aActions.forEach(function(oAction: any) {
1616
+ oActionBindingContext = oAction.getBindingContext();
1617
+ if (
1618
+ oActionBindingContext
1619
+ .getModel()
1620
+ .getMetaModel()
1621
+ .getMetaContext(oActionBindingContext.getPath())
1622
+ .getObject("$Type") === sOverloadEntityType
1623
+ ) {
1624
+ throw "context found - stop actions loop";
1625
+ }
1626
+ });
1627
+ return undefined;
1628
+ } catch (e) {
1629
+ return oActionBindingContext;
1630
+ }
1631
+ }
1632
+
1633
+ function _checkSubSections(aSubSections: Array<object>) {
1634
+ let oActionBindingContext: any;
1635
+ try {
1636
+ aSubSections.forEach(function(oSubSection: any) {
1637
+ if (oActionBindingContext) {
1638
+ throw "context found - stop SubSections loop";
1639
+ }
1640
+ const aActions = oSubSection.getAggregation("actions");
1641
+ oActionBindingContext = _checkActions(aActions);
1642
+ });
1643
+ return oActionBindingContext ? oActionBindingContext : undefined;
1644
+ } catch (e) {
1645
+ return oActionBindingContext;
1646
+ }
1647
+ }
1648
+
1649
+ try {
1650
+ if (oControl === undefined) {
1651
+ throw new Error("input parameter oControl undefined when trying to determine the action overload context");
1652
+ }
1653
+
1654
+ oCurrentControl = oControl;
1655
+ while (!oCurrentControl.isA("sap.uxap.ObjectPageSection")) {
1656
+ oCurrentControl = oCurrentControl.getParent();
1657
+ }
1658
+
1659
+ if (!oCurrentControl) {
1660
+ throw new Error("ObjectPageSection not found in UI hierarchy");
1661
+ } else {
1662
+ const aSubSections = oCurrentControl.getAggregation("subSections");
1663
+ return _checkSubSections(aSubSections);
1664
+ }
1665
+ } catch (error) {
1666
+ Log.info(error);
1667
+ return undefined;
1668
+ }
1669
+ }
1670
+ }
1671
+
1672
+ export default EditFlow;