@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,978 @@
1
+ import Event from "sap/ui/base/Event";
2
+ import ControllerExtension from "sap/ui/core/mvc/ControllerExtension";
3
+ import ControllerExtensionMetadata from "sap/fe/core/controllerextensions/ControllerExtensionMetadata";
4
+ import OverrideExecution from "sap/ui/core/mvc/OverrideExecution";
5
+ import Component from "sap/ui/core/Component";
6
+ import CommonUtils from "sap/fe/core/CommonUtils";
7
+ import BusyLocker from "sap/fe/core/BusyLocker";
8
+ import SemanticKeyHelper from "sap/fe/core/helpers/SemanticKeyHelper";
9
+ import Filter from "sap/ui/model/Filter";
10
+ import FilterOperator from "sap/ui/model/FilterOperator";
11
+ import Log from "sap/base/Log";
12
+ import EditState from "sap/fe/core/helpers/EditState";
13
+ import ModelHelper from "sap/fe/core/helpers/ModelHelper";
14
+ import { Extensible, Final, Override, Public, UI5Class } from "sap/fe/core/helpers/ClassSupport";
15
+ import PageController from "sap/fe/core/PageController";
16
+ import View from "sap/ui/core/mvc/View";
17
+ import AppComponent from "sap/fe/core/AppComponent";
18
+ import { TemplateComponentType } from "sap/fe/core/TemplateComponent";
19
+ import Router from "sap/ui/core/routing/Router";
20
+ import RouterProxy from "sap/fe/core/RouterProxy";
21
+ import { RoutingService } from "sap/fe/core/services/RoutingServiceFactory";
22
+ import JSONModel from "sap/ui/model/json/JSONModel";
23
+ import ResourceBundle from "sap/base/i18n/ResourceBundle";
24
+ import Context from "sap/ui/model/odata/v4/Context";
25
+
26
+ /**
27
+ * {@link sap.ui.core.mvc.ControllerExtension Controller extension}
28
+ *
29
+ * @namespace
30
+ * @alias sap.fe.core.controllerextensions.InternalRouting
31
+ *
32
+ * @private
33
+ * @since 1.74.0
34
+ */
35
+ @UI5Class("sap.fe.core.controllerextensions.InternalRouting", ControllerExtensionMetadata)
36
+ class InternalRouting extends ControllerExtension {
37
+ private base!: PageController;
38
+ private _oView!: View;
39
+ private _oAppComponent!: AppComponent;
40
+ private _oPageComponent!: TemplateComponentType | null;
41
+ private _oRouter!: Router;
42
+ private _oRoutingService!: RoutingService;
43
+ private _oRouterProxy!: RouterProxy;
44
+ private _fnRouteMatchedBound!: Function;
45
+ private _oTargetInformation: any;
46
+
47
+ @Override()
48
+ onExit() {
49
+ this._oRoutingService && this._oRoutingService.detachRouteMatched(this._fnRouteMatchedBound);
50
+ }
51
+
52
+ @Override()
53
+ onInit() {
54
+ this._oView = this.base.getView();
55
+ this._oAppComponent = CommonUtils.getAppComponent(this._oView);
56
+ this._oPageComponent = Component.getOwnerComponentFor(this._oView) as TemplateComponentType;
57
+ this._oRouter = this._oAppComponent.getRouter();
58
+ this._oRouterProxy = (this._oAppComponent as any).getRouterProxy();
59
+
60
+ if (!this._oAppComponent || !this._oPageComponent) {
61
+ throw new Error("Failed to initialize controler extension 'sap.fe.core.controllerextesions.InternalRouting");
62
+ }
63
+
64
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
65
+ // @ts-ignore
66
+ if (this._oAppComponent === this._oPageComponent) {
67
+ // The view isn't hosted in a dedicated UIComponent, but directly in the app
68
+ // --> just keep the view
69
+ this._oPageComponent = null;
70
+ }
71
+
72
+ this._oAppComponent
73
+ .getService("routingService")
74
+ .then((oRoutingService: RoutingService) => {
75
+ this._oRoutingService = oRoutingService;
76
+ this._fnRouteMatchedBound = this._onRouteMatched.bind(this);
77
+ this._oRoutingService.attachRouteMatched(this._fnRouteMatchedBound);
78
+ this._oTargetInformation = oRoutingService.getTargetInformationFor(this._oPageComponent || this._oView);
79
+ })
80
+ .catch(function() {
81
+ throw new Error("This controller extension cannot work without a 'routingService' on the main AppComponent");
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Triggered every time this controller is a navigation target.
87
+ */
88
+ @Public
89
+ @Extensible(OverrideExecution.After)
90
+ onRouteMatched() {
91
+ /**/
92
+ }
93
+
94
+ @Public
95
+ @Extensible(OverrideExecution.After)
96
+ onRouteMatchedFinished() {
97
+ /**/
98
+ }
99
+
100
+ @Public
101
+ @Extensible(OverrideExecution.After)
102
+ onBeforeBinding(oBindingContext: any, mParameters?: any) {
103
+ const oRouting = (this.base.getView().getController() as any).routing;
104
+ if (oRouting && oRouting.onBeforeBinding) {
105
+ oRouting.onBeforeBinding(oBindingContext, mParameters);
106
+ }
107
+ }
108
+
109
+ @Public
110
+ @Extensible(OverrideExecution.After)
111
+ onAfterBinding(oBindingContext: any, mParameters?: any) {
112
+ (this._oAppComponent as any).getRootViewController().onContextBoundToView(oBindingContext);
113
+ const oRouting = (this.base.getView().getController() as any).routing;
114
+ if (oRouting && oRouting.onAfterBinding) {
115
+ oRouting.onAfterBinding(oBindingContext, mParameters);
116
+ }
117
+ }
118
+
119
+ ///////////////////////////////////////////////////////////
120
+ // Methods triggering a navigation after a user action
121
+ // (e.g. click on a table row, button, etc...)
122
+ ///////////////////////////////////////////////////////////
123
+
124
+ /**
125
+ * Navigates to the specified navigation target.
126
+ *
127
+ * @param {sap.ui.model.odata.v4.Context} oContext Context instance
128
+ * @param {string} sNavigationTargetName Navigation target name
129
+ * @param {object} oSemanticObject Semantic object
130
+ * @param {boolean} bPreserveHistory True to force the new URL to be added at the end of the browser history (no replace)
131
+ * @ui5-restricted
132
+ */
133
+ @Public
134
+ navigateToTarget(oContext: any, sNavigationTargetName: string, oSemanticObject?: object, bPreserveHistory?: boolean) {
135
+ const oNavigationConfiguration =
136
+ this._oPageComponent &&
137
+ this._oPageComponent.getNavigationConfiguration &&
138
+ this._oPageComponent.getNavigationConfiguration(sNavigationTargetName);
139
+ if (oNavigationConfiguration) {
140
+ const oDetailRoute = oNavigationConfiguration.detail;
141
+ const sRouteName = oDetailRoute.route;
142
+ const mParameterMapping = oDetailRoute.parameters;
143
+ this._oRoutingService.navigateTo(oContext, sRouteName, mParameterMapping, bPreserveHistory);
144
+ } else {
145
+ this._oRoutingService.navigateTo(oContext, null, null, bPreserveHistory);
146
+ }
147
+ this._oView.getViewData();
148
+ }
149
+
150
+ /**
151
+ * Navigates to the specified navigation target route.
152
+ *
153
+ * @param {string} sTargetRouteName Name of the target route
154
+ * @param {object} [oParameters] Parameters to be used with route to create the target hash
155
+ * @returns {Promise} Promise that is resolved when the navigation is finalized
156
+ * @ui5-restricted
157
+ */
158
+ @Public
159
+ navigateToRoute(sTargetRouteName: string, oParameters?: object) {
160
+ return this._oRoutingService.navigateToRoute(sTargetRouteName, oParameters);
161
+ }
162
+
163
+ /**
164
+ * Navigates to a specific context.
165
+ *
166
+ * @param {sap.ui.model.odata.v4.Context} oContext The context to be navigated to
167
+ * @param {object} [mParameters] Optional navigation parameters
168
+ * @returns {Promise} Promise resolved when the navigation has been triggered
169
+ *
170
+ * @ui5-restricted
171
+ */
172
+ @Public
173
+ @Final
174
+ navigateToContext(oContext: any, mParameters?: any): Promise<void> {
175
+ const oContextInfo: any = {};
176
+ mParameters = mParameters || {};
177
+
178
+ if (oContext.isA("sap.ui.model.odata.v4.ODataListBinding")) {
179
+ if (mParameters.asyncContext) {
180
+ // the context is either created async (Promise)
181
+ // We need to activate the routeMatchSynchro on the RouterProxy to avoid that
182
+ // the subsequent call to navigateToContext conflicts with the current one
183
+ this._oRouterProxy.activateRouteMatchSynchronization();
184
+
185
+ mParameters.asyncContext
186
+ .then((oContext: any) => {
187
+ // once the context is returned we navigate into it
188
+ this.navigateToContext(oContext, {
189
+ checkNoHashChange: mParameters.checkNoHashChange,
190
+ editable: mParameters.editable,
191
+ bPersistOPScroll: mParameters.bPersistOPScroll,
192
+ updateFCLLevel: mParameters.updateFCLLevel,
193
+ bForceFocus: mParameters.bForceFocus
194
+ });
195
+ })
196
+ .catch(function(oError: any) {
197
+ Log.error("Error with the async context", oError);
198
+ });
199
+ } else if (!mParameters.bDeferredContext) {
200
+ // Navigate to a list binding not yet supported
201
+ throw "navigation to a list binding is not yet supported";
202
+ }
203
+ }
204
+
205
+ if (mParameters.callExtension) {
206
+ const oInternalModel = this._oView.getModel("internal") as JSONModel;
207
+ oInternalModel.setProperty("/paginatorCurrentContext", null);
208
+
209
+ oContextInfo.sourceBindingContext = oContext.getObject();
210
+ oContextInfo.bindingContext = oContext;
211
+ if (mParameters.oEvent) {
212
+ oContextInfo.oEvent = mParameters.oEvent;
213
+ }
214
+ // Storing the selected context to use it in internal route navigation if neccessary.
215
+ const bOverrideNav = (this.base.getView().getController() as any).routing.onBeforeNavigation(oContextInfo);
216
+ if (bOverrideNav) {
217
+ oInternalModel.setProperty("/paginatorCurrentContext", oContext);
218
+ return Promise.resolve();
219
+ }
220
+ }
221
+ mParameters.FCLLevel = this._getFCLLevel();
222
+
223
+ return this._oRoutingService.navigateToContext(oContext, mParameters, this._oView.getViewData(), this._oTargetInformation);
224
+ }
225
+
226
+ /**
227
+ * Navigates backwards from a context.
228
+ *
229
+ * @param {sap.ui.model.odata.v4.Context} oContext Context to be navigated from
230
+ * @param {object} [mParameters] Optional navigation parameters
231
+ * @returns {Promise} Promise resolved when the navigation has been triggered
232
+ *
233
+ * @ui5-restricted
234
+ */
235
+ @Public
236
+ @Final
237
+ navigateBackFromContext(oContext: any, mParameters?: any) {
238
+ mParameters = mParameters || {};
239
+ mParameters.updateFCLLevel = -1;
240
+
241
+ return this.navigateToContext(oContext, mParameters);
242
+ }
243
+
244
+ /**
245
+ * Navigates forwards to a context.
246
+ *
247
+ * @param {sap.ui.model.odata.v4.Context} oContext Context to be navigated to
248
+ * @param {object} mParameters Optional navigation parameters
249
+ * @returns {Promise} Promise resolved when the navigation has been triggered
250
+ *
251
+ * @ui5-restricted
252
+ */
253
+ @Public
254
+ @Final
255
+ navigateForwardToContext(oContext: any, mParameters?: any) {
256
+ if (this._oView.getBindingContext("internal")?.getProperty("messageFooterContainsErrors") === true) {
257
+ return Promise.resolve();
258
+ }
259
+ mParameters = mParameters || {};
260
+ mParameters.updateFCLLevel = 1;
261
+
262
+ return this.navigateToContext(oContext, mParameters);
263
+ }
264
+
265
+ /**
266
+ * Navigates back in history if the current hash corresponds to a transient state.
267
+ */
268
+ @Public
269
+ @Final
270
+ navigateBackFromTransientState() {
271
+ const sHash = this._oRouterProxy.getHash();
272
+
273
+ // if triggered while navigating to (...), we need to navigate back
274
+ if (sHash.indexOf("(...)") !== -1) {
275
+ this._oRouterProxy.navBack();
276
+ }
277
+ }
278
+
279
+ @Public
280
+ @Final
281
+ navigateToMessagePage(sErrorMessage: any, mParameters: any) {
282
+ mParameters = mParameters || {};
283
+ if (this._oRouterProxy.getHash().indexOf("i-action=create") > -1) {
284
+ return this._oRouterProxy.navToHash(this._oRoutingService.getDefaultCreateHash());
285
+ } else {
286
+ mParameters.FCLLevel = this._getFCLLevel();
287
+
288
+ return (this._oAppComponent as any).getRootViewController().displayMessagePage(sErrorMessage, mParameters);
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Checks if one of the current views on the screen is bound to a given context.
294
+ *
295
+ * @param {sap.ui.model.odata.v4.Context} oContext
296
+ * @returns {boolean}
297
+ *
298
+ * @ui5-restricted
299
+ */
300
+ @Public
301
+ @Final
302
+ isCurrentStateImpactedBy(oContext: any) {
303
+ return this._oRoutingService.isCurrentStateImpactedBy(oContext);
304
+ }
305
+
306
+ ///////////////////////////////////////////////////////////
307
+ // Methods to bind the page when a route is matched
308
+ ///////////////////////////////////////////////////////////
309
+
310
+ /**
311
+ * Called when a route is matched.
312
+ * Builds the binding context from the navigation parameters, and bind the page accordingly.
313
+ *
314
+ * @param {object} oEvent
315
+ *
316
+ * @ui5-restricted
317
+ */
318
+ _onRouteMatched(oEvent: Event) {
319
+ // Check if the target for this view is part of the event targets
320
+ const aTargets = oEvent.getParameter("routeInformation") && oEvent.getParameter("routeInformation").targets;
321
+ if (!aTargets || aTargets.indexOf(this._oTargetInformation.targetName) === -1) {
322
+ return;
323
+ }
324
+
325
+ // Retrieve the binding context pattern
326
+ let sTarget;
327
+ if (this._oPageComponent && this._oPageComponent.getBindingContextPattern) {
328
+ sTarget = this._oPageComponent.getBindingContextPattern();
329
+ }
330
+ sTarget = sTarget || this._oTargetInformation.contextPattern;
331
+
332
+ if (sTarget === null || sTarget === undefined) {
333
+ // Don't do this if we already got sTarget == '', which is a valid target pattern
334
+ sTarget = oEvent.getParameter("routePattern");
335
+ }
336
+ sTarget = sTarget.replace(":?query:", "");
337
+
338
+ // Replace the parameters by their values in the binding context pattern
339
+ const mArguments = (oEvent.getParameters() as any).arguments;
340
+ let bDeferred = false;
341
+ const oNavigationParameters = oEvent.getParameter("navigationInfo");
342
+
343
+ for (const sKey in mArguments) {
344
+ const sValue = mArguments[sKey];
345
+ if (sValue === "..." && sTarget.indexOf("{" + sKey + "}") >= 0) {
346
+ bDeferred = true;
347
+ // Sometimes in preferredMode = create, the edit button is shown in background when the
348
+ // action parameter dialog shows up, setting bTargetEditable passes editable as true
349
+ // to onBeforeBinding in _bindTargetPage function
350
+ oNavigationParameters.bTargetEditable = true;
351
+ }
352
+ sTarget = sTarget.replace("{" + sKey + "}", sValue);
353
+ }
354
+ if (mArguments["?query"] && mArguments["?query"].hasOwnProperty("i-action")) {
355
+ oNavigationParameters.bActionCreate = true;
356
+ }
357
+
358
+ // the binding target is always absolute
359
+ if (sTarget && sTarget[0] !== "/") {
360
+ sTarget = "/" + sTarget;
361
+ }
362
+
363
+ this.onRouteMatched();
364
+
365
+ const oModel = this._oView.getModel();
366
+ let oOut;
367
+ if (bDeferred) {
368
+ oOut = this._bindDeferred(sTarget, oNavigationParameters);
369
+ } else {
370
+ oOut = this._bindPage(sTarget, oModel, oNavigationParameters);
371
+ }
372
+ // eslint-disable-next-line promise/catch-or-return
373
+ oOut.finally(() => {
374
+ this.onRouteMatchedFinished();
375
+ });
376
+
377
+ (this._oAppComponent as any).getRootViewController().updateUIStateForView(this._oView, this._getFCLLevel());
378
+ }
379
+
380
+ /**
381
+ * Deferred binding (during object creation).
382
+ *
383
+ * @param {string} sTargetPath The path to the deffered context
384
+ * @param {object} oNavigationParameters Navigation parameters
385
+ * @returns {Promise}
386
+ * @ui5-restricted
387
+ */
388
+ _bindDeferred(sTargetPath: string, oNavigationParameters: any) {
389
+ this.onBeforeBinding(null, { editable: oNavigationParameters.bTargetEditable });
390
+
391
+ if (oNavigationParameters.bDeferredContext || !oNavigationParameters.oAsyncContext) {
392
+ // either the context shall be created in the target page (deferred Context) or it shall
393
+ // be created async but the user refreshed the page / bookmarked this URL
394
+ // TODO: currently the target component creates this document but we shall move this to
395
+ // a central place
396
+ if (this._oPageComponent && this._oPageComponent.createDeferredContext) {
397
+ this._oPageComponent.createDeferredContext(
398
+ sTargetPath,
399
+ oNavigationParameters.useContext,
400
+ oNavigationParameters.bActionCreate
401
+ );
402
+ }
403
+ }
404
+
405
+ if (this._getBindingContext() && this._getBindingContext().hasPendingChanges()) {
406
+ // For now remove the pending changes to avoid the model raises errors and the object page is at least bound
407
+ // Ideally the user should be asked for
408
+ this._getBindingContext()
409
+ .getBinding()
410
+ .resetChanges();
411
+ }
412
+
413
+ // remove the context to avoid showing old data
414
+ this._setBindingContext(null);
415
+
416
+ this.onAfterBinding(null);
417
+ return Promise.resolve();
418
+ }
419
+
420
+ /**
421
+ * Sets the binding context of the page from a path.
422
+ *
423
+ * @param {string} sTargetPath The path to the context
424
+ * @param {sap.ui.model.odata.v4.ODataModel} oModel The OData model
425
+ * @param {object} oNavigationParameters Navigation parameters
426
+ * @returns {Promise}
427
+ * @ui5-restricted
428
+ */
429
+ _bindPage(sTargetPath: string, oModel: any, oNavigationParameters: object) {
430
+ if (sTargetPath === "") {
431
+ return Promise.resolve(this._bindPageToContext(null, oModel, oNavigationParameters));
432
+ } else {
433
+ return this._resolveSemanticPath(sTargetPath, oModel)
434
+ .then((sTechnicalPath: any) => {
435
+ this._bindPageToPath(sTechnicalPath, oModel, oNavigationParameters);
436
+ })
437
+ .catch((oError: any) => {
438
+ // Error handling for erroneous metadata request
439
+ const oResourceBundle = sap.ui.getCore().getLibraryResourceBundle("sap.fe.core") as ResourceBundle;
440
+
441
+ this.navigateToMessagePage(oResourceBundle.getText("C_COMMON_SAPFE_DATA_RECEIVED_ERROR"), {
442
+ title: oResourceBundle.getText("C_COMMON_SAPFE_ERROR"),
443
+ description: oError.message
444
+ });
445
+ });
446
+ }
447
+ }
448
+
449
+ /**
450
+ * Creates the filter to retrieve a context corresponding to a semantic path.
451
+ *
452
+ * @param {string} sSemanticPath The semantic path
453
+ * @param {Array} aSemanticKeys The semantic keys for the path
454
+ * @param {object} oMetaModel The instance of the meta model
455
+ * @returns {sap.ui.model.Filter} The filter
456
+ *
457
+ * @ui5-restricted
458
+ */
459
+ _createFilterFromSemanticPath(sSemanticPath: string, aSemanticKeys: any[], oMetaModel: object) {
460
+ const fnUnquoteAndDecode = function(sValue: any) {
461
+ if (sValue.indexOf("'") === 0 && sValue.lastIndexOf("'") === sValue.length - 1) {
462
+ // Remove the quotes from the value and decode special chars
463
+ sValue = decodeURIComponent(sValue.substring(1, sValue.length - 1));
464
+ }
465
+ return sValue;
466
+ };
467
+ const aKeyValues = sSemanticPath.substring(sSemanticPath.indexOf("(") + 1, sSemanticPath.length - 1).split(",");
468
+ let aFilters: Filter[];
469
+
470
+ if (aSemanticKeys.length != aKeyValues.length) {
471
+ return null;
472
+ }
473
+
474
+ const bFilteringCaseSensitive = ModelHelper.isFilteringCaseSensitive(oMetaModel);
475
+
476
+ if (aSemanticKeys.length === 1) {
477
+ // Take the first key value
478
+ const sKeyValue = fnUnquoteAndDecode(aKeyValues[0]);
479
+ aFilters = [
480
+ new Filter({
481
+ path: aSemanticKeys[0].$PropertyPath,
482
+ operator: FilterOperator.EQ,
483
+ value1: sKeyValue,
484
+ caseSensitive: bFilteringCaseSensitive
485
+ })
486
+ ];
487
+ } else {
488
+ const mKeyValues: any = {};
489
+ // Create a map of all key values
490
+ aKeyValues.forEach(function(sKeyAssignment: string) {
491
+ const aParts = sKeyAssignment.split("="),
492
+ sKeyValue = fnUnquoteAndDecode(aParts[1]);
493
+
494
+ mKeyValues[aParts[0]] = sKeyValue;
495
+ });
496
+
497
+ let bFailed = false;
498
+ aFilters = aSemanticKeys.map(function(oSemanticKey: any) {
499
+ const sKey = oSemanticKey.$PropertyPath,
500
+ sValue = mKeyValues[sKey];
501
+
502
+ if (sValue !== undefined) {
503
+ return new Filter({
504
+ path: sKey,
505
+ operator: FilterOperator.EQ,
506
+ value1: sValue,
507
+ caseSensitive: bFilteringCaseSensitive
508
+ });
509
+ } else {
510
+ bFailed = true;
511
+ return new Filter({
512
+ path: "XX"
513
+ }); // will be ignore anyway since we return after
514
+ }
515
+ });
516
+
517
+ if (bFailed) {
518
+ return null;
519
+ }
520
+ }
521
+
522
+ // Add a draft filter to make sure we take the draft entity if there is one
523
+ // Or the active entity otherwise
524
+ const oDraftFilter = new Filter({
525
+ filters: [new Filter("IsActiveEntity", "EQ", false), new Filter("SiblingEntity/IsActiveEntity", "EQ", null)],
526
+ and: false
527
+ });
528
+ aFilters.push(oDraftFilter);
529
+
530
+ const oCombinedFilter = new Filter(aFilters, true);
531
+ return oCombinedFilter;
532
+ }
533
+
534
+ /**
535
+ * Converts a path with semantic keys to a path with technical keys.
536
+ *
537
+ * @param {string} sSemanticPath The path with semantic keys
538
+ * @param {sap.ui.model.odata.v4.ODataModel} oModel The model for the path
539
+ * @param {Array} aSemanticKeys The semantic keys for the path
540
+ * @returns {Promise} A Promise containing the path with technical keys if sSemanticPath could be interpreted as a semantic path, null otherwise
541
+ *
542
+ * @ui5-restricted
543
+ */
544
+ _getTechnicalPathFromSemanticPath(sSemanticPath: string, oModel: any, aSemanticKeys: any[]) {
545
+ const oMetaModel = oModel.getMetaModel();
546
+ let sEntitySetPath = oMetaModel.getMetaContext(sSemanticPath).getPath();
547
+
548
+ if (!aSemanticKeys || aSemanticKeys.length === 0) {
549
+ // No semantic keys
550
+ return Promise.resolve(null);
551
+ }
552
+
553
+ // Create a set of filters corresponding to all keys
554
+ const oFilter = this._createFilterFromSemanticPath(sSemanticPath, aSemanticKeys, oMetaModel);
555
+ if (oFilter === null) {
556
+ // Couldn't interpret the path as a semantic one
557
+ return Promise.resolve(null);
558
+ }
559
+
560
+ // Load the corresponding object
561
+ if (!sEntitySetPath?.startsWith("/")) {
562
+ sEntitySetPath = "/" + sEntitySetPath;
563
+ }
564
+ const oListBinding = oModel.bindList(sEntitySetPath, undefined, undefined, oFilter, {
565
+ "$$groupId": "$auto.Heroes"
566
+ });
567
+
568
+ return oListBinding.requestContexts(0, 2).then(function(oContexts: any) {
569
+ if (oContexts && oContexts.length) {
570
+ return oContexts[0].getPath();
571
+ } else {
572
+ // No data could be loaded
573
+ return null;
574
+ }
575
+ });
576
+ }
577
+
578
+ /**
579
+ * Checks if a path is eligible for semantic bookmarking.
580
+ *
581
+ * @param {string} sPath The path to test
582
+ * @param {sap.ui.model.odata.v4.ODataMetaModel} oMetaModel The associated metadata model
583
+ * @returns {boolean} `true` if the path is eligible
584
+ *
585
+ * @ui5-restricted
586
+ */
587
+ _checkPathForSemanticBookmarking(sPath: string, oMetaModel: any) {
588
+ // Only path on root objects allow semantic bookmarking, i.e. sPath = xxx(yyy)
589
+ const aMatches = /^[\/]?(\w+)\([^\/]+\)$/.exec(sPath);
590
+ if (!aMatches) {
591
+ return false;
592
+ }
593
+ // Get the entitySet name
594
+ const sEntitySetPath = "/" + aMatches[1];
595
+ // Check the entity set supports draft (otherwise we don't support semantic bookmarking)
596
+ const oDraftRoot = oMetaModel.getObject(sEntitySetPath + "@com.sap.vocabularies.Common.v1.DraftRoot");
597
+ const oDraftNode = oMetaModel.getObject(sEntitySetPath + "@com.sap.vocabularies.Common.v1.DraftNode");
598
+ return oDraftRoot || oDraftNode ? true : false;
599
+ }
600
+
601
+ /**
602
+ * Builds a path with semantic keys from a path with technical keys.
603
+ * @param {string} sPathToResolve The path to be transformed
604
+ * @param oModel
605
+ * @returns {Promise} String promise for the new path. If sPathToResolved couldn't be interpreted as a semantic path, it is returned as is.
606
+ * @ui5-restricted
607
+ */
608
+ _resolveSemanticPath(sPathToResolve: string, oModel: any): Promise<string> {
609
+ const oMetaModel = oModel.getMetaModel();
610
+ const oLastSemanticMapping = this._oRoutingService.getLastSemanticMapping();
611
+ let sCurrentHashNoParams = this._oRouter
612
+ .getHashChanger()
613
+ .getHash()
614
+ .split("?")[0];
615
+
616
+ if (sCurrentHashNoParams && sCurrentHashNoParams.lastIndexOf("/") === sCurrentHashNoParams.length - 1) {
617
+ // Remove trailing '/'
618
+ sCurrentHashNoParams = sCurrentHashNoParams.substring(0, sCurrentHashNoParams.length - 1);
619
+ }
620
+
621
+ let sRootEntityName = sCurrentHashNoParams && sCurrentHashNoParams.substr(0, sCurrentHashNoParams.indexOf("("));
622
+ if (sRootEntityName.indexOf("/") === 0) {
623
+ sRootEntityName = sRootEntityName.substring(1);
624
+ }
625
+ const bAllowSemanticBookmark = this._checkPathForSemanticBookmarking(sCurrentHashNoParams, oMetaModel),
626
+ aSemanticKeys = bAllowSemanticBookmark && SemanticKeyHelper.getSemanticKeys(oMetaModel, sRootEntityName);
627
+ if (!aSemanticKeys) {
628
+ // No semantic keys available --> use the path as is
629
+ return Promise.resolve(sPathToResolve);
630
+ } else if (oLastSemanticMapping && oLastSemanticMapping.semanticPath === sPathToResolve) {
631
+ // This semantic path has been resolved previously
632
+ return Promise.resolve(oLastSemanticMapping.technicalPath);
633
+ } else {
634
+ // We need resolve the semantic path to get the technical keys
635
+ return this._getTechnicalPathFromSemanticPath(sCurrentHashNoParams, oModel, aSemanticKeys).then((sTechnicalPath: any) => {
636
+ if (sTechnicalPath && sTechnicalPath !== sPathToResolve) {
637
+ // The semantic path was resolved (otherwise keep the original value for target)
638
+ this._oRoutingService.setLastSemanticMapping({
639
+ technicalPath: sTechnicalPath,
640
+ semanticPath: sPathToResolve
641
+ });
642
+ return sTechnicalPath;
643
+ } else {
644
+ return sPathToResolve;
645
+ }
646
+ });
647
+ }
648
+ }
649
+
650
+ /**
651
+ * Sets the binding context of the page from a path.
652
+ *
653
+ * @param {string} sTargetPath The path to build the context. Needs to contain technical keys only.
654
+ * @param {sap.ui.model.odata.v4.ODataModel} oModel The OData model
655
+ * @param {object} oNavigationParameters Navigation parameters
656
+ *
657
+ * @ui5-restricted
658
+ */
659
+ _bindPageToPath(sTargetPath: string, oModel: any, oNavigationParameters: any) {
660
+ const oCurrentContext = this._getBindingContext(),
661
+ sCurrentPath = oCurrentContext && oCurrentContext.getPath(),
662
+ oUseContext = oNavigationParameters.useContext;
663
+
664
+ // We set the binding context only if it's different from the current one
665
+ // or if we have a context already selected
666
+ if (sCurrentPath !== sTargetPath || (oUseContext && oUseContext.getPath() === sTargetPath)) {
667
+ let oTargetContext;
668
+ if (oUseContext && oUseContext.getPath() === sTargetPath) {
669
+ // We already have the context to be used
670
+ oTargetContext = oUseContext;
671
+ } else {
672
+ // Otherwise we need to create it from sTargetPath
673
+ oTargetContext = this._createBindingContext(sTargetPath, oModel);
674
+ }
675
+ if (oTargetContext !== oCurrentContext) {
676
+ this._bindPageToContext(oTargetContext, oModel, oNavigationParameters);
677
+ }
678
+ } else if (!oNavigationParameters.bReasonIsIappState && EditState.isEditStateDirty()) {
679
+ this._refreshBindingContext(oCurrentContext);
680
+ }
681
+ }
682
+
683
+ /**
684
+ * Binds the page to a context.
685
+ *
686
+ * @param {sap.ui.model.odata.v4.Context} oContext Context to be bound
687
+ * @param {sap.ui.model.odata.v4.ODataModel} oModel The OData model
688
+ * @param {object} oNavigationParameters Navigation parameters
689
+ *
690
+ * @ui5-restricted
691
+ */
692
+ _bindPageToContext(oContext: any, oModel: any, oNavigationParameters: any) {
693
+ if (!oContext) {
694
+ this.onBeforeBinding(null);
695
+ this.onAfterBinding(null);
696
+ } else {
697
+ const oParentListBinding = oContext.getBinding();
698
+
699
+ if (!oContext.getBinding() || oContext.getBinding().isA("sap.ui.model.odata.v4.ODataListBinding")) {
700
+ // We need to recreate the context otherwise we get errors
701
+ oContext = this._createBindingContext(oContext.getPath(), oModel);
702
+ if (EditState.isEditStateDirty()) {
703
+ // TODO: as a workaround we invalidate the model cache while the app is dirty
704
+ // as the manage model sets the parent in an async task and the request side effects
705
+ // relies on the parent relationship we have to set a timeout 0
706
+ setTimeout(() => {
707
+ this._refreshBindingContext(oContext);
708
+ }, 0);
709
+ }
710
+ }
711
+
712
+ // Set the binding context with the proper before/after callbacks
713
+ this.onBeforeBinding(oContext, {
714
+ editable: oNavigationParameters.bTargetEditable,
715
+ listBinding: oParentListBinding,
716
+ bPersistOPScroll: oNavigationParameters.bPersistOPScroll,
717
+ bDraftNavigation: oNavigationParameters.bDraftNavigation,
718
+ showPlaceholder: oNavigationParameters.bShowPlaceholder
719
+ });
720
+
721
+ this._setBindingContext(oContext);
722
+ this.onAfterBinding(oContext);
723
+ }
724
+ }
725
+
726
+ /**
727
+ * Creates a binding context from a path.
728
+ *
729
+ * @param {string} sPath The path
730
+ * @param {sap.ui.model.odata.v4.ODataModel} oModel The OData model
731
+ * @returns {sap.ui.model.odata.v4.Context} Created context
732
+ *
733
+ * @ui5-restricted
734
+ */
735
+ _createBindingContext(sPath: string, oModel: any) {
736
+ const oPageComponent = this._oPageComponent,
737
+ sEntitySet = oPageComponent && oPageComponent.getEntitySet && oPageComponent.getEntitySet(),
738
+ sContextPath =
739
+ (oPageComponent && oPageComponent.getContextPath && oPageComponent.getContextPath()) || (sEntitySet && "/" + sEntitySet),
740
+ oMetaModel = oModel.getMetaModel(),
741
+ mParameters: any = {
742
+ $$patchWithoutSideEffects: true,
743
+ $$groupId: "$auto.Heroes",
744
+ $$updateGroupId: "$auto"
745
+ };
746
+
747
+ if (sEntitySet) {
748
+ const sMessagesPath = oMetaModel.getObject(sContextPath + "/@com.sap.vocabularies.Common.v1.Messages/$Path");
749
+ if (sMessagesPath) {
750
+ mParameters.$select = sMessagesPath;
751
+ }
752
+ }
753
+
754
+ // In case of draft: $select the state flags (HasActiveEntity, HasDraftEntity, and IsActiveEntity)
755
+ const oDraftRoot = oMetaModel.getObject(sContextPath + "@com.sap.vocabularies.Common.v1.DraftRoot");
756
+ const oDraftNode = oMetaModel.getObject(sContextPath + "@com.sap.vocabularies.Common.v1.DraftNode");
757
+ if (oDraftRoot || oDraftNode) {
758
+ if (mParameters.$select === undefined) {
759
+ mParameters.$select = "HasActiveEntity,HasDraftEntity,IsActiveEntity";
760
+ } else {
761
+ mParameters.$select += ",HasActiveEntity,HasDraftEntity,IsActiveEntity";
762
+ }
763
+ }
764
+
765
+ const oHiddenBinding = oModel.bindContext(sPath, undefined, mParameters);
766
+
767
+ oHiddenBinding.attachEventOnce("dataRequested", () => {
768
+ BusyLocker.lock(this._oView);
769
+ });
770
+ oHiddenBinding.attachEventOnce("dataReceived", this._dataReceivedEventHandler.bind(this));
771
+ return oHiddenBinding.getBoundContext();
772
+ }
773
+
774
+ _dataReceivedEventHandler(oEvent: Event) {
775
+ const sErrorDescription = oEvent && oEvent.getParameter("error");
776
+ BusyLocker.unlock(this._oView);
777
+ if (sErrorDescription) {
778
+ // TODO: in case of 404 the text shall be different
779
+ (sap.ui.getCore().getLibraryResourceBundle("sap.fe.core", true) as Promise<ResourceBundle>)
780
+ .then(oResourceBundle => {
781
+ const messageHandler = this.base.messageHandler;
782
+ let mParams = {};
783
+ if (sErrorDescription && sErrorDescription.status === 503) {
784
+ mParams = {
785
+ isInitialLoad503Error: true,
786
+ shellBack: true
787
+ };
788
+ } else {
789
+ mParams = {
790
+ title: oResourceBundle.getText("SAPFE_ERROR"),
791
+ description: sErrorDescription,
792
+ isDataReceivedError: true,
793
+ shellBack: true
794
+ };
795
+ }
796
+ messageHandler.showMessages(mParams);
797
+ })
798
+ .catch(function(oError) {
799
+ Log.error("Error while getting the core resource bundle", oError);
800
+ });
801
+ }
802
+ }
803
+
804
+ /**
805
+ * Requests side effects on a binding context to "refresh" it.
806
+ * TODO: get rid of this once provided by the model
807
+ * a refresh on the binding context does not work in case a creation row with a transient context is
808
+ * used. also a requestSideEffects with an empty path would fail due to the transient context
809
+ * therefore we get all dependent bindings (via private model method) to determine all paths and then
810
+ * request them.
811
+ *
812
+ * @param {sap.ui.model.odata.v4.Context} oBindingContext Context to be refreshed
813
+ *
814
+ * @ui5-restricted
815
+ */
816
+ _refreshBindingContext(oBindingContext: any) {
817
+ const oPageComponent = this._oPageComponent;
818
+ const oSideEffectsService = this._oAppComponent.getSideEffectsService();
819
+ const sRootContextPath = oBindingContext.getPath();
820
+ const sEntitySet = oPageComponent && oPageComponent.getEntitySet && oPageComponent.getEntitySet();
821
+ const sContextPath =
822
+ (oPageComponent && oPageComponent.getContextPath && oPageComponent.getContextPath()) || (sEntitySet && "/" + sEntitySet);
823
+ const oMetaModel = this._oView.getModel().getMetaModel();
824
+ let sMessagesPath;
825
+ const aNavigationPropertyPaths: any[] = [];
826
+ const aPropertyPaths: any[] = [];
827
+ const oSideEffects: any = {
828
+ TargetProperties: [],
829
+ TargetEntities: []
830
+ };
831
+
832
+ function getBindingPaths(oBinding: any) {
833
+ let aDependentBindings;
834
+ const sRelativePath = ((oBinding.getContext() && oBinding.getContext().getPath()) || "").replace(sRootContextPath, ""); // If no context, this is an absolute binding so no relative path
835
+ const sPath = (sRelativePath ? sRelativePath.slice(1) + "/" : sRelativePath) + oBinding.getPath();
836
+
837
+ if (oBinding.isA("sap.ui.model.odata.v4.ODataContextBinding")) {
838
+ // if (sPath === "") {
839
+ // now get the dependent bindings
840
+ aDependentBindings = oBinding.getDependentBindings();
841
+ if (aDependentBindings) {
842
+ // ask the dependent bindings (and only those with the specified groupId
843
+ //if (aDependentBindings.length > 0) {
844
+ for (let i = 0; i < aDependentBindings.length; i++) {
845
+ getBindingPaths(aDependentBindings[i]);
846
+ }
847
+ } else if (aNavigationPropertyPaths.indexOf(sPath) === -1) {
848
+ aNavigationPropertyPaths.push(sPath);
849
+ }
850
+ } else if (oBinding.isA("sap.ui.model.odata.v4.ODataListBinding")) {
851
+ if (aNavigationPropertyPaths.indexOf(sPath) === -1) {
852
+ aNavigationPropertyPaths.push(sPath);
853
+ }
854
+ } else if (oBinding.isA("sap.ui.model.odata.v4.ODataPropertyBinding")) {
855
+ if (aPropertyPaths.indexOf(sPath) === -1) {
856
+ aPropertyPaths.push(sPath);
857
+ }
858
+ }
859
+ }
860
+
861
+ if (sContextPath) {
862
+ sMessagesPath = oMetaModel.getObject(sContextPath + "/@com.sap.vocabularies.Common.v1.Messages/$Path");
863
+ }
864
+
865
+ // binding of the context must have $$PatchWithoutSideEffects true, this bound context may be needed to be fetched from the dependent binding
866
+ getBindingPaths(oBindingContext.getBinding());
867
+
868
+ let i;
869
+ for (i = 0; i < aNavigationPropertyPaths.length; i++) {
870
+ oSideEffects.TargetEntities.push({
871
+ $NavigationPropertyPath: aNavigationPropertyPaths[i]
872
+ });
873
+ }
874
+ oSideEffects.TargetProperties = aPropertyPaths;
875
+ if (sMessagesPath) {
876
+ oSideEffects.TargetProperties.push({
877
+ $PropertyPath: sMessagesPath
878
+ });
879
+ }
880
+ oSideEffectsService.requestSideEffects(oSideEffects.TargetEntities.concat(oSideEffects.TargetProperties), oBindingContext);
881
+ }
882
+
883
+ /**
884
+ * Gets the binding context of the page or the component.
885
+ *
886
+ * @returns {sap.ui.model.odata.v4.Context} The binding context
887
+ *
888
+ * @ui5-restricted
889
+ */
890
+ _getBindingContext(): Context {
891
+ if (this._oPageComponent) {
892
+ return this._oPageComponent.getBindingContext() as Context;
893
+ } else {
894
+ return this._oView.getBindingContext() as Context;
895
+ }
896
+ }
897
+
898
+ /**
899
+ * Sets the binding context of the page or the component.
900
+ *
901
+ * @param {sap.ui.model.odata.v4.Context} oContext The binding context
902
+ *
903
+ * @ui5-restricted
904
+ */
905
+ _setBindingContext(oContext: any) {
906
+ if (this._oPageComponent) {
907
+ this._oPageComponent.setBindingContext(oContext);
908
+ } else {
909
+ this._oView.setBindingContext(oContext);
910
+ }
911
+ }
912
+
913
+ /**
914
+ * Gets the flexible column layout (FCL) level corresponding to the view (-1 if the app is not FCL).
915
+ *
916
+ * @returns {number} The level
917
+ *
918
+ * @ui5-restricted
919
+ */
920
+ _getFCLLevel() {
921
+ return this._oTargetInformation.FCLLevel;
922
+ }
923
+
924
+ /**
925
+ * Switches between column and full-screen mode when FCL is used.
926
+ *
927
+ * @ui5-restricted
928
+ */
929
+
930
+ @Public
931
+ @Final
932
+ switchFullScreen() {
933
+ const oSource = this.base.getView();
934
+ const oFCLHelperModel = oSource.getModel("fclhelper"),
935
+ bIsFullScreen = oFCLHelperModel.getProperty("/actionButtonsInfo/isFullScreen"),
936
+ sNextLayout = oFCLHelperModel.getProperty(
937
+ bIsFullScreen ? "/actionButtonsInfo/exitFullScreen" : "/actionButtonsInfo/fullScreen"
938
+ ),
939
+ oRootViewController = (this._oAppComponent as any).getRootViewController();
940
+
941
+ const oContext = oRootViewController.getRightmostContext ? oRootViewController.getRightmostContext() : oSource.getBindingContext();
942
+
943
+ this.base._routing.navigateToContext(oContext, { sLayout: sNextLayout }).catch(function() {
944
+ Log.warning("cannot switch between column and fullscreen");
945
+ });
946
+ }
947
+
948
+ /**
949
+ * Closes the column for the current view in a FCL.
950
+ *
951
+ * @ui5-restricted
952
+ */
953
+ @Public
954
+ @Extensible(OverrideExecution.Before)
955
+ closeColumn() {
956
+ const oSource = this.base.getView();
957
+ const oViewData = oSource.getViewData() as any;
958
+ const oContext = oSource.getBindingContext() as Context;
959
+ const base = this.base;
960
+ const oMetaModel = oContext.getModel().getMetaModel();
961
+
962
+ if (oViewData && oViewData.viewLevel === 1 && ModelHelper.isDraftSupported(oMetaModel, oContext.getPath())) {
963
+ CommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(
964
+ function() {
965
+ base._routing.navigateBackFromContext(oContext, { noPreservationCache: true });
966
+ },
967
+ Function.prototype,
968
+ oContext,
969
+ oSource.getController(),
970
+ false
971
+ );
972
+ } else {
973
+ base._routing.navigateBackFromContext(oContext, { noPreservationCache: true });
974
+ }
975
+ }
976
+ }
977
+
978
+ export default InternalRouting;