Page 9660 Report Layouts, source in 29

Source29

src/Layers/W1/BaseApp/Foundation/Reporting/ReportLayouts.page.al852 lines, Copyright (c) Microsoft Corporation. MIT

// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------

namespace Microsoft.Shared.Report;

using Microsoft.Foundation.Reporting;
using System.Environment.Configuration;
using System.Integration;
using System.Reflection;
using System.Security.AccessControl;

/// <summary>
/// The report layouts page, used for adding/deleting/editing user and extension defined report layouts.
/// </summary>
page 9660 "Report Layouts"
{
    ApplicationArea = Basic, Suite;
    Caption = 'Report Layouts';
    InsertAllowed = false;
    ModifyAllowed = false;
    DeleteAllowed = true;
    AdditionalSearchTerms = 'Custom Report Layouts, Report Layout Selection';
    AboutTitle = 'About Report Layouts';
    AboutText = 'Manage (create, export/import, delete) layouts for reports. Set the default layouts used on report request pages or troubleshoot layout issues with the validation action.';
    PageType = List;
    SourceTable = "Report Layout List";
    SourceTableView = sorting("Report ID", "Layout Format");
    UsageCategory = Administration;
    Extensible = true;
    Permissions = tabledata "Tenant Report Layout" = rd;

    layout
    {
        area(content)
        {
            repeater(Group)
            {
                field("Report ID"; Rec."Report ID")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    ToolTip = 'Specifies the object ID of the report.';
                }
                field("Report Name"; Rec."Report Name")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Caption = 'Report Name';
                    ToolTip = 'Specifies the name of the report.';
                }
                field("Layout Name"; Rec."Caption")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Caption = 'Layout Name';
                    ToolTip = 'Specifies the unique name of the layout.';
                }
                field(Description; Rec."Description")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Caption = 'Description';
                    ToolTip = 'Specifies a description of the report layout.';
                }
                field(IsDefaultLayout; IsDefaultLayout)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = not IsDefaultLayout;
                    Caption = 'Default';
                    ToolTip = 'Specifies whether this is the default layout selected for the report.';
                    trigger OnValidate()
                    begin
                        ReportLayoutsImpl.SetDefaultReportLayoutSelection(Rec, false);
                        IsDefaultLayout := true;

                        // Update the default layout list.
                        DefaultReportLayoutList.Init();
                        DefaultReportLayoutList.SetRange("Name", Rec."Name");
                        DefaultReportLayoutList.SetRange("Application ID", Rec."Application ID");
                        DefaultReportLayoutList.SetRange("Report ID", Rec."Report ID");
                        DefaultReportLayoutList.FindFirst();
                        CurrPage.Update(false);
                    end;
                }

                field("Layout Publisher"; Rec."Layout Publisher")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Caption = 'Extension';
                    ToolTip = 'Specifies the name and publisher of the extension that the layout belongs to. If this field is empty, it means that layout is user-defined and does not belong to an extension.';
                }
                field("Layout Format"; Rec."Layout Format")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Caption = 'Type';
                    OptionCaption = 'RDLC,Word,Excel,External';
                    ToolTip = 'Specifies the format of the report layout.';
                }
                field("User Defined"; Rec."User Defined")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = false;
                    Caption = 'User Defined';
                    ToolTip = 'Specifies whether the layout was created by a user.';
                }
                field("Obsolete"; Rec.IsObsolete)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = Rec."User Defined" = true;
                    Visible = true;
                    Caption = 'Obsolete';
                    ToolTip = 'Specifies whether the layout is obsolete.';
                }
                field("Layout Status"; Rec."Layout Status")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Caption = 'Layout Status';
                    ToolTip = 'Specifies the approval status of the layout. Only Approved layouts are available for selection on report request pages.';
                }
                field("Layout Subtype"; Rec."Layout Subtype")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = DocumentReportExperienceEnabled;
                    Caption = 'Subtype';
                    ToolTip = 'Specifies the role of the layout in the Composite Layout Merge: full body (Default), header/footer part, or theme part.';
                }
                field("Excel data sheet configuration"; Rec.ExcelLayoutMultipleDataSheets)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = true;
                    Caption = 'Excel Sheets';
                    ToolTip = 'Specifies the Microsoft Excel sheet configuration override with respect to multiple data sheets (Default is defined by the report object).';
                }
                field("Last modified date"; Rec.SystemModifiedAt)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = true;
                    Caption = 'Last Modified Date';
                    ToolTip = 'Specifies the date and time when the layout was last modified.';
                }
                field("Last modified by"; SystemModifiedByDisplayName)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = true;
                    Caption = 'Last Modified By';
                    ToolTip = 'Specifies the user who last modified the layout.';
                }
                field("Created date"; Rec.SystemCreatedAt)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = false;
                    Caption = 'Created Date';
                    ToolTip = 'Specifies the date and time when the layout was created.';
                }
                field("Created by"; SystemCreatedByDisplayName)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = false;
                    Caption = 'Created By';
                    ToolTip = 'Specifies the user who created the layout.';
                }
                field("Layout ID"; Rec."Layout".MediaId)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = false;
                    Caption = 'Layout ID';
                    ToolTip = 'Specifies the unique ID of the layout.';
                }
            }
        }
        area(factboxes)
        {
            part(ReportLayoutFactBox; "Report Layout FactBox")
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Details';
                SubPageLink = "Report ID" = field("Report ID"),
                              Name = field(Name),
                              "Application ID" = field("Application ID");
                Visible = DocumentReportExperienceEnabled and BodyLayoutSelected;
            }
            systempart(Control11; Notes)
            {
                ApplicationArea = Notes;
                Visible = false;
            }
            systempart(Control12; Links)
            {
                ApplicationArea = RecordLinks;
                Visible = false;
            }
        }
    }

    actions
    {
        area(Processing)
        {
            action(NewLayout)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'New';
                Image = NewDocument;
                Scope = Repeater;
                ToolTip = 'Create a new layout.';

                trigger OnAction()
                var
                    ReturnReportID: Integer;
                    ReturnLayoutName: Text;
                begin
                    ReportLayoutsImpl.CreateNewReportLayout(Rec, ImpliedSubtype, ReturnReportID, ReturnLayoutName);
                    SetFocusedRecord(ReturnReportID, ReturnLayoutName);
                end;
            }

            action(EditLayout)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Edit info';
                Image = Edit;
                Enabled = LayoutIsSelected;
                ToolTip = 'Edit layout information.';

                trigger OnAction()
                var
                    NewEditedLayoutName: Text;
                begin
                    ReportLayoutsImpl.EditReportLayout(Rec, NewEditedLayoutName);
                    SetFocusedRecord(Rec."Report ID", NewEditedLayoutName);
                end;
            }

            action(RunReport)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Run report';
                Image = "Report";
                Enabled = LayoutIsSelected;
                ToolTip = 'Run the report using the selected layout.';

                trigger OnAction()
                begin
                    ReportLayoutsImpl.RunCustomReport(Rec);
                end;
            }

            action(ExportLayout)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Export layout';
                Image = Export;
                Enabled = LayoutIsSelected;
                ToolTip = 'Export the selected layout file.';

                trigger OnAction()
                begin
                    ReportLayoutsImpl.ExportReportLayout(Rec, false);
                end;
            }

            action(UpdateAndExportLayout)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Update and export layout';
                Image = Export;
                Enabled = LayoutIsSelected;
                ToolTip = 'Export the selected layout file using the current report dataset design.';

                trigger OnAction()
                begin
                    ReportLayoutsImpl.ExportReportLayout(Rec, true);
                end;
            }

            action(ReplaceLayout)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Replace layout';
                Image = Import;
                Enabled = LayoutIsSelected;
                ToolTip = 'Replace the existing layout file.';

                trigger OnAction()
                var
                    ReturnReportID: Integer;
                    ReturnLayoutName: Text;
                begin
                    if not Rec."User Defined" then
                        Error(ModifyNonUserLayoutErr);

                    if Dialog.Confirm(StrSubstNo(ReplaceConfirmationTxt, Rec."Name"), false) then
                        ReportLayoutsImpl.ReplaceLayout(Rec."Report ID", Rec."Name", Rec."Description", Rec."Layout Format", ReturnReportID, ReturnLayoutName);
                end;
            }

            action(ExportReportSchema)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Export report schema';
                Image = Export;
                Enabled = LayoutIsSelected;
                ToolTip = 'Export report schema as a Microsft Word Custom Xml document.';
                trigger OnAction()
                begin
                    ReportLayoutsImpl.ExportReportSchema(Rec, '', true);
                end;
            }

            action(DefaulLayoutSelection)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Set as default';
                Image = ListPage;
                Enabled = LayoutIsSelected;
                ToolTip = 'Set the current layout as the default layout for the specified report.';
                trigger OnAction()
                begin
                    ReportLayoutsImpl.SetDefaultReportLayoutSelection(Rec, true);
                    CurrPage.Update(false);
                end;
            }

            action(ValidateLayout)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Validate layout';
                Image = ValidateEmailLoggingSetup;
                Enabled = LayoutIsSelected;
                ToolTip = 'Validate the report layout.';

                trigger OnAction()
                begin
                    ReportLayoutsImpl.ValidateLayout(Rec);
                end;
            }

            action(ShowInfoDialog)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Show layout info';
                Image = Info;
                Enabled = LayoutIsSelected;
                ToolTip = 'Show the report layout information.';

                trigger OnAction()
                begin
                    ReportLayoutsImpl.ShowInfoDialog(Rec);
                end;
            }

            action(OpenInOneDrive)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Open in OneDrive';
                ToolTip = 'Copy the file to your Business Central folder in OneDrive and open it in a new window so you can manage or share the file.', Comment = 'OneDrive should not be translated';
                Image = Cloud;
                Visible = ShareOptionsVisible;
                Enabled = ShareOptionsEnabled;
                Scope = Repeater;
                trigger OnAction()
                begin
                    ReportLayoutsImpl.OpenInOneDrive(Rec);
                end;
            }

            action(EditInOneDrive)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Edit in OneDrive';
                ToolTip = 'Copy the file to your Business Central folder in OneDrive and open it in a new window so you can edit the file.', Comment = 'OneDrive should not be translated';
                Image = Cloud;
                Visible = ShareOptionsVisible;
                Enabled = ShareOptionsEnabled;
                Scope = Repeater;

                trigger OnAction()
                begin
                    ReportLayoutsImpl.EditInOneDrive(Rec);
                end;
            }

            action(ShareWithOneDrive)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Share';
                ToolTip = 'Copy the file to your Business Central folder in OneDrive and share the file. You can also see who it''s already shared with.', Comment = 'OneDrive should not be translated';
                Image = Share;
                Visible = ShareOptionsVisible;
                Enabled = ShareOptionsEnabled;
                Scope = Repeater;
                trigger OnAction()
                begin
                    ReportLayoutsImpl.ShareWithOneDrive(Rec);
                end;
            }

            group(CompositeLayoutDetails)
            {
                Caption = 'Composite layout';
                Image = Document;
                Visible = DocumentReportExperienceEnabled;
                // The assignment page and lookup helper declare RIMD on Tenant Report Layout Cfg (indirect
                // permission) so the tenant-wide write can happen there. Each action below is gated with
                // AccessByPermission so only a user who actually holds Modify on that configuration can reach it;
                // otherwise anyone able to open Report Layouts could change tenant/company report branding defaults
                // without permission to that table.

                action(AssignReportDefaults)
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Set report theme and header-footer';
                    Image = Setup;
                    Enabled = BodyLayoutSelected;
                    AccessByPermission = tabledata "Tenant Report Layout Cfg" = M;
                    ToolTip = 'Set the theme and header/footer applied to the selected layout. Available for body layouts only: a theme and header/footer are merged onto a body layout when the report renders. The setting is stored per company/tenant for this layout, not per user.';

                    trigger OnAction()
                    var
                        HeaderFooterThemeAssignment: Page "Header/Footer Theme Assignment";
                    begin
                        HeaderFooterThemeAssignment.SetLayout(Rec."Report ID", LookupHelper.CompositeLayoutKey(Rec));
                        HeaderFooterThemeAssignment.RunModal();
                    end;
                }
                action(ManageAllThemesAndHeaderFooters)
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Set all report theme and header-footer';
                    Image = ViewDetails;
                    Enabled = WordLayoutSelected;
                    AccessByPermission = tabledata "Tenant Report Layout Cfg" = M;
                    ToolTip = 'Show every body layout of this report with the theme and header/footer that apply to each, and change them per layout. Inherited company and global defaults are shown with their source.';

                    trigger OnAction()
                    var
                        ReportLayoutList: Record "Report Layout List";
                        LayoutThemeHeaderFooter: Page "Layout Theme and Header/Footer";
                    begin
                        ReportLayoutList.SetRange("Report ID", Rec."Report ID");
                        ReportLayoutList.SetRange("Layout Format", ReportLayoutList."Layout Format"::Word);
                        ReportLayoutList.SetRange("Layout Subtype", ReportLayoutList."Layout Subtype"::Body);
                        if ReportLayoutList.IsEmpty() then begin
                            Message(NoBodyLayoutsForReportMsg, Rec."Report ID");
                            exit;
                        end;

                        LayoutThemeHeaderFooter.SetTableView(ReportLayoutList);
                        LayoutThemeHeaderFooter.Run();
                    end;
                }
                action(LayoutConfiguration)
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Set report global default';
                    Image = Setup;
                    Enabled = WordLayoutSelected;
                    AccessByPermission = tabledata "Tenant Report Layout Cfg" = M;
                    ToolTip = 'Set the theme and header/footer that apply when a layout has none of its own. The row with report ID 0 is the global default for every report; a row for this report covers all of its layouts.';

                    trigger OnAction()
                    var
                        TenantReportLayoutCfg: Record "Tenant Report Layout Cfg";
                    begin
                        TenantReportLayoutCfg.SetFilter("Report ID", '%1|%2', Rec."Report ID", 0);
                        Page.RunModal(Page::"Tenant Report Layout Cfg", TenantReportLayoutCfg);
                    end;
                }
                action(ManageThemesAndHeaderFooterLayouts)
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Manage themes and header-footer layouts';
                    Image = List;
                    ToolTip = 'Open the list of themes and header/footer layouts to add, export, or delete them. The list is shared by every report, so it does not depend on the layout selected here.';

                    trigger OnAction()
                    begin
                        Page.Run(Page::"Report Theme and Header/Footer");
                    end;
                }
            }

            // BaseSystemPermissionSet grants Tenant Report Layout and its override table together, so
            // gating on Tenant Report Layout = M covers both.
            action(SetApproved)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Set as Approved';
                ToolTip = 'Mark the selected layouts as approved. Only approved layouts are available for selection on report request pages.';
                Image = Approve;
                Enabled = CanModifyStatus;
                AccessByPermission = tabledata "Tenant Report Layout" = M;

                trigger OnAction()
                begin
                    SetLayoutStatusAction(Enum::"Report Layout Status"::Approved);
                end;
            }
            action(SetDraft)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Set as Draft';
                ToolTip = 'Mark the selected layouts as draft. Draft layouts are not available for selection on report request pages.';
                Image = OpenWorksheet;
                Enabled = CanModifyStatus;
                AccessByPermission = tabledata "Tenant Report Layout" = M;

                trigger OnAction()
                begin
                    SetLayoutStatusAction(Enum::"Report Layout Status"::Draft);
                end;
            }
            action(SetPendingApproval)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Set as Pending Approval';
                ToolTip = 'Mark the selected layouts as pending approval. Pending layouts are not available for selection on report request pages.';
                Image = AddWatch;
                Enabled = CanModifyStatus;
                AccessByPermission = tabledata "Tenant Report Layout" = M;

                trigger OnAction()
                begin
                    SetLayoutStatusAction(Enum::"Report Layout Status"::"Pending Approval");
                end;
            }
            action(SetRetired)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Set as Retired';
                ToolTip = 'Mark the selected layouts as retired. Retired layouts are not available for selection on report request pages.';
                Image = Archive;
                Enabled = CanModifyStatus;
                AccessByPermission = tabledata "Tenant Report Layout" = M;

                trigger OnAction()
                begin
                    SetLayoutStatusAction(Enum::"Report Layout Status"::Retired);
                end;
            }

#if not CLEAN29
            group(StatusActions)
            {
                Caption = 'Layout Status';
                Image = Status;
                ObsoleteState = Pending;
                ObsoleteReason = 'The Layout Status actions have been moved under the Layout action group in the promoted area. This empty group is kept for backward compatibility and will be removed in a future version.';
                ObsoleteTag = '29.0';
            }
#endif
        }

        area(Promoted)
        {
            actionref(NewLayout_Promoted; NewLayout)
            {
            }

            actionref(EditLayout_Promoted; EditLayout)
            {
            }

            actionref(RunReport_Promoted; RunReport)
            {
            }

            actionref(ExportLayout_Promoted; ExportLayout)
            {
            }

            actionref(ReplaceLayout_Promoted; ReplaceLayout)
            {
            }

            group(Layout)
            {
                Caption = 'Layout';

                actionref(UpdateAndExportLayout_Promoted; UpdateAndExportLayout)
                {
                }

                actionref(ExportReportSchema_Promoted; ExportReportSchema)
                {
                }

                actionref(DefaulLayoutSelection_Promoted; DefaulLayoutSelection)
                {
                }

                actionref(ValidateLayout_Promoted; ValidateLayout)
                {
                }

                actionref(ShowInfoDialog_Promoted; ShowInfoDialog)
                {
                }

                group(LayoutStatus)
                {
                    Caption = 'Layout Status';
                    Image = Status;

                    actionref(SetApproved_Promoted; SetApproved)
                    {
                    }

                    actionref(SetDraft_Promoted; SetDraft)
                    {
                    }

                    actionref(SetPendingApproval_Promoted; SetPendingApproval)
                    {
                    }

                    actionref(SetRetired_Promoted; SetRetired)
                    {
                    }
                }
            }

            group(CompositeLayout)
            {
                Caption = 'Composite layout';
                Visible = DocumentReportExperienceEnabled;

                actionref(AssignReportDefaults_Promoted; AssignReportDefaults)
                {
                }

                actionref(ManageAllThemesAndHeaderFooters_Promoted; ManageAllThemesAndHeaderFooters)
                {
                }

                actionref(LayoutConfiguration_Promoted; LayoutConfiguration)
                {
                }

                actionref(ManageThemesAndHeaderFooterLayouts_Promoted; ManageThemesAndHeaderFooterLayouts)
                {
                }
            }
        }
    }

    views
    {
        view(UserDefined)
        {
            Caption = 'User-Defined';
            Filters = where("User Defined" = const(true));
        }
        view(Extensions)
        {
            Caption = 'Extensions';
            Filters = where("User Defined" = const(false));
        }
        view(ApprovedLayouts)
        {
            Caption = 'Approved Layouts';
            Filters = where("Layout Status" = const(Approved));
        }
        view(DraftLayouts)
        {
            Caption = 'Draft Layouts';
            Filters = where("Layout Status" = const(Draft));
        }
        view(AwaitingApproval)
        {
            Caption = 'Pending Approval';
            Filters = where("Layout Status" = const("Pending Approval"));
        }
        view(RetiredLayouts)
        {
            Caption = 'Retired Layouts';
            Filters = where("Layout Status" = const(Retired));
        }
    }

    trigger OnOpenPage()
    var
        FeatureKeyManagement: Codeunit "Feature Key Management";
    begin
        ReportLayoutsImpl.SetSelectedCompany(CompanyName());
        if CurrPage.LookupMode and (not IncludeUnapproved) then
            Rec.SetRange("Layout Status", Enum::"Report Layout Status"::Approved);
        DocumentReportExperienceEnabled := FeatureKeyManagement.IsDocumentReportExperienceEnabled();
        if DocumentReportExperienceEnabled and (not CurrPage.LookupMode) and (ImpliedSubtype = Enum::"Report Layout Subtype"::Default) then begin
            Rec.FilterGroup(2);
            Rec.SetFilter("Layout Subtype", '<>%1&<>%2', Rec."Layout Subtype"::HeaderFooter, Rec."Layout Subtype"::Theme);
            Rec.FilterGroup(0);
        end;
    end;

    trigger OnDeleteRecord(): Boolean
    var
        TenantReportLayout: Record "Tenant Report Layout";
    begin
        TenantReportLayout.Init();
        if Rec."User Defined" then begin
            TenantReportLayout.Get(Rec."Report ID", Rec."Name", EmptyGuid);
            // If the selected layout is the default layout for the current report.
            if TenantReportLayoutSelection.Get(Rec."Report ID", CompanyName(), EmptyGuid) then
                if TenantReportLayoutSelection."Layout Name" = Rec.Name then
                    // selected layout is the default layout. In this case we confirm the deletion.
                    if not ReportLayoutsImpl.ConfirmDeleteDefaultLayoutSelection(Rec, TenantReportLayoutSelection) then
                        exit(false);

            if Rec."Layout Subtype" in [Rec."Layout Subtype"::HeaderFooter, Rec."Layout Subtype"::Theme] then begin
                if HasCompositePartReferences(Rec) then
                    if not Dialog.Confirm(DeletePartWithReferencesQst, false, Rec.Name) then
                        exit(false);
                LookupHelper.ClearPartAssignments(Rec);
            end;

            ReportLayoutsImpl.DeleteReportLayout(TenantReportLayout);
        end else
            Error(ModifyNonUserLayoutErr);

        CurrPage.Update(false);
        exit(false);
    end;

    trigger OnAfterGetCurrRecord()
    var
        SelectedReportLayoutList: Record "Report Layout List";
        DocumentSharing: Codeunit "Document Sharing";
    begin
        LayoutIsSelected := not ((Rec."Report ID" = 0) and (Rec.Name = ''));
        WordLayoutSelected := LayoutIsSelected and (Rec."Layout Format" = Rec."Layout Format"::Word);
        BodyLayoutSelected := WordLayoutSelected and (Rec."Layout Subtype" = Rec."Layout Subtype"::Body);

        CurrPage.SetSelectionFilter(SelectedReportLayoutList);
        IsMultiSelect := SelectedReportLayoutList.Count() > 1;
        ShareOptionsVisible := DocumentSharing.ShareEnabled(Enum::"Document Sharing Source"::System);
        ShareOptionsEnabled := LayoutIsSelected and (not IsMultiSelect) and Rec."User Defined" and (Rec."Layout Format" <> Rec."Layout Format"::RDLC);
        CanModifyStatus := LayoutIsSelected;
        UpdateUserDisplayName();
    end;

    trigger OnAfterGetRecord()
    begin
        if DefaultReportLayoutList."Report ID" <> Rec."Report ID" then
            ReportLayoutsImpl.GetDefaultReportLayoutSelection(Rec."Report ID", DefaultReportLayoutList);

        IsDefaultLayout := (DefaultReportLayoutList."Report ID" = Rec."Report ID") and (DefaultReportLayoutList.Name = Rec.Name) and (DefaultReportLayoutList."Application ID" = Rec."Application ID");
        UpdateUserDisplayName();
    end;

    local procedure UpdateUserDisplayName()
    var
        User: Record "User";
    begin
        Clear(SystemCreatedByDisplayName);
        Clear(SystemModifiedByDisplayName);

        if not User.ReadPermission() then
            exit;

        if (Rec.SystemCreatedBy <> EmptyGuid) and User.Get(Rec.SystemCreatedBy) then
            SystemCreatedByDisplayName := User."User Name";

        if (Rec.SystemModifiedBy <> EmptyGuid) and User.Get(Rec.SystemModifiedBy) then
            SystemModifiedByDisplayName := User."User Name";
    end;

    var
        DefaultReportLayoutList: Record "Report Layout List";
        TenantReportLayoutSelection: Record "Tenant Report Layout Selection";
        ReportLayoutsImpl: Codeunit "Report Layouts Impl.";
        LookupHelper: Codeunit "Composite Layout Lookup Helper";
        EmptyGuid: Guid;
        ImpliedSubtype: Enum "Report Layout Subtype";
        IsDefaultLayout: Boolean;
        IsMultiSelect: Boolean;
        LayoutIsSelected: Boolean;
        ShareOptionsVisible: Boolean;
        ShareOptionsEnabled: Boolean;
        CanModifyStatus: Boolean;
        DocumentReportExperienceEnabled: Boolean;
        WordLayoutSelected: Boolean;
        BodyLayoutSelected: Boolean;
        IncludeUnapproved: Boolean;
        ModifyNonUserLayoutErr: Label 'Only user-defined layouts can be modified or removed.';
        ReplaceConfirmationTxt: Label 'This action will replace the layout file of the currently selected layout "%1". Do you want to continue ?', Comment = '%1 = LayoutName';
        LayoutStatusChangedMsg: Label '%1 layout(s) set to %2.', Comment = '%1 = Number of layouts updated, %2 = Status name';
        NoBodyLayoutsForReportMsg: Label 'Report %1 has no body layouts, so there is nothing to set a theme or header/footer on. Only a body layout carries them: a theme and header/footer are merged onto it when the report renders.', Comment = '%1 = report ID';
        DeletePartWithReferencesQst: Label 'Layout part "%1" is referenced in the Tenant Report Layout Configuration. Deleting it will clear those references and may result in reports rendering without the expected header/footer or theme. Do you want to continue?', Comment = '%1 = Layout Name';
        SystemModifiedByDisplayName: Text;
        SystemCreatedByDisplayName: Text;

    local procedure HasCompositePartReferences(ReportLayoutList: Record "Report Layout List"): Boolean
    var
        TenantReportLayoutCfg: Record "Tenant Report Layout Cfg";
        CompositeName: Text;
    begin
        // Filter with the same stored-length value the assignment/clear paths use (CopyStr to the field length),
        // otherwise a composite name longer than the field would never match the truncated stored value and the
        // "part is still referenced" warning would be skipped even though the part is assigned.
        CompositeName := LookupHelper.EncodeCompositeName(ReportLayoutList."Application ID", ReportLayoutList.Name);
        TenantReportLayoutCfg.SetRange("Header Part Name", CopyStr(CompositeName, 1, MaxStrLen(TenantReportLayoutCfg."Header Part Name")));
        if not TenantReportLayoutCfg.IsEmpty() then
            exit(true);
        TenantReportLayoutCfg.SetRange("Header Part Name");
        TenantReportLayoutCfg.SetRange("Theme Part Name", CopyStr(CompositeName, 1, MaxStrLen(TenantReportLayoutCfg."Theme Part Name")));
        exit(not TenantReportLayoutCfg.IsEmpty());
    end;

    internal procedure SetIncludeUnapproved()
    begin
        IncludeUnapproved := true;
    end;

    local procedure SetLayoutStatusAction(NewStatus: Enum "Report Layout Status")
    var
        SelectedLayouts: Record "Report Layout List";
        UpdateCount: Integer;
    begin
        CurrPage.SetSelectionFilter(SelectedLayouts);
        UpdateCount := ReportLayoutsImpl.SetLayoutStatusBatch(SelectedLayouts, NewStatus);
        if UpdateCount > 0 then
            Message(LayoutStatusChangedMsg, UpdateCount, NewStatus);
        CurrPage.Update(false);
    end;

    local procedure SetFocusedRecord(ReportID: Integer; LayoutName: Text)
    var
        CurrReportLayoutList: Record "Report Layout List";
    begin
        if (ReportID = 0) or (LayoutName = '') then
            exit;
        if CurrReportLayoutList.get(ReportID, LayoutName, EmptyGuid) then begin
            CurrPage.SetRecord(CurrReportLayoutList);
            CurrPage.Update(false);
        end;
    end;
}