@sapui5/sap.fe.templates 1.106.0 → 1.108.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.
- package/package.json +3 -2
- package/src/sap/fe/templates/.library +1 -1
- package/src/sap/fe/templates/ListComponent.js +5 -1
- package/src/sap/fe/templates/ListComponent.ts +4 -0
- package/src/sap/fe/templates/ListReport/ExtensionAPI.js +43 -3
- package/src/sap/fe/templates/ListReport/ExtensionAPI.ts +38 -2
- package/src/sap/fe/templates/ListReport/ListReport.view.xml +12 -1
- package/src/sap/fe/templates/ListReport/ListReportController.controller.js +80 -22
- package/src/sap/fe/templates/ListReport/ListReportController.controller.ts +63 -14
- package/src/sap/fe/templates/ListReport/controls/MultipleModeControl.js +30 -21
- package/src/sap/fe/templates/ListReport/controls/MultipleModeControl.ts +21 -10
- package/src/sap/fe/templates/ListReport/overrides/IntentBasedNavigation.js +4 -7
- package/src/sap/fe/templates/ListReport/overrides/IntentBasedNavigation.ts +2 -6
- package/src/sap/fe/templates/ListReport/overrides/Share.js +9 -14
- package/src/sap/fe/templates/ListReport/overrides/Share.ts +8 -15
- package/src/sap/fe/templates/ListReport/overrides/ViewState.js +15 -11
- package/src/sap/fe/templates/ListReport/overrides/ViewState.ts +27 -9
- package/src/sap/fe/templates/ListReport/view/fragments/MultipleMode.fragment.js +3 -3
- package/src/sap/fe/templates/ListReport/view/fragments/MultipleMode.fragment.ts +2 -2
- package/src/sap/fe/templates/ListReport/view/fragments/Table.fragment.xml +0 -1
- package/src/sap/fe/templates/ObjectPage/ExtensionAPI.js +132 -3
- package/src/sap/fe/templates/ObjectPage/ExtensionAPI.ts +88 -1
- package/src/sap/fe/templates/ObjectPage/ObjectPage.view.xml +35 -47
- package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.js +286 -45
- package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.ts +209 -32
- package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.js +49 -7
- package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.ts +60 -5
- package/src/sap/fe/templates/ObjectPage/designtime/StashableHBox.designtime.js +1 -1
- package/src/sap/fe/templates/ObjectPage/designtime/StashableHBox.designtime.ts +1 -2
- package/src/sap/fe/templates/ObjectPage/designtime/StashableVBox.designtime.js +1 -1
- package/src/sap/fe/templates/ObjectPage/designtime/StashableVBox.designtime.ts +1 -2
- package/src/sap/fe/templates/ObjectPage/flexibility/ScrollableHeaderContainer.flexibility.js +33 -0
- package/src/sap/fe/templates/ObjectPage/flexibility/ScrollableHeaderContainer.flexibility.ts +23 -0
- package/src/sap/fe/templates/ObjectPage/manifest.json +8 -0
- package/src/sap/fe/templates/ObjectPage/overrides/MessageHandler.js +2 -2
- package/src/sap/fe/templates/ObjectPage/overrides/MessageHandler.ts +2 -1
- package/src/sap/fe/templates/ObjectPage/overrides/Share.js +10 -3
- package/src/sap/fe/templates/ObjectPage/overrides/Share.ts +8 -1
- package/src/sap/fe/templates/ObjectPage/overrides/ViewState.js +7 -1
- package/src/sap/fe/templates/ObjectPage/overrides/ViewState.ts +5 -0
- package/src/sap/fe/templates/ObjectPage/view/fragments/Actions.fragment.xml +8 -2
- package/src/sap/fe/templates/ObjectPage/view/fragments/HeaderContent.fragment.xml +38 -23
- package/src/sap/fe/templates/ObjectPage/view/fragments/HeadingContent.fragment.xml +30 -0
- package/src/sap/fe/templates/ObjectPage/view/fragments/MacroChart.fragment.xml +1 -0
- package/src/sap/fe/templates/ObjectPage/view/fragments/Table.fragment.xml +1 -0
- package/src/sap/fe/templates/library.js +1 -1
- package/src/sap/fe/templates/messagebundle_lt.properties +1 -1
- package/src/sap/fe/templates/RootContainer/controller/Fcl.controller.js +0 -899
- package/src/sap/fe/templates/RootContainer/controller/Fcl.controller.ts +0 -830
- package/src/sap/fe/templates/RootContainer/controller/NavContainer.controller.js +0 -207
- package/src/sap/fe/templates/RootContainer/controller/NavContainer.controller.ts +0 -177
- package/src/sap/fe/templates/RootContainer/controller/RootContainerBaseController.js +0 -575
- package/src/sap/fe/templates/RootContainer/controller/RootContainerBaseController.ts +0 -492
- package/src/sap/fe/templates/RootContainer/view/Fcl.view.xml +0 -16
- package/src/sap/fe/templates/RootContainer/view/NavContainer.view.xml +0 -9
|
@@ -1,492 +0,0 @@
|
|
|
1
|
-
import Log from "sap/base/Log";
|
|
2
|
-
import BaseController from "sap/fe/core/BaseController";
|
|
3
|
-
import CommonUtils from "sap/fe/core/CommonUtils";
|
|
4
|
-
import Placeholder from "sap/fe/core/controllerextensions/Placeholder";
|
|
5
|
-
import { defineUI5Class, usingExtension } from "sap/fe/core/helpers/ClassSupport";
|
|
6
|
-
import TableSizeHelper from "sap/fe/macros/table/TableSizeHelper";
|
|
7
|
-
import BindingParser from "sap/ui/base/BindingParser";
|
|
8
|
-
import HashChanger from "sap/ui/core/routing/HashChanger";
|
|
9
|
-
import type Router from "sap/ui/core/routing/Router";
|
|
10
|
-
import type Context from "sap/ui/model/Context";
|
|
11
|
-
import JSONModel from "sap/ui/model/json/JSONModel";
|
|
12
|
-
import AnnotationHelper from "sap/ui/model/odata/v4/AnnotationHelper";
|
|
13
|
-
import type ResourceModel from "sap/ui/model/resource/ResourceModel";
|
|
14
|
-
|
|
15
|
-
@defineUI5Class("sap.fe.templates.RootContainer.controller.RootContainerBaseController")
|
|
16
|
-
class RootContainerBaseController extends BaseController {
|
|
17
|
-
@usingExtension(Placeholder)
|
|
18
|
-
oPlaceholder!: Placeholder;
|
|
19
|
-
private _aHelperModels!: any[];
|
|
20
|
-
private oRouter?: Router;
|
|
21
|
-
private _oRouteMatchedPromise: any;
|
|
22
|
-
private oTitleHierarchyCache: any;
|
|
23
|
-
private bIsComputingTitleHierachy: boolean = false;
|
|
24
|
-
|
|
25
|
-
onInit() {
|
|
26
|
-
TableSizeHelper.init();
|
|
27
|
-
|
|
28
|
-
this._aHelperModels = [];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
getPlaceholder() {
|
|
32
|
-
return this.oPlaceholder;
|
|
33
|
-
}
|
|
34
|
-
attachRouteMatchers() {
|
|
35
|
-
this.oPlaceholder.attachRouteMatchers();
|
|
36
|
-
this.getAppComponent().getRoutingService().attachAfterRouteMatched(this._onAfterRouteMatched, this);
|
|
37
|
-
}
|
|
38
|
-
onExit() {
|
|
39
|
-
this.getAppComponent().getRoutingService().detachAfterRouteMatched(this._onAfterRouteMatched, this);
|
|
40
|
-
this.oRouter = undefined;
|
|
41
|
-
|
|
42
|
-
TableSizeHelper.exit();
|
|
43
|
-
|
|
44
|
-
// Destroy all JSON models created dynamically for the views
|
|
45
|
-
this._aHelperModels.forEach(function (oModel: any) {
|
|
46
|
-
oModel.destroy();
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Convenience method for getting the resource bundle.
|
|
51
|
-
*
|
|
52
|
-
* @public
|
|
53
|
-
* @returns The resourceModel of the component
|
|
54
|
-
*/
|
|
55
|
-
getResourceBundle() {
|
|
56
|
-
return (this.getOwnerComponent().getModel("i18n") as ResourceModel).getResourceBundle();
|
|
57
|
-
}
|
|
58
|
-
getRouter() {
|
|
59
|
-
if (!this.oRouter) {
|
|
60
|
-
this.oRouter = this.getAppComponent().getRouter();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return this.oRouter;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
_createHelperModel() {
|
|
67
|
-
// We keep a reference on the models created dynamically, as they don't get destroyed
|
|
68
|
-
// automatically when the view is destroyed.
|
|
69
|
-
// This is done during onExit
|
|
70
|
-
const oModel = new JSONModel();
|
|
71
|
-
this._aHelperModels.push(oModel);
|
|
72
|
-
|
|
73
|
-
return oModel;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Function waiting for the Right most view to be ready.
|
|
78
|
-
*
|
|
79
|
-
* @memberof sap.fe.templates.RootContainer.controller.BaseController
|
|
80
|
-
* @param oEvent Reference an Event parameter coming from routeMatched event
|
|
81
|
-
* @returns A promise indicating when the right most view is ready
|
|
82
|
-
*/
|
|
83
|
-
waitForRightMostViewReady(oEvent: any) {
|
|
84
|
-
return new Promise(function (resolve: (value: any) => void) {
|
|
85
|
-
const aContainers = oEvent.getParameter("views"),
|
|
86
|
-
// There can also be reuse components in the view, remove them before processing.
|
|
87
|
-
aFEContainers: any[] = [];
|
|
88
|
-
aContainers.forEach(function (oContainer: any) {
|
|
89
|
-
let oView = oContainer;
|
|
90
|
-
if (oContainer && oContainer.getComponentInstance) {
|
|
91
|
-
const oComponentInstance = oContainer.getComponentInstance();
|
|
92
|
-
oView = oComponentInstance.getRootControl();
|
|
93
|
-
}
|
|
94
|
-
if (oView && oView.getController() && oView.getController().pageReady) {
|
|
95
|
-
aFEContainers.push(oView);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
const oRightMostFEView = aFEContainers[aFEContainers.length - 1];
|
|
99
|
-
if (oRightMostFEView && oRightMostFEView.getController().pageReady.isPageReady()) {
|
|
100
|
-
resolve(oRightMostFEView);
|
|
101
|
-
} else if (oRightMostFEView) {
|
|
102
|
-
oRightMostFEView.getController().pageReady.attachEventOnce("pageReady", function () {
|
|
103
|
-
resolve(oRightMostFEView);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Callback when the navigation is done.
|
|
111
|
-
* - update the shell title.
|
|
112
|
-
* - update table scroll.
|
|
113
|
-
* - call onPageReady on the rightMostView.
|
|
114
|
-
*
|
|
115
|
-
* @param oEvent
|
|
116
|
-
* @name sap.fe.templates.RootContainer.controller.BaseController#_onAfterRouteMatched
|
|
117
|
-
* @memberof sap.fe.templates.RootContainer.controller.BaseController
|
|
118
|
-
*/
|
|
119
|
-
_onAfterRouteMatched(oEvent: any) {
|
|
120
|
-
if (!this._oRouteMatchedPromise) {
|
|
121
|
-
this._oRouteMatchedPromise = this.waitForRightMostViewReady(oEvent)
|
|
122
|
-
.then((oView: any) => {
|
|
123
|
-
// The autoFocus is initially disabled on the navContainer or the FCL, so that the focus stays on the Shell menu
|
|
124
|
-
// even if the app takes a long time to launch
|
|
125
|
-
// The first time the view is displayed, we need to enable the autofocus so that it's managed properly during navigation
|
|
126
|
-
const oRootControl = this.getView().getContent()[0] as any;
|
|
127
|
-
if (oRootControl && oRootControl.getAutoFocus && !oRootControl.getAutoFocus()) {
|
|
128
|
-
oRootControl.setProperty("autoFocus", true, true); // Do not mark the container as invalid, otherwise it's re-rendered
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const oAppComponent = this.getAppComponent();
|
|
132
|
-
this._scrollTablesToLastNavigatedItems();
|
|
133
|
-
if (oAppComponent.getEnvironmentCapabilities().getCapabilities().UShell) {
|
|
134
|
-
this._computeTitleHierarchy(oView);
|
|
135
|
-
}
|
|
136
|
-
const bForceFocus = oAppComponent.getRouterProxy().isFocusForced();
|
|
137
|
-
oAppComponent.getRouterProxy().setFocusForced(false); // reset
|
|
138
|
-
if (oView.getController() && oView.getController().onPageReady && oView.getParent().onPageReady) {
|
|
139
|
-
oView.getParent().onPageReady({ forceFocus: bForceFocus });
|
|
140
|
-
}
|
|
141
|
-
if (this.onContainerReady) {
|
|
142
|
-
this.onContainerReady();
|
|
143
|
-
}
|
|
144
|
-
})
|
|
145
|
-
.catch(function (oError: any) {
|
|
146
|
-
Log.error("An error occurs while computing the title hierarchy and calling focus method", oError);
|
|
147
|
-
})
|
|
148
|
-
.finally(() => {
|
|
149
|
-
this._oRouteMatchedPromise = null;
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* This function returns the TitleHierarchy cache ( or initializes it if undefined).
|
|
156
|
-
*
|
|
157
|
-
* @name sap.fe.templates.RootContainer.controller.BaseController#_getTitleHierarchyCache
|
|
158
|
-
* @memberof sap.fe.templates.RootContainer.controller.BaseController
|
|
159
|
-
* @returns The TitleHierarchy cache
|
|
160
|
-
*/
|
|
161
|
-
_getTitleHierarchyCache() {
|
|
162
|
-
if (!this.oTitleHierarchyCache) {
|
|
163
|
-
this.oTitleHierarchyCache = {};
|
|
164
|
-
}
|
|
165
|
-
return this.oTitleHierarchyCache;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* This function returns a titleInfo object.
|
|
170
|
-
*
|
|
171
|
-
* @memberof sap.fe.templates.RootContainer.controller.BaseController
|
|
172
|
-
* @param title
|
|
173
|
-
* @param subtitle
|
|
174
|
-
* @param sIntent The intent path to be redirected to
|
|
175
|
-
* @returns The title information
|
|
176
|
-
*/
|
|
177
|
-
_computeTitleInfo(title: any, subtitle: any, sIntent: any) {
|
|
178
|
-
const aParts = sIntent.split("/");
|
|
179
|
-
if (aParts[aParts.length - 1].indexOf("?") === -1) {
|
|
180
|
-
sIntent += "?restoreHistory=true";
|
|
181
|
-
} else {
|
|
182
|
-
sIntent += "&restoreHistory=true";
|
|
183
|
-
}
|
|
184
|
-
return {
|
|
185
|
-
title: title,
|
|
186
|
-
subtitle: subtitle,
|
|
187
|
-
intent: sIntent,
|
|
188
|
-
icon: ""
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
_formatTitle(displayMode: string, titleValue: string, titleDescription: string): string {
|
|
192
|
-
let formattedTitle = "";
|
|
193
|
-
switch (displayMode) {
|
|
194
|
-
case "Value":
|
|
195
|
-
formattedTitle = `${titleValue}`;
|
|
196
|
-
break;
|
|
197
|
-
case "ValueDescription":
|
|
198
|
-
formattedTitle = `${titleValue} (${titleDescription})`;
|
|
199
|
-
break;
|
|
200
|
-
case "DescriptionValue":
|
|
201
|
-
formattedTitle = `${titleDescription} (${titleValue})`;
|
|
202
|
-
break;
|
|
203
|
-
case "Description":
|
|
204
|
-
formattedTitle = `${titleDescription}`;
|
|
205
|
-
break;
|
|
206
|
-
default:
|
|
207
|
-
}
|
|
208
|
-
return formattedTitle;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Fetches the value of the HeaderInfo title for a given path.
|
|
213
|
-
*
|
|
214
|
-
* @param sPath The path to the entity
|
|
215
|
-
* @returns A promise containing the formatted title, or an empty string if no HeaderInfo title annotation is available
|
|
216
|
-
*/
|
|
217
|
-
async _fetchTitleValue(sPath: string) {
|
|
218
|
-
const oAppComponent = this.getAppComponent(),
|
|
219
|
-
oModel = this.getView().getModel(),
|
|
220
|
-
oMetaModel = oAppComponent.getMetaModel(),
|
|
221
|
-
sMetaPath = oMetaModel.getMetaPath(sPath),
|
|
222
|
-
oBindingViewContext = oModel.createBindingContext(sPath),
|
|
223
|
-
sValueExpression = AnnotationHelper.format(
|
|
224
|
-
oMetaModel.getObject(`${sMetaPath}/@com.sap.vocabularies.UI.v1.HeaderInfo/Title/Value`),
|
|
225
|
-
{ context: oMetaModel.createBindingContext("/") as Context }
|
|
226
|
-
);
|
|
227
|
-
if (!sValueExpression) {
|
|
228
|
-
return Promise.resolve("");
|
|
229
|
-
}
|
|
230
|
-
const sTextExpression = AnnotationHelper.format(
|
|
231
|
-
oMetaModel.getObject(
|
|
232
|
-
`${sMetaPath}/@com.sap.vocabularies.UI.v1.HeaderInfo/Title/Value/$Path@com.sap.vocabularies.Common.v1.Text`
|
|
233
|
-
),
|
|
234
|
-
{ context: oMetaModel.createBindingContext("/") as Context }
|
|
235
|
-
),
|
|
236
|
-
oPropertyContext = oMetaModel.getObject(`${sMetaPath}/@com.sap.vocabularies.UI.v1.HeaderInfo/Title/Value/$Path@`),
|
|
237
|
-
aPromises: Promise<void>[] = [],
|
|
238
|
-
oValueExpression = BindingParser.complexParser(sValueExpression),
|
|
239
|
-
oPromiseForDisplayMode = new Promise(function (resolve: (value: any) => void) {
|
|
240
|
-
const displayMode = CommonUtils.computeDisplayMode(oPropertyContext);
|
|
241
|
-
resolve(displayMode);
|
|
242
|
-
});
|
|
243
|
-
aPromises.push(oPromiseForDisplayMode);
|
|
244
|
-
const sValuePath = oValueExpression.parts ? oValueExpression.parts[0].path : oValueExpression.path,
|
|
245
|
-
fnValueFormatter = oValueExpression.formatter,
|
|
246
|
-
oValueBinding = oModel.bindProperty(sValuePath, oBindingViewContext);
|
|
247
|
-
oValueBinding.initialize();
|
|
248
|
-
const oPromiseForTitleValue = new Promise(function (resolve: (value: any) => void) {
|
|
249
|
-
const fnChange = function (oEvent: any) {
|
|
250
|
-
const sTargetValue = fnValueFormatter ? fnValueFormatter(oEvent.getSource().getValue()) : oEvent.getSource().getValue();
|
|
251
|
-
|
|
252
|
-
oValueBinding.detachChange(fnChange);
|
|
253
|
-
resolve(sTargetValue);
|
|
254
|
-
};
|
|
255
|
-
oValueBinding.attachChange(fnChange);
|
|
256
|
-
});
|
|
257
|
-
aPromises.push(oPromiseForTitleValue);
|
|
258
|
-
|
|
259
|
-
if (sTextExpression) {
|
|
260
|
-
const oTextExpression = BindingParser.complexParser(sTextExpression);
|
|
261
|
-
let sTextPath = oTextExpression.parts ? oTextExpression.parts[0].path : oTextExpression.path;
|
|
262
|
-
sTextPath = sValuePath.lastIndexOf("/") > -1 ? sValuePath.slice(0, sValuePath.lastIndexOf("/")) + "/" + sTextPath : sTextPath;
|
|
263
|
-
const fnTextFormatter = oTextExpression.formatter,
|
|
264
|
-
oTextBinding = oModel.bindProperty(sTextPath, oBindingViewContext);
|
|
265
|
-
oTextBinding.initialize();
|
|
266
|
-
const oPromiseForTitleText = new Promise(function (resolve: (description: any) => void) {
|
|
267
|
-
const fnChange = function (oEvent: any) {
|
|
268
|
-
const sTargetText = fnTextFormatter ? fnTextFormatter(oEvent.getSource().getValue()) : oEvent.getSource().getValue();
|
|
269
|
-
|
|
270
|
-
oTextBinding.detachChange(fnChange);
|
|
271
|
-
resolve(sTargetText);
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
oTextBinding.attachChange(fnChange);
|
|
275
|
-
});
|
|
276
|
-
aPromises.push(oPromiseForTitleText);
|
|
277
|
-
}
|
|
278
|
-
try {
|
|
279
|
-
const titleInfo: any[] = await Promise.all(aPromises);
|
|
280
|
-
let formattedTitle = "";
|
|
281
|
-
if (typeof titleInfo !== "string") {
|
|
282
|
-
formattedTitle = this._formatTitle(titleInfo[0], titleInfo[1], titleInfo[2]);
|
|
283
|
-
}
|
|
284
|
-
return formattedTitle;
|
|
285
|
-
} catch (error: any) {
|
|
286
|
-
Log.error("Error while fetching the title from the header info :" + error);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
_getAppSpecificHash() {
|
|
291
|
-
// HashChanged isShellNavigationHashChanger
|
|
292
|
-
return (HashChanger.getInstance() as any).hrefForAppSpecificHash
|
|
293
|
-
? (HashChanger.getInstance() as any).hrefForAppSpecificHash("")
|
|
294
|
-
: "";
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
_getHash() {
|
|
298
|
-
return HashChanger.getInstance().getHash();
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* This function returns titleInformation from a path.
|
|
303
|
-
* It updates the cache to store Title Information if necessary
|
|
304
|
-
*
|
|
305
|
-
* @name sap.fe.templates.RootContainer.controller.BaseController#getTitleInfoFromPath
|
|
306
|
-
* @memberof sap.fe.templates.RootContainer.controller.BaseController
|
|
307
|
-
* @param {*} sPath path of the context to retrieve title information from MetaModel
|
|
308
|
-
* @returns {Promise} oTitleinformation returned as promise
|
|
309
|
-
*/
|
|
310
|
-
|
|
311
|
-
getTitleInfoFromPath(sPath: any) {
|
|
312
|
-
const oTitleHierarchyCache = this._getTitleHierarchyCache();
|
|
313
|
-
|
|
314
|
-
if (oTitleHierarchyCache[sPath]) {
|
|
315
|
-
// The title info is already stored in the cache
|
|
316
|
-
return Promise.resolve(oTitleHierarchyCache[sPath]);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const oMetaModel = this.getAppComponent().getMetaModel();
|
|
320
|
-
const sEntityPath = oMetaModel.getMetaPath(sPath);
|
|
321
|
-
const sTypeName = oMetaModel.getObject(`${sEntityPath}/@com.sap.vocabularies.UI.v1.HeaderInfo/TypeName`);
|
|
322
|
-
const sAppSpecificHash = this._getAppSpecificHash();
|
|
323
|
-
const sIntent = sAppSpecificHash + sPath.slice(1);
|
|
324
|
-
return this._fetchTitleValue(sPath).then((sTitle: any) => {
|
|
325
|
-
const oTitleInfo = this._computeTitleInfo(sTypeName, sTitle, sIntent);
|
|
326
|
-
oTitleHierarchyCache[sPath] = oTitleInfo;
|
|
327
|
-
return oTitleInfo;
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Ensure that the ushell service receives all elements
|
|
332
|
-
* (title, subtitle, intent, icon) as strings.
|
|
333
|
-
*
|
|
334
|
-
* Annotation HeaderInfo allows for binding of title and description
|
|
335
|
-
* (which are used here as title and subtitle) to any element in the entity
|
|
336
|
-
* (being possibly types like boolean, timestamp, double, etc.)
|
|
337
|
-
*
|
|
338
|
-
* Creates a new hierarchy and converts non-string types to string.
|
|
339
|
-
*
|
|
340
|
-
* @param aHierarchy Shell title hierarchy
|
|
341
|
-
* @returns Copy of shell title hierarchy containing all elements as strings
|
|
342
|
-
*/
|
|
343
|
-
_ensureHierarchyElementsAreStrings(aHierarchy: any) {
|
|
344
|
-
const aHierarchyShell = [];
|
|
345
|
-
for (const level in aHierarchy) {
|
|
346
|
-
const oHierarchy = aHierarchy[level];
|
|
347
|
-
const oShellHierarchy: any = {};
|
|
348
|
-
for (const key in oHierarchy) {
|
|
349
|
-
oShellHierarchy[key] = typeof oHierarchy[key] !== "string" ? String(oHierarchy[key]) : oHierarchy[key];
|
|
350
|
-
}
|
|
351
|
-
aHierarchyShell.push(oShellHierarchy);
|
|
352
|
-
}
|
|
353
|
-
return aHierarchyShell;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
_getTargetTypeFromHash(sHash: any) {
|
|
357
|
-
const oAppComponent = this.getAppComponent();
|
|
358
|
-
let sTargetType = "";
|
|
359
|
-
|
|
360
|
-
const aRoutes = oAppComponent.getManifestEntry("/sap.ui5/routing/routes");
|
|
361
|
-
for (let j = 0; j < aRoutes.length; j++) {
|
|
362
|
-
const oRoute = oAppComponent.getRouter().getRoute(aRoutes[j].name);
|
|
363
|
-
if (oRoute.match(sHash)) {
|
|
364
|
-
const sTarget = Array.isArray(aRoutes[j].target) ? aRoutes[j].target[0] : aRoutes[j].target;
|
|
365
|
-
sTargetType = (oAppComponent.getRouter().getTarget(sTarget) as any)._oOptions.name;
|
|
366
|
-
break;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
return sTargetType;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* This function is updating the shell title after each navigation.
|
|
375
|
-
*
|
|
376
|
-
* @memberof sap.fe.templates.RootContainer.controller.BaseController
|
|
377
|
-
* @param oView The current view
|
|
378
|
-
* @returns A Promise that is resolved when the menu is filled properly
|
|
379
|
-
*/
|
|
380
|
-
_computeTitleHierarchy(oView: any) {
|
|
381
|
-
const oAppComponent = this.getAppComponent(),
|
|
382
|
-
oContext = oView.getBindingContext(),
|
|
383
|
-
oCurrentPage = oView.getParent(),
|
|
384
|
-
aTitleInformationPromises = [],
|
|
385
|
-
sAppSpecificHash = this._getAppSpecificHash(),
|
|
386
|
-
sAppTitle = oAppComponent.getMetadata().getManifestEntry("sap.app").title || "",
|
|
387
|
-
sAppSubTitle = oAppComponent.getMetadata().getManifestEntry("sap.app").appSubTitle || "";
|
|
388
|
-
let oPageTitleInformation: any, sNewPath;
|
|
389
|
-
|
|
390
|
-
if (oCurrentPage && oCurrentPage._getPageTitleInformation) {
|
|
391
|
-
if (oContext) {
|
|
392
|
-
// If the first page of the application is a LR, use the title and subtitle from the manifest
|
|
393
|
-
if (this._getTargetTypeFromHash("") === "sap.fe.templates.ListReport") {
|
|
394
|
-
aTitleInformationPromises.push(Promise.resolve(this._computeTitleInfo(sAppTitle, sAppSubTitle, sAppSpecificHash)));
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// Then manage other pages
|
|
398
|
-
sNewPath = oContext.getPath();
|
|
399
|
-
const aPathParts = sNewPath.split("/");
|
|
400
|
-
let sPath = "";
|
|
401
|
-
|
|
402
|
-
aPathParts.shift(); // Remove the first segment (empty string) as it has been managed above
|
|
403
|
-
aPathParts.pop(); // Remove the last segment as it corresponds to the current page and shouldn't appear in the menu
|
|
404
|
-
|
|
405
|
-
aPathParts.forEach((sPathPart: any) => {
|
|
406
|
-
sPath += `/${sPathPart}`;
|
|
407
|
-
const oMetaModel = oAppComponent.getMetaModel(),
|
|
408
|
-
sParameterPath = oMetaModel.getMetaPath(sPath),
|
|
409
|
-
bIsParameterized = oMetaModel.getObject(`${sParameterPath}/@com.sap.vocabularies.Common.v1.ResultContext`);
|
|
410
|
-
if (!bIsParameterized) {
|
|
411
|
-
aTitleInformationPromises.push(this.getTitleInfoFromPath(sPath));
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Current page
|
|
417
|
-
oPageTitleInformation = oCurrentPage._getPageTitleInformation();
|
|
418
|
-
oPageTitleInformation = this._computeTitleInfo(
|
|
419
|
-
oPageTitleInformation.title,
|
|
420
|
-
oPageTitleInformation.subtitle,
|
|
421
|
-
sAppSpecificHash + this._getHash()
|
|
422
|
-
);
|
|
423
|
-
|
|
424
|
-
if (oContext) {
|
|
425
|
-
this._getTitleHierarchyCache()[sNewPath] = oPageTitleInformation;
|
|
426
|
-
} else {
|
|
427
|
-
this._getTitleHierarchyCache()[sAppSpecificHash] = oPageTitleInformation;
|
|
428
|
-
}
|
|
429
|
-
} else {
|
|
430
|
-
aTitleInformationPromises.push(Promise.reject("Title information missing in HeaderInfo"));
|
|
431
|
-
}
|
|
432
|
-
return Promise.all(aTitleInformationPromises)
|
|
433
|
-
.then((aTitleInfoHierarchy: any[]) => {
|
|
434
|
-
// workaround for shell which is expecting all elements being of type string
|
|
435
|
-
const aTitleInfoHierarchyShell = this._ensureHierarchyElementsAreStrings(aTitleInfoHierarchy),
|
|
436
|
-
sTitle = oPageTitleInformation.title;
|
|
437
|
-
oAppComponent.getShellServices().setHierarchy(aTitleInfoHierarchyShell.reverse());
|
|
438
|
-
oAppComponent.getShellServices().setTitle(sTitle);
|
|
439
|
-
})
|
|
440
|
-
.catch(function (sErrorMessage: any) {
|
|
441
|
-
Log.error(sErrorMessage);
|
|
442
|
-
})
|
|
443
|
-
.finally(() => {
|
|
444
|
-
this.bIsComputingTitleHierachy = false;
|
|
445
|
-
})
|
|
446
|
-
.catch(function (sErrorMessage: any) {
|
|
447
|
-
Log.error(sErrorMessage);
|
|
448
|
-
});
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
452
|
-
calculateLayout(iNextFCLLevel: number, sHash: string, sProposedLayout: string | undefined, keepCurrentLayout: boolean | undefined) {
|
|
453
|
-
return null;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
/**
|
|
457
|
-
* Callback after a view has been bound to a context.
|
|
458
|
-
*
|
|
459
|
-
* @param oContext The context that has been bound to a view
|
|
460
|
-
*/
|
|
461
|
-
onContextBoundToView(oContext: any) {
|
|
462
|
-
if (oContext) {
|
|
463
|
-
const sDeepestPath = this.getView().getModel("internal").getProperty("/deepestPath"),
|
|
464
|
-
sViewContextPath = oContext.getPath();
|
|
465
|
-
|
|
466
|
-
if (!sDeepestPath || sDeepestPath.indexOf(sViewContextPath) !== 0) {
|
|
467
|
-
// There was no previous value for the deepest reached path, or the path
|
|
468
|
-
// for the view isn't a subpath of the previous deepest path --> update
|
|
469
|
-
(this.getView().getModel("internal") as JSONModel).setProperty("/deepestPath", sViewContextPath, undefined, true);
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
475
|
-
displayMessagePage(sErrorMessage: any, mParameters: any): Promise<boolean> {
|
|
476
|
-
// To be overridden
|
|
477
|
-
return Promise.resolve(true);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
481
|
-
updateUIStateForView(oView: any, FCLLevel: any) {
|
|
482
|
-
// To be overriden
|
|
483
|
-
}
|
|
484
|
-
_scrollTablesToLastNavigatedItems(): void {
|
|
485
|
-
// To be overriden
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
interface RootContainerBaseController {
|
|
489
|
-
onContainerReady?(): void;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
export default RootContainerBaseController;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<mvc:View
|
|
2
|
-
xmlns="sap.f"
|
|
3
|
-
xmlns:mvc="sap.ui.core.mvc"
|
|
4
|
-
displayBlock="true"
|
|
5
|
-
height="100%"
|
|
6
|
-
controllerName="sap.fe.templates.RootContainer.controller.Fcl"
|
|
7
|
-
>
|
|
8
|
-
<FlexibleColumnLayout
|
|
9
|
-
id="appContent"
|
|
10
|
-
backgroundDesign="Transparent"
|
|
11
|
-
stateChange="onStateChanged"
|
|
12
|
-
afterEndColumnNavigate="onStateChanged"
|
|
13
|
-
restoreFocusOnBackNavigation="true"
|
|
14
|
-
autoFocus="false"
|
|
15
|
-
/>
|
|
16
|
-
</mvc:View>
|