@sapui5/sap.fe.templates 1.146.0 → 1.147.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 (81) 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 +45 -10
  7. package/src/sap/fe/templates/ListReport/ListReportController.controller.js +40 -3
  8. package/src/sap/fe/templates/ListReport/ListReportController.controller.ts +49 -3
  9. package/src/sap/fe/templates/ListReport/ListReportTemplating.js +39 -3
  10. package/src/sap/fe/templates/ListReport/ListReportTemplating.ts +35 -1
  11. package/src/sap/fe/templates/ListReport/manifest.json +1 -1
  12. package/src/sap/fe/templates/ListReport/overrides/MessageHandler.js +3 -2
  13. package/src/sap/fe/templates/ListReport/overrides/MessageHandler.ts +2 -1
  14. package/src/sap/fe/templates/ObjectPage/Component.js +4 -2
  15. package/src/sap/fe/templates/ObjectPage/Component.ts +3 -1
  16. package/src/sap/fe/templates/ObjectPage/ExtensionAPI.js +30 -5
  17. package/src/sap/fe/templates/ObjectPage/ExtensionAPI.ts +31 -4
  18. package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.js +78 -19
  19. package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.ts +91 -23
  20. package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.js +24 -13
  21. package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.ts +32 -27
  22. package/src/sap/fe/templates/ObjectPage/manifest.json +1 -1
  23. package/src/sap/fe/templates/ObjectPage/overrides/Share.js +2 -2
  24. package/src/sap/fe/templates/ObjectPage/overrides/Share.ts +1 -1
  25. package/src/sap/fe/templates/ObjectPage/view/fragments/Actions.fragment.xml +12 -2
  26. package/src/sap/fe/templates/ObjectPage/view/fragments/EmphasizedFirstHeaderAction.fragment.xml +181 -0
  27. package/src/sap/fe/templates/ObjectPage/view/fragments/Section.fragment.xml +2 -0
  28. package/src/sap/fe/templates/ObjectPage/view/fragments/SectionContent.fragment.xml +18 -12
  29. package/src/sap/fe/templates/ObjectPage/view/fragments/SectionFormContent.fragment.xml +2 -0
  30. package/src/sap/fe/templates/ObjectPage/view/fragments/SectionMoreFormContent.fragment.xml +2 -0
  31. package/src/sap/fe/templates/library.js +1 -1
  32. package/src/sap/fe/templates/messagebundle.properties +1 -1
  33. package/src/sap/fe/templates/messagebundle_ar.properties +1 -1
  34. package/src/sap/fe/templates/messagebundle_bg.properties +1 -1
  35. package/src/sap/fe/templates/messagebundle_ca.properties +1 -1
  36. package/src/sap/fe/templates/messagebundle_cnr.properties +1 -1
  37. package/src/sap/fe/templates/messagebundle_cs.properties +1 -1
  38. package/src/sap/fe/templates/messagebundle_cy.properties +1 -1
  39. package/src/sap/fe/templates/messagebundle_da.properties +1 -1
  40. package/src/sap/fe/templates/messagebundle_de.properties +1 -1
  41. package/src/sap/fe/templates/messagebundle_el.properties +1 -1
  42. package/src/sap/fe/templates/messagebundle_en.properties +1 -1
  43. package/src/sap/fe/templates/messagebundle_en_GB.properties +1 -1
  44. package/src/sap/fe/templates/messagebundle_en_US_saprigi.properties +1 -1
  45. package/src/sap/fe/templates/messagebundle_es.properties +1 -1
  46. package/src/sap/fe/templates/messagebundle_es_MX.properties +1 -1
  47. package/src/sap/fe/templates/messagebundle_et.properties +1 -1
  48. package/src/sap/fe/templates/messagebundle_fi.properties +1 -1
  49. package/src/sap/fe/templates/messagebundle_fr.properties +1 -1
  50. package/src/sap/fe/templates/messagebundle_fr_CA.properties +1 -1
  51. package/src/sap/fe/templates/messagebundle_hi.properties +1 -1
  52. package/src/sap/fe/templates/messagebundle_hr.properties +1 -1
  53. package/src/sap/fe/templates/messagebundle_hu.properties +1 -1
  54. package/src/sap/fe/templates/messagebundle_id.properties +1 -1
  55. package/src/sap/fe/templates/messagebundle_it.properties +1 -1
  56. package/src/sap/fe/templates/messagebundle_iw.properties +2 -2
  57. package/src/sap/fe/templates/messagebundle_ja.properties +1 -1
  58. package/src/sap/fe/templates/messagebundle_kk.properties +1 -1
  59. package/src/sap/fe/templates/messagebundle_ko.properties +1 -1
  60. package/src/sap/fe/templates/messagebundle_lt.properties +1 -1
  61. package/src/sap/fe/templates/messagebundle_lv.properties +1 -1
  62. package/src/sap/fe/templates/messagebundle_mk.properties +1 -1
  63. package/src/sap/fe/templates/messagebundle_ms.properties +1 -1
  64. package/src/sap/fe/templates/messagebundle_nl.properties +1 -1
  65. package/src/sap/fe/templates/messagebundle_no.properties +1 -1
  66. package/src/sap/fe/templates/messagebundle_pl.properties +1 -1
  67. package/src/sap/fe/templates/messagebundle_pt.properties +1 -1
  68. package/src/sap/fe/templates/messagebundle_pt_PT.properties +1 -1
  69. package/src/sap/fe/templates/messagebundle_ro.properties +1 -1
  70. package/src/sap/fe/templates/messagebundle_ru.properties +1 -1
  71. package/src/sap/fe/templates/messagebundle_sh.properties +1 -1
  72. package/src/sap/fe/templates/messagebundle_sk.properties +1 -1
  73. package/src/sap/fe/templates/messagebundle_sl.properties +1 -1
  74. package/src/sap/fe/templates/messagebundle_sr.properties +1 -1
  75. package/src/sap/fe/templates/messagebundle_sv.properties +1 -1
  76. package/src/sap/fe/templates/messagebundle_th.properties +1 -1
  77. package/src/sap/fe/templates/messagebundle_tr.properties +1 -1
  78. package/src/sap/fe/templates/messagebundle_uk.properties +3 -3
  79. package/src/sap/fe/templates/messagebundle_vi.properties +1 -1
  80. package/src/sap/fe/templates/messagebundle_zh_CN.properties +1 -1
  81. package/src/sap/fe/templates/messagebundle_zh_TW.properties +1 -1
