@sapui5/sap.fe.core 1.102.3 → 1.102.5

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.
@@ -1,19 +1,19 @@
1
1
  import Log from "sap/base/Log";
2
- import AppComponent from "sap/fe/core/AppComponent";
2
+ import type AppComponent from "sap/fe/core/AppComponent";
3
+ import DataQueryWatcher from "sap/fe/core/controllerextensions/pageReady/DataQueryWatcher";
3
4
  import TemplatedViewServiceFactory from "sap/fe/core/services/TemplatedViewServiceFactory";
4
- import Event from "sap/ui/base/Event";
5
+ import type Event from "sap/ui/base/Event";
5
6
  import EventProvider from "sap/ui/base/EventProvider";
6
- import ManagedObject from "sap/ui/base/ManagedObject";
7
+ import type ManagedObject from "sap/ui/base/ManagedObject";
7
8
  import Component from "sap/ui/core/Component";
8
9
  import Core from "sap/ui/core/Core";
9
10
  import ControllerExtension from "sap/ui/core/mvc/ControllerExtension";
10
11
  import OverrideExecution from "sap/ui/core/mvc/OverrideExecution";
11
- import View from "sap/ui/core/mvc/View";
12
- import Context from "sap/ui/model/Context";
13
- import { CoreEx } from "types/extension_types";
12
+ import type View from "sap/ui/core/mvc/View";
13
+ import type Context from "sap/ui/model/odata/v4/Context";
14
+ import type { CoreEx } from "types/extension_types";
14
15
  import CommonUtils from "../CommonUtils";
15
16
  import { defineUI5Class, extensible, finalExtension, methodOverride, privateExtension, publicExtension } from "../helpers/ClassSupport";
16
-
17
17
  @defineUI5Class("sap.fe.core.controllerextensions.PageReady")
