Raporlama, Chart, Pivot hataları düzeltildi.

This commit is contained in:
Sedat Öztürk 2026-06-23 00:49:13 +03:00
parent 39e4e448d7
commit 16036ce7f9
14 changed files with 295 additions and 46 deletions

View file

@ -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)

View file

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Sozsoft.Platform.Migrations
{
[DbContext(typeof(PlatformDbContext))]
[Migration("20260619185755_Initial")]
[Migration("20260622213308_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -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);
});

View file

@ -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",

View file

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

View file

@ -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);

View file

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

View file

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

View file

@ -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<string, string> _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<string, string>();
@ -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<ICurrentUser>();
var pageWidth = PageWidth - Margins.Left - Margins.Right;
DynamicReportImageHelper.AddCurrentUserNameToFooter(BottomMargin.Controls, currentUser.UserName, pageWidth);
currentUserNameLabel.Text = currentUser.UserName ?? string.Empty;
}
catch
{

View file

@ -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";

View file

@ -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<string, string> parameters)
private byte[] TryGetStoredReportData(
string reportName,
Dictionary<string, string> 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<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)
{
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<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)
{
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)

View file

@ -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<void>
}
type LookupDisplayValues = Record<string, Map<string, string>>
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<any>()
const { createSelectDataSource } = useListFormCustomDataSource({} as any)
const { loadLookupDisplayValues } = useListFormColumns({
gridDto,
listFormCode,
isSubForm,
})
const [lookupDisplayValues, setLookupDisplayValues] = useState<LookupDisplayValues>({})
const params = useParams()
const _listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
@ -94,6 +104,34 @@ const Chart = (props: ChartProps) => {
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(() => {
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(() => {

View file

@ -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<string, Map<string, string>>
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<CustomStore<any, any>>()
const [columnData, setColumnData] = useState<GridColumnData[]>()
const [lookupDisplayValues, setLookupDisplayValues] = useState<LookupDisplayValues>({})
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(() => {

View file

@ -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<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 = (
load: () => any,
filter: any = null,
@ -1036,6 +1080,7 @@ const useListFormColumns = ({
return {
getBandedColumns,
loadLookupDisplayValues,
}
}

View file

@ -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 = () => {