@sapui5/sap.fe.core 1.121.4 → 1.121.6

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,6 +1,7 @@
1
1
  import Log from "sap/base/Log";
2
2
  import type PageController from "sap/fe/core/PageController";
3
3
  import EditState from "sap/fe/core/helpers/EditState";
4
+ import ModelHelper from "sap/fe/core/helpers/ModelHelper";
4
5
  import type ObjectPageControllerController from "sap/fe/templates/ObjectPage/ObjectPageController.controller";
5
6
  import type ODataV4Context from "sap/ui/model/odata/v4/Context";
6
7
  import DraftDataLossDialogBlock from "../../controls/DataLossOrDraftDiscard/DraftDataLossDialog.block";
@@ -12,7 +13,7 @@ enum NavigationType {
12
13
  ForwardNavigation = "ForwardNavigation"
13
14
  }
14
15
 
15
- /* Enum types for the dataloss dialog options */
16
+ /* Enum types for the data loss dialog options */
16
17
  enum DraftDataLossOptions {
17
18
  Save = "draftDataLossOptionSave",
18
19
  Keep = "draftDataLossOptionKeep",
@@ -24,7 +25,7 @@ type DraftAdministrativeData = {
24
25
  LastChangeDateTime: Date;
25
26
  };
26
27
 
27
- /*Create the dataloss dialog*/
28
+ /*Create the data loss dialog*/
28
29
  const dataLossDialog = new DraftDataLossDialogBlock({});
29
30
 
30
31
  /**
@@ -34,20 +35,21 @@ const dataLossDialog = new DraftDataLossDialogBlock({});
34
35
  * @returns Boolean value with true or false to silently keep the draft
35
36
  */
36
37
  function silentlyKeepDraftOnForwardNavigation(pageController: PageController): boolean {
37
- let rbSilentlyKeep = false;
38
+ let rbSilentlyKeep;
38
39
  const oManifest = pageController.getAppComponent().getManifestEntry("sap.fe");
39
40
  rbSilentlyKeep = oManifest?.app?.silentlyKeepDraftOnForwardNavigation || false;
40
41
  return rbSilentlyKeep;
41
42
  }
42
43
 
43
44
  /**
44
- * Logic to process the fcl mode.
45
+ * Logic to process the FCL mode.
45
46
  *
46
47
  * @param draftAdminData Admin data
47
48
  * @param fnCancelFunction The cancel function
48
49
  * @param oController The current controller referenced
49
- * @param processFunctionForDrafts The functon to process the handler
50
+ * @param processFunctionForDrafts The function to process the handler
50
51
  * @param bSkipBindingToView The optional parameter to skip the binding to the view
52
+ * @param context The context to be used for the draft operation
51
53
  * @returns Nothing
52
54
  */
53
55
  async function processFclMode(
@@ -55,7 +57,8 @@ async function processFclMode(
55
57
  fnCancelFunction: Function,
56
58
  oController: PageController,
57
59
  processFunctionForDrafts: Function,
58
- bSkipBindingToView?: boolean
60
+ bSkipBindingToView?: boolean,
61
+ context?: ODataV4Context
59
62
  ): Promise<void> {
60
63
  // The application is running in FCL mode so in this case we fall back to
61
64
  // the old logic since the dirty state handling is not properly working
@@ -69,7 +72,8 @@ async function processFclMode(
69
72
  processFunctionForDrafts,
70
73
  fnCancelFunction,
71
74
  oController,
72
- bSkipBindingToView
75
+ bSkipBindingToView,
76
+ context
73
77
  )
74
78
  );
75
79
  } else {
@@ -83,10 +87,11 @@ async function processFclMode(
83
87
  * @param draftAdminData Admin data
84
88
  * @param fnCancelFunction The cancel function
85
89
  * @param oController The current controller referenced
86
- * @param processFunctionForDrafts The functon to process the handler
90
+ * @param processFunctionForDrafts The function to process the handler
87
91
  * @param navigationType The navigation type for which the function should be called
88
92
  * @param bSilentlyKeepDraftOnForwardNavigation The parameter to determine whether to skip the popup appearance in forward case
89
93
  * @param bSkipBindingToView The optional parameter to skip the binding to the view
94
+ * @param context The context to be used for the draft operations
90
95
  * @returns Nothing
91
96
  */
92
97
  async function processNoActiveEntityMode(
@@ -96,9 +101,10 @@ async function processNoActiveEntityMode(
96
101
  processFunctionForDrafts: Function,
97
102
  navigationType: NavigationType,
98
103
  bSilentlyKeepDraftOnForwardNavigation: boolean,
99
- bSkipBindingToView?: boolean
104
+ bSkipBindingToView?: boolean,
105
+ context?: ODataV4Context
100
106
  ): Promise<void> {
101
- // There is no active entity so we are editing either newly created data or
107
+ // There is no active entity so, we are editing either newly created data or
102
108
  // a draft which has never been saved to active version
103
109
  // Since we want to react differently in the two situations, we have to check the
104
110
  // dirty state
@@ -108,7 +114,7 @@ async function processNoActiveEntityMode(
108
114
  // navigation we can silently discard the draft again
109
115
  // eslint-disable-next-line promise/no-nesting
110
116
  try {
111
- await draftDataLossPopup.discardDraft(oController, bSkipBindingToView);
117
+ await draftDataLossPopup.discardDraft(oController, bSkipBindingToView, context);
112
118
  processFunctionForDrafts();
113
119
  } catch (error: unknown) {
114
120
  Log.error("Error while canceling the document", error as string);
@@ -119,7 +125,7 @@ async function processNoActiveEntityMode(
119
125
  processFunctionForDrafts();
120
126
  } else {
121
127
  // In this case data is being changed or a forward navigation is triggered
122
- // and we always want to show the dataloss dialog on navigation
128
+ // and, we always want to show the data loss dialog on navigation
123
129
  return dataLossDialog
124
130
  .open(oController)
125
131
  .then((selectedKey) =>
@@ -128,7 +134,8 @@ async function processNoActiveEntityMode(
128
134
  processFunctionForDrafts,
129
135
  fnCancelFunction,
130
136
  oController,
131
- bSkipBindingToView
137
+ bSkipBindingToView,
138
+ context
132
139
  )
133
140
  );
134
141
  }
@@ -145,7 +152,7 @@ async function processNoActiveEntityMode(
145
152
  *
146
153
  * @param oController The current controller referenced.
147
154
  * @param oContext The context of the current call
148
- * @param processFunctionForDrafts The functon to process the handler
155
+ * @param processFunctionForDrafts The function to process the handler
149
156
  * @param navigationType The navigation type for which the function should be called
150
157
  */
151
158
  async function processEditingDraftForExistingEntity(
@@ -158,8 +165,8 @@ async function processEditingDraftForExistingEntity(
158
165
  // The CreationDateTime and LastChangeDateTime are equal, so this draft was
159
166
  // never saved before, hence we're currently editing a newly created draft for
160
167
  // an existing active entity for the first time.
161
- // Also there have so far been no changes made to the draft and in this
162
- // case we want to silently navigate and delete the draftin case of a back
168
+ // Also, there have so far been no changes made to the draft and in this
169
+ // case we want to silently navigate and delete the draft in case of a back
163
170
  // navigation but in case of a forward navigation we want to silently keep it!
164
171
  if (navigationType === NavigationType.BackNavigation) {
165
172
  const mParameters = {
@@ -180,14 +187,15 @@ async function processEditingDraftForExistingEntity(
180
187
  }
181
188
 
182
189
  /**
183
- * Logic to process the edit state dirty.
190
+ * Logic to process the context when the edit state is in dirty mode.
184
191
  *
185
192
  * @param oController The current controller referenced.
186
193
  * @param fnCancelFunction The cancel function
187
- * @param processFunctionForDrafts The functon to process the handler
194
+ * @param processFunctionForDrafts The function to process the handler
188
195
  * @param navigationType The navigation type for which the function should be called
189
196
  * @param bSilentlyKeepDraftOnForwardNavigation The parameter to determine whether to skip the popup appearance in forward case
190
197
  * @param bSkipBindingToView The optional parameter to skip the binding to the view.
198
+ * @param context The context to be used for the draft operations
191
199
  * @returns Nothing
192
200
  */
193
201
  async function processEditStateDirty(
@@ -196,7 +204,8 @@ async function processEditStateDirty(
196
204
  processFunctionForDrafts: Function,
197
205
  navigationType: NavigationType,
198
206
  bSilentlyKeepDraftOnForwardNavigation: boolean,
199
- bSkipBindingToView?: boolean
207
+ bSkipBindingToView?: boolean,
208
+ context?: ODataV4Context
200
209
  ): Promise<void> {
201
210
  if (navigationType === NavigationType.ForwardNavigation && bSilentlyKeepDraftOnForwardNavigation) {
202
211
  // In case we have a "forward navigation" and an additional parameter set in the manifest
@@ -206,8 +215,8 @@ async function processEditStateDirty(
206
215
  // The CreationDateTime and LastChangeDateTime are NOT equal, so we are currently editing
207
216
  // an existing draft and need to distinguish depending on if any changes
208
217
  // have been made in the current editing session or not
209
- // Changes have been made in the current editing session so we want
210
- // to show the dataloss dialog and let the user decide
218
+ // Changes have been made in the current editing session, so we want
219
+ // to show the data loss dialog and let the user decide
211
220
  return dataLossDialog
212
221
  .open(oController)
213
222
  .then((selectedKey) =>
@@ -216,7 +225,8 @@ async function processEditStateDirty(
216
225
  processFunctionForDrafts,
217
226
  fnCancelFunction,
218
227
  oController,
219
- bSkipBindingToView
228
+ bSkipBindingToView,
229
+ context
220
230
  )
221
231
  );
222
232
  }
@@ -226,7 +236,7 @@ async function processEditStateDirty(
226
236
  * Logic to process the admin data.
227
237
  *
228
238
  * @param draftAdminData Admin data
229
- * @param fnProcessFunction The functon to process the handler
239
+ * @param fnProcessFunction The function to process the handler
230
240
  * @param fnCancelFunction The cancel function
231
241
  * @param oContext The context of the current call
232
242
  * @param oController The current controller referenced
@@ -255,7 +265,7 @@ async function processDraftAdminData(
255
265
 
256
266
  if (draftAdminData) {
257
267
  if (oController.getAppComponent().getRootViewController().isFclEnabled()) {
258
- await processFclMode(draftAdminData, fnCancelFunction, oController, processFunctionForDrafts, bSkipBindingToView);
268
+ await processFclMode(draftAdminData, fnCancelFunction, oController, processFunctionForDrafts, bSkipBindingToView, oContext);
259
269
  } else if (!oContext.getObject().HasActiveEntity) {
260
270
  processNoActiveEntityMode(
261
271
  draftAdminData,
@@ -280,7 +290,7 @@ async function processDraftAdminData(
280
290
  } else {
281
291
  // The user started editing the existing draft but did not make any changes
282
292
  // in the current editing session, so in this case we do not want
283
- // to show the dataloss dialog but just keep the draft
293
+ // to show the data loss dialog but just keep the draft
284
294
  processFunctionForDrafts();
285
295
  }
286
296
  } else {
@@ -313,15 +323,20 @@ async function processDataLossOrDraftDiscardConfirmation(
313
323
  const isDraftRoot = entitySetName ? !!oMetaModel.getObject("/" + entitySetName + "@com.sap.vocabularies.Common.v1.DraftRoot") : false;
314
324
  const oUIModel = oView.getModel("ui");
315
325
  const bIsEditable = oUIModel.getProperty("/isEditable");
316
- const draftDataContext = oModel.bindContext(`${oContext.getPath()}/DraftAdministrativeData`).getBoundContext();
326
+ const originalContext = oContext;
327
+ let draftRootPath = oContext.getPath();
328
+ if (!isDraftRoot) {
329
+ draftRootPath = ModelHelper.getDraftRootPath(oContext) ?? draftRootPath;
330
+ }
331
+ oContext = oModel.bindContext(draftRootPath, undefined, { $expand: "DraftAdministrativeData" }).getBoundContext();
317
332
 
318
333
  // Shouldn't display data loss popover on shell back navigation from sub-object pages
319
334
  // or when object page is in display mode, or when the object is deleted
320
- if (oContext.isDeleted() || (!isDraftRoot && navigationType === NavigationType.BackNavigation) || !bIsEditable) {
335
+ if (originalContext.isDeleted() || (!isDraftRoot && navigationType === NavigationType.BackNavigation) || !bIsEditable) {
321
336
  fnProcessFunction();
322
337
  } else {
323
338
  try {
324
- const draftAdminData = await draftDataContext.requestObject();
339
+ const draftAdminData = await oContext.requestObject("DraftAdministrativeData");
325
340
  await processDraftAdminData(
326
341
  draftAdminData,
327
342
  fnProcessFunction,
@@ -343,11 +358,13 @@ async function processDataLossOrDraftDiscardConfirmation(
343
358
  * from EditFlow is called.
344
359
  *
345
360
  * @param controller Controller of the current view
361
+ * @param context The context to be used for the draft operations
346
362
  * @returns A promise resolved if the save was successful
347
363
  */
348
- async function saveDocument(controller: PageController): Promise<unknown> {
349
- const context = controller.getView().getBindingContext();
350
- if (controller.isA<ObjectPageControllerController>("sap.fe.templates.ObjectPage.ObjectPageController")) {
364
+ async function saveDocument(controller: PageController, context?: ODataV4Context): Promise<unknown> {
365
+ const hasInitialContext = context !== undefined;
366
+ context = context ?? controller.getView().getBindingContext();
367
+ if (!hasInitialContext && controller.isA<ObjectPageControllerController>("sap.fe.templates.ObjectPage.ObjectPageController")) {
351
368
  return controller._saveDocument();
352
369
  } else {
353
370
  return controller.editFlow.saveDocument(context, {});
@@ -359,10 +376,15 @@ async function saveDocument(controller: PageController): Promise<unknown> {
359
376
  *
360
377
  * @param controller Controller of the current view
361
378
  * @param skipBindingToView The parameter to skip the binding to the view
379
+ * @param context The context to be used for the draft operations
362
380
  * @returns A promise resolved if cancelDocument was successful
363
381
  */
364
- async function discardDraft(controller: PageController, skipBindingToView: boolean | undefined): Promise<unknown> {
365
- const context = controller.getView().getBindingContext();
382
+ async function discardDraft(
383
+ controller: PageController,
384
+ skipBindingToView: boolean | undefined,
385
+ context?: ODataV4Context
386
+ ): Promise<unknown> {
387
+ context = context ?? controller.getView().getBindingContext();
366
388
  const params = {
367
389
  skipBackNavigation: true,
368
390
  skipDiscardPopover: true,
@@ -372,25 +394,27 @@ async function discardDraft(controller: PageController, skipBindingToView: boole
372
394
  }
373
395
 
374
396
  /**
375
- * Executes the follow-up functions after an option was selected in the dataloss dialog.
397
+ * Executes the follow-up functions after an option was selected in the data loss dialog.
376
398
  *
377
- * @param selectedKey The key of the selected option from the dataloss dialog
399
+ * @param selectedKey The key of the selected option from the data loss dialog
378
400
  * @param processFunctionForDrafts The function to process the handler
379
401
  * @param fnCancelFunction The function to process the handler
380
402
  * @param controller Controller of the current view
381
403
  * @param skipBindingToView The parameter to skip the binding to the view
404
+ * @param context The context to be used for the binding
382
405
  */
383
406
  function handleDialogSelection(
384
407
  selectedKey: string,
385
408
  processFunctionForDrafts: Function,
386
409
  fnCancelFunction: Function,
387
410
  controller: PageController,
388
- skipBindingToView: boolean | undefined
411
+ skipBindingToView: boolean | undefined,
412
+ context?: ODataV4Context
389
413
  ): void {
390
414
  switch (selectedKey) {
391
415
  case DraftDataLossOptions.Save:
392
416
  draftDataLossPopup
393
- .saveDocument(controller)
417
+ .saveDocument(controller, context)
394
418
  .then((context?) => processFunctionForDrafts(context))
395
419
  .catch(function (error: string | undefined) {
396
420
  if (error === RecommendationDialogDecision.Continue) {
@@ -406,7 +430,7 @@ function handleDialogSelection(
406
430
  break;
407
431
  case DraftDataLossOptions.Discard:
408
432
  draftDataLossPopup
409
- .discardDraft(controller, skipBindingToView)
433
+ .discardDraft(controller, skipBindingToView, context)
410
434
  .then((context?) => processFunctionForDrafts(context))
411
435
  .catch(function (error: string | undefined) {
412
436
  Log.error("Error while discarding draft", error);
@@ -4,7 +4,7 @@
4
4
  "id": "sap.fe.core.fpm",
5
5
  "type": "component",
6
6
  "applicationVersion": {
7
- "version": "1.121.4"
7
+ "version": "1.121.6"
8
8
  },
9
9
  "title": "Object Page",
10
10
  "tags": {
@@ -48,7 +48,7 @@ sap.ui.define(["sap/base/Log", "sap/fe/core/formatters/FPMFormatter", "sap/fe/co
48
48
  controls: [],
49
49
  elements: [],
50
50
  // eslint-disable-next-line no-template-curly-in-string
51
- version: "1.121.4",
51
+ version: "1.121.6",
52
52
  noLibraryCSS: true,
53
53
  extensions: {
54
54
  //Configuration used for rule loading of Support Assistant