@sapui5/sap.fe.templates 1.106.0 → 1.108.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 (55) hide show
  1. package/package.json +3 -2
  2. package/src/sap/fe/templates/.library +1 -1
  3. package/src/sap/fe/templates/ListComponent.js +5 -1
  4. package/src/sap/fe/templates/ListComponent.ts +4 -0
  5. package/src/sap/fe/templates/ListReport/ExtensionAPI.js +43 -3
  6. package/src/sap/fe/templates/ListReport/ExtensionAPI.ts +38 -2
  7. package/src/sap/fe/templates/ListReport/ListReport.view.xml +12 -1
  8. package/src/sap/fe/templates/ListReport/ListReportController.controller.js +80 -22
  9. package/src/sap/fe/templates/ListReport/ListReportController.controller.ts +63 -14
  10. package/src/sap/fe/templates/ListReport/controls/MultipleModeControl.js +30 -21
  11. package/src/sap/fe/templates/ListReport/controls/MultipleModeControl.ts +21 -10
  12. package/src/sap/fe/templates/ListReport/overrides/IntentBasedNavigation.js +4 -7
  13. package/src/sap/fe/templates/ListReport/overrides/IntentBasedNavigation.ts +2 -6
  14. package/src/sap/fe/templates/ListReport/overrides/Share.js +9 -14
  15. package/src/sap/fe/templates/ListReport/overrides/Share.ts +8 -15
  16. package/src/sap/fe/templates/ListReport/overrides/ViewState.js +15 -11
  17. package/src/sap/fe/templates/ListReport/overrides/ViewState.ts +27 -9
  18. package/src/sap/fe/templates/ListReport/view/fragments/MultipleMode.fragment.js +3 -3
  19. package/src/sap/fe/templates/ListReport/view/fragments/MultipleMode.fragment.ts +2 -2
  20. package/src/sap/fe/templates/ListReport/view/fragments/Table.fragment.xml +0 -1
  21. package/src/sap/fe/templates/ObjectPage/ExtensionAPI.js +132 -3
  22. package/src/sap/fe/templates/ObjectPage/ExtensionAPI.ts +88 -1
  23. package/src/sap/fe/templates/ObjectPage/ObjectPage.view.xml +35 -47
  24. package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.js +286 -45
  25. package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.ts +209 -32
  26. package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.js +49 -7
  27. package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.ts +60 -5
  28. package/src/sap/fe/templates/ObjectPage/designtime/StashableHBox.designtime.js +1 -1
  29. package/src/sap/fe/templates/ObjectPage/designtime/StashableHBox.designtime.ts +1 -2
  30. package/src/sap/fe/templates/ObjectPage/designtime/StashableVBox.designtime.js +1 -1
  31. package/src/sap/fe/templates/ObjectPage/designtime/StashableVBox.designtime.ts +1 -2
  32. package/src/sap/fe/templates/ObjectPage/flexibility/ScrollableHeaderContainer.flexibility.js +33 -0
  33. package/src/sap/fe/templates/ObjectPage/flexibility/ScrollableHeaderContainer.flexibility.ts +23 -0
  34. package/src/sap/fe/templates/ObjectPage/manifest.json +8 -0
  35. package/src/sap/fe/templates/ObjectPage/overrides/MessageHandler.js +2 -2
  36. package/src/sap/fe/templates/ObjectPage/overrides/MessageHandler.ts +2 -1
  37. package/src/sap/fe/templates/ObjectPage/overrides/Share.js +10 -3
  38. package/src/sap/fe/templates/ObjectPage/overrides/Share.ts +8 -1
  39. package/src/sap/fe/templates/ObjectPage/overrides/ViewState.js +7 -1
  40. package/src/sap/fe/templates/ObjectPage/overrides/ViewState.ts +5 -0
  41. package/src/sap/fe/templates/ObjectPage/view/fragments/Actions.fragment.xml +8 -2
  42. package/src/sap/fe/templates/ObjectPage/view/fragments/HeaderContent.fragment.xml +38 -23
  43. package/src/sap/fe/templates/ObjectPage/view/fragments/HeadingContent.fragment.xml +30 -0
  44. package/src/sap/fe/templates/ObjectPage/view/fragments/MacroChart.fragment.xml +1 -0
  45. package/src/sap/fe/templates/ObjectPage/view/fragments/Table.fragment.xml +1 -0
  46. package/src/sap/fe/templates/library.js +1 -1
  47. package/src/sap/fe/templates/messagebundle_lt.properties +1 -1
  48. package/src/sap/fe/templates/RootContainer/controller/Fcl.controller.js +0 -899
  49. package/src/sap/fe/templates/RootContainer/controller/Fcl.controller.ts +0 -830
  50. package/src/sap/fe/templates/RootContainer/controller/NavContainer.controller.js +0 -207
  51. package/src/sap/fe/templates/RootContainer/controller/NavContainer.controller.ts +0 -177
  52. package/src/sap/fe/templates/RootContainer/controller/RootContainerBaseController.js +0 -575
  53. package/src/sap/fe/templates/RootContainer/controller/RootContainerBaseController.ts +0 -492
  54. package/src/sap/fe/templates/RootContainer/view/Fcl.view.xml +0 -16
  55. package/src/sap/fe/templates/RootContainer/view/NavContainer.view.xml +0 -9
