From 9689ef1bc688fad86f2f1b3cbf512f677e98c14b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?=
<76204082+iamsedatozturk@users.noreply.github.com>
Date: Mon, 29 Jun 2026 10:13:58 +0300
Subject: [PATCH] =?UTF-8?q?Demo=20ve=20Raporun=20ilk=20seferde=20a=C3=A7?=
=?UTF-8?q?=C4=B1lamamas=C4=B1n=C4=B1=20=C3=A7=C3=B6z=C3=BCmledim?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../CustomReportStorageWebExtension.cs | 65 +++++++++++++++++--
ui/src/components/layouts/PublicLayout.tsx | 13 ++--
ui/src/contexts/DemoContext.tsx | 19 ++++++
ui/src/views/public/Demo.tsx | 5 +-
ui/src/views/public/Home.tsx | 9 ++-
5 files changed, 97 insertions(+), 14 deletions(-)
create mode 100644 ui/src/contexts/DemoContext.tsx
diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/ReportServices/CustomReportStorageWebExtension.cs b/api/src/Sozsoft.Platform.HttpApi.Host/ReportServices/CustomReportStorageWebExtension.cs
index 6817621..6114099 100644
--- a/api/src/Sozsoft.Platform.HttpApi.Host/ReportServices/CustomReportStorageWebExtension.cs
+++ b/api/src/Sozsoft.Platform.HttpApi.Host/ReportServices/CustomReportStorageWebExtension.cs
@@ -3,9 +3,14 @@ using System.IO;
using System.Linq;
using System;
using System.Reflection;
+using System.Text.Json;
using System.Threading.Tasks;
+using DevExpress.DataAccess.Json;
+using DevExpress.DataAccess.Sql;
using DevExpress.XtraPrinting;
using Microsoft.Extensions.DependencyInjection;
+using Sozsoft.Platform.Entities;
+using Volo.Abp.Domain.Repositories;
using Volo.Abp.Users;
namespace Sozsoft.Platform.ReportServices;
@@ -186,10 +191,10 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
var storedReportName = GetStoredReportName(reportName, parameters);
var isDynamicReport = IsDynamicReport(reportName);
- var reportData = TryGetStoredReportData(storedReportName, parameters, isDynamicReport);
+ var reportData = await TryGetStoredReportDataAsync(storedReportName, parameters, isDynamicReport);
if (reportData == null && !string.Equals(storedReportName, reportName, StringComparison.OrdinalIgnoreCase))
{
- reportData = TryGetStoredReportData(reportName, parameters, isDynamicReport);
+ reportData = await TryGetStoredReportDataAsync(reportName, parameters, isDynamicReport);
}
if (reportData != null)
{
@@ -204,7 +209,7 @@ 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(
+ private async Task TryGetStoredReportDataAsync(
string reportName,
Dictionary parameters,
bool isDynamicReport)
@@ -215,14 +220,66 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
return null;
}
- ApplyReportParameters(report, parameters);
if (isDynamicReport)
{
+ await EmbedDynamicReportDataAsync(report, parameters);
ApplyDynamicReportFooter(report);
}
+ else
+ {
+ ApplyReportParameters(report, parameters);
+ }
+
return SaveReportLayout(report);
}
+ private async Task EmbedDynamicReportDataAsync(
+ XtraReport report,
+ IReadOnlyDictionary parameters)
+ {
+ if (!parameters.TryGetValue("id", out var idValue) || !Guid.TryParse(idValue, out var reportTemplateId))
+ {
+ throw new InvalidOperationException("A valid report template id is required.");
+ }
+
+ using var scope = _serviceProvider.CreateScope();
+ var repository = scope.ServiceProvider.GetRequiredService>();
+ var template = await repository.FindAsync(reportTemplateId);
+ if (template == null)
+ {
+ throw new InvalidOperationException($"Report template '{reportTemplateId}' was not found.");
+ }
+
+ // A stored DynamicReport layout can contain a named SqlDataSource. The cached document
+ // builder executes that source later on a background thread, where its connection can be
+ // stale or no longer carry the request's tenant context. Embed the tenant-scoped result in
+ // the layout so document generation no longer opens a second database connection.
+ foreach (var sqlDataSource in report.ComponentStorage.OfType().ToList())
+ {
+ if (ReferenceEquals(report.DataSource, sqlDataSource))
+ {
+ report.DataSource = null;
+ }
+
+ report.ComponentStorage.Remove(sqlDataSource);
+ sqlDataSource.Dispose();
+ }
+
+ var dataSource = new JsonDataSource
+ {
+ Name = "DynamicReportData",
+ JsonSource = new CustomJsonSource(JsonSerializer.Serialize(new[]
+ {
+ new { template.HtmlContent }
+ }))
+ };
+ dataSource.Fill();
+
+ report.ComponentStorage.Add(dataSource);
+ report.DataSource = dataSource;
+ report.DataMember = null;
+ }
+
private void ApplyDynamicReportFooter(XtraReport report)
{
var bottomMargin = report.Bands.OfType().FirstOrDefault();
diff --git a/ui/src/components/layouts/PublicLayout.tsx b/ui/src/components/layouts/PublicLayout.tsx
index 99b2b53..8d29c96 100644
--- a/ui/src/components/layouts/PublicLayout.tsx
+++ b/ui/src/components/layouts/PublicLayout.tsx
@@ -22,6 +22,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
import LanguageSelector from '../template/LanguageSelector'
import Demo from '@/views/public/Demo'
import { ScrollContext } from '@/contexts/ScrollContext'
+import { DemoProvider } from '@/contexts/DemoContext'
import useDarkMode from '@/utils/hooks/useDarkmode'
import { THEME_ENUM } from '@/constants/theme.constant'
import { Button } from '../ui'
@@ -170,8 +171,9 @@ const PublicLayout = () => {
}
return (
-
-
+
setIsDemoOpen(true) }}>
+
+
{/* HEADER */}
{
{/* Demo Modal */}
- setIsDemoOpen(false)} />
-
-
+ setIsDemoOpen(false)} />
+
+
+
)
}
diff --git a/ui/src/contexts/DemoContext.tsx b/ui/src/contexts/DemoContext.tsx
new file mode 100644
index 0000000..6735ce4
--- /dev/null
+++ b/ui/src/contexts/DemoContext.tsx
@@ -0,0 +1,19 @@
+import React, { createContext, useContext } from 'react'
+
+interface DemoContextValue {
+ openDemo: () => void
+}
+
+const DemoContext = createContext(undefined)
+
+export const DemoProvider = DemoContext.Provider
+
+export const useDemo = () => {
+ const context = useContext(DemoContext)
+
+ if (!context) {
+ throw new Error('useDemo must be used within a DemoProvider')
+ }
+
+ return context
+}
diff --git a/ui/src/views/public/Demo.tsx b/ui/src/views/public/Demo.tsx
index b358a81..7e684de 100644
--- a/ui/src/views/public/Demo.tsx
+++ b/ui/src/views/public/Demo.tsx
@@ -167,9 +167,10 @@ const Demo: React.FC = ({ isOpen, onClose }) => {
onClick={onClose}
title="Kapat"
aria-label="Kapat"
- variant="plain"
+ variant="default"
shape="circle"
- className="absolute top-4 right-4 !h-8 !w-8 !px-0 text-2xl text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100"
+ size="lg"
+ className="absolute top-4 right-4 !h-8 !w-8 !px-0 bg-gray-900 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100"
>
×
diff --git a/ui/src/views/public/Home.tsx b/ui/src/views/public/Home.tsx
index 3e9bb0a..54bbca2 100644
--- a/ui/src/views/public/Home.tsx
+++ b/ui/src/views/public/Home.tsx
@@ -18,6 +18,7 @@ import { DesignerSelection } from './designer/types'
import { useDesignerState } from './designer/useDesignerState'
import { getHome, HomeDto, saveHomePage } from '@/services/home.service'
import { Button, Notification, toast } from '@/components/ui'
+import { useDemo } from '@/contexts/DemoContext'
interface HomeSlideServiceContent {
icon: string
@@ -272,6 +273,7 @@ function buildHomeContent(home: HomeDto | undefined, translate: (key: string) =>
}
const Home: React.FC = () => {
+ const { openDemo } = useDemo()
const { translate } = useLocalization()
const { setLang } = useStoreActions((actions) => actions.locale)
const { getConfig } = useStoreActions((actions) => actions.abpConfig)
@@ -988,13 +990,14 @@ const Home: React.FC = () => {
-
{content?.heroPrimaryCtaLabel}{' '}
-
+