Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Mimeo.DynamicUI.Blazor/FormFields/DynamicField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class DynamicField : ComponentBase
private static readonly Dictionary<FormFieldType, Type> formFieldTypeMap = new()
{
{ FormFieldType.Text, typeof(TextField) },
{ FormFieldType.Combobox, typeof(TextField) },
{ FormFieldType.Checkbox, typeof(CheckboxField) },
{ FormFieldType.SingleSelect, typeof(SingleSelectField) },
{ FormFieldType.MultiSelect, typeof(MultiSelectField) },
Expand All @@ -22,7 +23,12 @@ public class DynamicField : ComponentBase
{ FormFieldType.DateTime, typeof(DateTimeField) },
{ FormFieldType.Integer, typeof(IntegerField) },
{ FormFieldType.Decimal, typeof(DecimalField) },
#pragma warning disable CS0618 // Type or member is obsolete (Justification: Backwards compatibility)
{ FormFieldType.List, typeof(ListField<>) },
#pragma warning restore CS0618 // Type or member is obsolete
{ FormFieldType.Table, typeof(ListField<>) },
{ FormFieldType.SectionList, typeof(ListField<>) },
{ FormFieldType.ReorderableSectionList, typeof(ListField<>) },
{ FormFieldType.Nullable, typeof(NullableFormField) },
{ FormFieldType.Guid, typeof(GuidFormField) }
};
Expand Down Expand Up @@ -118,7 +124,7 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
builder.CloseComponent();
}

private bool InheritsFormFieldBase(Type type)
private static bool InheritsFormFieldBase(Type type)
{
// The built-in methods don't support unbound generics (or I haven't found the correct one yet)

Expand Down
4 changes: 2 additions & 2 deletions Mimeo.DynamicUI.Blazor/FormFields/ListField.razor
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
@typeparam T
@inherits FormFieldBase<List<T>>

@if (!wrapInViewModel && ListDefinition?.PresentationMode == ListFieldPresentationMode.SectionList)
@if (!wrapInViewModel && ListDefinition?.Type == FormFieldType.SectionList)
{
if (ReadOnly)
{
Expand Down Expand Up @@ -56,7 +56,7 @@
<RadzenButton Icon="add_circle_outline" style="margin-top:1em;margin-bottom:1em;" Text="@lang.GetValueOrDefault("add")" Click="() => OnCreate(CreateViewModel())" />
}
}
else if (!wrapInViewModel && ListDefinition?.PresentationMode == ListFieldPresentationMode.ReorderableSectionList)
else if (!wrapInViewModel && ListDefinition?.Type == FormFieldType.ReorderableSectionList)
{
if (ReadOnly)
{
Expand Down
2 changes: 1 addition & 1 deletion Mimeo.DynamicUI.Blazor/Forms/ODataGrid.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ private void ShowTooltip(ElementReference element, string languageKey)
}
private bool GetActionsMenuVisibility()
{
return CanCopy || CanUpdate || CanView || CanDelete;
return CanCopy || CanUpdate || CanView || CanDelete || CustomRowActions.Any();
}

private GridItem CreateGridItem(ViewModel listModel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ protected override IEnumerable<FormFieldDefinition> GetListFormFields()
yield return FormField(() => Number);
yield return FormField(() => Decimal);
yield return FormField(() => DateTimeUtc, dateDisplayMode: DateDisplayMode.UserLocal);
yield return FormField(() => StringList);
yield return Table(() => StringList);
}

protected override IEnumerable<FormFieldDefinition> GetDropDownListFormFields()
Expand Down Expand Up @@ -185,13 +185,13 @@ protected override IEnumerable<FormFieldDefinition> GetEditFormFields()
yield return FormField(() => ComboBox, textType: TextType.SingleLine, items: ["Option 1", "option2languagekey", "Option 3"]);
yield return new FormFieldDefinition(FormFieldType.Color, () => Color);
yield return FormField(() => Section);
yield return FormField(() => StringList);
yield return Table(() => StringList);

// Depending on the structure of the view model, sometimes a table is more appropriate
yield return FormField(() => SimpleModelList, mode: ListFieldPresentationMode.Table);
yield return Table(() => SimpleModelList);

// but for sufficiently large view models, a section list is easier on the user
yield return FormField(() => AdvancedModelList, m => m.FormField(() => m.Property1), mode: ListFieldPresentationMode.SectionList);
yield return SectionList(() => AdvancedModelList, m => m.FormField(() => m.Property1));

yield return new SingleSelectDropDownFormFieldDefinition(() => RelatedModelId, relatedModelsSource, FormField(() => Name), idField);
yield return new MultiSelectDropDownFormFieldDefinition(() => RelatedModelIds, relatedModelsSource, FormField(() => Name), idField);
Expand Down Expand Up @@ -233,9 +233,9 @@ protected override IEnumerable<FormFieldDefinition> GetSearchFormFields()
yield return FormField(() => ComboBox, textType: TextType.SingleLine, items: ["Option 1", "option2languagekey", "Option 3"]);
yield return new FormFieldDefinition(FormFieldType.Color, () => Color);
yield return FormField(() => Section);
yield return FormField(() => StringList);
yield return FormField(() => SimpleModelList);
yield return FormField(() => AdvancedModelList);
yield return Table(() => StringList);
yield return Table(() => SimpleModelList);
yield return SectionList(() => AdvancedModelList);
yield return FormField(() => Enabled);
yield return new NullableFormFieldDefinition(() => NullableStringEnabled, FormField(() => NullableStringValue));
yield return new FormFieldDefinition(FormFieldType.Checkbox, () => EnableHiddenProperties)
Expand All @@ -249,15 +249,15 @@ protected override IEnumerable<FormFieldDefinition> GetSearchFormFields()

}

public class SimpleSubViewModel : ViewModel, INotifyPropertyChanged
public class SimpleSubViewModel : ViewModel
{
public string? Property1
{
get => _property1;
set
{
_property1 = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Property1)));
RaisePropertyChanged(nameof(Property1));
}
}
private string? _property1;
Expand All @@ -268,14 +268,11 @@ public int Property2
set
{
_property2 = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Property2)));
RaisePropertyChanged(nameof(Property2));
}
}
private int _property2;