@@ -4,7 +4,7 @@ import merge from "sap/base/util/merge";
4
4
  import ActionRuntime from "sap/fe/core/ActionRuntime";
5
5
  import CommonUtils from "sap/fe/core/CommonUtils";
6
6
  import BusyLocker from "sap/fe/core/controllerextensions/BusyLocker";
7
- import { connect } from "sap/fe/core/controllerextensions/collaboration/ActivitySync";
7
+ import { connect, disconnect, isConnected } from "sap/fe/core/controllerextensions/collaboration/ActivitySync";
8
8
  import { openManageDialog, showUserDetails } from "sap/fe/core/controllerextensions/collaboration/Manage";
9
9
  import EditFlow from "sap/fe/core/controllerextensions/EditFlow";
10
10
  import draft from "sap/fe/core/controllerextensions/editFlow/draft";
@@ -19,10 +19,13 @@ import Paginator from "sap/fe/core/controllerextensions/Paginator";
19
19
  import Placeholder from "sap/fe/core/controllerextensions/Placeholder";
20
20
  import Share from "sap/fe/core/controllerextensions/Share";
21
21
  import ViewState from "sap/fe/core/controllerextensions/ViewState";
22
+ import * as MetaModelConverter from "sap/fe/core/converters/MetaModelConverter";
22
23
  import { defineUI5Class, extensible, finalExtension, publicExtension, usingExtension } from "sap/fe/core/helpers/ClassSupport";
23
24
  import type { InternalModelContext } from "sap/fe/core/helpers/ModelHelper";
24
25
  import ModelHelper from "sap/fe/core/helpers/ModelHelper";
25
26
  import PageController from "sap/fe/core/PageController";
27
+ import type RootContainerBaseController from "sap/fe/core/rootView/RootViewBaseController";
28
+ import RootViewBaseController from "sap/fe/core/rootView/RootViewBaseController";
26
29
  import ChartRuntime from "sap/fe/macros/chart/ChartRuntime";
27
30
  import CommonHelper from "sap/fe/macros/CommonHelper";
28
31
  import DelegateUtil from "sap/fe/macros/DelegateUtil";
@@ -30,7 +33,6 @@ import TableUtils from "sap/fe/macros/table/Utils";
30
33
  import SelectionVariant from "sap/fe/navigation/SelectionVariant";
31
34
  import type { default as ObjectPageExtensionAPI } from "sap/fe/templates/ObjectPage/ExtensionAPI";
32
35
  import { default as ExtensionAPI } from "sap/fe/templates/ObjectPage/ExtensionAPI";
33
- import type RootContainerBaseController from "sap/fe/templates/RootContainer/controller/RootContainerBaseController";
34
36
  import EditFlowOverrides from "sap/fe/templates/RootContainer/overrides/EditFlow";
35
37
  import TableScroller from "sap/fe/templates/TableScroller";
36
38
  import InstanceManager from "sap/m/InstanceManager";
@@ -38,7 +40,9 @@ import Link from "sap/m/Link";
38
40
  import MessageBox from "sap/m/MessageBox";
39
41
  import type Popover from "sap/m/Popover";
40
42
  import Core from "sap/ui/core/Core";
43
+ import Message from "sap/ui/core/message/Message";
41
44
  import OverrideExecution from "sap/ui/core/mvc/OverrideExecution";
