Devexpress Raporların Culture Uygulaması
This commit is contained in:
parent
ecb32a502a
commit
a321e90a53
6 changed files with 455 additions and 72 deletions
|
|
@ -29,6 +29,7 @@ public class DynamicFormReport : XtraReport
|
|||
private const string QueryName = "DynamicForm";
|
||||
private const int HorizontalMargin = 35;
|
||||
private const float RowHeight = 24;
|
||||
private const float ColumnGap = 10;
|
||||
private static readonly System.Drawing.Color FieldBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
|
||||
private static IServiceProvider _serviceProvider;
|
||||
|
||||
|
|
@ -208,19 +209,28 @@ public class DynamicFormReport : XtraReport
|
|||
y += 26;
|
||||
}
|
||||
|
||||
foreach (var field in group.Fields)
|
||||
var columnCount = GetSafeColumnCount(group.ColumnCount);
|
||||
var cellWidth = GetCellWidth(pageWidth, columnCount);
|
||||
foreach (var rowFields in CreateLayoutRows(group.Fields, columnCount))
|
||||
{
|
||||
var rowHeight = GetFieldRowHeight(field);
|
||||
var labelWidth = pageWidth * 0.28F;
|
||||
detail.Controls.Add(CreateCaptionLabel(field, localizer, 0, y, labelWidth, rowHeight));
|
||||
if (field.IsImage)
|
||||
var rowHeight = rowFields.Max(x => GetFieldRowHeight(x.Field));
|
||||
foreach (var item in rowFields)
|
||||
{
|
||||
detail.Controls.Add(CreateImageValuePanel(field, row, imageBaseUrl, labelWidth, y, pageWidth - labelWidth, rowHeight));
|
||||
}
|
||||
else
|
||||
{
|
||||
detail.Controls.Add(CreateValueLabel(field, row, labelWidth, y, pageWidth - labelWidth, rowHeight));
|
||||
var x = item.ColumnIndex * (cellWidth + ColumnGap);
|
||||
var width = cellWidth * item.ColumnSpan + ColumnGap * (item.ColumnSpan - 1);
|
||||
var labelWidth = Math.Min(width * 0.36F, 110F);
|
||||
|
||||
detail.Controls.Add(CreateCaptionLabel(item.Field, localizer, x, y, labelWidth, rowHeight));
|
||||
if (item.Field.IsImage)
|
||||
{
|
||||
detail.Controls.Add(CreateImageValuePanel(item.Field, row, imageBaseUrl, x + labelWidth, y, width - labelWidth, rowHeight));
|
||||
}
|
||||
else
|
||||
{
|
||||
detail.Controls.Add(CreateValueLabel(item.Field, row, x + labelWidth, y, width - labelWidth, rowHeight));
|
||||
}
|
||||
}
|
||||
|
||||
y += rowHeight + 3;
|
||||
}
|
||||
|
||||
|
|
@ -417,19 +427,19 @@ public class DynamicFormReport : XtraReport
|
|||
}
|
||||
|
||||
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;
|
||||
if (DynamicReportImageHelper.TryFormatReportValue(field.Field, rawValue, field.EditorType, out var formattedValue))
|
||||
{
|
||||
text = formattedValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
text = Convert.ToString(rawValue, CultureInfo.CurrentCulture) ?? string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -439,12 +449,68 @@ public class DynamicFormReport : XtraReport
|
|||
{
|
||||
var groupHeight = groups
|
||||
.Sum(group => (string.IsNullOrWhiteSpace(group.Caption) ? 0 : 26) +
|
||||
group.Fields.Sum(field => GetFieldRowHeight(field) + 3) + 8);
|
||||
CalculateGroupFieldsHeight(group) + 8);
|
||||
|
||||
var subFormHeight = subFormCount * 32;
|
||||
return Math.Max(groupHeight + subFormHeight, RowHeight);
|
||||
}
|
||||
|
||||
private static float CalculateGroupFieldsHeight(FormGroup group)
|
||||
{
|
||||
var columnCount = GetSafeColumnCount(group.ColumnCount);
|
||||
return CreateLayoutRows(group.Fields, columnCount)
|
||||
.Sum(row => row.Max(x => GetFieldRowHeight(x.Field)) + 3);
|
||||
}
|
||||
|
||||
private static float GetCellWidth(float pageWidth, int columnCount)
|
||||
{
|
||||
return (pageWidth - ColumnGap * (columnCount - 1)) / columnCount;
|
||||
}
|
||||
|
||||
private static int GetSafeColumnCount(int columnCount)
|
||||
{
|
||||
return Math.Max(columnCount, 1);
|
||||
}
|
||||
|
||||
private static int GetSafeColumnSpan(int columnSpan, int columnCount)
|
||||
{
|
||||
return Math.Clamp(columnSpan <= 0 ? 1 : columnSpan, 1, columnCount);
|
||||
}
|
||||
|
||||
private static IEnumerable<IReadOnlyList<FormLayoutItem>> CreateLayoutRows(
|
||||
IReadOnlyList<FormReportField> fields,
|
||||
int columnCount)
|
||||
{
|
||||
var row = new List<FormLayoutItem>();
|
||||
var currentColumn = 0;
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var columnSpan = GetSafeColumnSpan(field.ColumnSpan, columnCount);
|
||||
if (currentColumn > 0 && currentColumn + columnSpan > columnCount)
|
||||
{
|
||||
yield return row;
|
||||
row = [];
|
||||
currentColumn = 0;
|
||||
}
|
||||
|
||||
row.Add(new FormLayoutItem(field, currentColumn, columnSpan));
|
||||
currentColumn += columnSpan;
|
||||
|
||||
if (currentColumn >= columnCount)
|
||||
{
|
||||
yield return row;
|
||||
row = [];
|
||||
currentColumn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (row.Count > 0)
|
||||
{
|
||||
yield return row;
|
||||
}
|
||||
}
|
||||
|
||||
private static float GetFieldRowHeight(FormReportField field)
|
||||
{
|
||||
if (field.IsImage)
|
||||
|
|
@ -475,12 +541,12 @@ public class DynamicFormReport : XtraReport
|
|||
var orderedFields = formItems.Count > 0
|
||||
? formItems
|
||||
.Where(x => fieldsByName.ContainsKey(x.DataField))
|
||||
.Select(x => new FieldWithEditor(fieldsByName[x.DataField], x.EditorType2))
|
||||
.Select(x => new FieldWithEditor(fieldsByName[x.DataField], x.EditorType2, x.ColSpan))
|
||||
.ToList()
|
||||
: fields
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.FieldName) && x.FieldName != "undefined")
|
||||
.Where(x => x.IsActive != false && x.Visible == true)
|
||||
.Select(x => new FieldWithEditor(x, null))
|
||||
.Select(x => new FieldWithEditor(x, null, 1))
|
||||
.ToList();
|
||||
|
||||
var selectFieldsByName = DynamicReportImageHelper.CreateSelectFieldMap(selectQueryManager.SelectFields);
|
||||
|
|
@ -489,7 +555,7 @@ public class DynamicFormReport : XtraReport
|
|||
.Select(x =>
|
||||
{
|
||||
var selectField = selectFieldsByName[x.Field.FieldName];
|
||||
return CreateFormReportField(x.Field, selectField, x.EditorType, defaultValueHelper);
|
||||
return CreateFormReportField(x.Field, selectField, x.EditorType, x.ColumnSpan, defaultValueHelper);
|
||||
})
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.BindingName) && x.BindingName != "undefined")
|
||||
.ToList();
|
||||
|
|
@ -501,7 +567,7 @@ public class DynamicFormReport : XtraReport
|
|||
var groups = GetEditingFormGroups(listForm).ToList();
|
||||
if (groups.Count == 0)
|
||||
{
|
||||
yield return new FormGroup(null, fields);
|
||||
yield return new FormGroup(null, 1, fields);
|
||||
yield break;
|
||||
}
|
||||
|
||||
|
|
@ -521,7 +587,7 @@ public class DynamicFormReport : XtraReport
|
|||
|
||||
if (groupFields.Count > 0)
|
||||
{
|
||||
yield return new FormGroup(group.Caption, groupFields);
|
||||
yield return new FormGroup(group.Caption, group.ColCount, groupFields);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -530,7 +596,7 @@ public class DynamicFormReport : XtraReport
|
|||
.ToList();
|
||||
if (remainingFields.Count > 0)
|
||||
{
|
||||
yield return new FormGroup(null, remainingFields);
|
||||
yield return new FormGroup(null, 1, remainingFields);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -609,6 +675,7 @@ public class DynamicFormReport : XtraReport
|
|||
ListFormField field,
|
||||
SelectField selectField,
|
||||
string editorType,
|
||||
int columnSpan,
|
||||
DefaultValueHelper defaultValueHelper)
|
||||
{
|
||||
var bindingName = DynamicReportImageHelper.GetReportFieldName(selectField);
|
||||
|
|
@ -616,12 +683,12 @@ public class DynamicFormReport : XtraReport
|
|||
|
||||
if (lookup == null || selectField?.JoinOptions != null)
|
||||
{
|
||||
return new FormReportField(field, bindingName, editorType, null, null, DynamicReportImageHelper.IsImageEditor(editorType));
|
||||
return new FormReportField(field, bindingName, editorType, columnSpan, null, null, DynamicReportImageHelper.IsImageEditor(editorType));
|
||||
}
|
||||
|
||||
if (DynamicReportSqlBuilder.IsReportQueryableLookup(lookup))
|
||||
{
|
||||
return new FormReportField(field, DynamicReportSqlBuilder.GetLookupBindingName(field), editorType, lookup, null, false);
|
||||
return new FormReportField(field, DynamicReportSqlBuilder.GetLookupBindingName(field), editorType, columnSpan, lookup, null, false);
|
||||
}
|
||||
|
||||
if (lookup.DataSourceType == UiLookupDataSourceTypeEnum.StaticData)
|
||||
|
|
@ -631,12 +698,13 @@ public class DynamicFormReport : XtraReport
|
|||
field,
|
||||
staticLookupValues?.Count > 0 ? DynamicReportSqlBuilder.GetLookupBindingName(field) : bindingName,
|
||||
editorType,
|
||||
columnSpan,
|
||||
lookup,
|
||||
staticLookupValues,
|
||||
false);
|
||||
}
|
||||
|
||||
return new FormReportField(field, bindingName, editorType, null, null, DynamicReportImageHelper.IsImageEditor(editorType));
|
||||
return new FormReportField(field, bindingName, editorType, columnSpan, null, null, DynamicReportImageHelper.IsImageEditor(editorType));
|
||||
}
|
||||
|
||||
private static string CreateKeyFilter(string keyFieldName, string id)
|
||||
|
|
@ -660,47 +728,19 @@ public class DynamicFormReport : XtraReport
|
|||
return null;
|
||||
}
|
||||
|
||||
private static bool IsBooleanEditor(FormReportField field)
|
||||
{
|
||||
return field.EditorType is PlatformConsts.EditorTypes.dxCheckBox or PlatformConsts.EditorTypes.dxSwitch ||
|
||||
field.Field.SourceDbType == DbType.Boolean;
|
||||
}
|
||||
|
||||
private static bool IsHtmlEditor(FormReportField field)
|
||||
{
|
||||
return field.EditorType == PlatformConsts.EditorTypes.dxHtmlEditor;
|
||||
}
|
||||
|
||||
private static bool TryFormatBoolean(string value, out string text)
|
||||
{
|
||||
if (bool.TryParse(value, out var boolean))
|
||||
{
|
||||
text = boolean ? "Evet" : "Hayır";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value == "1" || string.Equals(value, "true", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
text = "Evet";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value == "0" || string.Equals(value, "false", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
text = "Hayır";
|
||||
return true;
|
||||
}
|
||||
|
||||
text = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private sealed record FieldWithEditor(ListFormField Field, string EditorType);
|
||||
private sealed record FormGroup(string Caption, IReadOnlyList<FormReportField> Fields);
|
||||
private sealed record FieldWithEditor(ListFormField Field, string EditorType, int ColumnSpan);
|
||||
private sealed record FormGroup(string Caption, int ColumnCount, IReadOnlyList<FormReportField> Fields);
|
||||
private sealed record FormLayoutItem(FormReportField Field, int ColumnIndex, int ColumnSpan);
|
||||
private sealed record FormReportField(
|
||||
ListFormField Field,
|
||||
string BindingName,
|
||||
string EditorType,
|
||||
int ColumnSpan,
|
||||
LookupDto Lookup,
|
||||
Dictionary<string, string> StaticLookupValues,
|
||||
bool IsImage) : DynamicReportSqlBuilder.IReportLookupColumn;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ public class DynamicGridReport : XtraReport
|
|||
field,
|
||||
selectField,
|
||||
defaultValueHelper,
|
||||
editorType,
|
||||
DynamicReportImageHelper.IsImageEditor(editorType),
|
||||
editorType == PlatformConsts.EditorTypes.dxHtmlEditor);
|
||||
})
|
||||
|
|
@ -366,7 +367,10 @@ public class DynamicGridReport : XtraReport
|
|||
Multiline = false,
|
||||
CanGrow = false
|
||||
};
|
||||
cell.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", $"[{column.BindingName}]"));
|
||||
cell.ExpressionBindings.Add(new ExpressionBinding(
|
||||
"BeforePrint",
|
||||
"Text",
|
||||
DynamicReportImageHelper.CreateFormatValueExpression($"[{column.BindingName}]", field, column.EditorType)));
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
|
@ -412,7 +416,10 @@ public class DynamicGridReport : XtraReport
|
|||
return cell;
|
||||
}
|
||||
|
||||
cell.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", $"sumSum([{column.BindingName}])"));
|
||||
cell.ExpressionBindings.Add(new ExpressionBinding(
|
||||
"BeforePrint",
|
||||
"Text",
|
||||
DynamicReportImageHelper.CreateFormatValueExpression($"sumSum([{column.BindingName}])", field, column.EditorType)));
|
||||
cell.Summary = new XRSummary
|
||||
{
|
||||
Running = SummaryRunning.Report,
|
||||
|
|
@ -509,6 +516,7 @@ public class DynamicGridReport : XtraReport
|
|||
ListFormField field,
|
||||
SelectField selectField,
|
||||
DefaultValueHelper defaultValueHelper,
|
||||
string editorType,
|
||||
bool isImage,
|
||||
bool isHtml)
|
||||
{
|
||||
|
|
@ -517,12 +525,12 @@ public class DynamicGridReport : XtraReport
|
|||
|
||||
if (lookup == null || selectField?.JoinOptions != null)
|
||||
{
|
||||
return new ReportColumn(field, bindingName, null, null, isImage, isHtml);
|
||||
return new ReportColumn(field, bindingName, null, null, isImage, isHtml, editorType);
|
||||
}
|
||||
|
||||
if (DynamicReportSqlBuilder.IsReportQueryableLookup(lookup))
|
||||
{
|
||||
return new ReportColumn(field, DynamicReportSqlBuilder.GetLookupBindingName(field), lookup, null, isImage, isHtml);
|
||||
return new ReportColumn(field, DynamicReportSqlBuilder.GetLookupBindingName(field), lookup, null, isImage, isHtml, editorType);
|
||||
}
|
||||
|
||||
if (lookup.DataSourceType == UiLookupDataSourceTypeEnum.StaticData)
|
||||
|
|
@ -534,10 +542,11 @@ public class DynamicGridReport : XtraReport
|
|||
lookup,
|
||||
staticLookupValues,
|
||||
isImage,
|
||||
isHtml);
|
||||
isHtml,
|
||||
editorType);
|
||||
}
|
||||
|
||||
return new ReportColumn(field, bindingName, null, null, isImage, isHtml);
|
||||
return new ReportColumn(field, bindingName, null, null, isImage, isHtml, editorType);
|
||||
}
|
||||
|
||||
private sealed record ReportColumn(
|
||||
|
|
@ -547,6 +556,7 @@ public class DynamicGridReport : XtraReport
|
|||
Dictionary<string, string> StaticLookupValues,
|
||||
bool IsImage,
|
||||
bool IsHtml,
|
||||
string EditorType,
|
||||
int ImageCount = 1) : DynamicReportSqlBuilder.IReportLookupColumn;
|
||||
|
||||
private static SummaryFunc? GetSummaryType(string totalSummaryJson)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ public partial class DynamicReport : XtraReport
|
|||
|
||||
// Language verilerini yükle
|
||||
LoadLanguageParameters();
|
||||
|
||||
|
||||
pageInfo1.TextFormatString = "{0:d}";
|
||||
xrRichText1.BeforePrint += XrRichText1_BeforePrint;
|
||||
}
|
||||
|
||||
|
|
@ -58,11 +59,11 @@ public partial class DynamicReport : XtraReport
|
|||
SetParameter("name", language.DisplayName);
|
||||
}
|
||||
|
||||
SetParameter("date", DateTime.Now.ToString("dd.MM.yyyy"));
|
||||
SetParameter("date", DynamicReportImageHelper.FormatReportDate(DateTime.Now));
|
||||
}
|
||||
catch
|
||||
{
|
||||
SetParameter("date", DateTime.Now.ToString("dd.MM.yyyy"));
|
||||
SetParameter("date", DynamicReportImageHelper.FormatReportDate(DateTime.Now));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ internal static class DynamicReportImageHelper
|
|||
private const int MaxFormImages = 8;
|
||||
private const string ImageUrlFunctionName = "SozReportImageUrl";
|
||||
private const string ImageSourceFunctionName = "SozReportImageSource";
|
||||
private const string FormatValueFunctionName = "SozReportFormatValue";
|
||||
private static readonly Regex ReportPagingRegex = new(
|
||||
@"\s+ORDER\s+BY[\s\S]*?(?:\s+OFFSET\s+\d+\s+ROWS(?:\s+FETCH\s+NEXT\s+\d+\s+ROWS\s+ONLY)?)?\s*$",
|
||||
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
|
||||
|
|
@ -47,6 +48,7 @@ internal static class DynamicReportImageHelper
|
|||
{
|
||||
RegisterImageFunction(new ReportImageUrlFunction());
|
||||
RegisterImageFunction(new ReportImageSourceFunction());
|
||||
RegisterImageFunction(new ReportFormatValueFunction());
|
||||
}
|
||||
|
||||
public static Dictionary<string, SelectField> CreateSelectFieldMap(IEnumerable<SelectField> selectFields)
|
||||
|
|
@ -449,6 +451,261 @@ internal static class DynamicReportImageHelper
|
|||
!string.IsNullOrWhiteSpace(Convert.ToString(value, CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
public static IDisposable ApplyReportCulture(IDictionary<string, string> parameters)
|
||||
{
|
||||
var previousCulture = CultureInfo.CurrentCulture;
|
||||
var previousUiCulture = CultureInfo.CurrentUICulture;
|
||||
|
||||
if (TryGetCultureName(parameters, out var cultureName))
|
||||
{
|
||||
try
|
||||
{
|
||||
var culture = CultureInfo.GetCultureInfo(cultureName);
|
||||
CultureInfo.CurrentCulture = culture;
|
||||
CultureInfo.CurrentUICulture = culture;
|
||||
System.Threading.Thread.CurrentThread.CurrentCulture = culture;
|
||||
System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
|
||||
}
|
||||
catch (CultureNotFoundException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return new RestoreCultureScope(previousCulture, previousUiCulture);
|
||||
}
|
||||
|
||||
public static bool TryFormatReportValue(
|
||||
ListFormField field,
|
||||
object value,
|
||||
string editorType,
|
||||
out string text)
|
||||
{
|
||||
return TryFormatReportValue(value, field.SourceDbType, field.Format, editorType, out text);
|
||||
}
|
||||
|
||||
public static string CreateFormatValueExpression(
|
||||
string valueExpression,
|
||||
ListFormField field,
|
||||
string editorType)
|
||||
{
|
||||
return $"{FormatValueFunctionName}({valueExpression}, '{field.SourceDbType}', '{EscapeExpressionString(field.Format)}', '{EscapeExpressionString(editorType)}')";
|
||||
}
|
||||
|
||||
public static string FormatReportDate(DateTime value)
|
||||
{
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
return value.ToString(culture.DateTimeFormat.ShortDatePattern, culture);
|
||||
}
|
||||
|
||||
private static bool TryFormatReportValue(
|
||||
object value,
|
||||
DbType dbType,
|
||||
string format,
|
||||
string editorType,
|
||||
out string text)
|
||||
{
|
||||
text = null;
|
||||
if (value == null || value == DBNull.Value)
|
||||
{
|
||||
text = string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
var invariantValue = Convert.ToString(value, CultureInfo.InvariantCulture);
|
||||
if (IsBooleanField(editorType, dbType) && TryFormatBoolean(invariantValue, out text))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return TryFormatDateValue(dbType, format, value, out text) ||
|
||||
TryFormatNumericValue(dbType, format, value, out text);
|
||||
}
|
||||
|
||||
private static bool TryGetCultureName(IDictionary<string, string> parameters, out string cultureName)
|
||||
{
|
||||
foreach (var name in new[] { "cultureName", "culture", "ui-culture" })
|
||||
{
|
||||
if (parameters.TryGetValue(name, out cultureName) &&
|
||||
!string.IsNullOrWhiteSpace(cultureName))
|
||||
{
|
||||
cultureName = Uri.UnescapeDataString(cultureName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
cultureName = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryFormatDateValue(DbType dbType, string format, object value, out string text)
|
||||
{
|
||||
text = null;
|
||||
if (!IsDateField(dbType) || !TryConvertToDateTime(value, out var date))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
var customFormat = GetCustomFormat(format);
|
||||
if (!string.IsNullOrWhiteSpace(customFormat))
|
||||
{
|
||||
try
|
||||
{
|
||||
text = date.ToString(customFormat, culture);
|
||||
return true;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
text = dbType == DbType.Date || date.TimeOfDay == TimeSpan.Zero
|
||||
? date.ToString(culture.DateTimeFormat.ShortDatePattern, culture)
|
||||
: date.ToString("g", culture);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryFormatNumericValue(DbType dbType, string format, object value, out string text)
|
||||
{
|
||||
text = null;
|
||||
if (!IsNumeric(dbType) || !TryConvertToDecimal(value, out var number))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
var customFormat = GetCustomFormat(format);
|
||||
if (!string.IsNullOrWhiteSpace(customFormat))
|
||||
{
|
||||
try
|
||||
{
|
||||
text = number.ToString(customFormat, culture);
|
||||
return true;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
text = number.ToString("G29", culture);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryFormatBoolean(string value, out string text)
|
||||
{
|
||||
if (bool.TryParse(value, out var boolean))
|
||||
{
|
||||
text = FormatBoolean(boolean);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value == "1" || string.Equals(value, "true", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
text = FormatBoolean(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value == "0" || string.Equals(value, "false", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
text = FormatBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
text = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string FormatBoolean(bool value)
|
||||
{
|
||||
return CultureInfo.CurrentCulture.TwoLetterISOLanguageName.Equals("tr", StringComparison.OrdinalIgnoreCase)
|
||||
? value ? "Evet" : "Hayır"
|
||||
: value ? "Yes" : "No";
|
||||
}
|
||||
|
||||
private static bool IsBooleanField(string editorType, DbType dbType)
|
||||
{
|
||||
return editorType is PlatformConsts.EditorTypes.dxCheckBox or PlatformConsts.EditorTypes.dxSwitch ||
|
||||
dbType == DbType.Boolean;
|
||||
}
|
||||
|
||||
private static string GetCustomFormat(string format)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(format) ? null : format;
|
||||
}
|
||||
|
||||
private static bool IsDateField(DbType dbType)
|
||||
{
|
||||
return dbType is DbType.Date or DbType.DateTime or DbType.DateTime2 or DbType.DateTimeOffset;
|
||||
}
|
||||
|
||||
private static bool TryConvertToDateTime(object value, out DateTime date)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case DateTime dateTime:
|
||||
date = dateTime;
|
||||
return true;
|
||||
case DateTimeOffset dateTimeOffset:
|
||||
date = dateTimeOffset.LocalDateTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
var text = Convert.ToString(value, CultureInfo.InvariantCulture);
|
||||
if (DateTime.TryParse(text, CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal, out date) ||
|
||||
DateTime.TryParse(text, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out date))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
date = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryConvertToDecimal(object value, out decimal number)
|
||||
{
|
||||
if (value is IConvertible)
|
||||
{
|
||||
try
|
||||
{
|
||||
number = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
|
||||
return true;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
var text = Convert.ToString(value, CultureInfo.InvariantCulture);
|
||||
return decimal.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out number) ||
|
||||
decimal.TryParse(text, NumberStyles.Any, CultureInfo.CurrentCulture, out number);
|
||||
}
|
||||
|
||||
private sealed class RestoreCultureScope : IDisposable
|
||||
{
|
||||
private readonly CultureInfo _culture;
|
||||
private readonly CultureInfo _uiCulture;
|
||||
|
||||
public RestoreCultureScope(CultureInfo culture, CultureInfo uiCulture)
|
||||
{
|
||||
_culture = culture;
|
||||
_uiCulture = uiCulture;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
CultureInfo.CurrentCulture = _culture;
|
||||
CultureInfo.CurrentUICulture = _uiCulture;
|
||||
System.Threading.Thread.CurrentThread.CurrentCulture = _culture;
|
||||
System.Threading.Thread.CurrentThread.CurrentUICulture = _uiCulture;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasImageValue(object value)
|
||||
{
|
||||
return HasValue(value) && NormalizeImageValue(value).Any(IsPotentialImageSource);
|
||||
|
|
@ -1043,4 +1300,47 @@ internal static class DynamicReportImageHelper
|
|||
return GetImageSourceObjectAt(rawValue, baseUrl, index);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ReportFormatValueFunction : ICustomFunctionOperatorBrowsable
|
||||
{
|
||||
public string Name => FormatValueFunctionName;
|
||||
public int MinOperandCount => 4;
|
||||
public int MaxOperandCount => 4;
|
||||
public FunctionCategory Category => FunctionCategory.Text;
|
||||
public string Description => "Formats a report value using the active culture.";
|
||||
|
||||
public object Evaluate(params object[] operands)
|
||||
{
|
||||
var value = operands.ElementAtOrDefault(0);
|
||||
var dbType = ToDbType(Convert.ToString(operands.ElementAtOrDefault(1), CultureInfo.InvariantCulture));
|
||||
var format = Convert.ToString(operands.ElementAtOrDefault(2), CultureInfo.InvariantCulture);
|
||||
var editorType = Convert.ToString(operands.ElementAtOrDefault(3), CultureInfo.InvariantCulture);
|
||||
|
||||
return TryFormatReportValue(value, dbType, format, editorType, out var text)
|
||||
? text
|
||||
: Convert.ToString(value, CultureInfo.CurrentCulture) ?? string.Empty;
|
||||
}
|
||||
|
||||
public Type ResultType(params Type[] operands)
|
||||
{
|
||||
return typeof(string);
|
||||
}
|
||||
|
||||
public bool IsValidOperandCount(int count)
|
||||
{
|
||||
return count == 4;
|
||||
}
|
||||
|
||||
public bool IsValidOperandType(int operandIndex, int operandCount, Type type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private static DbType ToDbType(string value)
|
||||
{
|
||||
return Enum.TryParse<DbType>(value, true, out var dbType)
|
||||
? dbType
|
||||
: DbType.String;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
|||
try
|
||||
{
|
||||
var (reportName, parameters) = ParseReportUrl(url);
|
||||
using var _ = Sozsoft.Reports.PredefinedReports.DynamicReportImageHelper.ApplyReportCulture(parameters);
|
||||
|
||||
if (IsDynamicGridReport(reportName))
|
||||
{
|
||||
|
|
@ -238,6 +239,11 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
|||
var filters = new List<string>();
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
if (IsReportInfrastructureParameter(param.Key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var columnName = char.ToUpper(param.Key[0]) + param.Key.Substring(1);
|
||||
filters.Add($"[{columnName}] = '{param.Value.Replace("'", "''")}'");
|
||||
}
|
||||
|
|
@ -245,6 +251,13 @@ public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extens
|
|||
query.FilterString = string.Join(" AND ", filters);
|
||||
}
|
||||
|
||||
private static bool IsReportInfrastructureParameter(string name)
|
||||
{
|
||||
return string.Equals(name, "cultureName", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(name, "culture", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(name, "ui-culture", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static (string ReportName, Dictionary<string, string> Parameters) ParseReportUrl(string url)
|
||||
{
|
||||
var decodedUrl = DecodeRepeatedly(url);
|
||||
|
|
|
|||
|
|
@ -96,9 +96,14 @@ const DevexpressReportViewer: React.FC = () => {
|
|||
const location = useLocation()
|
||||
const token = useStoreState((state) => state.auth.session.token)
|
||||
const themeMode = useStoreState((state) => state.theme.mode)
|
||||
const cultureName = useStoreState((state) => state.locale.currentLang)
|
||||
const configCultureName = useStoreState(
|
||||
(state) => state.abpConfig.config?.localization.currentCulture.cultureName,
|
||||
)
|
||||
const [isRequestAuthReady, setIsRequestAuthReady] = useState(false)
|
||||
const previewModelRef = useRef<any>(null)
|
||||
const isDarkMode = themeMode === MODE_DARK
|
||||
const reportCultureName = cultureName || configCultureName
|
||||
|
||||
const getReportPreview = useCallback((eventOrModel?: any) => {
|
||||
const eventArgs = eventOrModel?.args
|
||||
|
|
@ -148,19 +153,33 @@ const DevexpressReportViewer: React.FC = () => {
|
|||
ajaxSetup.ajaxSettings.headers = {
|
||||
...ajaxHeaders,
|
||||
Authorization: authorization,
|
||||
...(reportCultureName ? { 'Accept-Language': reportCultureName } : {}),
|
||||
}
|
||||
setIsRequestAuthReady(true)
|
||||
return
|
||||
}
|
||||
|
||||
const { Authorization: _ajaxAuthorization, ...nextAjaxHeaders } = ajaxHeaders
|
||||
const {
|
||||
Authorization: _ajaxAuthorization,
|
||||
'Accept-Language': _ajaxAcceptLanguage,
|
||||
...nextAjaxHeaders
|
||||
} = ajaxHeaders
|
||||
if (reportCultureName) {
|
||||
nextAjaxHeaders['Accept-Language'] = reportCultureName
|
||||
}
|
||||
ajaxSetup.ajaxSettings.headers = nextAjaxHeaders
|
||||
setIsRequestAuthReady(true)
|
||||
}, [token])
|
||||
}, [token, reportCultureName])
|
||||
|
||||
const reportUrlWithParams = useMemo(() => {
|
||||
return createReportUrl({ report, id, listFormCode }, location.search)
|
||||
}, [report, id, listFormCode, location.search])
|
||||
const searchParams = new URLSearchParams(location.search)
|
||||
if (reportCultureName) {
|
||||
searchParams.set('cultureName', reportCultureName)
|
||||
}
|
||||
|
||||
const search = searchParams.toString()
|
||||
return createReportUrl({ report, id, listFormCode }, search ? `?${search}` : '')
|
||||
}, [report, id, listFormCode, location.search, reportCultureName])
|
||||
|
||||
if (!reportUrlWithParams) return null
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue