sozsoft-platform/api/src/Sozsoft.Platform.HttpApi.Host/PredefinedReports/DynamicTreeReport.cs

774 lines
28 KiB
C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using DevExpress.DataAccess.Json;
using DevExpress.Drawing;
using DevExpress.XtraPrinting;
using DevExpress.XtraReports.UI;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Sozsoft.Platform;
using Sozsoft.Platform.DynamicData;
using Sozsoft.Platform.Entities;
using Sozsoft.Platform.Enums;
using Sozsoft.Platform.ListForms;
using Sozsoft.Platform.Localization;
using Sozsoft.Platform.Queries;
using Volo.Abp.Users;
namespace Sozsoft.Reports.PredefinedReports;
public class DynamicTreeReport : XtraReport
{
public const string ReportName = nameof(DynamicTreeReport);
private const int A4PortraitWidth = 827;
private const int HorizontalMargin = 50;
private const int LandscapeColumnThreshold = 5;
private const string TreeLevelColumn = "__TreeLevel";
private const string TreeHasChildrenColumn = "__TreeHasChildren";
private const string TreePrefixColumn = "__TreePrefix";
private const string TreeDataSourceName = "DynamicTree";
private static readonly System.Drawing.Color TableBorderColor = System.Drawing.Color.FromArgb(226, 232, 240);
private static IServiceScopeFactory _scopeFactory;
public static void SetScopeFactory(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public static async Task<DynamicTreeReport> CreateAsync(IDictionary<string, string> parameters)
{
var report = new DynamicTreeReport();
await report.BuildAsync(parameters);
return report;
}
public DynamicTreeReport()
{
}
private async Task BuildAsync(IDictionary<string, string> parameters)
{
if (_scopeFactory == null)
{
throw new InvalidOperationException("DynamicTreeReport service provider is not configured.");
}
if (!parameters.TryGetValue("listFormCode", out var listFormCode) || string.IsNullOrWhiteSpace(listFormCode))
{
throw new ArgumentException("listFormCode parameter is required.");
}
using var scope = _scopeFactory.CreateScope();
var authManager = scope.ServiceProvider.GetRequiredService<IListFormAuthorizationManager>();
var listFormManager = scope.ServiceProvider.GetRequiredService<IListFormManager>();
var listFormFieldManager = scope.ServiceProvider.GetRequiredService<IListFormFieldManager>();
var customizationManager = scope.ServiceProvider.GetRequiredService<IListFormCustomizationManager>();
var dynamicDataManager = scope.ServiceProvider.GetRequiredService<IDynamicDataManager>();
var selectQueryManager = scope.ServiceProvider.GetRequiredService<ISelectQueryManager>();
var defaultValueHelper = scope.ServiceProvider.GetRequiredService<DefaultValueHelper>();
var localizer = scope.ServiceProvider.GetRequiredService<IStringLocalizer<PlatformResource>>();
var configuration = scope.ServiceProvider.GetRequiredService<IConfiguration>();
var currentUser = scope.ServiceProvider.GetRequiredService<ICurrentUser>();
var isSubReport = DynamicReportImageHelper.IsSubReport(parameters);
if (!await authManager.CanAccess(listFormCode))
{
throw new UnauthorizedAccessException($"No read permission for list form '{listFormCode}'.");
}
var listForm = await listFormManager.GetUserListForm(listFormCode);
var gridState = await customizationManager.GetUserGridState(
listFormCode,
DynamicReportGridStateHelper.GetFilterName(listForm, "tree"));
var treeOptions = GetTreeOptions(listForm);
if (string.IsNullOrWhiteSpace(treeOptions?.KeyExpr) || string.IsNullOrWhiteSpace(treeOptions.ParentIdExpr))
{
throw new InvalidOperationException($"Tree options are not configured for list form '{listFormCode}'.");
}
var fields = (await listFormFieldManager.GetUserListFormFields(listFormCode))
.Where(x => x.CanRead)
.OrderBy(x => x.ListOrderNo ?? int.MaxValue)
.ThenBy(x => x.CaptionName)
.ToList();
var customizations = await customizationManager.GetUsersServerCustomizations(listFormCode);
var (dynamicDataRepository, connectionString, dataSourceType) = await dynamicDataManager.GetAsync(listForm.IsTenant, listForm.DataSourceCode);
var queryParams = new QueryParameters
{
ListFormCode = listFormCode,
Filter = GetParameter(parameters, "filter"),
Sort = GetParameter(parameters, "sort"),
Group = GetParameter(parameters, "group"),
GroupSummary = GetParameter(parameters, "groupSummary"),
TotalSummary = GetParameter(parameters, "totalSummary"),
Take = 0,
Skip = 0
};
await selectQueryManager.PrepareQueriesAsync(listForm, fields, dataSourceType, customizations, queryParams);
var selectFieldsByName = DynamicReportImageHelper.CreateSelectFieldMap(selectQueryManager.SelectFields);
var editorTypesByField = DynamicReportImageHelper.CreateEditorTypeMap(fields);
var availableFields = fields
.Where(x => !string.IsNullOrWhiteSpace(x.FieldName) && x.FieldName != "undefined")
.Where(x => x.IsActive != false)
.Where(x => selectFieldsByName.ContainsKey(x.FieldName))
.ToList();
var visibleFields = DynamicReportGridStateHelper.GetVisibleFields(
availableFields,
gridState?.CustomizationData);
var stateWidths = DynamicReportGridStateHelper.GetColumnWidths(
gridState?.CustomizationData,
GetParameter(parameters, "columnWidths"));
if (visibleFields.Count == 0)
{
visibleFields = availableFields
.Where(x => x.Visible == true)
.Take(8)
.ToList();
}
var reportColumns = visibleFields
.Select(field =>
{
var selectField = selectFieldsByName[field.FieldName];
editorTypesByField.TryGetValue(field.FieldName, out var editorType);
return CreateReportColumn(
field,
selectField,
defaultValueHelper,
editorType,
DynamicReportImageHelper.IsImageEditor(editorType),
editorType == PlatformConsts.EditorTypes.dxHtmlEditor);
})
.Where(x => !string.IsNullOrWhiteSpace(x.BindingName) && x.BindingName != "undefined")
.ToList();
var selectQuery = DynamicReportImageHelper.StripReportPaging(DynamicReportImageHelper.ApplyQueryParameters(
selectQueryManager.SelectQuery,
selectQueryManager.SelectQueryParameters,
dataSourceType));
selectQuery = DynamicReportSqlBuilder.ApplyLookupTextColumns(
selectQuery,
reportColumns,
defaultValueHelper,
dataSourceType);
var imageBaseUrl = DynamicReportImageHelper.GetImageBaseUrl(configuration);
var criteriaText = DynamicReportImageHelper.BuildReportCriteriaText(
queryParams.Filter,
queryParams.Sort,
fields,
localizer);
var sourceRows = await ReadRowsAsync(dynamicDataRepository, selectQuery, connectionString);
var orderedRows = OrderTreeRows(sourceRows, treeOptions).ToList();
reportColumns = ApplyImageCounts(reportColumns, orderedRows, imageBaseUrl);
ConfigurePage(reportColumns, localizer, stateWidths);
ConfigureDataSource(orderedRows, reportColumns);
BuildLayout(listForm, reportColumns, localizer, imageBaseUrl, currentUser.UserName, criteriaText, isSubReport, stateWidths);
RequestParameters = false;
}
#pragma warning disable CA1416
private void ConfigurePage(
IReadOnlyCollection<ReportColumn> visibleFields,
IStringLocalizer<PlatformResource> localizer,
IReadOnlyDictionary<string, float> stateWidths)
{
Margins = CreateReportMargins(HorizontalMargin, HorizontalMargin, 35, 35);
PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4;
var portraitContentWidth = A4PortraitWidth - Margins.Left - Margins.Right;
var requestedContentWidth = visibleFields.Sum(x => x.IsImage
? GetImageColumnWidth(x)
: DynamicReportGridStateHelper.GetPreferredColumnWidth(x.Field, localizer, stateWidths));
Landscape = visibleFields.Count >= LandscapeColumnThreshold || requestedContentWidth > portraitContentWidth;
Font = DynamicReportFontHelper.CreateDataFont();
}
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 static async Task<List<Dictionary<string, object>>> ReadRowsAsync(
IDynamicDataRepository dynamicDataRepository,
string selectQuery,
string connectionString)
{
var rows = await dynamicDataRepository.QueryAsync(selectQuery, connectionString);
return rows
.OfType<IDictionary<string, object>>()
.Select(row => row.ToDictionary(x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase))
.ToList();
}
private static IEnumerable<Dictionary<string, object>> OrderTreeRows(
IReadOnlyList<Dictionary<string, object>> rows,
TreeOptionDto treeOptions)
{
var childrenByParent = rows
.GroupBy(row => NormalizeTreeKey(GetRowValue(row, treeOptions.ParentIdExpr)))
.ToDictionary(x => x.Key, x => x.ToList(), StringComparer.OrdinalIgnoreCase);
var visited = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var rootKey = NormalizeTreeKey(treeOptions.RootValue);
var roots = childrenByParent.TryGetValue(rootKey, out var configuredRoots)
? configuredRoots
: rows.Where(row => IsRootValue(GetRowValue(row, treeOptions.ParentIdExpr), treeOptions.RootValue)).ToList();
foreach (var row in Traverse(roots, childrenByParent, treeOptions.KeyExpr, 0, visited))
{
yield return row;
}
foreach (var row in rows)
{
var key = NormalizeTreeKey(GetRowValue(row, treeOptions.KeyExpr));
if (visited.Contains(key))
{
continue;
}
foreach (var orphan in Traverse([row], childrenByParent, treeOptions.KeyExpr, 0, visited))
{
yield return orphan;
}
}
}
private static IEnumerable<Dictionary<string, object>> Traverse(
IEnumerable<Dictionary<string, object>> rows,
IReadOnlyDictionary<string, List<Dictionary<string, object>>> childrenByParent,
string keyExpr,
int level,
ISet<string> visited)
{
foreach (var row in rows)
{
var key = NormalizeTreeKey(GetRowValue(row, keyExpr));
if (!visited.Add(key))
{
continue;
}
var hasChildren = childrenByParent.TryGetValue(key, out var children) && children.Count > 0;
row[TreeLevelColumn] = level;
row[TreeHasChildrenColumn] = hasChildren;
row[TreePrefixColumn] = $"{new string(' ', level * 4)}{(hasChildren ? "[-] " : " ")}";
yield return row;
if (!hasChildren)
{
continue;
}
foreach (var child in Traverse(children, childrenByParent, keyExpr, level + 1, visited))
{
yield return child;
}
}
}
private static bool IsRootValue(object parentValue, object rootValue)
{
if (rootValue == null)
{
return parentValue == null ||
parentValue == DBNull.Value ||
string.IsNullOrWhiteSpace(Convert.ToString(parentValue, CultureInfo.InvariantCulture));
}
return string.Equals(
NormalizeTreeKey(parentValue),
NormalizeTreeKey(rootValue),
StringComparison.OrdinalIgnoreCase);
}
private static object GetRowValue(IDictionary<string, object> row, string fieldName) =>
DynamicReportImageHelper.TryGetRowValue(row, fieldName, out var value) ? value : null;
private static string NormalizeTreeKey(object value)
{
if (value == null || value == DBNull.Value)
{
return string.Empty;
}
return Convert.ToString(value, CultureInfo.InvariantCulture)?.Trim() ?? string.Empty;
}
private void ConfigureDataSource(
IEnumerable<Dictionary<string, object>> rows,
IReadOnlyList<ReportColumn> columns)
{
var normalizedRows = rows
.Select(row => NormalizeJsonRow(row, columns))
.ToList();
if (normalizedRows.Count == 0)
{
normalizedRows.Add(NormalizeJsonRow(new Dictionary<string, object>(), columns));
}
var dataSource = new JsonDataSource
{
Name = TreeDataSourceName,
JsonSource = new CustomJsonSource(DynamicReportImageHelper.SerializeJson(normalizedRows))
};
dataSource.Fill();
ComponentStorage.Add(dataSource);
DataSource = dataSource;
}
private static Dictionary<string, object> NormalizeJsonRow(
IDictionary<string, object> row,
IReadOnlyList<ReportColumn> columns)
{
var normalized = row.ToDictionary(
x => x.Key,
x => NormalizeJsonValue(x.Value),
StringComparer.OrdinalIgnoreCase);
foreach (var column in columns)
{
normalized.TryAdd(column.BindingName, null);
}
normalized.TryAdd(TreeLevelColumn, 0);
normalized.TryAdd(TreeHasChildrenColumn, false);
normalized.TryAdd(TreePrefixColumn, string.Empty);
return normalized;
}
private static object NormalizeJsonValue(object value)
{
if (value == null || value == DBNull.Value)
{
return null;
}
if (value is Guid guid)
{
return guid.ToString();
}
if (value is DateTime dateTime)
{
return dateTime;
}
if (value is DateTimeOffset dateTimeOffset)
{
return dateTimeOffset;
}
if (value is byte[] bytes)
{
return Convert.ToBase64String(bytes);
}
return value;
}
private static List<ReportColumn> ApplyImageCounts(
IReadOnlyList<ReportColumn> columns,
IReadOnlyList<Dictionary<string, object>> rows,
string imageBaseUrl)
{
var imageColumns = columns.Where(x => x.IsImage).ToList();
if (imageColumns.Count == 0)
{
return columns.ToList();
}
var imageCounts = imageColumns.ToDictionary(x => x.BindingName, _ => 1, StringComparer.OrdinalIgnoreCase);
foreach (var row in rows)
{
foreach (var column in imageColumns)
{
var count = DynamicReportImageHelper.CountImageSources(GetImageRawValue(row, column), imageBaseUrl);
if (count > imageCounts[column.BindingName])
{
imageCounts[column.BindingName] = count;
}
}
}
return columns
.Select(column => column.IsImage
? column with { ImageCount = imageCounts[column.BindingName] }
: column)
.ToList();
}
private static object GetImageRawValue(IDictionary<string, object> row, ReportColumn column)
{
if (DynamicReportImageHelper.TryGetRowValue(row, column.BindingName, out var value) &&
DynamicReportImageHelper.HasValue(value))
{
return value;
}
return DynamicReportImageHelper.TryGetRowValue(row, column.Field.FieldName, out value) ? value : null;
}
private void BuildLayout(
ListForm listForm,
IReadOnlyList<ReportColumn> fields,
IStringLocalizer<PlatformResource> localizer,
string imageBaseUrl,
string currentUserName,
string criteriaText,
bool isSubReport,
IReadOnlyDictionary<string, float> stateWidths)
{
Bands.Clear();
var topMargin = new TopMarginBand { HeightF = Margins.Top };
var bottomMargin = new BottomMarginBand { HeightF = 32 };
var reportHeader = new ReportHeaderBand { HeightF = string.IsNullOrWhiteSpace(criteriaText) ? 32 : 50 };
var pageHeader = new PageHeaderBand { HeightF = 28 };
var detailHeight = fields.Any(x => x.IsImage)
? DynamicReportImageHelper.GetGridImageHeight()
: fields.Any(x => x.IsHtml)
? 48
: 24;
var detail = new DetailBand { HeightF = detailHeight };
var reportFooter = new ReportFooterBand { HeightF = HasAnySummary(fields) ? 28 : 0 };
Bands.AddRange([topMargin, reportHeader, pageHeader, detail, reportFooter, bottomMargin]);
var pageWidth = PageWidth - Margins.Left - Margins.Right;
reportHeader.Controls.Add(new XRLabel
{
Text = DynamicReportImageHelper.GetLocalizedReportTitle(listForm, localizer),
BoundsF = new System.Drawing.RectangleF(0, 0, pageWidth, 30),
Font = DynamicReportFontHelper.CreateValueFont(14F, DXFontStyle.Bold),
TextAlignment = TextAlignment.MiddleLeft
});
if (!isSubReport)
{
DynamicReportImageHelper.AddGeneratedAtToHeader(reportHeader.Controls, pageWidth);
}
DynamicReportImageHelper.AddReportCriteriaToHeader(reportHeader.Controls, criteriaText, pageWidth);
DynamicReportImageHelper.AddFooterTopLine(bottomMargin.Controls, pageWidth);
DynamicReportImageHelper.AddCurrentUserNameToFooter(bottomMargin.Controls, currentUserName, pageWidth);
bottomMargin.Controls.Add(new XRPageInfo
{
TextFormatString = "Sayfa {0} / {1}",
BoundsF = new System.Drawing.RectangleF(pageWidth / 2, 8, pageWidth / 2, 18),
Font = DynamicReportFontHelper.CreateValueFont(8F),
TextAlignment = TextAlignment.MiddleRight
});
var widths = DynamicReportGridStateHelper.CalculateWidths(fields, pageWidth, localizer, stateWidths);
var headerTable = CreateTable(pageWidth, 28);
var headerRow = new XRTableRow { HeightF = 28 };
var detailTable = CreateTable(pageWidth, detailHeight);
detailTable.CanGrow = true;
var detailRow = new XRTableRow { HeightF = detailHeight, CanGrow = true };
var footerTable = CreateTable(pageWidth, 24);
var footerRow = new XRTableRow { HeightF = 24 };
for (var i = 0; i < fields.Count; i++)
{
var field = fields[i];
headerRow.Cells.Add(CreateHeaderCell(field, widths[i], localizer));
detailRow.Cells.Add(CreateDetailCell(field, widths[i], imageBaseUrl, detailHeight, i == 0));
footerRow.Cells.Add(CreateFooterCell(field, widths[i]));
}
headerTable.Rows.Add(headerRow);
detailTable.Rows.Add(detailRow);
footerTable.Rows.Add(footerRow);
pageHeader.Controls.Add(headerTable);
detail.Controls.Add(detailTable);
if (HasAnySummary(fields))
{
reportFooter.Controls.Add(footerTable);
}
}
private static XRTable CreateTable(float width, float height)
{
return new XRTable
{
BoundsF = new System.Drawing.RectangleF(0, 0, width, height),
Borders = BorderSide.All,
BorderColor = TableBorderColor,
BorderWidth = 0.25F
};
}
private static XRTableCell CreateHeaderCell(
ReportColumn column,
float width,
IStringLocalizer<PlatformResource> localizer)
{
return new XRTableCell
{
Text = DynamicReportImageHelper.GetLocalizedFieldCaption(column.Field, localizer),
WidthF = width,
Weight = width,
Font = DynamicReportFontHelper.CreateHeaderFont(),
BackColor = System.Drawing.Color.FromArgb(238, 242, 247),
Padding = new PaddingInfo(4, 4, 2, 2),
TextAlignment = TextAlignment.MiddleCenter,
Multiline = true
};
}
private static XRTableCell CreateDetailCell(
ReportColumn column,
float width,
string imageBaseUrl,
float height,
bool isTreeColumn)
{
if (column.IsImage)
{
return DynamicReportImageHelper.CreateGridImageCell(
column.BindingName,
column.Field.FieldName,
width,
imageBaseUrl,
column.ImageCount);
}
if (column.IsHtml)
{
return CreateHtmlDetailCell(column, width, height);
}
var cell = new XRTableCell
{
WidthF = width,
Weight = width,
Font = DynamicReportFontHelper.CreateDataFont(),
Padding = new PaddingInfo(4, 4, 2, 2),
TextAlignment = isTreeColumn
? TextAlignment.MiddleLeft
: DynamicReportImageHelper.ToTextAlignment(column.Field.Alignment, column.Field.SourceDbType),
Multiline = true,
CanGrow = true
};
var valueExpression = DynamicReportImageHelper.CreateFormatValueExpression($"[{column.BindingName}]", column.Field, column.EditorType);
var textExpression = isTreeColumn
? $"Concat([{TreePrefixColumn}], {valueExpression})"
: valueExpression;
cell.ExpressionBindings.Add(new ExpressionBinding(
"BeforePrint",
"Text",
textExpression));
cell.ExpressionBindings.Add(new ExpressionBinding(
"BeforePrint",
"Font.Name",
DynamicReportImageHelper.CreateFontFamilyExpression(textExpression)));
if (isTreeColumn)
{
cell.ExpressionBindings.Add(new ExpressionBinding(
"BeforePrint",
"Font.Bold",
$"[{TreeHasChildrenColumn}]"));
}
return cell;
}
private static XRTableCell CreateHtmlDetailCell(
ReportColumn column,
float width,
float height)
{
var cell = new XRTableCell
{
WidthF = width,
Weight = width,
Padding = new PaddingInfo(0, 0, 0, 0),
CanGrow = true
};
var richText = new XRRichText
{
BoundsF = new System.Drawing.RectangleF(0, 0, width, height),
Font = DynamicReportFontHelper.CreateDataFont(),
Padding = new PaddingInfo(4, 4, 2, 2),
CanGrow = true
};
richText.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Html", $"[{column.BindingName}]"));
cell.Controls.Add(richText);
return cell;
}
private static XRTableCell CreateFooterCell(ReportColumn column, float width)
{
var summaryType = GetSummaryType(column.Field.TotalSummaryJson);
var cell = new XRTableCell
{
WidthF = width,
Weight = width,
Font = DynamicReportFontHelper.CreateDataFont(DXFontStyle.Bold),
Padding = new PaddingInfo(4, 4, 2, 2),
TextAlignment = DynamicReportImageHelper.ToTextAlignment(column.Field.Alignment, column.Field.SourceDbType)
};
if (summaryType == null)
{
return cell;
}
cell.ExpressionBindings.Add(new ExpressionBinding(
"BeforePrint",
"Text",
DynamicReportImageHelper.CreateFormatValueExpression($"sumSum([{column.BindingName}])", column.Field, column.EditorType)));
cell.Summary = new XRSummary
{
Running = SummaryRunning.Report,
Func = summaryType.Value,
IgnoreNullValues = true
};
return cell;
}
private static bool HasAnySummary(IEnumerable<ReportColumn> fields)
{
return fields.Any(x => GetSummaryType(x.Field.TotalSummaryJson) != null);
}
private static float GetImageColumnWidth(ReportColumn column)
{
return DynamicReportImageHelper.GetGridImageColumnWidth(column.ImageCount);
}
private static ReportColumn CreateReportColumn(
ListFormField field,
SelectField selectField,
DefaultValueHelper defaultValueHelper,
string editorType,
bool isImage,
bool isHtml)
{
var bindingName = DynamicReportImageHelper.GetReportFieldName(selectField);
var lookup = DynamicReportImageHelper.GetLookup(field);
var isMultiValue = IsMultiValueLookupEditor(editorType);
if (lookup == null || selectField?.JoinOptions != null)
{
return new ReportColumn(field, bindingName, null, null, isMultiValue, isImage, isHtml, editorType);
}
if (DynamicReportSqlBuilder.IsReportQueryableLookup(lookup))
{
return new ReportColumn(field, DynamicReportSqlBuilder.GetLookupBindingName(field), lookup, null, isMultiValue, isImage, isHtml, editorType);
}
if (lookup.DataSourceType == UiLookupDataSourceTypeEnum.StaticData)
{
var staticLookupValues = DynamicReportImageHelper.GetStaticLookupValues(lookup, defaultValueHelper);
return new ReportColumn(
field,
staticLookupValues?.Count > 0 ? DynamicReportSqlBuilder.GetLookupBindingName(field) : bindingName,
lookup,
staticLookupValues,
isMultiValue,
isImage,
isHtml,
editorType);
}
return new ReportColumn(field, bindingName, null, null, isMultiValue, isImage, isHtml, editorType);
}
private static bool IsMultiValueLookupEditor(string editorType)
{
return editorType is PlatformConsts.EditorTypes.dxTagBox or "dxGridBox";
}
private static TreeOptionDto GetTreeOptions(ListForm listForm)
{
if (string.IsNullOrWhiteSpace(listForm.TreeOptionJson))
{
return null;
}
try
{
return JsonSerializer.Deserialize<TreeOptionDto>(listForm.TreeOptionJson, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
catch (JsonException)
{
return null;
}
}
private sealed record ReportColumn(
ListFormField Field,
string BindingName,
LookupDto Lookup,
Dictionary<string, string> StaticLookupValues,
bool IsMultiValue,
bool IsImage,
bool IsHtml,
string EditorType,
int ImageCount = 1) : DynamicReportSqlBuilder.IReportLookupColumn, DynamicReportGridStateHelper.IReportColumnWidth
{
public float ImageWidth => GetImageColumnWidth(this);
}
private static SummaryFunc? GetSummaryType(string totalSummaryJson)
{
if (string.IsNullOrWhiteSpace(totalSummaryJson))
{
return null;
}
var value = totalSummaryJson.ToLowerInvariant();
if (value.Contains("\"summarytype\":\"sum\""))
{
return SummaryFunc.Sum;
}
if (value.Contains("\"summarytype\":\"avg\""))
{
return SummaryFunc.Avg;
}
if (value.Contains("\"summarytype\":\"min\""))
{
return SummaryFunc.Min;
}
if (value.Contains("\"summarytype\":\"max\""))
{
return SummaryFunc.Max;
}
if (value.Contains("\"summarytype\":\"count\""))
{
return SummaryFunc.Count;
}
return null;
}
private static string GetParameter(IDictionary<string, string> parameters, string name) =>
DynamicReportImageHelper.GetParameter(parameters, name);
}