@@ -52,13 +52,16 @@ import TableScroller from "sap/fe/templates/TableScroller";
52
52
  import type Button from "sap/m/Button";
53
53
  import type InputBase from "sap/m/InputBase";
54
54
  import InstanceManager from "sap/m/InstanceManager";
55
+ import type MenuButton from "sap/m/MenuButton";
55
56
  import type NavContainer from "sap/m/NavContainer";
56
57
  import type Popover from "sap/m/Popover";
57
58
  import type ToolbarSpacer from "sap/m/ToolbarSpacer";
58
59
  import Device from "sap/ui/Device";
59
60
  import type UI5Event from "sap/ui/base/Event";
61
+ import type ManagedObject from "sap/ui/base/ManagedObject";
60
62
  import type { CommandExecution$ExecuteEvent } from "sap/ui/core/CommandExecution";
61
63
  import type Control from "sap/ui/core/Control";
64
+ import type CustomData from "sap/ui/core/CustomData";
62
65
  import UI5Element from "sap/ui/core/Element";
63
66
  import type InvisibleText from "sap/ui/core/InvisibleText";
64
67
  import Library from "sap/ui/core/Lib";
@@ -186,6 +189,37 @@ class ObjectPageController extends PageController {
186
189
 
187
190
  private previousBindingContextPath?: string;
188
191
 
192
+ /**
193
+ * Returns controls (Button / MenuButton) that are marked as "primary action".
194
+ * The marker is set by the converters when an action is emphasized (annotation-based) or
195
+ * configured as primaryAction (custom action defined in the manifest).
196
+ * @param root Root control to start the search from
197
+ * @param onlyActionable If true, only actionable (enabled) candidates are returned
198
+ * @returns An array of controls that are candidates for primary action shortcuts
199
+ */
200
+ private _getPrimaryActionShortcutCandidates(root: ManagedObject, onlyActionable = false): Array<Button | MenuButton> {
201
+ return root.findAggregatedObjects(true, (object: ManagedObject) => {
202
+ const isButton = object.isA("sap.m.Button");
203
+ const isMenuButton = object.isA("sap.m.MenuButton");
204
+ if (!isButton && !isMenuButton) {
205
+ return false;
206
+ }
207
+ const ctrl = object as Button | MenuButton;
208
+ const flag = ctrl
209
+ .getCustomData()
210
+ .find((customData: CustomData) => customData.getKey() === "fePrimaryActionShortcut")
211
+ ?.getValue();
212
+ if (flag !== true && flag !== "true") {
213
+ return false;
214
+ }
215
+ if (!ctrl.getVisible()) {
216
+ return false;
217
+ }
218
+ // For focus placement we must ignore disabled candidates.
219
+ return onlyActionable ? ctrl.getEnabled() : true;
220
+ }) as Array<Button | MenuButton>;
221
+ }
222
+
189
223
  @publicExtension()
190
224
  @finalExtension()
191
225
  getExtensionAPI(sId?: string): ExtensionAPI {
@@ -298,12 +332,13 @@ class ObjectPageController extends PageController {
298
332
  }
299
333
 
300
334
  /**
301
- * Find the last visible subsection and add the sapUxAPObjectPageSubSectionFitContainer CSS class if it contains only a GridTable or a TreeTable.
335
+ * Add the sapUxAPObjectPageSubSectionFitContainer CSS class to every visible subsection that contains only a single GridTable or TreeTable.
336
+ * This makes the table fill the full height of its container so that the scrollbar appears on the table itself rather than on the page.
302
337
  * @param subSections The sub sections to look for
303
338
  */
304
339
  private checkSectionsForNonResponsiveTable(subSections: ObjectPageSubSection[]): void {
305
- const changeClassForTables = (event: Event, lastVisibleSubSection: ObjectPageSubSection): void => {
306
- const blocks = [...lastVisibleSubSection.getBlocks(), ...lastVisibleSubSection.getMoreBlocks()];
340
+ const changeClassForTables = (event: Event, visibleSubSection: ObjectPageSubSection): void => {
341
+ const blocks = [...visibleSubSection.getBlocks(), ...visibleSubSection.getMoreBlocks()];
307
342
  if (blocks.length === 1) {
308
343
  const table = this.searchTableInBlock(blocks[0] as SubSectionBlock);
309
344
  if (!table) {
@@ -317,17 +352,15 @@ class ObjectPageController extends PageController {
317
352
  tableAPI?.getTableDefinition().control.rowCountMode === "Auto"
318
353
  ) {
319
354
  //In case there is only a single table in a subSection we fit that to the whole page so that the scrollbar comes only on table and not on page
320
- lastVisibleSubSection.addStyleClass("sapUxAPObjectPageSubSectionFitContainer");
321
- lastVisibleSubSection.detachEvent("modelContextChange", changeClassForTables, this);
355
+ visibleSubSection.addStyleClass("sapUxAPObjectPageSubSectionFitContainer");
356
+ visibleSubSection.detachEvent("modelContextChange", changeClassForTables, this);
322
357
  }
323
358
  }
324
359
  };
325
- for (let subSectionIndex = subSections.length - 1; subSectionIndex >= 0; subSectionIndex--) {
326
- if (subSections[subSectionIndex].getVisible()) {
327
- const lastVisibleSubSection = subSections[subSectionIndex];
360
+ for (const subSection of subSections) {
361
+ if (subSection.getVisible()) {
328
362
  // We need to attach this event in order to manage the Object Page Lazy Loading mechanism
329
- lastVisibleSubSection.attachEvent("modelContextChange", lastVisibleSubSection, changeClassForTables, this);
330
- break;
363
+ subSection.attachEvent("modelContextChange", subSection, changeClassForTables, this);
331
364
  }
332
365
  }
333
366
  }
@@ -507,12 +540,21 @@ class ObjectPageController extends PageController {
507
540
  }
508
541
 
509
542
  /**
510
- * Get the first clickable element in the header of the object page.
543
+ * Get the first clickable element in the object page.
511
544
  * @private
512
545
  * @param objectPage Object Page Layout control
513
- * @returns The first clickable element found in the header
546
+ * @returns The first clickable element found
514
547
  */
515
548
  private getFirstClickableElement(objectPage: ObjectPageLayout): UI5Element | undefined {
549
+ // In display mode, if a visible primary action with the emphasis exists in the footer, it must be the first clickable element on the page.
550
+ const footer = objectPage.getFooter();
551
+ const footerPrimaryAction = footer
552
+ ? this._getPrimaryActionShortcutCandidates(footer as unknown as ManagedObject, true)[0]
553
+ : undefined;
554
+ if (footerPrimaryAction) {
555
+ return footerPrimaryAction;
556
+ }
557
+ // Fallback: first visible & enabled header action (Edit, etc.)
516
558
  let firstClickableElement;
517
559
  const actions = objectPage.getHeaderTitle() && (objectPage.getHeaderTitle() as ObjectPageDynamicHeaderTitle).getActions();
518
560
  if (actions?.length) {
@@ -775,11 +817,14 @@ class ObjectPageController extends PageController {
775
817
  }
776
818
 
777
819
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
778
- _onAfterBinding(inputBindingContext: Context | undefined, mParameters: BindingParams | undefined): void {
820
+ _onAfterBinding(inputBindingContext: ODataV4Context | undefined, mParameters: BindingParams | undefined): void {
779
821
  const view = this.getView();
780
822
  const viewLevel = view?.getViewData()?.viewLevel;
781
823
  const oObjectPage = this._getObjectPageLayoutControl();
782
824
  const aTables = this._findTables();
825
+ if ([NavigationReason.EditFlowAction, NavigationReason.RowPress].includes(mParameters?.reason as NavigationReason)) {
826
+ this.editFlow.storeSiblingContextData(inputBindingContext);
827
+ }
783
828
 
784
829
  this._sideEffects.clearFieldGroupsValidity();
785
830
 
@@ -1415,10 +1460,11 @@ class ObjectPageController extends PageController {
1415
1460
  );
1416
1461
  }
1417
1462
  });
1418
- const isSkipBindingToView = skipBindingToView as unknown as CommandExecution$ExecuteEvent;
1419
- const isStandardSave =
1420
- isSkipBindingToView && typeof isSkipBindingToView == "object" && isSkipBindingToView.getSource().getCommand() === "Save";
1421
-
1463
+ let isStandardSave: boolean | undefined;
1464
+ if (skipBindingToView && typeof skipBindingToView === "object") {
1465
+ const command = (skipBindingToView as CommandExecution$ExecuteEvent)?.getSource?.()?.getCommand?.();
1466
+ isStandardSave = command === "Save";
1467
+ }
1422
1468
  const bindings = await Promise.all(awaitCreateDocuments);
1423
1469
  // We need to either reject or resolve a promise here and return it since this save
1424
1470
  // function is not only called when pressing the save button in the footer, but also
@@ -1961,8 +2007,27 @@ class ObjectPageController extends PageController {
1961
2007
  }
1962
2008
  ): void {
1963
2009
  /**
1964
- * Invokes the page primary action on press of Ctrl+Enter.
2010
+ * Invokes the page primary action when the user presses Ctrl+Enter (Cmd+Enter on macOS).
1965
2011
  */
2012
+
2013
+ const primaryCandidate = oController._getPrimaryActionShortcutCandidates(oView)[0];
2014
+
2015
+ /* By design, there must be at most one candidate due to the "single emphasis per page" rule.
2016
+ If a primary-enter target is found, it must fully take over Ctrl/Cmd+Enter.*/
2017
+
2018
+ if (primaryCandidate) {
2019
+ if (!primaryCandidate.getEnabled()) {
2020
+ // Take over Ctrl/Cmd+Enter, but do not trigger anything when the primary action is disabled.
2021
+ return;
2022
+ }
2023
+ if (primaryCandidate.isA("sap.m.Button")) {
2024
+ (primaryCandidate as Button).firePress();
2025
+ }
2026
+ if ((primaryCandidate as MenuButton).isA("sap.m.MenuButton")) {
2027
+ (primaryCandidate as MenuButton).fireDefaultAction();
2028
+ }
2029
+ return;
2030
+ }
1966
2031
  const iViewLevel = oController.getView().getViewData().viewLevel;
1967
2032
  if (mConditions.positiveActionVisible) {
1968
2033
  if (mConditions.positiveActionEnabled) {
@@ -1990,7 +2055,7 @@ class ObjectPageController extends PageController {
1990
2055
  const tableAPI = event.getSource();
1991
2056
  const table = tableAPI.content;
1992
2057
  const currentActionPromise = this.editFlow.getCurrentActionPromise();
1993
- const tableContexts = this._getTableBinding(table)?.getCurrentContexts();
2058
+ const tableContexts = this._getTableBinding(table)?.getAllCurrentContexts();
1994
2059
 
1995
2060
  if (currentActionPromise && tableContexts?.length) {
1996
2061
  try {
@@ -1998,10 +2063,13 @@ class ObjectPageController extends PageController {
1998
2063
  if (actionResponse?.controlId === table.getId()) {
1999
2064
  const actionData = actionResponse.oData;
2000
2065
  const keys = actionResponse.keys;
2001
- const newItem = tableContexts.findIndex((tableContext: Context) => {
2002
- const tableData = tableContext.getObject();
2003
- return keys.every((key: string) => tableData[key] === actionData[key]);
2004
- });
2066
+ const newItem =
2067
+ tableContexts
2068
+ .find((tableContext: Context) => {
2069
+ const tableData = tableContext.getObject();
2070
+ return keys.every((key: string) => tableData[key] === actionData[key]);
2071
+ })
2072
+ ?.getIndex() ?? -1;
2005
2073
  if (newItem !== -1) {
2006
2074
  const dialog = InstanceManager.getOpenDialogs().find((dialog) => dialog.data("FullScreenDialog") !== true);
2007
2075
  if (dialog) {