@sapui5/sap.fe.templates 1.141.1 → 1.142.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 (74) hide show
  1. package/package.json +1 -1
  2. package/src/sap/fe/templates/.library +1 -1
  3. package/src/sap/fe/templates/AnalyticalListPage/manifest.json +1 -1
  4. package/src/sap/fe/templates/ListReport/ExtensionAPI.js +1 -1
  5. package/src/sap/fe/templates/ListReport/ExtensionAPI.ts +1 -1
  6. package/src/sap/fe/templates/ListReport/ListReport.view.xml +10 -12
  7. package/src/sap/fe/templates/ListReport/ListReportController.controller.js +95 -60
  8. package/src/sap/fe/templates/ListReport/ListReportController.controller.ts +92 -53
  9. package/src/sap/fe/templates/ListReport/manifest.json +1 -1
  10. package/src/sap/fe/templates/ListReport/overrides/MessageHandler.js +25 -0
  11. package/src/sap/fe/templates/ListReport/overrides/MessageHandler.ts +20 -0
  12. package/src/sap/fe/templates/ObjectPage/ExtensionAPI.js +180 -13
  13. package/src/sap/fe/templates/ObjectPage/ExtensionAPI.ts +209 -13
  14. package/src/sap/fe/templates/ObjectPage/ObjectPage.view.xml +4 -0
  15. package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.js +136 -24
  16. package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.ts +178 -26
  17. package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.js +3 -2
  18. package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.ts +2 -1
  19. package/src/sap/fe/templates/ObjectPage/manifest.json +1 -1
  20. package/src/sap/fe/templates/ObjectPage/view/fragments/Actions.fragment.xml +7 -4
  21. package/src/sap/fe/templates/ObjectPage/view/fragments/Heading.fragment.xml +2 -2
  22. package/src/sap/fe/templates/library.js +1 -1
  23. package/src/sap/fe/templates/messagebundle.properties +8 -7
  24. package/src/sap/fe/templates/messagebundle_ar.properties +5 -5
  25. package/src/sap/fe/templates/messagebundle_bg.properties +6 -6
  26. package/src/sap/fe/templates/messagebundle_ca.properties +4 -4
  27. package/src/sap/fe/templates/messagebundle_cnr.properties +5 -5
  28. package/src/sap/fe/templates/messagebundle_cs.properties +6 -6
  29. package/src/sap/fe/templates/messagebundle_cy.properties +5 -5
  30. package/src/sap/fe/templates/messagebundle_da.properties +6 -6
  31. package/src/sap/fe/templates/messagebundle_de.properties +7 -7
  32. package/src/sap/fe/templates/messagebundle_el.properties +5 -5
  33. package/src/sap/fe/templates/messagebundle_en.properties +6 -6
  34. package/src/sap/fe/templates/messagebundle_en_GB.properties +6 -6
  35. package/src/sap/fe/templates/messagebundle_en_US_saprigi.properties +3 -3
  36. package/src/sap/fe/templates/messagebundle_es.properties +4 -4
  37. package/src/sap/fe/templates/messagebundle_es_MX.properties +4 -4
  38. package/src/sap/fe/templates/messagebundle_et.properties +4 -4
  39. package/src/sap/fe/templates/messagebundle_fi.properties +4 -4
  40. package/src/sap/fe/templates/messagebundle_fr.properties +4 -4
  41. package/src/sap/fe/templates/messagebundle_fr_CA.properties +5 -5
  42. package/src/sap/fe/templates/messagebundle_hi.properties +6 -6
  43. package/src/sap/fe/templates/messagebundle_hr.properties +4 -4
  44. package/src/sap/fe/templates/messagebundle_hu.properties +6 -6
  45. package/src/sap/fe/templates/messagebundle_id.properties +7 -7
  46. package/src/sap/fe/templates/messagebundle_it.properties +4 -4
  47. package/src/sap/fe/templates/messagebundle_iw.properties +6 -6
  48. package/src/sap/fe/templates/messagebundle_ja.properties +4 -4
  49. package/src/sap/fe/templates/messagebundle_kk.properties +4 -4
  50. package/src/sap/fe/templates/messagebundle_ko.properties +4 -4
  51. package/src/sap/fe/templates/messagebundle_lt.properties +4 -4
  52. package/src/sap/fe/templates/messagebundle_lv.properties +6 -6
  53. package/src/sap/fe/templates/messagebundle_mk.properties +4 -4
  54. package/src/sap/fe/templates/messagebundle_ms.properties +5 -5
  55. package/src/sap/fe/templates/messagebundle_nl.properties +4 -4
  56. package/src/sap/fe/templates/messagebundle_no.properties +4 -4
  57. package/src/sap/fe/templates/messagebundle_pl.properties +4 -4
  58. package/src/sap/fe/templates/messagebundle_pt.properties +5 -5
  59. package/src/sap/fe/templates/messagebundle_pt_PT.properties +6 -6
  60. package/src/sap/fe/templates/messagebundle_ro.properties +4 -4
  61. package/src/sap/fe/templates/messagebundle_ru.properties +4 -4
  62. package/src/sap/fe/templates/messagebundle_sh.properties +5 -5
  63. package/src/sap/fe/templates/messagebundle_sk.properties +4 -4
  64. package/src/sap/fe/templates/messagebundle_sl.properties +6 -6
  65. package/src/sap/fe/templates/messagebundle_sr.properties +5 -5
  66. package/src/sap/fe/templates/messagebundle_sv.properties +4 -4
  67. package/src/sap/fe/templates/messagebundle_th.properties +4 -4
  68. package/src/sap/fe/templates/messagebundle_tr.properties +4 -4
  69. package/src/sap/fe/templates/messagebundle_uk.properties +4 -4
  70. package/src/sap/fe/templates/messagebundle_vi.properties +6 -6
  71. package/src/sap/fe/templates/messagebundle_zh_CN.properties +4 -4
  72. package/src/sap/fe/templates/messagebundle_zh_TW.properties +4 -4
  73. package/src/sap/fe/templates/types/sap.fe.templates-auto-ext.d.js +10 -0
  74. package/src/sap/fe/templates/types/sap.fe.templates-auto-ext.d.ts +49 -0
