@sapui5/sap.fe.templates 1.100.0 → 1.101.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 (132) hide show
  1. package/package.json +4 -5
  2. package/src/sap/fe/templates/.library +1 -2
  3. package/src/sap/fe/templates/AnalyticalListPage/Component.js +24 -12
  4. package/src/sap/fe/templates/AnalyticalListPage/Component.ts +6 -0
  5. package/src/sap/fe/templates/AnalyticalListPage/chart/FEChartDelegate.js +30 -32
  6. package/src/sap/fe/templates/AnalyticalListPage/chart/FEChartDelegate.ts +25 -0
  7. package/src/sap/fe/templates/Feedback.js +80 -0
  8. package/src/sap/fe/templates/Feedback.ts +67 -0
  9. package/src/sap/fe/templates/ListComponent.js +156 -118
  10. package/src/sap/fe/templates/ListComponent.ts +105 -0
  11. package/src/sap/fe/templates/ListReport/Component.js +82 -53
  12. package/src/sap/fe/templates/ListReport/Component.ts +39 -0
  13. package/src/sap/fe/templates/ListReport/ExtensionAPI.js +123 -112
  14. package/src/sap/fe/templates/ListReport/ExtensionAPI.ts +100 -0
  15. package/src/sap/fe/templates/ListReport/ListReport.view.xml +2 -1
  16. package/src/sap/fe/templates/ListReport/ListReportController.controller.js +1111 -1081
  17. package/src/sap/fe/templates/ListReport/ListReportController.controller.ts +1009 -0
  18. package/src/sap/fe/templates/ListReport/overrides/IntentBasedNavigation.js +54 -53
  19. package/src/sap/fe/templates/ListReport/overrides/IntentBasedNavigation.ts +55 -0
  20. package/src/sap/fe/templates/ListReport/overrides/Share.js +134 -137
  21. package/src/sap/fe/templates/ListReport/overrides/Share.ts +134 -0
  22. package/src/sap/fe/templates/ListReport/overrides/ViewState.js +443 -428
  23. package/src/sap/fe/templates/ListReport/overrides/ViewState.ts +413 -0
  24. package/src/sap/fe/templates/ListReport/view/fragments/CollectionVisualization.fragment.xml +25 -25
  25. package/src/sap/fe/templates/ListReport/view/fragments/MultipleMode.fragment.js +72 -0
  26. package/src/sap/fe/templates/ListReport/view/fragments/MultipleMode.fragment.ts +62 -0
  27. package/src/sap/fe/templates/ListReport/view/fragments/{MultipleMode.fragment.xml → MultipleModeOld.fragment.xml} +24 -23
  28. package/src/sap/fe/templates/ObjectPage/AnnotationHelper.js +478 -514
  29. package/src/sap/fe/templates/ObjectPage/AnnotationHelper.ts +511 -0
  30. package/src/sap/fe/templates/ObjectPage/Component.js +169 -138
  31. package/src/sap/fe/templates/ObjectPage/Component.ts +131 -0
  32. package/src/sap/fe/templates/ObjectPage/ExtensionAPI.js +140 -142
  33. package/src/sap/fe/templates/ObjectPage/ExtensionAPI.ts +116 -0
  34. package/src/sap/fe/templates/ObjectPage/ObjectPage.view.xml +3 -9
  35. package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.js +1530 -1447
  36. package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.ts +1442 -0
  37. package/src/sap/fe/templates/ObjectPage/controls/StashableHBox.js +136 -101
  38. package/src/sap/fe/templates/ObjectPage/controls/StashableHBox.ts +84 -0
  39. package/src/sap/fe/templates/ObjectPage/controls/StashableVBox.js +24 -21
  40. package/src/sap/fe/templates/ObjectPage/controls/StashableVBox.ts +10 -0
  41. package/src/sap/fe/templates/ObjectPage/controls/SubSectionBlock.js +98 -53
  42. package/src/sap/fe/templates/ObjectPage/controls/SubSectionBlock.ts +50 -0
  43. package/src/sap/fe/templates/ObjectPage/designtime/FlexBox.designtime.js +20 -19
  44. package/src/sap/fe/templates/ObjectPage/designtime/FlexBox.designtime.ts +15 -0
  45. package/src/sap/fe/templates/ObjectPage/designtime/StashableHBox.designtime.js +50 -47
  46. package/src/sap/fe/templates/ObjectPage/designtime/StashableHBox.designtime.ts +47 -0
  47. package/src/sap/fe/templates/ObjectPage/designtime/StashableVBox.designtime.js +34 -34
  48. package/src/sap/fe/templates/ObjectPage/designtime/StashableVBox.designtime.ts +34 -0
  49. package/src/sap/fe/templates/ObjectPage/flexibility/StashableHBox.flexibility.js +15 -15
  50. package/src/sap/fe/templates/ObjectPage/flexibility/StashableHBox.flexibility.ts +13 -0
  51. package/src/sap/fe/templates/ObjectPage/flexibility/StashableVBox.flexibility.js +11 -11
  52. package/src/sap/fe/templates/ObjectPage/flexibility/StashableVBox.flexibility.ts +7 -0
  53. package/src/sap/fe/templates/ObjectPage/overrides/IntentBasedNavigation.js +55 -52
  54. package/src/sap/fe/templates/ObjectPage/overrides/IntentBasedNavigation.ts +57 -0
  55. package/src/sap/fe/templates/ObjectPage/overrides/InternalRouting.js +15 -17
  56. package/src/sap/fe/templates/ObjectPage/overrides/InternalRouting.ts +13 -0
  57. package/src/sap/fe/templates/ObjectPage/overrides/MessageHandler.js +13 -17
  58. package/src/sap/fe/templates/ObjectPage/overrides/MessageHandler.ts +14 -0
  59. package/src/sap/fe/templates/ObjectPage/overrides/Paginator.js +23 -21
  60. package/src/sap/fe/templates/ObjectPage/overrides/Paginator.ts +21 -0
  61. package/src/sap/fe/templates/ObjectPage/overrides/Share.js +310 -317
  62. package/src/sap/fe/templates/ObjectPage/overrides/Share.ts +316 -0
  63. package/src/sap/fe/templates/ObjectPage/overrides/ViewState.js +66 -57
  64. package/src/sap/fe/templates/ObjectPage/overrides/ViewState.ts +65 -0
  65. package/src/sap/fe/templates/ObjectPage/templating/ObjectPageTemplating.js +1 -1
  66. package/src/sap/fe/templates/ObjectPage/templating/ObjectPageTemplating.ts +1 -1
  67. package/src/sap/fe/templates/ObjectPage/view/fragments/Actions.fragment.xml +18 -24
  68. package/src/sap/fe/templates/ObjectPage/view/fragments/CollaborationDraft.fragment.xml +11 -9
  69. package/src/sap/fe/templates/ObjectPage/view/fragments/FooterContent.fragment.xml +4 -4
  70. package/src/sap/fe/templates/ObjectPage/view/fragments/SwitchDraftAndActiveObjectPopOver.fragment.xml +27 -0
  71. package/src/sap/fe/templates/RootContainer/controller/Fcl.controller.js +851 -817
  72. package/src/sap/fe/templates/RootContainer/controller/Fcl.controller.ts +795 -0
  73. package/src/sap/fe/templates/RootContainer/controller/NavContainer.controller.js +205 -189
  74. package/src/sap/fe/templates/RootContainer/controller/NavContainer.controller.ts +178 -0
  75. package/src/sap/fe/templates/RootContainer/controller/RootContainerBaseController.js +484 -459
  76. package/src/sap/fe/templates/RootContainer/controller/RootContainerBaseController.ts +438 -0
  77. package/src/sap/fe/templates/RootContainer/overrides/EditFlow.js +16 -14
  78. package/src/sap/fe/templates/RootContainer/overrides/EditFlow.ts +20 -0
  79. package/src/sap/fe/templates/TableScroller.js +45 -53
  80. package/src/sap/fe/templates/TableScroller.ts +48 -0
  81. package/src/sap/fe/templates/controls/Chart.fragment.xml +18 -17
  82. package/src/sap/fe/templates/controls/MacroChart.fragment.xml +22 -0
  83. package/src/sap/fe/templates/library.js +49 -63
  84. package/src/sap/fe/templates/library.ts +57 -0
  85. package/src/sap/fe/templates/messagebundle.properties +19 -7
  86. package/src/sap/fe/templates/messagebundle_ar.properties +6 -2
  87. package/src/sap/fe/templates/messagebundle_bg.properties +6 -2
  88. package/src/sap/fe/templates/messagebundle_ca.properties +6 -2
  89. package/src/sap/fe/templates/messagebundle_cs.properties +6 -2
  90. package/src/sap/fe/templates/messagebundle_cy.properties +6 -2
  91. package/src/sap/fe/templates/messagebundle_da.properties +6 -2
  92. package/src/sap/fe/templates/messagebundle_de.properties +6 -2
  93. package/src/sap/fe/templates/messagebundle_el.properties +6 -2
  94. package/src/sap/fe/templates/messagebundle_en.properties +6 -2
  95. package/src/sap/fe/templates/messagebundle_en_GB.properties +6 -2
  96. package/src/sap/fe/templates/messagebundle_en_US_saprigi.properties +6 -2
  97. package/src/sap/fe/templates/messagebundle_en_US_saptrc.properties +6 -2
  98. package/src/sap/fe/templates/messagebundle_es.properties +6 -2
  99. package/src/sap/fe/templates/messagebundle_es_MX.properties +6 -2
  100. package/src/sap/fe/templates/messagebundle_et.properties +6 -2
  101. package/src/sap/fe/templates/messagebundle_fi.properties +6 -2
  102. package/src/sap/fe/templates/messagebundle_fr.properties +6 -2
  103. package/src/sap/fe/templates/messagebundle_fr_CA.properties +6 -2
  104. package/src/sap/fe/templates/messagebundle_hi.properties +6 -2
  105. package/src/sap/fe/templates/messagebundle_hr.properties +6 -2
  106. package/src/sap/fe/templates/messagebundle_hu.properties +6 -2
  107. package/src/sap/fe/templates/messagebundle_id.properties +6 -2
  108. package/src/sap/fe/templates/messagebundle_it.properties +6 -2
  109. package/src/sap/fe/templates/messagebundle_iw.properties +6 -2
  110. package/src/sap/fe/templates/messagebundle_ja.properties +6 -2
  111. package/src/sap/fe/templates/messagebundle_kk.properties +6 -2
  112. package/src/sap/fe/templates/messagebundle_ko.properties +6 -2
  113. package/src/sap/fe/templates/messagebundle_lt.properties +6 -2
  114. package/src/sap/fe/templates/messagebundle_lv.properties +6 -2
  115. package/src/sap/fe/templates/messagebundle_ms.properties +6 -2
  116. package/src/sap/fe/templates/messagebundle_nl.properties +6 -2
  117. package/src/sap/fe/templates/messagebundle_no.properties +6 -2
  118. package/src/sap/fe/templates/messagebundle_pl.properties +6 -2
  119. package/src/sap/fe/templates/messagebundle_pt.properties +6 -2
  120. package/src/sap/fe/templates/messagebundle_pt_PT.properties +6 -2
  121. package/src/sap/fe/templates/messagebundle_ro.properties +6 -2
  122. package/src/sap/fe/templates/messagebundle_ru.properties +6 -2
  123. package/src/sap/fe/templates/messagebundle_sh.properties +6 -2
  124. package/src/sap/fe/templates/messagebundle_sk.properties +6 -2
  125. package/src/sap/fe/templates/messagebundle_sl.properties +6 -2
  126. package/src/sap/fe/templates/messagebundle_sv.properties +6 -2
  127. package/src/sap/fe/templates/messagebundle_th.properties +6 -2
  128. package/src/sap/fe/templates/messagebundle_tr.properties +6 -2
  129. package/src/sap/fe/templates/messagebundle_uk.properties +6 -2
  130. package/src/sap/fe/templates/messagebundle_vi.properties +6 -2
  131. package/src/sap/fe/templates/messagebundle_zh_CN.properties +6 -2
  132. package/src/sap/fe/templates/messagebundle_zh_TW.properties +6 -2
