Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic data 2 - Auto UI #1293

Merged
merged 64 commits into from
Aug 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
f549498
Make DynamicEntity and DynamicEditor work compile-time
exyi Feb 13, 2022
993a616
Sample for DynamicEditor added
tomasherceg Feb 13, 2022
23da0a2
SelectorFormEditorProvider implemented
tomasherceg Feb 13, 2022
b4bc92c
DynamicEntity is now just a wrapper for DynamicEditor
exyi Feb 13, 2022
fadd94b
Added OnChange to DynamicEditor
exyi Feb 13, 2022
ffe196d
Added Changed- property group to dynamic entity
exyi Feb 13, 2022
41e025d
Property metadata rules fluent API added
tomasherceg Feb 13, 2022
fa80590
Added cascading ComboBox to DynamicEntity sample
tomasherceg Feb 13, 2022
be2fec2
Migrate dynamic data to nullable types, remove redundant code
exyi Feb 19, 2022
e908715
Add rudimentary localization support
exyi Feb 19, 2022
b490428
Infer textbox type from property type or DataType attribute
exyi Feb 19, 2022
facf470
dynamic data: Remove the form builder indirection.
exyi Feb 19, 2022
ad012d9
dynamic data: Replace bootstrap builder
exyi Feb 20, 2022
0f2ea50
Visible and Enabled attribute support added
tomasherceg Feb 20, 2022
06b12d3
dynamic data: add support for DynamicGridColumn
exyi Feb 20, 2022
fc747f0
styles: support Replace in Appended control
exyi Feb 20, 2022
c01baad
dynamic data: support DynamicColumns virtual column
exyi Feb 20, 2022
78e6a8b
dynamic data: Support Grid inline editing
exyi Feb 20, 2022
0f87e7a
dynamic data: proper support for label[for]
exyi Feb 20, 2022
4884e2a
dynamic data: add include/exclude properties
exyi Feb 20, 2022
78b6f02
Implement DynamicEditor.Attributes
exyi Feb 20, 2022
46318b7
LocalizableString uses DynamicDataContext in ToBinding method
tomasherceg Feb 20, 2022
2e308fb
Make DataContextStack binding property optional
exyi Feb 20, 2022
43a6923
Removed UseLocalizationResourceFiles flag from configuration
tomasherceg Feb 20, 2022
d19a366
dynamic data: support for {propertyName} resources
exyi Feb 20, 2022
f9de77c
Renamed Id to Value in SelectorItem
tomasherceg Feb 20, 2022
b5de449
DynamicEntity: Support editor template
exyi Feb 20, 2022
c7d97ca
Add support for field template
exyi Feb 20, 2022
302139a
Multi-selection provider with CheckBoxes added
tomasherceg Feb 27, 2022
f064127
DynamicColumns: support advanced customization fields
exyi Feb 20, 2022
15efedd
Add BulmaDynamicEntity
exyi Feb 26, 2022
2969344
dynamic data: use in-style precompilation, fix and test bulma styles
exyi Mar 3, 2022
7f8e761
dynamic data: localization of enum members
exyi Mar 4, 2022
d35cf6a
dynamic data: support for Property-X={value: Override}
exyi Mar 4, 2022
3aebaf2
dynamic data: support for Visible-X, auto hide selectors with empty d…
exyi Mar 4, 2022
fc079dd
Renamed test output files
tomasherceg May 18, 2022
96f4ce3
Renamed Dynamic Data to AutoUI
tomasherceg May 18, 2022
666847c
AutoUI moved to different folder structure
tomasherceg May 18, 2022
87d0678
Old version of DynamicData added back
tomasherceg May 18, 2022
6a3e181
autoui: invisible fields are not included in the page
exyi Jun 6, 2022
53529d4
Slnf file updated
tomasherceg May 18, 2022
94fecc4
SelectorItem and related classes renamed
tomasherceg May 20, 2022
57797e7
Added support for primary names and alternative names for controls
tomasherceg May 20, 2022
938c1f3
Auto UI control renamed, tag prefixes and tag names updated
exyi Jun 6, 2022
283af03
Fixed renaming of SelectorViewModel
tomasherceg May 20, 2022
b0e2f2d
ViewName and GroupName properties are applied on the server without r…
tomasherceg May 20, 2022
ece24b4
UIHint attribute support
tomasherceg May 22, 2022
9586468
Renamed SelectorAttribute to SelectionAttribute and fixed tests
tomasherceg May 22, 2022
159857b
Configurable CSS classes of auto Bulma/BS forms
tomasherceg May 22, 2022
e6dbfec
autoUI: Remove the dummy grid column
exyi Jun 4, 2022
a863283
Rename dynamicdata-* css classes to autoui-
exyi Jun 4, 2022
00b626d
autoui: remove some unused code, test enum property
exyi Jun 4, 2022
1251775
Selections test added
tomasherceg Jun 4, 2022
86d76fe
Tests for Bulma and Bootstrap forms
tomasherceg Jun 4, 2022
fe50fb6
Localization of fields and validation messages covered with tests
tomasherceg Jun 4, 2022
44780f7
UI Tests for AutoUI components
tomasherceg Jun 4, 2022
52882ca
Updated OWIN project so it can be run from Visual Studio
tomasherceg Jun 8, 2022
078eda9
autoui: rewritten the README file
exyi Aug 5, 2022
db4cd75
autoui: pre-compiled expression in LocalizableString
exyi Aug 5, 2022
e13fe30
autoui: make regexes CultureInvariant
exyi Aug 5, 2022
160b9ca
fixup! Selections test added
exyi Aug 5, 2022
00abd5b
fixup! UI Tests for AutoUI components
exyi Aug 5, 2022
dbeba19
autoui: remove dynamic data from docs and comments
exyi Aug 5, 2022
f4a5049
fixup! autoui: rewritten the README file
exyi Aug 5, 2022
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
2 changes: 2 additions & 0 deletions ci/scripts/CopyBetweenNugetFeeds.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ $packages = @(
[pscustomobject]@{ Package = "DotVVM.HotReload.Owin"; Directory = "Tools/HotReload/Owin"; Type = "standard" },
[pscustomobject]@{ Package = "DotVVM.DynamicData"; Directory = "DynamicData/DynamicData"; Type = "standard" },
[pscustomobject]@{ Package = "DotVVM.DynamicData.Annotations"; Directory = "DynamicData/Annotations"; Type = "standard" },
[pscustomobject]@{ Package = "DotVVM.AutoUI"; Directory = "AutoUI/Core"; Type = "standard" },
[pscustomobject]@{ Package = "DotVVM.AutoUI.Annotations"; Directory = "AutoUI/Annotations"; Type = "standard" },
[pscustomobject]@{ Package = "DotVVM.Tracing.ApplicationInsights"; Directory = "Tracing/ApplicationInsights"; Type = "standard" },
[pscustomobject]@{ Package = "DotVVM.Tracing.ApplicationInsights.AspNetCore"; Directory = "Tracing/ApplicationInsights.AspNetCore"; Type = "standard" },
[pscustomobject]@{ Package = "DotVVM.Tracing.ApplicationInsights.Owin"; Directory = "Tracing/ApplicationInsights.Owin"; Type = "standard" }
Expand Down
2 changes: 2 additions & 0 deletions ci/scripts/publish.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ $packages = @(
[pscustomobject]@{ Package = "DotVVM.Testing"; Directory = "Framework/Testing" },
[pscustomobject]@{ Package = "DotVVM.DynamicData"; Directory = "DynamicData/DynamicData" },
[pscustomobject]@{ Package = "DotVVM.DynamicData.Annotations"; Directory = "DynamicData/Annotations" },
[pscustomobject]@{ Package = "DotVVM.AutoUI"; Directory = "AutoUI/Core" },
[pscustomobject]@{ Package = "DotVVM.AutoUI.Annotations"; Directory = "AutoUI/Annotations" },
[pscustomobject]@{ Package = "DotVVM.Tracing.ApplicationInsights"; Directory = "Tracing/ApplicationInsights" },
[pscustomobject]@{ Package = "DotVVM.Tracing.ApplicationInsights.AspNetCore"; Directory = "Tracing/ApplicationInsights.AspNetCore" },
[pscustomobject]@{ Package = "DotVVM.Tracing.ApplicationInsights.Owin"; Directory = "Tracing/ApplicationInsights.Owin" }
Expand Down
8 changes: 8 additions & 0 deletions src/AutoUI/Annotations/AuthenticationMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DotVVM.AutoUI.Annotations;

public enum AuthenticationMode
{
Any = 0,
Authenticated = 1,
NonAuthenticated = 2
}
33 changes: 33 additions & 0 deletions src/AutoUI/Annotations/ComboBoxSettingsAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;

namespace DotVVM.AutoUI.Annotations
{
/// <summary>
/// Defines the settings for the ComboBox form editor provider.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ComboBoxSettingsAttribute : Attribute
{

/// <summary>
/// Gets or sets the name of the property to be displayed.
/// </summary>
public string DisplayMember { get; set; }

/// <summary>
/// Gets or sets the name of the property to be used as selected value.
/// </summary>
public string ValueMember { get; set; }

/// <summary>
/// Gets or sets the binding expression for the list of items.
/// </summary>
public string DataSourceBinding { get; set; }

/// <summary>
/// Gets or sets the text on the empty item. If null or empty, the empty item will not be included.
/// </summary>
public string EmptyItemText { get; set; }

}
}
24 changes: 24 additions & 0 deletions src/AutoUI/Annotations/DotVVM.AutoUI.Annotations.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(DefaultTargetFrameworks)</TargetFrameworks>
<AssemblyOriginatorKeyFile>dotvvmwizard.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>DotVVM.AutoUI.Annotations</PackageId>
<Description>Annotation attributes for DotVVM AutoUI.</Description>
<PackageProjectUrl>https://www.dotvvm.com/docs/3.0/pages/community-add-ons/dotvvm-dynamic-data</PackageProjectUrl>
<PackageTags>($PackageTags);autoui;annotations;metadata;ui generation</PackageTags>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.ComponentModel.DataAnnotations" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Framework\Core\DotVVM.Core.csproj" />
</ItemGroup>
</Project>
37 changes: 37 additions & 0 deletions src/AutoUI/Annotations/EnabledAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;

namespace DotVVM.AutoUI.Annotations;

/// <summary>
/// Indicates under which conditions the auto-generated field should be enable (i.e. editable) to the user.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class EnabledAttribute : Attribute, IConditionalFieldAttribute
{

/// <summary>
/// Gets or sets a name of the view or an expression that specifies for which views the field should be editable.
/// You can use ! (NOT), &amp; (AND) and | (OR) operators.
/// Examples:
/// - Insert // editable only in the Insert view
/// - Insert | Edit // editable in Insert or Edit views
/// - !Insert &amp; !Edit // editable in all views except for Insert and Edit
/// </summary>
public string ViewNames { get; set; }

/// <summary>
/// Gets or sets a name of the role or an expression that specifies for which roles the field should be editable.
/// You can use ! (NOT), &amp; (AND) and | (OR) operators.
/// Examples:
/// - Admin // editable only for the Admin role
/// - Admin | Contributor // editable for Admin or Contributor roles
/// - !Admin &amp; !Contributor // editable for all roles except for Admin or Contributor roles
/// </summary>
public string Roles { get; set; }

/// <summary>
/// Gets or sets whether the field should be editable for authenticated or non-authenticated users, or null for both kinds (default behavior).
/// </summary>
public AuthenticationMode IsAuthenticated { get; set; }

}
8 changes: 8 additions & 0 deletions src/AutoUI/Annotations/IConditionalFieldAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DotVVM.AutoUI.Annotations;

public interface IConditionalFieldAttribute
{
string ViewNames { get; set; }
string Roles { get; set; }
AuthenticationMode IsAuthenticated { get; set; }
}
17 changes: 17 additions & 0 deletions src/AutoUI/Annotations/ISelectionProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using DotVVM.Framework.ViewModel;

namespace DotVVM.AutoUI.Annotations;

public interface ISelectionProvider<TItem>
{
[AllowStaticCommand]
Task<List<TItem>> GetSelectorItems();
}

public interface ISelectionProvider<TItem, TParam>
{
[AllowStaticCommand]
Task<List<TItem>> GetSelectorItems(TParam parameter);
}
20 changes: 20 additions & 0 deletions src/AutoUI/Annotations/IViewContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace DotVVM.AutoUI.Annotations
{
/// <summary>
/// Provides information about the context in which the field is being rendered.
/// </summary>
public interface IViewContext
{

/// <summary>
/// Gets the name of the current view.
/// </summary>
string ViewName { get; }

/// <summary>
/// Gets the name of the current field group.
/// </summary>
string GroupName { get; }

}
}
15 changes: 15 additions & 0 deletions src/AutoUI/Annotations/Selection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace DotVVM.AutoUI.Annotations;

public abstract record Selection
{
public string DisplayName { get; set; }

private protected abstract void SorryWeCannotAllowYouToInheritThisClass();
}

public abstract record Selection<TKey> : Selection
{
public TKey Value { get; set; }

private protected override void SorryWeCannotAllowYouToInheritThisClass() => throw new System.NotImplementedException("Mischief managed.");
}
14 changes: 14 additions & 0 deletions src/AutoUI/Annotations/SelectionAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace DotVVM.AutoUI.Annotations;

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class SelectionAttribute : System.Attribute
{
public Type PropertyType { get; }

public SelectionAttribute(Type propertyType)
{
PropertyType = propertyType;
}
}
38 changes: 38 additions & 0 deletions src/AutoUI/Annotations/StyleAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;

namespace DotVVM.AutoUI.Annotations
{
/// <summary>
/// Defines the CSS classes applied to the field.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class StyleAttribute : Attribute
{

/// <summary>
/// Gets or sets the CSS class applied to the container of the form control (e.g. table cell which contains the TextBox control) for this field.
/// </summary>
public string FormControlContainerCssClass { get; set; }

/// <summary>
/// Gets or sets the CSS class applied to the row in the form (e.g. table row which contains the label and the TextBox control) for this field.
/// </summary>
public string FormRowCssClass { get; set; }

/// <summary>
/// Gets or sets the CSS class applied to the control in the form.
/// </summary>
public string FormControlCssClass { get; set; }

/// <summary>
/// Gets or sets the CSS class applied to the GridView table cell for this field.
/// </summary>
public string GridCellCssClass { get; set; }

/// <summary>
/// Gets or sets the CSS class applied to the GridView table header cell for this field.
/// </summary>
public string GridHeaderCellCssClass { get; set; }

}
}
37 changes: 37 additions & 0 deletions src/AutoUI/Annotations/VisibleAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;

namespace DotVVM.AutoUI.Annotations;

/// <summary>
/// Indicates under which conditions the auto-generated field should be visible to the user.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class VisibleAttribute : Attribute, IConditionalFieldAttribute
{

/// <summary>
/// Gets or sets a name of the view or an expression that specifies for which views the field should be visible.
/// You can use ! (NOT), &amp; (AND) and | (OR) operators.
/// Examples:
/// - Insert // visible only in the Insert view
/// - Insert | Edit // visible in Insert or Edit views
/// - !Insert &amp; !Edit // visible in all views except for Insert and Edit
/// </summary>
public string ViewNames { get; set; }

/// <summary>
/// Gets or sets a name of the role or an expression that specifies for which roles the field should be visible.
/// You can use ! (NOT), &amp; (AND) and | (OR) operators.
/// Examples:
/// - Admin // visible only for the Admin role
/// - Admin | Contributor // visible for Admin or Contributor roles
/// - !Admin &amp; !Contributor // visible for all roles except for Admin or Contributor roles
/// </summary>
public string Roles { get; set; }

/// <summary>
/// Gets or sets whether the field should be visible for authenticated or non-authenticated users, or null for both kinds (default behavior).
/// </summary>
public AuthenticationMode IsAuthenticated { get; set; }

}
Binary file added src/AutoUI/Annotations/dotvvmwizard.snk
Binary file not shown.
91 changes: 91 additions & 0 deletions src/AutoUI/Core/AutoUIContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using DotVVM.AutoUI.Annotations;
using DotVVM.AutoUI.Configuration;
using DotVVM.AutoUI.Metadata;
using DotVVM.Framework.Binding;
using DotVVM.Framework.Binding.Expressions;
using DotVVM.Framework.Binding.Properties;
using DotVVM.Framework.Compilation.ControlTree;
using DotVVM.Framework.ViewModel.Validation;
using Microsoft.Extensions.DependencyInjection;

namespace DotVVM.AutoUI
{
public class AutoUIContext
{
public DataContextStack DataContextStack { get; }
public IServiceProvider Services { get; }

public IViewModelValidationMetadataProvider ValidationMetadataProvider { get; }

public IPropertyDisplayMetadataProvider PropertyDisplayMetadataProvider { get; }
public AutoUIConfiguration AutoUiConfiguration { get; }

public Type EntityType => DataContextStack.DataContextType;

public string? ViewName { get; set; }

public string? GroupName { get; set; }

public BindingCompilationService BindingService { get; }

public AutoUIContext(DataContextStack dataContextStack, IServiceProvider services)
{
DataContextStack = dataContextStack;
Services = services;

ValidationMetadataProvider = services.GetRequiredService<IViewModelValidationMetadataProvider>();
PropertyDisplayMetadataProvider = services.GetRequiredService<IPropertyDisplayMetadataProvider>();
AutoUiConfiguration = services.GetRequiredService<AutoUIConfiguration>();
BindingService = services.GetRequiredService<BindingCompilationService>();
}

public IValueBinding CreateValueBinding(PropertyDisplayMetadata property)
{
if (property.ValueBinding is not null)
return property.ValueBinding;

if (property.PropertyInfo is null)
throw new ArgumentException("property.PropertyInfo is null => cannot create value binding for this property");

var s = this.BindingService;
return s.Cache.CreateCachedBinding("AutoUI-Value", new object?[] { property.PropertyInfo, DataContextStack }, () => {
var _this = Expression.Parameter(DataContextStack.DataContextType, "_this").AddParameterAnnotation(new BindingParameterAnnotation(DataContextStack));
var expr = Expression.Property(_this, property.PropertyInfo);
return (IValueBinding)BindingService.CreateBinding(typeof(ValueBindingExpression<>), new object[] {
DataContextStack,
new ParsedExpressionBindingProperty(expr)
});
});
}

public IValueBinding CreateValueBinding(string expression, params Type[] nestedDataContextTypes)
{
var dataContextStack = CreateDataContextStack(DataContextStack, nestedDataContextTypes);

return BindingService.Cache.CreateValueBinding(expression, dataContextStack);
}

private DataContextStack CreateDataContextStack(DataContextStack dataContextStack, Type[] nestedDataContextTypes)
{
foreach (var type in nestedDataContextTypes)
{
dataContextStack = DataContextStack.Create(type, dataContextStack, dataContextStack.NamespaceImports, dataContextStack.ExtensionParameters);
}
return dataContextStack;
}

public IViewContext CreateViewContext()
{
return new ViewContext()
{
ViewName = ViewName,
GroupName = GroupName
};
}
}
}
Loading