@sapui5/sap.fe.core 1.96.4 → 1.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/package.json +6 -5
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AnnotationHelper.js +377 -405
  4. package/src/sap/fe/core/AnnotationHelper.ts +385 -0
  5. package/src/sap/fe/core/AppComponent.js +5 -3
  6. package/src/sap/fe/core/AppStateHandler.js +229 -195
  7. package/src/sap/fe/core/AppStateHandler.ts +171 -0
  8. package/src/sap/fe/core/BaseController.js +3 -2
  9. package/src/sap/fe/core/BusyLocker.js +105 -121
  10. package/src/sap/fe/core/BusyLocker.ts +98 -0
  11. package/src/sap/fe/core/CommonUtils.js +2073 -2606
  12. package/src/sap/fe/core/CommonUtils.ts +2078 -0
  13. package/src/sap/fe/core/ExtensionAPI.js +16 -7
  14. package/src/sap/fe/core/PageController.js +84 -119
  15. package/src/sap/fe/core/PageController.ts +101 -0
  16. package/src/sap/fe/core/RouterProxy.js +986 -809
  17. package/src/sap/fe/core/RouterProxy.ts +838 -0
  18. package/src/sap/fe/core/Synchronization.js +51 -35
  19. package/src/sap/fe/core/Synchronization.ts +29 -0
  20. package/src/sap/fe/core/TemplateComponent.js +173 -155
  21. package/src/sap/fe/core/TemplateComponent.ts +166 -0
  22. package/src/sap/fe/core/TemplateModel.js +97 -54
  23. package/src/sap/fe/core/TemplateModel.ts +63 -0
  24. package/src/sap/fe/core/TransactionHelper.js +1576 -1627
  25. package/src/sap/fe/core/TransactionHelper.ts +1706 -0
  26. package/src/sap/fe/core/actions/draft.js +559 -581
  27. package/src/sap/fe/core/actions/draft.ts +593 -0
  28. package/src/sap/fe/core/actions/messageHandling.js +545 -435
  29. package/src/sap/fe/core/actions/messageHandling.ts +532 -0
  30. package/src/sap/fe/core/actions/nonDraft.js +17 -19
  31. package/src/sap/fe/core/actions/nonDraft.ts +12 -0
  32. package/src/sap/fe/core/actions/operations.js +1074 -1192
  33. package/src/sap/fe/core/actions/operations.ts +1162 -0
  34. package/src/sap/fe/core/actions/sticky.js +102 -105
  35. package/src/sap/fe/core/actions/sticky.ts +102 -0
  36. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +3 -2
  37. package/src/sap/fe/core/controllerextensions/EditFlow.js +235 -264
  38. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +3 -2
  39. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +288 -13
  40. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +35 -25
  41. package/src/sap/fe/core/controllerextensions/InternalRouting.js +79 -46
  42. package/src/sap/fe/core/controllerextensions/KPIManagement.js +86 -10
  43. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +109 -31
  44. package/src/sap/fe/core/controllerextensions/MassEdit.js +172 -0
  45. package/src/sap/fe/core/controllerextensions/MessageHandler.js +237 -104
  46. package/src/sap/fe/core/controllerextensions/PageReady.js +3 -3
  47. package/src/sap/fe/core/controllerextensions/PageReady.ts +12 -8
  48. package/src/sap/fe/core/controllerextensions/Paginator.js +37 -9
  49. package/src/sap/fe/core/controllerextensions/Placeholder.js +8 -4
  50. package/src/sap/fe/core/controllerextensions/Routing.js +25 -5
  51. package/src/sap/fe/core/controllerextensions/RoutingListener.js +3 -2
  52. package/src/sap/fe/core/controllerextensions/Share.js +3 -2
  53. package/src/sap/fe/core/controllerextensions/SideEffects.js +9 -9
  54. package/src/sap/fe/core/controllerextensions/SideEffects.ts +22 -21
  55. package/src/sap/fe/core/controllerextensions/ViewState.js +36 -8
  56. package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +2 -1
  57. package/src/sap/fe/core/controls/CommandExecution.js +3 -2
  58. package/src/sap/fe/core/controls/ConditionalWrapper.js +3 -2
  59. package/src/sap/fe/core/controls/CustomQuickViewPage.js +112 -113
  60. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +9 -5
  61. package/src/sap/fe/core/controls/FieldWrapper.js +18 -23
  62. package/src/sap/fe/core/controls/FilterBar.js +3 -2
  63. package/src/sap/fe/core/controls/FormElementWrapper.js +3 -7
  64. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +3 -2
  65. package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +2 -1
  66. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +3 -2
  67. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +5 -4
  68. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +3 -2
  69. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +3 -2
  70. package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +106 -0
  71. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +79 -0
  72. package/src/sap/fe/core/converters/ConverterContext.js +14 -2
  73. package/src/sap/fe/core/converters/ConverterContext.ts +14 -3
  74. package/src/sap/fe/core/converters/ManifestSettings.js +2 -1
  75. package/src/sap/fe/core/converters/ManifestSettings.ts +8 -1
  76. package/src/sap/fe/core/converters/ManifestWrapper.js +56 -32
  77. package/src/sap/fe/core/converters/ManifestWrapper.ts +24 -6
  78. package/src/sap/fe/core/converters/MetaModelConverter.js +76 -6
  79. package/src/sap/fe/core/converters/MetaModelConverter.ts +79 -15
  80. package/src/sap/fe/core/converters/TemplateConverter.js +1 -1
  81. package/src/sap/fe/core/converters/TemplateConverter.ts +2 -2
  82. package/src/sap/fe/core/converters/annotations/DataField.js +3 -3
  83. package/src/sap/fe/core/converters/annotations/DataField.ts +1 -1
  84. package/src/sap/fe/core/converters/common/AnnotationConverter.js +85 -46
  85. package/src/sap/fe/core/converters/controls/Common/Action.js +16 -4
  86. package/src/sap/fe/core/converters/controls/Common/Action.ts +14 -5
  87. package/src/sap/fe/core/converters/controls/Common/Chart.js +5 -3
  88. package/src/sap/fe/core/converters/controls/Common/Chart.ts +11 -3
  89. package/src/sap/fe/core/converters/controls/Common/DataVisualization.js +3 -3
  90. package/src/sap/fe/core/converters/controls/Common/DataVisualization.ts +2 -2
  91. package/src/sap/fe/core/converters/controls/Common/Form.js +60 -19
  92. package/src/sap/fe/core/converters/controls/Common/Form.ts +66 -14
  93. package/src/sap/fe/core/converters/controls/Common/KPI.js +69 -4
  94. package/src/sap/fe/core/converters/controls/Common/KPI.ts +72 -0
  95. package/src/sap/fe/core/converters/controls/Common/Table.js +503 -399
  96. package/src/sap/fe/core/converters/controls/Common/Table.ts +615 -480
  97. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +527 -0
  98. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +655 -0
  99. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +489 -37
  100. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +506 -58
  101. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +2 -2
  102. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +1 -1
  103. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +6 -6
  104. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +9 -15
  105. package/src/sap/fe/core/converters/helpers/Aggregation.js +18 -3
  106. package/src/sap/fe/core/converters/helpers/Aggregation.ts +28 -5
  107. package/src/sap/fe/core/converters/helpers/ID.js +9 -1
  108. package/src/sap/fe/core/converters/helpers/ID.ts +4 -0
  109. package/src/sap/fe/core/converters/helpers/IssueManager.js +7 -1
  110. package/src/sap/fe/core/converters/helpers/IssueManager.ts +6 -0
  111. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +4 -4
  112. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +3 -3
  113. package/src/sap/fe/core/converters/templates/ListReportConverter.js +29 -11
  114. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +36 -20
  115. package/src/sap/fe/core/designtime/AppComponent.designtime.js +13 -3
  116. package/src/sap/fe/core/formatters/CriticalityFormatter.js +1 -1
  117. package/src/sap/fe/core/formatters/CriticalityFormatter.ts +1 -1
  118. package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
  119. package/src/sap/fe/core/formatters/FPMFormatter.ts +4 -10
  120. package/src/sap/fe/core/formatters/KPIFormatter.js +1 -1
  121. package/src/sap/fe/core/formatters/KPIFormatter.ts +3 -1
  122. package/src/sap/fe/core/formatters/TableFormatter.js +65 -31
  123. package/src/sap/fe/core/formatters/TableFormatter.ts +62 -30
  124. package/src/sap/fe/core/formatters/ValueFormatter.js +30 -5
  125. package/src/sap/fe/core/formatters/ValueFormatter.ts +30 -7
  126. package/src/sap/fe/core/fpm/Component.js +3 -2
  127. package/src/sap/fe/core/helpers/AppStartupHelper.js +359 -0
  128. package/src/sap/fe/core/helpers/AppStartupHelper.ts +391 -0
  129. package/src/sap/fe/core/helpers/BindingExpression.js +479 -464
  130. package/src/sap/fe/core/helpers/BindingExpression.ts +477 -483
  131. package/src/sap/fe/core/helpers/ClassSupport.js +27 -15
  132. package/src/sap/fe/core/helpers/ClassSupport.ts +31 -20
  133. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +63 -59
  134. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.ts +56 -0
  135. package/src/sap/fe/core/helpers/EditState.js +81 -84
  136. package/src/sap/fe/core/helpers/EditState.ts +81 -0
  137. package/src/sap/fe/core/helpers/ExcelFormatHelper.js +62 -48
  138. package/src/sap/fe/core/helpers/ExcelFormatHelper.ts +49 -0
  139. package/src/sap/fe/core/helpers/FPMHelper.js +52 -56
  140. package/src/sap/fe/core/helpers/FPMHelper.ts +62 -0
  141. package/src/sap/fe/core/helpers/KeepAliveHelper.js +210 -0
  142. package/src/sap/fe/core/helpers/KeepAliveHelper.ts +202 -0
  143. package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.js +32 -0
  144. package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.ts +36 -0
  145. package/src/sap/fe/core/helpers/MassEditHelper.js +687 -0
  146. package/src/sap/fe/core/helpers/ModelHelper.js +229 -174
  147. package/src/sap/fe/core/helpers/ModelHelper.ts +227 -0
  148. package/src/sap/fe/core/helpers/PasteHelper.js +210 -132
  149. package/src/sap/fe/core/helpers/PasteHelper.ts +196 -0
  150. package/src/sap/fe/core/helpers/SemanticDateOperators.js +332 -313
  151. package/src/sap/fe/core/helpers/SemanticDateOperators.ts +330 -0
  152. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +66 -67
  153. package/src/sap/fe/core/helpers/SemanticKeyHelper.ts +73 -0
  154. package/src/sap/fe/core/helpers/StableIdHelper.js +4 -7
  155. package/src/sap/fe/core/helpers/StableIdHelper.ts +2 -6
  156. package/src/sap/fe/core/jsx-runtime/jsx.js +1 -1
  157. package/src/sap/fe/core/jsx-runtime/jsx.ts +1 -1
  158. package/src/sap/fe/core/library.js +30 -3
  159. package/src/sap/fe/core/library.support.js +12 -5
  160. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +62 -0
  161. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +66 -0
  162. package/src/sap/fe/core/messagebundle.properties +72 -10
  163. package/src/sap/fe/core/messagebundle_ar.properties +41 -0
  164. package/src/sap/fe/core/messagebundle_bg.properties +41 -0
  165. package/src/sap/fe/core/messagebundle_ca.properties +41 -0
  166. package/src/sap/fe/core/messagebundle_cs.properties +42 -1
  167. package/src/sap/fe/core/messagebundle_cy.properties +41 -0
  168. package/src/sap/fe/core/messagebundle_da.properties +41 -0
  169. package/src/sap/fe/core/messagebundle_de.properties +41 -0
  170. package/src/sap/fe/core/messagebundle_el.properties +41 -0
  171. package/src/sap/fe/core/messagebundle_en.properties +41 -0
  172. package/src/sap/fe/core/messagebundle_en_GB.properties +41 -0
  173. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +41 -0
  174. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +35 -0
  175. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +41 -0
  176. package/src/sap/fe/core/messagebundle_es.properties +41 -0
  177. package/src/sap/fe/core/messagebundle_es_MX.properties +41 -0
  178. package/src/sap/fe/core/messagebundle_et.properties +41 -0
  179. package/src/sap/fe/core/messagebundle_fi.properties +41 -0
  180. package/src/sap/fe/core/messagebundle_fr.properties +46 -5
  181. package/src/sap/fe/core/messagebundle_fr_CA.properties +41 -0
  182. package/src/sap/fe/core/messagebundle_hi.properties +41 -0
  183. package/src/sap/fe/core/messagebundle_hr.properties +41 -0
  184. package/src/sap/fe/core/messagebundle_hu.properties +42 -1
  185. package/src/sap/fe/core/messagebundle_id.properties +45 -4
  186. package/src/sap/fe/core/messagebundle_it.properties +41 -0
  187. package/src/sap/fe/core/messagebundle_iw.properties +41 -0
  188. package/src/sap/fe/core/messagebundle_ja.properties +50 -9
  189. package/src/sap/fe/core/messagebundle_kk.properties +41 -0
  190. package/src/sap/fe/core/messagebundle_ko.properties +41 -0
  191. package/src/sap/fe/core/messagebundle_lt.properties +41 -0
  192. package/src/sap/fe/core/messagebundle_lv.properties +41 -0
  193. package/src/sap/fe/core/messagebundle_ms.properties +41 -0
  194. package/src/sap/fe/core/messagebundle_nl.properties +41 -0
  195. package/src/sap/fe/core/messagebundle_no.properties +41 -0
  196. package/src/sap/fe/core/messagebundle_pl.properties +41 -0
  197. package/src/sap/fe/core/messagebundle_pt.properties +43 -2
  198. package/src/sap/fe/core/messagebundle_pt_PT.properties +41 -0
  199. package/src/sap/fe/core/messagebundle_ro.properties +41 -0
  200. package/src/sap/fe/core/messagebundle_ru.properties +41 -0
  201. package/src/sap/fe/core/messagebundle_sh.properties +41 -0
  202. package/src/sap/fe/core/messagebundle_sk.properties +41 -0
  203. package/src/sap/fe/core/messagebundle_sl.properties +41 -0
  204. package/src/sap/fe/core/messagebundle_sv.properties +42 -1
  205. package/src/sap/fe/core/messagebundle_th.properties +41 -0
  206. package/src/sap/fe/core/messagebundle_tr.properties +41 -0
  207. package/src/sap/fe/core/messagebundle_uk.properties +41 -0
  208. package/src/sap/fe/core/messagebundle_vi.properties +41 -0
  209. package/src/sap/fe/core/messagebundle_zh_CN.properties +41 -0
  210. package/src/sap/fe/core/messagebundle_zh_TW.properties +41 -0
  211. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +2 -2
  212. package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +3 -1
  213. package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +269 -202
  214. package/src/sap/fe/core/services/CacheHandlerServiceFactory.ts +212 -0
  215. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +4 -3
  216. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +9 -5
  217. package/src/sap/fe/core/services/NavigationServiceFactory.js +406 -300
  218. package/src/sap/fe/core/services/NavigationServiceFactory.ts +316 -0
  219. package/src/sap/fe/core/services/ResourceModelServiceFactory.js +149 -81
  220. package/src/sap/fe/core/services/ResourceModelServiceFactory.ts +80 -0
  221. package/src/sap/fe/core/services/RoutingServiceFactory.js +987 -1166
  222. package/src/sap/fe/core/services/RoutingServiceFactory.ts +898 -0
  223. package/src/sap/fe/core/services/ShellServicesFactory.js +31 -2
  224. package/src/sap/fe/core/services/ShellServicesFactory.ts +45 -11
  225. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +41 -84
  226. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +56 -99
  227. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +461 -478
  228. package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +453 -0
  229. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +10 -8
  230. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.ts +8 -0
  231. package/src/sap/fe/core/support/AnnotationIssue.support.js +15 -3
  232. package/src/sap/fe/core/support/AnnotationIssue.support.ts +16 -2
  233. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.js +2 -2
  234. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.ts +1 -1
  235. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.js +38 -0
  236. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.ts +18 -0
  237. package/src/sap/fe/core/templating/DataModelPathHelper.js +6 -24
  238. package/src/sap/fe/core/templating/DataModelPathHelper.ts +10 -23
  239. package/src/sap/fe/core/templating/DisplayModeFormatter.js +114 -0
  240. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +86 -0
  241. package/src/sap/fe/core/templating/EntitySetHelper.js +80 -7
  242. package/src/sap/fe/core/templating/EntitySetHelper.ts +42 -2
  243. package/src/sap/fe/core/templating/FieldControlHelper.js +8 -8
  244. package/src/sap/fe/core/templating/FieldControlHelper.ts +25 -7
  245. package/src/sap/fe/core/templating/FilterHelper.js +139 -70
  246. package/src/sap/fe/core/templating/FilterHelper.ts +140 -70
  247. package/src/sap/fe/core/templating/PropertyHelper.js +2 -2
  248. package/src/sap/fe/core/templating/PropertyHelper.ts +1 -1
  249. package/src/sap/fe/core/templating/UIFormatters.js +45 -113
  250. package/src/sap/fe/core/templating/UIFormatters.ts +39 -76
  251. package/src/sap/fe/core/type/Email.js +1 -1
  252. package/src/sap/fe/core/type/Email.ts +4 -6
  253. package/ui5.yaml +0 -3
