@sapui5/sap.fe.templates 1.146.0 → 1.148.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.
- package/package.json +1 -1
- package/src/sap/fe/templates/.library +1 -1
- package/src/sap/fe/templates/AnalyticalListPage/manifest.json +1 -1
- package/src/sap/fe/templates/ListReport/ExtensionAPI.js +1 -1
- package/src/sap/fe/templates/ListReport/ExtensionAPI.ts +1 -1
- package/src/sap/fe/templates/ListReport/ListReport.view.xml +45 -10
- package/src/sap/fe/templates/ListReport/ListReportController.controller.js +43 -16
- package/src/sap/fe/templates/ListReport/ListReportController.controller.ts +51 -15
- package/src/sap/fe/templates/ListReport/ListReportTemplating.js +39 -3
- package/src/sap/fe/templates/ListReport/ListReportTemplating.ts +35 -1
- package/src/sap/fe/templates/ListReport/controls/MultipleModeControl.js +4 -1
- package/src/sap/fe/templates/ListReport/controls/MultipleModeControl.ts +3 -0
- package/src/sap/fe/templates/ListReport/manifest.json +1 -1
- package/src/sap/fe/templates/ListReport/overrides/MessageHandler.js +3 -2
- package/src/sap/fe/templates/ListReport/overrides/MessageHandler.ts +2 -1
- package/src/sap/fe/templates/ObjectPage/Component.js +4 -2
- package/src/sap/fe/templates/ObjectPage/Component.ts +3 -1
- package/src/sap/fe/templates/ObjectPage/ExtensionAPI.js +163 -28
- package/src/sap/fe/templates/ObjectPage/ExtensionAPI.ts +163 -23
- package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.js +246 -35
- package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.ts +286 -42
- package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.js +32 -16
- package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.ts +46 -33
- package/src/sap/fe/templates/ObjectPage/components/CollaborationDiscardDialog.js +4 -1
- package/src/sap/fe/templates/ObjectPage/components/CollaborationDiscardDialog.tsx +1 -0
- package/src/sap/fe/templates/ObjectPage/components/CollaborationDraft.js +15 -4
- package/src/sap/fe/templates/ObjectPage/components/CollaborationDraft.tsx +11 -2
- package/src/sap/fe/templates/ObjectPage/controls/StashableHBox.js +28 -1
- package/src/sap/fe/templates/ObjectPage/controls/StashableHBox.ts +31 -0
- package/src/sap/fe/templates/ObjectPage/helpers/SectionNavigationHelper.js +72 -0
- package/src/sap/fe/templates/ObjectPage/helpers/SectionNavigationHelper.ts +75 -0
- package/src/sap/fe/templates/ObjectPage/manifest.json +1 -15
- package/src/sap/fe/templates/ObjectPage/overrides/CollaborationManager.js +29 -20
- package/src/sap/fe/templates/ObjectPage/overrides/CollaborationManager.ts +28 -21
- package/src/sap/fe/templates/ObjectPage/overrides/IntentBasedNavigation.js +4 -3
- package/src/sap/fe/templates/ObjectPage/overrides/IntentBasedNavigation.ts +4 -4
- package/src/sap/fe/templates/ObjectPage/overrides/Share.js +2 -2
- package/src/sap/fe/templates/ObjectPage/overrides/Share.ts +1 -1
- package/src/sap/fe/templates/ObjectPage/overrides/ViewState.js +93 -17
- package/src/sap/fe/templates/ObjectPage/overrides/ViewState.ts +108 -22
- package/src/sap/fe/templates/ObjectPage/view/fragments/Actions.fragment.xml +12 -2
- package/src/sap/fe/templates/ObjectPage/view/fragments/EmphasizedFirstHeaderAction.fragment.xml +182 -0
- package/src/sap/fe/templates/ObjectPage/view/fragments/ExpandedHeading.fragment.xml +4 -4
- package/src/sap/fe/templates/ObjectPage/view/fragments/Heading.fragment.xml +4 -4
- package/src/sap/fe/templates/ObjectPage/view/fragments/ObjectPageHeaderAddress.fragment.xml +1 -1
- package/src/sap/fe/templates/ObjectPage/view/fragments/ObjectPageHeaderContact.fragment.xml +1 -1
- package/src/sap/fe/templates/ObjectPage/view/fragments/ObjectPageHeaderForm.fragment.xml +1 -0
- package/src/sap/fe/templates/ObjectPage/view/fragments/Section.fragment.xml +2 -0
- package/src/sap/fe/templates/ObjectPage/view/fragments/SectionContent.fragment.xml +18 -12
- package/src/sap/fe/templates/ObjectPage/view/fragments/SectionFormContent.fragment.xml +2 -0
- package/src/sap/fe/templates/ObjectPage/view/fragments/SectionMoreFormContent.fragment.xml +2 -0
- package/src/sap/fe/templates/library.js +1 -1
- package/src/sap/fe/templates/messagebundle.properties +1 -1
- package/src/sap/fe/templates/messagebundle_ar.properties +1 -1
- package/src/sap/fe/templates/messagebundle_bg.properties +1 -1
- package/src/sap/fe/templates/messagebundle_ca.properties +1 -1
- package/src/sap/fe/templates/messagebundle_cnr.properties +1 -1
- package/src/sap/fe/templates/messagebundle_cs.properties +1 -1
- package/src/sap/fe/templates/messagebundle_cy.properties +1 -1
- package/src/sap/fe/templates/messagebundle_da.properties +1 -1
- package/src/sap/fe/templates/messagebundle_de.properties +1 -1
- package/src/sap/fe/templates/messagebundle_el.properties +1 -1
- package/src/sap/fe/templates/messagebundle_en.properties +1 -1
- package/src/sap/fe/templates/messagebundle_en_GB.properties +1 -1
- package/src/sap/fe/templates/messagebundle_en_US_saprigi.properties +1 -1
- package/src/sap/fe/templates/messagebundle_es.properties +1 -1
- package/src/sap/fe/templates/messagebundle_es_MX.properties +1 -1
- package/src/sap/fe/templates/messagebundle_et.properties +1 -1
- package/src/sap/fe/templates/messagebundle_fi.properties +1 -1
- package/src/sap/fe/templates/messagebundle_fr.properties +1 -1
- package/src/sap/fe/templates/messagebundle_fr_CA.properties +1 -1
- package/src/sap/fe/templates/messagebundle_hi.properties +1 -1
- package/src/sap/fe/templates/messagebundle_hr.properties +1 -1
- package/src/sap/fe/templates/messagebundle_hu.properties +1 -1
- package/src/sap/fe/templates/messagebundle_id.properties +1 -1
- package/src/sap/fe/templates/messagebundle_it.properties +1 -1
- package/src/sap/fe/templates/messagebundle_iw.properties +2 -2
- package/src/sap/fe/templates/messagebundle_ja.properties +1 -1
- package/src/sap/fe/templates/messagebundle_kk.properties +1 -1
- package/src/sap/fe/templates/messagebundle_ko.properties +1 -1
- package/src/sap/fe/templates/messagebundle_lt.properties +1 -1
- package/src/sap/fe/templates/messagebundle_lv.properties +1 -1
- package/src/sap/fe/templates/messagebundle_mk.properties +1 -1
- package/src/sap/fe/templates/messagebundle_ms.properties +1 -1
- package/src/sap/fe/templates/messagebundle_nl.properties +1 -1
- package/src/sap/fe/templates/messagebundle_no.properties +2 -2
- package/src/sap/fe/templates/messagebundle_pl.properties +1 -1
- package/src/sap/fe/templates/messagebundle_pt.properties +1 -1
- package/src/sap/fe/templates/messagebundle_pt_PT.properties +1 -1
- package/src/sap/fe/templates/messagebundle_ro.properties +1 -1
- package/src/sap/fe/templates/messagebundle_ru.properties +1 -1
- package/src/sap/fe/templates/messagebundle_sh.properties +1 -1
- package/src/sap/fe/templates/messagebundle_sk.properties +1 -1
- package/src/sap/fe/templates/messagebundle_sl.properties +1 -1
- package/src/sap/fe/templates/messagebundle_sr.properties +1 -1
- package/src/sap/fe/templates/messagebundle_sv.properties +1 -1
- package/src/sap/fe/templates/messagebundle_th.properties +1 -1
- package/src/sap/fe/templates/messagebundle_tr.properties +1 -1
- package/src/sap/fe/templates/messagebundle_uk.properties +3 -3
- package/src/sap/fe/templates/messagebundle_vi.properties +1 -1
- package/src/sap/fe/templates/messagebundle_zh_CN.properties +1 -1
- package/src/sap/fe/templates/messagebundle_zh_TW.properties +1 -1
|
@@ -48,6 +48,12 @@ class ObjectPageExtensionAPI extends ExtensionAPI {
|
|
|
48
48
|
*/
|
|
49
49
|
private customMessageStripId?: string;
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Flag to prevent concurrent navigateToSubSection calls.
|
|
53
|
+
* Set to true when navigation starts, reset after navigation completes (including polling).
|
|
54
|
+
*/
|
|
55
|
+
private isNavigatingToSubSection = false;
|
|
56
|
+
|
|
51
57
|
/**
|
|
52
58
|
* Refreshes either the whole object page or only parts of it.
|
|
53
59
|
* @param [vPath] Path or array of paths referring to entities or properties to be refreshed.
|
|
@@ -130,9 +136,32 @@ class ObjectPageExtensionAPI extends ExtensionAPI {
|
|
|
130
136
|
*/
|
|
131
137
|
showSideContent(sSubSectionKey: string, bShow?: boolean): void {
|
|
132
138
|
const sBlockID = getSideContentLayoutID(sSubSectionKey),
|
|
133
|
-
oBlock = this._view.byId(sBlockID)
|
|
134
|
-
|
|
135
|
-
(oBlock
|
|
139
|
+
oBlock = this._view.byId(sBlockID) as DynamicSideContent;
|
|
140
|
+
|
|
141
|
+
if (!oBlock) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const sCurrentBreakpoint = oBlock.getCurrentBreakpoint();
|
|
146
|
+
const bBlockState = bShow === undefined ? !oBlock.getShowSideContent() : bShow;
|
|
147
|
+
|
|
148
|
+
// On small screens (S breakpoint), side content should replace main content
|
|
149
|
+
if (sCurrentBreakpoint === "S") {
|
|
150
|
+
if (bBlockState) {
|
|
151
|
+
// Show side content, hide main content
|
|
152
|
+
oBlock.setShowSideContent(true, false);
|
|
153
|
+
oBlock.setShowMainContent(false, false);
|
|
154
|
+
} else {
|
|
155
|
+
// Hide side content, show main content
|
|
156
|
+
oBlock.setShowSideContent(false, false);
|
|
157
|
+
oBlock.setShowMainContent(true, false);
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
// On larger screens, show side content alongside main content
|
|
161
|
+
// Always keep main content visible on large screens
|
|
162
|
+
oBlock.setShowMainContent(true, false);
|
|
163
|
+
oBlock.setShowSideContent(bBlockState, false);
|
|
164
|
+
}
|
|
136
165
|
}
|
|
137
166
|
|
|
138
167
|
/**
|
|
@@ -313,7 +342,11 @@ class ObjectPageExtensionAPI extends ExtensionAPI {
|
|
|
313
342
|
*/
|
|
314
343
|
_showMessages(messages: Message[], origin: "Backend" | "Custom" = "Custom"): void {
|
|
315
344
|
try {
|
|
316
|
-
|
|
345
|
+
if (messages.length > 0) {
|
|
346
|
+
// Only if there are messages to show, we remove custom message strip.
|
|
347
|
+
// This way we ensure that we don't interfere with custom message strip's lifecyle until there are new messages to show in the standard message strip.
|
|
348
|
+
this.removeCustomMessageStrip();
|
|
349
|
+
}
|
|
317
350
|
|
|
318
351
|
const view = this._view;
|
|
319
352
|
const internalModel = view.getModel("internal");
|
|
@@ -478,70 +511,177 @@ class ObjectPageExtensionAPI extends ExtensionAPI {
|
|
|
478
511
|
MessageBox.error(sTitle);
|
|
479
512
|
}
|
|
480
513
|
|
|
514
|
+
/**
|
|
515
|
+
* Navigate to the first section of the object page.
|
|
516
|
+
* Used as a fallback when the target section is not found or invalid.
|
|
517
|
+
* @param objectPageLayout The ObjectPageLayout control to navigate within
|
|
518
|
+
*/
|
|
519
|
+
private navigateToFirstSection(objectPageLayout: ObjectPageLayout): void {
|
|
520
|
+
const sections = objectPageLayout.getSections();
|
|
521
|
+
if (!sections || sections.length === 0) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const firstSection = sections[0];
|
|
526
|
+
const subSections = firstSection.getSubSections();
|
|
527
|
+
if (!subSections || subSections.length === 0) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const firstSubSection = subSections[0];
|
|
532
|
+
const subSectionFullId = firstSubSection.getId();
|
|
533
|
+
|
|
534
|
+
if (!subSectionFullId) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
objectPageLayout.setSelectedSection(subSectionFullId);
|
|
539
|
+
objectPageLayout.fireNavigate({
|
|
540
|
+
section: firstSection,
|
|
541
|
+
subSection: firstSubSection
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
|
|
481
545
|
/**
|
|
482
546
|
* Navigate to a specific section or subsection within the current page.
|
|
483
547
|
* Works with Object Page layouts and other section-based layouts.
|
|
548
|
+
* If the target section is not found or invalid, the app automatically falls back to the first available section.
|
|
484
549
|
* @param sectionOrSubSectionId The ID of the target section or subsection (without a view prefix, for example, "fe::FacetSection::TravelData" or "fe::SubSection::Details")
|
|
485
550
|
* @public
|
|
486
551
|
*/
|
|
487
552
|
navigateToSubSection(sectionOrSubSectionId: string): void {
|
|
553
|
+
// Guard against concurrent navigation calls to prevent infinite loops
|
|
554
|
+
// from multiple polling mechanisms (ViewState.apply and ObjectPageController._navigateToTargetSection)
|
|
555
|
+
if (this.isNavigatingToSubSection) {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
this.isNavigatingToSubSection = true;
|
|
559
|
+
|
|
560
|
+
// Helper to reset navigation flag after a delay
|
|
561
|
+
const resetNavigationFlag = (delayMs: number): void => {
|
|
562
|
+
setTimeout(() => {
|
|
563
|
+
this.isNavigatingToSubSection = false;
|
|
564
|
+
}, delayMs);
|
|
565
|
+
};
|
|
566
|
+
|
|
488
567
|
try {
|
|
489
568
|
// Find the Object Page Layout control
|
|
490
569
|
const objectPageLayout = this._view.getContent()[0] as ObjectPageLayout | undefined;
|
|
491
570
|
|
|
492
|
-
if (!objectPageLayout) {
|
|
493
|
-
|
|
571
|
+
if (!objectPageLayout || !objectPageLayout.getDomRef()) {
|
|
572
|
+
// ObjectPageLayout not available or destroyed - silently return during navigation transitions
|
|
573
|
+
// This is expected when ViewState.apply runs on a view being navigated away from
|
|
574
|
+
this.isNavigatingToSubSection = false;
|
|
494
575
|
return;
|
|
495
576
|
}
|
|
496
577
|
|
|
497
578
|
if (!sectionOrSubSectionId) {
|
|
498
|
-
this.
|
|
579
|
+
this.navigateToFirstSection(objectPageLayout);
|
|
580
|
+
resetNavigationFlag(100);
|
|
499
581
|
return;
|
|
500
582
|
}
|
|
501
583
|
|
|
502
584
|
const control = this._view.byId(sectionOrSubSectionId);
|
|
503
585
|
|
|
504
|
-
if (!control) {
|
|
586
|
+
if (!control || !(control as Control).getVisible()) {
|
|
587
|
+
this.navigateToFirstSection(objectPageLayout);
|
|
505
588
|
this.showNavigationError();
|
|
589
|
+
resetNavigationFlag(100);
|
|
506
590
|
return;
|
|
507
591
|
}
|
|
508
592
|
|
|
509
593
|
let targetSubSection: ObjectPageSubSection | undefined;
|
|
594
|
+
let targetSection: ObjectPageSection | undefined;
|
|
595
|
+
let isNavigatingToSection = false; // Track if original target was a Section (not SubSection)
|
|
510
596
|
|
|
511
597
|
// Check if control is a SubSection or Section
|
|
512
598
|
if (control.isA<ObjectPageSubSection>("sap.uxap.ObjectPageSubSection")) {
|
|
513
599
|
targetSubSection = control;
|
|
514
600
|
} else if (control.isA<ObjectPageSection>("sap.uxap.ObjectPageSection")) {
|
|
515
|
-
|
|
601
|
+
targetSection = control;
|
|
602
|
+
isNavigatingToSection = true;
|
|
603
|
+
// If it's a section, get the first subsection (if available)
|
|
516
604
|
const subSections = control.getSubSections();
|
|
517
605
|
targetSubSection = subSections.length > 0 ? subSections[0] : undefined;
|
|
518
606
|
}
|
|
519
607
|
|
|
520
|
-
// Validate subsection
|
|
521
|
-
|
|
608
|
+
// Validate we have either a section or subsection
|
|
609
|
+
const hasValidTarget = targetSubSection || targetSection;
|
|
610
|
+
if (!hasValidTarget || (targetSubSection && !targetSubSection.getVisible())) {
|
|
611
|
+
this.navigateToFirstSection(objectPageLayout);
|
|
522
612
|
this.showNavigationError();
|
|
613
|
+
resetNavigationFlag(100);
|
|
523
614
|
return;
|
|
524
615
|
}
|
|
525
616
|
|
|
526
|
-
//
|
|
527
|
-
|
|
617
|
+
// If we have a section but no subsection (lazy loading scenario), scroll directly to the section
|
|
618
|
+
if (targetSection && !targetSubSection) {
|
|
619
|
+
const sectionFullId = targetSection.getId();
|
|
620
|
+
objectPageLayout.scrollToSection(sectionFullId, 0);
|
|
621
|
+
resetNavigationFlag(100);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
528
624
|
|
|
529
|
-
|
|
530
|
-
|
|
625
|
+
// At this point, targetSubSection is guaranteed to be defined
|
|
626
|
+
// (we've already returned if it was undefined with a valid targetSection)
|
|
627
|
+
if (!targetSubSection) {
|
|
628
|
+
// This should never happen, but satisfies TypeScript
|
|
629
|
+
this.isNavigatingToSubSection = false;
|
|
531
630
|
return;
|
|
532
631
|
}
|
|
533
632
|
|
|
534
|
-
//
|
|
535
|
-
|
|
633
|
+
// Note: we intentionally do not check getVisible() here.
|
|
634
|
+
// When navigating to a subsection in an inactive IconTabBar tab, the subsection is not yet visible.
|
|
635
|
+
// setSelectedSection will activate the parent section and make the subsection visible.
|
|
636
|
+
|
|
637
|
+
// Get the full subsection ID (including view prefix)
|
|
638
|
+
const subSectionFullId = targetSubSection.getId();
|
|
639
|
+
|
|
640
|
+
if (!subSectionFullId) {
|
|
641
|
+
this.isNavigatingToSubSection = false;
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
536
644
|
|
|
537
|
-
// Trigger iApp state change by firing navigate event
|
|
538
645
|
const parentSection = targetSubSection.getParent() as ObjectPageSection;
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
646
|
+
const parentSectionFullId = parentSection.getId();
|
|
647
|
+
const isParentSectionSelected = objectPageLayout.getSelectedSection() === parentSectionFullId;
|
|
648
|
+
|
|
649
|
+
if (!isParentSectionSelected && !isNavigatingToSection) {
|
|
650
|
+
// When navigating to a subsection in an inactive section, we must first activate
|
|
651
|
+
// the parent section, then wait for subsection to be ready before scrolling to it
|
|
652
|
+
objectPageLayout.scrollToSection(parentSectionFullId, 0);
|
|
653
|
+
|
|
654
|
+
// Poll for subsection DOM to be ready after parent section activation
|
|
655
|
+
// Related: helpers/SectionNavigationHelper.ts (used by ViewState.apply and ObjectPageController.navigateToTargetSection)
|
|
656
|
+
// This polling differs: checks DOM readiness (binary), not section ID stability
|
|
657
|
+
let attempts = 0;
|
|
658
|
+
const maxAttempts = 10;
|
|
659
|
+
const checkSubsectionReady = (): void => {
|
|
660
|
+
attempts++;
|
|
661
|
+
const subSectionDom = targetSubSection.getDomRef();
|
|
662
|
+
if (subSectionDom) {
|
|
663
|
+
// Subsection is ready, scroll to it
|
|
664
|
+
objectPageLayout.scrollToSection(subSectionFullId, 0);
|
|
665
|
+
resetNavigationFlag(100);
|
|
666
|
+
} else if (attempts < maxAttempts) {
|
|
667
|
+
// Not ready yet, check again
|
|
668
|
+
setTimeout(checkSubsectionReady, 50);
|
|
669
|
+
} else {
|
|
670
|
+
// Timeout - try scrolling anyway
|
|
671
|
+
objectPageLayout.scrollToSection(subSectionFullId, 0);
|
|
672
|
+
resetNavigationFlag(100);
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
// Start checking after 100ms initial delay
|
|
676
|
+
setTimeout(checkSubsectionReady, 100);
|
|
677
|
+
} else {
|
|
678
|
+
// Parent section already selected or navigating to section - scroll directly
|
|
679
|
+
const scrollTarget = isNavigatingToSection ? parentSectionFullId : subSectionFullId;
|
|
680
|
+
objectPageLayout.scrollToSection(scrollTarget, 0);
|
|
681
|
+
resetNavigationFlag(100);
|
|
682
|
+
}
|
|
543
683
|
} catch (error) {
|
|
544
|
-
|
|
684
|
+
this.isNavigatingToSubSection = false;
|
|
545
685
|
}
|
|
546
686
|
}
|
|
547
687
|
}
|