diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs
index 2af5040..16b69ae 100644
--- a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs
+++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs
@@ -1231,8 +1231,6 @@ public class PlatformDbContext :
b.Property(x => x.SubmissionTime).IsRequired();
- b.HasIndex(x => new { x.SurveyId, x.UserId }).IsUnique().HasFilter("[IsDeleted] = 0");
-
b.HasOne(x => x.Survey)
.WithMany(x => x.SurveyResponses)
.HasForeignKey(x => x.SurveyId)
diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260619185755_Initial.Designer.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260622213308_Initial.Designer.cs
similarity index 99%
rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260619185755_Initial.Designer.cs
rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260622213308_Initial.Designer.cs
index 938a71d..bddb82d 100644
--- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260619185755_Initial.Designer.cs
+++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260622213308_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Sozsoft.Platform.Migrations
{
[DbContext(typeof(PlatformDbContext))]
- [Migration("20260619185755_Initial")]
+ [Migration("20260622213308_Initial")]
partial class Initial
{
///
@@ -5470,9 +5470,7 @@ namespace Sozsoft.Platform.Migrations
b.HasKey("Id");
- b.HasIndex("SurveyId", "UserId")
- .IsUnique()
- .HasFilter("[IsDeleted] = 0");
+ b.HasIndex("SurveyId");
b.ToTable("Adm_T_SurveyResponse", (string)null);
});
diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260619185755_Initial.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260622213308_Initial.cs
similarity index 99%
rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260619185755_Initial.cs
rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260622213308_Initial.cs
index 003a7a4..5613d37 100644
--- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260619185755_Initial.cs
+++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260622213308_Initial.cs
@@ -3808,11 +3808,9 @@ namespace Sozsoft.Platform.Migrations
column: "QuestionId");
migrationBuilder.CreateIndex(
- name: "IX_Adm_T_SurveyResponse_SurveyId_UserId",
+ name: "IX_Adm_T_SurveyResponse_SurveyId",
table: "Adm_T_SurveyResponse",
- columns: new[] { "SurveyId", "UserId" },
- unique: true,
- filter: "[IsDeleted] = 0");
+ column: "SurveyId");
migrationBuilder.CreateIndex(
name: "IX_Adm_T_Videoroom_TenantId_BranchId_Name",
diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs
index eba8393..ff51bb1 100644
--- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs
+++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs
@@ -5467,9 +5467,7 @@ namespace Sozsoft.Platform.Migrations
b.HasKey("Id");
- b.HasIndex("SurveyId", "UserId")
- .IsUnique()
- .HasFilter("[IsDeleted] = 0");
+ b.HasIndex("SurveyId");
b.ToTable("Adm_T_SurveyResponse", (string)null);
});
diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicFormReport.cs b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicFormReport.cs
index e24ab21..a32d473 100644
--- a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicFormReport.cs
+++ b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicFormReport.cs
@@ -28,7 +28,7 @@ public class DynamicFormReport : XtraReport
{
public const string ReportName = nameof(DynamicFormReport);
private const string QueryName = "DynamicForm";
- private const int HorizontalMargin = 35;
+ private const int HorizontalMargin = 50;
private const float RowHeight = 24;
private const float ColumnGap = 10;
private static readonly System.Drawing.Color FieldBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicGridReport.cs b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicGridReport.cs
index bcd2171..00b5a18 100644
--- a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicGridReport.cs
+++ b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicGridReport.cs
@@ -27,7 +27,7 @@ public class DynamicGridReport : XtraReport
public const string ReportName = nameof(DynamicGridReport);
private const string QueryName = "DynamicGrid";
private const int A4PortraitWidth = 827;
- private const int HorizontalMargin = 35;
+ private const int HorizontalMargin = 50;
private const int LandscapeColumnThreshold = 5;
private static readonly System.Drawing.Color TableBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
private static IServiceProvider _serviceProvider;
diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicReport.Designer.cs b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicReport.Designer.cs
index ed55324..73df6cd 100644
--- a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicReport.Designer.cs
+++ b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicReport.Designer.cs
@@ -39,7 +39,7 @@ namespace Sozsoft.Reports.PredefinedReports
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DynamicReport));
this.TopMargin = new DevExpress.XtraReports.UI.TopMarginBand();
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.ReportHeader = new DevExpress.XtraReports.UI.ReportHeaderBand();
this.label1 = new DevExpress.XtraReports.UI.XRLabel();
@@ -55,6 +55,10 @@ namespace Sozsoft.Reports.PredefinedReports
this.PageInfo = new DevExpress.XtraReports.UI.XRControlStyle();
((System.ComponentModel.ISupportInitialize)(this.xrRichText1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
+ //
+ // ReportHeader
+ //
+ this.ReportHeader.HeightF = 35F;
//
// TopMargin
//
@@ -63,17 +67,16 @@ namespace Sozsoft.Reports.PredefinedReports
// BottomMargin
//
this.BottomMargin.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] {
- this.pageInfo1,
+ this.currentUserNameLabel,
this.pageInfo2});
this.BottomMargin.Name = "BottomMargin";
//
- // pageInfo1
+ // currentUserNameLabel
//
- this.pageInfo1.LocationFloat = new DevExpress.Utils.PointFloat(0F, 0F);
- this.pageInfo1.Name = "pageInfo1";
- this.pageInfo1.PageInfo = DevExpress.XtraPrinting.PageInfo.DateTime;
- this.pageInfo1.SizeF = new System.Drawing.SizeF(325F, 23F);
- this.pageInfo1.StyleName = "PageInfo";
+ this.currentUserNameLabel.LocationFloat = new DevExpress.Utils.PointFloat(0F, 0F);
+ this.currentUserNameLabel.Name = "currentUserNameLabel";
+ this.currentUserNameLabel.SizeF = new System.Drawing.SizeF(325F, 23F);
+ this.currentUserNameLabel.StyleName = "PageInfo";
//
// pageInfo2
//
@@ -196,7 +199,7 @@ namespace Sozsoft.Reports.PredefinedReports
private DevExpress.XtraReports.UI.TopMarginBand TopMargin;
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.ReportHeaderBand ReportHeader;
private DevExpress.XtraReports.UI.XRLabel label1;
diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicReport.cs b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicReport.cs
index 8fa2a13..3dfd2f2 100644
--- a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicReport.cs
+++ b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicReport.cs
@@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
+using DevExpress.Drawing;
+using DevExpress.XtraPrinting;
using DevExpress.XtraReports.UI;
using Sozsoft.Languages.Entities;
using Sozsoft.Platform.EntityFrameworkCore;
@@ -12,6 +14,9 @@ namespace Sozsoft.Reports.PredefinedReports;
public partial class DynamicReport : XtraReport
{
+ private const int HorizontalMargin = 50;
+ private const int VerticalMargin = 35;
+
private Dictionary _parameters;
private static IServiceProvider _serviceProvider;
@@ -27,10 +32,7 @@ public partial class DynamicReport : XtraReport
{
InitializeComponent();
- // A4 kağıt ayarları
- this.PageHeight = 1169;
- this.PageWidth = 827;
- this.Landscape = false;
+ ConfigurePage();
_parameters = new Dictionary();
@@ -40,15 +42,39 @@ public partial class DynamicReport : XtraReport
AddFooterCurrentUserName();
AddFooterLine();
- pageInfo1.Visible = false;
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()
{
var pageWidth = PageWidth - Margins.Left - Margins.Right;
DynamicReportImageHelper.AddFooterTopLine(BottomMargin.Controls, pageWidth);
- pageInfo1.TopF = 8;
pageInfo2.TopF = 8;
}
@@ -69,8 +95,7 @@ public partial class DynamicReport : XtraReport
using var scope = _serviceProvider.CreateScope();
var currentUser = scope.ServiceProvider.GetRequiredService();
- var pageWidth = PageWidth - Margins.Left - Margins.Right;
- DynamicReportImageHelper.AddCurrentUserNameToFooter(BottomMargin.Controls, currentUser.UserName, pageWidth);
+ currentUserNameLabel.Text = currentUser.UserName ?? string.Empty;
}
catch
{
diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicTreeReport.cs b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicTreeReport.cs
index b6cb6c7..7be7aa3 100644
--- a/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicTreeReport.cs
+++ b/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicTreeReport.cs
@@ -27,7 +27,7 @@ public class DynamicTreeReport : XtraReport
{
public const string ReportName = nameof(DynamicTreeReport);
private const int A4PortraitWidth = 827;
- private const int HorizontalMargin = 35;
+ private const int HorizontalMargin = 50;
private const int LandscapeColumnThreshold = 5;
private const string TreeLevelColumn = "__TreeLevel";
private const string TreeHasChildrenColumn = "__TreeHasChildren";
diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/ReportServices/CustomReportStorageWebExtension.cs b/api/src/Sozsoft.Platform.HttpApi.Host/ReportServices/CustomReportStorageWebExtension.cs
index 4cd2fb9..e993f7d 100644
--- a/api/src/Sozsoft.Platform.HttpApi.Host/ReportServices/CustomReportStorageWebExtension.cs
+++ b/api/src/Sozsoft.Platform.HttpApi.Host/ReportServices/CustomReportStorageWebExtension.cs
@@ -4,6 +4,9 @@ using System.Linq;
using System;
using System.Reflection;
using System.Threading.Tasks;
+using DevExpress.XtraPrinting;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Users;
namespace Sozsoft.Platform.ReportServices;
@@ -48,11 +51,11 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
this.reportDirectory = reportDirectory;
}
- private bool IsWithinReportsFolder(string url, string folder)
+ private static bool IsSafeReportFileName(string reportName)
{
- var rootDirectory = new DirectoryInfo(folder);
- var fileInfo = new FileInfo(Path.Combine(folder, url));
- return fileInfo.Directory.FullName.ToLower().StartsWith(rootDirectory.FullName.ToLower());
+ return !string.IsNullOrWhiteSpace(reportName) &&
+ Path.GetFileName(reportName) == reportName &&
+ reportName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0;
}
public override bool CanSetData(string url)
@@ -72,8 +75,8 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
// Return **true** if no validation is required.
// Query string veya path parametreleri gelse bile sadece rapor adını kontrol et.
- var (reportName, _) = ParseReportUrl(url);
- return Path.GetFileName(reportName) == reportName;
+ var reportName = GetStorageReportName(url);
+ return IsSafeReportFileName(reportName);
}
public override byte[] GetData(string url)
@@ -181,7 +184,13 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
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)
{
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");
}
- private byte[] TryGetStoredReportData(string reportName, Dictionary parameters)
+ private byte[] TryGetStoredReportData(
+ string reportName,
+ Dictionary parameters,
+ bool isDynamicReport)
{
var report = TryLoadStoredReport(reportName);
if (report == null)
@@ -204,9 +216,52 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
}
ApplyReportParameters(report, parameters);
+ if (isDynamicReport)
+ {
+ ApplyDynamicReportFooter(report);
+ }
return SaveReportLayout(report);
}
+ private void ApplyDynamicReportFooter(XtraReport report)
+ {
+ var bottomMargin = report.Bands.OfType().FirstOrDefault();
+ if (bottomMargin == null)
+ {
+ return;
+ }
+
+ var pageWidth = report.PageWidth - report.Margins.Left - report.Margins.Right;
+ var legacyDateTime = bottomMargin.Controls
+ .OfType()
+ .FirstOrDefault(control =>
+ string.Equals(control.Name, "pageInfo1", StringComparison.OrdinalIgnoreCase) &&
+ control.PageInfo == PageInfo.DateTime);
+ if (legacyDateTime != null)
+ {
+ legacyDateTime.Visible = false;
+ }
+
+ var userNameLabel = bottomMargin.Controls
+ .OfType()
+ .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();
+ 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)
{
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]);
}
+ private static string GetStorageReportName(string url)
+ {
+ var (reportName, parameters) = ParseReportUrl(url);
+ return GetStoredReportName(reportName, parameters);
+ }
+
+ private static string GetStoredReportName(string reportName, Dictionary parameters)
+ {
+ return string.Equals(reportName, nameof(Sozsoft.Reports.PredefinedReports.DynamicReport), StringComparison.OrdinalIgnoreCase) &&
+ HasParameter(parameters, "id")
+ ? parameters["id"]
+ : reportName;
+ }
+
private static bool IsDynamicGridReport(string reportName)
{
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);
}
+ private static bool IsDynamicReport(string reportName)
+ {
+ return string.Equals(
+ reportName,
+ nameof(Sozsoft.Reports.PredefinedReports.DynamicReport),
+ StringComparison.OrdinalIgnoreCase);
+ }
+
private static bool IsReportActionSegment(string value)
{
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 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");
- 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)
diff --git a/ui/src/views/list/Chart.tsx b/ui/src/views/list/Chart.tsx
index fe4d4f3..475e60a 100644
--- a/ui/src/views/list/Chart.tsx
+++ b/ui/src/views/list/Chart.tsx
@@ -26,6 +26,8 @@ import {
} from '@/services/admin/list-form.service'
import { layoutTypes } from '../admin/listForm/edit/types'
import { useListFormCustomDataSource } from './useListFormCustomDataSource'
+import { useListFormColumns } from './useListFormColumns'
+import { GridColumnData } from './GridColumnData'
import Toolbar, { Item } from 'devextreme-react/toolbar'
interface ChartProps extends CommonProps, Meta {
@@ -39,6 +41,8 @@ interface ChartProps extends CommonProps, Meta {
refreshGridDto?: () => Promise
}
+type LookupDisplayValues = Record>
+
const Chart = (props: ChartProps) => {
// State UserId güncellemesi için
const { userName } = useStoreState((s) => s.auth.user)
@@ -51,6 +55,12 @@ const Chart = (props: ChartProps) => {
const [searchParams] = useSearchParams()
const [chartOptions, setChartOptions] = useState()
const { createSelectDataSource } = useListFormCustomDataSource({} as any)
+ const { loadLookupDisplayValues } = useListFormColumns({
+ gridDto,
+ listFormCode,
+ isSubForm,
+ })
+ const [lookupDisplayValues, setLookupDisplayValues] = useState({})
const params = useParams()
const _listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
@@ -94,6 +104,34 @@ const Chart = (props: ChartProps) => {
const [allSeries, setAllSeries] = useState([])
+ const lookupColumns = useMemo(
+ () =>
+ 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(() => {
if (gridDto) {
const initialSeries = gridDto.gridOptions.seriesDto.map((s, index) => ({ ...s, index }))
@@ -134,6 +172,10 @@ const Chart = (props: ChartProps) => {
layoutTypes.chart,
)
+ const argumentLookupValues = currentSeries
+ .map((series) => (series.argumentField ? lookupDisplayValues[series.argumentField] : undefined))
+ .find((values) => values?.size)
+
return {
dataSource: dataSource,
@@ -165,7 +207,20 @@ const Chart = (props: ChartProps) => {
animation: gridDto.gridOptions.animationDto,
export: gridDto.gridOptions.exportDto,
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,
tooltip: gridDto.gridOptions.tooltipDto || {
enabled: true,
@@ -194,6 +249,7 @@ const Chart = (props: ChartProps) => {
listFormCode,
urlSearchParams,
openDrawer,
+ lookupDisplayValues,
])
useEffect(() => {
diff --git a/ui/src/views/list/Pivot.tsx b/ui/src/views/list/Pivot.tsx
index ce5f276..bfd00aa 100644
--- a/ui/src/views/list/Pivot.tsx
+++ b/ui/src/views/list/Pivot.tsx
@@ -55,6 +55,8 @@ interface PivotProps {
const statedGridPanelColor = 'rgba(50, 200, 200, 0.5)' // kullanici tanimli gridState ile islem gormus gridin paneline ait renk
+type LookupDisplayValues = Record>
+
const Pivot = (props: PivotProps) => {
const { listFormCode, searchParams, isSubForm, level, gridDto } = props
const { translate } = useLocalization()
@@ -68,6 +70,7 @@ const Pivot = (props: PivotProps) => {
const [gridDataSource, setGridDataSource] = useState>()
const [columnData, setColumnData] = useState()
+ const [lookupDisplayValues, setLookupDisplayValues] = useState({})
const [showChart, setShowChart] = useState(false)
// StateStoring için storageKey'i memoize et
@@ -82,7 +85,7 @@ const Pivot = (props: PivotProps) => {
})
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })
- const { getBandedColumns } = useListFormColumns({
+ const { getBandedColumns, loadLookupDisplayValues } = useListFormColumns({
gridDto,
listFormCode,
isSubForm,
@@ -355,6 +358,30 @@ const Pivot = (props: PivotProps) => {
}
}, [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(() => {
if (memoizedDataSource) {
setGridDataSource(memoizedDataSource)
@@ -384,6 +411,7 @@ const Pivot = (props: PivotProps) => {
// Default fields'i hazırla
const defaultFields: any = columnData?.map((b) => {
+ const lookupValues = b.dataField ? lookupDisplayValues[b.dataField] : undefined
return {
dataField: b.dataField,
caption: b.caption,
@@ -397,6 +425,14 @@ const Pivot = (props: PivotProps) => {
wordWrapEnabled: b.colData?.pivotSettingsDto.wordWrapEnabled,
visible: true,
width: b.width,
+ ...(lookupValues
+ ? {
+ customizeText: (cellInfo: any) => {
+ const value = cellInfo.value ?? cellInfo.valueText
+ return lookupValues.get(String(value)) ?? cellInfo.valueText ?? String(value ?? '')
+ },
+ }
+ : {}),
} as Field
})
@@ -408,7 +444,7 @@ const Pivot = (props: PivotProps) => {
}
instance.option('dataSource', dataSource)
- }, [columnData, gridDataSource, gridDto])
+ }, [columnData, gridDataSource, gridDto, lookupDisplayValues])
// Component mount olduğunda state'i bir kez yükle
useEffect(() => {
diff --git a/ui/src/views/list/useListFormColumns.ts b/ui/src/views/list/useListFormColumns.ts
index 52be303..8e25a33 100644
--- a/ui/src/views/list/useListFormColumns.ts
+++ b/ui/src/views/list/useListFormColumns.ts
@@ -435,6 +435,50 @@ const useListFormColumns = ({
[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 } | undefined)?.store
+ const items = ((await store?.load?.()) ?? []) as Record[]
+ const values = new Map()
+
+ items.forEach((item: Record) => {
+ 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>
+ },
+ [listFormCode, lookupDataSource],
+ )
+
const createLookupStaticDataSource = (
load: () => any,
filter: any = null,
@@ -1036,6 +1080,7 @@ const useListFormColumns = ({
return {
getBandedColumns,
+ loadLookupDisplayValues,
}
}
diff --git a/ui/src/views/report/DevexpressReportDesigner.tsx b/ui/src/views/report/DevexpressReportDesigner.tsx
index 4f20293..9f7e20f 100644
--- a/ui/src/views/report/DevexpressReportDesigner.tsx
+++ b/ui/src/views/report/DevexpressReportDesigner.tsx
@@ -15,6 +15,7 @@ const ReportDesigner = lazy(() =>
const VIEWER_THEME_LINK_ID = 'devexpress-report-viewer-theme'
const VIEWER_DARK_OVERRIDES_ID = 'devexpress-report-viewer-dark-overrides'
+const REPORT_DESIGNER_CSS_ID = 'devexpress-report-designer-css'
const getViewerClassName = (isDarkMode: boolean) =>
[
@@ -58,6 +59,17 @@ const loadViewerCss = (isDarkMode: boolean) => {
if (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 = () => {