// INotifyPropertyChanged is partially supported by the UI, and is generally not required, but can be useful in niche situations
public event PropertyChangedEventHandler? PropertyChanged;

protected override IEnumerable<FormFieldDefinition> GetEditFormFields()
{
yield return FormField(() => Property1);
Expand All @@ -291,7 +288,7 @@ public string? Property1
set
{
_property1 = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Property1)));
RaisePropertyChanged(nameof(Property1));
}
}
private string? _property1;
Expand All @@ -302,21 +299,18 @@ public int Property2
set
{
_property2 = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Property2)));
RaisePropertyChanged(nameof(Property2));
}
}
private int _property2;

public List<string> SubList { get; set; } = [];

// INotifyPropertyChanged is partially supported by the UI, and is generally not required, but can be useful in niche situations
public event PropertyChangedEventHandler? PropertyChanged;

protected override IEnumerable<FormFieldDefinition> GetEditFormFields()
{
yield return FormField(() => Property1);
yield return FormField(() => Property2);
yield return FormField(() => SubList);
yield return Table(() => SubList);
}
}

Expand Down
5 changes: 5 additions & 0 deletions Mimeo.DynamicUI/Data/OData/ODataExpressionGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,12 @@ public IEnumerable<DataFilterOperator> GetSupportedFilterOperators(DataFieldDefi
DataFilterOperator.GreaterThan,
DataFilterOperator.GreaterThanOrEquals
};
#pragma warning disable CS0618 // Type or member is obsolete (Justification: Backwards compatibility)
case FormFieldType.List:
#pragma warning restore CS0618 // Type or member is obsolete
case FormFieldType.Table:
case FormFieldType.SectionList:
case FormFieldType.ReorderableSectionList:
var sampleItem = (filter.FormFieldDefinition as IListFieldDefinition)?.CreateNewItem();
if (sampleItem is ViewModel)
{
Expand Down
2 changes: 2 additions & 0 deletions Mimeo.DynamicUI/FormFieldDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ public string FilterPropertyName

public string LanguageKey { get; set; }

public string DescriptionLanguageKey => LanguageKey + "_desc";

public Type PropertyType { get; set; }

public Type? FilterType { get; set; }
Expand Down
61 changes: 59 additions & 2 deletions Mimeo.DynamicUI/FormFieldType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,79 @@
public enum FormFieldType
{
Hidden = 0,
Text,

/// <summary>
/// A field that accepts user-entered text
/// </summary>
Text,

/// <summary>
/// A field that accepts user-entered text but presents some pre-defined values
/// </summary>
Combobox,

Checkbox,

/// <summary>
/// A field that presents the user with pre-defined value and allows selection of a single value
/// </summary>
SingleSelect,

/// <summary>
/// A field that presents the user with a dropdown to select a single pre-defined value
/// </summary>
SingleSelectDropdown,

/// <summary>
/// A field that presents the user with a dropdown to select a single value from a data source
/// </summary>
SingleSelectDataSourceDropdown,

/// <summary>
/// A field that presents the user with pre-defined value and allows selection of multiple values
/// </summary>
MultiSelect,

/// <summary>
/// A field that presents the user with a dropdown to select one or more pre-defined values
/// </summary>
MultiSelectDropdown,

/// <summary>
/// A field that presents the user with values that come from a data source and allows selection of multiple values
/// </summary>
MultiSelectDataSourceDropdown,

Date,
Time,
DateTime,
Color,
Integer,
Decimal,
Decimal,

[Obsolete("Use Table, SectionList, or ReorderableSectionList instead")]
List,

/// <summary>
/// Presents a list of items or view models in a table
/// </summary>
Table,

/// <summary>
/// Presents a list of items or view models as a sequential list of sub-editors
/// </summary>
SectionList,

/// <summary>
/// Presents a list of items or view models as a sequential list of sub-editors, with the ability to reorder items
/// </summary>
ReorderableSectionList,

/// <summary>
/// Presents another form field, wrapped with a checkbox that is meant to indicate whether the value is null
/// </summary>
Nullable,

Guid,
Section,
Custom
Expand Down
41 changes: 40 additions & 1 deletion Mimeo.DynamicUI/ListFieldDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,54 @@ public interface IListFieldDefinition

public class ListFieldDefinition<T> : FormFieldDefinition, IListFieldDefinition
{
[Obsolete("Use overload with FormFieldType instead")]
public ListFieldDefinition(Expression<Func<List<T>>> @for)
: base(FormFieldType.List, LinqExtensions.Cast<List<T>, object?>(@for))
{
}

public ListFieldDefinition(FormFieldType formFieldType, Expression<Func<List<T>>> @for)
: base(formFieldType, LinqExtensions.Cast<List<T>, object?>(@for))
{
switch (formFieldType)
{
case FormFieldType.Table:
case FormFieldType.SectionList:
case FormFieldType.ReorderableSectionList:
break;
default:
throw new ArgumentException("formFieldType must be Table, SectionList, or ReorderableSectionList", nameof(formFieldType));
}
}

public FormFieldType? ItemFormFieldType { get; set; }

public Func<T>? NewItemCreator { get; set; }

public ListFieldPresentationMode PresentationMode { get; set; } = ListFieldPresentationMode.Table;
[Obsolete("Differentiate using FormFieldType instead")]
public ListFieldPresentationMode PresentationMode
{
get => _presentationMode;
set
{
_presentationMode = value;
if (_presentationMode == ListFieldPresentationMode.Table)
{
this.Type = FormFieldType.Table;
}
else if (_presentationMode == ListFieldPresentationMode.SectionList)
{
this.Type = FormFieldType.SectionList;
}
else if (_presentationMode == ListFieldPresentationMode.ReorderableSectionList)
{
this.Type = FormFieldType.ReorderableSectionList;
}
}
}

[Obsolete("Differentiate using FormFieldType instead")]
private ListFieldPresentationMode _presentationMode = ListFieldPresentationMode.Table;

/// <summary>
/// For use with <see cref="PresentationMode"/> equal to <see cref="ListFieldPresentationMode.SectionList"/> or <see cref="ListFieldPresentationMode.ReorderableSectionList"/>,
Expand Down Expand Up @@ -50,6 +88,7 @@ public T CreateNewItem()
object? IListFieldDefinition.CreateNewItem() => CreateNewItem();
}

[Obsolete("Differentiate using FormFieldType instead")]
public enum ListFieldPresentationMode
{
Table,
Expand Down
18 changes: 17 additions & 1 deletion Mimeo.DynamicUI/TextFieldDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ public TextType TextType
/// <summary>
/// An optional set of values that can be selected as a combobox. Requires <see cref="TextType"/> to be <see cref="DynamicUI.TextType.SingleLine"/>.
/// </summary>
public List<string>? Items { get; set; }
public List<string>? Items
{
get => _items;
set
{
_items = value;

if (value != null && value.Count > 0)
{
// Backwards compatibility for when Items was just an option under a Text form field type
Type = FormFieldType.Combobox;
}
}
}
private List<string>? _items;

public bool MultiLine => TextType != TextType.SingleLine;
}
}
Loading