45
+ import type View from "sap/ui/core/mvc/View";
42
46
  import type Binding from "sap/ui/model/Binding";
43
47
  import type JSONModel from "sap/ui/model/json/JSONModel";
44
48
  import type Context from "sap/ui/model/odata/v4/Context";
@@ -51,6 +55,7 @@ import type ObjectPageDynamicHeaderTitle from "sap/uxap/ObjectPageDynamicHeaderT
51
55
  import type ObjectPageLayout from "sap/uxap/ObjectPageLayout";
52
56
  import type ObjectPageSection from "sap/uxap/ObjectPageSection";
53
57
  import type ObjectPageSubSection from "sap/uxap/ObjectPageSubSection";
58
+ import type { ODataContextBindingEx, V4Context } from "types/extension_types";
54
59
  import IntentBasedNavigationOverride from "./overrides/IntentBasedNavigation";
55
60
  import InternalRoutingOverride from "./overrides/InternalRouting";
56
61
  import MessageHandlerOverride from "./overrides/MessageHandler";
@@ -101,11 +106,12 @@ class ObjectPageController extends PageController {
101
106
  @usingExtension(MassEdit)
102
107
  massEdit!: MassEdit;
103
108
  private mCustomSectionExtensionAPIs?: Record<string, ObjectPageExtensionAPI>;
104
- private extensionAPI?: ObjectPageExtensionAPI;
109
+ protected extensionAPI?: ObjectPageExtensionAPI;
105
110
  private oResourceBundle?: ResourceBundle;
106
111
  private bSectionNavigated?: boolean;
107
112
  private switchDraftAndActivePopOver?: Popover;
108
113
  private currentBinding?: Binding;
114
+ private messageButton: any;
109
115
 
110
116
  @publicExtension()
111
117
  @finalExtension()
@@ -132,17 +138,19 @@ class ObjectPageController extends PageController {
132
138
 
133
139
  // Setting defaults of internal model context
134
140
  const oInternalModelContext = this.getView().getBindingContext("internal") as InternalModelContext;
135
- oInternalModelContext.setProperty("externalNavigationContext", { "page": true });
136
- oInternalModelContext.setProperty("relatedApps", {
141
+ oInternalModelContext?.setProperty("externalNavigationContext", { "page": true });
142
+ oInternalModelContext?.setProperty("relatedApps", {
137
143
  visibility: false,
138
144
  items: null
139
145
  });
140
- oInternalModelContext.setProperty("batchGroups", this._getBatchGroupsForView());
141
- oInternalModelContext.setProperty("errorNavigationSectionFlag", false);
146
+ oInternalModelContext?.setProperty("batchGroups", this._getBatchGroupsForView());
147
+ oInternalModelContext?.setProperty("errorNavigationSectionFlag", false);
142
148
  if (!(this.getView().getViewData() as any).useNewLazyLoading && (oObjectPage as any).getEnableLazyLoading()) {
143
149
  //Attaching the event to make the subsection context binding active when it is visible.
144
150
  oObjectPage.attachEvent("subSectionEnteredViewPort", this._handleSubSectionEnteredViewPort.bind(this));
145
151
  }
152
+ this.messageButton = this.getView().byId("fe::FooterBar::MessageButton");
153
+ this.messageButton.oItemBinding.attachChange(this._fnShowOPMessage, this);
146
154
  }
147
155
 
148
156
  onExit() {
@@ -159,8 +167,7 @@ class ObjectPageController extends PageController {
159
167
  }
160
168
  delete this.extensionAPI;
161
169
 
162
- const oMessageButton = this.getView().byId("fe::FooterBar::MessageButton"),
163
- oMessagePopover = oMessageButton ? (oMessageButton as any).oMessagePopover : null;
170
+ const oMessagePopover = this.messageButton ? this.messageButton.oMessagePopover : null;
164
171
  if (oMessagePopover && oMessagePopover.isOpen()) {
165
172
  oMessagePopover.close();
166
173
  }
@@ -169,6 +176,29 @@ class ObjectPageController extends PageController {
169
176
  if (oContext && oContext.isKeepAlive()) {
170
177
  oContext.setKeepAlive(false);
171
178
  }
179
+ if (isConnected(this.getView())) {
180
+ disconnect(this.getView()); // Cleanup collaboration connection when leaving the app
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Method to show the message strip on the object page.
186
+ *
187
+ * @private
188
+ */
189
+ _fnShowOPMessage() {
190
+ const extensionAPI = this.getExtensionAPI();
191
+ const view = this.getView();
192
+ const messages = this.messageButton.oMessagePopover
193
+ .getItems()
194
+ .map((item: any) => item.getBindingContext("message").getObject())
195
+ .filter((message: Message) => {
196
+ return message.getTargets()[0] === view.getBindingContext()?.getPath();
197
+ });
198
+
199
+ if (extensionAPI) {
200
+ extensionAPI.showMessages(messages);
201
+ }
172
202
  }
173
203
 
174
204
  _getTableBinding(oTable: any) {
@@ -319,12 +349,13 @@ class ObjectPageController extends PageController {
319
349
  // Due to the left alignment of the Draft switch and the collaborative draft avatar controls
320
350
  // there is a ToolbarSpacer in the actions aggregation which we need to exclude here!
321
351
  // Due to the ACC report, we also need not to check for the InvisibleText elements
322
- return (
323
- !oAction.isA("sap.ui.core.InvisibleText") &&
324
- !oAction.isA("sap.m.ToolbarSpacer") &&
325
- oAction.getVisible() &&
326
- oAction.getEnabled()
327
- );
352
+ if (oAction.isA("sap.fe.macros.ShareAPI")) {
353
+ // since ShareAPI does not have a disable property
354
+ // hence there is no need to check if it is disbaled or not
355
+ return oAction.getVisible();
356
+ } else if (!oAction.isA("sap.ui.core.InvisibleText") && !oAction.isA("sap.m.ToolbarSpacer")) {
357
+ return oAction.getVisible() && oAction.getEnabled();
358
+ }
328
359
  });
329
360
  }
330
361
  return oFirstClickableElement;
@@ -560,6 +591,8 @@ class ObjectPageController extends PageController {
560
591
  .then(() => {
561
592
  if (this.getView().getModel("ui").getProperty("/isEditable")) {
562
593
  connect(this.getView());
594
+ } else if (isConnected(this.getView())) {
595
+ disconnect(this.getView()); // Cleanup collaboration connection in case we switch to another element (e.g. in FCL)
563
596
  }
564
597
  })
565
598
  .catch(function (oError: any) {
@@ -619,7 +652,9 @@ class ObjectPageController extends PageController {
619
652
  }
620
653
  } else {
621
654
  const oSelectedSection: any = Core.byId(oObjectPage.getSelectedSection());
622
- this._updateFocusInEditMode(oSelectedSection.getSubSections());
655
+ if (oSelectedSection) {
656
+ this._updateFocusInEditMode(oSelectedSection.getSubSections());
657
+ }
623
658
  }
624
659
  };
625
660
  // Apply app state only after the page is ready with the first section selected
@@ -751,7 +786,7 @@ class ObjectPageController extends PageController {
751
786
  ? rootViewController.getRightmostView()
752
787
  : (this.getAppComponent().getRootContainer() as any).getCurrentPage();
753
788
  if (!currentPageView.isA("sap.m.MessagePage")) {
754
- const oMessageButton = this.getView().byId("fe::FooterBar::MessageButton") as any,
789
+ const oMessageButton = this.messageButton,
755
790
  oMessagePopover = oMessageButton.oMessagePopover,
756
791
  oItemBinding = oMessagePopover.getBinding("items");
757
792
 
@@ -773,6 +808,74 @@ class ObjectPageController extends PageController {
773
808
  BusyLocker.unlock(oModel);
774
809
  });
775
810
  }
811
+ /**
812
+ * Gets the context of the DraftRoot path.
813
+ * If a view has been created with the draft Root Path, this method returns its bindingContext.
814
+ * Where no view is found a new created context is returned.
815
+ * The new created context request the key of the entity in order to get the Etag of this entity.
816
+ *
817
+ * @function
818
+ * @name getDraftRootPath
819
+ * @returns Returns a Promise
820
+ */
821
+ async getDraftRootContext(): Promise<V4Context | undefined> {
822
+ const view = this.getView();
823
+ const context = view.getBindingContext() as V4Context;
824
+ if (context) {
825
+ const draftRootContextPath = ModelHelper.getDraftRootPath(context);
826
+ let simpleDraftRootContext: V4Context;
827
+ if (draftRootContextPath) {
828
+ // Check if a view matches with the draft root path
829
+ const existingBindingContextOnPage = (this.getAppComponent().getRootViewController() as RootViewBaseController)
830
+ .getInstancedViews()
831
+ .find((pageView: View) => pageView.getBindingContext()?.getPath() === draftRootContextPath)
832
+ ?.getBindingContext() as V4Context;
833
+ if (existingBindingContextOnPage) {
834
+ return existingBindingContextOnPage;
835
+ }
836
+ const internalModel = view.getModel("internal") as JSONModel;
837
+ simpleDraftRootContext = internalModel.getProperty("/simpleDraftRootContext");
838
+ if (simpleDraftRootContext?.getPath() === draftRootContextPath) {
839
+ return simpleDraftRootContext;
840
+ }
841
+ const model = context.getModel();
842
+ const metaModel = model.getMetaModel();
843
+ const sEntityPath = metaModel.getMetaPath(draftRootContextPath);
844
+ const mDataModel = MetaModelConverter.getInvolvedDataModelObjects(metaModel.getContext(sEntityPath));
845
+ simpleDraftRootContext = model.bindContext(draftRootContextPath).getBoundContext();
846
+ await simpleDraftRootContext.requestProperty(mDataModel.targetEntityType.keys[0]?.name);
847
+ // Store this new created context to use it on the next iterations
848
+ internalModel.setProperty("/simpleDraftRootContext", simpleDraftRootContext);
849
+ return simpleDraftRootContext;
850
+ }
851
+ return undefined;
852
+ }
853
+ return undefined;
854
+ }
855
+
856
+ async _validateDocument(): Promise<void | any[] | ODataContextBindingEx> {
857
+ const control = Core.byId(Core.getCurrentFocusedControlId());
858
+ const context = control?.getBindingContext() as V4Context;
859
+ if (context && !context.isTransient()) {
860
+ // Wait for the pending changes before starting this validation
861
+ await this._editFlow.syncTask();
862
+ const appComponent = this.getAppComponent();
863
+ const sideEffectsService = appComponent.getSideEffectsService();
864
+ const entityType = sideEffectsService.getEntityTypeFromContext(context);
865
+ const globalSideEffects = entityType ? sideEffectsService.getGlobalODataEntitySideEffects(entityType) : [];
866
+ // If there is at least one global SideEffects for the related entity, execute it/them
867
+ if (globalSideEffects.length) {
868
+ return Promise.all(globalSideEffects.map((sideEffects) => this._sideEffects.requestSideEffects(sideEffects, context)));
869
+ } else {
870
+ const draftRootContext = await this.getDraftRootContext();
871
+ //Execute the draftValidation if there is no globalSideEffects
872
+ if (draftRootContext) {
873
+ return draft.executeDraftValidation(draftRootContext, appComponent);
874
+ }
875
+ }
876
+ }
877
+ return undefined;
878
+ }
776
879
 
777
880
  async _saveDocument(oContext: any) {
778
881
  const oModel = this.getView().getModel("ui"),
@@ -856,10 +959,20 @@ class ObjectPageController extends PageController {
856
959
  }
857
960
  }
858
961
 
859
- _findTableInSubSection(aParentElement: any, aSubsection: any, aTables: any) {
962
+ _findControlInSubSection(aParentElement: any, aSubsection: any, aControls: any, bIsChart?: boolean) {
860
963
  const aSubSectionTables = [];
861
964
  for (let element = 0; element < aParentElement.length; element++) {
862
965
  let oElement = aParentElement[element].getContent instanceof Function && aParentElement[element].getContent();
966
+ if (bIsChart) {
967
+ if (oElement && oElement.mAggregations && oElement.getAggregation("items")) {
968
+ const aItems = oElement.getAggregation("items");
969
+ aItems.forEach(function (oItem: any) {
970
+ if (oItem.isA("sap.fe.macros.chart.ChartAPI")) {
971
+ oElement = oItem;
972
+ }
973
+ });
974
+ }
975
+ }
863
976
  if (oElement && oElement.isA && oElement.isA("sap.ui.layout.DynamicSideContent")) {
864
977
  oElement = oElement.getMainContent instanceof Function && oElement.getMainContent();
865
978
  if (oElement && oElement.length > 0) {
@@ -873,12 +986,22 @@ class ObjectPageController extends PageController {
873
986
  }
874
987
  }
875
988
  if (oElement && oElement.isA && oElement.isA("sap.ui.mdc.Table")) {
876
- aTables.push(oElement);
989
+ aControls.push(oElement);
877
990
  aSubSectionTables.push({
878
991
  "table": oElement,
879
992
  "gridTable": oElement.getType().isA("sap.ui.mdc.table.GridTableType")
880
993
  });
881
994
  }
995
+
996
+ if (oElement && oElement.isA && oElement.isA("sap.fe.macros.chart.ChartAPI")) {
997
+ oElement = oElement.getContent instanceof Function && oElement.getContent();
998
+ if (oElement && oElement.length > 0) {
999
+ oElement = oElement[0];
1000
+ }
1001
+ }
1002
+ if (oElement && oElement.isA && oElement.isA("sap.ui.mdc.Chart")) {
1003
+ aControls.push(oElement);
1004
+ }
882
1005
  }
883
1006
  if (
884
1007
  aSubSectionTables.length === 1 &&
@@ -888,13 +1011,6 @@ class ObjectPageController extends PageController {
888
1011
  ) {
889
1012
  //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
890
1013
  aSubsection.addStyleClass("sapUxAPObjectPageSubSectionFitContainer");
891
- } else if (aSubSectionTables && !aSubsection.hasStyleClass("sapUxAPObjectPageSubSectionFitContainer")) {
892
- aSubSectionTables.forEach(function (oTable: { table: any; gridTable: any }) {
893
- if (oTable.gridTable) {
894
- //Resetting the row count to default value in case we have a combination of forms and tables or multiple tables in a subsection
895
- oTable.table.getType().setRowCount(null);
896
- }
897
- });
898
1014
  }
899
1015
  }
900
1016
 
@@ -919,12 +1035,22 @@ class ObjectPageController extends PageController {
919
1035
  const aSubSections = this._getAllSubSections();
920
1036
  const aTables: any[] = [];
921
1037
  for (let subSection = 0; subSection < aSubSections.length; subSection++) {
922
- this._findTableInSubSection(aSubSections[subSection].getBlocks(), aSubSections[subSection], aTables);
923
- this._findTableInSubSection(aSubSections[subSection].getMoreBlocks(), aSubSections[subSection], aTables);
1038
+ this._findControlInSubSection(aSubSections[subSection].getBlocks(), aSubSections[subSection], aTables);
1039
+ this._findControlInSubSection(aSubSections[subSection].getMoreBlocks(), aSubSections[subSection], aTables);
924
1040
  }
925
1041
  return aTables;
926
1042
  }
927
1043
 
1044
+ _findCharts() {
1045
+ const aSubSections = this._getAllSubSections();
1046
+ const aCharts: any[] = [];
1047
+ for (let subSection = 0; subSection < aSubSections.length; subSection++) {
1048
+ this._findControlInSubSection(aSubSections[subSection].getBlocks(), aSubSections[subSection], aCharts, true);
1049
+ this._findControlInSubSection(aSubSections[subSection].getMoreBlocks(), aSubSections[subSection], aCharts, true);
1050
+ }
1051
+ return aCharts;
1052
+ }
1053
+
928
1054
  _closeSideContent() {
929
1055
  this._getAllBlocks().forEach(function (oBlock: any) {
930
1056
  const oContent = oBlock.getContent instanceof Function && oBlock.getContent();
@@ -1097,7 +1223,8 @@ class ObjectPageController extends PageController {
1097
1223
  oLink = oSource.getLinks()[idx] ? oSource.getLinks()[idx] : new Link();
1098
1224
  //sCurrentEntity is a fallback value in case of empty title
1099
1225
  oLink.setText(titleHierarchyInfo.subtitle || titleHierarchyInfo.title);
1100
- oLink.setHref(titleHierarchyInfo.intent);
1226
+ //We apply an additional encodeURI in case of special characters (ie "/") used in the url through the semantic keys
1227
+ oLink.setHref(encodeURI(titleHierarchyInfo.intent));
1101
1228
  if (!oSource.getLinks()[idx]) {
1102
1229
  oSource.addLink(oLink);
1103
1230
  }
@@ -1204,6 +1331,54 @@ class ObjectPageController extends PageController {
1204
1331
  }
1205
1332
 
1206
1333
  handlers = {
1334
+ /**
1335
+ * Invokes the page primary action on press of Ctrl+Enter.
1336
+ *
1337
+ * @param oController The page controller
1338
+ * @param oView
1339
+ * @param oContext Context for which the action is called
1340
+ * @param sActionName The name of the action to be called
1341
+ * @param [mParameters] Contains the following attributes:
1342
+ * @param [mParameters.contexts] Mandatory for a bound action, either one context or an array with contexts for which the action is called
1343
+ * @param [mParameters.model] Mandatory for an unbound action; an instance of an OData V4 model
1344
+ * @param [mConditions] Contains the following attributes:
1345
+ * @param [mConditions.positiveActionVisible] The visibility of sematic positive action
1346
+ * @param [mConditions.positiveActionEnabled] The enablement of semantic positive action
1347
+ * @param [mConditions.editActionVisible] The Edit button visibility
1348
+ * @param [mConditions.editActionEnabled] The enablement of Edit button
1349
+ * @ui5-restricted
1350
+ * @final
1351
+ */
1352
+ onPrimaryAction(
1353
+ oController: ObjectPageController,
1354
+ oView: View,
1355
+ oContext: Context,
1356
+ sActionName: string,
1357
+ mParameters: unknown,
1358
+ mConditions: {
1359
+ positiveActionVisible: boolean;
1360
+ positiveActionEnabled: boolean;
1361
+ editActionVisible: boolean;
1362
+ editActionEnabled: boolean;
1363
+ }
1364
+ ) {
1365
+ const iViewLevel = (oController.getView().getViewData() as any).viewLevel,
1366
+ oObjectPage = oController._getObjectPageLayoutControl();
1367
+ if (mConditions.positiveActionVisible) {
1368
+ if (mConditions.positiveActionEnabled) {
1369
+ oController.handlers.onCallAction(oView, sActionName, mParameters);
1370
+ }
1371
+ } else if (mConditions.editActionVisible && iViewLevel === 1) {
1372
+ if (mConditions.editActionEnabled) {
1373
+ oController._editDocument(oContext);
1374
+ }
1375
+ } else if (iViewLevel === 1 && oObjectPage.getModel("ui").getProperty("/isEditable")) {
1376
+ oController._saveDocument(oContext);
1377
+ } else if (oObjectPage.getModel("ui").getProperty("/isEditable")) {
1378
+ oController._applyDocument(oContext);
1379
+ }
1380
+ },
1381
+
1207
1382
  onTableContextChange(this: ObjectPageController, oEvent: any) {
1208
1383
  const oSource = oEvent.getSource();
1209
1384
  let oTable: any;
@@ -1266,8 +1441,7 @@ class ObjectPageController extends PageController {
1266
1441
  });
1267
1442
  }
1268
1443
  // fire ModelContextChange on the message button whenever the table context changes
1269
- const oMessageButton = this.getView().byId("fe::FooterBar::MessageButton");
1270
- oMessageButton.fireModelContextChange();
1444
+ this.messageButton.fireModelContextChange();
1271
1445
  },
1272
1446
 
1273
1447
  /**
@@ -1276,7 +1450,7 @@ class ObjectPageController extends PageController {
1276
1450
  * @param oView
1277
1451
  * @param sActionName The name of the action to be called
1278
1452
  * @param [mParameters] Contains the following attributes:
1279
- * @param [mParameters.contexts] Mandatory for a bound action, either one context or an array with contexts for which the action shall be called
1453
+ * @param [mParameters.contexts] Mandatory for a bound action, either one context or an array with contexts for which the action is called
1280
1454
  * @param [mParameters.model] Mandatory for an unbound action; an instance of an OData V4 model
1281
1455
  * @returns The action promise
1282
1456
  * @ui5-restricted
@@ -1403,6 +1577,9 @@ class ObjectPageController extends PageController {
1403
1577
  },
1404
1578
  onChartSelectionChanged: function (oEvent: any) {
1405
1579
  ChartRuntime.fnUpdateChart(oEvent);
1580
+ },
1581
+ onStateChange(this: ObjectPageController) {
1582
+ this.getExtensionAPI().updateAppState();
1406
1583
  }
1407
1584
  };
1408
1585
  }