Raporlama, Chart, Pivot hataları düzeltildi.
This commit is contained in:
parent
39e4e448d7
commit
16036ce7f9
14 changed files with 295 additions and 46 deletions
|
|
@ -1231,8 +1231,6 @@ public class PlatformDbContext :
|
||||||
|
|
||||||
b.Property(x => x.SubmissionTime).IsRequired();
|
b.Property(x => x.SubmissionTime).IsRequired();
|
||||||
|
|
||||||
b.HasIndex(x => new { x.SurveyId, x.UserId }).IsUnique().HasFilter("[IsDeleted] = 0");
|
|
||||||
|
|
||||||
b.HasOne(x => x.Survey)
|
b.HasOne(x => x.Survey)
|
||||||
.WithMany(x => x.SurveyResponses)
|
.WithMany(x => x.SurveyResponses)
|
||||||
.HasForeignKey(x => x.SurveyId)
|
.HasForeignKey(x => x.SurveyId)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
||||||
namespace Sozsoft.Platform.Migrations
|
namespace Sozsoft.Platform.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(PlatformDbContext))]
|
[DbContext(typeof(PlatformDbContext))]
|
||||||
[Migration("20260619185755_Initial")]
|
[Migration("20260622213308_Initial")]
|
||||||
partial class Initial
|
partial class Initial
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -5470,9 +5470,7 @@ namespace Sozsoft.Platform.Migrations
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("SurveyId", "UserId")
|
b.HasIndex("SurveyId");
|
||||||
.IsUnique()
|
|
||||||
.HasFilter("[IsDeleted] = 0");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SurveyResponse", (string)null);
|
b.ToTable("Adm_T_SurveyResponse", (string)null);
|
||||||
});
|
});
|
||||||
|
|
@ -3808,11 +3808,9 @@ namespace Sozsoft.Platform.Migrations
|
||||||
column: "QuestionId");
|
column: "QuestionId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Adm_T_SurveyResponse_SurveyId_UserId",
|
name: "IX_Adm_T_SurveyResponse_SurveyId",
|
||||||
table: "Adm_T_SurveyResponse",
|
table: "Adm_T_SurveyResponse",
|
||||||
columns: new[] { "SurveyId", "UserId" },
|
column: "SurveyId");
|
||||||
unique: true,
|
|
||||||
filter: "[IsDeleted] = 0");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Adm_T_Videoroom_TenantId_BranchId_Name",
|
name: "IX_Adm_T_Videoroom_TenantId_BranchId_Name",
|
||||||
|
|
@ -5467,9 +5467,7 @@ namespace Sozsoft.Platform.Migrations
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("SurveyId", "UserId")
|
b.HasIndex("SurveyId");
|
||||||
.IsUnique()
|
|
||||||
.HasFilter("[IsDeleted] = 0");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SurveyResponse", (string)null);
|
b.ToTable("Adm_T_SurveyResponse", (string)null);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ public class DynamicFormReport : XtraReport
|
||||||
{
|
{
|
||||||
public const string ReportName = nameof(DynamicFormReport);
|
public const string ReportName = nameof(DynamicFormReport);
|
||||||
private const string QueryName = "DynamicForm";
|
private const string QueryName = "DynamicForm";
|
||||||
private const int HorizontalMargin = 35;
|
private const int HorizontalMargin = 50;
|
||||||
private const float RowHeight = 24;
|
private const float RowHeight = 24;
|
||||||
private const float ColumnGap = 10;
|
private const float ColumnGap = 10;
|
||||||
private static readonly System.Drawing.Color FieldBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
|
private static readonly System.Drawing.Color FieldBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public class DynamicGridReport : XtraReport
|
||||||
public const string ReportName = nameof(DynamicGridReport);
|
public const string ReportName = nameof(DynamicGridReport);
|
||||||
private const string QueryName = "DynamicGrid";
|
private const string QueryName = "DynamicGrid";
|
||||||
private const int A4PortraitWidth = 827;
|
private const int A4PortraitWidth = 827;
|
||||||
private const int HorizontalMargin = 35;
|
private const int HorizontalMargin = 50;
|
||||||
private const int LandscapeColumnThreshold = 5;
|
private const int LandscapeColumnThreshold = 5;
|
||||||
private static readonly System.Drawing.Color TableBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
|
private static readonly System.Drawing.Color TableBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
|
||||||
private static IServiceProvider _serviceProvider;
|
private static IServiceProvider _serviceProvider;
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace Sozsoft.Reports.PredefinedReports
|
||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DynamicReport));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DynamicReport));
|
||||||
this.TopMargin = new DevExpress.XtraReports.UI.TopMarginBand();
|
this.TopMargin = new DevExpress.XtraReports.UI.TopMarginBand();
|
||||||
this.BottomMargin = new DevExpress.XtraReports.UI.BottomMarginBand();
|
this.BottomMargin = new DevExpress.XtraReports.UI.BottomMarginBand();
|
||||||
this.pageInfo1 = new DevExpress.XtraReports.UI.XRPageInfo();
|
this.currentUserNameLabel = new DevExpress.XtraReports.UI.XRLabel();
|
||||||
this.pageInfo2 = new DevExpress.XtraReports.UI.XRPageInfo();
|
this.pageInfo2 = new DevExpress.XtraReports.UI.XRPageInfo();
|
||||||
this.ReportHeader = new DevExpress.XtraReports.UI.ReportHeaderBand();
|
this.ReportHeader = new DevExpress.XtraReports.UI.ReportHeaderBand();
|
||||||
this.label1 = new DevExpress.XtraReports.UI.XRLabel();
|
this.label1 = new DevExpress.XtraReports.UI.XRLabel();
|
||||||
|
|
@ -55,6 +55,10 @@ namespace Sozsoft.Reports.PredefinedReports
|
||||||
this.PageInfo = new DevExpress.XtraReports.UI.XRControlStyle();
|
this.PageInfo = new DevExpress.XtraReports.UI.XRControlStyle();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.xrRichText1)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.xrRichText1)).BeginInit();
|
||||||
((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
|
||||||
|
//
|
||||||
|
// ReportHeader
|
||||||
|
//
|
||||||
|
this.ReportHeader.HeightF = 35F;
|
||||||
//
|
//
|
||||||
// TopMargin
|
// TopMargin
|
||||||
//
|
//
|
||||||
|
|
@ -63,17 +67,16 @@ namespace Sozsoft.Reports.PredefinedReports
|
||||||
// BottomMargin
|
// BottomMargin
|
||||||
//
|
//
|
||||||
this.BottomMargin.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] {
|
this.BottomMargin.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] {
|
||||||
this.pageInfo1,
|
this.currentUserNameLabel,
|
||||||
this.pageInfo2});
|
this.pageInfo2});
|
||||||
this.BottomMargin.Name = "BottomMargin";
|
this.BottomMargin.Name = "BottomMargin";
|
||||||
//
|
//
|
||||||
// pageInfo1
|
// currentUserNameLabel
|
||||||
//
|
//
|
||||||
this.pageInfo1.LocationFloat = new DevExpress.Utils.PointFloat(0F, 0F);
|
this.currentUserNameLabel.LocationFloat = new DevExpress.Utils.PointFloat(0F, 0F);
|
||||||
this.pageInfo1.Name = "pageInfo1";
|
this.currentUserNameLabel.Name = "currentUserNameLabel";
|
||||||
this.pageInfo1.PageInfo = DevExpress.XtraPrinting.PageInfo.DateTime;
|
this.currentUserNameLabel.SizeF = new System.Drawing.SizeF(325F, 23F);
|
||||||
this.pageInfo1.SizeF = new System.Drawing.SizeF(325F, 23F);
|
this.currentUserNameLabel.StyleName = "PageInfo";
|
||||||
this.pageInfo1.StyleName = "PageInfo";
|
|
||||||
//
|
//
|
||||||
// pageInfo2
|
// pageInfo2
|
||||||
//
|
//
|
||||||
|
|
@ -196,7 +199,7 @@ namespace Sozsoft.Reports.PredefinedReports
|
||||||
|
|
||||||
private DevExpress.XtraReports.UI.TopMarginBand TopMargin;
|
private DevExpress.XtraReports.UI.TopMarginBand TopMargin;
|
||||||
private DevExpress.XtraReports.UI.BottomMarginBand BottomMargin;
|
private DevExpress.XtraReports.UI.BottomMarginBand BottomMargin;
|
||||||
private DevExpress.XtraReports.UI.XRPageInfo pageInfo1;
|
private DevExpress.XtraReports.UI.XRLabel currentUserNameLabel;
|
||||||
private DevExpress.XtraReports.UI.XRPageInfo pageInfo2;
|
private DevExpress.XtraReports.UI.XRPageInfo pageInfo2;
|
||||||
private DevExpress.XtraReports.UI.ReportHeaderBand ReportHeader;
|
private DevExpress.XtraReports.UI.ReportHeaderBand ReportHeader;
|
||||||
private DevExpress.XtraReports.UI.XRLabel label1;
|
private DevExpress.XtraReports.UI.XRLabel label1;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using DevExpress.Drawing;
|
||||||
|
using DevExpress.XtraPrinting;
|
||||||
using DevExpress.XtraReports.UI;
|
using DevExpress.XtraReports.UI;
|
||||||
using Sozsoft.Languages.Entities;
|
using Sozsoft.Languages.Entities;
|
||||||
using Sozsoft.Platform.EntityFrameworkCore;
|
using Sozsoft.Platform.EntityFrameworkCore;
|
||||||
|
|
@ -12,6 +14,9 @@ namespace Sozsoft.Reports.PredefinedReports;
|
||||||
|
|
||||||
public partial class DynamicReport : XtraReport
|
public partial class DynamicReport : XtraReport
|
||||||
{
|
{
|
||||||
|
private const int HorizontalMargin = 50;
|
||||||
|
private const int VerticalMargin = 35;
|
||||||
|
|
||||||
private Dictionary<string, string> _parameters;
|
private Dictionary<string, string> _parameters;
|
||||||
private static IServiceProvider _serviceProvider;
|
private static IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
|
@ -27,10 +32,7 @@ public partial class DynamicReport : XtraReport
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
// A4 kağıt ayarları
|
ConfigurePage();
|
||||||
this.PageHeight = 1169;
|
|
||||||
this.PageWidth = 827;
|
|
||||||
this.Landscape = false;
|
|
||||||
|
|
||||||
_parameters = new Dictionary<string, string>();
|
_parameters = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
|
@ -40,15 +42,39 @@ public partial class DynamicReport : XtraReport
|
||||||
AddFooterCurrentUserName();
|
AddFooterCurrentUserName();
|
||||||
AddFooterLine();
|
AddFooterLine();
|
||||||
|
|
||||||
pageInfo1.Visible = false;
|
|
||||||
xrRichText1.BeforePrint += XrRichText1_BeforePrint;
|
xrRichText1.BeforePrint += XrRichText1_BeforePrint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
private void ConfigurePage()
|
||||||
|
{
|
||||||
|
PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4;
|
||||||
|
Landscape = false;
|
||||||
|
Margins = new System.Drawing.Printing.Margins(
|
||||||
|
HorizontalMargin,
|
||||||
|
HorizontalMargin,
|
||||||
|
VerticalMargin,
|
||||||
|
VerticalMargin);
|
||||||
|
Font = new DXFont("Arial", 8.25F);
|
||||||
|
|
||||||
|
TopMargin.HeightF = Margins.Top;
|
||||||
|
BottomMargin.HeightF = Margins.Bottom;
|
||||||
|
|
||||||
|
var pageWidth = PageWidth - Margins.Left - Margins.Right;
|
||||||
|
xrRichText1.WidthF = pageWidth;
|
||||||
|
currentUserNameLabel.LocationFloat = new DevExpress.Utils.PointFloat(0, 8);
|
||||||
|
currentUserNameLabel.SizeF = new System.Drawing.SizeF(pageWidth / 2, 18);
|
||||||
|
currentUserNameLabel.TextAlignment = TextAlignment.MiddleLeft;
|
||||||
|
pageInfo2.LocationFloat = new DevExpress.Utils.PointFloat(pageWidth / 2, 8);
|
||||||
|
pageInfo2.SizeF = new System.Drawing.SizeF(pageWidth / 2, 18);
|
||||||
|
pageInfo2.TextAlignment = TextAlignment.MiddleRight;
|
||||||
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
|
||||||
private void AddFooterLine()
|
private void AddFooterLine()
|
||||||
{
|
{
|
||||||
var pageWidth = PageWidth - Margins.Left - Margins.Right;
|
var pageWidth = PageWidth - Margins.Left - Margins.Right;
|
||||||
DynamicReportImageHelper.AddFooterTopLine(BottomMargin.Controls, pageWidth);
|
DynamicReportImageHelper.AddFooterTopLine(BottomMargin.Controls, pageWidth);
|
||||||
pageInfo1.TopF = 8;
|
|
||||||
pageInfo2.TopF = 8;
|
pageInfo2.TopF = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,8 +95,7 @@ public partial class DynamicReport : XtraReport
|
||||||
|
|
||||||
using var scope = _serviceProvider.CreateScope();
|
using var scope = _serviceProvider.CreateScope();
|
||||||
var currentUser = scope.ServiceProvider.GetRequiredService<ICurrentUser>();
|
var currentUser = scope.ServiceProvider.GetRequiredService<ICurrentUser>();
|
||||||
var pageWidth = PageWidth - Margins.Left - Margins.Right;
|
currentUserNameLabel.Text = currentUser.UserName ?? string.Empty;
|
||||||
DynamicReportImageHelper.AddCurrentUserNameToFooter(BottomMargin.Controls, currentUser.UserName, pageWidth);
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public class DynamicTreeReport : XtraReport
|
||||||
{
|
{
|
||||||
public const string ReportName = nameof(DynamicTreeReport);
|
public const string ReportName = nameof(DynamicTreeReport);
|
||||||
private const int A4PortraitWidth = 827;
|
private const int A4PortraitWidth = 827;
|
||||||
private const int HorizontalMargin = 35;
|
private const int HorizontalMargin = 50;
|
||||||
private const int LandscapeColumnThreshold = 5;
|
private const int LandscapeColumnThreshold = 5;
|
||||||
private const string TreeLevelColumn = "__TreeLevel";
|
private const string TreeLevelColumn = "__TreeLevel";
|
||||||
private const string TreeHasChildrenColumn = "__TreeHasChildren";
|
private const string TreeHasChildrenColumn = "__TreeHasChildren";
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ using System.Linq;
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using DevExpress.XtraPrinting;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Volo.Abp.Users;
|
||||||
|
|
||||||
namespace Sozsoft.Platform.ReportServices;
|
namespace Sozsoft.Platform.ReportServices;
|
||||||
|
|
||||||
|
|
@ -48,11 +51,11 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
||||||
this.reportDirectory = reportDirectory;
|
this.reportDirectory = reportDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsWithinReportsFolder(string url, string folder)
|
private static bool IsSafeReportFileName(string reportName)
|
||||||
{
|
{
|
||||||
var rootDirectory = new DirectoryInfo(folder);
|
return !string.IsNullOrWhiteSpace(reportName) &&
|
||||||
var fileInfo = new FileInfo(Path.Combine(folder, url));
|
Path.GetFileName(reportName) == reportName &&
|
||||||
return fileInfo.Directory.FullName.ToLower().StartsWith(rootDirectory.FullName.ToLower());
|
reportName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanSetData(string url)
|
public override bool CanSetData(string url)
|
||||||
|
|
@ -72,8 +75,8 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
||||||
// Return **true** if no validation is required.
|
// Return **true** if no validation is required.
|
||||||
|
|
||||||
// Query string veya path parametreleri gelse bile sadece rapor adını kontrol et.
|
// Query string veya path parametreleri gelse bile sadece rapor adını kontrol et.
|
||||||
var (reportName, _) = ParseReportUrl(url);
|
var reportName = GetStorageReportName(url);
|
||||||
return Path.GetFileName(reportName) == reportName;
|
return IsSafeReportFileName(reportName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] GetData(string url)
|
public override byte[] GetData(string url)
|
||||||
|
|
@ -181,7 +184,13 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
||||||
return SaveReportLayout(report);
|
return SaveReportLayout(report);
|
||||||
}
|
}
|
||||||
|
|
||||||
var reportData = TryGetStoredReportData(reportName, parameters);
|
var storedReportName = GetStoredReportName(reportName, parameters);
|
||||||
|
var isDynamicReport = IsDynamicReport(reportName);
|
||||||
|
var reportData = TryGetStoredReportData(storedReportName, parameters, isDynamicReport);
|
||||||
|
if (reportData == null && !string.Equals(storedReportName, reportName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
reportData = TryGetStoredReportData(reportName, parameters, isDynamicReport);
|
||||||
|
}
|
||||||
if (reportData != null)
|
if (reportData != null)
|
||||||
{
|
{
|
||||||
return reportData;
|
return reportData;
|
||||||
|
|
@ -195,7 +204,10 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
||||||
throw new FaultException(new FaultReason(string.Format("Could not find report '{0}'.", url)), new FaultCode("Server"), "GetData");
|
throw new FaultException(new FaultReason(string.Format("Could not find report '{0}'.", url)), new FaultCode("Server"), "GetData");
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] TryGetStoredReportData(string reportName, Dictionary<string, string> parameters)
|
private byte[] TryGetStoredReportData(
|
||||||
|
string reportName,
|
||||||
|
Dictionary<string, string> parameters,
|
||||||
|
bool isDynamicReport)
|
||||||
{
|
{
|
||||||
var report = TryLoadStoredReport(reportName);
|
var report = TryLoadStoredReport(reportName);
|
||||||
if (report == null)
|
if (report == null)
|
||||||
|
|
@ -204,9 +216,52 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyReportParameters(report, parameters);
|
ApplyReportParameters(report, parameters);
|
||||||
|
if (isDynamicReport)
|
||||||
|
{
|
||||||
|
ApplyDynamicReportFooter(report);
|
||||||
|
}
|
||||||
return SaveReportLayout(report);
|
return SaveReportLayout(report);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplyDynamicReportFooter(XtraReport report)
|
||||||
|
{
|
||||||
|
var bottomMargin = report.Bands.OfType<BottomMarginBand>().FirstOrDefault();
|
||||||
|
if (bottomMargin == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pageWidth = report.PageWidth - report.Margins.Left - report.Margins.Right;
|
||||||
|
var legacyDateTime = bottomMargin.Controls
|
||||||
|
.OfType<XRPageInfo>()
|
||||||
|
.FirstOrDefault(control =>
|
||||||
|
string.Equals(control.Name, "pageInfo1", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
control.PageInfo == PageInfo.DateTime);
|
||||||
|
if (legacyDateTime != null)
|
||||||
|
{
|
||||||
|
legacyDateTime.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userNameLabel = bottomMargin.Controls
|
||||||
|
.OfType<XRLabel>()
|
||||||
|
.FirstOrDefault(control =>
|
||||||
|
string.Equals(control.Name, "currentUserNameLabel", StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (userNameLabel == null)
|
||||||
|
{
|
||||||
|
userNameLabel = new XRLabel { Name = "currentUserNameLabel" };
|
||||||
|
bottomMargin.Controls.Add(userNameLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
using var scope = _serviceProvider.CreateScope();
|
||||||
|
var currentUser = scope.ServiceProvider.GetService<ICurrentUser>();
|
||||||
|
userNameLabel.Text = currentUser?.Name ?? currentUser?.UserName ?? string.Empty;
|
||||||
|
userNameLabel.BoundsF = new System.Drawing.RectangleF(0, 8, pageWidth / 2, 18);
|
||||||
|
userNameLabel.Font = new DevExpress.Drawing.DXFont("Arial", 7.5F);
|
||||||
|
userNameLabel.TextAlignment = TextAlignment.MiddleLeft;
|
||||||
|
userNameLabel.CanGrow = false;
|
||||||
|
userNameLabel.Multiline = false;
|
||||||
|
}
|
||||||
|
|
||||||
private XtraReport TryLoadStoredReport(string reportName)
|
private XtraReport TryLoadStoredReport(string reportName)
|
||||||
{
|
{
|
||||||
if (Directory.EnumerateFiles(reportDirectory).Select(Path.GetFileNameWithoutExtension).Contains(reportName))
|
if (Directory.EnumerateFiles(reportDirectory).Select(Path.GetFileNameWithoutExtension).Contains(reportName))
|
||||||
|
|
@ -329,6 +384,20 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
||||||
parameters.TryAdd("id", pathParameters[0]);
|
parameters.TryAdd("id", pathParameters[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetStorageReportName(string url)
|
||||||
|
{
|
||||||
|
var (reportName, parameters) = ParseReportUrl(url);
|
||||||
|
return GetStoredReportName(reportName, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetStoredReportName(string reportName, Dictionary<string, string> parameters)
|
||||||
|
{
|
||||||
|
return string.Equals(reportName, nameof(Sozsoft.Reports.PredefinedReports.DynamicReport), StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
HasParameter(parameters, "id")
|
||||||
|
? parameters["id"]
|
||||||
|
: reportName;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool IsDynamicGridReport(string reportName)
|
private static bool IsDynamicGridReport(string reportName)
|
||||||
{
|
{
|
||||||
return string.Equals(reportName, "DynamicGrid", StringComparison.OrdinalIgnoreCase) ||
|
return string.Equals(reportName, "DynamicGrid", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
|
@ -347,6 +416,14 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
||||||
string.Equals(reportName, Sozsoft.Reports.PredefinedReports.DynamicFormReport.ReportName, StringComparison.OrdinalIgnoreCase);
|
string.Equals(reportName, Sozsoft.Reports.PredefinedReports.DynamicFormReport.ReportName, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsDynamicReport(string reportName)
|
||||||
|
{
|
||||||
|
return string.Equals(
|
||||||
|
reportName,
|
||||||
|
nameof(Sozsoft.Reports.PredefinedReports.DynamicReport),
|
||||||
|
StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
private static bool IsReportActionSegment(string value)
|
private static bool IsReportActionSegment(string value)
|
||||||
{
|
{
|
||||||
return string.Equals(value, "view", StringComparison.OrdinalIgnoreCase) ||
|
return string.Equals(value, "view", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
|
@ -403,9 +480,12 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
||||||
{
|
{
|
||||||
// Saves the specified report to the report storage with the specified name
|
// Saves the specified report to the report storage with the specified name
|
||||||
// (saves existing reports only).
|
// (saves existing reports only).
|
||||||
if (!IsWithinReportsFolder(url, reportDirectory))
|
var reportName = GetStorageReportName(url);
|
||||||
|
if (!IsSafeReportFileName(reportName))
|
||||||
throw new FaultException(new FaultReason("Invalid report name."), new FaultCode("Server"), "GetData");
|
throw new FaultException(new FaultReason("Invalid report name."), new FaultCode("Server"), "GetData");
|
||||||
report.SaveLayoutToXml(Path.Combine(reportDirectory, url + FileExtension));
|
|
||||||
|
Directory.CreateDirectory(reportDirectory);
|
||||||
|
report.SaveLayoutToXml(Path.Combine(reportDirectory, reportName + FileExtension));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string SetNewData(XtraReport report, string defaultUrl)
|
public override string SetNewData(XtraReport report, string defaultUrl)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ import {
|
||||||
} from '@/services/admin/list-form.service'
|
} from '@/services/admin/list-form.service'
|
||||||
import { layoutTypes } from '../admin/listForm/edit/types'
|
import { layoutTypes } from '../admin/listForm/edit/types'
|
||||||
import { useListFormCustomDataSource } from './useListFormCustomDataSource'
|
import { useListFormCustomDataSource } from './useListFormCustomDataSource'
|
||||||
|
import { useListFormColumns } from './useListFormColumns'
|
||||||
|
import { GridColumnData } from './GridColumnData'
|
||||||
import Toolbar, { Item } from 'devextreme-react/toolbar'
|
import Toolbar, { Item } from 'devextreme-react/toolbar'
|
||||||
|
|
||||||
interface ChartProps extends CommonProps, Meta {
|
interface ChartProps extends CommonProps, Meta {
|
||||||
|
|
@ -39,6 +41,8 @@ interface ChartProps extends CommonProps, Meta {
|
||||||
refreshGridDto?: () => Promise<void>
|
refreshGridDto?: () => Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LookupDisplayValues = Record<string, Map<string, string>>
|
||||||
|
|
||||||
const Chart = (props: ChartProps) => {
|
const Chart = (props: ChartProps) => {
|
||||||
// State UserId güncellemesi için
|
// State UserId güncellemesi için
|
||||||
const { userName } = useStoreState((s) => s.auth.user)
|
const { userName } = useStoreState((s) => s.auth.user)
|
||||||
|
|
@ -51,6 +55,12 @@ const Chart = (props: ChartProps) => {
|
||||||
const [searchParams] = useSearchParams()
|
const [searchParams] = useSearchParams()
|
||||||
const [chartOptions, setChartOptions] = useState<any>()
|
const [chartOptions, setChartOptions] = useState<any>()
|
||||||
const { createSelectDataSource } = useListFormCustomDataSource({} as any)
|
const { createSelectDataSource } = useListFormCustomDataSource({} as any)
|
||||||
|
const { loadLookupDisplayValues } = useListFormColumns({
|
||||||
|
gridDto,
|
||||||
|
listFormCode,
|
||||||
|
isSubForm,
|
||||||
|
})
|
||||||
|
const [lookupDisplayValues, setLookupDisplayValues] = useState<LookupDisplayValues>({})
|
||||||
|
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const _listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
|
const _listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
|
||||||
|
|
@ -94,6 +104,34 @@ const Chart = (props: ChartProps) => {
|
||||||
|
|
||||||
const [allSeries, setAllSeries] = useState<ChartSeriesDto[]>([])
|
const [allSeries, setAllSeries] = useState<ChartSeriesDto[]>([])
|
||||||
|
|
||||||
|
const lookupColumns = useMemo<GridColumnData[]>(
|
||||||
|
() =>
|
||||||
|
gridDto?.columnFormats
|
||||||
|
.filter((column) => column.fieldName)
|
||||||
|
.map((column) => ({ dataField: column.fieldName, colData: column })) ?? [],
|
||||||
|
[gridDto?.columnFormats],
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let isActive = true
|
||||||
|
|
||||||
|
const loadValues = async () => {
|
||||||
|
try {
|
||||||
|
const values = await loadLookupDisplayValues(lookupColumns)
|
||||||
|
if (isActive) {
|
||||||
|
setLookupDisplayValues(values)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Chart lookup load error:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadValues()
|
||||||
|
return () => {
|
||||||
|
isActive = false
|
||||||
|
}
|
||||||
|
}, [lookupColumns, loadLookupDisplayValues])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (gridDto) {
|
if (gridDto) {
|
||||||
const initialSeries = gridDto.gridOptions.seriesDto.map((s, index) => ({ ...s, index }))
|
const initialSeries = gridDto.gridOptions.seriesDto.map((s, index) => ({ ...s, index }))
|
||||||
|
|
@ -134,6 +172,10 @@ const Chart = (props: ChartProps) => {
|
||||||
layoutTypes.chart,
|
layoutTypes.chart,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const argumentLookupValues = currentSeries
|
||||||
|
.map((series) => (series.argumentField ? lookupDisplayValues[series.argumentField] : undefined))
|
||||||
|
.find((values) => values?.size)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dataSource: dataSource,
|
dataSource: dataSource,
|
||||||
|
|
||||||
|
|
@ -165,7 +207,20 @@ const Chart = (props: ChartProps) => {
|
||||||
animation: gridDto.gridOptions.animationDto,
|
animation: gridDto.gridOptions.animationDto,
|
||||||
export: gridDto.gridOptions.exportDto,
|
export: gridDto.gridOptions.exportDto,
|
||||||
crosshair: gridDto.gridOptions.crosshairDto,
|
crosshair: gridDto.gridOptions.crosshairDto,
|
||||||
argumentAxis: gridDto.gridOptions.argumentAxisDto,
|
argumentAxis: {
|
||||||
|
...gridDto.gridOptions.argumentAxisDto,
|
||||||
|
label: {
|
||||||
|
...gridDto.gridOptions.argumentAxisDto?.label,
|
||||||
|
...(argumentLookupValues
|
||||||
|
? {
|
||||||
|
customizeText: (argument: any) => {
|
||||||
|
const value = argument.value ?? argument.valueText
|
||||||
|
return argumentLookupValues.get(String(value)) ?? argument.valueText ?? String(value ?? '')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
},
|
||||||
|
},
|
||||||
valueAxis: gridDto.gridOptions.valueAxisDto,
|
valueAxis: gridDto.gridOptions.valueAxisDto,
|
||||||
tooltip: gridDto.gridOptions.tooltipDto || {
|
tooltip: gridDto.gridOptions.tooltipDto || {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
@ -194,6 +249,7 @@ const Chart = (props: ChartProps) => {
|
||||||
listFormCode,
|
listFormCode,
|
||||||
urlSearchParams,
|
urlSearchParams,
|
||||||
openDrawer,
|
openDrawer,
|
||||||
|
lookupDisplayValues,
|
||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@ interface PivotProps {
|
||||||
|
|
||||||
const statedGridPanelColor = 'rgba(50, 200, 200, 0.5)' // kullanici tanimli gridState ile islem gormus gridin paneline ait renk
|
const statedGridPanelColor = 'rgba(50, 200, 200, 0.5)' // kullanici tanimli gridState ile islem gormus gridin paneline ait renk
|
||||||
|
|
||||||
|
type LookupDisplayValues = Record<string, Map<string, string>>
|
||||||
|
|
||||||
const Pivot = (props: PivotProps) => {
|
const Pivot = (props: PivotProps) => {
|
||||||
const { listFormCode, searchParams, isSubForm, level, gridDto } = props
|
const { listFormCode, searchParams, isSubForm, level, gridDto } = props
|
||||||
const { translate } = useLocalization()
|
const { translate } = useLocalization()
|
||||||
|
|
@ -68,6 +70,7 @@ const Pivot = (props: PivotProps) => {
|
||||||
|
|
||||||
const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>()
|
const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>()
|
||||||
const [columnData, setColumnData] = useState<GridColumnData[]>()
|
const [columnData, setColumnData] = useState<GridColumnData[]>()
|
||||||
|
const [lookupDisplayValues, setLookupDisplayValues] = useState<LookupDisplayValues>({})
|
||||||
const [showChart, setShowChart] = useState(false)
|
const [showChart, setShowChart] = useState(false)
|
||||||
|
|
||||||
// StateStoring için storageKey'i memoize et
|
// StateStoring için storageKey'i memoize et
|
||||||
|
|
@ -82,7 +85,7 @@ const Pivot = (props: PivotProps) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })
|
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })
|
||||||
const { getBandedColumns } = useListFormColumns({
|
const { getBandedColumns, loadLookupDisplayValues } = useListFormColumns({
|
||||||
gridDto,
|
gridDto,
|
||||||
listFormCode,
|
listFormCode,
|
||||||
isSubForm,
|
isSubForm,
|
||||||
|
|
@ -355,6 +358,30 @@ const Pivot = (props: PivotProps) => {
|
||||||
}
|
}
|
||||||
}, [memoizedColumns])
|
}, [memoizedColumns])
|
||||||
|
|
||||||
|
// PivotGrid, DataGrid'deki lookup ayarını doğrudan desteklemez. Lookup değerlerini
|
||||||
|
// yükleyip sadece görünen metni dönüştürüyoruz; gruplama/filtreleme gerçek value ile devam eder.
|
||||||
|
useEffect(() => {
|
||||||
|
let isActive = true
|
||||||
|
|
||||||
|
const loadValues = async () => {
|
||||||
|
if (!columnData) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const values = await loadLookupDisplayValues(columnData)
|
||||||
|
if (isActive) {
|
||||||
|
setLookupDisplayValues(values)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Pivot lookup load error:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadValues()
|
||||||
|
return () => {
|
||||||
|
isActive = false
|
||||||
|
}
|
||||||
|
}, [columnData, loadLookupDisplayValues])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (memoizedDataSource) {
|
if (memoizedDataSource) {
|
||||||
setGridDataSource(memoizedDataSource)
|
setGridDataSource(memoizedDataSource)
|
||||||
|
|
@ -384,6 +411,7 @@ const Pivot = (props: PivotProps) => {
|
||||||
|
|
||||||
// Default fields'i hazırla
|
// Default fields'i hazırla
|
||||||
const defaultFields: any = columnData?.map((b) => {
|
const defaultFields: any = columnData?.map((b) => {
|
||||||
|
const lookupValues = b.dataField ? lookupDisplayValues[b.dataField] : undefined
|
||||||
return {
|
return {
|
||||||
dataField: b.dataField,
|
dataField: b.dataField,
|
||||||
caption: b.caption,
|
caption: b.caption,
|
||||||
|
|
@ -397,6 +425,14 @@ const Pivot = (props: PivotProps) => {
|
||||||
wordWrapEnabled: b.colData?.pivotSettingsDto.wordWrapEnabled,
|
wordWrapEnabled: b.colData?.pivotSettingsDto.wordWrapEnabled,
|
||||||
visible: true,
|
visible: true,
|
||||||
width: b.width,
|
width: b.width,
|
||||||
|
...(lookupValues
|
||||||
|
? {
|
||||||
|
customizeText: (cellInfo: any) => {
|
||||||
|
const value = cellInfo.value ?? cellInfo.valueText
|
||||||
|
return lookupValues.get(String(value)) ?? cellInfo.valueText ?? String(value ?? '')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
} as Field
|
} as Field
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -408,7 +444,7 @@ const Pivot = (props: PivotProps) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.option('dataSource', dataSource)
|
instance.option('dataSource', dataSource)
|
||||||
}, [columnData, gridDataSource, gridDto])
|
}, [columnData, gridDataSource, gridDto, lookupDisplayValues])
|
||||||
|
|
||||||
// Component mount olduğunda state'i bir kez yükle
|
// Component mount olduğunda state'i bir kez yükle
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -435,6 +435,50 @@ const useListFormColumns = ({
|
||||||
[listFormCode],
|
[listFormCode],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const loadLookupDisplayValues = useCallback(
|
||||||
|
async (columns: GridColumnData[]) => {
|
||||||
|
const entries = await Promise.all(
|
||||||
|
columns
|
||||||
|
.filter(
|
||||||
|
(column) =>
|
||||||
|
column.dataField &&
|
||||||
|
column.colData?.lookupDto?.dataSourceType &&
|
||||||
|
!column.colData.lookupDto.cascadeParentFields,
|
||||||
|
)
|
||||||
|
.map(async (column) => {
|
||||||
|
const lookup = column.colData!.lookupDto
|
||||||
|
const source = lookupDataSource({}, column.colData, listFormCode)
|
||||||
|
const store =
|
||||||
|
source instanceof CustomStore
|
||||||
|
? source
|
||||||
|
: (source as { store?: CustomStore<any, any> } | undefined)?.store
|
||||||
|
const items = ((await store?.load?.()) ?? []) as Record<string, any>[]
|
||||||
|
const values = new Map<string, string>()
|
||||||
|
|
||||||
|
items.forEach((item: Record<string, any>) => {
|
||||||
|
const getValue = (expression?: string) => {
|
||||||
|
const key = Object.keys(item).find(
|
||||||
|
(itemKey) => itemKey.toLowerCase() === expression?.toLowerCase(),
|
||||||
|
)
|
||||||
|
return key ? item[key] : undefined
|
||||||
|
}
|
||||||
|
const value = getValue(lookup.valueExpr)
|
||||||
|
const text = getValue(lookup.displayExpr)
|
||||||
|
|
||||||
|
if (value !== undefined && value !== null && text !== undefined && text !== null) {
|
||||||
|
values.set(String(value), String(text))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return [column.dataField!, values] as const
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
return Object.fromEntries(entries) as Record<string, Map<string, string>>
|
||||||
|
},
|
||||||
|
[listFormCode, lookupDataSource],
|
||||||
|
)
|
||||||
|
|
||||||
const createLookupStaticDataSource = (
|
const createLookupStaticDataSource = (
|
||||||
load: () => any,
|
load: () => any,
|
||||||
filter: any = null,
|
filter: any = null,
|
||||||
|
|
@ -1036,6 +1080,7 @@ const useListFormColumns = ({
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getBandedColumns,
|
getBandedColumns,
|
||||||
|
loadLookupDisplayValues,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ const ReportDesigner = lazy(() =>
|
||||||
|
|
||||||
const VIEWER_THEME_LINK_ID = 'devexpress-report-viewer-theme'
|
const VIEWER_THEME_LINK_ID = 'devexpress-report-viewer-theme'
|
||||||
const VIEWER_DARK_OVERRIDES_ID = 'devexpress-report-viewer-dark-overrides'
|
const VIEWER_DARK_OVERRIDES_ID = 'devexpress-report-viewer-dark-overrides'
|
||||||
|
const REPORT_DESIGNER_CSS_ID = 'devexpress-report-designer-css'
|
||||||
|
|
||||||
const getViewerClassName = (isDarkMode: boolean) =>
|
const getViewerClassName = (isDarkMode: boolean) =>
|
||||||
[
|
[
|
||||||
|
|
@ -58,6 +59,17 @@ const loadViewerCss = (isDarkMode: boolean) => {
|
||||||
if (themeLink.href !== themeHref) {
|
if (themeLink.href !== themeHref) {
|
||||||
themeLink.href = themeHref
|
themeLink.href = themeHref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!document.getElementById(REPORT_DESIGNER_CSS_ID)) {
|
||||||
|
const designerLink = document.createElement('link')
|
||||||
|
designerLink.id = REPORT_DESIGNER_CSS_ID
|
||||||
|
designerLink.rel = 'stylesheet'
|
||||||
|
designerLink.href = new URL(
|
||||||
|
'devexpress-reporting/dist/css/dx-reportdesigner.css',
|
||||||
|
import.meta.url,
|
||||||
|
).href
|
||||||
|
document.head.appendChild(designerLink)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DevexpressReportDesigner: React.FC = () => {
|
const DevexpressReportDesigner: React.FC = () => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue