@sapui5/sap.fe.core 1.99.0 → 1.101.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/package.json +6 -4
  2. package/src/sap/fe/core/.library +2 -3
  3. package/src/sap/fe/core/AnnotationHelper.js +43 -92
  4. package/src/sap/fe/core/AnnotationHelper.ts +43 -107
  5. package/src/sap/fe/core/AppComponent.js +381 -399
  6. package/src/sap/fe/core/AppComponent.ts +397 -0
  7. package/src/sap/fe/core/AppStateHandler.js +131 -162
  8. package/src/sap/fe/core/AppStateHandler.ts +2 -2
  9. package/src/sap/fe/core/BaseController.js +82 -58
  10. package/src/sap/fe/core/BaseController.ts +67 -0
  11. package/src/sap/fe/core/CommonUtils.js +179 -31
  12. package/src/sap/fe/core/CommonUtils.ts +295 -125
  13. package/src/sap/fe/core/ExtensionAPI.js +279 -274
  14. package/src/sap/fe/core/ExtensionAPI.ts +242 -0
  15. package/src/sap/fe/core/PageController.js +158 -29
  16. package/src/sap/fe/core/PageController.ts +65 -37
  17. package/src/sap/fe/core/RouterProxy.js +700 -750
  18. package/src/sap/fe/core/RouterProxy.ts +47 -31
  19. package/src/sap/fe/core/Synchronization.js +21 -31
  20. package/src/sap/fe/core/TemplateComponent.js +193 -118
  21. package/src/sap/fe/core/TemplateComponent.ts +104 -109
  22. package/src/sap/fe/core/TemplateModel.js +24 -44
  23. package/src/sap/fe/core/TemplateModel.ts +3 -3
  24. package/src/sap/fe/core/TransactionHelper.js +1368 -1369
  25. package/src/sap/fe/core/TransactionHelper.ts +201 -171
  26. package/src/sap/fe/core/actions/collaboration/ActivitySync.js +406 -0
  27. package/src/sap/fe/core/actions/collaboration/ActivitySync.ts +362 -0
  28. package/src/sap/fe/core/actions/collaboration/CollaborationCommon.js +146 -0
  29. package/src/sap/fe/core/actions/collaboration/CollaborationCommon.ts +129 -0
  30. package/src/sap/fe/core/actions/collaboration/Manage.js +264 -0
  31. package/src/sap/fe/core/actions/collaboration/Manage.ts +246 -0
  32. package/src/sap/fe/core/actions/collaboration/ManageDialog.fragment.xml +100 -0
  33. package/src/sap/fe/core/actions/collaboration/UserDetails.fragment.xml +13 -0
  34. package/src/sap/fe/core/actions/draft.js +324 -220
  35. package/src/sap/fe/core/actions/draft.ts +209 -133
  36. package/src/sap/fe/core/actions/messageHandling.js +79 -48
  37. package/src/sap/fe/core/actions/messageHandling.ts +113 -83
  38. package/src/sap/fe/core/actions/operations.js +37 -18
  39. package/src/sap/fe/core/actions/operations.ts +51 -20
  40. package/src/sap/fe/core/actions/sticky.js +17 -4
  41. package/src/sap/fe/core/actions/sticky.ts +21 -4
  42. package/src/sap/fe/core/buildingBlocks/AttributeModel.js +60 -0
  43. package/src/sap/fe/core/buildingBlocks/AttributeModel.ts +37 -0
  44. package/src/sap/fe/core/buildingBlocks/BuildingBlock.js +165 -0
  45. package/src/sap/fe/core/buildingBlocks/BuildingBlock.ts +178 -0
  46. package/src/sap/fe/core/buildingBlocks/BuildingBlockRuntime.js +707 -0
  47. package/src/sap/fe/core/buildingBlocks/BuildingBlockRuntime.ts +628 -0
  48. package/src/sap/fe/core/buildingBlocks/TraceInfo.js +436 -0
  49. package/src/sap/fe/core/buildingBlocks/TraceInfo.ts +431 -0
  50. package/src/sap/fe/core/controllerextensions/EditFlow.js +1854 -1669
  51. package/src/sap/fe/core/controllerextensions/EditFlow.ts +1792 -0
  52. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +79 -54
  53. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.ts +60 -0
  54. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +716 -779
  55. package/src/sap/fe/core/controllerextensions/InternalEditFlow.ts +785 -0
  56. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +796 -816
  57. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.ts +810 -0
  58. package/src/sap/fe/core/controllerextensions/InternalRouting.js +1056 -1005
  59. package/src/sap/fe/core/controllerextensions/InternalRouting.ts +1001 -0
  60. package/src/sap/fe/core/controllerextensions/KPIManagement.js +498 -532
  61. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +13 -12
  62. package/src/sap/fe/core/controllerextensions/MassEdit.js +141 -169
  63. package/src/sap/fe/core/controllerextensions/MassEdit.ts +155 -0
  64. package/src/sap/fe/core/controllerextensions/MessageHandler.js +221 -244
  65. package/src/sap/fe/core/controllerextensions/MessageHandler.ts +215 -0
  66. package/src/sap/fe/core/controllerextensions/PageReady.js +312 -345
  67. package/src/sap/fe/core/controllerextensions/PageReady.ts +57 -53
  68. package/src/sap/fe/core/controllerextensions/Paginator.js +188 -175
  69. package/src/sap/fe/core/controllerextensions/Paginator.ts +169 -0
  70. package/src/sap/fe/core/controllerextensions/Placeholder.js +157 -149
  71. package/src/sap/fe/core/controllerextensions/Placeholder.ts +149 -0
  72. package/src/sap/fe/core/controllerextensions/Routing.js +144 -125
  73. package/src/sap/fe/core/controllerextensions/Routing.ts +131 -0
  74. package/src/sap/fe/core/controllerextensions/RoutingListener.js +7 -6
  75. package/src/sap/fe/core/controllerextensions/RoutingListener.ts +3 -0
  76. package/src/sap/fe/core/controllerextensions/Share.js +230 -268
  77. package/src/sap/fe/core/controllerextensions/Share.ts +231 -0
  78. package/src/sap/fe/core/controllerextensions/SideEffects.js +603 -644
  79. package/src/sap/fe/core/controllerextensions/SideEffects.ts +68 -68
  80. package/src/sap/fe/core/controllerextensions/ViewState.js +774 -806
  81. package/src/sap/fe/core/controllerextensions/ViewState.ts +796 -0
  82. package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +2 -2
  83. package/src/sap/fe/core/controls/ActionPartial.fragment.xml +2 -2
  84. package/src/sap/fe/core/controls/Any.js +28 -0
  85. package/src/sap/fe/core/controls/Any.ts +30 -0
  86. package/src/sap/fe/core/controls/CommandExecution.js +92 -68
  87. package/src/sap/fe/core/controls/CommandExecution.ts +72 -0
  88. package/src/sap/fe/core/controls/ConditionalWrapper.js +165 -79
  89. package/src/sap/fe/core/controls/ConditionalWrapper.ts +74 -0
  90. package/src/sap/fe/core/controls/CustomFilterFieldContentWrapper.js +366 -0
  91. package/src/sap/fe/core/controls/CustomFilterFieldContentWrapper.ts +278 -0
  92. package/src/sap/fe/core/controls/CustomQuickViewPage.js +167 -125
  93. package/src/sap/fe/core/controls/CustomQuickViewPage.ts +116 -0
  94. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossDraft.fragment.xml +44 -5
  95. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +163 -122
  96. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.ts +155 -0
  97. package/src/sap/fe/core/controls/FieldWrapper.js +212 -141
  98. package/src/sap/fe/core/controls/FieldWrapper.ts +104 -0
  99. package/src/sap/fe/core/controls/FileWrapper.js +313 -0
  100. package/src/sap/fe/core/controls/FileWrapper.ts +169 -0
  101. package/src/sap/fe/core/controls/FilterBar.js +197 -159
  102. package/src/sap/fe/core/controls/FilterBar.ts +148 -0
  103. package/src/sap/fe/core/controls/FormElementWrapper.js +100 -39
  104. package/src/sap/fe/core/controls/FormElementWrapper.ts +37 -0
  105. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +37 -42
  106. package/src/sap/fe/core/controls/MultiValueParameterDelegate.ts +31 -0
  107. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +147 -115
  108. package/src/sap/fe/core/controls/filterbar/FilterContainer.ts +102 -0
  109. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +300 -265
  110. package/src/sap/fe/core/controls/filterbar/VisualFilter.ts +252 -0
  111. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +185 -140
  112. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.ts +125 -0
  113. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +335 -322
  114. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.ts +337 -0
  115. package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +37 -42
  116. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +75 -74
  117. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.ts +71 -0
  118. package/src/sap/fe/core/converters/ConverterContext.js +348 -379
  119. package/src/sap/fe/core/converters/ConverterContext.ts +19 -16
  120. package/src/sap/fe/core/converters/ManifestSettings.js +13 -1
  121. package/src/sap/fe/core/converters/ManifestSettings.ts +17 -2
  122. package/src/sap/fe/core/converters/ManifestWrapper.js +354 -378
  123. package/src/sap/fe/core/converters/ManifestWrapper.ts +10 -0
  124. package/src/sap/fe/core/converters/MetaModelConverter.js +6 -4
  125. package/src/sap/fe/core/converters/MetaModelConverter.ts +5 -2
  126. package/src/sap/fe/core/converters/TemplateConverter.js +1 -1
  127. package/src/sap/fe/core/converters/TemplateConverter.ts +2 -1
  128. package/src/sap/fe/core/converters/annotations/DataField.js +26 -13
  129. package/src/sap/fe/core/converters/annotations/DataField.ts +40 -17
  130. package/src/sap/fe/core/converters/controls/Common/Action.js +10 -10
  131. package/src/sap/fe/core/converters/controls/Common/Action.ts +20 -19
  132. package/src/sap/fe/core/converters/controls/Common/Chart.js +8 -8
  133. package/src/sap/fe/core/converters/controls/Common/Chart.ts +12 -11
  134. package/src/sap/fe/core/converters/controls/Common/Form.js +6 -6
  135. package/src/sap/fe/core/converters/controls/Common/Form.ts +7 -3
  136. package/src/sap/fe/core/converters/controls/Common/KPI.js +1 -1
  137. package/src/sap/fe/core/converters/controls/Common/KPI.ts +2 -2
  138. package/src/sap/fe/core/converters/controls/Common/Table.js +326 -86
  139. package/src/sap/fe/core/converters/controls/Common/Table.ts +384 -167
  140. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +120 -55
  141. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +158 -98
  142. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +206 -223
  143. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +263 -287
  144. package/src/sap/fe/core/converters/controls/ObjectPage/HeaderFacet.js +6 -6
  145. package/src/sap/fe/core/converters/controls/ObjectPage/HeaderFacet.ts +20 -18
  146. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +5 -2
  147. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +4 -1
  148. package/src/sap/fe/core/converters/helpers/Aggregation.js +115 -133
  149. package/src/sap/fe/core/converters/helpers/BindingHelper.js +20 -6
  150. package/src/sap/fe/core/converters/helpers/BindingHelper.ts +16 -4
  151. package/src/sap/fe/core/converters/helpers/ConfigurableObject.js +12 -1
  152. package/src/sap/fe/core/converters/helpers/ConfigurableObject.ts +11 -0
  153. package/src/sap/fe/core/converters/helpers/Key.js +42 -57
  154. package/src/sap/fe/core/converters/helpers/Key.ts +1 -1
  155. package/src/sap/fe/core/converters/objectPage/FormMenuActions.js +1 -1
  156. package/src/sap/fe/core/converters/objectPage/FormMenuActions.ts +0 -4
  157. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +51 -27
  158. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +69 -43
  159. package/src/sap/fe/core/converters/templates/ListReportConverter.js +42 -25
  160. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +91 -65
  161. package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +11 -9
  162. package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +8 -8
  163. package/src/sap/fe/core/designtime/AppComponent.designtime.js +92 -98
  164. package/src/sap/fe/core/designtime/AppComponent.designtime.ts +91 -0
  165. package/src/sap/fe/core/formatters/CollaborationFormatter.js +104 -0
  166. package/src/sap/fe/core/formatters/CollaborationFormatter.ts +60 -0
  167. package/src/sap/fe/core/formatters/KPIFormatter.js +3 -12
  168. package/src/sap/fe/core/formatters/KPIFormatter.ts +3 -2
  169. package/src/sap/fe/core/formatters/TableFormatter.js +53 -2
  170. package/src/sap/fe/core/formatters/TableFormatter.ts +51 -0
  171. package/src/sap/fe/core/formatters/ValueFormatter.js +4 -4
  172. package/src/sap/fe/core/formatters/ValueFormatter.ts +4 -7
  173. package/src/sap/fe/core/fpm/Component.js +80 -55
  174. package/src/sap/fe/core/fpm/Component.ts +43 -0
  175. package/src/sap/fe/core/helpers/AppStartupHelper.js +323 -309
  176. package/src/sap/fe/core/helpers/AppStartupHelper.ts +363 -337
  177. package/src/sap/fe/core/helpers/BindingExpression.js +7 -7
  178. package/src/sap/fe/core/helpers/BindingExpression.ts +7 -7
  179. package/src/sap/fe/core/helpers/ClassSupport.js +307 -166
  180. package/src/sap/fe/core/helpers/ClassSupport.ts +348 -155
  181. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +5 -4
  182. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.ts +1 -5
  183. package/src/sap/fe/core/helpers/FPMHelper.js +1 -1
  184. package/src/sap/fe/core/helpers/FPMHelper.ts +1 -1
  185. package/src/sap/fe/core/helpers/MassEditHelper.js +735 -684
  186. package/src/sap/fe/core/helpers/MassEditHelper.ts +803 -0
  187. package/src/sap/fe/core/helpers/ModelHelper.js +53 -1
  188. package/src/sap/fe/core/helpers/ModelHelper.ts +46 -0
  189. package/src/sap/fe/core/helpers/PasteHelper.js +4 -4
  190. package/src/sap/fe/core/helpers/PasteHelper.ts +4 -3
  191. package/src/sap/fe/core/helpers/SemanticDateOperators.js +7 -3
  192. package/src/sap/fe/core/helpers/SemanticDateOperators.ts +7 -1
  193. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +1 -1
  194. package/src/sap/fe/core/helpers/SemanticKeyHelper.ts +1 -1
  195. package/src/sap/fe/core/helpers/StableIdHelper.js +1 -7
  196. package/src/sap/fe/core/helpers/StableIdHelper.ts +0 -4
  197. package/src/sap/fe/core/jsx-runtime/jsx.js +35 -5
  198. package/src/sap/fe/core/jsx-runtime/jsx.ts +22 -8
  199. package/src/sap/fe/core/library.js +425 -451
  200. package/src/sap/fe/core/library.support.js +22 -33
  201. package/src/sap/fe/core/library.support.ts +23 -0
  202. package/src/sap/fe/core/library.ts +420 -0
  203. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +5 -3
  204. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +4 -4
  205. package/src/sap/fe/core/messagebundle.properties +45 -13
  206. package/src/sap/fe/core/messagebundle_ar.properties +29 -7
  207. package/src/sap/fe/core/messagebundle_bg.properties +29 -7
  208. package/src/sap/fe/core/messagebundle_ca.properties +29 -7
  209. package/src/sap/fe/core/messagebundle_cs.properties +29 -7
  210. package/src/sap/fe/core/messagebundle_cy.properties +29 -7
  211. package/src/sap/fe/core/messagebundle_da.properties +29 -7
  212. package/src/sap/fe/core/messagebundle_de.properties +29 -7
  213. package/src/sap/fe/core/messagebundle_el.properties +29 -7
  214. package/src/sap/fe/core/messagebundle_en.properties +29 -7
  215. package/src/sap/fe/core/messagebundle_en_GB.properties +29 -7
  216. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +29 -7
  217. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +29 -7
  218. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +29 -7
  219. package/src/sap/fe/core/messagebundle_es.properties +29 -7
  220. package/src/sap/fe/core/messagebundle_es_MX.properties +29 -7
  221. package/src/sap/fe/core/messagebundle_et.properties +29 -7
  222. package/src/sap/fe/core/messagebundle_fi.properties +30 -8
  223. package/src/sap/fe/core/messagebundle_fr.properties +31 -9
  224. package/src/sap/fe/core/messagebundle_fr_CA.properties +31 -9
  225. package/src/sap/fe/core/messagebundle_hi.properties +29 -7
  226. package/src/sap/fe/core/messagebundle_hr.properties +29 -7
  227. package/src/sap/fe/core/messagebundle_hu.properties +29 -7
  228. package/src/sap/fe/core/messagebundle_id.properties +29 -7
  229. package/src/sap/fe/core/messagebundle_it.properties +29 -7
  230. package/src/sap/fe/core/messagebundle_iw.properties +29 -7
  231. package/src/sap/fe/core/messagebundle_ja.properties +28 -6
  232. package/src/sap/fe/core/messagebundle_kk.properties +29 -7
  233. package/src/sap/fe/core/messagebundle_ko.properties +29 -7
  234. package/src/sap/fe/core/messagebundle_lt.properties +29 -7
  235. package/src/sap/fe/core/messagebundle_lv.properties +30 -8
  236. package/src/sap/fe/core/messagebundle_ms.properties +29 -7
  237. package/src/sap/fe/core/messagebundle_nl.properties +29 -7
  238. package/src/sap/fe/core/messagebundle_no.properties +29 -7
  239. package/src/sap/fe/core/messagebundle_pl.properties +29 -7
  240. package/src/sap/fe/core/messagebundle_pt.properties +30 -8
  241. package/src/sap/fe/core/messagebundle_pt_PT.properties +29 -7
  242. package/src/sap/fe/core/messagebundle_ro.properties +29 -7
  243. package/src/sap/fe/core/messagebundle_ru.properties +29 -7
  244. package/src/sap/fe/core/messagebundle_sh.properties +29 -7
  245. package/src/sap/fe/core/messagebundle_sk.properties +29 -7
  246. package/src/sap/fe/core/messagebundle_sl.properties +29 -7
  247. package/src/sap/fe/core/messagebundle_sv.properties +30 -8
  248. package/src/sap/fe/core/messagebundle_th.properties +28 -6
  249. package/src/sap/fe/core/messagebundle_tr.properties +32 -10
  250. package/src/sap/fe/core/messagebundle_uk.properties +29 -7
  251. package/src/sap/fe/core/messagebundle_vi.properties +29 -7
  252. package/src/sap/fe/core/messagebundle_zh_CN.properties +29 -7
  253. package/src/sap/fe/core/messagebundle_zh_TW.properties +29 -7
  254. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +47 -73
  255. package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +1 -1
  256. package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +158 -196
  257. package/src/sap/fe/core/services/CacheHandlerServiceFactory.ts +5 -6
  258. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +70 -96
  259. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +7 -6
  260. package/src/sap/fe/core/services/NavigationServiceFactory.js +287 -342
  261. package/src/sap/fe/core/services/NavigationServiceFactory.ts +11 -14
  262. package/src/sap/fe/core/services/ResourceModelServiceFactory.js +70 -105
  263. package/src/sap/fe/core/services/ResourceModelServiceFactory.ts +6 -3
  264. package/src/sap/fe/core/services/RoutingServiceFactory.js +796 -820
  265. package/src/sap/fe/core/services/RoutingServiceFactory.ts +62 -53
  266. package/src/sap/fe/core/services/ShellServicesFactory.js +694 -741
  267. package/src/sap/fe/core/services/ShellServicesFactory.ts +33 -33
  268. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +570 -595
  269. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +23 -4
  270. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +357 -389
  271. package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +25 -29
  272. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +43 -5
  273. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.ts +7 -4
  274. package/src/sap/fe/core/support/CommonHelper.js +1 -1
  275. package/src/sap/fe/core/support/CommonHelper.ts +1 -4
  276. package/src/sap/fe/core/support/Diagnostics.js +36 -48
  277. package/src/sap/fe/core/templating/DataModelPathHelper.js +91 -90
  278. package/src/sap/fe/core/templating/DataModelPathHelper.ts +126 -123
  279. package/src/sap/fe/core/templating/DisplayModeFormatter.js +23 -3
  280. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +26 -5
  281. package/src/sap/fe/core/templating/FilterHelper.js +25 -32
  282. package/src/sap/fe/core/templating/FilterHelper.ts +36 -35
  283. package/src/sap/fe/core/templating/PropertyHelper.js +16 -2
  284. package/src/sap/fe/core/templating/PropertyHelper.ts +31 -24
  285. package/src/sap/fe/core/templating/UIFormatters.js +150 -44
  286. package/src/sap/fe/core/templating/UIFormatters.ts +165 -67
  287. package/src/sap/fe/core/type/Email.js +26 -8
  288. package/src/sap/fe/core/type/Email.ts +8 -7
  289. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +0 -75
