GetDeleteSelectedRowsResult()
- {
- var html = new Div();
- var messageFactory = ComponentFactory.Html.MessageBox;
- var errorMessage = new StringBuilder();
- int errorCount = 0;
- int successCount = 0;
-
- try
- {
- var rows = GridView.GetSelectedGridValues();
-
- foreach (var row in rows)
- {
- var errors = await DeleteFormValuesAsync(row!);
-
- if (errors.Count > 0)
- {
- foreach (var err in errors)
- {
- errorMessage.Append(" - ");
- errorMessage.Append(err.Value);
- errorMessage.Append("
");
- }
-
- errorCount++;
- }
- else
- {
- successCount++;
- }
- }
-
- if (rows.Count > 0)
- {
- var message = new StringBuilder();
- var icon = MessageIcon.Info;
- if (successCount > 0)
- {
- message.Append("");
- message.Append(StringLocalizer["{0} Record(s) deleted successfully", successCount]);
- message.Append("
");
- }
-
- if (errorCount > 0)
- {
- message.Append("");
- message.Append(StringLocalizer["{0} Record(s) with error", successCount]);
- message.Append(StringLocalizer["Details:"]);
- message.Append("
");
- message.Append(errorMessage);
- icon = MessageIcon.Warning;
- }
-
- html.AppendComponent(messageFactory.Create(message.ToString(), icon));
-
- GridView.ClearSelectedGridValues();
- }
- }
- catch (Exception ex)
- {
- html.AppendComponent(messageFactory.Create(ex.Message, MessageIcon.Error));
- }
-
- var gridViewResult = await GetGridViewResult();
-
- if (gridViewResult is RenderedComponentResult)
- {
- html.Append(new HtmlBuilder(gridViewResult));
- }
- else
- {
- return gridViewResult;
- }
-
- PageState = PageState.List;
-
- return new RenderedComponentResult(html);
- }
-
private async Task GetAuditLogResult()
{
var actionMap = _currentActionMap;
@@ -1212,7 +1131,8 @@ internal async Task GetRelationshipLayoutResult(
var bottomActions =
toolbarActions.Where(a => a.Location is FormToolbarActionLocation.Bottom).ToList();
- toolbarActions.BackAction.SetVisible(true);
+ if(!IsChildFormView)
+ toolbarActions.BackAction.SetVisible(true);
html.AppendComponent(await GetFormToolbarAsync(bottomActions));
@@ -1476,7 +1396,7 @@ public async Task> UpdateFormValuesAsync(Dictionary> DeleteFormValuesAsync(Dictionary? filter)
{
var values =
- await FieldValuesService.MergeWithExpressionValuesAsync(FormElement, new FormStateData(filter!, UserValues, PageState.Delete), true);
+ await FieldValuesService.MergeWithExpressionValuesAsync(FormElement, new FormStateData(filter!, UserValues, PageState.Delete));
var result = await FormService.DeleteAsync(FormElement, values,
new DataContext(CurrentContext.Request, DataContextSource.Form, UserId));
UrlRedirect = result.UrlRedirect;
@@ -1604,12 +1524,7 @@ private void AddEventHandlers(IFormEventHandler eventHandler)
private JJTitle GetTitle(FormStateData formStateData)
{
- return ComponentFactory.Html.Title.Create(FormElement,formStateData);
- }
-
- private async Task GetTitleAsync()
- {
- return ComponentFactory.Html.Title.Create(FormElement, await GetFormStateDataAsync());
+ return ComponentFactory.Html.Title.Create(FormElement,formStateData, TitleActions);
}
#region "Legacy inherited GridView compatibility"
diff --git a/src/Core/UI/Components/GridView/GridPagination.cs b/src/Core/UI/Components/GridView/GridPagination.cs
index a1dd64853..a4ca54b57 100644
--- a/src/Core/UI/Components/GridView/GridPagination.cs
+++ b/src/Core/UI/Components/GridView/GridPagination.cs
@@ -204,6 +204,7 @@ private HtmlBuilder GetEnableMultSelectTotalRecords()
string multipleRecordsSelected = GridView.StringLocalizer["{0} selected records", selectedValues.Count];
var span = new HtmlBuilder(HtmlTag.Span);
+ span.WithCssClass("small");
span.WithAttribute("id", $"selected-text-{GridView.Name}");
span.WithAttribute("no-record-selected-label", noRecordSelected);
span.WithAttribute("one-record-selected-label", oneRecordSelected);
diff --git a/src/Core/UI/Components/GridView/GridSqlCommandAction.cs b/src/Core/UI/Components/GridView/GridSqlCommandAction.cs
index 1f11af187..0b951c7ce 100644
--- a/src/Core/UI/Components/GridView/GridSqlCommandAction.cs
+++ b/src/Core/UI/Components/GridView/GridSqlCommandAction.cs
@@ -6,6 +6,7 @@
using JJMasterData.Commons.Exceptions;
using JJMasterData.Core.DataDictionary.Models;
using JJMasterData.Core.DataDictionary.Models.Actions;
+using JJMasterData.Core.DataManager.Expressions;
using JJMasterData.Core.DataManager.Expressions.Providers;
using JJMasterData.Core.DataManager.Models;
using JJMasterData.Core.Logging;
@@ -61,11 +62,11 @@ private async Task ExecuteOnList(SqlCommandAction sqlCommandAction, List $"{GridView.Name}-table";
+ private string Name { get; } = $"{gridView.Name}-table";
private JJGridView GridView { get; } = gridView;
@@ -34,19 +35,23 @@ public async Task GetHtmlBuilderAsync()
var tbody = new HtmlBuilder(HtmlTag.Tbody);
tbody.WithAttribute("id", Name);
- await tbody.AppendRangeAsync(GetRowsList());
+ tbody.AppendRange(await GetRowsList());
return tbody;
}
- private async IAsyncEnumerable GetRowsList()
+ private async Task> GetRowsList()
{
- var rows = GridView.DataSource;
+ List rows = [];
+
+ var dataSource = GridView.DataSource;
- for (var i = 0; i < rows?.Count; i++)
+ for (var i = 0; i < dataSource?.Count; i++)
{
- yield return await GetRowHtml(rows[i], i);
+ rows.Add(await GetRowHtml(dataSource[i], i));
}
+
+ return rows;
}
private async Task GetRowHtml(Dictionary row, int index)
@@ -58,8 +63,8 @@ private async Task GetRowHtml(Dictionary row, int
tr.WithAttribute("id", $"row{index}");
var enableGridAction = !GridView.EnableEditMode && (defaultAction != null || GridView.EnableMultiSelect);
tr.WithCssClassIf(enableGridAction, "tr-hover-action");
-
- await tr.AppendRangeAsync(GetTdHtmlList(row, index));
+
+ tr.AppendRange(await GetTdHtmlList(row, index));
if (OnRenderRowAsync is not null)
await OnRenderRowAsync(GridView, new()
@@ -71,7 +76,7 @@ private async Task GetRowHtml(Dictionary row, int
return tr;
}
- internal async IAsyncEnumerable GetTdHtmlList(Dictionary row, int index)
+ internal async Task> GetTdHtmlList(Dictionary row, int index)
{
var values = await GetValues(row);
var formStateData = new FormStateData(values, GridView.UserValues, PageState.List);
@@ -79,6 +84,8 @@ internal async IAsyncEnumerable GetTdHtmlList(Dictionary x is { IsVisible: true, IsDefaultOption: true });
var onClickScript = await GetOnClickScript(formStateData, defaultAction);
+ var tdList = new List();
+
if (GridView.EnableMultiSelect)
{
var checkBox = await GetMultiSelectCheckbox(row, index, values);
@@ -93,28 +100,39 @@ internal async IAsyncEnumerable GetTdHtmlList(Dictionary GetVisibleFieldsHtmlList(Dictionary row, int index,
- Dictionary values, string onClickScript)
+ private async Task> GetVisibleFieldsHtmlList(
+ Dictionary row,
+ int index,
+ Dictionary values,
+ string onClickScript)
{
+ List result = [];
+ var formStateData = new FormStateData(GetEncodedValues(values), GridView.UserValues, PageState.List);
foreach (var field in await GridView.GetVisibleFieldsAsync())
{
+ var formattedValue = string.Empty;
+ var stringValue = string.Empty;
+
if (values.TryGetValue(field.Name, out var value))
{
- value = FieldFormattingService.FormatValue(field, value);
+ formattedValue = FieldFormattingService.FormatValue(field, value);
+ stringValue = value?.ToString() ?? string.Empty;
}
var td = new HtmlBuilder(HtmlTag.Td);
@@ -124,93 +142,130 @@ private async IAsyncEnumerable GetVisibleFieldsHtmlList(Dictionary<
if (GridView.EnableEditMode && field.DataBehavior != FieldBehavior.ViewOnly)
{
- td.Append(await GetEditModeFieldHtml(field, row, index, values, value?.ToString()));
+ td.Append(await GetEditModeFieldHtml(field, formStateData, row, index, formattedValue));
}
else
{
- values.TryGetValue(field.Name, out var objValue);
- value = objValue?.ToString() ?? string.Empty;
- var formStateData = new FormStateData(values, GridView.UserValues, PageState.List);
- HtmlBuilder cell;
- if (field.DataItem is not null && field.DataItem.ShowIcon &&
- field.DataItem.GridBehavior is DataItemGridBehavior.Icon
- or DataItemGridBehavior.IconWithDescription)
- {
- var dataItemValues = await GridView.DataItemService.GetValuesAsync(field.DataItem, formStateData,
- null,
- value.ToString());
- var dataItemValue = dataItemValues.FirstOrDefault(d => d.Id == value.ToString());
+ td.Append(await GetGridFieldHtml(field, formStateData, row, stringValue));
+ }
+ result.Add(td);
+ }
- string tooltip;
- if (field.DataItem.GridBehavior is DataItemGridBehavior.Icon)
- tooltip = GridView.StringLocalizer[dataItemValue?.Description ?? string.Empty];
- else
- tooltip = string.Empty;
+ return result;
+ }
- if (dataItemValue != null)
- {
- cell = GetIconCell(dataItemValue.Icon, dataItemValue.IconColor ?? string.Empty, tooltip);
-
- cell.AppendIf(field.DataItem.GridBehavior is DataItemGridBehavior.IconWithDescription,
- HtmlTag.Span,
- span =>
- {
- span.AppendText(dataItemValue.Description ?? dataItemValue.Id);
- span.WithCssClass($"{BootstrapHelper.MarginLeft}-1");
- });
- }
- else
- {
- cell = new HtmlBuilder();
- }
- }
- else if (field.DataFile is not null)
- {
- var textFile = GridView.ComponentFactory.Controls.Create(GridView.FormElement, field,
- new(formStateData, Name, value));
- cell = textFile.GetButtonGroupHtml();
- }
- else if (field.Component is FormComponent.Color && !string.IsNullOrEmpty(value.ToString()))
- {
- var stringValue = value.ToString()!;
- cell = GetIconCell(IconType.Circle, stringValue, stringValue);
- }
- else if (field.Component is FormComponent.Icon && !string.IsNullOrEmpty(value.ToString()))
- {
- var iconType = IconHelper.GetIconTypeFromField(field,value);
+ private async Task GetGridFieldHtml(FormElementField field,
+ FormStateData formStateData,
+ Dictionary row,
+ string stringValue)
+ {
+ HtmlBuilder cell;
- cell = GetIconCell(iconType, null, iconType.ToString());
- }
- else
- {
- value = await GridView.FieldsService.FormatGridValueAsync(field, values, GridView.UserValues);
- var valueString = value?.ToString()?.Trim() ?? string.Empty;
- cell = new HtmlBuilder(valueString);
- }
+ var isDataIconWithIcon = field.DataItem is {
+ ShowIcon: true,
+ GridBehavior: DataItemGridBehavior.Icon or DataItemGridBehavior.IconWithDescription
+ };
+
+ if (isDataIconWithIcon)
+ {
+ cell = await GetDataItemIconCell(field.DataItem!, formStateData, stringValue);
+ }
+ else if (field.DataFile is not null)
+ {
+ var controlContext = new ControlContext(formStateData, Name, stringValue);
+ var controlFactory = GridView.ComponentFactory.Controls;
+ var textFile = controlFactory.Create(GridView.FormElement, field,controlContext);
+ cell = textFile.GetButtonGroupHtml();
+ }
+ else if (field.Component is FormComponent.Color && !string.IsNullOrEmpty(stringValue))
+ {
+ cell = GetIconCell(IconType.Circle, stringValue, stringValue);
+ }
+ else if (field.Component is FormComponent.Icon && !string.IsNullOrEmpty(stringValue))
+ {
+ var iconType = IconHelper.GetIconTypeFromField(field, stringValue);
- if (OnRenderCellAsync != null)
- {
- var args = new GridCellEventArgs
- {
- Field = field,
- DataRow = row,
- HtmlResult = cell,
- Sender = new JJText(value?.ToString())
- };
+ cell = GetIconCell(iconType, null, iconType.ToString());
+ }
+ else if (!string.IsNullOrEmpty(field.GridRenderingTemplate))
+ {
+ var replacedTemplate = ExpressionHelper.ReplaceExpression(field.GridRenderingTemplate!, formStateData.Values);
+ cell = new HtmlBuilder(replacedTemplate);
+ }
+ else
+ {
+ var selector = new FormElementFieldSelector(GridView.FormElement, field.Name);
+ var gridValue = await GridView.FieldsService.FormatGridValueAsync(selector, formStateData);
+ var gridStringValue = gridValue?.Trim() ?? string.Empty;
+ cell = new HtmlBuilder(gridStringValue);
+ }
- await OnRenderCellAsync(this, args);
+ if (OnRenderCellAsync == null)
+ return cell;
+
+ var args = new GridCellEventArgs
+ {
+ Field = field,
+ DataRow = row,
+ HtmlResult = cell,
+ Sender = new JJText(stringValue)
+ };
- td.Append(args.HtmlResult ?? cell);
- }
- else
- {
- td.Append(cell);
- }
+ await OnRenderCellAsync(this, args);
+
+ return args.HtmlResult ?? cell;
+
+ }
+
+ private Dictionary GetEncodedValues(Dictionary values)
+ {
+ var result = new Dictionary(StringComparer.CurrentCultureIgnoreCase);
+ foreach (var kvp in values)
+ {
+ if (GridView.FormElement.Fields.TryGetField(kvp.Key, out var field) && field.EncodeHtml)
+ {
+ result[kvp.Key] = HttpUtility.HtmlEncode(kvp.Value);
}
+ else
+ {
+ result[kvp.Key] = kvp.Value;
+ }
+ }
+
+ return result;
+ }
- yield return td;
+ private async Task GetDataItemIconCell(FormElementDataItem dataItem, FormStateData formStateData, string stringValue)
+ {
+ HtmlBuilder cell;
+ var dataQuery = new DataQuery(formStateData, GridView.FormElement.ConnectionId)
+ {
+ SearchId = stringValue
+ };
+ var dataItemValues = await GridView.DataItemService.GetValuesAsync(dataItem, dataQuery);
+ var dataItemValue = dataItemValues.FirstOrDefault(d => d.Id == stringValue);
+
+ var tooltip = dataItem.GridBehavior is DataItemGridBehavior.Icon ? GridView.StringLocalizer[dataItemValue?.Description ?? string.Empty] : string.Empty;
+
+ if (dataItemValue != null)
+ {
+ cell = GetIconCell(dataItemValue.Icon, dataItemValue.IconColor ?? string.Empty, tooltip);
+
+ cell.AppendIf(dataItem.GridBehavior is DataItemGridBehavior.IconWithDescription,
+ HtmlTag.Span,
+ span =>
+ {
+ span.AppendText(dataItemValue.Description ?? dataItemValue.Id);
+ span.WithCssClass($"{BootstrapHelper.MarginLeft}-1");
+ });
}
+ else
+ {
+ cell = new HtmlBuilder();
+ }
+
+ return cell;
}
private static HtmlBuilder GetIconCell(IconType iconType, string? color = null, string? tooltip = null)
@@ -226,19 +281,21 @@ private static HtmlBuilder GetIconCell(IconType iconType, string? color = null,
return cell;
}
- private async Task GetEditModeFieldHtml(FormElementField field, Dictionary row,
- int index, Dictionary values,
+ private async Task GetEditModeFieldHtml(
+ FormElementField field,
+ FormStateData formStateData,
+ Dictionary row,
+ int index,
string? value)
{
- var name = GridView.GetFieldName(field.Name, values);
+ var name = GridView.GetFieldName(field.Name, formStateData.Values);
var hasError = GridView.Errors.ContainsKey(name);
var div = new Div();
div.WithCssClassIf(hasError, BootstrapHelper.HasError);
- var control = GridView.ComponentFactory.Controls.Create(GridView.FormElement, field,
- new(values, GridView.UserValues, PageState.List), name, value);
+ var control = GridView.ComponentFactory.Controls.Create(GridView.FormElement, field, formStateData, name, value);
control.Name = name;
control.Attributes.Add("gridViewRowIndex", index.ToString());
@@ -272,20 +329,24 @@ private async Task GetEditModeFieldHtml(FormElementField field, Dic
return div;
}
- public async IAsyncEnumerable GetActionsHtmlListAsync(FormStateData formStateData)
+ public async Task> GetActionsHtmlListAsync(FormStateData formStateData)
{
+ List result = [];
var basicActions = GridView.GridTableActions.OrderBy(x => x.Order).ToList();
var actionsWithoutGroup = basicActions.FindAll(x => x.IsVisible && !x.IsGroup);
var groupedActions = basicActions.FindAll(x => x.IsVisible && x.IsGroup);
- await foreach (var action in GetActionsWithoutGroupHtmlAsync(actionsWithoutGroup, formStateData))
+
+ foreach (var action in await GetActionsWithoutGroupHtmlAsync(actionsWithoutGroup, formStateData))
{
- yield return action;
+ result.Add(action);
}
if (groupedActions.Count > 0)
{
- yield return await GetActionsGroupHtmlAsync(groupedActions, formStateData);
+ result.Add(await GetActionsGroupHtmlAsync(groupedActions, formStateData));
}
+
+ return result;
}
@@ -318,10 +379,11 @@ private async Task GetActionsGroupHtmlAsync(IEnumerable GetActionsWithoutGroupHtmlAsync(
+ private async Task> GetActionsWithoutGroupHtmlAsync(
IEnumerable actionsWithoutGroup, FormStateData formStateData)
{
var factory = GridView.ComponentFactory.ActionButton;
+ List result = [];
foreach (var action in actionsWithoutGroup)
{
var td = new HtmlBuilder(HtmlTag.Td);
@@ -330,11 +392,9 @@ private async IAsyncEnumerable GetActionsWithoutGroupHtmlAsync(
if (OnRenderActionAsync is not null)
{
var args = new ActionEventArgs(action, link, formStateData.Values);
-
-
+
await OnRenderActionAsync(GridView, args);
-
if (args.HtmlResult != null)
{
td.AppendText(args.HtmlResult);
@@ -345,8 +405,10 @@ private async IAsyncEnumerable GetActionsWithoutGroupHtmlAsync(
if (link != null)
td.AppendComponent(link);
- yield return td;
+ result.Add(td);
}
+
+ return result;
}
private static string GetTdStyle(FormElementField field)
diff --git a/src/Core/UI/Components/GridView/GridTableHeader.cs b/src/Core/UI/Components/GridView/GridTableHeader.cs
index 9ee865e8b..a548d0324 100644
--- a/src/Core/UI/Components/GridView/GridTableHeader.cs
+++ b/src/Core/UI/Components/GridView/GridTableHeader.cs
@@ -29,7 +29,7 @@ public async Task GetHtmlBuilderAsync()
await html.AppendAsync(HtmlTag.Tr, async tr =>
{
tr.AppendIf(GridView.EnableMultiSelect, GetMultSelectThHtmlElement);
- await tr.AppendRangeAsync(GetVisibleFieldsThList());
+ tr.AppendRange(await GetVisibleFieldsThList());
tr.AppendRange(GetActionsThList());
});
@@ -55,8 +55,9 @@ private IEnumerable GetActionsThList()
}
}
- private async IAsyncEnumerable GetVisibleFieldsThList()
+ private async Task> GetVisibleFieldsThList()
{
+ List thList = [];
foreach (var field in await GridView.GetVisibleFieldsAsync())
{
var th = new HtmlBuilder(HtmlTag.Th);
@@ -114,15 +115,17 @@ private async IAsyncEnumerable GetVisibleFieldsThList()
if (IsAppliedFilter(field, currentFilter))
{
th.AppendText(" ");
- th.Append((HtmlBuilder)new JJIcon("fa fa-filter").GetHtmlBuilder()
+ th.Append(new JJIcon("fa fa-filter").GetHtmlBuilder()
.WithToolTip(StringLocalizer["Applied filter"]));
}
- yield return th;
+ thList.Add(th);
}
+
+ return thList;
}
- private bool IsAppliedFilter(ElementField field, Dictionary currentFilter)
+ private static bool IsAppliedFilter(ElementField field, Dictionary currentFilter)
{
var hasFilterType = field.Filter.Type is not FilterMode.None;
var hasFieldOrFromKey = currentFilter.ContainsKey(field.Name) || currentFilter.ContainsKey($"{field.Name}_from");
diff --git a/src/Core/UI/Components/GridView/JJGridView.cs b/src/Core/UI/Components/GridView/JJGridView.cs
index 5c792135b..52d07aa63 100644
--- a/src/Core/UI/Components/GridView/JJGridView.cs
+++ b/src/Core/UI/Components/GridView/JJGridView.cs
@@ -25,6 +25,7 @@
using JJMasterData.Core.DataManager.Services;
using JJMasterData.Core.Extensions;
using JJMasterData.Core.Http.Abstractions;
+using JJMasterData.Core.Logging;
using JJMasterData.Core.Tasks;
using JJMasterData.Core.UI.Events.Args;
using JJMasterData.Core.UI.Html;
@@ -198,8 +199,11 @@ private static bool VisibleAtGrid(FormElementField field)
}
private bool IsUserSetDataSource { get; set; }
+
public bool ShowTitle { get; set; }
-
+
+ public List? TitleActions { get; set; }
+
public bool EnableFilter { get; set; }
public string? ParentComponentName { get; set; }
@@ -655,7 +659,7 @@ protected override async Task BuildResultAsync()
return new ContentComponentResult(html);
}
- if (ComponentContext is ComponentContext.GridViewFilterSearchBox)
+ if (ComponentContext is ComponentContext.SearchBoxFilter)
{
var fieldName = CurrentContext.Request.QueryString["fieldName"];
var field = FormElement.Fields[fieldName];
@@ -817,8 +821,8 @@ internal async Task GetTableRowHtmlAsync(int rowIndex)
var row = DataSource?[rowIndex];
string result = string.Empty;
- await foreach (var builder in Table.Body.GetTdHtmlList(row ?? new Dictionary(), rowIndex))
- result = result + builder;
+ foreach (var builder in await Table.Body.GetTdHtmlList(row ?? new Dictionary(), rowIndex))
+ result += builder;
return result;
}
@@ -836,7 +840,7 @@ public async Task GetTitleHtmlAsync()
internal async Task GetTitleAsync()
{
- return ComponentFactory.Html.Title.Create(FormElement, await GetFormStateDataAsync());
+ return ComponentFactory.Html.Title.Create(FormElement, await GetFormStateDataAsync(), TitleActions);
}
internal Task GetToolbarHtmlBuilder() => Toolbar.GetHtmlBuilderAsync();
@@ -1125,37 +1129,45 @@ private async Task SetDataSource()
private async Task GetDataSourceAsync(EntityParameters parameters)
{
- if (IsUserSetDataSource && DataSource != null)
+ try
{
+ if (IsUserSetDataSource && DataSource != null)
+ {
- using var dataView = new DataView(EnumerableHelper.ConvertToDataTable( new List>(DataSource)));
- dataView.Sort = parameters.OrderBy.ToQueryParameter();
- var dataTable = dataView.ToTable();
+ using var dataView = new DataView(EnumerableHelper.ConvertToDataTable( new List>(DataSource)));
+ dataView.Sort = parameters.OrderBy.ToQueryParameter();
+ var dataTable = dataView.ToTable();
- return DictionaryListResult.FromDataTable(dataTable);
- }
+ return DictionaryListResult.FromDataTable(dataTable);
+ }
- if (OnDataLoadAsync != null)
- {
- var args = new GridDataLoadEventArgs
+ if (OnDataLoadAsync != null)
{
- Filters = parameters.Filters,
- OrderBy = parameters.OrderBy,
- RecordsPerPage = parameters.RecordsPerPage,
- CurrentPage = parameters.CurrentPage,
- };
+ var args = new GridDataLoadEventArgs
+ {
+ Filters = parameters.Filters,
+ OrderBy = parameters.OrderBy,
+ RecordsPerPage = parameters.RecordsPerPage,
+ CurrentPage = parameters.CurrentPage,
+ };
- await OnDataLoadAsync.Invoke(this, args);
+ await OnDataLoadAsync.Invoke(this, args);
- if (args.DataSource is not null)
- {
- TotalOfRecords = args.TotalOfRecords;
+ if (args.DataSource is not null)
+ {
+ TotalOfRecords = args.TotalOfRecords;
- return new DictionaryListResult(args.DataSource, args.TotalOfRecords);
+ return new DictionaryListResult(args.DataSource, args.TotalOfRecords);
+ }
}
- }
- return await EntityRepository.GetDictionaryListResultAsync(FormElement, parameters);
+ return await EntityRepository.GetDictionaryListResultAsync(FormElement, parameters);
+ }
+ catch (Exception ex)
+ {
+ Logger.LogGridViewDataSourceException(ex, FormElement.Name);
+ throw;
+ }
}
///
diff --git a/src/Core/UI/Components/Html/Breadcrumb/BreadcrumbFactory.cs b/src/Core/UI/Components/Html/Breadcrumb/BreadcrumbFactory.cs
new file mode 100644
index 000000000..6060fb532
--- /dev/null
+++ b/src/Core/UI/Components/Html/Breadcrumb/BreadcrumbFactory.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+
+namespace JJMasterData.Core.UI.Components;
+
+public class BreadcrumbFactory : IComponentFactory
+{
+ public JJBreadcrumb Create()
+ {
+ return new JJBreadcrumb();
+ }
+
+ public JJBreadcrumb Create(IEnumerable items)
+ {
+ var breadcrumb = new JJBreadcrumb();
+ breadcrumb.Items.AddRange(items);
+
+ return breadcrumb;
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/Breadcrumb/BreadcrumbItem.cs b/src/Core/UI/Components/Html/Breadcrumb/BreadcrumbItem.cs
new file mode 100644
index 000000000..8b622a630
--- /dev/null
+++ b/src/Core/UI/Components/Html/Breadcrumb/BreadcrumbItem.cs
@@ -0,0 +1,42 @@
+#nullable enable
+
+using JJMasterData.Core.UI.Html;
+
+namespace JJMasterData.Core.UI.Components;
+
+public class BreadcrumbItem
+{
+ public string? Url { get; set; }
+
+ public HtmlBuilder HtmlContent { get; }
+
+ public string Content
+ {
+ init => HtmlContent.AppendText(value);
+ }
+
+ public BreadcrumbItem() : this(new HtmlBuilder())
+ {
+ }
+
+ public BreadcrumbItem(string text) : this()
+ {
+ HtmlContent.AppendText(text);
+ }
+
+ public BreadcrumbItem(string text, string url) : this(text)
+ {
+ Url = url;
+ }
+
+ public BreadcrumbItem(HtmlBuilder htmlContent)
+ {
+ HtmlContent = htmlContent;
+ }
+
+ public BreadcrumbItem(HtmlBuilder htmlContent, string url)
+ {
+ HtmlContent = htmlContent;
+ Url = url;
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/Breadcrumb/JJBreadcrumb.cs b/src/Core/UI/Components/Html/Breadcrumb/JJBreadcrumb.cs
new file mode 100644
index 000000000..77063d4c3
--- /dev/null
+++ b/src/Core/UI/Components/Html/Breadcrumb/JJBreadcrumb.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using JJMasterData.Core.UI.Html;
+
+namespace JJMasterData.Core.UI.Components;
+
+public class JJBreadcrumb : HtmlComponent
+{
+ public List Items { get; }
+
+ public JJBreadcrumb()
+ {
+ Items = [];
+ CssClass = "border-bottom mb-3";
+ }
+
+ internal override HtmlBuilder BuildHtml()
+ {
+ var html = new Div()
+ .WithNameAndId(Name)
+ .WithAttributes(Attributes)
+ .WithCssClass(CssClass)
+ .Append(HtmlTag.Nav, nav =>
+ {
+ nav.WithCssClass("mb-2 pb-2")
+ .WithAttribute("aria-label", "breadcrumb")
+ .Append(GetHtmlOlItems());
+ });
+
+ return html;
+ }
+
+ private HtmlBuilder GetHtmlOlItems()
+ {
+ var ol = new Ol();
+ ol.WithCssClass("breadcrumb mb-0");
+
+ var totalItems = Items.Count;
+ for (var index = 0; index < totalItems; index++)
+ {
+ var item = Items[index];
+ var isLast = index == totalItems - 1;
+ ol.Append(GetHtmlItem(item, isLast));
+ }
+
+ return ol;
+ }
+
+ private static HtmlBuilder GetHtmlItem(BreadcrumbItem item, bool isLast)
+ {
+ var li = new Li();
+ li.WithCssClass("breadcrumb-item");
+ li.WithCssClassIf(isLast, "active");
+
+ if (item.Url is null || isLast)
+ {
+ li.Append(item.HtmlContent);
+ }
+ else
+ {
+ li.Append(HtmlTag.A, a =>
+ {
+ a.WithAttribute("href", item.Url);
+ a.Append(item.HtmlContent);
+ });
+ }
+
+ return li;
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/CollapsePanel/JJCollapsePanel.cs b/src/Core/UI/Components/Html/CollapsePanel/JJCollapsePanel.cs
index 16954a15b..dba241e19 100644
--- a/src/Core/UI/Components/Html/CollapsePanel/JJCollapsePanel.cs
+++ b/src/Core/UI/Components/Html/CollapsePanel/JJCollapsePanel.cs
@@ -101,7 +101,7 @@ private HtmlBuilder GetAccordionHeader()
button.WithAttribute("id", $"heading-{Name.ToLower()}");
button.WithDataAttribute("toggle", "collapse");
button.WithDataAttribute("target", $"#collapse-{Name.ToLower()}");
- button.AppendComponentIf(TitleIcon != null, TitleIcon);
+ button.AppendComponentIf(TitleIcon != null, ()=>TitleIcon);
button.AppendTextIf(TitleIcon != null, " ");
button.AppendText(Title);
});
diff --git a/src/Core/UI/Components/Html/HtmlComponentFactory.cs b/src/Core/UI/Components/Html/HtmlComponentFactory.cs
index e2b559363..fc5a20fbe 100644
--- a/src/Core/UI/Components/Html/HtmlComponentFactory.cs
+++ b/src/Core/UI/Components/Html/HtmlComponentFactory.cs
@@ -18,13 +18,15 @@ public class HtmlComponentFactory(
public AlertFactory Alert => new();
+ public BreadcrumbFactory Breadcrumb => new();
+
public CardFactory Card => new();
public CollapsePanelFactory CollapsePanel => new(currentContext.Request.Form);
-
+
public IconFactory Icon => new();
- public ImageFactory Image => new(currentContext);
+ public ImageFactory Image => new();
public LabelFactory Label => new(stringLocalizer);
@@ -32,6 +34,10 @@ public class HtmlComponentFactory(
public MessageBoxFactory MessageBox => new(stringLocalizer);
+ public MessageToastFactory MessageToast => new(stringLocalizer);
+
+ public OffcanvasFactory Offcanvas => new();
+
public ModalDialogFactory ModalDialog => new();
public SpinnerFactory Spinner => new();
diff --git a/src/Core/UI/Components/Html/Image/ImageFactory.cs b/src/Core/UI/Components/Html/Image/ImageFactory.cs
index 69e373151..4700182b7 100644
--- a/src/Core/UI/Components/Html/Image/ImageFactory.cs
+++ b/src/Core/UI/Components/Html/Image/ImageFactory.cs
@@ -1,27 +1,14 @@
-using JJMasterData.Core.Http.Abstractions;
-
namespace JJMasterData.Core.UI.Components;
-public class ImageFactory(IHttpContext httpContext)
+public class ImageFactory : IComponentFactory
{
- public JJImage Create(string src)
+ JJImage IComponentFactory.Create()
{
- return new JJImage(src);
+ return new JJImage(string.Empty);
}
-
- public JJImage CreateMasterDataLogo()
+
+ public JJImage Create(string src)
{
- var appPath = httpContext.Request.ApplicationPath;
- var baseUrl = string.IsNullOrEmpty(appPath) ? "/" : appPath;
-
- if (!baseUrl.EndsWith("/"))
- baseUrl += "/";
-
- var logoSrc = $"{baseUrl}_content/JJMasterData.Web/images/JJMasterData.png";
- var image = Create(logoSrc);
- image.SetAttr("style","width:8%;height:8%;");
- image.Title = "JJMasterData";
- return image;
+ return new JJImage(src);
}
-
}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/Image/JJImage.cs b/src/Core/UI/Components/Html/Image/JJImage.cs
index eb0a43bb3..c6fc40f2a 100644
--- a/src/Core/UI/Components/Html/Image/JJImage.cs
+++ b/src/Core/UI/Components/Html/Image/JJImage.cs
@@ -9,7 +9,7 @@ public class JJImage : HtmlComponent
public string Src { get; set; }
public string? Title { get; set; }
- internal JJImage(string src)
+ public JJImage(string src)
{
Src = src;
}
diff --git a/src/Core/UI/Components/Html/Image/JJMasterDataLogo.cs b/src/Core/UI/Components/Html/Image/JJMasterDataLogo.cs
new file mode 100644
index 000000000..cbbe51caf
--- /dev/null
+++ b/src/Core/UI/Components/Html/Image/JJMasterDataLogo.cs
@@ -0,0 +1,32 @@
+using JJMasterData.Core.Http.Abstractions;
+using JJMasterData.Core.UI.Html;
+
+namespace JJMasterData.Core.UI.Components;
+
+public class JJMasterDataLogo(IHttpContext httpContext)
+{
+ public HtmlBuilder GetHtmlBuilder()
+ {
+ var logoSrc = GetMasterDataLogoSrc();
+
+ var image = new JJImage(logoSrc)
+ {
+ CssClass = "img-responsive md-logo",
+ Title = "JJMasterData"
+ };
+
+ return image.GetHtmlBuilder();
+ }
+
+ private string GetMasterDataLogoSrc()
+ {
+ var appPath = httpContext.Request.ApplicationPath;
+ var baseUrl = string.IsNullOrEmpty(appPath) ? "/" : appPath;
+
+ if (!baseUrl.EndsWith("/"))
+ baseUrl += "/";
+
+ var logoSrc = $"{baseUrl}_content/JJMasterData.Web/images/JJMasterData.png";
+ return logoSrc;
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/MessageBox/MessageBoxFactory.cs b/src/Core/UI/Components/Html/MessageBox/MessageBoxFactory.cs
index f28d92818..373f6c5c3 100644
--- a/src/Core/UI/Components/Html/MessageBox/MessageBoxFactory.cs
+++ b/src/Core/UI/Components/Html/MessageBox/MessageBoxFactory.cs
@@ -22,8 +22,8 @@ public JJMessageBox Create(string text, MessageIcon icon)
messageBox.Size = MessageSize.Default;
messageBox.Title = messageBox.Icon switch
{
- MessageIcon.Error => StringLocalizer["Erro"],
- MessageIcon.Warning => StringLocalizer["Aviso"],
+ MessageIcon.Error => StringLocalizer["Error"],
+ MessageIcon.Warning => StringLocalizer["Warning"],
MessageIcon.Info => StringLocalizer["Info"],
_ => StringLocalizer["Message"],
};
diff --git a/src/Core/UI/Components/Html/MessageToast/JJMessageToast.cs b/src/Core/UI/Components/Html/MessageToast/JJMessageToast.cs
new file mode 100644
index 000000000..6cf2f3c3e
--- /dev/null
+++ b/src/Core/UI/Components/Html/MessageToast/JJMessageToast.cs
@@ -0,0 +1,78 @@
+#nullable enable
+
+using JJMasterData.Core.UI.Html;
+using JJMasterData.Core.DataDictionary.Models;
+
+namespace JJMasterData.Core.UI.Components;
+
+public class JJMessageToast : HtmlComponent
+{
+ public string Title { get; set; } = null!;
+ public string? TitleMuted { get; set; }
+ public string? Message { get; set; }
+ public JJIcon? Icon { get; set; }
+ public BootstrapColor TitleColor { get; set; }
+ public bool ShowAsOpened { get; set; } = true;
+
+ internal JJMessageToast()
+ {
+ TitleColor = BootstrapColor.Default;
+ Name = "toast-alert";
+ }
+
+ internal override HtmlBuilder BuildHtml()
+ {
+ var htmlToast = new HtmlBuilder(HtmlTag.Div)
+ .WithCssClass("position-fixed bottom-0 end-0 p-3")
+ .WithAttribute("style", "z-index: 5")
+ .AppendDiv(alert =>
+ {
+ alert.WithId(Name)
+ .WithCssClass("toast fade")
+ .WithAttribute("role", "alert")
+ .WithAttribute("aria-live", "assertive")
+ .WithAttribute("aria-atomic", "true")
+ .AppendDiv(header =>
+ {
+ header.WithCssClass("toast-header")
+ .Append(HtmlTag.Strong)
+ .WithCssClass($"me-auto text-{TitleColor.ToColorString()}")
+ .Append(HtmlTag.Strong, s =>
+ {
+ s.WithCssClass($"me-auto text-{TitleColor.ToColorString()}")
+ .Append(Icon?.GetHtmlBuilder()?.WithCssClass("fs-7 me-1"))
+ .AppendText(Title);
+ })
+ .AppendIf(TitleMuted != null, HtmlTag.Small, small =>
+ {
+ small.WithCssClass("text-muted")
+ .AppendText(TitleMuted!);
+ })
+ .Append(HtmlTag.Button, b =>
+ {
+ b.WithCssClass("btn ms-2 p-0")
+ .WithAttribute("type", "button")
+ .WithAttribute("data-bs-dismiss", "toast")
+ .WithAttribute("aria-label", "Close")
+ .AppendSpan(uil => { uil.WithCssClass("uil uil-times fs-7"); });
+ });
+ });
+ alert.AppendIf(Message != null, HtmlTag.Div, body =>
+ {
+ body.WithCssClass("toast-body")
+ .AppendText(Message!);
+ });
+ });
+
+ var html = new HtmlBuilder();
+ html.Append(htmlToast);
+ html.AppendIf(ShowAsOpened, HtmlTag.Script, script =>
+ {
+ script.WithAttribute("type", "text/javascript")
+ .WithAttribute("lang", "javascript")
+ .AppendText($"MessageToastHelper.showWhenDOMLoaded('{Name}');");
+ });
+
+ return html;
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/MessageToast/MessageToastFactory.cs b/src/Core/UI/Components/Html/MessageToast/MessageToastFactory.cs
new file mode 100644
index 000000000..27bd22b4c
--- /dev/null
+++ b/src/Core/UI/Components/Html/MessageToast/MessageToastFactory.cs
@@ -0,0 +1,43 @@
+using System;
+using JJMasterData.Commons.Localization;
+using JJMasterData.Core.DataDictionary;
+using JJMasterData.Core.DataDictionary.Models;
+using Microsoft.Extensions.Localization;
+
+namespace JJMasterData.Core.UI.Components;
+
+public class MessageToastFactory(IStringLocalizer stringLocalizer) : IComponentFactory
+{
+ public JJMessageToast Create()
+ {
+ return new JJMessageToast();
+ }
+
+ public JJMessageToast Create(string message, BootstrapColor color = BootstrapColor.Default)
+ {
+ var messageToast = Create();
+ messageToast.Message = message;
+ messageToast.TitleMuted = DateTime.Now.ToShortTimeString();
+ messageToast.TitleColor = color;
+ messageToast.Icon = new JJIcon();
+
+ switch (color)
+ {
+ case BootstrapColor.Danger:
+ messageToast.Icon.IconClass = IconType.TimesCircle.GetCssClass();
+ messageToast.Title = stringLocalizer["Error"];
+ break;
+ case BootstrapColor.Warning:
+ messageToast.Icon.IconClass = IconType.Warning.GetCssClass();
+ messageToast.Title = stringLocalizer["Warning"];
+ break;
+ default:
+ messageToast.Icon.IconClass = IconType.Check.GetCssClass();
+ messageToast.Title = stringLocalizer["Operation Performed"];
+ break;
+ }
+
+ return messageToast;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/Offcanvas/JJOffcanvas.cs b/src/Core/UI/Components/Html/Offcanvas/JJOffcanvas.cs
new file mode 100644
index 000000000..1a0c04437
--- /dev/null
+++ b/src/Core/UI/Components/Html/Offcanvas/JJOffcanvas.cs
@@ -0,0 +1,43 @@
+#nullable enable
+using JJMasterData.Core.UI.Html;
+
+namespace JJMasterData.Core.UI.Components;
+
+public class JJOffcanvas : HtmlComponent
+{
+ public OffcanvasPosition Position { get; set; }
+ public string? Title { get; set; }
+ public HtmlBuilder? Body { get; set; }
+
+ internal override HtmlBuilder BuildHtml()
+ {
+ var offcanvas = new Div()
+ .WithCssClass($"offcanvas {Position.GetCssClass()}")
+ .WithAttribute("tabindex", "-1")
+ .WithId(Name)
+ .AppendDiv(div =>
+ {
+ div.WithCssClass("offcanvas-header")
+ .AppendIf(!string.IsNullOrEmpty(Title),HtmlTag.H5, h5 =>
+ {
+ h5.AppendText(Title!).WithCssClass("offcanvas-title");
+ })
+ .Append(HtmlTag.Button, button =>
+ {
+ button.WithAttribute("type", "button")
+ .WithCssClass("btn-close")
+ .WithAttribute("data-bs-dismiss", "offcanvas")
+ .WithAttribute("aria-label", "Close");
+ });
+ }
+ )
+ .AppendDiv(div =>
+ {
+ div.WithId(Name + "-body")
+ .WithCssClass("offcanvas-body")
+ .Append(Body);
+ });
+
+ return offcanvas;
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/Offcanvas/OffcanvasFactory.cs b/src/Core/UI/Components/Html/Offcanvas/OffcanvasFactory.cs
new file mode 100644
index 000000000..a9587eeb2
--- /dev/null
+++ b/src/Core/UI/Components/Html/Offcanvas/OffcanvasFactory.cs
@@ -0,0 +1,6 @@
+namespace JJMasterData.Core.UI.Components;
+
+public class OffcanvasFactory : IComponentFactory
+{
+ public JJOffcanvas Create() => new();
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/Offcanvas/OffcanvasPosition.cs b/src/Core/UI/Components/Html/Offcanvas/OffcanvasPosition.cs
new file mode 100644
index 000000000..eef974e08
--- /dev/null
+++ b/src/Core/UI/Components/Html/Offcanvas/OffcanvasPosition.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace JJMasterData.Core.UI.Components;
+
+public enum OffcanvasPosition
+{
+ Top,
+ Bottom,
+ Start,
+ End
+}
+
+public static class OffcanvasPositionExtensions
+{
+ public static string GetCssClass(this OffcanvasPosition offcanvasPosition)
+ {
+ return offcanvasPosition switch
+ {
+ OffcanvasPosition.Top => "offcanvas-top",
+ OffcanvasPosition.Bottom =>"offcanvas-bottom",
+ OffcanvasPosition.Start => "offcanvas-start",
+ OffcanvasPosition.End => "offcanvas-end",
+ _ => throw new ArgumentOutOfRangeException(nameof(offcanvasPosition), offcanvasPosition, null)
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/Title/JJTitle.cs b/src/Core/UI/Components/Html/Title/JJTitle.cs
index a33780063..64eabb107 100644
--- a/src/Core/UI/Components/Html/Title/JJTitle.cs
+++ b/src/Core/UI/Components/Html/Title/JJTitle.cs
@@ -1,4 +1,6 @@
-using System;
+#nullable enable
+using System;
+using System.Collections.Generic;
using JJMasterData.Core.DataDictionary;
using JJMasterData.Core.UI.Html;
@@ -6,10 +8,12 @@ namespace JJMasterData.Core.UI.Components;
public class JJTitle : HtmlComponent
{
- public string Title { get; set; }
- public string SubTitle { get; set; }
+ public string? Title { get; set; }
+ public string? SubTitle { get; set; }
public HeadingSize Size { get; set; }
public IconType? Icon { get; set; }
+
+ public List? Actions { get; set; }
private HtmlTag Tag => Size switch
{
@@ -21,9 +25,7 @@ public class JJTitle : HtmlComponent
HeadingSize.H6 => HtmlTag.H6,
_ => throw new ArgumentOutOfRangeException()
};
-
-
-
+
public JJTitle()
{
Size = HeadingSize.H1;
@@ -38,27 +40,52 @@ public JJTitle(string title, string subtitle)
internal override HtmlBuilder BuildHtml()
{
- if (string.IsNullOrWhiteSpace(Title) && string.IsNullOrWhiteSpace(SubTitle))
+ if (string.IsNullOrEmpty(Title) && string.IsNullOrEmpty(SubTitle))
return new HtmlBuilder();
- return new HtmlBuilder(HtmlTag.Div)
+ var div = new HtmlBuilder(HtmlTag.Div)
.WithNameAndId(Name)
.WithAttributes(Attributes)
.WithCssClass(CssClass)
.WithCssClass(BootstrapHelper.PageHeader)
- .Append(Tag, e =>
+ .WithCssClass("d-flex justify-content-between")
+ .Append(Tag, tag =>
{
- e.AppendIf(Icon.HasValue,HtmlTag.Span,span =>
+ tag.AppendIf(Icon.HasValue,HtmlTag.Span,span =>
{
span.AppendComponent(new JJIcon(Icon!.Value));
});
- e.AppendText(Title);
- e.Append(HtmlTag.Small, small =>
+ tag.AppendText(Title);
+ tag.Append(HtmlTag.Small, small =>
{
small.WithCssClass("sub-title");
small.AppendText($" {SubTitle}");
});
});
+
+ if (Actions == null)
+ return div;
+
+ div.AppendDiv(div =>
+ {
+ foreach (var action in Actions)
+ {
+ div.Append(HtmlTag.A,a =>
+ {
+ a.WithCssClass("btn btn-secondary");
+ a.WithHref(action.Url);
+ a.AppendComponentIf(Icon.HasValue, () => new JJIcon(action.Icon!.Value)
+ {
+ CssClass = "fs-8"
+ });
+ a.AppendTextIf(!string.IsNullOrEmpty(action.Text)," "+ action.Text!);
+ a.WithToolTip(action.Tooltip);
+ });
+ }
+ });
+
+
+ return div;
}
diff --git a/src/Core/UI/Components/Html/Title/TitleAction.cs b/src/Core/UI/Components/Html/Title/TitleAction.cs
new file mode 100644
index 000000000..14408c6eb
--- /dev/null
+++ b/src/Core/UI/Components/Html/Title/TitleAction.cs
@@ -0,0 +1,13 @@
+#nullable enable
+
+using JJMasterData.Core.DataDictionary;
+
+namespace JJMasterData.Core.UI.Components;
+
+public sealed class TitleAction
+{
+ public IconType? Icon { get; set; }
+ public string? Text { get; set; }
+ public string? Tooltip { get; set; }
+ public required string Url { get; set; }
+}
\ No newline at end of file
diff --git a/src/Core/UI/Components/Html/Title/TitleFactory.cs b/src/Core/UI/Components/Html/Title/TitleFactory.cs
index 2fb01fa15..9f40d512c 100644
--- a/src/Core/UI/Components/Html/Title/TitleFactory.cs
+++ b/src/Core/UI/Components/Html/Title/TitleFactory.cs
@@ -1,4 +1,6 @@
+#nullable enable
using System;
+using System.Collections.Generic;
using System.Drawing;
using JJMasterData.Core.DataDictionary;
using JJMasterData.Core.DataDictionary.Models;
@@ -14,17 +16,18 @@ public JJTitle Create()
return new JJTitle();
}
- public JJTitle Create(string title, string subtitle, IconType? icon)
+ public JJTitle Create(string title, string subtitle, IconType? icon = null, List? actions = null)
{
var htmlTitle = Create();
htmlTitle.Title = title;
htmlTitle.SubTitle = subtitle;
htmlTitle.Icon = icon;
+ htmlTitle.Actions = actions;
return htmlTitle;
}
- public JJTitle Create(FormElement formElement, FormStateData formStateData)
+ public JJTitle Create(FormElement formElement, FormStateData formStateData, List? actions)
{
if (formElement == null)
throw new ArgumentNullException(nameof(formElement));
@@ -33,6 +36,7 @@ public JJTitle Create(FormElement formElement, FormStateData formStateData)
htmlTitle.Title = expressionsService.GetExpressionValue(formElement.Title, formStateData) as string;
htmlTitle.Size = formElement.TitleSize;
htmlTitle.Icon = formElement.Icon;
+ htmlTitle.Actions = actions;
htmlTitle.SubTitle = expressionsService.GetExpressionValue(formElement.SubTitle, formStateData) as string;
return htmlTitle;
diff --git a/src/Core/UI/Components/IO/UploadView/JJUploadView.cs b/src/Core/UI/Components/IO/UploadView/JJUploadView.cs
index 706792125..5aa0408fd 100644
--- a/src/Core/UI/Components/IO/UploadView/JJUploadView.cs
+++ b/src/Core/UI/Components/IO/UploadView/JJUploadView.cs
@@ -550,8 +550,8 @@ await li.AppendAsync(HtmlTag.Table, async table =>
table.WithCssClass("table-gallery");
var fileValues = ConvertFormFileToDictionary(file);
var formStateData = new FormStateData(fileValues, UserValues, PageState.List);
- var htmlActions = GridView.Table.Body.GetActionsHtmlListAsync(formStateData);
- await table.AppendRangeAsync(htmlActions);
+ var htmlActions = await GridView.Table.Body.GetActionsHtmlListAsync(formStateData);
+ table.AppendRange(htmlActions);
});
});
});
diff --git a/src/Core/UI/Components/Importation/DataImportationHelp.cs b/src/Core/UI/Components/Importation/DataImportationHelp.cs
index 3bd76ac80..537312c86 100644
--- a/src/Core/UI/Components/Importation/DataImportationHelp.cs
+++ b/src/Core/UI/Components/Importation/DataImportationHelp.cs
@@ -37,7 +37,7 @@ public async Task GetHtmlHelpAsync()
var html = panel.BuildHtml()
.AppendHiddenInput("filename", "")
- .AppendComponentIf(!string.IsNullOrWhiteSpace(DataImportation.ImportAction.HelpText), new JJAlert
+ .AppendComponentIf(!string.IsNullOrWhiteSpace(DataImportation.ImportAction.HelpText), ()=>new JJAlert
{
Title = StringLocalizer["Information"],
Icon = IconType.InfoCircle,
diff --git a/src/Core/UI/Html/HtmlBuilder.Children.cs b/src/Core/UI/Html/HtmlBuilder.Children.cs
index 1a2729b98..02de98e0c 100644
--- a/src/Core/UI/Html/HtmlBuilder.Children.cs
+++ b/src/Core/UI/Html/HtmlBuilder.Children.cs
@@ -161,11 +161,11 @@ public HtmlBuilder AppendIf(bool condition, HtmlTag tag, Action? bu
///
/// Insert raw text as a child of caller builder.
///
- public HtmlBuilder AppendText(string rawText)
+ public HtmlBuilder AppendText(string? rawText)
{
if (!string.IsNullOrEmpty(rawText))
{
- var child = new HtmlBuilder(rawText);
+ var child = new HtmlBuilder(rawText!);
Append(child);
}
@@ -249,10 +249,10 @@ public HtmlBuilder AppendComponent(HtmlComponent? component)
return this;
}
- public HtmlBuilder AppendComponentIf(bool condition, HtmlComponent? component)
+ public HtmlBuilder AppendComponentIf(bool condition, Func componentFunc)
{
if (condition)
- AppendComponent(component);
+ AppendComponent(componentFunc());
return this;
}
diff --git a/src/Core/UI/Html/HtmlBuilder.cs b/src/Core/UI/Html/HtmlBuilder.cs
index 20b6b50b7..55fe0923f 100644
--- a/src/Core/UI/Html/HtmlBuilder.cs
+++ b/src/Core/UI/Html/HtmlBuilder.cs
@@ -88,7 +88,7 @@ private string ParseHtmlAsString(int tabCount)
}
html.Append('<');
- html.Append(Tag.TagName.ToString().ToLower());
+ html.Append(Tag.TagName.GetTagName());
html.Append(GetAttributesHtml());
if (!Tag.HasClosingTag)
@@ -112,7 +112,7 @@ private string ParseHtmlAsString(int tabCount)
}
html.Append("");
- html.Append(Tag.TagName.ToString().ToLower());
+ html.Append(Tag.TagName.GetTagName());
html.Append('>');
return html.ToString();
diff --git a/src/Core/UI/Html/HtmlBuilderTags.cs b/src/Core/UI/Html/HtmlBuilderTags.cs
index 8e6bbdf63..16b5fa4b6 100644
--- a/src/Core/UI/Html/HtmlBuilderTags.cs
+++ b/src/Core/UI/Html/HtmlBuilderTags.cs
@@ -17,6 +17,7 @@ public sealed class H3() : HtmlBuilder(HtmlTag.H3);
public sealed class H4() : HtmlBuilder(HtmlTag.H4);
public sealed class H5() : HtmlBuilder(HtmlTag.H5);
public sealed class H6() : HtmlBuilder(HtmlTag.H6);
+public sealed class Ol() : HtmlBuilder(HtmlTag.Ol);
public sealed class Small() : HtmlBuilder(HtmlTag.Small);
public sealed class Ul() : HtmlBuilder(HtmlTag.Ul);
public sealed class Li() : HtmlBuilder(HtmlTag.Li);
diff --git a/src/Core/UI/Html/HtmlTag.cs b/src/Core/UI/Html/HtmlTag.cs
index f864ec871..55ab8df32 100644
--- a/src/Core/UI/Html/HtmlTag.cs
+++ b/src/Core/UI/Html/HtmlTag.cs
@@ -1,4 +1,6 @@
-namespace JJMasterData.Core.UI.Html;
+using System;
+
+namespace JJMasterData.Core.UI.Html;
public enum HtmlTag
{
@@ -44,5 +46,63 @@ public enum HtmlTag
FieldSet,
Legend,
U,
- OptGroup
+ OptGroup,
+ Nav,
+ Ol
+}
+
+public static class HtmlTagExtensions
+{
+ public static string GetTagName(this HtmlTag tag)
+ {
+ return tag switch
+ {
+ HtmlTag.A => "a",
+ HtmlTag.B => "b",
+ HtmlTag.Blockquote => "blockquote",
+ HtmlTag.Area => "area",
+ HtmlTag.Br => "br",
+ HtmlTag.Div => "div",
+ HtmlTag.Span => "span",
+ HtmlTag.Label => "label",
+ HtmlTag.Input => "input",
+ HtmlTag.Strong => "strong",
+ HtmlTag.Button => "button",
+ HtmlTag.H1 => "h1",
+ HtmlTag.H2 => "h2",
+ HtmlTag.H3 => "h3",
+ HtmlTag.H4 => "h4",
+ HtmlTag.H5 => "h5",
+ HtmlTag.H6 => "h6",
+ HtmlTag.Small => "small",
+ HtmlTag.Ul => "ul",
+ HtmlTag.Li => "li",
+ HtmlTag.TextArea => "textarea",
+ HtmlTag.Script => "script",
+ HtmlTag.Select => "select",
+ HtmlTag.Option => "option",
+ HtmlTag.Table => "table",
+ HtmlTag.Tr => "tr",
+ HtmlTag.Th => "th",
+ HtmlTag.Td => "td",
+ HtmlTag.Thead => "thead",
+ HtmlTag.Tbody => "tbody",
+ HtmlTag.Hr => "hr",
+ HtmlTag.I => "i",
+ HtmlTag.Section => "section",
+ HtmlTag.P => "p",
+ HtmlTag.Footer => "footer",
+ HtmlTag.Img => "img",
+ HtmlTag.Center => "center",
+ HtmlTag.Video => "video",
+ HtmlTag.Form => "form",
+ HtmlTag.FieldSet => "fieldset",
+ HtmlTag.Legend => "legend",
+ HtmlTag.U => "u",
+ HtmlTag.OptGroup => "optgroup",
+ HtmlTag.Nav => "nav",
+ HtmlTag.Ol => "ol",
+ _ => throw new ArgumentOutOfRangeException(nameof(tag), tag, null)
+ };
+ }
}
\ No newline at end of file
diff --git a/src/Plugins/Hangfire/Hangfire.csproj b/src/Plugins/Hangfire/Hangfire.csproj
index 93ffae5e2..a2bae392c 100644
--- a/src/Plugins/Hangfire/Hangfire.csproj
+++ b/src/Plugins/Hangfire/Hangfire.csproj
@@ -5,9 +5,9 @@
true
JJMasterData Hangfire support to background tasks, like exportation and importation.
https://www.github.com/jjconsulting/jjmasterdata
- 2.0.2
- 2.0.2
- 2.0.2
+ 2.0.3
+ 2.0.3
+ 2.0.3
hangfire,jjmasterdata
JJMasterData.Hangfire
JJMasterData.Hangfire
diff --git a/src/Plugins/NCalc/Configuration/MasterDataServiceBuilderExtensions.cs b/src/Plugins/NCalc/Configuration/MasterDataServiceBuilderExtensions.cs
index 2e39e129b..ab6d43717 100644
--- a/src/Plugins/NCalc/Configuration/MasterDataServiceBuilderExtensions.cs
+++ b/src/Plugins/NCalc/Configuration/MasterDataServiceBuilderExtensions.cs
@@ -23,10 +23,29 @@ public static MasterDataServiceBuilder WithNCalcExpressionProvider(this MasterDa
builder.Services.PostConfigure(o =>
{
o.ReplaceDefaultExpressionProvider = options.ReplaceDefaultExpressionProvider;
- o.EvaluateOptions = options.EvaluateOptions;
+ o.ExpressionOptions = options.ExpressionOptions;
o.AdditionalFunctions = options.AdditionalFunctions;
});
return builder;
}
+
+ public static MasterDataServiceBuilder WithNCalcExpressions(this MasterDataServiceBuilder builder)
+ {
+ builder.WithNCalcExpressionProvider(new NCalcExpressionProviderOptions
+ {
+ ReplaceDefaultExpressionProvider = true,
+ AdditionalFunctions =
+ [
+ (name, args) =>
+ {
+ if (name == "now")
+ args.Result = DateTime.Now;
+ }
+ ]
+ });
+
+ return builder;
+ }
+
}
\ No newline at end of file
diff --git a/src/Plugins/NCalc/Configuration/NCalcExpressionProviderOptions.cs b/src/Plugins/NCalc/Configuration/NCalcExpressionProviderOptions.cs
index b0d1e2177..4559637bb 100644
--- a/src/Plugins/NCalc/Configuration/NCalcExpressionProviderOptions.cs
+++ b/src/Plugins/NCalc/Configuration/NCalcExpressionProviderOptions.cs
@@ -1,4 +1,5 @@
using NCalc;
+using NCalc.Handlers;
namespace JJMasterData.NCalc.Configuration;
@@ -10,9 +11,9 @@ public class NCalcExpressionProviderOptions
public bool ReplaceDefaultExpressionProvider { get; set; } = false;
///
- /// EvaluateOptions [Flags] enum. Check NCalc wiki for more information
+ /// ExpressionOptions [Flags] enum. Check NCalc wiki for more information
///
- public EvaluateOptions EvaluateOptions { get; set; } = EvaluateOptions.IgnoreCase | EvaluateOptions.CaseInsensitiveComparer;
+ public ExpressionOptions ExpressionOptions { get; set; } = ExpressionOptions.IgnoreCase | ExpressionOptions.CaseInsensitiveComparer;
///
/// Additional functions to be used at expressions. Check NCalc wiki for more information
diff --git a/src/Plugins/NCalc/NCalc.csproj b/src/Plugins/NCalc/NCalc.csproj
index 5d9a8482a..3183ac58d 100644
--- a/src/Plugins/NCalc/NCalc.csproj
+++ b/src/Plugins/NCalc/NCalc.csproj
@@ -12,10 +12,10 @@
JJMasterData.NCalc
ncalc,jjmasterdata
true
- Update NCalc to 3.12.0.
- 1.0.5
- 1.0.5
- 1.0.5
+ Update NCalc to 4.0.
+ 2.0.0
+ 2.0.0
+ 2.0.0
@@ -23,7 +23,7 @@
-
+
diff --git a/src/Plugins/NCalc/NCalcExpressionProvider.cs b/src/Plugins/NCalc/NCalcExpressionProvider.cs
index 68c3cbc43..8fa1d0fbe 100644
--- a/src/Plugins/NCalc/NCalcExpressionProvider.cs
+++ b/src/Plugins/NCalc/NCalcExpressionProvider.cs
@@ -6,7 +6,7 @@
namespace JJMasterData.NCalc;
-public class NCalcExpressionProvider(IOptionsSnapshot options) :
+public sealed class NCalcExpressionProvider(IOptionsSnapshot options) :
IAsyncExpressionProvider,
ISyncExpressionProvider
{
@@ -14,11 +14,10 @@ public class NCalcExpressionProvider(IOptionsSnapshot Options.ReplaceDefaultExpressionProvider ? "Expression" : "NCalc";
private NCalcExpressionProviderOptions Options { get; } = options.Value;
-
public object? Evaluate(string expression, Dictionary parsedValues)
{
var replacedExpression = ExpressionHelper.ReplaceExpression(expression, parsedValues);
- var ncalcExpression = new Expression(replacedExpression, Options.EvaluateOptions);
+ var ncalcExpression = new Expression(replacedExpression, Options.ExpressionOptions);
foreach (var function in Options.AdditionalFunctions)
ncalcExpression.EvaluateFunction += function;
diff --git a/src/Plugins/Pdf/Pdf.csproj b/src/Plugins/Pdf/Pdf.csproj
index 56c3f8653..c9dfd67ea 100644
--- a/src/Plugins/Pdf/Pdf.csproj
+++ b/src/Plugins/Pdf/Pdf.csproj
@@ -8,9 +8,9 @@
https://www.github.com/jjconsulting/jjmasterdata
JJMasterData.png
pdf,jjmasterdata
- 2.0.3
- 2.0.3
- 2.0.3
+ 2.0.4
+ 2.0.4
+ 2.0.4
© 2023 JJConsulting. All rights reserved.
JJMasterData.Pdf
JJMasterData.Pdf
diff --git a/src/Plugins/Pdf/PdfWriter.cs b/src/Plugins/Pdf/PdfWriter.cs
index da41d5a9f..e333f75ac 100644
--- a/src/Plugins/Pdf/PdfWriter.cs
+++ b/src/Plugins/Pdf/PdfWriter.cs
@@ -201,7 +201,8 @@ private async Task CreateCellAsync(Dictionary row, FormElem
}
else
{
- value = await FieldFormattingService.FormatGridValueAsync(field, row,null);
+ var fieldSelector = new FormElementFieldSelector(FormElement, field.Name);
+ value = await FieldFormattingService.FormatGridValueAsync(fieldSelector, new FormStateData(row,PageState.List));
}
}
@@ -306,7 +307,10 @@ private void SetCellStyle(FormElementField field, ref Cell cell)
string value = string.Empty;
string selectedValue = values[field.Name].ToString();
var formStateData = new FormStateData(values, PageState.List);
- var dataItemValues = await DataItemService.GetValuesAsync(field.DataItem!, formStateData);
+
+ var dataQuery = new DataQuery(formStateData, FormElement.ConnectionId);
+
+ var dataItemValues = await DataItemService.GetValuesAsync(field.DataItem!, dataQuery);
var item = dataItemValues.First(v=>v.Id == selectedValue);
if (item != null)
diff --git a/src/Web/Areas/DataDictionary/Controllers/AboutController.cs b/src/Web/Areas/DataDictionary/Controllers/AboutController.cs
index b7251adf1..b3c8a2b3f 100644
--- a/src/Web/Areas/DataDictionary/Controllers/AboutController.cs
+++ b/src/Web/Areas/DataDictionary/Controllers/AboutController.cs
@@ -17,7 +17,6 @@ public IActionResult Index()
ExecutingAssemblyVersion = executingAssembly.GetName()
.Version!.ToString(),
ExecutingAssemblyCopyright = AboutService.GetAssemblyCopyright(executingAssembly),
- Dependencies = AboutService.GetJJAssemblies(),
ExecutingAssemblyLastWriteTime = AboutService.GetAssemblyDate(executingAssembly)
};
diff --git a/src/Web/Areas/DataDictionary/Controllers/ElementController.cs b/src/Web/Areas/DataDictionary/Controllers/ElementController.cs
index 128f5aab1..8c151c9f2 100644
--- a/src/Web/Areas/DataDictionary/Controllers/ElementController.cs
+++ b/src/Web/Areas/DataDictionary/Controllers/ElementController.cs
@@ -4,6 +4,7 @@
using JJMasterData.Commons.Configuration.Options;
using JJMasterData.Commons.Data.Entity.Repository.Abstractions;
using JJMasterData.Commons.Localization;
+using JJMasterData.Core.DataDictionary.Models;
using JJMasterData.Core.UI.Components;
using JJMasterData.Core.UI.Events.Args;
using JJMasterData.Web.Areas.DataDictionary.Models;
@@ -123,7 +124,7 @@ public async Task Scripts(string elementName)
{
var formElement = await elementService.GetFormElementAsync(elementName);
var scripts = await scriptsService.GetScriptsAsync(formElement);
- var tableExists = await entityRepository.TableExistsAsync(formElement.TableName);
+ var tableExists = await entityRepository.TableExistsAsync(formElement.TableName, formElement.ConnectionId);
var model = new ElementScriptsViewModel
{
@@ -136,16 +137,16 @@ public async Task Scripts(string elementName)
}
[HttpPost]
- public async Task Add(AddElementViewModel model)
+ public async Task Add(ElementBean model)
{
- var element = await elementService.CreateEntityAsync(model.Name, model.ImportFields);
- if (element != null)
+ var formElement = await elementService.CreateEntityAsync(model);
+ if (formElement != null)
{
- return RedirectToAction("Index", "Entity", new { elementName = element.Name });
+ return RedirectToAction("Index", "Entity", new { elementName = formElement.Name });
}
- var jjValidationSummary = elementService.GetValidationSummary();
- ViewBag.Error = jjValidationSummary.GetHtml();
+ var validationSummary = elementService.GetValidationSummary();
+ ViewBag.Error = validationSummary.GetHtml();
return View();
}
diff --git a/src/Web/Areas/DataDictionary/Controllers/EntityController.cs b/src/Web/Areas/DataDictionary/Controllers/EntityController.cs
index a62c4b337..7b2007f72 100644
--- a/src/Web/Areas/DataDictionary/Controllers/EntityController.cs
+++ b/src/Web/Areas/DataDictionary/Controllers/EntityController.cs
@@ -1,17 +1,16 @@
-using JJMasterData.Commons.Configuration.Options;
+
using JJMasterData.Core.DataDictionary.Models;
using JJMasterData.Core.DataDictionary.Services;
using JJMasterData.Core.Events.Abstractions;
using JJMasterData.Core.UI.Events.Abstractions;
using JJMasterData.Web.Areas.DataDictionary.Models;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Options;
+
namespace JJMasterData.Web.Areas.DataDictionary.Controllers;
public class EntityController(
EntityService entityService,
- IOptions options,
IFormEventHandlerResolver? formEventHandlerFactory = null,
IGridEventHandlerResolver? gridEventHandlerResolver = null)
: DataDictionaryController
@@ -20,7 +19,25 @@ public async Task Index(string elementName)
{
return View(await Populate(elementName, true));
}
+
+ [HttpPost]
+ public async Task Index(
+ EntityViewModel model)
+ {
+ var entity = await entityService.EditEntityAsync(model.Entity, model.ElementName);
+
+ if (entity != null)
+ {
+ return View(model);
+ }
+ model.MenuId = "Entity";
+ model.ValidationSummary = entityService.GetValidationSummary();
+
+ return View(model);
+
+ }
+
public async Task Edit(string elementName)
{
return View(await Populate(elementName, false));
@@ -54,12 +71,6 @@ private async Task Populate(string elementName, bool readOnly)
FormEvent = formEventHandlerFactory?.GetFormEventHandler(elementName) as IEventHandler ?? gridEventHandlerResolver?.GetGridEventHandler(elementName),
Disabled = readOnly
};
-
- if (string.IsNullOrEmpty(viewModel.Entity.ReadProcedureName))
- entity.ReadProcedureName = options.Value.GetReadProcedureName(formElement);
-
- if (string.IsNullOrEmpty(viewModel.Entity.WriteProcedureName))
- entity.WriteProcedureName = options.Value.GetWriteProcedureName(formElement);
return viewModel;
}
diff --git a/src/Web/Areas/DataDictionary/Controllers/FieldController.cs b/src/Web/Areas/DataDictionary/Controllers/FieldController.cs
index 50889260b..3e236d98e 100644
--- a/src/Web/Areas/DataDictionary/Controllers/FieldController.cs
+++ b/src/Web/Areas/DataDictionary/Controllers/FieldController.cs
@@ -203,6 +203,7 @@ private async Task PopulateViewBag(FormElement formElement, FormElementField? fi
else
ViewBag.OriginalName = field.Name;
+ ViewBag.IsForm = formElement.TypeIdentifier == 'F';
ViewBag.MenuId = "Fields";
ViewBag.FormElement = formElement;
ViewBag.ElementName = formElement.Name;
diff --git a/src/Web/Areas/DataDictionary/Models/AboutViewModel.cs b/src/Web/Areas/DataDictionary/Models/AboutViewModel.cs
index eb75ff9a4..3a53134c5 100644
--- a/src/Web/Areas/DataDictionary/Models/AboutViewModel.cs
+++ b/src/Web/Areas/DataDictionary/Models/AboutViewModel.cs
@@ -4,7 +4,6 @@ namespace JJMasterData.Web.Areas.DataDictionary.Models;
public sealed class AboutViewModel
{
- public required List Dependencies { get; set; }
public required string ExecutingAssemblyProduct { get; set; }
public required string ExecutingAssemblyVersion { get; set; }
public required string ExecutingAssemblyCopyright { get; set; }
diff --git a/src/Web/Areas/DataDictionary/Models/AddElementViewModel.cs b/src/Web/Areas/DataDictionary/Models/AddElementViewModel.cs
deleted file mode 100644
index 048f89d51..000000000
--- a/src/Web/Areas/DataDictionary/Models/AddElementViewModel.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-
-namespace JJMasterData.Web.Areas.DataDictionary.Models;
-
-public sealed class AddElementViewModel
-{
- [Display(Name = "Table Or View Name", Prompt = "Table Or View Name")]
- public string Name { get; init; } = null!;
- [Display(Name = "Import Fields")]
- public bool ImportFields { get; init; }
-}
\ No newline at end of file
diff --git a/src/Web/Areas/DataDictionary/Models/ConnectionResult.cs b/src/Web/Areas/DataDictionary/Models/ConnectionResult.cs
deleted file mode 100644
index 800e22341..000000000
--- a/src/Web/Areas/DataDictionary/Models/ConnectionResult.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace JJMasterData.Web.Areas.DataDictionary.Models;
-
-public class ConnectionResult
-{
- public bool? IsConnectionSuccessful { get; set; }
- public string? ErrorMessage { get; set; }
-
- public ConnectionResult()
- {
-
- }
- public ConnectionResult(bool isConnectionSuccessful, string? errorMessage)
- {
- IsConnectionSuccessful = isConnectionSuccessful;
- ErrorMessage = errorMessage;
- }
-
-}
\ No newline at end of file
diff --git a/src/Web/Areas/DataDictionary/Models/ConnectionString.cs b/src/Web/Areas/DataDictionary/Models/ConnectionStringModel.cs
similarity index 91%
rename from src/Web/Areas/DataDictionary/Models/ConnectionString.cs
rename to src/Web/Areas/DataDictionary/Models/ConnectionStringModel.cs
index c471c8e7a..789260017 100644
--- a/src/Web/Areas/DataDictionary/Models/ConnectionString.cs
+++ b/src/Web/Areas/DataDictionary/Models/ConnectionStringModel.cs
@@ -3,7 +3,7 @@
namespace JJMasterData.Web.Areas.DataDictionary.Models;
-public class ConnectionString
+public class ConnectionStringModel
{
[Required] public string? Server { get; init; }
@@ -19,21 +19,21 @@ public class ConnectionString
public int? Timeout { get; init; }
- public bool? TrustServerCertificate { get; init; }
+ public bool TrustServerCertificate { get; init; }
- public bool? Encrypt { get; init; }
+ public bool Encrypt { get; init; }
- public bool? Pooling { get; init; }
+ public bool Pooling { get; init; }
public int? MinPoolSize { get; init; }
public int? MaxPoolSize { get; init; }
- public ConnectionString()
+ public ConnectionStringModel()
{
}
- public ConnectionString(string? connectionString)
+ public ConnectionStringModel(string? connectionString)
{
var builder = new DbConnectionStringBuilder
{
@@ -143,13 +143,13 @@ public override string ToString()
if (Timeout != null)
builder["timeout"] = Timeout;
- if (TrustServerCertificate != null)
+ if (TrustServerCertificate)
builder["trust server certificate"] = TrustServerCertificate;
- if (Encrypt != null)
+ if (Encrypt)
builder["encrypt"] = Encrypt;
- if (Pooling != null)
+ if (Pooling)
builder["pooling"] = Pooling;
if (MinPoolSize != null)
diff --git a/src/Web/Areas/DataDictionary/Models/EntityViewModel.cs b/src/Web/Areas/DataDictionary/Models/EntityViewModel.cs
index 5644e4c68..cb100fbd7 100644
--- a/src/Web/Areas/DataDictionary/Models/EntityViewModel.cs
+++ b/src/Web/Areas/DataDictionary/Models/EntityViewModel.cs
@@ -12,7 +12,7 @@ public sealed class EntityViewModel : DataDictionaryViewModel
public string FormEventType => IsPythonFormEvent ? "Python" : ".NET";
public bool IsPythonFormEvent => FormEvent != null && FormEvent.GetType().ToString().Contains('$');
public bool Disabled { get; init; }
-
+
// ReSharper disable once UnusedMember.Global
// Reason: Used for model binding.
public EntityViewModel()
diff --git a/src/Web/Areas/DataDictionary/Models/SettingsViewModel.cs b/src/Web/Areas/DataDictionary/Models/SettingsViewModel.cs
index b0661c977..7df8eca96 100644
--- a/src/Web/Areas/DataDictionary/Models/SettingsViewModel.cs
+++ b/src/Web/Areas/DataDictionary/Models/SettingsViewModel.cs
@@ -7,7 +7,7 @@ namespace JJMasterData.Web.Areas.DataDictionary.Models;
public sealed class SettingsViewModel
{
- public required ConnectionString ConnectionString { get; init; } = new();
+ public required ConnectionStringModel ConnectionString { get; init; } = new();
public MasterDataCommonsOptions? Options { get; init; }
public string? FilePath { get; init; }
diff --git a/src/Web/Areas/DataDictionary/Services/SettingsService.cs b/src/Web/Areas/DataDictionary/Services/SettingsService.cs
index 88c0b0dec..c810af6ed 100644
--- a/src/Web/Areas/DataDictionary/Services/SettingsService.cs
+++ b/src/Web/Areas/DataDictionary/Services/SettingsService.cs
@@ -1,6 +1,7 @@
using JJMasterData.Commons.Configuration.Options;
using JJMasterData.Commons.Configuration.Options.Abstractions;
using JJMasterData.Commons.Data;
+using JJMasterData.Commons.Data.Entity.Models;
using JJMasterData.Commons.Localization;
using JJMasterData.Core.Configuration.Options;
using JJMasterData.Core.DataDictionary.Repository.Abstractions;
@@ -63,12 +64,11 @@ public async Task GetViewModel()
var connectionResult = await GetConnectionResultAsync(connectionString, connectionProvider);
var viewModel = new SettingsViewModel
{
- ConnectionString = new ConnectionString(connectionString),
+ ConnectionString = new ConnectionStringModel(connectionString),
CommonsOptions = CommonsWritableOptions.Value!,
CoreOptions = CoreWritableOptions.Value!,
WebOptions = WebWritableOptions.Value!,
- FilePath = CoreWritableOptions.FilePath,
-
+ FilePath = CoreWritableOptions.FilePath
};
if (!viewModel.PathExists)
@@ -96,7 +96,6 @@ public static async Task GetConnectionResultAsync(
{
TimeOut = 5
};
- var result = await dataAccess.TryConnectionAsync(cancellationToken);
- return new ConnectionResult(result.Item1, result.Item2);
+ return await dataAccess.TryConnectionAsync(cancellationToken);
}
}
\ No newline at end of file
diff --git a/src/Web/Areas/DataDictionary/Views/About/Index.cshtml b/src/Web/Areas/DataDictionary/Views/About/Index.cshtml
index 1da3d11fc..8b02130c4 100644
--- a/src/Web/Areas/DataDictionary/Views/About/Index.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/About/Index.cshtml
@@ -6,33 +6,20 @@
}
-
+
@Model.ExecutingAssemblyProduct
- Version: @Model.ExecutingAssemblyVersion
+ @Localizer["Version"]: @Model.ExecutingAssemblyVersion
- Last Write: @Model.ExecutingAssemblyLastWriteTime
+ @Localizer["Last Write"]: @Model.ExecutingAssemblyLastWriteTime
@Model.ExecutingAssemblyCopyright
-
-
- @foreach (var assembly in Model.Dependencies!)
- {
- -
- @assembly.GetName().Name
-
- Version: @assembly.GetName().Version?.ToString()
-
-
- }
-
-
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/AuditLogFormToolbarAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/AuditLogFormToolbarAction.cshtml
index e9a8c2e5c..e4091c4ae 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/AuditLogFormToolbarAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/AuditLogFormToolbarAction.cshtml
@@ -9,14 +9,14 @@
}
@using (Html.BeginMasterDataForm("AuditLogFormToolbarAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/AuditLogGridToolbarAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/AuditLogGridToolbarAction.cshtml
index e852d78aa..0a0161c4b 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/AuditLogGridToolbarAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/AuditLogGridToolbarAction.cshtml
@@ -10,14 +10,14 @@
}
@using (Html.BeginMasterDataForm("AuditLogGridToolbarAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/BackAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/BackAction.cshtml
index 69489cba1..21102e909 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/BackAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/BackAction.cshtml
@@ -7,14 +7,14 @@
}
@using (Html.BeginMasterDataForm("BackAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/CancelAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/CancelAction.cshtml
index 0097cbf4e..97af80bba 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/CancelAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/CancelAction.cshtml
@@ -7,14 +7,14 @@
}
@using (Html.BeginMasterDataForm("CancelAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/ConfigAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/ConfigAction.cshtml
index 5c408fec3..f96f49639 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/ConfigAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/ConfigAction.cshtml
@@ -18,7 +18,7 @@
@StringLocalizer["Advanced"]
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/DeleteAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/DeleteAction.cshtml
index d4f685e7d..b4a9ea0be 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/DeleteAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/DeleteAction.cshtml
@@ -7,14 +7,14 @@
}
@using (Html.BeginMasterDataForm("DeleteAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/EditAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/EditAction.cshtml
index f1f87148a..adb8c643c 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/EditAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/EditAction.cshtml
@@ -9,7 +9,7 @@
}
@using (Html.BeginMasterDataForm("EditAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/ExportAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/ExportAction.cshtml
index c6cfb8ffe..468f473f2 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/ExportAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/ExportAction.cshtml
@@ -7,7 +7,7 @@
}
@using (Html.BeginMasterDataForm("ExportAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/FilterAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/FilterAction.cshtml
index 6a9c2cf9c..9a48d89dc 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/FilterAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/FilterAction.cshtml
@@ -7,7 +7,7 @@
}
@using (Html.BeginMasterDataForm("FilterAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/FormEditAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/FormEditAction.cshtml
index 06f2c5d86..7cbc37438 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/FormEditAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/FormEditAction.cshtml
@@ -7,14 +7,14 @@
}
@using (Html.BeginMasterDataForm("FormEditAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/ImportAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/ImportAction.cshtml
index 6f585e835..3ce3b7623 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/ImportAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/ImportAction.cshtml
@@ -7,7 +7,7 @@
}
@using (Html.BeginMasterDataForm("ImportAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/InsertAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/InsertAction.cshtml
index 80cadf073..0f4e76079 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/InsertAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/InsertAction.cshtml
@@ -33,7 +33,7 @@
}
@using (Html.BeginMasterDataForm("InsertAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/InternalAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/InternalAction.cshtml
index 47f4e7230..bdc6cd545 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/InternalAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/InternalAction.cshtml
@@ -49,7 +49,7 @@
@using (Html.BeginMasterDataForm("InternalAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }))
{
@@ -59,7 +59,7 @@
@StringLocalizer["Advanced"]
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/LegendAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/LegendAction.cshtml
index 817641840..c6f800fa9 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/LegendAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/LegendAction.cshtml
@@ -7,14 +7,14 @@
}
@using (Html.BeginMasterDataForm("LegendAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/PluginAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/PluginAction.cshtml
index 8997a9c6d..ffda527c9 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/PluginAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/PluginAction.cshtml
@@ -35,7 +35,7 @@
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/PluginFieldAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/PluginFieldAction.cshtml
index 695e1f0c3..2c5bb1203 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/PluginFieldAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/PluginFieldAction.cshtml
@@ -21,7 +21,7 @@
}
@using (Html.BeginMasterDataForm("PluginFieldAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }))
{
@@ -43,7 +43,7 @@
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/RefreshAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/RefreshAction.cshtml
index 025297a9d..793f05cbc 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/RefreshAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/RefreshAction.cshtml
@@ -7,14 +7,14 @@
}
@using (Html.BeginMasterDataForm("RefreshAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/SaveAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/SaveAction.cshtml
index c2ae1e842..efa4c0c68 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/SaveAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/SaveAction.cshtml
@@ -7,14 +7,14 @@
}
@using (Html.BeginMasterDataForm("SaveAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/ScriptAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/ScriptAction.cshtml
index f055470fc..029112da7 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/ScriptAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/ScriptAction.cshtml
@@ -8,7 +8,7 @@
}
@using (Html.BeginMasterDataForm("ScriptAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }))
{
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/SortAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/SortAction.cshtml
index 6896b6fc4..491151593 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/SortAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/SortAction.cshtml
@@ -7,14 +7,14 @@
}
@using (Html.BeginMasterDataForm("SortAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction }))
{
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/SqlCommandAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/SqlCommandAction.cshtml
index 858df99fd..8360dc2e3 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/SqlCommandAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/SqlCommandAction.cshtml
@@ -45,7 +45,7 @@
}
@using (Html.BeginMasterDataForm("SqlCommandAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }))
{
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/UrlRedirectAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/UrlRedirectAction.cshtml
index 9ff4c769b..e69545281 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/UrlRedirectAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/UrlRedirectAction.cshtml
@@ -8,7 +8,7 @@
}
@using (Html.BeginMasterDataForm("UrlRedirectAction", "Actions",
- new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }, FormMethod.Post))
+ new { elementName = ViewBag.ElementName, context = ViewBag.ContextAction, fieldName = ViewBag.FieldName }))
{
-
+
@await Html.PartialAsync("_NavGeneral", Model)
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/ViewAction.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/ViewAction.cshtml
index 2ee314b58..8904db9f2 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/ViewAction.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/ViewAction.cshtml
@@ -22,7 +22,7 @@
-
+
diff --git a/src/Web/Areas/DataDictionary/Views/Actions/_List.cshtml b/src/Web/Areas/DataDictionary/Views/Actions/_List.cshtml
index 9933020c6..f0e99f8a8 100644
--- a/src/Web/Areas/DataDictionary/Views/Actions/_List.cshtml
+++ b/src/Web/Areas/DataDictionary/Views/Actions/_List.cshtml
@@ -94,12 +94,12 @@
|