DynamicForm Url değişiklikleri ve Rapor Aç
This commit is contained in:
parent
fdf48c04ee
commit
1997a8aacb
13 changed files with 313 additions and 93 deletions
|
|
@ -1398,6 +1398,18 @@
|
|||
"en": "Menu Management",
|
||||
"tr": "Menü Yönetimi"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Reports.List",
|
||||
"en": "List Report",
|
||||
"tr": "Liste Raporu"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Reports.Form",
|
||||
"en": "Form Report",
|
||||
"tr": "Form Raporu"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Reports",
|
||||
|
|
|
|||
|
|
@ -1584,7 +1584,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
|||
Text ="App.Platform.View",
|
||||
UrlTarget="_blank",
|
||||
AuthName = listFormName,
|
||||
Url=$"/admin/reports/DynamicReport/view?id=@Id",
|
||||
Url=$"/admin/reports/DynamicReport/view/@Id",
|
||||
IsVisible = true,
|
||||
VisibleExpression = "((e)=> e.row.data.CategoryId === 'Raporlar')"
|
||||
},
|
||||
|
|
@ -1593,7 +1593,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
|||
Text ="App.Platform.Design",
|
||||
UrlTarget="_blank",
|
||||
AuthName = listFormName + ".Update",
|
||||
Url=$"/admin/reports/DynamicReport/design?id=@Id",
|
||||
Url=$"/admin/reports/DynamicReport/design/@Id",
|
||||
IsVisible = true,
|
||||
VisibleExpression = "((e)=> e.row.data.CategoryId === 'Raporlar')"
|
||||
},
|
||||
|
|
@ -1602,7 +1602,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
|||
Text ="App.Platform.View",
|
||||
UrlTarget="_blank",
|
||||
AuthName = listFormName,
|
||||
Url=$"/admin/reports/DynamicGrid/view?listFormCode=@Name",
|
||||
Url=$"/admin/reports/DynamicGrid/view/@Name",
|
||||
IsVisible = true,
|
||||
VisibleExpression = "((e)=> e.row.data.CategoryId === 'Listeler')"
|
||||
},
|
||||
|
|
@ -1611,7 +1611,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
|||
Text ="App.Platform.View",
|
||||
UrlTarget="_blank",
|
||||
AuthName = listFormName,
|
||||
Url=$"/admin/reports/DynamicGrid/view?listFormCode=@Name&id=@Id",
|
||||
Url=$"/admin/reports/DynamicGrid/view/@Id/@Name",
|
||||
IsVisible = true,
|
||||
VisibleExpression = "((e)=> e.row.data.CategoryId === 'Formlar')"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@
|
|||
},
|
||||
{
|
||||
"key": "admin.devexpressDynamicReportView",
|
||||
"path": "/admin/reports/:id/view",
|
||||
"path": "/admin/reports/:report/view/:id?/:listFormCode?",
|
||||
"componentType": "normal",
|
||||
"componentPath": "@/views/report/DevexpressReportViewer",
|
||||
"routeType": "protected",
|
||||
|
|
@ -426,7 +426,7 @@
|
|||
},
|
||||
{
|
||||
"key": "admin.devexpressDynamicReportDesigner",
|
||||
"path": "/admin/reports/:id/design",
|
||||
"path": "/admin/reports/:report/design/:id?/:listFormCode?",
|
||||
"componentType": "normal",
|
||||
"componentPath": "@/views/report/DevexpressReportDesigner",
|
||||
"routeType": "protected",
|
||||
|
|
|
|||
|
|
@ -1383,21 +1383,21 @@
|
|||
"name": "Standard Taahhütname",
|
||||
"description": "Standard Taahhütname",
|
||||
"categoryName": "Raporlar",
|
||||
"htmlContent": "<h1>Taahhütname</h1><p>http://localhost:3000/admin/reports/DynamicReport/view?id=ede12de7-0e94-4b84-a953-6c359606478b</p>",
|
||||
"htmlContent": "<h1>Taahhütname</h1><p>http://localhost:3000/admin/reports/DynamicReport/view/ede12de7-0e94-4b84-a953-6c359606478b</p>",
|
||||
"status": "active"
|
||||
},
|
||||
{
|
||||
"name": "App.Languages.LanguageText",
|
||||
"description": "Liste Raporları",
|
||||
"categoryName": "Listeler",
|
||||
"htmlContent": "<h1>Liste Raporları.</h1><p>http://localhost:3000/admin/reports/DynamicGridReport/view?listFormCode=App.Languages.LanguageText&filter=[%22CultureName%22,%22=%22,%22en%22]</p>",
|
||||
"htmlContent": "<h1>Liste Raporları.</h1><p>http://localhost:3000/admin/reports/DynamicGridReport/view/App.Languages.LanguageText?filter=[%22CultureName%22,%22=%22,%22en%22]</p>",
|
||||
"status": "active"
|
||||
},
|
||||
{
|
||||
"name": "App.Languages.Language",
|
||||
"description": "Form Raporları",
|
||||
"categoryName": "Formlar",
|
||||
"htmlContent": "<h1>Liste Raporları.</h1><p>http://localhost:3000/admin/reports/DynamicFormReport/view?listFormCode=App.Languages.Language&id=e2c8a2e0-af22-f7bb-5d88-3a21e3079997</p>",
|
||||
"htmlContent": "<h1>Liste Raporları.</h1><p>http://localhost:3000/admin/reports/DynamicFormReport/view/e2c8a2e0-af22-f7bb-5d88-3a21e3079997/App.Languages.Language</p>",
|
||||
"status": "active"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public class DynamicFormReport : XtraReport
|
|||
private const string QueryName = "DynamicForm";
|
||||
private const int HorizontalMargin = 35;
|
||||
private const float RowHeight = 24;
|
||||
private static readonly System.Drawing.Color FieldBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
|
||||
private static IServiceProvider _serviceProvider;
|
||||
|
||||
public static void SetServiceProvider(IServiceProvider serviceProvider)
|
||||
|
|
@ -107,6 +108,7 @@ public class DynamicFormReport : XtraReport
|
|||
reportFields,
|
||||
defaultValueHelper);
|
||||
selectQuery = ApplyQueryParameters(selectQuery, selectQueryManager.SelectQueryParameters);
|
||||
selectQuery = StripReportPaging(selectQuery);
|
||||
|
||||
var row = GetFirstRow(dynamicDataRepository.QueryAsync(selectQuery, connectionString).GetAwaiter().GetResult());
|
||||
|
||||
|
|
@ -118,12 +120,23 @@ public class DynamicFormReport : XtraReport
|
|||
|
||||
private void ConfigurePage()
|
||||
{
|
||||
Margins = new System.Drawing.Printing.Margins(HorizontalMargin, HorizontalMargin, 35, 35);
|
||||
Margins = CreateReportMargins(HorizontalMargin, HorizontalMargin, 35, 35);
|
||||
PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4;
|
||||
Landscape = false;
|
||||
Font = new DXFont("Arial", 8.25F);
|
||||
}
|
||||
|
||||
#pragma warning disable CA1416
|
||||
private static System.Drawing.Printing.Margins CreateReportMargins(
|
||||
int left,
|
||||
int right,
|
||||
int top,
|
||||
int bottom)
|
||||
{
|
||||
return new System.Drawing.Printing.Margins(left, right, top, bottom);
|
||||
}
|
||||
#pragma warning restore CA1416
|
||||
|
||||
private void ConfigureDataSource(string selectQuery, string connectionString, DataSourceTypeEnum dataSourceType)
|
||||
{
|
||||
var dataSource = new SqlDataSource(new CustomStringConnectionParameters(ToDevExpressConnectionString(connectionString, dataSourceType)));
|
||||
|
|
@ -195,7 +208,7 @@ public class DynamicFormReport : XtraReport
|
|||
var rowHeight = GetFieldRowHeight(field);
|
||||
var labelWidth = pageWidth * 0.28F;
|
||||
detail.Controls.Add(CreateCaptionLabel(field, localizer, 0, y, labelWidth, rowHeight));
|
||||
detail.Controls.Add(CreateValueLabel(field, labelWidth, y, pageWidth - labelWidth, rowHeight));
|
||||
detail.Controls.Add(CreateValueLabel(field, row, labelWidth, y, pageWidth - labelWidth, rowHeight));
|
||||
y += rowHeight + 3;
|
||||
}
|
||||
|
||||
|
|
@ -230,48 +243,75 @@ public class DynamicFormReport : XtraReport
|
|||
Font = new DXFont("Arial", 8F, DXFontStyle.Bold),
|
||||
BackColor = System.Drawing.Color.FromArgb(248, 250, 252),
|
||||
Borders = BorderSide.All,
|
||||
BorderWidth = 0.5F,
|
||||
BorderColor = FieldBorderColor,
|
||||
BorderWidth = 0.25F,
|
||||
Padding = new PaddingInfo(5, 5, 2, 2),
|
||||
TextAlignment = TextAlignment.MiddleLeft,
|
||||
Multiline = true
|
||||
};
|
||||
}
|
||||
|
||||
private static XRLabel CreateValueLabel(FormReportField field, float x, float y, float width, float height)
|
||||
private static XRLabel CreateValueLabel(
|
||||
FormReportField field,
|
||||
IDictionary<string, object> row,
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float height)
|
||||
{
|
||||
var label = new XRLabel
|
||||
{
|
||||
BoundsF = new System.Drawing.RectangleF(x, y, width, height),
|
||||
Font = new DXFont("Arial", 8F),
|
||||
Borders = BorderSide.All,
|
||||
BorderWidth = 0.5F,
|
||||
BorderColor = FieldBorderColor,
|
||||
BorderWidth = 0.25F,
|
||||
Padding = new PaddingInfo(5, 5, 2, 2),
|
||||
TextAlignment = ToTextAlignment(field.Field.Alignment, field.Field.SourceDbType),
|
||||
Multiline = true,
|
||||
CanGrow = true
|
||||
};
|
||||
|
||||
label.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", $"[{field.BindingName}]"));
|
||||
|
||||
if (IsBooleanEditor(field) || field.StaticLookupValues?.Count > 0)
|
||||
if (TryGetFormattedValue(field, row, out var text))
|
||||
{
|
||||
label.BeforePrint += (_, _) =>
|
||||
{
|
||||
var value = Convert.ToString(label.Text, CultureInfo.InvariantCulture);
|
||||
if (IsBooleanEditor(field) && TryFormatBoolean(value, out var booleanText))
|
||||
{
|
||||
label.Text = booleanText;
|
||||
}
|
||||
else if (value != null && field.StaticLookupValues?.TryGetValue(value, out var displayText) == true)
|
||||
{
|
||||
label.Text = displayText;
|
||||
}
|
||||
};
|
||||
label.Text = text;
|
||||
}
|
||||
else
|
||||
{
|
||||
label.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", $"[{field.BindingName}]"));
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
private static bool TryGetFormattedValue(
|
||||
FormReportField field,
|
||||
IDictionary<string, object> row,
|
||||
out string text)
|
||||
{
|
||||
text = null;
|
||||
if (row == null || !TryGetRowValue(row, field.BindingName, out var rawValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var value = Convert.ToString(rawValue, CultureInfo.InvariantCulture);
|
||||
if (IsBooleanEditor(field) && TryFormatBoolean(value, out var booleanText))
|
||||
{
|
||||
text = booleanText;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value != null && field.StaticLookupValues?.TryGetValue(value, out var displayText) == true)
|
||||
{
|
||||
text = displayText;
|
||||
return true;
|
||||
}
|
||||
|
||||
text = value ?? string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static float CalculateDetailHeight(
|
||||
IReadOnlyList<FormReportField> fields,
|
||||
ListForm listForm,
|
||||
|
|
@ -546,6 +586,20 @@ public class DynamicFormReport : XtraReport
|
|||
return sql;
|
||||
}
|
||||
|
||||
private static string StripReportPaging(string sql)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sql))
|
||||
{
|
||||
return sql;
|
||||
}
|
||||
|
||||
return Regex.Replace(
|
||||
sql,
|
||||
@"\s+ORDER\s+BY[\s\S]*?(?:\s+OFFSET\s+\d+\s+ROWS(?:\s+FETCH\s+NEXT\s+\d+\s+ROWS\s+ONLY)?)?\s*$",
|
||||
string.Empty,
|
||||
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
}
|
||||
|
||||
private static string ToSqlLiteral(object value)
|
||||
{
|
||||
if (value == null || value == DBNull.Value)
|
||||
|
|
@ -741,7 +795,7 @@ public class DynamicFormReport : XtraReport
|
|||
var query = lookupQuery.Trim().TrimEnd(';');
|
||||
return Regex.Replace(
|
||||
query,
|
||||
@"\s+ORDER\s+BY\s+[\s\S]*$",
|
||||
@"(?<![A-Za-z0-9_])ORDER\s+BY\b[\s\S]*$",
|
||||
string.Empty,
|
||||
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public class DynamicGridReport : XtraReport
|
|||
private const int A4PortraitWidth = 827;
|
||||
private const int HorizontalMargin = 35;
|
||||
private const int LandscapeColumnThreshold = 5;
|
||||
private static readonly System.Drawing.Color TableBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
|
||||
private static IServiceProvider _serviceProvider;
|
||||
|
||||
public static void SetServiceProvider(IServiceProvider serviceProvider)
|
||||
|
|
@ -126,19 +127,21 @@ public class DynamicGridReport : XtraReport
|
|||
listForm,
|
||||
reportColumns,
|
||||
defaultValueHelper);
|
||||
selectQuery = StripReportPaging(ApplyQueryParameters(selectQuery, selectQueryManager.SelectQueryParameters));
|
||||
|
||||
ConfigurePage(reportColumns);
|
||||
ConfigureDataSource(
|
||||
ApplyQueryParameters(selectQuery, selectQueryManager.SelectQueryParameters),
|
||||
selectQuery,
|
||||
connectionString,
|
||||
dataSourceType);
|
||||
BuildLayout(listForm, reportColumns, localizer);
|
||||
RequestParameters = false;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1416
|
||||
private void ConfigurePage(IReadOnlyCollection<ReportColumn> visibleFields)
|
||||
{
|
||||
Margins = new System.Drawing.Printing.Margins(HorizontalMargin, HorizontalMargin, 35, 35);
|
||||
Margins = CreateReportMargins(HorizontalMargin, HorizontalMargin, 35, 35);
|
||||
PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4;
|
||||
var portraitContentWidth = A4PortraitWidth - Margins.Left - Margins.Right;
|
||||
var requestedContentWidth = visibleFields.Sum(x => Math.Max(x.Field.Width ?? 90, 60));
|
||||
|
|
@ -146,6 +149,16 @@ public class DynamicGridReport : XtraReport
|
|||
Font = new DXFont("Arial", 8.25F);
|
||||
}
|
||||
|
||||
private static System.Drawing.Printing.Margins CreateReportMargins(
|
||||
int left,
|
||||
int right,
|
||||
int top,
|
||||
int bottom)
|
||||
{
|
||||
return new System.Drawing.Printing.Margins(left, right, top, bottom);
|
||||
}
|
||||
#pragma warning restore CA1416
|
||||
|
||||
private void ConfigureDataSource(string selectQuery, string connectionString, DataSourceTypeEnum dataSourceType)
|
||||
{
|
||||
var dataSource = new SqlDataSource(new CustomStringConnectionParameters(ToDevExpressConnectionString(connectionString, dataSourceType)));
|
||||
|
|
@ -195,6 +208,20 @@ public class DynamicGridReport : XtraReport
|
|||
return sql;
|
||||
}
|
||||
|
||||
private static string StripReportPaging(string sql)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sql))
|
||||
{
|
||||
return sql;
|
||||
}
|
||||
|
||||
return Regex.Replace(
|
||||
sql,
|
||||
@"\s+ORDER\s+BY[\s\S]*?(?:\s+OFFSET\s+\d+\s+ROWS(?:\s+FETCH\s+NEXT\s+\d+\s+ROWS\s+ONLY)?)?\s*$",
|
||||
string.Empty,
|
||||
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
}
|
||||
|
||||
private static string ToSqlLiteral(object value)
|
||||
{
|
||||
if (value == null || value == DBNull.Value)
|
||||
|
|
@ -293,7 +320,8 @@ public class DynamicGridReport : XtraReport
|
|||
{
|
||||
BoundsF = new System.Drawing.RectangleF(0, 0, width, height),
|
||||
Borders = BorderSide.All,
|
||||
BorderWidth = 0.5F
|
||||
BorderColor = TableBorderColor,
|
||||
BorderWidth = 0.25F
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -353,17 +381,6 @@ public class DynamicGridReport : XtraReport
|
|||
CanGrow = false
|
||||
};
|
||||
cell.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", $"[{column.BindingName}]"));
|
||||
if (column.StaticLookupValues?.Count > 0)
|
||||
{
|
||||
cell.BeforePrint += (_, _) =>
|
||||
{
|
||||
var value = Convert.ToString(cell.Text, CultureInfo.InvariantCulture);
|
||||
if (value != null && column.StaticLookupValues.TryGetValue(value, out var displayText))
|
||||
{
|
||||
cell.Text = displayText;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
|
@ -455,11 +472,12 @@ public class DynamicGridReport : XtraReport
|
|||
|
||||
if (lookup.DataSourceType == UiLookupDataSourceTypeEnum.StaticData)
|
||||
{
|
||||
var staticLookupValues = GetStaticLookupValues(lookup, defaultValueHelper);
|
||||
return new ReportColumn(
|
||||
field,
|
||||
bindingName,
|
||||
staticLookupValues?.Count > 0 ? GetLookupBindingName(field) : bindingName,
|
||||
lookup,
|
||||
GetStaticLookupValues(lookup, defaultValueHelper));
|
||||
staticLookupValues);
|
||||
}
|
||||
|
||||
return new ReportColumn(field, bindingName, null, null);
|
||||
|
|
@ -570,11 +588,15 @@ public class DynamicGridReport : XtraReport
|
|||
IReadOnlyList<ReportColumn> reportColumns,
|
||||
DefaultValueHelper defaultValueHelper)
|
||||
{
|
||||
var lookupColumns = reportColumns
|
||||
var queryLookupColumns = reportColumns
|
||||
.Where(x => x.Lookup != null && IsReportQueryableLookup(x.Lookup))
|
||||
.ToList();
|
||||
var staticLookupColumns = reportColumns
|
||||
.Where(x => x.StaticLookupValues?.Count > 0)
|
||||
.ToList();
|
||||
|
||||
if (lookupColumns.Count == 0 || string.IsNullOrWhiteSpace(selectQuery))
|
||||
if ((queryLookupColumns.Count == 0 && staticLookupColumns.Count == 0) ||
|
||||
string.IsNullOrWhiteSpace(selectQuery))
|
||||
{
|
||||
return selectQuery;
|
||||
}
|
||||
|
|
@ -585,7 +607,12 @@ public class DynamicGridReport : XtraReport
|
|||
|
||||
var selectParts = new List<string>();
|
||||
var joinParts = new List<string>();
|
||||
foreach (var column in lookupColumns)
|
||||
foreach (var column in staticLookupColumns)
|
||||
{
|
||||
selectParts.Add(CreateStaticLookupSelectPart(column, tableAlias));
|
||||
}
|
||||
|
||||
foreach (var column in queryLookupColumns)
|
||||
{
|
||||
var lookup = column.Lookup;
|
||||
var alias = GetLookupAlias(column.Field);
|
||||
|
|
@ -612,6 +639,10 @@ public class DynamicGridReport : XtraReport
|
|||
{
|
||||
joinInsertIndex = FindClauseIndex(selectQuery, " ORDER BY ");
|
||||
}
|
||||
if (joinParts.Count == 0)
|
||||
{
|
||||
return selectQuery;
|
||||
}
|
||||
if (joinInsertIndex < 0)
|
||||
{
|
||||
return selectQuery + " " + string.Join(' ', joinParts);
|
||||
|
|
@ -620,6 +651,15 @@ public class DynamicGridReport : XtraReport
|
|||
return selectQuery.Insert(joinInsertIndex, " " + string.Join(' ', joinParts));
|
||||
}
|
||||
|
||||
private static string CreateStaticLookupSelectPart(ReportColumn column, string tableAlias)
|
||||
{
|
||||
var sourceField = $"{QuoteSqlIdentifier(tableAlias)}.{QuoteSqlIdentifier(column.Field.FieldName)}";
|
||||
var cases = column.StaticLookupValues
|
||||
.Select(item => $"WHEN {ToSqlLiteral(item.Key)} THEN {ToSqlLiteral(item.Value)}");
|
||||
|
||||
return $"CASE {sourceField} {string.Join(" ", cases)} ELSE CAST({sourceField} AS VARCHAR(4000)) END AS {QuoteSqlIdentifier(column.BindingName)}";
|
||||
}
|
||||
|
||||
private static int FindClauseIndex(string sql, string clause)
|
||||
{
|
||||
return sql.IndexOf(clause, StringComparison.OrdinalIgnoreCase);
|
||||
|
|
@ -630,7 +670,7 @@ public class DynamicGridReport : XtraReport
|
|||
var query = lookupQuery.Trim().TrimEnd(';');
|
||||
return Regex.Replace(
|
||||
query,
|
||||
@"\s+ORDER\s+BY\s+[\s\S]*$",
|
||||
@"(?<![A-Za-z0-9_])ORDER\s+BY\b[\s\S]*$",
|
||||
string.Empty,
|
||||
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
|||
// Implement your own logic to prohibit URLs that contain spaces or other specific characters.
|
||||
// Return **true** if no validation is required.
|
||||
|
||||
// Query string encoded 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);
|
||||
return Path.GetFileName(reportName) == reportName;
|
||||
}
|
||||
|
|
@ -172,9 +172,10 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
|||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FaultException(new FaultReason("Could not get report data."), new FaultCode("Server"), "GetData");
|
||||
var message = ex.GetBaseException().Message;
|
||||
throw new FaultException(new FaultReason($"Could not get report data. {message}"), new FaultCode("Server"), "GetData");
|
||||
}
|
||||
throw new FaultException(new FaultReason(string.Format("Could not find report '{0}'.", url)), new FaultCode("Server"), "GetData");
|
||||
}
|
||||
|
|
@ -182,31 +183,67 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
|||
private static (string ReportName, Dictionary<string, string> Parameters) ParseReportUrl(string url)
|
||||
{
|
||||
var decodedUrl = DecodeRepeatedly(url);
|
||||
var reportName = decodedUrl;
|
||||
var parameters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var queryIndex = decodedUrl.IndexOf('?');
|
||||
if (queryIndex < 0)
|
||||
var reportPath = queryIndex < 0 ? decodedUrl : decodedUrl[..queryIndex];
|
||||
if (queryIndex >= 0)
|
||||
{
|
||||
return (reportName, parameters);
|
||||
}
|
||||
var queryString = decodedUrl[(queryIndex + 1)..];
|
||||
var paramPairs = queryString.Split('&', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
reportName = decodedUrl[..queryIndex];
|
||||
var queryString = decodedUrl[(queryIndex + 1)..];
|
||||
var paramPairs = queryString.Split('&', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (var pair in paramPairs)
|
||||
{
|
||||
var keyValue = pair.Split('=', 2);
|
||||
if (keyValue.Length == 2 && !string.IsNullOrWhiteSpace(keyValue[0]))
|
||||
foreach (var pair in paramPairs)
|
||||
{
|
||||
parameters[keyValue[0]] = keyValue[1];
|
||||
var keyValue = pair.Split('=', 2);
|
||||
if (keyValue.Length == 2 && !string.IsNullOrWhiteSpace(keyValue[0]))
|
||||
{
|
||||
parameters[keyValue[0]] = keyValue[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var pathParts = reportPath
|
||||
.Split('/', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(Uri.UnescapeDataString)
|
||||
.ToArray();
|
||||
|
||||
if (pathParts.Length == 0)
|
||||
{
|
||||
return (reportPath, parameters);
|
||||
}
|
||||
|
||||
var reportName = pathParts[0];
|
||||
if (pathParts.Length >= 3 && IsReportActionSegment(pathParts[1]))
|
||||
{
|
||||
AddPathParameters(reportName, pathParts.Skip(2).ToArray(), parameters);
|
||||
}
|
||||
|
||||
return (reportName, parameters);
|
||||
}
|
||||
|
||||
private static void AddPathParameters(string reportName, string[] pathParameters, Dictionary<string, string> parameters)
|
||||
{
|
||||
if (pathParameters.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsDynamicGridReport(reportName) || IsDynamicFormReport(reportName))
|
||||
{
|
||||
if (pathParameters.Length == 1)
|
||||
{
|
||||
parameters.TryAdd("listFormCode", pathParameters[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
parameters.TryAdd("id", pathParameters[0]);
|
||||
parameters.TryAdd("listFormCode", pathParameters[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
parameters.TryAdd("id", pathParameters[0]);
|
||||
}
|
||||
|
||||
private static bool IsDynamicGridReport(string reportName)
|
||||
{
|
||||
return string.Equals(reportName, "DynamicGrid", StringComparison.OrdinalIgnoreCase) ||
|
||||
|
|
@ -219,6 +256,12 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
|||
string.Equals(reportName, Sozsoft.Reports.PredefinedReports.DynamicFormReport.ReportName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static bool IsReportActionSegment(string value)
|
||||
{
|
||||
return string.Equals(value, "view", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(value, "design", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static bool HasParameter(Dictionary<string, string> parameters, string name)
|
||||
{
|
||||
return parameters.TryGetValue(name, out var value) && !string.IsNullOrWhiteSpace(value);
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ export const ROUTES_ENUM = {
|
|||
dynamicServicesEdit: '/admin/developerkit/dynamic-services/edit/:id',
|
||||
},
|
||||
reports: {
|
||||
view: '/admin/reports/:id/view',
|
||||
design: '/admin/reports/:id/design',
|
||||
view: '/admin/reports/:report/view/:id?/:listFormCode?',
|
||||
design: '/admin/reports/:report/design/:id?/:listFormCode?',
|
||||
},
|
||||
},
|
||||
admin: {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
FaEye,
|
||||
FaSave,
|
||||
FaCog,
|
||||
FaFileAlt,
|
||||
} from 'react-icons/fa'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { GridColumnData } from '../list/GridColumnData'
|
||||
|
|
@ -80,6 +81,13 @@ const FormButtons = (props: {
|
|||
layout,
|
||||
})
|
||||
|
||||
const openDynamicGridReport = () => {
|
||||
if (!id) return
|
||||
|
||||
const reportUrl = `/admin/reports/DynamicGrid/view/${encodeURIComponent(id)}/${encodeURIComponent(listFormCode)}`
|
||||
window.open(reportUrl, isPwaMode ? '_self' : '_blank')
|
||||
}
|
||||
|
||||
const handleDelete = async (e: any) => {
|
||||
//auth check
|
||||
e.preventDefault()
|
||||
|
|
@ -279,7 +287,17 @@ const FormButtons = (props: {
|
|||
{...(permissions.c || permissions.u ? {} : { disabled: true })}
|
||||
></Button>
|
||||
)}
|
||||
{checkPermission(gridDto?.gridOptions.permissionDto.c) && !isSubForm && (
|
||||
{id && !isSubForm && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="default"
|
||||
className="dx-button dx-button-mode-contained dx-button-normal"
|
||||
icon={<FaFileAlt />}
|
||||
title={translate('::App.Reports.Form')}
|
||||
onClick={openDynamicGridReport}
|
||||
></Button>
|
||||
)}
|
||||
{checkPermission(gridDto?.gridOptions.permissionDto.u) && !isSubForm && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="default"
|
||||
|
|
|
|||
|
|
@ -251,11 +251,20 @@ const useFilters = ({
|
|||
}
|
||||
|
||||
const menus = []
|
||||
const openDynamicGridReport = () => {
|
||||
const reportUrl = `/admin/reports/DynamicGrid/view/${encodeURIComponent(listFormCode)}`
|
||||
window.open(reportUrl, isPwaMode ? '_self' : '_blank')
|
||||
}
|
||||
|
||||
// #region Save/Reset grid state and Filters
|
||||
if (grdOpt.filterRowDto?.allowUserUiFilterSave || grdOpt.stateStoringDto?.enabled) {
|
||||
//Kullanicinin filtre islemi yapmasina izin verilmis ise filtreleme menu elemanlarini ekle
|
||||
if (grdOpt?.filterRowDto?.allowUserUiFilterSave) {
|
||||
menus.push({
|
||||
text: translate('::App.Reports.List'),
|
||||
id: 'openDynamicGridReport',
|
||||
icon: 'doc',
|
||||
})
|
||||
menus.push({
|
||||
text: translate('::ListForms.ListForm.SaveFilter'),
|
||||
id: 'saveActiveFilter',
|
||||
|
|
@ -410,6 +419,8 @@ const useFilters = ({
|
|||
setIsImportModalOpen(true)
|
||||
} else if (itemData.id === 'permissionGrantedUsers') {
|
||||
setIsPermissionUsersModalOpen(true)
|
||||
} else if (itemData.id === 'openDynamicGridReport') {
|
||||
openDynamicGridReport()
|
||||
}
|
||||
},
|
||||
// filtre menüsündeki elemanlar
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ import React, { lazy, Suspense, useEffect } from 'react'
|
|||
import { Container } from '@/components/shared'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useLocation, useParams } from 'react-router-dom'
|
||||
import { RequestOptions } from 'devexpress-reporting-react/dx-report-designer'
|
||||
import { APP_NAME } from '@/constants/app.constant'
|
||||
import { createReportUrl } from './reportRouteParams'
|
||||
|
||||
const ReportDesigner = lazy(() =>
|
||||
import('devexpress-reporting-react/dx-report-designer')
|
||||
|
|
@ -30,13 +31,19 @@ const loadDesignerCss = () => {
|
|||
|
||||
const DevexpressReportDesigner: React.FC = () => {
|
||||
const { translate } = useLocalization()
|
||||
const { id } = useParams<{ id: string }>()
|
||||
const { report, id, listFormCode } = useParams<{
|
||||
report: string
|
||||
id: string
|
||||
listFormCode: string
|
||||
}>()
|
||||
const location = useLocation()
|
||||
const reportUrlWithParams = createReportUrl({ report, id, listFormCode }, location.search, 'design')
|
||||
|
||||
useEffect(() => {
|
||||
loadDesignerCss()
|
||||
}, [])
|
||||
|
||||
if (!id) return null
|
||||
if (!reportUrlWithParams) return null
|
||||
|
||||
return (
|
||||
<Container>
|
||||
|
|
@ -47,7 +54,7 @@ const DevexpressReportDesigner: React.FC = () => {
|
|||
/>
|
||||
|
||||
<Suspense fallback={<div>Rapor tasarımcısı yükleniyor...</div>}>
|
||||
<ReportDesigner reportUrl={id}>
|
||||
<ReportDesigner reportUrl={reportUrlWithParams}>
|
||||
<RequestOptions
|
||||
host={`${import.meta.env.VITE_API_URL}/`}
|
||||
getDesignerModelAction="DXXRD/GetDesignerModel"
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { ajaxSetup } from '@devexpress/analytics-core/analytics-utils-native'
|
|||
import { APP_NAME } from '@/constants/app.constant'
|
||||
import { MODE_DARK } from '@/constants/theme.constant'
|
||||
import { useStoreState } from '@/store'
|
||||
import { createReportUrl } from './reportRouteParams'
|
||||
|
||||
const VIEWER_THEME_LINK_ID = 'devexpress-report-viewer-theme'
|
||||
const VIEWER_DARK_OVERRIDES_ID = 'devexpress-report-viewer-dark-overrides'
|
||||
|
|
@ -84,17 +85,16 @@ const loadViewerCss = (isDarkMode: boolean) => {
|
|||
|
||||
const DevexpressReportViewer: React.FC = () => {
|
||||
const { translate } = useLocalization()
|
||||
const { id, listFormCode, recordId } = useParams<{
|
||||
id: string
|
||||
const { report, listFormCode, id } = useParams<{
|
||||
report: string
|
||||
listFormCode: string
|
||||
recordId: string
|
||||
id: string
|
||||
}>()
|
||||
const location = useLocation()
|
||||
const token = useStoreState((state) => state.auth.session.token)
|
||||
const themeMode = useStoreState((state) => state.theme.mode)
|
||||
const [isRequestAuthReady, setIsRequestAuthReady] = useState(false)
|
||||
const isDarkMode = themeMode === MODE_DARK
|
||||
const formRecordId = recordId ?? (listFormCode ? id : undefined)
|
||||
|
||||
useEffect(() => {
|
||||
loadViewerCss(isDarkMode)
|
||||
|
|
@ -121,22 +121,8 @@ const DevexpressReportViewer: React.FC = () => {
|
|||
}, [token])
|
||||
|
||||
const reportUrlWithParams = useMemo(() => {
|
||||
const searchParams = new URLSearchParams(location.search)
|
||||
|
||||
if (listFormCode) {
|
||||
searchParams.set('listFormCode', listFormCode)
|
||||
|
||||
if (formRecordId) {
|
||||
searchParams.set('id', formRecordId)
|
||||
return `DynamicFormReport?${searchParams.toString()}`
|
||||
}
|
||||
|
||||
return `DynamicListFormReport?${searchParams.toString()}`
|
||||
}
|
||||
|
||||
if (!id) return ''
|
||||
return location.search ? `${id}${location.search}` : id
|
||||
}, [id, listFormCode, formRecordId, location.search])
|
||||
return createReportUrl({ report, id, listFormCode }, location.search)
|
||||
}, [report, id, listFormCode, location.search])
|
||||
|
||||
if (!reportUrlWithParams) return null
|
||||
|
||||
|
|
|
|||
49
ui/src/views/report/reportRouteParams.ts
Normal file
49
ui/src/views/report/reportRouteParams.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
export type ReportRouteParams = {
|
||||
report?: string
|
||||
id?: string
|
||||
listFormCode?: string
|
||||
}
|
||||
|
||||
const isDynamicGridReport = (report?: string) =>
|
||||
report === 'DynamicGrid' || report === 'DynamicGridReport'
|
||||
|
||||
export const normalizeReportRouteParams = ({
|
||||
report,
|
||||
id,
|
||||
listFormCode,
|
||||
}: ReportRouteParams) => {
|
||||
if (isDynamicGridReport(report) && id && !listFormCode) {
|
||||
return {
|
||||
report,
|
||||
id: undefined,
|
||||
listFormCode: id,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
report,
|
||||
id,
|
||||
listFormCode,
|
||||
}
|
||||
}
|
||||
|
||||
export const createReportUrl = (
|
||||
params: ReportRouteParams,
|
||||
search: string,
|
||||
action = 'view',
|
||||
) => {
|
||||
const { report, id, listFormCode } = normalizeReportRouteParams(params)
|
||||
if (!report) return ''
|
||||
|
||||
const searchParams = new URLSearchParams(search)
|
||||
searchParams.delete('id')
|
||||
searchParams.delete('listFormCode')
|
||||
|
||||
const pathSegments = [report, action]
|
||||
if (id) pathSegments.push(id)
|
||||
if (listFormCode) pathSegments.push(listFormCode)
|
||||
|
||||
const path = pathSegments.map((segment) => encodeURIComponent(segment)).join('/')
|
||||
const queryString = searchParams.toString()
|
||||
return queryString ? `${path}?${queryString}` : path
|
||||
}
|
||||
Loading…
Reference in a new issue