@sapui5/sap.ushell_abap 1.152.1 → 1.154.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 (121) hide show
  1. package/package.json +1 -1
  2. package/src/main/js/sap/ushell_abap/.library +1 -1
  3. package/src/main/js/sap/ushell_abap/adapters/abap/AppStateAdapter.js +53 -63
  4. package/src/main/js/sap/ushell_abap/adapters/abap/ClientSideTargetResolutionAdapter.js +1 -1
  5. package/src/main/js/sap/ushell_abap/adapters/abap/CommonDataModelAdapter.js +1 -1
  6. package/src/main/js/sap/ushell_abap/adapters/abap/ConfigurationDefaultsAdapter.js +1 -1
  7. package/src/main/js/sap/ushell_abap/adapters/abap/ContainerAdapter.js +1 -1
  8. package/src/main/js/sap/ushell_abap/adapters/abap/FlpLaunchPageAdapter.js +62 -4
  9. package/src/main/js/sap/ushell_abap/adapters/abap/LaunchPageAdapter.js +1 -1
  10. package/src/main/js/sap/ushell_abap/adapters/abap/NavTargetResolutionAdapter.js +1 -1
  11. package/src/main/js/sap/ushell_abap/adapters/abap/NavTargetResolutionInternalAdapter.js +1 -1
  12. package/src/main/js/sap/ushell_abap/adapters/abap/PageBuildingAdapter.js +1 -1
  13. package/src/main/js/sap/ushell_abap/adapters/abap/PagePersistenceAdapter.js +8 -8
  14. package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationAdapter.js +1 -1
  15. package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationV2Adapter.js +1 -1
  16. package/src/main/js/sap/ushell_abap/adapters/abap/SearchAdapter.js +1 -1
  17. package/src/main/js/sap/ushell_abap/adapters/abap/SupportTicketAdapter.js +1 -1
  18. package/src/main/js/sap/ushell_abap/adapters/abap/Ui5ComponentLoaderAdapter.js +1 -1
  19. package/src/main/js/sap/ushell_abap/adapters/abap/UserInfoAdapter.js +11 -11
  20. package/src/main/js/sap/ushell_abap/adapters/abap/VisualizationInstantiationAdapter.js +76 -0
  21. package/src/main/js/sap/ushell_abap/adapters/hana/ContainerAdapter.js +1 -1
  22. package/src/main/js/sap/ushell_abap/adapters/local/ClientSideTargetResolutionAdapter.js +123 -0
  23. package/src/main/js/sap/ushell_abap/adapters/local/FlpLaunchPageAdapter.js +115 -0
  24. package/src/main/js/sap/ushell_abap/adapters/local/MenuAdapter.js +92 -0
  25. package/src/main/js/sap/ushell_abap/adapters/local/PageBuildingAdapter.js +242 -0
  26. package/src/main/js/sap/ushell_abap/adapters/local/PagePersistenceAdapter.js +308 -0
  27. package/src/main/js/sap/ushell_abap/api/S4MyHome.js +58 -0
  28. package/src/main/js/sap/ushell_abap/bootstrap/DirectAppStart.js +28 -15
  29. package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad/CreateRenderer.js +4 -2
  30. package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad/RequestPages.js +2 -6
  31. package/src/main/js/sap/ushell_abap/bootstrap/PlatformConfig.js +5 -5
  32. package/src/main/js/sap/ushell_abap/bootstrap/XhrLogonEventHandler.js +6 -7
  33. package/src/main/js/sap/ushell_abap/bootstrap/abapConstants.js +30 -0
  34. package/src/main/js/sap/ushell_abap/components/SideNavigation/modules/Favorites.js +549 -0
  35. package/src/main/js/sap/ushell_abap/components/SideNavigation/modules/GenericNavigationListProvider.js +241 -0
  36. package/src/main/js/sap/ushell_abap/components/cards/Card.controller.js +117 -0
  37. package/src/main/js/sap/ushell_abap/components/cards/Card.view.xml +11 -0
  38. package/src/main/js/sap/ushell_abap/components/cards/Configuration.controller.js +280 -0
  39. package/src/main/js/sap/ushell_abap/components/cards/Configuration.view.xml +27 -0
  40. package/src/main/js/sap/ushell_abap/components/cards/ManifestPropertyHelper.js +298 -0
  41. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/Component.js +90 -0
  42. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/TransactionCode.controller.js +110 -0
  43. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/TransactionCode.view.xml +16 -0
  44. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n.properties +17 -0
  45. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_ar.properties +10 -0
  46. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_bg.properties +10 -0
  47. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_ca.properties +10 -0
  48. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_cnr.properties +10 -0
  49. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_cs.properties +10 -0
  50. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_cy.properties +10 -0
  51. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_da.properties +10 -0
  52. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_de.properties +10 -0
  53. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_el.properties +10 -0
  54. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_en.properties +10 -0
  55. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_en_GB.properties +10 -0
  56. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_en_US_sappsd.properties +10 -0
  57. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_en_US_saprigi.properties +10 -0
  58. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_en_US_saptrc.properties +10 -0
  59. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_es.properties +10 -0
  60. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_es_MX.properties +10 -0
  61. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_et.properties +10 -0
  62. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_fi.properties +10 -0
  63. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_fr.properties +10 -0
  64. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_fr_CA.properties +10 -0
  65. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_hi.properties +10 -0
  66. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_hr.properties +10 -0
  67. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_hu.properties +10 -0
  68. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_id.properties +10 -0
  69. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_it.properties +10 -0
  70. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_iw.properties +10 -0
  71. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_ja.properties +10 -0
  72. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_kk.properties +10 -0
  73. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_ko.properties +10 -0
  74. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_lt.properties +10 -0
  75. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_lv.properties +10 -0
  76. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_mk.properties +10 -0
  77. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_ms.properties +10 -0
  78. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_nl.properties +10 -0
  79. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_no.properties +10 -0
  80. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_pl.properties +10 -0
  81. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_pt.properties +10 -0
  82. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_pt_PT.properties +10 -0
  83. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_ro.properties +10 -0
  84. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_ru.properties +10 -0
  85. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_sh.properties +10 -0
  86. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_sk.properties +10 -0
  87. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_sl.properties +10 -0
  88. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_sr.properties +10 -0
  89. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_sv.properties +10 -0
  90. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_th.properties +10 -0
  91. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_tr.properties +10 -0
  92. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_uk.properties +10 -0
  93. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_vi.properties +10 -0
  94. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_zh_CN.properties +10 -0
  95. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/i18n/i18n_zh_TW.properties +10 -0
  96. package/src/main/js/sap/ushell_abap/components/settings/TransactionCode/manifest.json +96 -0
  97. package/src/main/js/sap/ushell_abap/components/tiles/action/ActionTile.controller.js +189 -0
  98. package/src/main/js/sap/ushell_abap/components/tiles/action/ActionTile.view.xml +13 -0
  99. package/src/main/js/sap/ushell_abap/components/tiles/action/Configuration.controller.js +193 -0
  100. package/src/main/js/sap/ushell_abap/components/tiles/action/Configuration.view.xml +333 -0
  101. package/src/main/js/sap/ushell_abap/components/tiles/applauncher/Component.js +41 -0
  102. package/src/main/js/sap/ushell_abap/components/tiles/applauncher/Configuration.controller.js +114 -0
  103. package/src/main/js/sap/ushell_abap/components/tiles/applauncher/Configuration.view.xml +208 -0
  104. package/src/main/js/sap/ushell_abap/components/tiles/applauncher/StaticTile.controller.js +497 -0
  105. package/src/main/js/sap/ushell_abap/components/tiles/applauncher/StaticTile.view.js +61 -0
  106. package/src/main/js/sap/ushell_abap/components/tiles/applauncherdynamic/Component.js +45 -0
  107. package/src/main/js/sap/ushell_abap/components/tiles/applauncherdynamic/Configuration.controller.js +113 -0
  108. package/src/main/js/sap/ushell_abap/components/tiles/applauncherdynamic/Configuration.view.xml +231 -0
  109. package/src/main/js/sap/ushell_abap/components/tiles/applauncherdynamic/DynamicTile.controller.js +729 -0
  110. package/src/main/js/sap/ushell_abap/components/tiles/applauncherdynamic/DynamicTile.view.js +106 -0
  111. package/src/main/js/sap/ushell_abap/library.js +12 -1
  112. package/src/main/js/sap/ushell_abap/messagebundle.properties +6 -2
  113. package/src/main/js/sap/ushell_abap/pbServices/ui2/Chip.js +7 -3
  114. package/src/main/js/sap/ushell_abap/pbServices/ui2/ODataWrapper.js +3 -5
  115. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/configuration.js +54 -4
  116. package/src/main/js/sap/ushell_abap/services/NavigationDataProvider.js +4 -4
  117. package/src/main/js/sap/ushell_abap/ui/VisualizationInstantiation/ChipInstanceWrapper.js +248 -0
  118. package/src/main/js/sap/ushell_abap/ui/VisualizationInstantiation/VizInstanceAbap.js +134 -0
  119. package/src/main/js/sap/ushell_abap/ui/VisualizationInstantiation/VizInstanceAbapLink.js +145 -0
  120. package/src/main/js/sap/ushell_abap/utils/UserPersonalization.js +127 -0
  121. package/ui5.yaml +21 -3