@@ -4,6 +4,7 @@ import merge from "sap/base/util/merge";
4
4
  import type { EnhanceWithUI5 } from "sap/fe/base/ClassSupport";
5
5
  import { defineUI5Class, extensible, finalExtension, publicExtension, usingExtension } from "sap/fe/base/ClassSupport";
6
6
  import ActionRuntime from "sap/fe/core/ActionRuntime";
7
+ import type { StartupParameters } from "sap/fe/core/AppComponent";
7
8
  import type { FEView } from "sap/fe/core/BaseController";
8
9
  import CommonUtils from "sap/fe/core/CommonUtils";
9
10
  import PageController from "sap/fe/core/PageController";
@@ -72,6 +73,7 @@ import type Chart from "sap/ui/mdc/Chart";
72
73
  import type Table from "sap/ui/mdc/Table";
73
74
  import type TableTypeBase from "sap/ui/mdc/table/TableTypeBase";
74
75
  import type Binding from "sap/ui/model/Binding";
76
+ import type CompositeBinding from "sap/ui/model/CompositeBinding";
75
77
  import type Context from "sap/ui/model/Context";
76
78
  import type ListBinding from "sap/ui/model/ListBinding";
77
79
  import type JSONModel from "sap/ui/model/json/JSONModel";
@@ -102,7 +104,11 @@ export type BindingParams = {
102
104
  };
103
105
 
104
106
  const ProgrammingModel = FELibrary.ProgrammingModel;
107
+ const PreferredActionStatus = FELibrary.PreferredActionStatusType;
105
108
 
109
+ /**
110
+ * @public
111
+ */
106
112
  @defineUI5Class("sap.fe.templates.ObjectPage.ObjectPageController")