@@ -0,0 +1,362 @@
1
+ import Log from "sap/base/Log";
2
+ import UriParameters from "sap/base/util/UriParameters";
3
+ import { Activity, CollaborationUtils, Message, User, UserActivity } from "sap/fe/core/actions/collaboration/CollaborationCommon";
4
+ import MessageBox from "sap/m/MessageBox";
5
+ import Event from "sap/ui/base/Event";
6
+ import Control from "sap/ui/core/Control";
7
+ import View from "sap/ui/core/mvc/View";
8
+ import SapPcpWebSocket from "sap/ui/core/ws/SapPcpWebSocket";
9
+ import Context from "sap/ui/model/odata/v4/Context";
10
+ import ODataMetaModel from "sap/ui/model/odata/v4/ODataMetaModel";
11
+
12
+ const CONNECTED = "/collaboration/connected";
13
+ const CONNECTION = "/collaboration/connection";
14
+ const MYACTIVITY = "/collaboration/myActivity";
15
+ const ACTIVEUSERS = "/collaboration/activeUsers";
16
+ const ACTIVITIES = "/collaboration/activities";
17
+
18
+ export const isConnected = function (control: Control): boolean {
19
+ return !!control.getModel("internal").getProperty(CONNECTED);
20
+ };
21
+
22
+ export const send = function (control: Control, action: Activity, content: string | string[] | Context | Context[] | undefined) {
23
+ if (isConnected(control)) {
24
+ const contentArray = Array.isArray(content) ? content : [content];
25
+ let clientContent: string = "";
26
+ contentArray.forEach(function (c) {
27
+ if (c) {
28
+ clientContent += clientContent ? "|" : "";
29
+ clientContent += typeof c === "string" ? c : c.getPath();
30
+ }
31
+ });
32
+
33
+ const internalModel = control.getModel("internal") as any;
34
+ const webSocket = internalModel.getProperty(CONNECTION) as SapPcpWebSocket;
35
+
36
+ if (action === Activity.LiveChange) {
37
+ // To avoid unnecessary traffic we keep track of live changes and send it only once
38
+ const myActivity = internalModel.getProperty(MYACTIVITY);
39
+ if (myActivity === clientContent) {
40
+ return;
41
+ } else {
42
+ internalModel.setProperty(MYACTIVITY, clientContent);
43
+ }
44
+ } else {
45
+ // user finished the activity
46
+ internalModel.setProperty(MYACTIVITY, null);
47
+ }
48
+
49
+ webSocket.send("", {
50
+ clientAction: action,
51
+ clientContent: clientContent
52
+ });
53
+
54
+ if (action === Activity.Activate || action === Activity.Discard) {
55
+ disconnect(control);
56
+ }
57
+ }
58
+ };
59
+
60
+ const getWebSocketBaseURL = function (bindingContext: Context): string {
61
+ return bindingContext.getModel().getMetaModel().getObject("/@com.sap.vocabularies.Common.v1.WebSocketBaseURL");
62
+ };
63
+
64
+ export const isCollaborationEnabled = function (view: View): boolean {
65
+ const bindingContext = view?.getBindingContext && (view.getBindingContext() as Context);
66
+ return !!(bindingContext && getWebSocketBaseURL(bindingContext));
67
+ };
68
+
69
+ export const connect = async function (view: View) {
70
+ const internalModel: any = view.getModel("internal");
71
+ const me = CollaborationUtils.getMe(view);
72
+ if (internalModel.getProperty(CONNECTION)) {
73
+ // connection already established
74
+ return;
75
+ }
76
+
77
+ // Retrieving ME from shell service
78
+ if (!me) {
79
+ // no me = no shell = not sure what to do
80
+ return;
81
+ }
82
+
83
+ const activeUsers: any[] = [me];
84
+ internalModel.setProperty("/collaboration", { activeUsers: activeUsers, activities: {} });
85
+ const bindingContext = view.getBindingContext() as Context;
86
+ const webSocketBaseURL = getWebSocketBaseURL(bindingContext);
87
+
88
+ if (!webSocketBaseURL) {
89
+ return;
90
+ }
91
+
92
+ const sDraftUUID = await bindingContext.requestProperty("DraftAdministrativeData/DraftUUID");
93
+ if (!sDraftUUID) {
94
+ return;
95
+ }
96
+
97
+ const webSocket = establishWebSocketConnection(webSocketBaseURL, sDraftUUID, view);
98
+
99
+ webSocket.attachMessage(function (event: Event) {
100
+ const message: Message = event.getParameter("pcpFields");
101
+ messageReceive(message, view, webSocket);
102
+ });
103
+ };
104
+
105
+ export const disconnect = function (control: Control) {
106
+ const internalModel = control.getModel("internal") as any;
107
+ const webSocket = internalModel.getProperty(CONNECTION) as SapPcpWebSocket;
108
+ webSocket.close();
109
+ internalModel.setProperty(CONNECTION, null);
110
+ };
111
+
112
+ function establishWebSocketConnection(socketBaseURL: string, draftUUID: string, view: View) {
113
+ const internalModel: any = view.getModel("internal");
114
+ const hostLocation = window.location;
115
+ let socketURI;
116
+
117
+ // Support useBackendUrl for local testing
118
+ const useBackendUrl = UriParameters.fromQuery(window.location.search).get("useBackendUrl");
119
+ if (useBackendUrl) {
120
+ socketURI = useBackendUrl.replace("https", "wss");
121
+ } else {
122
+ socketURI = hostLocation.protocol === "https:" ? "wss:" : "ws:";
123
+ socketURI += "//" + hostLocation.host;
124
+ }
125
+
126
+ socketURI += (socketBaseURL.startsWith("/") ? "" : "/") + socketBaseURL + "?draft=" + draftUUID;
127
+
128
+ const useFLPUser = UriParameters.fromQuery(window.location.search).get("useFLPUser");
129
+ if (useFLPUser === "true") {
130
+ const me = CollaborationUtils.getMe(view);
131
+ socketURI += "&userID=" + encodeURI(me.id) + "&userName=" + encodeURI(me.initialName || "");
132
+ }
133
+
134
+ const webSocket = new SapPcpWebSocket(socketURI, ["v10.pcp.sap.com"]); // TODO: use enum
135
+ internalModel.setProperty(CONNECTION, webSocket);
136
+
137
+ webSocket.attachOpen(function () {
138
+ internalModel.setProperty(CONNECTED, true);
139
+ });
140
+
141
+ webSocket.attachError(function () {
142
+ Log.error("The connection to the websocket channel " + socketBaseURL + " could not be established");
143
+ internalModel.setProperty(CONNECTED, false);
144
+ });
145
+
146
+ webSocket.attachClose(function () {
147
+ internalModel.setProperty(CONNECTED, false);
148
+ });
149
+
150
+ return webSocket;
151
+ }
152
+
153
+ function messageReceive(message: Message, view: View, webSocket: any) {
154
+ const internalModel: any = view.getModel("internal");
155
+ let activeUsers: User[] = internalModel.getProperty(ACTIVEUSERS);
156
+ let activities: UserActivity[];
157
+ let activityKey: string;
158
+ const metaPath: string = message.clientContent && (view.getModel().getMetaModel() as ODataMetaModel).getMetaPath(message.clientContent);
159
+ message.userAction = message.userAction || message.clientAction;
160
+
161
+ const sender: User = {
162
+ id: message.userID,
163
+ name: message.userDescription,
164
+ initials: CollaborationUtils.formatInitials(message.userDescription),
165
+ color: CollaborationUtils.getUserColor(message.userID, activeUsers, [])
166
+ };
167
+
168
+ switch (message.userAction) {
169
+ case Activity.Join:
170
+ case Activity.JoinEcho:
171
+ if (activeUsers.findIndex((user) => user.id === sender.id) === -1) {
172
+ activeUsers.push(sender);
173
+ internalModel.setProperty(ACTIVEUSERS, activeUsers);
174
+ }
175
+
176
+ if (message.userAction === Activity.Join) {
177
+ // we echo our existence to the newly entered user and also send the current activity if there is any
178
+ webSocket.send("", {
179
+ clientAction: Activity.JoinEcho,
180
+ clientContent: internalModel.getProperty(MYACTIVITY)
181
+ });
182
+ // TODO: echo current activity
183
+ }
184
+
185
+ if (message.userAction === Activity.JoinEcho) {
186
+ if (message.clientContent) {
187
+ // another user was already typing therefore I want to see his activity immediately. Calling me again as a live change
188
+ message.userAction = Activity.LiveChange;
189
+ messageReceive(message, view, webSocket);
190
+ }
191
+ }
192
+
193
+ break;
194
+ case Activity.Leave:
195
+ // Removing the active user. Not removing "me" if I had the screen open in another session
196
+ activeUsers = activeUsers.filter((user) => user.id !== sender.id || user.me);
197
+ internalModel.setProperty(ACTIVEUSERS, activeUsers);
198
+ const allActivities = internalModel.getProperty(ACTIVITIES) || {};
199
+ const removeUserActivities = function (bag: any) {
200
+ if (Array.isArray(bag)) {
201
+ return bag.filter((activity) => activity.id !== sender.id);
202
+ } else {
203
+ for (const p in bag) {
204
+ bag[p] = removeUserActivities(bag[p]);
205
+ }
206
+ return bag;
207
+ }
208
+ };
209
+ removeUserActivities(allActivities);
210
+ internalModel.setProperty(ACTIVITIES, allActivities);
211
+ break;
212
+
213
+ case Activity.Change:
214
+ let currentActivities: any[] = internalModel.getProperty(ACTIVITIES + metaPath) || [];
215
+ activityKey = getActivityKey(message.clientContent);
216
+ currentActivities = currentActivities.filter((activity) => activity.key !== activityKey);
217
+ internalModel.setProperty(ACTIVITIES + metaPath, currentActivities);
218
+
219
+ update(view, message, metaPath, Activity.Change);
220
+ break;
221
+ case Activity.Create:
222
+ // For create we actually just need to refresh the table
223
+ update(view, message, metaPath, Activity.Create);
224
+ break;
225
+ case Activity.Delete:
226
+ // For now also refresh the page but in case of deletion we need to inform the user
227
+ update(view, message, metaPath, Activity.Delete);
228
+ break;
229
+ case Activity.Activate:
230
+ disconnect(view);
231
+ MessageBox.information(CollaborationUtils.getText("C_COLLABORATIONDRAFT_ACTIVATE", sender.name));
232
+ navigate(message.clientContent, view);
233
+ break;
234
+ case Activity.Discard:
235
+ disconnect(view);
236
+ MessageBox.information(CollaborationUtils.getText("C_COLLABORATIONDRAFT_DISCARD", sender.name));
237
+ navigate(message.clientContent, view);
238
+ break;
239
+ /*
240
+ // TODO: Action to be implemented
241
+ case Activity.Action:
242
+ // Just for test reasons show a toast - to be checked with UX
243
+ MessageToast.show("User " + sender.name + " has executed action " + metaPath.split("|")[0]);
244
+ //update(view, message, metaPath, Activity.Delete);
245
+ break;
246
+ */
247
+ case Activity.LiveChange:
248
+ const activity: UserActivity = sender;
249
+ activity.key = getActivityKey(message.clientContent);
250
+
251
+ // stupid JSON model...
252
+ let initJSONModel: string = "";
253
+ const parts = metaPath.split("/");
254
+ for (let i = 1; i < parts.length - 1; i++) {
255
+ initJSONModel += "/" + parts[i];
256
+ if (!internalModel.getProperty(ACTIVITIES + initJSONModel)) {
257
+ internalModel.setProperty(ACTIVITIES + initJSONModel, {});
258
+ }
259
+ }
260
+
261
+ activities = internalModel.getProperty(ACTIVITIES + metaPath);
262
+ activities = activities ? activities.slice() : [];
263
+ activities.push(activity);
264
+ internalModel.setProperty(ACTIVITIES + metaPath, activities);
265
+ break;
266
+ case Activity.Undo:
267
+ // The user did a change but reverted it, therefore unblock the control
268
+ activities = internalModel.getProperty(ACTIVITIES + metaPath);
269
+ activityKey = getActivityKey(message.clientContent);
270
+ internalModel.setProperty(
271
+ ACTIVITIES + metaPath,
272
+ activities.filter((a) => a.key !== activityKey)
273
+ );
274
+ break;
275
+ }
276
+ }
277
+
278
+ function update(view: View, message: Message, metaPath: string, action: Activity) {
279
+ const appComponent = CollaborationUtils.getAppComponent(view);
280
+ const metaModel = view.getModel().getMetaModel() as ODataMetaModel;
281
+ const currentPage = getCurrentPage(view);
282
+ const sideEffectsService = (appComponent as any).getSideEffectsService(); // TODO: add to appcomponent
283
+ const currentContext = currentPage.getBindingContext();
284
+ const currentPath = currentContext.getPath();
285
+ const currentMetaPath = metaModel.getMetaPath(currentPath);
286
+ let changedDocument = message.clientContent;
287
+
288
+ if (action === Activity.Delete) {
289
+ // check if user currently displays one deleted object
290
+ const deletedObjects = message.clientContent.split("|");
291
+ if (deletedObjects.findIndex((deletedObject) => currentPath.startsWith(deletedObject)) > -1) {
292
+ // any other user deleted the object I'm currently looking at. Inform the user we will navigate to root now
293
+ MessageBox.information(CollaborationUtils.getText("C_COLLABORATIONDRAFT_DELETE", message.userDescription), {
294
+ onClose: function () {
295
+ // TODO: Navigate to root? To be implemented
296
+ history.back();
297
+ }
298
+ });
299
+ }
300
+ // TODO: For now just take the first object to get the meta path and do a full refresh of the table
301
+ changedDocument = deletedObjects[0];
302
+ }
303
+
304
+ if (changedDocument.startsWith(currentPath)) {
305
+ // Execute SideEffects (TODO for Meet there should be one central method)
306
+ const activityPath = metaPath.replace(currentMetaPath, "").slice(1);
307
+ if (activityPath) {
308
+ // Request also the property itself
309
+ const sideEffects: any[] = [
310
+ {
311
+ $PropertyPath: activityPath
312
+ }
313
+ ];
314
+ const entityType = sideEffectsService.getEntityTypeFromContext(currentContext);
315
+ const entityTypeSideEffects = sideEffectsService.getODataEntitySideEffects(entityType);
316
+ // Poor man solution without checking source targets, just for POC, this is throw-way coding only
317
+ const object: any = Object; // just to overcome TS issues, will be anyway replaced
318
+ const relevantSideEffects = object.fromEntries(
319
+ object
320
+ .entries(entityTypeSideEffects)
321
+ .filter((x: any[]) => x[1].SourceProperties?.findIndex((source: any) => source.value === activityPath) > -1)
322
+ );
323
+ for (const p in relevantSideEffects) {
324
+ relevantSideEffects[p].TargetProperties.forEach(function (targetProperty: any) {
325
+ sideEffects.push({
326
+ $PropertyPath: targetProperty
327
+ });
328
+ });
329
+ }
330
+ sideEffectsService.requestSideEffects(sideEffects, currentContext, "$auto");
331
+ }
332
+ }
333
+
334
+ // Simulate any change so the edit flow shows the draft indicator and sets the page to dirty
335
+ currentPage.getController().editFlow.updateDocument(currentContext, Promise.resolve());
336
+ }
337
+
338
+ function navigate(path: string, view: View) {
339
+ // TODO: routing.navigate doesn't consider semantic bookmarking
340
+ const currentPage = getCurrentPage(view);
341
+ const targetContext = view.getModel().bindContext(path).getBoundContext();
342
+ currentPage.getController().routing.navigate(targetContext);
343
+ }
344
+
345
+ function getCurrentPage(view: View) {
346
+ const appComponent = CollaborationUtils.getAppComponent(view);
347
+ // TODO: isn't there an easier way to get the current page?
348
+ // TODO: What about FCL?
349
+ return (appComponent.getRootControl() as any).getContent()[0].getCurrentPage().getComponentInstance().getRootControl();
350
+ }
351
+
352
+ function getActivityKey(x: string): string {
353
+ return x.substring(x.lastIndexOf("(") + 1, x.lastIndexOf(")"));
354
+ }
355
+
356
+ export default {
357
+ connect: connect,
358
+ disconnect: disconnect,
359
+ isConnected: isConnected,
360
+ isCollaborationEnabled: isCollaborationEnabled,
361
+ send: send
362
+ };
@@ -0,0 +1,146 @@
1
+ /*!
2
+ * SAP UI development toolkit for HTML5 (SAPUI5)
3
+ * (c) Copyright 2009-2021 SAP SE. All rights reserved
4
+ */
5
+ sap.ui.define(["sap/ui/core/Component", "sap/ui/core/Core"], function (Component, Core) {
6
+ "use strict";
7
+
8
+ var _exports = {};
9
+
10
+ var Role;
11
+
12
+ (function (Role) {
13
+ Role["Owner"] = "O";
14
+ Role["Edit"] = "E";
15
+ })(Role || (Role = {}));
16
+
17
+ _exports.Role = Role;
18
+ var Activity;
19
+
20
+ (function (Activity) {
21
+ Activity["Join"] = "JOIN";
22
+ Activity["JoinEcho"] = "JOINECHO";
23
+ Activity["Leave"] = "LEAVE";
24
+ Activity["Change"] = "CHANGE";
25
+ Activity["Create"] = "CREATE";
26
+ Activity["Delete"] = "DELETE";
27
+ Activity["Action"] = "ACTION";
28
+ Activity["LiveChange"] = "LIVECHANGE";
29
+ Activity["Activate"] = "ACTIVATE";
30
+ Activity["Discard"] = "DISCARD";
31
+ Activity["Undo"] = "UNDO";
32
+ })(Activity || (Activity = {}));
33
+
34
+ _exports.Activity = Activity;
35
+
36
+ function formatInitials(fullName) {
37
+ // remove titles - those are the ones from S/4 to be checked if there are others
38
+ var academicTitles = ["Dr.", "Prof.", "Prof. Dr.", "B.A.", "MBA", "Ph.D."];
39
+ academicTitles.forEach(function (academicTitle) {
40
+ fullName = fullName.replace(academicTitle, "");
41
+ });
42
+ var initials;
43
+ var parts = fullName.trimStart().split(" ");
44
+
45
+ if (parts.length > 1) {
46
+ var _parts$shift, _parts$pop;
47
+
48
+ initials = ((parts === null || parts === void 0 ? void 0 : (_parts$shift = parts.shift()) === null || _parts$shift === void 0 ? void 0 : _parts$shift.charAt(0)) || "") + ((_parts$pop = parts.pop()) === null || _parts$pop === void 0 ? void 0 : _parts$pop.charAt(0));
49
+ } else {
50
+ initials = fullName.substring(0, 2);
51
+ }
52
+
53
+ return initials.toUpperCase();
54
+ }
55
+
56
+ function getUserColor(UserID, activeUsers, invitedUsers) {
57
+ // search if user is known
58
+ var user = activeUsers.find(function (u) {
59
+ return u.id === UserID;
60
+ });
61
+
62
+ if (user) {
63
+ return user.color;
64
+ } else {
65
+ var _loop = function (i) {
66
+ if (activeUsers.findIndex(function (u) {
67
+ return u.color === i;
68
+ }) === -1 && invitedUsers.findIndex(function (u) {
69
+ return u.color === i;
70
+ }) === -1) {
71
+ return {
72
+ v: i
73
+ };
74
+ }
75
+ };
76
+
77
+ // search for next free color
78
+ for (var i = 1; i <= 10; i++) {
79
+ var _ret = _loop(i);
80
+
81
+ if (typeof _ret === "object") return _ret.v;
82
+ } // this seems to be a popular object :) for now just return 10 for all.
83
+ // for invited we should start from 1 again so the colors are different
84
+
85
+
86
+ return 10;
87
+ }
88
+ } // copied from CommonUtils. Due to a cycle dependency I can't use CommonUtils here.
89
+ // That's to be fixed. the discard popover thingy shouldn't be in the common utils at all
90
+
91
+
92
+ function getAppComponent(oControl) {
93
+ if (oControl.isA("sap.fe.core.AppComponent")) {
94
+ return oControl;
95
+ }
96
+
97
+ var oOwner = Component.getOwnerComponentFor(oControl);
98
+
99
+ if (!oOwner) {
100
+ return oControl;
101
+ } else {
102
+ return getAppComponent(oOwner);
103
+ }
104
+ }
105
+
106
+ function getMe(view) {
107
+ var shellServiceHelper = getAppComponent(view).getShellServices();
108
+
109
+ if (!shellServiceHelper || !shellServiceHelper.hasUShell()) {
110
+ throw "No Shell... No User";
111
+ }
112
+
113
+ var me = {
114
+ initials: shellServiceHelper.getUser().getInitials(),
115
+ id: shellServiceHelper.getUser().getId(),
116
+ name: shellServiceHelper.getUser().getFullName() + " (" + getText("C_COLLABORATIONDRAFT_YOU") + ")",
117
+ initialName: shellServiceHelper.getUser().getFullName(),
118
+ color: 6,
119
+ // same color as FLP...
120
+ role: Role.Owner,
121
+ me: true
122
+ };
123
+ return me;
124
+ }
125
+
126
+ function getText(textId) {
127
+ var oResourceModel = Core.getLibraryResourceBundle("sap.fe.core");
128
+
129
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
130
+ args[_key - 1] = arguments[_key];
131
+ }
132
+
133
+ return oResourceModel.getText(textId, args);
134
+ }
135
+
136
+ var CollaborationUtils = {
137
+ formatInitials: formatInitials,
138
+ getUserColor: getUserColor,
139
+ getMe: getMe,
140
+ getAppComponent: getAppComponent,
141
+ getText: getText
142
+ };
143
+ _exports.CollaborationUtils = CollaborationUtils;
144
+ return _exports;
145
+ }, false);
146
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbGxhYm9yYXRpb25Db21tb24udHMiXSwibmFtZXMiOlsiUm9sZSIsIkFjdGl2aXR5IiwiZm9ybWF0SW5pdGlhbHMiLCJmdWxsTmFtZSIsImFjYWRlbWljVGl0bGVzIiwiZm9yRWFjaCIsImFjYWRlbWljVGl0bGUiLCJyZXBsYWNlIiwiaW5pdGlhbHMiLCJwYXJ0cyIsInRyaW1TdGFydCIsInNwbGl0IiwibGVuZ3RoIiwic2hpZnQiLCJjaGFyQXQiLCJwb3AiLCJzdWJzdHJpbmciLCJ0b1VwcGVyQ2FzZSIsImdldFVzZXJDb2xvciIsIlVzZXJJRCIsImFjdGl2ZVVzZXJzIiwiaW52aXRlZFVzZXJzIiwidXNlciIsImZpbmQiLCJ1IiwiaWQiLCJjb2xvciIsImkiLCJmaW5kSW5kZXgiLCJnZXRBcHBDb21wb25lbnQiLCJvQ29udHJvbCIsImlzQSIsIm9Pd25lciIsIkNvbXBvbmVudCIsImdldE93bmVyQ29tcG9uZW50Rm9yIiwiZ2V0TWUiLCJ2aWV3Iiwic2hlbGxTZXJ2aWNlSGVscGVyIiwiZ2V0U2hlbGxTZXJ2aWNlcyIsImhhc1VTaGVsbCIsIm1lIiwiZ2V0VXNlciIsImdldEluaXRpYWxzIiwiZ2V0SWQiLCJuYW1lIiwiZ2V0RnVsbE5hbWUiLCJnZXRUZXh0IiwiaW5pdGlhbE5hbWUiLCJyb2xlIiwiT3duZXIiLCJ0ZXh0SWQiLCJvUmVzb3VyY2VNb2RlbCIsIkNvcmUiLCJnZXRMaWJyYXJ5UmVzb3VyY2VCdW5kbGUiLCJhcmdzIiwiQ29sbGFib3JhdGlvblV0aWxzIl0sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBOzs7Ozs7TUFtQllBLEk7O2FBQUFBLEk7QUFBQUEsSUFBQUEsSTtBQUFBQSxJQUFBQSxJO0tBQUFBLEksS0FBQUEsSTs7O01BS0FDLFE7O2FBQUFBLFE7QUFBQUEsSUFBQUEsUTtBQUFBQSxJQUFBQSxRO0FBQUFBLElBQUFBLFE7QUFBQUEsSUFBQUEsUTtBQUFBQSxJQUFBQSxRO0FBQUFBLElBQUFBLFE7QUFBQUEsSUFBQUEsUTtB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LEtBSDBCO0FBSWpDTixJQUFBQSxlQUFlLEVBQUVBLGVBSmdCO0FBS2pDaUIsSUFBQUEsT0FBTyxFQUFFQTtBQUx3QixHQUEzQiIsInNvdXJjZVJvb3QiOiIuIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFZpZXcgZnJvbSBcInNhcC91aS9jb3JlL212Yy9WaWV3XCI7XG5pbXBvcnQgQ29tcG9uZW50IGZyb20gXCJzYXAvdWkvY29yZS9Db21wb25lbnRcIjtcbmltcG9ydCBBcHBDb21wb25lbnQgZnJvbSBcInNhcC9mZS9jb3JlL0FwcENvbXBvbmVudFwiO1xuaW1wb3J0IHsgQ29yZUV4IH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3R5cGVzL2V4dGVuc2lvbl90eXBlc1wiO1xuaW1wb3J0IENvcmUgZnJvbSBcInNhcC91aS9jb3JlL0NvcmVcIjtcblxuZXhwb3J0IHR5cGUgVXNlciA9IHtcblx0aWQ6IHN0cmluZztcblx0aW5pdGlhbHM/OiBzdHJpbmc7XG5cdG5hbWU6IHN0cmluZztcblx0cm9sZT86IFJvbGU7XG5cdGNvbG9yPzogbnVtYmVyO1xuXHR0cmFuc2llbnQ/OiBib29sZWFuO1xuXHRtZT86IGJvb2xlYW47XG5cdGluaXRpYWxOYW1lPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgVXNlckFjdGl2aXR5ID0gVXNlciAmIHtcblx0a2V5Pzogc3RyaW5nO1xufTtcblxuZXhwb3J0IGVudW0gUm9sZSB7XG5cdE93bmVyID0gXCJPXCIsXG5cdEVkaXQgPSBcIkVcIlxufVxuXG5leHBvcnQgZW51bSBBY3Rpdml0eSB7XG5cdEpvaW4gPSBcIkpPSU5cIixcblx0Sm9pbkVjaG8gPSBcIkpPSU5FQ0hPXCIsXG5cdExlYXZlID0gXCJMRUFWRVwiLFxuXHRDaGFuZ2UgPSBcIkNIQU5HRVwiLFxuXHRDcmVhdGUgPSBcIkNSRUFURVwiLFxuXHREZWxldGUgPSBcIkRFTEVURVwiLFxuXHRBY3Rpb24gPSBcIkFDVElPTlwiLFxuXHRMaXZlQ2hhbmdlID0gXCJMSVZFQ0hBTkdFXCIsXG5cdEFjdGl2YXRlID0gXCJBQ1RJVkFURVwiLFxuXHREaXNjYXJkID0gXCJESVNDQVJEXCIsXG5cdFVuZG8gPSBcIlVORE9cIlxufVxuXG5leHBvcnQgdHlwZSBNZXNzYWdlID0ge1xuXHR1c2VyRGVzY3JpcHRpb246IHN0cmluZztcblx0dXNlcklEOiBzdHJpbmc7XG5cdHVzZXJBY3Rpb246IHN0cmluZztcblx0Y2xpZW50QWN0aW9uOiBzdHJpbmc7XG5cdGNsaWVudENvbnRlbnQ6IHN0cmluZztcbn07XG5cbmZ1bmN0aW9uIGZvcm1hdEluaXRpYWxzKGZ1bGxOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuXHQvLyByZW1vdmUgdGl0bGVzIC0gdGhvc2UgYXJlIHRoZSBvbmVzIGZyb20gUy80IHRvIGJlIGNoZWNrZWQgaWYgdGhlcmUgYXJlIG90aGVyc1xuXHRjb25zdCBhY2FkZW1pY1RpdGxlcyA9IFtcIkRyLlwiLCBcIlByb2YuXCIsIFwiUHJvZi4gRHIuXCIsIFwiQi5BLlwiLCBcIk1CQVwiLCBcIlBoLkQuXCJdO1xuXHRhY2FkZW1pY1RpdGxlcy5mb3JFYWNoKGZ1bmN0aW9uKGFjYWRlbWljVGl0bGUpIHtcblx0XHRmdWxsTmFtZSA9IGZ1bGxOYW1lLnJlcGxhY2UoYWNhZGVtaWNUaXRsZSwgXCJcIik7XG5cdH0pO1xuXG5cdGxldCBpbml0aWFsczogc3RyaW5nO1xuXHRjb25zdCBwYXJ0cyA9IGZ1bGxOYW1lLnRyaW1TdGFydCgpLnNwbGl0KFwiIFwiKTtcblxuXHRpZiAocGFydHMubGVuZ3RoID4gMSkge1xuXHRcdGluaXRpYWxzID0gKHBhcnRzPy5zaGlmdCgpPy5jaGFyQXQoMCkgfHwgXCJcIikgKyBwYXJ0cy5wb3AoKT8uY2hhckF0KDApO1xuXHR9IGVsc2Uge1xuXHRcdGluaXRpYWxzID0gZnVsbE5hbWUuc3Vic3RyaW5nKDAsIDIpO1xuXHR9XG5cblx0cmV0dXJuIGluaXRpYWxzLnRvVXBwZXJDYXNlKCk7XG59XG5cbmZ1bmN0aW9uIGdldFVzZXJDb2xvcihVc2VySUQ6IHN0cmluZywgYWN0aXZlVXNlcnM6IFVzZXJbXSwgaW52aXRlZFVzZXJzOiBVc2VyW10pIHtcblx0Ly8gc2VhcmNoIGlmIHVzZXIgaXMga25vd25cblx0Y29uc3QgdXNlciA9IGFjdGl2ZVVzZXJzLmZpbmQodSA9PiB1LmlkID09PSBVc2VySUQpO1xuXHRpZiAodXNlcikge1xuXHRcdHJldHVybiB1c2VyLmNvbG9yO1xuXHR9IGVsc2Uge1xuXHRcdC8vIHNlYXJjaCBmb3IgbmV4dCBmcmVlIGNvbG9yXG5cdFx0Zm9yIChsZXQgaSA9IDE7IGkgPD0gMTA7IGkrKykge1xuXHRcdFx0aWYgKGFjdGl2ZVVzZXJzLmZpbmRJbmRleCh1ID0+IHUuY29sb3IgPT09IGkpID09PSAtMSAmJiBpbnZpdGVkVXNlcnMuZmluZEluZGV4KHUgPT4gdS5jb2xvciA9PT0gaSkgPT09IC0xKSB7XG5cdFx0XHRcdHJldHVybiBpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHQvLyB0aGlzIHNlZW1zIHRvIGJlIGEgcG9wdWxhciBvYmplY3QgOikgZm9yIG5vdyBqdXN0IHJldHVybiAxMCBmb3IgYWxsLlxuXHRcdC8vIGZvciBpbnZpdGVkIHdlIHNob3VsZCBzdGFydCBmcm9tIDEgYWdhaW4gc28gdGhlIGNvbG9ycyBhcmUgZGlmZmVyZW50XG5cdFx0cmV0dXJuIDEwO1xuXHR9XG59XG5cbi8vIGNvcGllZCBmcm9tIENvbW1vblV0aWxzLiBEdWUgdG8gYSBjeWNsZSBkZXBlbmRlbmN5IEkgY2FuJ3QgdXNlIENvbW1vblV0aWxzIGhlcmUuXG4vLyBUaGF0J3MgdG8gYmUgZml4ZWQuIHRoZSBkaXNjYXJkIHBvcG92ZXIgdGhpbmd5IHNob3VsZG4ndCBiZSBpbiB0aGUgY29tbW9uIHV0aWxzIGF0IGFsbFxuZnVuY3Rpb24gZ2V0QXBwQ29tcG9uZW50KG9Db250cm9sOiBhbnkpOiBBcHBDb21wb25lbnQge1xuXHRpZiAob0NvbnRyb2wuaXNBKFwic2FwLmZlLmNvcmUuQXBwQ29tcG9uZW50XCIpKSB7XG5cdFx0cmV0dXJuIG9Db250cm9sO1xuXHR9XG5cdGNvbnN0IG9Pd25lciA9IENvbXBvbmVudC5nZXRPd25lckNvbXBvbmVudEZvcihvQ29udHJvbCk7XG5cdGlmICghb093bmVyKSB7XG5cdFx0cmV0dXJuIG9Db250cm9sO1xuXHR9IGVsc2Uge1xuXHRcdHJldHVybiBnZXRBcHBDb21wb25lbnQob093bmVyKTtcblx0fVxufVxuXG5mdW5jdGlvbiBnZXRNZSh2aWV3OiBWaWV3KTogVXNlciB7XG5cdGNvbnN0IHNoZWxsU2VydmljZUhlbHBlciA9IGdldEFwcENvbXBvbmVudCh2aWV3KS5nZXRTaGVsbFNlcnZpY2VzKCk7XG5cdGlmICghc2hlbGxTZXJ2aWNlSGVscGVyIHx8ICFzaGVsbFNlcnZpY2VIZWxwZXIuaGFzVVNoZWxsKCkpIHtcblx0XHR0aHJvdyBcIk5vIFNoZWxsLi4uIE5vIFVzZXJcIjtcblx0fVxuXHRjb25zdCBtZTogVXNlciA9IHtcblx0XHRpbml0aWFsczogc2hlbGxTZXJ2aWNlSGVscGVyLmdldFVzZXIoKS5nZXRJbml0aWFscygpLFxuXHRcdGlkOiBzaGVsbFNlcnZpY2VIZWxwZXIuZ2V0VXNlcigpLmdldElkKCksXG5cdFx0bmFtZTogc2hlbGxTZXJ2aWNlSGVscGVyLmdldFVzZXIoKS5nZXRGdWxsTmFtZSgpICsgXCIgKFwiICsgZ2V0VGV4dChcIkNfQ09MTEFCT1JBVElPTkRSQUZUX1lPVVwiKSArIFwiKVwiLFxuXHRcdGluaXRpYWxOYW1lOiBzaGVsbFNlcnZpY2VIZWxwZXIuZ2V0VXNlcigpLmdldEZ1bGxOYW1lKCksXG5cdFx0Y29sb3I6IDYsIC8vICBzYW1lIGNvbG9yIGFzIEZMUC4uLlxuXHRcdHJvbGU6IFJvbGUuT3duZXIsXG5cdFx0bWU6IHRydWVcblx0fTtcblxuXHRyZXR1cm4gbWU7XG59XG5cbmZ1bmN0aW9uIGdldFRleHQodGV4dElkOiBzdHJpbmcsIC4uLmFyZ3M6IHN0cmluZ1tdKTogc3RyaW5nIHtcblx0Y29uc3Qgb1Jlc291cmNlTW9kZWwgPSAoQ29yZSBhcyBDb3JlRXgpLmdldExpYnJhcnlSZXNvdXJjZUJ1bmRsZShcInNhcC5mZS5jb3JlXCIpO1xuXHRyZXR1cm4gb1Jlc291cmNlTW9kZWwuZ2V0VGV4dCh0ZXh0SWQsIGFyZ3MpO1xufVxuXG5leHBvcnQgY29uc3QgQ29sbGFib3JhdGlvblV0aWxzID0ge1xuXHRmb3JtYXRJbml0aWFsczogZm9ybWF0SW5pdGlhbHMsXG5cdGdldFVzZXJDb2xvcjogZ2V0VXNlckNvbG9yLFxuXHRnZXRNZTogZ2V0TWUsXG5cdGdldEFwcENvbXBvbmVudDogZ2V0QXBwQ29tcG9uZW50LFxuXHRnZXRUZXh0OiBnZXRUZXh0XG59O1xuIl19
@@ -0,0 +1,129 @@
1
+ import View from "sap/ui/core/mvc/View";
2
+ import Component from "sap/ui/core/Component";
3
+ import AppComponent from "sap/fe/core/AppComponent";
4
+ import { CoreEx } from "../../../../../../../../types/extension_types";
5
+ import Core from "sap/ui/core/Core";
6
+
7
+ export type User = {
8
+ id: string;
9
+ initials?: string;
10
+ name: string;
11
+ role?: Role;
12
+ color?: number;
13
+ transient?: boolean;
14
+ me?: boolean;
15
+ initialName?: string;
16
+ };
17
+
18
+ export type UserActivity = User & {
19
+ key?: string;
20
+ };
21
+
22
+ export enum Role {
23
+ Owner = "O",
24
+ Edit = "E"
25
+ }
26
+
27
+ export enum Activity {
28
+ Join = "JOIN",
29
+ JoinEcho = "JOINECHO",
30
+ Leave = "LEAVE",
31
+ Change = "CHANGE",
32
+ Create = "CREATE",
33
+ Delete = "DELETE",
34
+ Action = "ACTION",
35
+ LiveChange = "LIVECHANGE",
36
+ Activate = "ACTIVATE",
37
+ Discard = "DISCARD",
38
+ Undo = "UNDO"
39
+ }
40
+
41
+ export type Message = {
42
+ userDescription: string;
43
+ userID: string;
44
+ userAction: string;
45
+ clientAction: string;
46
+ clientContent: string;
47
+ };
48
+
49
+ function formatInitials(fullName: string): string {
50
+ // remove titles - those are the ones from S/4 to be checked if there are others
51
+ const academicTitles = ["Dr.", "Prof.", "Prof. Dr.", "B.A.", "MBA", "Ph.D."];
52
+ academicTitles.forEach(function(academicTitle) {
53
+ fullName = fullName.replace(academicTitle, "");
54
+ });
55
+
56
+ let initials: string;
57
+ const parts = fullName.trimStart().split(" ");
58
+
59
+ if (parts.length > 1) {
60
+ initials = (parts?.shift()?.charAt(0) || "") + parts.pop()?.charAt(0);
61
+ } else {
62
+ initials = fullName.substring(0, 2);
63
+ }
64
+
65
+ return initials.toUpperCase();
66
+ }
67
+
68
+ function getUserColor(UserID: string, activeUsers: User[], invitedUsers: User[]) {
69
+ // search if user is known
70
+ const user = activeUsers.find(u => u.id === UserID);
71
+ if (user) {
72
+ return user.color;
73
+ } else {
74
+ // search for next free color
75
+ for (let i = 1; i <= 10; i++) {
76
+ if (activeUsers.findIndex(u => u.color === i) === -1 && invitedUsers.findIndex(u => u.color === i) === -1) {
77
+ return i;
78
+ }
79
+ }
80
+ // this seems to be a popular object :) for now just return 10 for all.
81
+ // for invited we should start from 1 again so the colors are different
82
+ return 10;
83
+ }
84
+ }
85
+
86
+ // copied from CommonUtils. Due to a cycle dependency I can't use CommonUtils here.
87
+ // That's to be fixed. the discard popover thingy shouldn't be in the common utils at all
88
+ function getAppComponent(oControl: any): AppComponent {
89
+ if (oControl.isA("sap.fe.core.AppComponent")) {
90
+ return oControl;
91
+ }
92
+ const oOwner = Component.getOwnerComponentFor(oControl);
93
+ if (!oOwner) {
94
+ return oControl;
95
+ } else {
96
+ return getAppComponent(oOwner);
97
+ }
98
+ }
99
+
100
+ function getMe(view: View): User {
101
+ const shellServiceHelper = getAppComponent(view).getShellServices();
102
+ if (!shellServiceHelper || !shellServiceHelper.hasUShell()) {
103
+ throw "No Shell... No User";
104
+ }
105
+ const me: User = {
106
+ initials: shellServiceHelper.getUser().getInitials(),
107
+ id: shellServiceHelper.getUser().getId(),
108
+ name: shellServiceHelper.getUser().getFullName() + " (" + getText("C_COLLABORATIONDRAFT_YOU") + ")",
109
+ initialName: shellServiceHelper.getUser().getFullName(),
110
+ color: 6, // same color as FLP...
111
+ role: Role.Owner,
112
+ me: true
113
+ };
114
+
115
+ return me;
116
+ }
117
+
118
+ function getText(textId: string, ...args: string[]): string {
119
+ const oResourceModel = (Core as CoreEx).getLibraryResourceBundle("sap.fe.core");
120
+ return oResourceModel.getText(textId, args);
121
+ }
122
+
123
+ export const CollaborationUtils = {
124
+ formatInitials: formatInitials,
125
+ getUserColor: getUserColor,
126
+ getMe: getMe,
127
+ getAppComponent: getAppComponent,
128
+ getText: getText
129
+ };