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;
}