18
18
  class PageReadyControllerExtension extends ControllerExtension {
19
19
  private _oEventProvider!: EventProvider;
@@ -24,19 +24,17 @@ class PageReadyControllerExtension extends ControllerExtension {
24
24
  private _bAfterBindingAlreadyApplied!: boolean;
25
25
  private _fnContainerDelegate: any;
26
26
  private _nbWaits!: number;
27
- private _bSeachTriggered!: boolean;
28
27
  private _bIsPageReady!: boolean;
29
28
  private _bWaitingForRefresh!: boolean;
30
29
  private bShown!: boolean;
31
30
  private bHasContext!: boolean;
32
- private bDataReceived: boolean | undefined;
33
- private bTablesLoaded: boolean | undefined;
31
+ private bTablesChartsLoaded?: boolean;
34
32
  private pageReadyTimer: NodeJS.Timeout | undefined;
33
+ private queryWatcher!: DataQueryWatcher;
35
34
 
36
35
  @methodOverride()
37
36
  public onInit() {
38
37
  this._nbWaits = 0;
39
- this._bSeachTriggered = false;
40
38
  this._oEventProvider = this._oEventProvider ? this._oEventProvider : new EventProvider();
41
39
  this._oView = (this as any).base.getView();
42
40
  this._oAppComponent = CommonUtils.getAppComponent(this._oView);
@@ -68,6 +66,8 @@ class PageReadyControllerExtension extends ControllerExtension {
68
66
  this
69
67
  );
70
68
  }
69
+
70
+ this.queryWatcher = new DataQueryWatcher(this._oEventProvider, this.checkPageReadyDebounced.bind(this));
71
71
  }
72
72
 
73
73
  @methodOverride()
@@ -75,7 +75,9 @@ class PageReadyControllerExtension extends ControllerExtension {
75
75
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
76
76
  // @ts-ignore
77
77
  delete this._oAppComponent;
78
- this._oContainer && this._oContainer.removeEventDelegate(this._fnContainerDelegate);
78
+ if (this._oContainer) {
79
+ this._oContainer.removeEventDelegate(this._fnContainerDelegate);
80
+ }
79
81
  }
80
82
 
81
83
  @publicExtension()
@@ -99,162 +101,78 @@ class PageReadyControllerExtension extends ControllerExtension {
99
101
  this.checkPageReadyDebounced();
100
102
  }
101
103
 
102
- @methodOverride("_routing")
103
- onAfterBinding(oBindingContext: Context) {
104
- if (!this._bAfterBindingAlreadyApplied) {
105
- this._bAfterBindingAlreadyApplied = true;
106
- let aBoundElements: any[] = [];
107
- const aNotBoundMDCTables: any[] = [];
108
- let iRequested = 0;
109
- let iReceived = 0;
110
- const fnRequested = (oEvent: Event) => {
111
- (oEvent.getSource() as any).detachDataRequested(fnRequested);
112
- iRequested++;
113
- this.bDataReceived = false;
114
- };
115
- const fnReceived = (oEvent: Event) => {
116
- switch ((oEvent.getSource() as any).sGroupId) {
117
- case "$auto.Workers":
118
- this._oEventProvider.fireEvent("workersBatchReceived");
119
- break;
120
- case "$auto.Heroes":
121
- this._oEventProvider.fireEvent("heroesBatchReceived");
122
- break;
123
- default:
124
- }
125
- (oEvent.getSource() as any).detachDataReceived(fnReceived);
126
- iReceived++;
127
- if (iReceived >= iRequested && iRequested !== 0) {
128
- iRequested = 0;
129
- iReceived = 0;
130
- this.bDataReceived = true;
131
- this.checkPageReadyDebounced();
132
- }
133
- };
134
- const fnSearch = (oEvent: Event) => {
135
- const aMDCTables = aNotBoundMDCTables.filter((oElem) => {
136
- if ((oEvent.getSource() as any).sId === oElem.getFilter() && oElem.getVisible()) {
137
- return true;
138
- }
139
- return false;
140
- });
141
- if (aMDCTables.length > 0) {
142
- this._bSeachTriggered = true;
143
- }
144
- aMDCTables.forEach((oMDCTable: any) => {
145
- let oRowBinding = oMDCTable.getRowBinding();
146
- const fnAttachDataEvents = () => {
147
- oRowBinding.attachDataRequested(fnRequested);
148
- oRowBinding.attachDataReceived((oEvent: any) => {
149
- fnReceived(oEvent);
150
- this._bSeachTriggered = false;
151
- });
152
- aBoundElements.push(oRowBinding);
153
- };
154
- if (oRowBinding) {
155
- fnAttachDataEvents();
156
- } else {
157
- oMDCTable.attachEventOnce(
158
- "bindingUpdated",
159
- null,
160
- () => {
161
- oRowBinding = oMDCTable.getRowBinding();
162
- fnAttachDataEvents();
163
- },
164
- null
165
- );
104
+ public registerAggregatedControls(mainBindingContext?: Context): Promise<void>[] {
105
+ if (mainBindingContext) {
106
+ const mainObjectBinding = mainBindingContext.getBinding();
107
+ this.queryWatcher.registerBinding(mainObjectBinding);
108
+ }
109
+
110
+ const aPromises: Promise<void>[] = [];
111
+ const aControls = this.getView().findAggregatedObjects(true);
112
+
113
+ aControls.forEach((oElement: any) => {
114
+ const oObjectBinding = oElement.getObjectBinding();
115
+ if (oObjectBinding) {
116
+ // Register on all object binding (mostly used on object pages)
117
+ this.queryWatcher.registerBinding(oObjectBinding);
118
+ } else {
119
+ const aBindingKeys = Object.keys(oElement.mBindingInfos);
120
+ aBindingKeys.forEach((sPropertyName) => {
121
+ const oListBinding = oElement.mBindingInfos[sPropertyName].binding;
122
+
123
+ if (oListBinding && oListBinding.isA("sap.ui.model.odata.v4.ODataListBinding")) {
124
+ this.queryWatcher.registerBinding(oListBinding);
166
125
  }
167
126
  });
168
- };
169
- if (this.isContextExpected() && oBindingContext === undefined) {
170
- // Force to mention we are expecting data
171
- this.bHasContext = false;
172
- return;
173
- } else {
174
- this.bHasContext = true;
175
127
  }
176
-
177
- this.attachEventOnce(
178
- "pageReady",
179
- null,
180
- () => {
181
- aBoundElements.forEach((oElement: any) => {
182
- oElement.detachEvent("dataRequested", fnRequested);
183
- oElement.detachEvent("dataReceived", fnReceived);
184
- oElement.detachEvent("search", fnSearch);
185
- });
186
- this._bAfterBindingAlreadyApplied = false;
187
- aBoundElements = [];
188
- },
189
- null
190
- );
191
- if (oBindingContext) {
192
- const mainObjectBinding = (oBindingContext as any).getBinding();
193
- mainObjectBinding.attachDataRequested(fnRequested);
194
- mainObjectBinding.attachDataReceived(fnReceived);
195
- aBoundElements.push(mainObjectBinding);
128
+ // This is dirty but MDCTables and MDCCharts have a weird loading lifecycle
129
+ if (oElement.isA("sap.ui.mdc.Table") || oElement.isA("sap.ui.mdc.Chart")) {
130
+ this.bTablesChartsLoaded = false;
131
+ aPromises.push(this.queryWatcher.registerTableOrChart(oElement));
132
+ } else if (oElement.isA("sap.fe.core.controls.FilterBar")) {
133
+ this.queryWatcher.registerFilterBar(oElement);
196
134
  }
135
+ });
197
136
 
198
- const aTableInitializedPromises: Promise<any>[] = [];
199
- this._oView.findAggregatedObjects(true, (oElement: any) => {
200
- const oObjectBinding = oElement.getObjectBinding();
201
- if (oObjectBinding) {
202
- // Register on all object binding (mostly used on object pages)
203
- oObjectBinding.attachDataRequested(fnRequested);
204
- oObjectBinding.attachDataReceived(fnReceived);
205
- aBoundElements.push(oObjectBinding);
206
- } else {
207
- const aBindingKeys = Object.keys(oElement.mBindingInfos);
208
- if (aBindingKeys.length > 0) {
209
- aBindingKeys.forEach((sPropertyName) => {
210
- const oListBinding = oElement.mBindingInfos[sPropertyName].binding;
211
- // Register on all list binding, good for basic tables, problematic for MDC, see above
212
- if (oListBinding && oListBinding.isA("sap.ui.model.odata.v4.ODataListBinding")) {
213
- oListBinding.attachDataRequested(fnRequested);
214
- oListBinding.attachDataReceived(fnReceived);
215
- aBoundElements.push(oListBinding);
216
- }
217
- });
218
- }
219
- }
220
- // This is dirty but MDC Table has a weird loading lifecycle
221
- if (oElement.isA("sap.ui.mdc.Table")) {
222
- this.bTablesLoaded = false;
223
- // access binding only after table is bound
224
- aTableInitializedPromises.push(
225
- oElement
226
- .initialized()
227
- .then(() => {
228
- const oRowBinding = oElement.getRowBinding();
229
- if (oRowBinding) {
230
- oRowBinding.attachDataRequested(fnRequested);
231
- oRowBinding.attachDataReceived(fnReceived);
232
- aBoundElements.push(oRowBinding);
233
- } else {
234
- aNotBoundMDCTables.push(oElement);
235
- }
236
- })
237
- .catch(function (oError: Error) {
238
- Log.error("Cannot find a bound table", oError as any);
239
- })
240
- );
241
- } else if (oElement.isA("sap.fe.core.controls.FilterBar")) {
242
- oElement.attachEvent("search", fnSearch);
243
- aBoundElements.push(oElement);
244
- }
245
- });
246
- if (aTableInitializedPromises.length > 0) {
247
- Promise.all(aTableInitializedPromises)
248
- .then(() => {
249
- this.bTablesLoaded = true;
250
- this.checkPageReadyDebounced();
251
- })
252
- .catch((oError) => {
253
- Log.info("There was an error with one or multiple table", oError);
254
- this.bTablesLoaded = true;
255
- this.checkPageReadyDebounced();
256
- });
257
- }
137
+ return aPromises;
138
+ }
139
+
140
+ @methodOverride("_routing")
141
+ onAfterBinding(oBindingContext: Context) {
142
+ if (this._bAfterBindingAlreadyApplied) {
143
+ return;
144
+ }
145
+ this._bAfterBindingAlreadyApplied = true;
146
+
147
+ if (this.isContextExpected() && oBindingContext === undefined) {
148
+ // Force to mention we are expecting data
149
+ this.bHasContext = false;
150
+ return;
151
+ } else {
152
+ this.bHasContext = true;
153
+ }
154
+
155
+ this.attachEventOnce(
156
+ "pageReady",
157
+ null,
158
+ () => {
159
+ this._bAfterBindingAlreadyApplied = false;
160
+ this.queryWatcher.reset();
161
+ },
162
+ null
163
+ );
164
+
165
+ const aTableChartInitializedPromises = this.registerAggregatedControls(oBindingContext);
166
+
167
+ if (aTableChartInitializedPromises.length > 0) {
168
+ Promise.all(aTableChartInitializedPromises)
169
+ .finally(() => {
170
+ this.bTablesChartsLoaded = true;
171
+ this.checkPageReadyDebounced();
172
+ })
173
+ .catch((oError) => {
174
+ Log.info("There was an error with one or multiple tables or charts", oError);
175
+ });
258
176
  }
259
177
  }
260
178
 
@@ -361,13 +279,13 @@ class PageReadyControllerExtension extends ControllerExtension {
361
279
 
362
280
  if (
363
281
  this.bShown &&
364
- this.bDataReceived !== false &&
365
- this.bTablesLoaded !== false &&
282
+ this.queryWatcher.isDataReceived() !== false &&
283
+ this.bTablesChartsLoaded !== false &&
366
284
  (!this.isContextExpected() || this.bHasContext) // Either no context is expected or there is one
367
285
  ) {
368
- if (this.bDataReceived === true && !bFromNav && !this._bWaitingForRefresh && Core.getUIDirty()) {
286
+ if (this.queryWatcher.isDataReceived() === true && !bFromNav && !this._bWaitingForRefresh && Core.getUIDirty()) {
369
287
  // If we requested data we get notified as soon as the data arrived, so before the next rendering tick
370
- this.bDataReceived = undefined;
288
+ this.queryWatcher.resetDataReceived();
371
289
  this._bWaitingForRefresh = true;
372
290
  (Core as CoreEx).attachEvent("UIUpdated", fnUIUpdated);
373
291
  setTimeout(checkUIUpdated, 500);
@@ -375,7 +293,7 @@ class PageReadyControllerExtension extends ControllerExtension {
375
293
  (!this._bWaitingForRefresh && Core.getUIDirty()) ||
376
294
  this._nbWaits !== 0 ||
377
295
  TemplatedViewServiceFactory.getNumberOfViewsInCreationState() > 0 ||
378
- this._bSeachTriggered
296
+ this.queryWatcher.isSearchPending()
379
297
  ) {
380
298
  this._bWaitingForRefresh = true;
381
299
  (Core as CoreEx).attachEvent("UIUpdated", fnUIUpdated);