@@ -0,0 +1,391 @@
1
+ import ODataMetaModel from "sap/ui/model/odata/v4/ODataMetaModel";
2
+ import ODataModel from "sap/ui/model/odata/v4/ODataModel";
3
+ import Context from "sap/ui/model/odata/v4/Context";
4
+ import Filter from "sap/ui/model/Filter";
5
+ import FilterOperator from "sap/ui/model/FilterOperator";
6
+ import Router from "sap/ui/core/routing/Router";
7
+ import ModelHelper from "./ModelHelper";
8
+
9
+ type ValuedKey = {
10
+ name: string;
11
+ value: string;
12
+ };
13
+
14
+ type PageInfo = {
15
+ pattern: string;
16
+ contextPath: string;
17
+ draftMode: Boolean;
18
+ technicalKeys: ValuedKey[] | undefined;
19
+ semanticKeys: ValuedKey[] | undefined;
20
+ target: string;
21
+ };
22
+
23
+ /**
24
+ * Retrieves a set of key values from startup parameters.
25
+ *
26
+ * @param aKeyNames The array of key names
27
+ * @param oStartupParameters The startup parameters
28
+ * @returns An array of pairs {name, value} if all key values could be found in the startup parameters, undefined otherwise
29
+ */
30
+ function _getKeysFromStartupParams(aKeyNames: string[], oStartupParameters: any): ValuedKey[] | undefined {
31
+ let bAllFound = true;
32
+ const aKeys = aKeyNames.map(name => {
33
+ if (oStartupParameters[name] && oStartupParameters[name].length === 1) {
34
+ return { name, value: oStartupParameters[name][0] as string };
35
+ } else {
36
+ // A unique key value couldn't be found in the startup parameters
37
+ bAllFound = false;
38
+ return { name, value: "" };
39
+ }
40
+ });
41
+
42
+ return bAllFound ? aKeys : undefined;
43
+ }
44
+
45
+ /**
46
+ * Creates a filter from a list of key values.
47
+ *
48
+ * @param aKeys Array of semantic keys or technical keys (with values)
49
+ * @param bDraftMode True if the entity supports draft mode
50
+ * @param oMetaModel The metamodel
51
+ * @returns The filter
52
+ */
53
+ function _createFilterFromKeys(aKeys: ValuedKey[], bDraftMode: Boolean, oMetaModel: ODataMetaModel): Filter {
54
+ const bFilterCaseSensitive = ModelHelper.isFilteringCaseSensitive(oMetaModel);
55
+
56
+ let bFilterOnActiveEntity = false;
57
+ const aFilters = aKeys.map(key => {
58
+ if (key.name === "IsActiveEntity") {
59
+ bFilterOnActiveEntity = true;
60
+ }
61
+ return new Filter({
62
+ path: key.name,
63
+ operator: FilterOperator.EQ,
64
+ value1: key.value,
65
+ caseSensitive: bFilterCaseSensitive
66
+ });
67
+ });
68
+ if (bDraftMode && !bFilterOnActiveEntity) {
69
+ const oDraftFilter = new Filter({
70
+ filters: [new Filter("IsActiveEntity", "EQ", false), new Filter("SiblingEntity/IsActiveEntity", "EQ", null)],
71
+ and: false
72
+ });
73
+ aFilters.push(oDraftFilter);
74
+ }
75
+
76
+ return new Filter(aFilters, true);
77
+ }
78
+
79
+ /**
80
+ * Loads all contexts for a list of page infos.
81
+ *
82
+ * @param aStartupPages The list of page infos
83
+ * @param oModel The model used to load the contexts
84
+ * @returns A Promise for all contexts
85
+ */
86
+ function _requestObjectsFromParameters(aStartupPages: PageInfo[], oModel: ODataModel): Promise<Context[][]> {
87
+ // Load the respective objects for all object pages found in aExternallyNavigablePages
88
+ const aContextPromises = aStartupPages.map(pageInfo => {
89
+ const aKeys = pageInfo.semanticKeys || pageInfo.technicalKeys || [];
90
+ const oFilter = _createFilterFromKeys(aKeys, pageInfo.draftMode, oModel.getMetaModel());
91
+
92
+ // only request a minimum of fields to boost backend performance since this is only used to check if an object exists
93
+ const oListBind = oModel.bindList(pageInfo.contextPath, undefined, undefined, oFilter, {
94
+ "$select": aKeys
95
+ .map(key => {
96
+ return key.name;
97
+ })
98
+ .join(",")
99
+ } as any);
100
+ return oListBind.requestContexts(0, 2);
101
+ });
102
+
103
+ return Promise.all(aContextPromises);
104
+ }
105
+
106
+ /**
107
+ * Returns the list of all pages that allow deeplink and that can be reached using the startup parameters.
108
+ *
109
+ * @param oManifestRouting The routing information from the app manifest
110
+ * @param oStartupParameters The startup parameters
111
+ * @param oMetaModel The metamodel
112
+ * @returns
113
+ */
114
+ function _getReachablePages(oManifestRouting: any, oStartupParameters: any, oMetaModel: ODataMetaModel): PageInfo[][] {
115
+ const aRoutes: any[] = oManifestRouting.routes;
116
+ const mPagesByLevel: Record<number, PageInfo[]> = {};
117
+
118
+ aRoutes.forEach(oRoute => {
119
+ let sPattern: string = oRoute.pattern.replace(":?query:", "");
120
+ if (sPattern.endsWith("/")) {
121
+ sPattern = sPattern.substr(0, sPattern.length - 1);
122
+ }
123
+
124
+ if (sPattern) {
125
+ // Ignore level-0 routes (ListReport)
126
+ sPattern = sPattern.replace(/\(\{[^\}]*\}\)/g, "(#)"); // Replace keys with #
127
+
128
+ // Get the rightmost target for this route
129
+ const sTargetName: string = Array.isArray(oRoute.target) ? oRoute.target[oRoute.target.length - 1] : oRoute.target;
130
+ const oTarget = oManifestRouting.targets[sTargetName];
131
+
132
+ const aPatternSegments = sPattern.split("/");
133
+ const pageLevel = aPatternSegments.length - 1;
134
+
135
+ // The first level of object page allows deep linking by default.
136
+ // Otherwise, the target must allow deep linking explicitely in the manifest
137
+ if (pageLevel === 0 || oTarget?.options?.settings?.allowDeepLinking) {
138
+ const sContextPath: string =
139
+ oTarget.options.settings.contextPath ||
140
+ (oTarget.options.settings.entitySet && "/" + oTarget.options.settings.entitySet);
141
+ const oEntityType = sContextPath && oMetaModel.getObject("/$EntityContainer" + sContextPath + "/");
142
+
143
+ if (oEntityType) {
144
+ // Get the semantic key values for the entity
145
+ const aSemanticKeyNames: any = oMetaModel.getObject(
146
+ "/$EntityContainer" + sContextPath + "/@com.sap.vocabularies.Common.v1.SemanticKey"
147
+ );
148
+ const aSemantickKeys = aSemanticKeyNames
149
+ ? _getKeysFromStartupParams(
150
+ aSemanticKeyNames.map((semKey: any) => {
151
+ return semKey.$PropertyPath as string;
152
+ }),
153
+ oStartupParameters
154
+ )
155
+ : undefined;
156
+
157
+ // Get the technical keys only if we couldn't find the semantic key values, and on first level OP
158
+ const aTechnicalKeys =
159
+ !aSemantickKeys && pageLevel === 0 ? _getKeysFromStartupParams(oEntityType["$Key"], oStartupParameters) : undefined;
160
+
161
+ if (aSemantickKeys || aTechnicalKeys) {
162
+ // The startup parameters contain values for all semantic keys (or technical keys) --> we can store the page info in the corresponding level
163
+ const draftMode =
164
+ oMetaModel.getObject("/$EntityContainer" + sContextPath + "@com.sap.vocabularies.Common.v1.DraftRoot") ||
165
+ oMetaModel.getObject("/$EntityContainer" + sContextPath + "@com.sap.vocabularies.Common.v1.DraftNode")
166
+ ? true
167
+ : false;
168
+
169
+ if (!mPagesByLevel[pageLevel]) {
170
+ mPagesByLevel[pageLevel] = [];
171
+ }
172
+ mPagesByLevel[pageLevel].push({
173
+ pattern: sPattern,
174
+ contextPath: sContextPath,
175
+ draftMode,
176
+ technicalKeys: aTechnicalKeys,
177
+ semanticKeys: aSemantickKeys,
178
+ target: sTargetName
179
+ });
180
+ }
181
+ }
182
+ }
183
+ }
184
+ });
185
+
186
+ // A page is reachable only if all its parents are also reachable
187
+ // So if we couldn't find any pages for a given level, all pages with a higher level won't be reachable anyway
188
+ const aReachablePages: PageInfo[][] = [];
189
+ let level = 0;
190
+ while (mPagesByLevel[level]) {
191
+ aReachablePages.push(mPagesByLevel[level]);
192
+ level++;
193
+ }
194
+
195
+ return aReachablePages;
196
+ }
197
+
198
+ /**
199
+ * Get the list of startup pages.
200
+ *
201
+ * @param oManifestRouting The routing information from the app manifest
202
+ * @param oStartupParameters The startup parameters
203
+ * @param oMetaModel The metamodel
204
+ * @returns An array of startup page infos
205
+ */
206
+ function _getStartupPagesFromStartupParams(oManifestRouting: any, oStartupParameters: any, oMetaModel: ODataMetaModel): PageInfo[] {
207
+ // Find all pages that can be reached with the startup parameters
208
+ const aReachablePages = _getReachablePages(oManifestRouting, oStartupParameters, oMetaModel);
209
+
210
+ if (aReachablePages.length === 0) {
211
+ return [];
212
+ }
213
+
214
+ // Find the longest sequence of pages that can be reached (recursively)
215
+ let result: PageInfo[] = [];
216
+ const current: PageInfo[] = [];
217
+
218
+ function findRecursive(level: number) {
219
+ const aCurrentLevelPages = aReachablePages[level];
220
+ const lastPage = current.length ? current[current.length - 1] : undefined;
221
+
222
+ if (aCurrentLevelPages) {
223
+ aCurrentLevelPages.forEach(function(nextPage) {
224
+ if (!lastPage || nextPage.pattern.indexOf(lastPage.pattern) === 0) {
225
+ // We only consider pages that can be reached from the page at the previous level,
226
+ // --> their pattern must be the pattern of the previous page with another segment appended
227
+ current.push(nextPage);
228
+ findRecursive(level + 1);
229
+ current.pop();
230
+ }
231
+ });
232
+ }
233
+ if (current.length > result.length) {
234
+ result = current.slice(); // We have found a sequence longer than our previous best --> store it as the new longest
235
+ }
236
+ }
237
+
238
+ findRecursive(0);
239
+
240
+ return result;
241
+ }
242
+
243
+ /**
244
+ * Creates the startup object from the list of pages and contexts.
245
+ *
246
+ * @param aStartupPages The pages
247
+ * @param aContexts The contexts
248
+ * @returns An object containing either a hash or a context to navigate to, or an empty object if no deep link was found
249
+ */
250
+ function _getDeepLinkObject(aStartupPages: PageInfo[], aContexts: Context[]): { hash?: string; context?: Context } {
251
+ if (aContexts.length === 1) {
252
+ return { context: aContexts[0] };
253
+ } else if (aContexts.length > 1) {
254
+ // Navigation to a deeper level --> use the pattern of the deepest object page
255
+ // and replace the parameters by the ID from the contexts
256
+ let hash = aStartupPages[aStartupPages.length - 1].pattern;
257
+ aContexts.forEach(function(oContext) {
258
+ hash = hash.replace("(#)", "(" + oContext.getPath().split("(")[1]);
259
+ });
260
+
261
+ return { hash };
262
+ } else {
263
+ return {};
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Calculates startup parameters for a deeplink case, from startup parameters and routing infoirmation.
269
+ *
270
+ * @param oManifestRouting The routing information from the app manifest
271
+ * @param oStartupParameters The startup parameters
272
+ * @param oModel The OData model
273
+ * @returns An object containing either a hash or a context to navigate to, or an empty object if no deep link was found
274
+ */
275
+ function getDeepLinkStartupHash(
276
+ oManifestRouting: any,
277
+ oStartupParameters: any,
278
+ oModel: ODataModel
279
+ ): Promise<{ hash?: string; context?: Context }> {
280
+ let aStartupPages: PageInfo[];
281
+
282
+ return oModel
283
+ .getMetaModel()
284
+ .requestObject("/$EntityContainer/")
285
+ .then(() => {
286
+ // Check if semantic keys are present in url parameters for every object page at each level
287
+ aStartupPages = _getStartupPagesFromStartupParams(oManifestRouting, oStartupParameters, oModel.getMetaModel());
288
+
289
+ return _requestObjectsFromParameters(aStartupPages, oModel);
290
+ })
291
+ .then((aValues: Context[][]) => {
292
+ if (aValues.length) {
293
+ // Make sure we only get 1 context per promise, and flatten the array
294
+ const aContexts: Context[] = [];
295
+ aValues.forEach(function(aFoundContexts) {
296
+ if (aFoundContexts.length === 1) {
297
+ aContexts.push(aFoundContexts[0]);
298
+ }
299
+ });
300
+
301
+ return aContexts.length === aValues.length ? _getDeepLinkObject(aStartupPages, aContexts) : {};
302
+ } else {
303
+ return {};
304
+ }
305
+ });
306
+ }
307
+
308
+ /**
309
+ * Calculates the new hash based on the startup parameters.
310
+ *
311
+ * @param oStartupParameters The startup parameter values (map parameter name -> array of values)
312
+ * @param sContextPath The context path for the startup of the app (generally the path to the main entity set)
313
+ * @param oRouter The router instance
314
+ * @param oMetaModel The meta model
315
+ * @returns A promise containing the hash to navigate to, or an empty string if there's no need to navigate
316
+ */
317
+ function getCreateStartupHash(oStartupParameters: any, sContextPath: string, oRouter: Router, oMetaModel: ODataMetaModel): Promise<String> {
318
+ return oMetaModel.requestObject(sContextPath + "@").then(function(oEntitySetAnnotations: any) {
319
+ let sMetaPath = "";
320
+ let bCreatable = true;
321
+
322
+ if (
323
+ oEntitySetAnnotations["@com.sap.vocabularies.Common.v1.DraftRoot"] &&
324
+ oEntitySetAnnotations["@com.sap.vocabularies.Common.v1.DraftRoot"]["NewAction"]
325
+ ) {
326
+ sMetaPath = sContextPath + "@com.sap.vocabularies.Common.v1.DraftRoot/NewAction@Org.OData.Core.V1.OperationAvailable";
327
+ } else if (
328
+ oEntitySetAnnotations["@com.sap.vocabularies.Session.v1.StickySessionSupported"] &&
329
+ oEntitySetAnnotations["@com.sap.vocabularies.Session.v1.StickySessionSupported"]["NewAction"]
330
+ ) {
331
+ sMetaPath =
332
+ sContextPath + "@com.sap.vocabularies.Session.v1.StickySessionSupported/NewAction@Org.OData.Core.V1.OperationAvailable";
333
+ }
334
+
335
+ if (sMetaPath) {
336
+ const bNewActionOperationAvailable = oMetaModel.getObject(sMetaPath);
337
+ if (bNewActionOperationAvailable === false) {
338
+ bCreatable = false;
339
+ }
340
+ } else {
341
+ const oInsertRestrictions = oEntitySetAnnotations["@Org.OData.Capabilities.V1.InsertRestrictions"];
342
+ if (oInsertRestrictions && oInsertRestrictions.Insertable === false) {
343
+ bCreatable = false;
344
+ }
345
+ }
346
+ if (bCreatable) {
347
+ return getDefaultCreateHash(oStartupParameters, sContextPath, oRouter);
348
+ } else {
349
+ return "";
350
+ }
351
+ });
352
+ }
353
+
354
+ /**
355
+ * Calculates the hash to create a new object.
356
+ *
357
+ * @param oStartupParameters The startup parameter values (map parameter name -> array of values)
358
+ * @param sContextPath The context path of the entity set to be used for the creation
359
+ * @param oRouter The router instance
360
+ * @returns The hash
361
+ */
362
+ function getDefaultCreateHash(oStartupParameters: any, sContextPath: string, oRouter: Router): string {
363
+ let sDefaultCreateHash =
364
+ oStartupParameters && oStartupParameters.preferredMode ? (oStartupParameters.preferredMode[0] as string) : "create";
365
+ let sHash = "";
366
+
367
+ sDefaultCreateHash =
368
+ sDefaultCreateHash.indexOf(":") !== -1 && sDefaultCreateHash.length > sDefaultCreateHash.indexOf(":") + 1
369
+ ? sDefaultCreateHash.substr(0, sDefaultCreateHash.indexOf(":"))
370
+ : "create";
371
+ sHash = sContextPath.substring(1) + "(...)?i-action=" + sDefaultCreateHash;
372
+ if (oRouter.getRouteInfoByHash(sHash)) {
373
+ return sHash;
374
+ } else {
375
+ throw new Error("No route match for creating a new " + sContextPath.substring(1));
376
+ }
377
+ }
378
+
379
+ const AppStartupHelper = {
380
+ _getKeysFromStartupParams,
381
+ _createFilterFromKeys,
382
+ _requestObjectsFromParameters,
383
+ _getReachablePages,
384
+ _getStartupPagesFromStartupParams,
385
+ _getDeepLinkObject,
386
+ getDeepLinkStartupHash,
387
+ getCreateStartupHash,
388
+ getDefaultCreateHash
389
+ };
390
+
391
+ export default AppStartupHelper;