Demo ve Raporun ilk seferde açılamamasını çözümledim
This commit is contained in:
parent
352cf047b0
commit
9689ef1bc6
5 changed files with 97 additions and 14 deletions
|
|
@ -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<byte[]> TryGetStoredReportDataAsync(
|
||||
string reportName,
|
||||
Dictionary<string, string> 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<string, string> 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<IRepository<ReportTemplate, Guid>>();
|
||||
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<SqlDataSource>().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<BottomMarginBand>().FirstOrDefault();
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<ScrollContext.Provider value={scrolled}>
|
||||
<div className="flex flex-col min-h-screen">
|
||||
<DemoProvider value={{ openDemo: () => setIsDemoOpen(true) }}>
|
||||
<ScrollContext.Provider value={scrolled}>
|
||||
<div className="flex flex-col min-h-screen">
|
||||
{/* HEADER */}
|
||||
<header
|
||||
className={`fixed w-full z-50 transition-all duration-500 ${
|
||||
|
|
@ -607,9 +609,10 @@ const PublicLayout = () => {
|
|||
</footer>
|
||||
|
||||
{/* Demo Modal */}
|
||||
<Demo isOpen={isDemoOpen} onClose={() => setIsDemoOpen(false)} />
|
||||
</div>
|
||||
</ScrollContext.Provider>
|
||||
<Demo isOpen={isDemoOpen} onClose={() => setIsDemoOpen(false)} />
|
||||
</div>
|
||||
</ScrollContext.Provider>
|
||||
</DemoProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
19
ui/src/contexts/DemoContext.tsx
Normal file
19
ui/src/contexts/DemoContext.tsx
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import React, { createContext, useContext } from 'react'
|
||||
|
||||
interface DemoContextValue {
|
||||
openDemo: () => void
|
||||
}
|
||||
|
||||
const DemoContext = createContext<DemoContextValue | undefined>(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
|
||||
}
|
||||
|
|
@ -167,9 +167,10 @@ const Demo: React.FC<DemoModalProps> = ({ 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"
|
||||
>
|
||||
×
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -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 = () => {
|
|||
</p>
|
||||
|
||||
<div className="flex flex-col md:flex-row justify-center gap-6 mb-16">
|
||||
<Link
|
||||
to={ROUTES_ENUM.public.contact}
|
||||
<button
|
||||
type="button"
|
||||
onClick={openDemo}
|
||||
className={content?.heroPrimaryCtaStyle}
|
||||
>
|
||||
{content?.heroPrimaryCtaLabel}{' '}
|
||||
<FaArrowRight className="ml-2" size={20} />
|
||||
</Link>
|
||||
</button>
|
||||
<Link
|
||||
to={ROUTES_ENUM.public.products}
|
||||
className={content?.heroSecondaryCtaStyle}
|
||||
|
|
|
|||
Loading…
Reference in a new issue