@@ -0,0 +1,549 @@
1
+ // Copyright (c) 2009-2026 SAP SE, All Rights Reserved
2
+
3
+ sap.ui.define([
4
+ "sap/base/Log",
5
+ "sap/base/util/deepClone",
6
+ "sap/m/GenericTile",
7
+ "sap/m/ObjectStatus",
8
+ "sap/tnt/NavigationListGroup",
9
+ "sap/tnt/NavigationListItem",
10
+ "sap/ui/core/ComponentContainer",
11
+ "sap/ui/core/CustomData",
12
+ "sap/ui/core/library",
13
+ "sap/ui/model/Filter",
14
+ "sap/ui/model/FilterOperator",
15
+ "sap/ui/model/json/JSONModel",
16
+ "sap/ushell/Config",
17
+ "sap/ushell/Container",
18
+ "sap/ushell/components/shell/SideNavigation/modules/NavigationHelper",
19
+ "sap/ui/model/resource/ResourceModel",
20
+ "sap/base/i18n/Localization",
21
+ "sap/ushell_abap/utils/UserPersonalization"
22
+ ], (
23
+ Log,
24
+ deepClone,
25
+ GenericTile,
26
+ ObjectStatus,
27
+ NavigationListGroup,
28
+ NavigationListItem,
29
+ ComponentContainer,
30
+ CustomData,
31
+ coreLibrary,
32
+ Filter,
33
+ FilterOperator,
34
+ JSONModel,
35
+ Config,
36
+ Container,
37
+ NavigationHelper,
38
+ ResourceModel,
39
+ Localization,
40
+ UserPersonalization
41
+ ) => {
42
+ "use strict";
43
+
44
+ // shortcut for sap.ui.core.ValueState
45
+ const ValueState = coreLibrary.ValueState;
46
+
47
+ /**
48
+ * @typedef {object} VisualizationPosition
49
+ * @property {int} sectionIndex the position in the top-level favorites array.
50
+ * @property {int|undefined} vizIndex the position inside a folder's visualizations array, or
51
+ * <code>undefined</code> when the visualization is a flat top-level item).
52
+ *
53
+ * @since 1.154
54
+ * @private
55
+ */
56
+
57
+ /**
58
+ * The menu entry "Favorites" with the sections (folders) and apps from the MyHome page for the SideNavigation.
59
+ *
60
+ * @since 1.134.0
61
+ * @private
62
+ */
63
+ class Favorites {
64
+ /**
65
+ * The side navigation API object passed to the constructor.
66
+ * @type {sap.ushell.modules.NavigationMenu.ListProviderAPI}
67
+ */
68
+ #oSideNavAPI;
69
+
70
+ /**
71
+ * The promise which resolves with the root navigation list item when everything is loaded.
72
+ * @type {Promise<sap.tnt.NavigationListGroup>}
73
+ */
74
+ #pItemReady;
75
+
76
+ /**
77
+ * The root navigation list item group item configured with sections and apps.
78
+ * @type {sap.tnt.NavigationListGroup}
79
+ */
80
+ #oRootItem;
81
+
82
+ /**
83
+ * Helper class for performing navigation actions.
84
+ * @type {NavigationHelper} Helper class for performing navigation actions.
85
+ */
86
+ #NavigationHelper;
87
+
88
+ /**
89
+ * The object that stores the smart business visualization instances.
90
+ * Those are used to navigate to the app by firing the press event on the GenericTile.
91
+ * @type {Map<string, sap.ushell.ui.launchpad.VizInstance>}
92
+ */
93
+ #mVizInstances = new Map();
94
+
95
+ /**
96
+ * The promise that resolves with the resource bundle for the i18n texts.
97
+ * @type {sap.ui.model.resource.ResourceModel}
98
+ */
99
+ #oI18nModel;
100
+
101
+ /**
102
+ * The favorites JSON model.
103
+ * @type {sap.ui.model.json.JSONModel}
104
+ */
105
+ #oFavoritesModel;
106
+
107
+ /**
108
+ * Cleanup method
109
+ * @type {function|undefined}
110
+ */
111
+ #fnDetachModelHandlers;
112
+
113
+ /**
114
+ * Creates a new menu entry "Favorites" with the sections and apps from the MyHome page for the SideNavigation.
115
+ *
116
+ * @param {sap.ushell.modules.NavigationMenu.ListProviderAPI} oSideNavAPI The side navigation API object.
117
+ *
118
+ * @since 1.134.0
119
+ * @private
120
+ */
121
+ constructor (oSideNavAPI) {
122
+ this.#oI18nModel = new ResourceModel({
123
+ bundleUrl: sap.ui.require.toUrl("sap/ushell/components/shell/SideNavigation/resources/resources.properties"),
124
+ bundleLocale: Localization.getLanguage(),
125
+ async: true
126
+ });
127
+ this.#oSideNavAPI = oSideNavAPI;
128
+ this.#oRootItem = new NavigationListGroup({
129
+ text: "{i18n>SideNavigation.Item.Favorites.Title}",
130
+ enabled: "{viewConfiguration>/enableSideNavigation}",
131
+ items: {
132
+ path: "favorites>/",
133
+ key: "{favorites>id}",
134
+ factory: this.#favoritesModelItemFactory.bind(this)
135
+ },
136
+ customData: [new CustomData({
137
+ key: "help-id",
138
+ value: "MenuEntry-Favorites",
139
+ writeToDom: true
140
+ })]
141
+ });
142
+ this.#pItemReady = new Promise((resolve, reject) => {
143
+ this.#prepareModel(resolve, reject);
144
+ });
145
+
146
+ this.#NavigationHelper = new NavigationHelper();
147
+ }
148
+
149
+ /**
150
+ * Asynchronously retrieves the root navigation list item.
151
+ *
152
+ * @async
153
+ * @returns {Promise<sap.tnt.NavigationListGroup>} A promise that resolves to NavigationListGroup once the model is prepared and ready.
154
+ * @since 1.134.0
155
+ * @private
156
+ */
157
+ async getRootItem () {
158
+ return this.#pItemReady;
159
+ }
160
+
161
+ /**
162
+ * Triggered whenever a user selects a recent activity item.
163
+ *
164
+ * Closes the side navigation.
165
+ *
166
+ * @param {sap.ui.base.Event} oEvent The event object.
167
+ * @since 1.134.0
168
+ */
169
+ async onItemPressed (oEvent) {
170
+ const oVisualization = oEvent.getSource().getBindingContext("favorites").getProperty();
171
+ // Check if the item is a visualization
172
+ if (!oVisualization.vizType) {
173
+ // No navigation for sections
174
+ return;
175
+ }
176
+
177
+ const pVizInstance = this.#mVizInstances.get(oVisualization.id);
178
+ if (pVizInstance) {
179
+ // Is smart business visualization
180
+ const oVizInstance = await pVizInstance;
181
+ this.#getGenericTileInstance(oVizInstance.getContent())?.firePress();
182
+ } else if (oVisualization.targetURL && oVisualization.target?.type === "URL") {
183
+ this.#NavigationHelper.navigate({
184
+ target: { url: oVisualization.targetURL },
185
+ type: "URL"
186
+ });
187
+ } else if (oVisualization.targetURL && oVisualization.target?.semanticObject && oVisualization.target?.action) {
188
+ this.#NavigationHelper.navigate({
189
+ target: { shellHash: oVisualization.targetURL },
190
+ type: "IBN"
191
+ });
192
+ }
193
+ this.#oSideNavAPI.closeSideNavigation();
194
+ }
195
+
196
+ /**
197
+ * Prepares the model by fetching the pages service and setting the favorites model on the root item.
198
+ *
199
+ * @async
200
+ * @param {function} resolve The function to call if the operation is successful.
201
+ * @param {function} reject The function to call if the operation fails.
202
+ * @returns {Promise<undefined>} A promise that resolves when the model is prepared.
203
+ * @since 1.134.0
204
+ * @private
205
+ */
206
+ async #prepareModel (resolve, reject) {
207
+ const oPagesService = await Container.getServiceAsync("Pages");
208
+
209
+ const sMyHomePageId = Config.last("/core/spaces/myHome/myHomePageId");
210
+ if (!sMyHomePageId) {
211
+ reject(new Error("MyHome pageId is not defined"));
212
+ return;
213
+ }
214
+
215
+ const sHomePagePath = await oPagesService.loadPage(sMyHomePageId);
216
+ if (!sHomePagePath) {
217
+ reject(new Error("MyHome page not loaded"));
218
+ return;
219
+ }
220
+
221
+ const oPagesModel = oPagesService.getModel();
222
+ this.#oFavoritesModel = new JSONModel([]);
223
+
224
+ const fnBoundUpdateFavoritesModel = this.#updateFavoritesModel.bind(this, this.#oFavoritesModel, sMyHomePageId);
225
+
226
+ oPagesModel.attachEvent("dataChange", fnBoundUpdateFavoritesModel);
227
+ UserPersonalization.attachDisplayTransactionCodeChanged(fnBoundUpdateFavoritesModel);
228
+
229
+ this.#fnDetachModelHandlers = () => {
230
+ oPagesModel.detachEvent("dataChange", fnBoundUpdateFavoritesModel);
231
+ UserPersonalization.detachDisplayTransactionCodeChanged(fnBoundUpdateFavoritesModel);
232
+ };
233
+
234
+ this.#oRootItem.setModel(this.#oFavoritesModel, "favorites");
235
+ await this.#updateFavoritesModel(this.#oFavoritesModel, sMyHomePageId);
236
+ resolve(this.#oRootItem);
237
+ }
238
+
239
+ /**
240
+ * Updates the favorites model with the sections and apps from the MyHome page.
241
+ *
242
+ * @param {sap.ui.model.json.JSONModel} oFavoritesModel The favorites model.
243
+ * @param {string} sMyHomePageId The path to the MyHome page.
244
+ *
245
+ * @since 1.134.0
246
+ * @private
247
+ */
248
+ async #updateFavoritesModel (oFavoritesModel, sMyHomePageId) {
249
+ const oPagesService = await Container.getServiceAsync("Pages");
250
+ const sHomePagePath = await oPagesService.loadPage(sMyHomePageId);
251
+ const oPagesModel = oPagesService.getModel();
252
+
253
+ const aMyHomePageSections = oPagesModel.getProperty(`${sHomePagePath}/sections`) || [];
254
+ const aFavorites = [];
255
+ let oDefaultSection;
256
+
257
+ const oCurrentFavorites = oFavoritesModel.getProperty("/");
258
+
259
+ const oExpandedList = oCurrentFavorites.reduce((oExpanded, oSection) => {
260
+ oExpanded[oSection.id] = oSection.expanded;
261
+ return oExpanded;
262
+ }, {});
263
+
264
+ aMyHomePageSections.forEach((oSection) => {
265
+ // Remember default section to add its visualizations to the beginning
266
+ if (oSection.default) {
267
+ oDefaultSection = oSection;
268
+ return;
269
+ }
270
+ // Add sections in existing order
271
+ const aVisualizations = deepClone(oSection.visualizations, 20);
272
+ if (aVisualizations.length > 0) {
273
+ this.#processSmartBusinessVisualizations(aVisualizations);
274
+ this.#calculateTags(aVisualizations);
275
+ aFavorites.push({
276
+ id: oSection.id,
277
+ title: oSection.title,
278
+ visualizations: aVisualizations,
279
+ expanded: !!oExpandedList[oSection.id]
280
+ });
281
+ }
282
+ });
283
+
284
+ // Add a button at the bottom of the "Favorites" menu entry to add new favorite apps using the App Finder
285
+ const sAddAppsText = (await this.#oI18nModel.getResourceBundle()).getText("SideNavigation.Item.Favorites.AddApps");
286
+ aFavorites.push({
287
+ id: "addAppsToFavoritesFolder",
288
+ title: sAddAppsText,
289
+ vizType: "sap.ushell.StaticAppLauncher",
290
+ target: {
291
+ semanticObject: "Shell",
292
+ action: "appfinder"
293
+ },
294
+ targetURL: "#Shell-appfinder"
295
+ });
296
+
297
+ if (oDefaultSection?.visualizations?.length > 0) {
298
+ // Add default section visualizations to the beginning
299
+ this.#processSmartBusinessVisualizations(oDefaultSection.visualizations);
300
+ this.#calculateTags(oDefaultSection.visualizations);
301
+ aFavorites.splice(0, 0, ...oDefaultSection.visualizations);
302
+ }
303
+ oFavoritesModel.setProperty("/", aFavorites);
304
+ }
305
+
306
+ /**
307
+ * Finds the position of a visualization within the favorites model.
308
+ *
309
+ * Returns the section index and, if the visualization is nested inside a folder,
310
+ * the visualization index within that folder. Returns <code>undefined</code> when
311
+ * the visualization is not found.
312
+ *
313
+ * @param {object} oVisualization The visualization to locate.
314
+ * @param {string} oVisualization.id The unique identifier of the visualization.
315
+ * @returns {VisualizationPosition|undefined} An object the position in the model or <code>undefined</code> if the visualization is not found.
316
+ *
317
+ * @since 1.154.0
318
+ * @private
319
+ */
320
+ #findVisualizationInModel (oVisualization) {
321
+ const oModel = this.#oRootItem.getModel("favorites");
322
+ const aFavorites = oModel.getProperty("/");
323
+ for (let iSectionIndex = 0; iSectionIndex < aFavorites.length; iSectionIndex++) {
324
+ const oElement = aFavorites[iSectionIndex];
325
+
326
+ // Is in default section
327
+ if (oElement.id === oVisualization.id) {
328
+ return {
329
+ sectionIndex: iSectionIndex,
330
+ vizIndex: undefined
331
+ };
332
+ }
333
+
334
+ // Is in section
335
+ if (Array.isArray(oElement.visualizations)) {
336
+ for (let iVizIndex = 0; iVizIndex < oElement.visualizations.length; iVizIndex++) {
337
+ const oVisualizationInSection = oElement.visualizations[iVizIndex];
338
+ if (oVisualizationInSection.id === oVisualization.id) {
339
+ return {
340
+ sectionIndex: iSectionIndex,
341
+ vizIndex: iVizIndex
342
+ };
343
+ }
344
+ }
345
+ }
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Initiates async resolution of the transaction code tag for each ABAP visualization
351
+ * and writes the result back to the favorites model once resolved.
352
+ *
353
+ * Can handle simplified chip and real chips. Non-ABAP visualizations are skipped.
354
+ *
355
+ * @param {object[]} aVisualizations The visualization objects to process.
356
+ *
357
+ * @since 1.154.0
358
+ * @private
359
+ */
360
+ #calculateTags (aVisualizations) {
361
+ aVisualizations.forEach((oVisualization) => {
362
+ let pTag = Promise.resolve("");
363
+ let pVizInstance = this.#mVizInstances.get(oVisualization.id);
364
+ if (!pVizInstance) {
365
+ pVizInstance = Container.getServiceAsync("VisualizationInstantiation").then(async (oVisualizationInstantiationService) => {
366
+ const oVizInstance = oVisualizationInstantiationService.instantiateVisualization(oVisualization);
367
+ oVizInstance.setActive(true);
368
+ await oVizInstance.loaded();
369
+
370
+ return oVizInstance;
371
+ });
372
+
373
+ this.#mVizInstances.set(oVisualization.id, pVizInstance);
374
+ }
375
+
376
+ pTag = pVizInstance.then(async (oVizInstance) => {
377
+ if (oVizInstance.getTransactionCode) {
378
+ return oVizInstance.getTransactionCode();
379
+ }
380
+ return UserPersonalization.formatTransactionCode("");
381
+ });
382
+
383
+ pTag.then((sTag) => {
384
+ const oModel = this.#oRootItem.getModel("favorites");
385
+ const oPosition = this.#findVisualizationInModel(oVisualization);
386
+ if (!oPosition) {
387
+ Log.error(`Could not update tag for Visualization '${oVisualization.id}' in Favorites SideNavigation Module: Missing visualization in model`);
388
+ }
389
+ // Is in default section
390
+ if (typeof oPosition.sectionIndex === "number" && typeof oPosition.vizIndex !== "number") {
391
+ oModel.setProperty(`/${oPosition.sectionIndex}/tag`, sTag);
392
+ }
393
+
394
+ // Is in section
395
+ if (typeof oPosition.sectionIndex === "number" && typeof oPosition.vizIndex === "number") {
396
+ oModel.setProperty(`/${oPosition.sectionIndex}/visualizations/${oPosition.vizIndex}/tag`, sTag);
397
+ }
398
+ });
399
+ });
400
+ }
401
+
402
+ /**
403
+ * Creates visualization instances for smart business visualizations and registers callbacks to update their titles.
404
+ *
405
+ * @param {Array} aVisualizations The array of visualizations to process.
406
+ *
407
+ * @since 1.136.0
408
+ * @private
409
+ */
410
+ #processSmartBusinessVisualizations (aVisualizations) {
411
+ // Process visualizations to extract relevant information
412
+ Container.getServiceAsync("VisualizationInstantiation").then((oVisualizationInstantiationService) => {
413
+ aVisualizations.forEach((oVisualization) => {
414
+ if (oVisualization.vizType?.startsWith("X-SAP-UI2-CHIP:SSB") && !this.#mVizInstances.has(oVisualization.id)) {
415
+ const oDeferred = Promise.withResolvers();
416
+ this.#mVizInstances.set(oVisualization.id, oDeferred.promise);
417
+ const oVizInstance = oVisualizationInstantiationService.instantiateVisualization(oVisualization);
418
+ oVizInstance.setActive(true);
419
+ oVizInstance.loaded().then(() => {
420
+ oDeferred.resolve(oVizInstance);
421
+ const sTitle = this.#getGenericTileInstance(oVizInstance.getContent())?.getHeader();
422
+ if (!oVisualization.title && sTitle) {
423
+ const oModel = this.#oRootItem.getModel("favorites");
424
+ const oPosition = this.#findVisualizationInModel(oVisualization);
425
+ if (!oPosition) {
426
+ Log.error(`Could not update title and url for Visualization '${oVisualization.id}' in Favorites SideNavigation Module: Missing visualization in model`);
427
+ }
428
+ // Is in default section
429
+ if (typeof oPosition.sectionIndex === "number" && typeof oPosition.vizIndex !== "number") {
430
+ oModel.setProperty(`/${oPosition.sectionIndex}/title`, sTitle);
431
+ oModel.setProperty(`/${oPosition.sectionIndex}/targetURL`, "");
432
+ }
433
+
434
+ // Is in section
435
+ if (typeof oPosition.sectionIndex === "number" && typeof oPosition.vizIndex === "number") {
436
+ oModel.setProperty(`/${oPosition.sectionIndex}/visualizations/${oPosition.vizIndex}/title`, sTitle);
437
+ oModel.setProperty(`/${oPosition.sectionIndex}/visualizations/${oPosition.vizIndex}/targetURL`, "");
438
+ }
439
+ }
440
+ });
441
+ }
442
+ });
443
+ });
444
+ }
445
+
446
+ /**
447
+ * Recursively retrieves the GenericTile instance from the given control.
448
+ *
449
+ * @param {sap.ui.core.Control} oVizInstanceRootControl The root control of the visualization instance.
450
+ * @returns {sap.m.GenericTile|null} The GenericTile instance if found, otherwise null.
451
+ * @since 1.136.0
452
+ * @private
453
+ */
454
+ #getGenericTileInstance (oVizInstanceRootControl) {
455
+ if (!oVizInstanceRootControl) {
456
+ return null;
457
+ }
458
+
459
+ if (oVizInstanceRootControl instanceof GenericTile) {
460
+ return oVizInstanceRootControl;
461
+ } else if (oVizInstanceRootControl instanceof ComponentContainer) {
462
+ oVizInstanceRootControl = oVizInstanceRootControl.getComponentInstance().getRootControl();
463
+ }
464
+
465
+ const oControlMetadata = oVizInstanceRootControl.getMetadata();
466
+ const oDefaultAggregationDefinition = oControlMetadata.getDefaultAggregation() || null;
467
+ const sDefaultAggregationName = oDefaultAggregationDefinition ? oDefaultAggregationDefinition?.name : "content";
468
+
469
+ const aAggregationData = sDefaultAggregationName ? oVizInstanceRootControl.getAggregation(sDefaultAggregationName) : null;
470
+ const oAggregationValue = Array.isArray(aAggregationData) ? aAggregationData[0] : aAggregationData;
471
+
472
+ if (!oAggregationValue) {
473
+ return null;
474
+ }
475
+
476
+ return this.#getGenericTileInstance(oAggregationValue);
477
+ }
478
+
479
+ /**
480
+ * Factory function for creating a navigation list item in the "Favorites" menu entry for the favorites model.
481
+ *
482
+ * @param {string} sId - The unique identifier for the navigation list item.
483
+ * @returns {sap.tnt.NavigationListItem} A new instance of NavigationListItem configured for the favorites model.
484
+ * @since 1.134.0
485
+ * @private
486
+ */
487
+ #favoritesModelItemFactory (sId) {
488
+ return new NavigationListItem(sId, {
489
+ key: "{favorites>id}",
490
+ text: "{= !%{favorites>vizType} && %{favorites>title} === '' ? %{i18n>SideNavigation.Item.Favorites.UntitledFolder} : %{favorites>title} }",
491
+ enabled: "{viewConfiguration>/enableSideNavigation}",
492
+ expanded: "{favorites>expanded}",
493
+ icon: "{= !%{favorites>vizType} ? 'sap-icon://folder' : '' }",
494
+ href: "{favorites>targetURL}",
495
+ selectable: false,
496
+ // Show transaction code on flat app items from the default section.
497
+ // Folders have no transaction code, so the tag stays hidden for them.
498
+ tag: new ObjectStatus({
499
+ text: "{favorites>tag}",
500
+ visible: "{= !!%{favorites>tag} }",
501
+ state: ValueState.Indication10,
502
+ inverted: true
503
+ }),
504
+ // There should be at least one visualization with a title to show the folder
505
+ visible: {
506
+ path: "favorites>visualizations",
507
+ formatter: (aVisualizations) => aVisualizations?.some((oItem) => !!oItem.title)
508
+ },
509
+ items: {
510
+ path: "favorites>visualizations",
511
+ template: new NavigationListItem({
512
+ key: "{favorites>id}",
513
+ text: "{favorites>title}",
514
+ enabled: "{viewConfiguration>/enableSideNavigation}",
515
+ href: "{favorites>targetURL}",
516
+ selectable: false,
517
+ tag: new ObjectStatus({
518
+ text: "{favorites>tag}",
519
+ visible: "{= !!%{favorites>tag} }",
520
+ state: ValueState.Indication10,
521
+ inverted: true
522
+ }),
523
+ press: this.onItemPressed.bind(this)
524
+ }),
525
+ filters: new Filter("title", FilterOperator.NE, "")
526
+ },
527
+ press: this.onItemPressed.bind(this)
528
+ });
529
+ }
530
+
531
+ /**
532
+ * Cleans up the instance.
533
+ *
534
+ * @since 1.144.0
535
+ * @private
536
+ */
537
+ async destroy () {
538
+ await this.pItemReady;
539
+
540
+ this.#oRootItem.destroy();
541
+ this.#oI18nModel.destroy();
542
+ this.#oFavoritesModel?.destroy();
543
+
544
+ this.#fnDetachModelHandlers?.();
545
+ }
546
+ }
547
+
548
+ return Favorites;
549
+ }, false);