@@ -0,0 +1,1442 @@
1
+ import ResourceBundle from "sap/base/i18n/ResourceBundle";
2
+ import Log from "sap/base/Log";
3
+ import merge from "sap/base/util/merge";
4
+ import { connect } from "sap/fe/core/actions/collaboration/ActivitySync";
5
+ import { openManageDialog, showUserDetails } from "sap/fe/core/actions/collaboration/Manage";
6
+ import BusyLocker from "sap/fe/core/BusyLocker";
7
+ import CommonUtils from "sap/fe/core/CommonUtils";
8
+ import EditFlow from "sap/fe/core/controllerextensions/EditFlow";
9
+ import IntentBasedNavigation from "sap/fe/core/controllerextensions/IntentBasedNavigation";
10
+ import InternalEditFlow from "sap/fe/core/controllerextensions/InternalEditFlow";
11
+ import InternalIntentBasedNavigation from "sap/fe/core/controllerextensions/InternalIntentBasedNavigation";
12
+ import InternalRouting from "sap/fe/core/controllerextensions/InternalRouting";
13
+ import MassEdit from "sap/fe/core/controllerextensions/MassEdit";
14
+ import MessageHandler from "sap/fe/core/controllerextensions/MessageHandler";
15
+ import PageReady from "sap/fe/core/controllerextensions/PageReady";
16
+ import Paginator from "sap/fe/core/controllerextensions/Paginator";
17
+ import Placeholder from "sap/fe/core/controllerextensions/Placeholder";
18
+ import Share from "sap/fe/core/controllerextensions/Share";
19
+ import ViewState from "sap/fe/core/controllerextensions/ViewState";
20
+ import { defineUI5Class, extensible, finalExtension, publicExtension, usingExtension } from "sap/fe/core/helpers/ClassSupport";
21
+ import ModelHelper, { InternalModelContext } from "sap/fe/core/helpers/ModelHelper";
22
+ import PageController from "sap/fe/core/PageController";
23
+ import ChartRuntime from "sap/fe/macros/chart/ChartRuntime";
24
+ import CommonHelper from "sap/fe/macros/CommonHelper";
25
+ import DelegateUtil from "sap/fe/macros/DelegateUtil";
26
+ import TableUtils from "sap/fe/macros/table/Utils";
27
+ import SelectionVariant from "sap/fe/navigation/SelectionVariant";
28
+ import { default as ExtensionAPI, default as ObjectPageExtensionAPI } from "sap/fe/templates/ObjectPage/ExtensionAPI";
29
+ import RootContainerBaseController from "sap/fe/templates/RootContainer/controller/RootContainerBaseController";
30
+ import EditFlowOverrides from "sap/fe/templates/RootContainer/overrides/EditFlow";
31
+ import TableScroller from "sap/fe/templates/TableScroller";
32
+ import InstanceManager from "sap/m/InstanceManager";
33
+ import Link from "sap/m/Link";
34
+ import MessageBox from "sap/m/MessageBox";
35
+ import Popover from "sap/m/Popover";
36
+ import SelectList from "sap/m/SelectList";
37
+ import Event from "sap/ui/base/Event";
38
+ import Control from "sap/ui/core/Control";
39
+ import Fragment from "sap/ui/core/Fragment";
40
+ import Item from "sap/ui/core/Item";
41
+ import OverrideExecution from "sap/ui/core/mvc/OverrideExecution";
42
+ import XMLPreprocessor from "sap/ui/core/util/XMLPreprocessor";
43
+ import XMLTemplateProcessor from "sap/ui/core/XMLTemplateProcessor";
44
+ import JSONModel from "sap/ui/model/json/JSONModel";
45
+ import Context from "sap/ui/model/odata/v4/Context";
46
+ import ODataListBinding from "sap/ui/model/odata/v4/ODataListBinding";
47
+ import ODataMetaModel from "sap/ui/model/odata/v4/ODataMetaModel";
48
+ import ODataModel from "sap/ui/model/odata/v4/ODataModel";
49
+ import ResourceModel from "sap/ui/model/resource/ResourceModel";
50
+ import ObjectPageDynamicHeaderTitle from "sap/uxap/ObjectPageDynamicHeaderTitle";
51
+ import ObjectPageLayout from "sap/uxap/ObjectPageLayout";
52
+ import ObjectPageSection from "sap/uxap/ObjectPageSection";
53
+ import ObjectPageSubSection from "sap/uxap/ObjectPageSubSection";
54
+ import IntentBasedNavigationOverride from "./overrides/IntentBasedNavigation";
55
+ import InternalRoutingOverride from "./overrides/InternalRouting";
56
+ import MessageHandlerOverride from "./overrides/MessageHandler";
57
+ import PaginatorOverride from "./overrides/Paginator";
58
+ import ShareOverrides from "./overrides/Share";
59
+ import ViewStateOverrides from "./overrides/ViewState";
60
+
61
+ @defineUI5Class("sap.fe.templates.ObjectPage.ObjectPageController")
62
+ class ObjectPageController extends PageController {
63
+ @usingExtension(Placeholder)
64
+ placeholder!: Placeholder;
65
+ @usingExtension(EditFlow)
66
+ editFlow!: EditFlow;
67
+ @usingExtension(Share.override(ShareOverrides))
68
+ share!: Share;
69
+ @usingExtension(InternalEditFlow.override(EditFlowOverrides))
70
+ _editFlow!: InternalEditFlow;
71
+ @usingExtension(InternalRouting.override(InternalRoutingOverride))
72
+ _routing!: InternalRouting;
73
+ @usingExtension(Paginator.override(PaginatorOverride))
74
+ paginator!: Paginator;
75
+ @usingExtension(MessageHandler.override(MessageHandlerOverride))
76
+ messageHandler!: MessageHandler;
77
+ @usingExtension(IntentBasedNavigation.override(IntentBasedNavigationOverride))
78
+ intentBasedNavigation!: IntentBasedNavigation;
79
+ @usingExtension(
80
+ InternalIntentBasedNavigation.override({
81
+ getNavigationMode: function (this: InternalIntentBasedNavigation) {
82
+ const bIsStickyEditMode =
83
+ (this.getView().getController() as ObjectPageController).getStickyEditMode &&
84
+ (this.getView().getController() as ObjectPageController).getStickyEditMode();
85
+ return bIsStickyEditMode ? "explace" : undefined;
86
+ }
87
+ })
88
+ )
89
+ _intentBasedNavigation!: InternalIntentBasedNavigation;
90
+ @usingExtension(ViewState.override(ViewStateOverrides))
91
+ viewState!: ViewState;
92
+ @usingExtension(
93
+ PageReady.override({
94
+ isContextExpected: function () {
95
+ return true;
96
+ }
97
+ })
98
+ )
99
+ pageReady!: PageReady;
100
+ @usingExtension(MassEdit)
101
+ massEdit!: MassEdit;
102
+ private mCustomSectionExtensionAPIs?: Record<string, ObjectPageExtensionAPI>;
103
+ private extensionAPI?: ObjectPageExtensionAPI;
104
+ private oResourceBundle?: ResourceBundle;
105
+ private bSectionNavigated?: boolean;
106
+ private switchDraftAndActivePopOver?: Popover;
107
+
108
+ @publicExtension()
109
+ @finalExtension()
110
+ getExtensionAPI(sId?: string): ExtensionAPI {
111
+ if (sId) {
112
+ // to allow local ID usage for custom pages we'll create/return own instances for custom sections
113
+ this.mCustomSectionExtensionAPIs = this.mCustomSectionExtensionAPIs || {};
114
+
115
+ if (!this.mCustomSectionExtensionAPIs[sId]) {
116
+ this.mCustomSectionExtensionAPIs[sId] = new ExtensionAPI(this, sId);
117
+ }
118
+ return this.mCustomSectionExtensionAPIs[sId];
119
+ } else {
120
+ if (!this.extensionAPI) {
121
+ this.extensionAPI = new ExtensionAPI(this);
122
+ }
123
+ return this.extensionAPI;
124
+ }
125
+ }
126
+
127
+ onInit() {
128
+ super.onInit();
129
+ const oObjectPage = this._getObjectPageLayoutControl();
130
+
131
+ // Setting defaults of internal model context
132
+ const oInternalModelContext = this.getView().getBindingContext("internal") as InternalModelContext;
133
+ oInternalModelContext.setProperty("externalNavigationContext", { "page": true });
134
+ oInternalModelContext.setProperty("relatedApps", {
135
+ visibility: false,
136
+ items: null
137
+ });
138
+ oInternalModelContext.setProperty("batchGroups", this._getBatchGroupsForView());
139
+ oInternalModelContext.setProperty("errorNavigationSectionFlag", false);
140
+ if (!(this.getView().getViewData() as any).useNewLazyLoading && (oObjectPage as any).getEnableLazyLoading()) {
141
+ //Attaching the event to make the subsection context binding active when it is visible.
142
+ oObjectPage.attachEvent("subSectionEnteredViewPort", this._handleSubSectionEnteredViewPort.bind(this));
143
+ }
144
+ }
145
+
146
+ onExit() {
147
+ if (this.mCustomSectionExtensionAPIs) {
148
+ for (const sId of Object.keys(this.mCustomSectionExtensionAPIs)) {
149
+ this.mCustomSectionExtensionAPIs[sId] && this.mCustomSectionExtensionAPIs[sId].destroy();
150
+ }
151
+ delete this.mCustomSectionExtensionAPIs;
152
+ }
153
+ this.extensionAPI && this.extensionAPI.destroy();
154
+ delete this.extensionAPI;
155
+
156
+ const oMessageButton = this.getView().byId("fe::FooterBar::MessageButton"),
157
+ oMessagePopover = oMessageButton ? (oMessageButton as any).oMessagePopover : null;
158
+ if (oMessagePopover && oMessagePopover.isOpen()) {
159
+ oMessagePopover.close();
160
+ }
161
+ }
162
+
163
+ _getTableBinding(oTable: any) {
164
+ return oTable && oTable.getRowBinding();
165
+ }
166
+
167
+ onBeforeRendering() {
168
+ PageController.prototype.onBeforeRendering.apply(this);
169
+ }
170
+
171
+ onAfterRendering() {
172
+ ((this.getView().getModel("sap.fe.i18n") as ResourceModel).getResourceBundle() as Promise<ResourceBundle>)
173
+ .then((response: any) => {
174
+ this.oResourceBundle = response;
175
+ })
176
+ .catch(function (oError: any) {
177
+ Log.error("Error while retrieving the resource bundle", oError);
178
+ });
179
+ }
180
+
181
+ _onBeforeBinding(oContext: any, mParameters: any) {
182
+ // TODO: we should check how this comes together with the transaction helper, same to the change in the afterBinding
183
+ const aTables = this._findTables(),
184
+ oObjectPage = this._getObjectPageLayoutControl() as ObjectPageLayout,
185
+ oInternalModelContext = this.getView().getBindingContext("internal") as InternalModelContext,
186
+ oInternalModel = this.getView().getModel("internal") as JSONModel,
187
+ aBatchGroups = oInternalModelContext.getProperty("batchGroups"),
188
+ iViewLevel = (this.getView().getViewData() as any).viewLevel;
189
+ let oFastCreationRow;
190
+ aBatchGroups.push("$auto");
191
+ if (mParameters.bDraftNavigation !== true) {
192
+ this._closeSideContent();
193
+ }
194
+ const opContext = oObjectPage.getBindingContext() as Context;
195
+ if (
196
+ opContext &&
197
+ opContext.hasPendingChanges() &&
198
+ !aBatchGroups.some((opContext.getModel() as ODataModel).hasPendingChanges.bind(opContext.getModel()))
199
+ ) {
200
+ /* In case there are pending changes for the creation row and no others we need to reset the changes
201
+ TODO: this is just a quick solution, this needs to be reworked
202
+ */
203
+
204
+ opContext.getBinding().resetChanges();
205
+ }
206
+
207
+ // For now we have to set the binding context to null for every fast creation row
208
+ // TODO: Get rid of this coding or move it to another layer - to be discussed with MDC and model
209
+ for (let i = 0; i < aTables.length; i++) {
210
+ oFastCreationRow = aTables[i].getCreationRow();
211
+ if (oFastCreationRow) {
212
+ oFastCreationRow.setBindingContext(null);
213
+ }
214
+ }
215
+
216
+ // Scroll to present Section so that bindings are enabled during navigation through paginator buttons, as there is no view rerendering/rebind
217
+ const fnScrollToPresentSection = function () {
218
+ if (!(oObjectPage as any).isFirstRendering() && !mParameters.bPersistOPScroll) {
219
+ oObjectPage.setSelectedSection(null as any);
220
+ }
221
+ };
222
+ oObjectPage.attachEventOnce("modelContextChange", fnScrollToPresentSection);
223
+
224
+ // if the structure of the ObjectPageLayout is changed then scroll to present Section
225
+ // FIXME Is this really working as intended ? Initially this was onBeforeRendering, but never triggered onBeforeRendering because it was registered after it
226
+ const oDelegateOnBefore = {
227
+ onAfterRendering: fnScrollToPresentSection
228
+ };
229
+ oObjectPage.addEventDelegate(oDelegateOnBefore, this);
230
+ this.pageReady.attachEventOnce("pageReady", function () {
231
+ oObjectPage.removeEventDelegate(oDelegateOnBefore);
232
+ });
233
+
234
+ //Set the Binding for Paginators using ListBinding ID
235
+ if (iViewLevel > 1) {
236
+ let oBinding = mParameters && mParameters.listBinding;
237
+ const oPaginatorCurrentContext = oInternalModel.getProperty("/paginatorCurrentContext");
238
+ if (oPaginatorCurrentContext) {
239
+ const oBindingToUse = oPaginatorCurrentContext.getBinding();
240
+ this.paginator.initialize(oBindingToUse, oPaginatorCurrentContext);
241
+ oInternalModel.setProperty("/paginatorCurrentContext", null);
242
+ } else if (oBinding) {
243
+ if (oBinding.isA("sap.ui.model.odata.v4.ODataListBinding")) {
244
+ this.paginator.initialize(oBinding, oContext);
245
+ } else {
246
+ //if the binding type is not ODataListBinding because of a deeplink navigation or a refresh of the page
247
+ // we need to create it
248
+ const sContextPath = oBinding.getPath().replace(/\([^\)]*\)*$/, ""); //removing the last tuple
249
+ oBinding = new (ODataListBinding as any)(oBinding.oModel, "", oBinding.oModel.createBindingContext(sContextPath));
250
+ const _setListBindingAsync = () => {
251
+ if (oBinding.getContexts().length > 0) {
252
+ this.paginator.initialize(oBinding, oContext);
253
+ oBinding.detachEvent("change", _setListBindingAsync);
254
+ }
255
+ };
256
+ oBinding.getContexts(0);
257
+ oBinding.attachEvent("change", _setListBindingAsync);
258
+ }
259
+ }
260
+ }
261
+ if (!(this.getView().getViewData() as any).useNewLazyLoading && oObjectPage.getEnableLazyLoading()) {
262
+ const aSections = oObjectPage.getSections();
263
+ const bUseIconTabBar = oObjectPage.getUseIconTabBar();
264
+ let iSkip = 2;
265
+ const bIsInEditMode = oObjectPage.getModel("ui").getProperty("/isEditable");
266
+ const bEditableHeader = (this.getView().getViewData() as any).editableHeaderContent;
267
+ for (let iSection = 0; iSection < aSections.length; iSection++) {
268
+ const oSection = aSections[iSection];
269
+ const aSubSections = oSection.getSubSections();
270
+ for (let iSubSection = 0; iSubSection < aSubSections.length; iSubSection++, iSkip--) {
271
+ // In IconTabBar mode keep the second section bound if there is an editable header and we are switching to display mode
272
+ if (iSkip < 1 || (bUseIconTabBar && (iSection > 1 || (iSection === 1 && !bEditableHeader && !bIsInEditMode)))) {
273
+ const oSubSection = aSubSections[iSubSection];
274
+ if (oSubSection.data().isVisibilityDynamic !== "true") {
275
+ oSubSection.setBindingContext(null as any);
276
+ }
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ if (this.placeholder.isPlaceholderEnabled() && mParameters.showPlaceholder) {
283
+ const oView = this.getView();
284
+ const oNavContainer = (oView.getParent() as any).oContainer.getParent();
285
+ if (oNavContainer) {
286
+ oNavContainer.showPlaceholder({});
287
+ }
288
+ }
289
+ }
290
+
291
+ _getFirstClickableElement(oObjectPage: any) {
292
+ let oFirstClickableElement;
293
+ const aActions = oObjectPage.getHeaderTitle() && oObjectPage.getHeaderTitle().getActions();
294
+ if (aActions && aActions.length) {
295
+ oFirstClickableElement = aActions.find(function (oAction: any) {
296
+ // Due to the left alignment of the Draft switch and the collaborative draft avatar controls
297
+ // there is a ToolbarSpacer in the actions aggregation which we need to exclude here!
298
+ return !oAction.isA("sap.m.ToolbarSpacer") && oAction.getVisible() && oAction.getEnabled();
299
+ });
300
+ }
301
+ return oFirstClickableElement;
302
+ }
303
+
304
+ _getFirstEmptyMandatoryFieldFromSubSection(aSubSections: any) {
305
+ if (aSubSections) {
306
+ for (let subSection = 0; subSection < aSubSections.length; subSection++) {
307
+ const aBlocks = aSubSections[subSection].getBlocks();
308
+
309
+ if (aBlocks) {
310
+ for (let block = 0; block < aBlocks.length; block++) {
311
+ let aFormContainers;
312
+
313
+ if (aBlocks[block].isA("sap.ui.layout.form.Form")) {
314
+ aFormContainers = aBlocks[block].getFormContainers();
315
+ } else if (
316
+ aBlocks[block].getContent &&
317
+ aBlocks[block].getContent() &&
318
+ aBlocks[block].getContent().isA("sap.ui.layout.form.Form")
319
+ ) {
320
+ aFormContainers = aBlocks[block].getContent().getFormContainers();
321
+ }
322
+
323
+ if (aFormContainers) {
324
+ for (let formContainer = 0; formContainer < aFormContainers.length; formContainer++) {
325
+ const aFormElements = aFormContainers[formContainer].getFormElements();
326
+ if (aFormElements) {
327
+ for (let formElement = 0; formElement < aFormElements.length; formElement++) {
328
+ const aFields = aFormElements[formElement].getFields();
329
+
330
+ // The first field is not necessarily an InputBase (e.g. could be a Text)
331
+ // So we need to check whether it has a getRequired method
332
+ try {
333
+ if (aFields[0].getRequired && aFields[0].getRequired() && !aFields[0].getValue()) {
334
+ return aFields[0];
335
+ }
336
+ } catch (error) {
337
+ Log.debug("Error when searching for mandaotry empty field: " + error);
338
+ }
339
+ }
340
+ }
341
+ }
342
+ }
343
+ }
344
+ }
345
+ }
346
+ }
347
+ return undefined;
348
+ }
349
+
350
+ _updateFocusInEditMode(aSubSections: any) {
351
+ const oObjectPage = this._getObjectPageLayoutControl() as ObjectPageLayout;
352
+
353
+ const oMandatoryField = this._getFirstEmptyMandatoryFieldFromSubSection(aSubSections);
354
+ let oFieldToFocus: any;
355
+ if (oMandatoryField) {
356
+ oFieldToFocus = oMandatoryField.content.getContentEdit()[0];
357
+ } else {
358
+ oFieldToFocus = (oObjectPage as any)._getFirstEditableInput() || this._getFirstClickableElement(oObjectPage);
359
+ }
360
+
361
+ if (oFieldToFocus) {
362
+ setTimeout(function () {
363
+ // We set the focus in a timeeout, otherwise the focus sometimes goes to the TabBar
364
+ oFieldToFocus.focus();
365
+ }, 0);
366
+ }
367
+ }
368
+
369
+ _handleSubSectionEnteredViewPort(oEvent: any) {
370
+ const oSubSection = oEvent.getParameter("subSection");
371
+ oSubSection.setBindingContext(undefined);
372
+ }
373
+
374
+ _onBackNavigationInDraft(oContext: any) {
375
+ if (this.getAppComponent().getRouterProxy().checkIfBackHasSameContext()) {
376
+ // Back nav will keep the same context --> no need to display the dialog
377
+ history.back();
378
+ } else {
379
+ CommonUtils.fnProcessDataLossOrDraftDiscardConfirmation(
380
+ function () {
381
+ history.back();
382
+ },
383
+ Function.prototype,
384
+ oContext,
385
+ this,
386
+ false
387
+ );
388
+ }
389
+ }
390
+
391
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
392
+ _onAfterBinding(oBindingContext: any, mParameters: any) {
393
+ const oObjectPage = this._getObjectPageLayoutControl() as ObjectPageLayout;
394
+ const aTables = this._findTables();
395
+
396
+ this._sideEffects.clearPropertiesStatus();
397
+
398
+ // TODO: this is only a temp solution as long as the model fix the cache issue and we use this additional
399
+ // binding with ownRequest
400
+ oBindingContext = oObjectPage.getBindingContext();
401
+
402
+ let aIBNActions: any[] = [];
403
+ oObjectPage.getSections().forEach(function (oSection: any) {
404
+ oSection.getSubSections().forEach(function (oSubSection: any) {
405
+ aIBNActions = CommonUtils.getIBNActions(oSubSection, aIBNActions);
406
+ });
407
+ });
408
+
409
+ // Assign internal binding contexts to oFormContainer:
410
+ // 1. It is not possible to assign the internal binding context to the XML fragment
411
+ // (FormContainer.fragment.xml) yet - it is used already for the data-structure.
412
+ // 2. Another problem is, that FormContainers assigned to a 'MoreBlock' does not have an
413
+ // internal model context at all.
414
+
415
+ aTables.forEach(function (oTable: any) {
416
+ const oInternalModelContext = oTable.getBindingContext("internal");
417
+ oInternalModelContext.setProperty("creationRowFieldValidity", {});
418
+ oInternalModelContext.setProperty("creationRowCustomValidity", {});
419
+
420
+ aIBNActions = CommonUtils.getIBNActions(oTable, aIBNActions);
421
+ // temporary workaround for BCP: 2080218004
422
+ // Need to fix with BLI: FIORITECHP1-15274
423
+ // only for edit mode, we clear the table cache
424
+ // Workaround starts here!!
425
+ const oTableRowBinding = oTable.getRowBinding();
426
+ if (oTableRowBinding) {
427
+ if (ModelHelper.isStickySessionSupported(oTableRowBinding.getModel().getMetaModel())) {
428
+ // apply for both edit and display mode in sticky
429
+ oTableRowBinding.removeCachesAndMessages("");
430
+ }
431
+ }
432
+ // Workaround ends here!!
433
+
434
+ // Update 'enabled' property of DataFieldForAction buttons on table toolbar
435
+ // The same is also performed on Table selectionChange event
436
+ const oActionOperationAvailableMap = JSON.parse(
437
+ CommonHelper.parseCustomData(DelegateUtil.getCustomData(oTable, "operationAvailableMap")) as any
438
+ ),
439
+ aSelectedContexts = oTable.getSelectedContexts();
440
+
441
+ CommonUtils.setActionEnablement(oInternalModelContext, oActionOperationAvailableMap, aSelectedContexts);
442
+ });
443
+ CommonUtils.getSemanticTargetsFromPageModel(this, "_pageModel");
444
+ //Retrieve Object Page header actions from Object Page title control
445
+ const oObjectPageTitle = oObjectPage.getHeaderTitle();
446
+ let aIBNHeaderActions: any[] = [];
447
+ aIBNHeaderActions = CommonUtils.getIBNActions(oObjectPageTitle, aIBNHeaderActions);
448
+ aIBNActions = aIBNActions.concat(aIBNHeaderActions);
449
+ CommonUtils.updateDataFieldForIBNButtonsVisibility(aIBNActions, this.getView());
450
+
451
+ let oModel: any, oFinalUIState: any;
452
+
453
+ // TODO: this should be moved into an init event of the MDC tables (not yet existing) and should be part
454
+ // of any controller extension
455
+ /**
456
+ * @param oTable
457
+ * @param oListBinding
458
+ */
459
+ function enableFastCreationRow(oTable: any, oListBinding: any) {
460
+ const oFastCreationRow = oTable.getCreationRow();
461
+ let oFastCreationListBinding, oFastCreationContext;
462
+
463
+ if (oFastCreationRow) {
464
+ oFinalUIState
465
+ .then(function () {
466
+ if (oFastCreationRow.getModel("ui").getProperty("/isEditable")) {
467
+ oFastCreationListBinding = oModel.bindList(oListBinding.getPath(), oListBinding.getContext(), [], [], {
468
+ $$updateGroupId: "doNotSubmit",
469
+ $$groupId: "doNotSubmit"
470
+ });
471
+ // Workaround suggested by OData model v4 colleagues
472
+ oFastCreationListBinding.refreshInternal = function () {
473
+ /* do nothing */
474
+ };
475
+ /*
476
+ oFastCreationListBinding.hasPendingChanges = function() {
477
+ return false;
478
+ };
479
+ */
480
+
481
+ oFastCreationContext = oFastCreationListBinding.create();
482
+ oFastCreationRow.setBindingContext(oFastCreationContext);
483
+
484
+ // this is needed to avoid console error
485
+ oFastCreationContext.created().catch(function () {
486
+ Log.trace("transient fast creation context deleted");
487
+ });
488
+ }
489
+ })
490
+ .catch(function (oError: any) {
491
+ Log.error("Error while computing the final UI state", oError);
492
+ });
493
+ }
494
+ }
495
+
496
+ // this should not be needed at the all
497
+ /**
498
+ * @param oTable
499
+ */
500
+ const handleTableModifications = (oTable: any) => {
501
+ const oBinding = this._getTableBinding(oTable),
502
+ fnHandleTablePatchEvents = function () {
503
+ enableFastCreationRow(oTable, oBinding);
504
+ };
505
+
506
+ if (!oBinding) {
507
+ Log.error("Expected binding missing for table: " + oTable.getId());
508
+ return;
509
+ }
510
+
511
+ if (oBinding.oContext) {
512
+ fnHandleTablePatchEvents();
513
+ } else {
514
+ const fnHandleChange = function () {
515
+ if (oBinding.oContext) {
516
+ fnHandleTablePatchEvents();
517
+ oBinding.detachChange(fnHandleChange);
518
+ }
519
+ };
520
+ oBinding.attachChange(fnHandleChange);
521
+ }
522
+ };
523
+
524
+ if (oBindingContext) {
525
+ oModel = oBindingContext.getModel();
526
+
527
+ // Compute Edit Mode
528
+ oFinalUIState = this._editFlow.computeEditMode(oBindingContext);
529
+
530
+ if (ModelHelper.isCollaborationDraftSupported(oModel.getMetaModel())) {
531
+ oFinalUIState
532
+ .then(() => {
533
+ if (this.getView().getModel("ui").getProperty("/isEditable")) {
534
+ connect(this.getView());
535
+ }
536
+ })
537
+ .catch(function (oError: any) {
538
+ Log.error("Error while waiting for the final UI State", oError);
539
+ });
540
+ }
541
+
542
+ // update related apps once Data is received in case of binding cache is not available
543
+ // TODO: this is only a temp solution since we need to call _updateRelatedApps method only after data for Object Page is received (if there is no binding)
544
+ if (oBindingContext.getBinding().oCache) {
545
+ this._updateRelatedApps();
546
+ } else {
547
+ const fnUpdateRelatedApps = () => {
548
+ this._updateRelatedApps();
549
+ oBindingContext.getBinding().detachDataReceived(fnUpdateRelatedApps);
550
+ };
551
+ oBindingContext.getBinding().attachDataReceived(fnUpdateRelatedApps);
552
+ }
553
+
554
+ //Attach the patch sent and patch completed event to the object page binding so that we can react
555
+ const oBinding = (oBindingContext.getBinding && oBindingContext.getBinding()) || oBindingContext;
556
+ oBinding.attachEvent("patchSent", this.editFlow.handlePatchSent, this);
557
+
558
+ aTables.forEach(function (oTable: any) {
559
+ // access binding only after table is bound
560
+ TableUtils.whenBound(oTable)
561
+ .then(handleTableModifications)
562
+ .catch(function (oError: any) {
563
+ Log.error("Error while waiting for the table to be bound", oError);
564
+ });
565
+ });
566
+
567
+ if (!(this.getView().getViewData() as any).useNewLazyLoading) {
568
+ // should be called only after binding is ready hence calling it in onAfterBinding
569
+ (oObjectPage as any)._triggerVisibleSubSectionsEvents();
570
+ }
571
+ }
572
+ }
573
+
574
+ @publicExtension()
575
+ @extensible(OverrideExecution.After)
576
+ onPageReady(mParameters: any) {
577
+ // Apply app state only after the page is ready with the first section selected
578
+ const oView = this.getView();
579
+ const oInternalModelContext = oView.getBindingContext("internal") as InternalModelContext;
580
+ const oBindingContext = oView.getBindingContext();
581
+ //Show popup while navigating back from object page in case of draft
582
+ if (oBindingContext) {
583
+ const bIsStickyMode = ModelHelper.isStickySessionSupported((oBindingContext.getModel() as ODataModel).getMetaModel());
584
+ if (!bIsStickyMode) {
585
+ const oAppComponent = CommonUtils.getAppComponent(oView);
586
+ oAppComponent.getShellServices().setBackNavigation(() => this._onBackNavigationInDraft(oBindingContext));
587
+ }
588
+ }
589
+ this.getAppComponent().getAppStateHandler().applyAppState();
590
+
591
+ if (mParameters.forceFocus) {
592
+ const oObjectPage = this._getObjectPageLayoutControl() as ObjectPageLayout;
593
+ // set the focus to the first action button, or to the first editable input if in editable mode
594
+ const isInDisplayMode = !oObjectPage.getModel("ui").getProperty("/isEditable");
595
+ const aVisibleSections = oObjectPage.getSections().filter(function (oSection) {
596
+ return oSection.getVisible() === true;
597
+ });
598
+ // Select the first visible section
599
+ oObjectPage.setSelectedSection(aVisibleSections[0].getId());
600
+
601
+ if (isInDisplayMode) {
602
+ const oFirstClickableElement = this._getFirstClickableElement(oObjectPage);
603
+ if (oFirstClickableElement) {
604
+ oFirstClickableElement.focus();
605
+ }
606
+ } else {
607
+ let aVisibleSubSections;
608
+ if ((oView.getViewData() as any).sectionLayout === "Tabs") {
609
+ // In a tabbed layout, only the subsections of the selected section are visible on the screen
610
+ aVisibleSubSections = aVisibleSections[0].getSubSections();
611
+ } else {
612
+ // In a paged layout, all subsections of the visible sections are visible on the screen
613
+ aVisibleSubSections = (
614
+ aVisibleSections.map(function (oSection: any) {
615
+ return oSection.getSubSections();
616
+ }) as any
617
+ ).flat();
618
+ }
619
+ this._updateFocusInEditMode(aVisibleSubSections);
620
+ }
621
+ }
622
+
623
+ oInternalModelContext.setProperty("errorNavigationSectionFlag", false);
624
+ this._checkDataPointTitleForExternalNavigation();
625
+ }
626
+
627
+ /**
628
+ * Get the status of edit mode for sticky session.
629
+ *
630
+ * @returns {boolean} The status of edit mode for sticky session
631
+ *
632
+ *
633
+ */
634
+ getStickyEditMode() {
635
+ const oBindingContext = this.getView().getBindingContext && (this.getView().getBindingContext() as Context);
636
+ let bIsStickyEditMode = false;
637
+ if (oBindingContext) {
638
+ const bIsStickyMode = ModelHelper.isStickySessionSupported(oBindingContext.getModel().getMetaModel() as ODataMetaModel);
639
+ if (bIsStickyMode) {
640
+ bIsStickyEditMode = this.getView().getModel("ui").getProperty("/isEditable");
641
+ }
642
+ }
643
+ return bIsStickyEditMode;
644
+ }
645
+
646
+ _getObjectPageLayoutControl() {
647
+ return this.byId("fe::ObjectPage") as ObjectPageLayout;
648
+ }
649
+
650
+ _getPageTitleInformation() {
651
+ const oObjectPage = this._getObjectPageLayoutControl();
652
+ const oObjectPageSubtitle = oObjectPage.getCustomData().find(function (oCustomData: any) {
653
+ return oCustomData.getKey() === "ObjectPageSubtitle";
654
+ });
655
+ const oTitleInfo = {
656
+ title: oObjectPage.data("ObjectPageTitle") || "",
657
+ subtitle: oObjectPageSubtitle && oObjectPageSubtitle.getValue(),
658
+ intent: "",
659
+ icon: ""
660
+ };
661
+
662
+ return oTitleInfo;
663
+ }
664
+
665
+ _executeHeaderShortcut(sId: any) {
666
+ const sButtonId = this.getView().getId() + "--" + sId,
667
+ oButton = (this._getObjectPageLayoutControl().getHeaderTitle() as ObjectPageDynamicHeaderTitle)
668
+ .getActions()
669
+ .find(function (oElement: any) {
670
+ return oElement.getId() === sButtonId;
671
+ });
672
+ CommonUtils.fireButtonPress(oButton);
673
+ }
674
+
675
+ _executeFooterShortcut(sId: any) {
676
+ const sButtonId = this.getView().getId() + "--" + sId,
677
+ oButton = (this._getObjectPageLayoutControl().getFooter() as any).getContent().find(function (oElement: any) {
678
+ return oElement.getMetadata().getName() === "sap.m.Button" && oElement.getId() === sButtonId;
679
+ });
680
+ CommonUtils.fireButtonPress(oButton);
681
+ }
682
+
683
+ _executeTabShortCut(oExecution: any) {
684
+ const oObjectPage = this._getObjectPageLayoutControl(),
685
+ aSections = oObjectPage.getSections(),
686
+ iSectionIndexMax = aSections.length - 1,
687
+ sCommand = oExecution.oSource.getCommand();
688
+ let newSection,
689
+ iSelectedSectionIndex = oObjectPage.indexOfSection(this.byId(oObjectPage.getSelectedSection()) as ObjectPageSection);
690
+ if (iSelectedSectionIndex !== -1 && iSectionIndexMax > 0) {
691
+ if (sCommand === "NextTab") {
692
+ if (iSelectedSectionIndex <= iSectionIndexMax - 1) {
693
+ newSection = aSections[++iSelectedSectionIndex];
694
+ }
695
+ } else {
696
+ // PreviousTab
697
+ if (iSelectedSectionIndex !== 0) {
698
+ newSection = aSections[--iSelectedSectionIndex];
699
+ }
700
+ }
701
+ if (newSection) {
702
+ oObjectPage.setSelectedSection(newSection);
703
+ newSection.focus();
704
+ }
705
+ }
706
+ }
707
+
708
+ _getFooterVisibility() {
709
+ const oInternalModelContext = this.getView().getBindingContext("internal") as InternalModelContext;
710
+ const sViewId = this.getView().getId();
711
+ oInternalModelContext.setProperty("messageFooterContainsErrors", false);
712
+ sap.ui
713
+ .getCore()
714
+ .getMessageManager()
715
+ .getMessageModel()
716
+ .getData()
717
+ .forEach(function (oMessage: any) {
718
+ if (oMessage.validation && oMessage.type === "Error" && oMessage.target.indexOf(sViewId) > -1) {
719
+ oInternalModelContext.setProperty("messageFooterContainsErrors", true);
720
+ }
721
+ });
722
+ }
723
+
724
+ _showMessagePopover(err?: any, oRet?: any) {
725
+ if (err) {
726
+ Log.error(err);
727
+ }
728
+ if (!(this.getAppComponent().getRootContainer() as any).getCurrentPage().isA("sap.m.MessagePage")) {
729
+ const oMessageButton = this.getView().byId("fe::FooterBar::MessageButton") as any,
730
+ oMessagePopover = oMessageButton.oMessagePopover,
731
+ oItemBinding = oMessagePopover.getBinding("items");
732
+
733
+ if (oItemBinding.getLength() > 0 && !oMessagePopover.isOpen()) {
734
+ oMessageButton.setVisible(true);
735
+ // workaround to ensure that oMessageButton is rendered when openBy is called
736
+ setTimeout(function () {
737
+ oMessagePopover.openBy(oMessageButton);
738
+ }, 0);
739
+ }
740
+ }
741
+ return oRet;
742
+ }
743
+
744
+ _editDocument(oContext: any) {
745
+ const oModel = this.getView().getModel("ui");
746
+ BusyLocker.lock(oModel);
747
+ return this.editFlow.editDocument.apply(this.editFlow, [oContext]).finally(function () {
748
+ BusyLocker.unlock(oModel);
749
+ });
750
+ }
751
+
752
+ _saveDocument(oContext: any) {
753
+ const oModel = this.getView().getModel("ui"),
754
+ aWaitCreateDocuments: any[] = [];
755
+ // indicates if we are creating a new row in the OP
756
+ let bExecuteSideEffectsOnError = false;
757
+ BusyLocker.lock(oModel);
758
+ this._findTables().forEach((oTable: any) => {
759
+ const oBinding = this._getTableBinding(oTable);
760
+ const mParameters: any = {
761
+ creationMode: oTable.data("creationMode"),
762
+ creationRow: oTable.getCreationRow(),
763
+ createAtEnd: oTable.data("createAtEnd") === "true"
764
+ };
765
+ const bCreateDocument =
766
+ mParameters.creationRow &&
767
+ mParameters.creationRow.getBindingContext() &&
768
+ Object.keys(mParameters.creationRow.getBindingContext().getObject()).length > 1;
769
+ if (bCreateDocument) {
770
+ // the bSkipSideEffects is a parameter created when we click the save key. If we press this key
771
+ // we don't execute the handleSideEffects funciton to avoid batch redundancy
772
+ mParameters.bSkipSideEffects = true;
773
+ bExecuteSideEffectsOnError = true;
774
+ aWaitCreateDocuments.push(
775
+ this.editFlow.createDocument(oBinding, mParameters).then(function () {
776
+ return oBinding;
777
+ })
778
+ );
779
+ }
780
+ });
781
+ return Promise.all(aWaitCreateDocuments)
782
+ .then((aBindings: any[]) => {
783
+ const mParameters = {
784
+ bExecuteSideEffectsOnError: bExecuteSideEffectsOnError,
785
+ bindings: aBindings
786
+ };
787
+ return this.editFlow.saveDocument(oContext, mParameters).catch(() => this._showMessagePopover);
788
+ })
789
+ .finally(function () {
790
+ if (BusyLocker.isLocked(oModel)) {
791
+ BusyLocker.unlock(oModel);
792
+ }
793
+ });
794
+ }
795
+
796
+ _manageCollaboration() {
797
+ openManageDialog(this.getView());
798
+ }
799
+
800
+ _showCollaborationUserDetails(event: any) {
801
+ showUserDetails(event, this.getView());
802
+ }
803
+
804
+ _cancelDocument(oContext: any, mParameters: any) {
805
+ mParameters.cancelButton = this.getView().byId(mParameters.cancelButton); //to get the reference of the cancel button from command execution
806
+ return this.editFlow.cancelDocument(oContext, mParameters);
807
+ }
808
+
809
+ _applyDocument(oContext: any) {
810
+ return this.editFlow.applyDocument(oContext).catch(() => this._showMessagePopover());
811
+ }
812
+
813
+ _showSwitchDraftAndActivePopover(event: Event) {
814
+ const view = this.getView(),
815
+ source = event.getSource(),
816
+ fragmentName = "sap.fe.templates.ObjectPage.view.fragments.SwitchDraftAndActiveObjectPopOver";
817
+
818
+ if (this.switchDraftAndActivePopOver) {
819
+ this.switchDraftAndActivePopOver.openBy(source, false);
820
+ } else {
821
+ const localThisModel = new JSONModel({}),
822
+ preprocessorSettings = {
823
+ bindingContexts: {
824
+ "this": localThisModel.createBindingContext("/")
825
+ },
826
+ models: {
827
+ "this": localThisModel
828
+ }
829
+ };
830
+ const popoverFragment = XMLTemplateProcessor.loadTemplate(fragmentName, "fragment");
831
+ Promise.resolve(XMLPreprocessor.process(popoverFragment, { name: fragmentName }, preprocessorSettings))
832
+ .then((fragment) => {
833
+ return Fragment.load({ definition: fragment, controller: this });
834
+ })
835
+ .then((popover: any) => {
836
+ view.addDependent(popover);
837
+ popover.setModel(view.getModel("sap.fe.i18n"), "i18n");
838
+ popover.setPlacement("Bottom"); // TODO
839
+ this.switchDraftAndActivePopOver = popover;
840
+ popover.attachAfterOpen(() => {
841
+ // While the list entry corresponding to the currently displayed document version is emphasized with a blue
842
+ // background, we need to pre-focus the other entry
843
+ const context: any = this.getView().getBindingContext(),
844
+ isActiveEntity = context.getObject().IsActiveEntity;
845
+ const switchDraftAndActiveOptionsList: SelectList = (popover.getContent() as unknown as Control[]).find(
846
+ (element) => element.data("listIdentifier") === "switchDraftAndActivePopoverList"
847
+ ) as SelectList;
848
+ const listItemToFocus: Item = isActiveEntity
849
+ ? (switchDraftAndActiveOptionsList.getItems().find((element) => element.getKey() === "switchToDraft") as Item)
850
+ : (switchDraftAndActiveOptionsList.getItems().find((element) => element.getKey() === "switchToActive") as Item);
851
+ listItemToFocus.focus();
852
+ });
853
+ popover.openBy(source);
854
+ // ensure to remove the reference to the draft popover as it would be destroyed on exit
855
+ view.attachEventOnce("beforeExit", () => {
856
+ delete this.switchDraftAndActivePopOver;
857
+ });
858
+ })
859
+ .catch(function (Error) {
860
+ Log.error("Error while opening the draft switch popup", Error);
861
+ });
862
+ }
863
+ }
864
+
865
+ _switchDraftAndActivePopoverListSelect(event: Event) {
866
+ const context: any = this.getView().getBindingContext(),
867
+ selectedItemKey = event.getParameter("item").getProperty("key"),
868
+ isActiveEntity = context.getObject().IsActiveEntity;
869
+ // It was decided that we should NOT set the entry in the list corresponding to the currently displayed document version to
870
+ // disabled, hence the user can click entries which to not cause an action (clicking "Draft" when you already display the
871
+ // draft version of the document)
872
+ // Hence we check here which entry in the list was clicked and which document version we currently display and only do
873
+ // the switch between draft / active version if it makes sense.
874
+ if ((isActiveEntity && selectedItemKey === "switchToDraft") || (!isActiveEntity && selectedItemKey === "switchToActive")) {
875
+ this.editFlow.toggleDraftActive(context);
876
+ }
877
+ ((event.getSource() as Control).getParent() as Popover).close();
878
+ }
879
+
880
+ _updateRelatedApps() {
881
+ const oObjectPage = this._getObjectPageLayoutControl();
882
+ if (CommonUtils.resolveStringtoBoolean(oObjectPage.data("showRelatedApps"))) {
883
+ CommonUtils.updateRelatedAppsDetails(oObjectPage);
884
+ }
885
+ }
886
+
887
+ _findTableInSubSection(aParentElement: any, aSubsection: any, aTables: any) {
888
+ const aSubSectionTables = [];
889
+ for (let element = 0; element < aParentElement.length; element++) {
890
+ let oElement = aParentElement[element].getContent instanceof Function && aParentElement[element].getContent();
891
+ if (oElement && oElement.isA && oElement.isA("sap.ui.layout.DynamicSideContent")) {
892
+ oElement = oElement.getMainContent instanceof Function && oElement.getMainContent();
893
+ if (oElement && oElement.length > 0) {
894
+ oElement = oElement[0];
895
+ }
896
+ }
897
+ if (oElement && oElement.isA && oElement.isA("sap.fe.macros.TableAPI")) {
898
+ oElement = oElement.getContent instanceof Function && oElement.getContent();
899
+ if (oElement && oElement.length > 0) {
900
+ oElement = oElement[0];
901
+ }
902
+ }
903
+ if (oElement && oElement.isA && oElement.isA("sap.ui.mdc.Table")) {
904
+ aTables.push(oElement);
905
+ aSubSectionTables.push({
906
+ "table": oElement,
907
+ "gridTable": oElement.getType().isA("sap.ui.mdc.table.GridTableType")
908
+ });
909
+ }
910
+ }
911
+ if (
912
+ aSubSectionTables.length === 1 &&
913
+ aParentElement.length === 1 &&
914
+ aSubSectionTables[0].gridTable &&
915
+ !aSubsection.hasStyleClass("sapUxAPObjectPageSubSectionFitContainer")
916
+ ) {
917
+ //In case there is only a single table in a section we fit that to the whole page so that the scrollbar comes only on table and not on page
918
+ aSubsection.addStyleClass("sapUxAPObjectPageSubSectionFitContainer");
919
+ } else {
920
+ if (aSubSectionTables && !aSubsection.hasStyleClass("sapUxAPObjectPageSubSectionFitContainer")) {
921
+ aSubSectionTables.forEach(function (oTable: { table: any; gridTable: any }) {
922
+ if (oTable.gridTable) {
923
+ //Resetting the row count to default value in case we have a combination of forms and tables or multiple tables in a subsection
924
+ oTable.table.getType().setRowCount(null);
925
+ }
926
+ });
927
+ }
928
+ }
929
+ }
930
+
931
+ _getAllSubSections() {
932
+ const oObjectPage = this._getObjectPageLayoutControl();
933
+ let aSubSections: any[] = [];
934
+ oObjectPage.getSections().forEach(function (oSection: any) {
935
+ aSubSections = aSubSections.concat(oSection.getSubSections());
936
+ });
937
+ return aSubSections;
938
+ }
939
+
940
+ _getAllBlocks() {
941
+ let aBlocks: any[] = [];
942
+ this._getAllSubSections().forEach(function (oSubSection: any) {
943
+ aBlocks = aBlocks.concat(oSubSection.getBlocks());
944
+ });
945
+ return aBlocks;
946
+ }
947
+
948
+ //TODO: This is needed for two workarounds - to be removed again
949
+ _findTables() {
950
+ const aSubSections = this._getAllSubSections();
951
+ const aTables: any[] = [];
952
+ for (let subSection = 0; subSection < aSubSections.length; subSection++) {
953
+ this._findTableInSubSection(aSubSections[subSection].getBlocks(), aSubSections[subSection], aTables);
954
+ this._findTableInSubSection(aSubSections[subSection].getMoreBlocks(), aSubSections[subSection], aTables);
955
+ }
956
+ return aTables;
957
+ }
958
+
959
+ _closeSideContent() {
960
+ this._getAllBlocks().forEach(function (oBlock: any) {
961
+ const oContent = oBlock.getContent instanceof Function && oBlock.getContent();
962
+ if (oContent && oContent.isA && oContent.isA("sap.ui.layout.DynamicSideContent")) {
963
+ if (oContent.setShowSideContent instanceof Function) {
964
+ oContent.setShowSideContent(false);
965
+ }
966
+ }
967
+ });
968
+ }
969
+
970
+ /**
971
+ * Chart Context is resolved for 1:n microcharts.
972
+ *
973
+ * @param {sap.ui.model.Context} oChartContext The Context of the MicroChart
974
+ * @param {string} sChartPath The collectionPath of the the chart
975
+ * @returns {Array} Array of Attributes of the chart Context
976
+ */
977
+ _getChartContextData(oChartContext: any, sChartPath: string) {
978
+ const oContextData = oChartContext.getObject();
979
+ let oChartContextData = [oContextData];
980
+ if (oChartContext && sChartPath) {
981
+ if (oContextData[sChartPath]) {
982
+ oChartContextData = oContextData[sChartPath];
983
+ delete oContextData[sChartPath];
984
+ oChartContextData.push(oContextData);
985
+ }
986
+ }
987
+ return oChartContextData;
988
+ }
989
+
990
+ /**
991
+ * Scroll the tables to the row with the sPath
992
+ *
993
+ * @function
994
+ * @name sap.fe.templates.ObjectPage.ObjectPageController.controller#_scrollTablesToRow
995
+ * @param {string} sRowPath 'sPath of the table row'
996
+ *
997
+ */
998
+
999
+ _scrollTablesToRow(sRowPath: string) {
1000
+ if (this._findTables && this._findTables().length > 0) {
1001
+ const aTables = this._findTables();
1002
+ for (let i = 0; i < aTables.length; i++) {
1003
+ TableScroller.scrollTableToRow(aTables[i], sRowPath);
1004
+ }
1005
+ }
1006
+ }
1007
+
1008
+ /**
1009
+ * Method to merge selected contexts and filters.
1010
+ *
1011
+ * @function
1012
+ * @name _mergeMultipleContexts
1013
+ * @param {object} oPageContext Page context
1014
+ * @param {object|Array} aLineContext Selected Contexts
1015
+ * @param {string} sChartPath Collection name of the chart
1016
+ * @returns {object} Selection Variant Object
1017
+ */
1018
+ _mergeMultipleContexts(oPageContext: Context, aLineContext: any[], sChartPath: string) {
1019
+ let aAttributes: any[] = [],
1020
+ aPageAttributes = [],
1021
+ oContext,
1022
+ sMetaPathLine: string,
1023
+ sPathLine;
1024
+
1025
+ const sPagePath = oPageContext.getPath();
1026
+ const oMetaModel = oPageContext && oPageContext.getModel() && (oPageContext.getModel().getMetaModel() as ODataMetaModel);
1027
+ const sMetaPathPage = oMetaModel && oMetaModel.getMetaPath(sPagePath).replace(/^\/*/, "");
1028
+
1029
+ // Get single line context if necessary
1030
+ if (aLineContext && aLineContext.length) {
1031
+ oContext = aLineContext[0];
1032
+ sPathLine = oContext.getPath();
1033
+ sMetaPathLine = oMetaModel && oMetaModel.getMetaPath(sPathLine).replace(/^\/*/, "");
1034
+
1035
+ aLineContext.map((oSingleContext: any) => {
1036
+ if (sChartPath) {
1037
+ const oChartContextData = this._getChartContextData(oSingleContext, sChartPath);
1038
+ if (oChartContextData) {
1039
+ aAttributes = oChartContextData.map(function (oChartContextData: any) {
1040
+ return {
1041
+ contextData: oChartContextData,
1042
+ entitySet: sMetaPathPage + "/" + sChartPath
1043
+ };
1044
+ });
1045
+ }
1046
+ } else {
1047
+ aAttributes.push({
1048
+ contextData: oSingleContext.getObject(),
1049
+ entitySet: sMetaPathLine
1050
+ });
1051
+ }
1052
+ });
1053
+ }
1054
+ aPageAttributes.push({
1055
+ contextData: oPageContext.getObject(),
1056
+ entitySet: sMetaPathPage
1057
+ });
1058
+ // Adding Page Context to selection variant
1059
+ aPageAttributes = CommonUtils.removeSensitiveData(aPageAttributes, oMetaModel);
1060
+ const oPageLevelSV = CommonUtils.addPageContextToSelectionVariant(new SelectionVariant(), aPageAttributes, this.getView());
1061
+ aAttributes = CommonUtils.removeSensitiveData(aAttributes, oMetaModel);
1062
+ return {
1063
+ selectionVariant: oPageLevelSV,
1064
+ attributes: aAttributes
1065
+ };
1066
+ }
1067
+
1068
+ _getBatchGroupsForView() {
1069
+ const oViewData = this.getView().getViewData() as any,
1070
+ oConfigurations = oViewData.controlConfiguration,
1071
+ aConfigurations = oConfigurations && Object.keys(oConfigurations),
1072
+ aBatchGroups = ["$auto.Heroes", "$auto.Decoration", "$auto.Workers"];
1073
+
1074
+ if (aConfigurations && aConfigurations.length > 0) {
1075
+ aConfigurations.forEach(function (sKey: any) {
1076
+ const oConfiguration = oConfigurations[sKey];
1077
+ if (oConfiguration.requestGroupId === "LongRunners") {
1078
+ aBatchGroups.push("$auto.LongRunners");
1079
+ }
1080
+ });
1081
+ }
1082
+ return aBatchGroups;
1083
+ }
1084
+
1085
+ /*
1086
+ * Reset Breadcrumb links
1087
+ *
1088
+ * @function
1089
+ * @param {sap.m.Breadcrumbs} [oSource] parent control
1090
+ * @description Used when context of the objectpage changes.
1091
+ * This event callback is attached to modelContextChange
1092
+ * event of the Breadcrumb control to catch context change.
1093
+ * Then element binding and hrefs are updated for each Link.
1094
+ *
1095
+ * @ui5-restricted
1096
+ * @experimental
1097
+ */
1098
+ _setBreadcrumbLinks(oSource: any) {
1099
+ const oContext = oSource.getBindingContext();
1100
+ const oAppComponent = this.getAppComponent();
1101
+ if (oContext) {
1102
+ const sNewPath = oContext.getPath(),
1103
+ aPathParts = sNewPath.split("/"),
1104
+ oMetaModel = oAppComponent.getMetaModel();
1105
+ let sPath = "",
1106
+ iSkipParameterized = 0;
1107
+
1108
+ aPathParts.shift();
1109
+ aPathParts.splice(-1, 1);
1110
+ aPathParts.forEach(function (sPathPart: any, i: any) {
1111
+ sPath += "/" + sPathPart;
1112
+ const oRootViewController = oAppComponent.getRootViewController() as RootContainerBaseController;
1113
+ const sParameterPath = oMetaModel.getMetaPath(sPath);
1114
+ const bResultContext = oMetaModel.getObject(sParameterPath + "/@com.sap.vocabularies.Common.v1.ResultContext");
1115
+ if (bResultContext) {
1116
+ // We dont need to create a breadcrumb for Parameter path
1117
+ iSkipParameterized = 1;
1118
+ return;
1119
+ }
1120
+
1121
+ const pWaitForTitleHiearchyInfo = oRootViewController.getTitleInfoFromPath(sPath);
1122
+
1123
+ pWaitForTitleHiearchyInfo
1124
+ .then(function (oTitleHiearchyInfo: any) {
1125
+ const idx = i - iSkipParameterized,
1126
+ oLink = oSource.getLinks()[idx] ? oSource.getLinks()[idx] : new Link();
1127
+ // sCurrentEntity is a fallback value in case of empty title
1128
+ oLink.setText(oTitleHiearchyInfo.subtitle || oTitleHiearchyInfo.title);
1129
+ oLink.setHref(oTitleHiearchyInfo.intent);
1130
+ if (!oSource.getLinks()[idx]) {
1131
+ oSource.addLink(oLink);
1132
+ }
1133
+ })
1134
+ .catch(function (oError: any) {
1135
+ Log.error("Error while computing the title hierarchy", oError);
1136
+ });
1137
+ });
1138
+ }
1139
+ }
1140
+
1141
+ _checkDataPointTitleForExternalNavigation() {
1142
+ const oView = this.getView();
1143
+ const oInternalModelContext = oView.getBindingContext("internal") as InternalModelContext;
1144
+ const oDataPoints = CommonUtils.getHeaderFacetItemConfigForExternalNavigation(
1145
+ oView.getViewData(),
1146
+ this.getAppComponent().getRoutingService().getOutbounds()
1147
+ );
1148
+ const oShellServices = this.getAppComponent().getShellServices();
1149
+ const oPageContext = oView && (oView.getBindingContext() as Context);
1150
+ oInternalModelContext.setProperty("isHeaderDPLinkVisible", {});
1151
+ if (oPageContext) {
1152
+ oPageContext
1153
+ .requestObject()
1154
+ .then(function (oData: any) {
1155
+ fnGetLinks(oDataPoints, oData);
1156
+ })
1157
+ .catch(function (oError: any) {
1158
+ Log.error("Cannot retrieve the links from the shell service", oError);
1159
+ });
1160
+ }
1161
+
1162
+ /**
1163
+ * @param oError
1164
+ */
1165
+ function fnOnError(oError: any) {
1166
+ Log.error(oError);
1167
+ }
1168
+
1169
+ function fnSetLinkEnablement(id: string, aSupportedLinks: any) {
1170
+ const sLinkId = id;
1171
+ // process viable links from getLinks for all datapoints having outbound
1172
+ if (aSupportedLinks && aSupportedLinks.length === 1 && aSupportedLinks[0].supported) {
1173
+ oInternalModelContext.setProperty("isHeaderDPLinkVisible/" + sLinkId, true);
1174
+ }
1175
+ }
1176
+
1177
+ /**
1178
+ * @param oDataPoints
1179
+ * @param oPageData
1180
+ */
1181
+ function fnGetLinks(oDataPoints: any, oPageData: any) {
1182
+ for (const sId in oDataPoints) {
1183
+ const oDataPoint = oDataPoints[sId];
1184
+ const oParams: any = {};
1185
+ const oLink = oView.byId(sId);
1186
+ if (!oLink) {
1187
+ // for data points configured in app descriptor but not annotated in the header
1188
+ continue;
1189
+ }
1190
+ const oLinkContext = oLink.getBindingContext();
1191
+ const oLinkData: any = oLinkContext && oLinkContext.getObject();
1192
+ let oMixedContext: any = merge({}, oPageData, oLinkData);
1193
+ // process semantic object mappings
1194
+ if (oDataPoint.semanticObjectMapping) {
1195
+ const aSemanticObjectMapping = oDataPoint.semanticObjectMapping;
1196
+ for (const item in aSemanticObjectMapping) {
1197
+ const oMapping = aSemanticObjectMapping[item];
1198
+ const sMainProperty = oMapping["LocalProperty"]["$PropertyPath"];
1199
+ const sMappedProperty = oMapping["SemanticObjectProperty"];
1200
+ if (sMainProperty !== sMappedProperty) {
1201
+ if (oMixedContext.hasOwnProperty(sMainProperty)) {
1202
+ const oNewMapping: any = {};
1203
+ oNewMapping[sMappedProperty] = oMixedContext[sMainProperty];
1204
+ oMixedContext = merge({}, oMixedContext, oNewMapping);
1205
+ delete oMixedContext[sMainProperty];
1206
+ }
1207
+ }
1208
+ }
1209
+ }
1210
+
1211
+ if (oMixedContext) {
1212
+ for (const sKey in oMixedContext) {
1213
+ if (sKey.indexOf("_") !== 0 && sKey.indexOf("odata.context") === -1) {
1214
+ oParams[sKey] = oMixedContext[sKey];
1215
+ }
1216
+ }
1217
+ }
1218
+ // validate if a link must be rendered
1219
+ oShellServices
1220
+ .isNavigationSupported([
1221
+ {
1222
+ target: {
1223
+ semanticObject: oDataPoint.semanticObject,
1224
+ action: oDataPoint.action
1225
+ },
1226
+ params: oParams
1227
+ }
1228
+ ])
1229
+ .then((aLinks) => {
1230
+ return fnSetLinkEnablement(sId, aLinks);
1231
+ })
1232
+ .catch(fnOnError);
1233
+ }
1234
+ }
1235
+ }
1236
+
1237
+ handlers = {
1238
+ onTableContextChange(this: ObjectPageController, oEvent: any) {
1239
+ const oSource = oEvent.getSource();
1240
+ let oTable: any;
1241
+ this._findTables().some(function (_oTable: any) {
1242
+ if (_oTable.getRowBinding() === oSource) {
1243
+ oTable = _oTable;
1244
+ return true;
1245
+ }
1246
+ return false;
1247
+ });
1248
+
1249
+ const oCurrentActionPromise = this._editFlow.getCurrentActionPromise();
1250
+ if (oCurrentActionPromise) {
1251
+ let aTableContexts: any;
1252
+ if (oTable.getType().getMetadata().isA("sap.ui.mdc.table.GridTableType")) {
1253
+ aTableContexts = oSource.getContexts(0);
1254
+ } else {
1255
+ aTableContexts = oSource.getCurrentContexts();
1256
+ }
1257
+ //if contexts are not fully loaded the getcontexts function above will trigger a new change event call
1258
+ if (!aTableContexts[0]) {
1259
+ return;
1260
+ }
1261
+ oCurrentActionPromise
1262
+ .then((oActionResponse: any) => {
1263
+ if (!oActionResponse || oActionResponse.controlId !== oTable.sId) {
1264
+ return;
1265
+ }
1266
+ const oActionData = oActionResponse.oData;
1267
+ const aKeys = oActionResponse.keys;
1268
+ let iNewItemp = -1;
1269
+ aTableContexts.find(function (oTableContext: any, i: any) {
1270
+ const oTableData = oTableContext.getObject();
1271
+ const bCompare = aKeys.every(function (sKey: any) {
1272
+ return oTableData[sKey] === oActionData[sKey];
1273
+ });
1274
+ if (bCompare) {
1275
+ iNewItemp = i;
1276
+ }
1277
+ return bCompare;
1278
+ });
1279
+ if (iNewItemp !== -1) {
1280
+ const aDialogs = InstanceManager.getOpenDialogs();
1281
+ const oDialog =
1282
+ aDialogs.length > 0 ? aDialogs.find((dialog) => dialog.data("FullScreenDialog") !== true) : null;
1283
+ if (oDialog) {
1284
+ // by design, a sap.m.dialog set the focus to the previous focused element when closing.
1285
+ // we should wait for the dialog to be close before to focus another element
1286
+ oDialog.attachEventOnce("afterClose", function () {
1287
+ oTable.focusRow(iNewItemp, true);
1288
+ });
1289
+ } else {
1290
+ oTable.focusRow(iNewItemp, true);
1291
+ }
1292
+ this._editFlow.deleteCurrentActionPromise();
1293
+ }
1294
+ })
1295
+ .catch(function (err: any) {
1296
+ Log.error("An error occurs while scrolling to the newly created Item: " + err);
1297
+ });
1298
+ }
1299
+ // fire ModelContextChange on the message button whenever the table context changes
1300
+ const oMessageButton = this.getView().byId("fe::FooterBar::MessageButton");
1301
+ oMessageButton.fireModelContextChange();
1302
+ },
1303
+
1304
+ /**
1305
+ * Invokes an action - bound/unbound and sets the page dirty.
1306
+ *
1307
+ * @param oView
1308
+ * @param {string} sActionName The name of the action to be called
1309
+ * @param {map} [mParameters] Contains the following attributes:
1310
+ * @param {sap.ui.model.odata.v4.Context} [mParameters.contexts] Mandatory for a bound action, either one context or an array with contexts for which the action shall be called
1311
+ * @param {sap.ui.model.odata.v4.ODataModel} [mParameters.model] Mandatory for an unbound action; an instance of an OData V4 model
1312
+ * @returns {Promise}
1313
+ * @ui5-restricted
1314
+ * @final
1315
+ */
1316
+ onCallAction(oView: any, sActionName: string, mParameters: any) {
1317
+ const oController = oView.getController();
1318
+ const that = oController;
1319
+ return oController.editFlow
1320
+ .invokeAction(sActionName, mParameters)
1321
+ .then(that._showMessagePopover.bind(that, undefined))
1322
+ .catch(that._showMessagePopover.bind(that));
1323
+ },
1324
+ onDataPointTitlePressed(oController: any, oSource: any, oManifestOutbound: any, sControlConfig: any, sCollectionPath: any) {
1325
+ oManifestOutbound = typeof oManifestOutbound === "string" ? JSON.parse(oManifestOutbound) : oManifestOutbound;
1326
+ const oTargetInfo = oManifestOutbound[sControlConfig],
1327
+ aSemanticObjectMapping = CommonUtils.getSemanticObjectMapping(oTargetInfo),
1328
+ oDataPointOrChartBindingContext = oSource.getBindingContext(),
1329
+ sMetaPath = oDataPointOrChartBindingContext
1330
+ .getModel()
1331
+ .getMetaModel()
1332
+ .getMetaPath(oDataPointOrChartBindingContext.getPath());
1333
+ let aNavigationData = oController._getChartContextData(oDataPointOrChartBindingContext, sCollectionPath);
1334
+ let additionalNavigationParameters;
1335
+
1336
+ aNavigationData = aNavigationData.map(function (oNavigationData: any) {
1337
+ return {
1338
+ data: oNavigationData,
1339
+ metaPath: sMetaPath + (sCollectionPath ? "/" + sCollectionPath : "")
1340
+ };
1341
+ });
1342
+ if (oTargetInfo && oTargetInfo.parameters) {
1343
+ const oParams = oTargetInfo.parameters && oController._intentBasedNavigation.getOutboundParams(oTargetInfo.parameters);
1344
+ if (Object.keys(oParams).length > 0) {
1345
+ additionalNavigationParameters = oParams;
1346
+ }
1347
+ }
1348
+ if (oTargetInfo && oTargetInfo.semanticObject && oTargetInfo.action) {
1349
+ oController._intentBasedNavigation.navigate(oTargetInfo.semanticObject, oTargetInfo.action, {
1350
+ navigationContexts: aNavigationData,
1351
+ semanticObjectMapping: aSemanticObjectMapping,
1352
+ additionalNavigationParameters: additionalNavigationParameters
1353
+ });
1354
+ }
1355
+ },
1356
+ /**
1357
+ * Triggers an outbound navigation when a user chooses the chevron.
1358
+ *
1359
+ * @param {object} oController
1360
+ * @param {string} sOutboundTarget Name of the outbound target (needs to be defined in the manifest)
1361
+ * @param {sap.ui.model.odata.v4.Context} oContext The context that contains the data for the target app
1362
+ * @param {string} sCreatePath Create path when the chevron is created.
1363
+ * @returns {Promise} Promise which is resolved once the navigation is triggered (??? maybe only once finished?)
1364
+ * @ui5-restricted
1365
+ * @final
1366
+ */
1367
+ onChevronPressNavigateOutBound(oController: ObjectPageController, sOutboundTarget: string, oContext: any, sCreatePath: string) {
1368
+ return oController._intentBasedNavigation.onChevronPressNavigateOutBound(oController, sOutboundTarget, oContext, sCreatePath);
1369
+ },
1370
+
1371
+ onNavigateChange(this: ObjectPageController, oEvent: any) {
1372
+ //will be called always when we click on a section tab
1373
+ this.getExtensionAPI().updateAppState();
1374
+ this.bSectionNavigated = true;
1375
+
1376
+ const oInternalModelContext = this.getView().getBindingContext("internal") as InternalModelContext;
1377
+ const oObjectPage = this._getObjectPageLayoutControl();
1378
+ if (
1379
+ oObjectPage.getModel("ui").getProperty("/isEditable") &&
1380
+ (this.getView().getViewData() as any).sectionLayout === "Tabs" &&
1381
+ oInternalModelContext.getProperty("errorNavigationSectionFlag") === false
1382
+ ) {
1383
+ const oSubSection = oEvent.getParameter("subSection");
1384
+ this._updateFocusInEditMode([oSubSection]);
1385
+ }
1386
+ },
1387
+ onVariantSelected: function (this: ObjectPageController) {
1388
+ this.getExtensionAPI().updateAppState();
1389
+ },
1390
+ onVariantSaved: function (this: ObjectPageController) {
1391
+ //TODO: Should remove this setTimeOut once Variant Management provides an api to fetch the current variant key on save
1392
+ setTimeout(() => {
1393
+ this.getExtensionAPI().updateAppState();
1394
+ }, 500);
1395
+ },
1396
+ navigateToSubSection: function (oController: ObjectPageController, vDetailConfig: any) {
1397
+ const oDetailConfig = typeof vDetailConfig === "string" ? JSON.parse(vDetailConfig) : vDetailConfig;
1398
+ const oObjectPage = oController.getView().byId("fe::ObjectPage") as ObjectPageLayout;
1399
+ let oSection;
1400
+ let oSubSection;
1401
+ if (oDetailConfig.sectionId) {
1402
+ oSection = oController.getView().byId(oDetailConfig.sectionId) as ObjectPageSection;
1403
+ oSubSection = (
1404
+ oDetailConfig.subSectionId
1405
+ ? oController.getView().byId(oDetailConfig.subSectionId)
1406
+ : oSection && oSection.getSubSections() && oSection.getSubSections()[0]
1407
+ ) as ObjectPageSubSection;
1408
+ } else if (oDetailConfig.subSectionId) {
1409
+ oSubSection = oController.getView().byId(oDetailConfig.subSectionId) as ObjectPageSubSection;
1410
+ oSection = oSubSection && (oSubSection.getParent() as ObjectPageSection);
1411
+ }
1412
+ if (!oSection || !oSubSection || !oSection.getVisible() || !oSubSection.getVisible()) {
1413
+ ((oController.getView().getModel("sap.fe.i18n") as ResourceModel).getResourceBundle() as Promise<ResourceBundle>)
1414
+ .then(function (oResourceBundle) {
1415
+ const sTitle = CommonUtils.getTranslatedText(
1416
+ "C_ROUTING_NAVIGATION_DISABLED_TITLE",
1417
+ oResourceBundle,
1418
+ null,
1419
+ (oController.getView().getViewData() as any).entitySet
1420
+ );
1421
+ Log.error(sTitle);
1422
+ MessageBox.error(sTitle);
1423
+ })
1424
+ .catch(function (error) {
1425
+ Log.error(error);
1426
+ });
1427
+ } else {
1428
+ oObjectPage.scrollToSection(oSubSection.getId());
1429
+ // trigger iapp state change
1430
+ oObjectPage.fireNavigate({
1431
+ section: oSection,
1432
+ subSection: oSubSection
1433
+ });
1434
+ }
1435
+ },
1436
+ onChartSelectionChanged: function (oEvent: any) {
1437
+ ChartRuntime.fnUpdateChart(oEvent);
1438
+ }
1439
+ };
1440
+ }
1441
+
1442
+ export default ObjectPageController;