107
113
  class ObjectPageController extends PageController {
108
114
  oView!: FEView;
@@ -158,7 +164,7 @@ class ObjectPageController extends PageController {
158
164
 
159
165
  private bSectionNavigated?: boolean;
160
166
 
161
- private clearTitleHierarchyCacheSetUp = false;
167
+ private invalidateTitleHierarchyCacheSetUp = false;
162
168
 
163
169
  private switchDraftAndActivePopOver?: Popover;
164
170
 
@@ -174,6 +180,8 @@ class ObjectPageController extends PageController {
174
180
 
175
181
  private messageBinding?: Binding;
176
182
 
183
+ private isFirstBinding = true;
184
+
177
185
  @publicExtension()
178
186
  @finalExtension()
179
187
  getExtensionAPI(sId?: string): ExtensionAPI {
@@ -198,12 +206,17 @@ class ObjectPageController extends PageController {
198
206
  const oObjectPage = this._getObjectPageLayoutControl();
199
207
 
200
208
  // Setting defaults of internal model context
201
- const oInternalModelContext = this.getView().getBindingContext("internal") as InternalModelContext;
202
- oInternalModelContext?.setProperty("externalNavigationContext", { page: true });
203
- oInternalModelContext?.setProperty("relatedApps", {
204
- visibility: false,
205
- items: null
206
- });
209
+ const oInternalModelContext = this.getOwnerComponent().getBindingContext("internal") as InternalModelContext;
210
+ oInternalModelContext?.setProperty("externalNavigationContext", { page: true }, undefined, true);
211
+ oInternalModelContext?.setProperty(
212
+ "relatedApps",
213
+ {
214
+ visibility: false,
215
+ items: null
216
+ },
217
+ undefined,
218
+ true
219
+ );
207
220
  oInternalModelContext?.setProperty("batchGroups", this._getBatchGroupsForView());
208
221
  oInternalModelContext?.setProperty("errorNavigationSectionFlag", false);
209
222
  if (oObjectPage.getEnableLazyLoading()) {
@@ -213,8 +226,10 @@ class ObjectPageController extends PageController {
213
226
  this.messageButton = this.getView().byId("fe::FooterBar::MessageButton") as MessageButton;
214
227
  this.messageBinding = Messaging.getMessageModel().bindList("/");
215
228
  this.messageBinding?.attachChange(this._fnShowOPMessage, this);
216
- oInternalModelContext?.setProperty("rootEditEnabled", true);
217
- oInternalModelContext?.setProperty("rootEditVisible", true);
229
+ oInternalModelContext?.setProperty("rootEditEnabled", true, undefined, true);
230
+ oInternalModelContext?.setProperty("rootEditVisible", true, undefined, true);
231
+
232
+ this._handleSmartSummaryStartupAction();
218
233
  }
219
234
 
220
235
  onExit(): void {
@@ -410,6 +425,28 @@ class ObjectPageController extends PageController {
410
425
  //Set the Binding for Paginators using ListBinding ID
411
426
  this._initializePagination(oContext, oInternalModel, mParameters?.listBinding);
412
427
 
428
+ const firstSubSectionVisibilityBinding = this._getfirstSubSectionVisibilityBinding();
429
+
430
+ if (
431
+ this.useLazyLoaderOptimizations() &&
432
+ oObjectPage.getEnableLazyLoading() &&
433
+ firstSubSectionVisibilityBinding &&
434
+ this.isFirstBinding
435
+ ) {
436
+ // if lazy loading is enabled and at least one subsection has a visibility binding
437
+ oObjectPage.setVisible(false); // The objectPage Visibility is set to false to prevent the lazy loader to compute the sections
438
+ firstSubSectionVisibilityBinding.attachEventOnce("change", async () => {
439
+ const MDCTablePromises = this._getAllBlocks().map(async (block) =>
440
+ block.getVisible() && block.getContent?.()?.isA<TableAPI>("sap.fe.macros.table.TableAPI")
441
+ ? (block.getContent() as TableAPI).getContent().initialized()
442
+ : null
443
+ );
444
+ await Promise.all(MDCTablePromises);
445
+ oObjectPage.setVisible(true); // Visibility is restored once the visibility bindings of the sections are resolved, allowing lazy loading to properly process them
446
+ this.isFirstBinding = false;
447
+ });
448
+ }
449
+
413
450
  if (oObjectPage.getEnableLazyLoading()) {
414
451
  this._disableBlocksBindings(oObjectPage);
415
452
  }
@@ -424,6 +461,13 @@ class ObjectPageController extends PageController {
424
461
  }
425
462
  }
426
463
 
464
+ private useLazyLoaderOptimizations(): boolean {
465
+ if (new URLSearchParams(window.location.search).get("sap-ui-xx-lazyloader-optimizations") === "true") {
466
+ return true;
467
+ }
468
+ return false;
469
+ }
470
+
427
471
  private getFirstEditableInput(): UI5Element | undefined {
428
472
  const domEditableElement = this._getObjectPageLayoutControl()._getFirstEditableInput();
429
473
  return domEditableElement ? UI5Element.closestTo(domEditableElement) : undefined;
@@ -471,22 +515,29 @@ class ObjectPageController extends PageController {
471
515
  let iSkip = 3; // 3 sections/subsections are loaded initially, the others are loaded lazily
472
516
  const bIsInEditMode = CommonUtils.getIsEditable(this.getView());
473
517
  const bEditableHeader = this.getView().getViewData().editableHeaderContent;
518
+ const firstVisibilityBinding = this._getfirstSubSectionVisibilityBinding();
474
519
  for (let iSection = 0; iSection < aSections.length; iSection++) {
475
520
  const oSection = aSections[iSection];
476
521
  const aSubSections = oSection.getSubSections();
477
522
  for (let iSubSection = 0; iSubSection < aSubSections.length; iSubSection++, iSkip--) {
478
523
  // In IconTabBar mode keep the second section bound if there is an editable header and we are switching to display mode
479
- if (iSkip < 1 || (bUseIconTabBar && (iSection > 1 || (iSection === 1 && !bEditableHeader && !bIsInEditMode)))) {
524
+
525
+ const disableBindingContextCondition =
526
+ (!this.useLazyLoaderOptimizations() &&
527
+ (iSkip < 1 || (bUseIconTabBar && (iSection > 1 || (iSection === 1 && !bEditableHeader && !bIsInEditMode))))) ||
528
+ (this.useLazyLoaderOptimizations() &&
529
+ ((!bUseIconTabBar && firstVisibilityBinding) || //if some subsections have visibility binding and we are not in IconTabBar mode
530
+ (!bUseIconTabBar && !firstVisibilityBinding && iSkip < 1) || // if no subsection has visibility binding and we are not in IconTabBar mode
531
+ (bUseIconTabBar && (iSection > 1 || (iSection === 1 && !bEditableHeader && !bIsInEditMode)))));
532
+ if (disableBindingContextCondition) {
480
533
  const oSubSection = aSubSections[iSubSection];
481
- if (oSubSection.data().isVisibilityDynamic !== "true") {
482
- // SubSection's binding is enabled.
483
- oSubSection.setBindingContext(undefined);
484
- const blocks = oSubSection.getBlocks() as SubSectionBlock[];
485
- // SubSection's contents binding is disabled.
486
- blocks.forEach((block) => block.setBindingContext(null));
487
- oSubSection.getMoreBlocks().forEach((subBlock) => subBlock.setBindingContext(null));
488
- oSubSection.getActions().forEach((actions) => actions.setBindingContext(null));
489
- }
534
+ // SubSection's binding is enabled.
535
+ oSubSection.setBindingContext(undefined);
536
+ const blocks = oSubSection.getBlocks() as SubSectionBlock[];
537
+ // SubSection's contents binding is disabled.
538
+ blocks.forEach((block) => block.setBindingContext(null));
539
+ oSubSection.getMoreBlocks().forEach((subBlock) => subBlock.setBindingContext(null));
540
+ oSubSection.getActions().forEach((actions) => actions.setBindingContext(null));
490
541
  }
491
542
  }
492
543
  }
@@ -587,10 +638,28 @@ class ObjectPageController extends PageController {
587
638
  oFieldToFocus.focus(focusInfo);
588
639
  }
589
640
  }.bind(this),
590
- 0
641
+ 0 //300
591
642
  );
592
643
  }
593
644
 
645
+ /**
646
+ * Get the first sub-section with a visibility bound to the model of the view.
647
+ * Sections with Bindings on internal models only are ignored.
648
+ * @returns The visibility binding of the first sub-section or undefined if not found.
649
+ */
650
+ _getfirstSubSectionVisibilityBinding(): Binding | undefined {
651
+ const allsubSections = this._getAllSubSections();
652
+ const currentModel = this.getView().getModel();
653
+ return allsubSections
654
+ .find(
655
+ (subSection) =>
656
+ (subSection.getBinding("visible") as CompositeBinding | undefined)
657
+ ?.getBindings?.()
658
+ .some((binding) => binding.getModel() === currentModel)
659
+ )
660
+ ?.getBinding("visible");
661
+ }
662
+
594
663
  _handleSubSectionEnteredViewPort(oEvent: UI5Event<{ subSection: ObjectPageSubSection }>): void {
595
664
  const oSubSection = oEvent.getParameter("subSection");
596
665
  const blocks = oSubSection.getBlocks() as SubSectionBlock[];
@@ -776,6 +845,8 @@ class ObjectPageController extends PageController {
776
845
 
777
846
  //To Compute the Edit Binding of the subObject page using root object page, create a context for draft root and update the edit button in sub OP using the context
778
847
  ActionRuntime.updateEditButtonVisibilityAndEnablement(this.getView());
848
+
849
+ this._updateAvailableCards([]);
779
850
  }
780
851
  // we are clearing any previous data from recommendations every time we come to new OP
781
852
  // so that cached recommendations are not shown to user
@@ -786,11 +857,10 @@ class ObjectPageController extends PageController {
786
857
  return;
787
858
  });
788
859
  }
789
- this._updateAvailableCards([]);
790
860
  this.displayCollaborationMessage(mParameters?.redirectedToNonDraft);
791
861
  this._setOPMessageStripInternalContext();
792
862
 
793
- const applyAppState = this.getAppComponent().getAppStateHandler().applyAppState(view.getId(), view);
863
+ const applyAppState = this.getAppComponent().getAppStateHandler().applyAppState(view);
794
864
  this.pageReady.waitFor(applyAppState);
795
865
  }
796
866
 
@@ -982,11 +1052,12 @@ class ObjectPageController extends PageController {
982
1052
  const appComponent = this.getAppComponent();
983
1053
  const rootViewController = appComponent.getRootViewController();
984
1054
  const fnClearCacheTitle = (): void => {
985
- rootViewController.clearTitleHierarchyCache(oObjectPage.getBindingContext()?.getPath() as string);
1055
+ rootViewController.invalidateTitleHierarchyCache(oObjectPage.getBindingContext()?.getPath() as string);
986
1056
  };
987
- if (oObjectPageSubtitle && !this.clearTitleHierarchyCacheSetUp) {
988
- oObjectPageSubtitle.getBinding("value")?.attachChange(fnClearCacheTitle, this);
989
- this.clearTitleHierarchyCacheSetUp = true;
1057
+ if ((oObjectPageDescription || oObjectPageSubtitle) && !this.invalidateTitleHierarchyCacheSetUp) {
1058
+ oObjectPageSubtitle?.getBinding("value")?.attachChange(fnClearCacheTitle, this);
1059
+ oObjectPageDescription?.getBinding("value")?.attachChange(fnClearCacheTitle, this);
1060
+ this.invalidateTitleHierarchyCacheSetUp = true;
990
1061
  }
991
1062
  const oObjectPageContext = oObjectPage.getBindingContext();
992
1063
  const build = (): { title: string; subtitle: string; intent: string; icon: string; description: string } => ({
@@ -1650,6 +1721,86 @@ class ObjectPageController extends PageController {
1650
1721
  }
1651
1722
  }
1652
1723
 
1724
+ _findSummarizeButton(): Button | undefined {
1725
+ const objectPage = this._getObjectPageLayoutControl();
1726
+ const objectPageTitle = objectPage.getHeaderTitle() as ObjectPageDynamicHeaderTitle;
1727
+ const actions = objectPageTitle?.getActions();
1728
+ let summarizeButton: Button | undefined;
1729
+
1730
+ for (const action of actions) {
1731
+ if (action.isA<SummarizationButton>("sap.fe.macros.ai.SummarizationButton")) {
1732
+ const button = action.getContent() as Button | undefined;
1733
+ if (button && button.getId().endsWith("::Summarize::button")) {
1734
+ summarizeButton = button;
1735
+ break;
1736
+ }
1737
+ }
1738
+ }
1739
+
1740
+ return summarizeButton;
1741
+ }
1742
+
1743
+ /**
1744
+ * Evaluates startup parameters and triggers the smart summary action on the Object Page if required.
1745
+ *
1746
+ * This method checks whether the startup parameters indicate that a smart summary should be performed for the current Object Page level.
1747
+ * The level parameter determines which Object Page should be summarized, which is relevant in Flexible Column Layout (FCL) scenarios where
1748
+ * multiple Object Pages may be displayed simultaneously.
1749
+ * If no level is provided in the startup parameters, the method defaults the level to 1.
1750
+ * If the summary action is allowed and the SmartSummarize capability is available, it locates the summarize button and triggers its press event.
1751
+ * The method ensures the summary is only executed once per navigation and logs errors if prerequisites are not met or the button is unavailable.
1752
+ * All errors encountered during the process are caught and logged.
1753
+ * @private
1754
+ */
1755
+ _handleSmartSummaryStartupAction(): void {
1756
+ const appComponent = this.getAppComponent();
1757
+ appComponent
1758
+ ?.getStartupParameters()
1759
+ ?.then((startupParams: StartupParameters) => {
1760
+ if (!startupParams.preferredAction || !startupParams.preferredAction[0].startsWith("summary")) {
1761
+ return;
1762
+ }
1763
+
1764
+ // check if we are on the correct OP by checking the level provided in the startup parameters
1765
+ const viewLevel = this.getView().getViewData().viewLevel;
1766
+ const preferredActionLevel =
1767
+ startupParams.preferredAction[0] === "summary" ? 1 : parseInt(startupParams.preferredAction[0].split("-")[1], 10);
1768
+ if (isNaN(preferredActionLevel) || viewLevel !== preferredActionLevel) {
1769
+ return;
1770
+ }
1771
+
1772
+ // Check if summary action shall be executed now (it might have already been executed by a higher level OP)
1773
+ if (appComponent.getPreferredActionStatus() === PreferredActionStatus.CanPerform) {
1774
+ appComponent.setPreferredActionStatus(PreferredActionStatus.AlreadyPerformed); // to prevent other OPs on higher levels to execute the summary again
1775
+ } else {
1776
+ return;
1777
+ }
1778
+
1779
+ // Check if SmartSummarize capability is available
1780
+ const environmentService = appComponent.getEnvironmentCapabilities();
1781
+ if (!environmentService?.environmentCapabilities.SmartSummarize) {
1782
+ Log.error("Smart Summarization was not triggered because SmartSummarize capability is not available");
1783
+ return;
1784
+ }
1785
+
1786
+ // Find the Summary button
1787
+ const summarizeButton = this._findSummarizeButton();
1788
+
1789
+ if (summarizeButton && summarizeButton.getVisible() && summarizeButton.getEnabled()) {
1790
+ summarizeButton.firePress();
1791
+ return;
1792
+ } else {
1793
+ Log.error(
1794
+ "Smart Summarization was not triggered because the Summarize button is either not visible or not enabled or not found."
1795
+ );
1796
+ return;
1797
+ }
1798
+ })
1799
+ .catch((error: unknown) => {
1800
+ Log.error("Error while retrieving startup parameters or triggering smart summary:", error as string);
1801
+ });
1802
+ }
1803
+
1653
1804
  handlers = {
1654
1805
  onPrimaryAction(
1655
1806
  oController: ObjectPageController,
@@ -1765,6 +1916,7 @@ class ObjectPageController extends PageController {
1765
1916
  notApplicableContexts?: ODataV4Context[];
1766
1917
  enableAutoScroll?: boolean;
1767
1918
  defaultValuesExtensionFunction?: string;
1919
+ disableStrictHandling?: boolean;
1768
1920
  }
1769
1921
  ): Promise<unknown> {
1770
1922
  const oController = oView.getController() as ObjectPageController;