start working on security group view

This commit is contained in:
Holger Börchers 2020-08-21 22:23:30 +02:00
parent 8fcd1c4c44
commit 6d975599a3
15 changed files with 243 additions and 110 deletions

View File

@ -17,7 +17,7 @@ namespace UserService.DatabaseLayer.DataModels
var arizona = new OrganizationUnit{CommonName = "Arizona" , Id = -4, ParentId = -5 }; var arizona = new OrganizationUnit{CommonName = "Arizona" , Id = -4, ParentId = -5 };
var france = new OrganizationUnit{CommonName = "France" , Id = -3, ParentId = -2 }; var france = new OrganizationUnit{CommonName = "France" , Id = -3, ParentId = -2 };
modelBuilder.Entity<OrganizationUnit>().HasData(users, groups, germany, usa, arizona, france); modelBuilder.Entity<OrganizationUnit>().HasData(users, groups, germany, usa, arizona, france);
var user = new User { CommonName = "holger", IsActive = true, Id = -7, ParentId = germany.Id }; var user = new User { CommonName = Environment.UserName, IsActive = true, Id = -7, ParentId = users.Id };
modelBuilder.Entity<User>().HasData(user); modelBuilder.Entity<User>().HasData(user);
var secGroup = new SecurityGroup { CommonName = "Global Admin", Id = -8, ParentId = groups.Id }; var secGroup = new SecurityGroup { CommonName = "Global Admin", Id = -8, ParentId = groups.Id };
modelBuilder.Entity<SecurityGroup>().HasData(secGroup); modelBuilder.Entity<SecurityGroup>().HasData(secGroup);
@ -39,7 +39,6 @@ namespace UserService.DatabaseLayer.DataModels
.HasOne(bc => bc.Member) .HasOne(bc => bc.Member)
.WithMany(c => c!.Members) .WithMany(c => c!.Members)
.HasForeignKey(bc => bc.MemberId); .HasForeignKey(bc => bc.MemberId);
modelBuilder.Entity<Node>() modelBuilder.Entity<Node>()
.HasMany(c => c.Children) .HasMany(c => c.Children)
.WithOne(e => e.Parent!) .WithOne(e => e.Parent!)

View File

@ -9,16 +9,16 @@ using UserService.DatabaseLayer.DataModels;
namespace UserService.DatabaseLayer.Migrations namespace UserService.DatabaseLayer.Migrations
{ {
[DbContext(typeof(UserServiceDbContext))] [DbContext(typeof(UserServiceDbContext))]
[Migration("20200725195658_initial")] [Migration("20200821193933_InitialCreate")]
partial class initial partial class InitialCreate
{ {
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "3.1.6"); .HasAnnotation("ProductVersion", "3.1.7");
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.Node", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.Node", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@ -47,7 +47,7 @@ namespace UserService.DatabaseLayer.Migrations
b.HasDiscriminator<string>("Discriminator").HasValue("Node"); b.HasDiscriminator<string>("Discriminator").HasValue("Node");
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.UserMember", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.UserMember", b =>
{ {
b.Property<int>("MemberId") b.Property<int>("MemberId")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@ -69,9 +69,9 @@ namespace UserService.DatabaseLayer.Migrations
}); });
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.Member", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.Member", b =>
{ {
b.HasBaseType("UserService.DatabaseLayer.DataModels.Node"); b.HasBaseType("UserService.Infrastructure.DataModels.Node");
b.Property<string>("EMail") b.Property<string>("EMail")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
@ -79,9 +79,9 @@ namespace UserService.DatabaseLayer.Migrations
b.HasDiscriminator().HasValue("Member"); b.HasDiscriminator().HasValue("Member");
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.OrganizationUnit", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.OrganizationUnit", b =>
{ {
b.HasBaseType("UserService.DatabaseLayer.DataModels.Node"); b.HasBaseType("UserService.Infrastructure.DataModels.Node");
b.Property<int?>("ManagerId") b.Property<int?>("ManagerId")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@ -127,9 +127,9 @@ namespace UserService.DatabaseLayer.Migrations
}); });
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.SecurityGroup", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.SecurityGroup", b =>
{ {
b.HasBaseType("UserService.DatabaseLayer.DataModels.Member"); b.HasBaseType("UserService.Infrastructure.DataModels.Member");
b.HasDiscriminator().HasValue("SecurityGroup"); b.HasDiscriminator().HasValue("SecurityGroup");
@ -142,9 +142,9 @@ namespace UserService.DatabaseLayer.Migrations
}); });
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.User", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.User", b =>
{ {
b.HasBaseType("UserService.DatabaseLayer.DataModels.Member"); b.HasBaseType("UserService.Infrastructure.DataModels.Member");
b.Property<string>("FirstName") b.Property<string>("FirstName")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
@ -162,36 +162,36 @@ namespace UserService.DatabaseLayer.Migrations
{ {
Id = -7, Id = -7,
CommonName = "holger", CommonName = "holger",
ParentId = -6, ParentId = -2,
IsActive = true IsActive = true
}); });
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.Node", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.Node", b =>
{ {
b.HasOne("UserService.DatabaseLayer.DataModels.Node", "Parent") b.HasOne("UserService.Infrastructure.DataModels.Node", "Parent")
.WithMany("Children") .WithMany("Children")
.HasForeignKey("ParentId"); .HasForeignKey("ParentId");
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.UserMember", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.UserMember", b =>
{ {
b.HasOne("UserService.DatabaseLayer.DataModels.Member", "Member") b.HasOne("UserService.Infrastructure.DataModels.Member", "Member")
.WithMany("Members") .WithMany("Members")
.HasForeignKey("MemberId") .HasForeignKey("MemberId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("UserService.DatabaseLayer.DataModels.User", "User") b.HasOne("UserService.Infrastructure.DataModels.User", "User")
.WithMany("MemberOf") .WithMany("MemberOf")
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.OrganizationUnit", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.OrganizationUnit", b =>
{ {
b.HasOne("UserService.DatabaseLayer.DataModels.Member", "Manager") b.HasOne("UserService.Infrastructure.DataModels.Member", "Manager")
.WithMany() .WithMany()
.HasForeignKey("ManagerId"); .HasForeignKey("ManagerId");
}); });

View File

@ -2,7 +2,7 @@
namespace UserService.DatabaseLayer.Migrations namespace UserService.DatabaseLayer.Migrations
{ {
public partial class initial : Migration public partial class InitialCreate : Migration
{ {
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
@ -90,13 +90,13 @@ namespace UserService.DatabaseLayer.Migrations
migrationBuilder.InsertData( migrationBuilder.InsertData(
table: "Node", table: "Node",
columns: new[] { "Id", "CommonName", "Description", "Discriminator", "ParentId", "EMail" }, columns: new[] { "Id", "CommonName", "Description", "Discriminator", "ParentId", "EMail", "FirstName", "IsActive", "LastName" },
values: new object[] { -8, "Global Admin", null, "SecurityGroup", -1, null }); values: new object[] { -7, "holger", null, "User", -2, null, null, true, null });
migrationBuilder.InsertData( migrationBuilder.InsertData(
table: "Node", table: "Node",
columns: new[] { "Id", "CommonName", "Description", "Discriminator", "ParentId", "EMail", "FirstName", "IsActive", "LastName" }, columns: new[] { "Id", "CommonName", "Description", "Discriminator", "ParentId", "EMail" },
values: new object[] { -7, "holger", null, "User", -6, null, null, true, null }); values: new object[] { -8, "Global Admin", null, "SecurityGroup", -1, null });
migrationBuilder.InsertData( migrationBuilder.InsertData(
table: "Node", table: "Node",

View File

@ -1,7 +1,8 @@
// <auto-generated /> // <auto-generated />
using System;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using UserService.DatabaseLayer.DataModels; using UserService.DatabaseLayer.DataModels;
namespace UserService.DatabaseLayer.Migrations namespace UserService.DatabaseLayer.Migrations
@ -13,9 +14,9 @@ namespace UserService.DatabaseLayer.Migrations
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "3.1.6"); .HasAnnotation("ProductVersion", "3.1.7");
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.Node", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.Node", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@ -44,7 +45,7 @@ namespace UserService.DatabaseLayer.Migrations
b.HasDiscriminator<string>("Discriminator").HasValue("Node"); b.HasDiscriminator<string>("Discriminator").HasValue("Node");
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.UserMember", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.UserMember", b =>
{ {
b.Property<int>("MemberId") b.Property<int>("MemberId")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@ -66,9 +67,9 @@ namespace UserService.DatabaseLayer.Migrations
}); });
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.Member", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.Member", b =>
{ {
b.HasBaseType("UserService.DatabaseLayer.DataModels.Node"); b.HasBaseType("UserService.Infrastructure.DataModels.Node");
b.Property<string>("EMail") b.Property<string>("EMail")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
@ -76,9 +77,9 @@ namespace UserService.DatabaseLayer.Migrations
b.HasDiscriminator().HasValue("Member"); b.HasDiscriminator().HasValue("Member");
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.OrganizationUnit", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.OrganizationUnit", b =>
{ {
b.HasBaseType("UserService.DatabaseLayer.DataModels.Node"); b.HasBaseType("UserService.Infrastructure.DataModels.Node");
b.Property<int?>("ManagerId") b.Property<int?>("ManagerId")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@ -124,9 +125,9 @@ namespace UserService.DatabaseLayer.Migrations
}); });
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.SecurityGroup", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.SecurityGroup", b =>
{ {
b.HasBaseType("UserService.DatabaseLayer.DataModels.Member"); b.HasBaseType("UserService.Infrastructure.DataModels.Member");
b.HasDiscriminator().HasValue("SecurityGroup"); b.HasDiscriminator().HasValue("SecurityGroup");
@ -139,9 +140,9 @@ namespace UserService.DatabaseLayer.Migrations
}); });
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.User", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.User", b =>
{ {
b.HasBaseType("UserService.DatabaseLayer.DataModels.Member"); b.HasBaseType("UserService.Infrastructure.DataModels.Member");
b.Property<string>("FirstName") b.Property<string>("FirstName")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
@ -159,36 +160,36 @@ namespace UserService.DatabaseLayer.Migrations
{ {
Id = -7, Id = -7,
CommonName = "holger", CommonName = "holger",
ParentId = -6, ParentId = -2,
IsActive = true IsActive = true
}); });
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.Node", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.Node", b =>
{ {
b.HasOne("UserService.DatabaseLayer.DataModels.Node", "Parent") b.HasOne("UserService.Infrastructure.DataModels.Node", "Parent")
.WithMany("Children") .WithMany("Children")
.HasForeignKey("ParentId"); .HasForeignKey("ParentId");
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.UserMember", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.UserMember", b =>
{ {
b.HasOne("UserService.DatabaseLayer.DataModels.Member", "Member") b.HasOne("UserService.Infrastructure.DataModels.Member", "Member")
.WithMany("Members") .WithMany("Members")
.HasForeignKey("MemberId") .HasForeignKey("MemberId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("UserService.DatabaseLayer.DataModels.User", "User") b.HasOne("UserService.Infrastructure.DataModels.User", "User")
.WithMany("MemberOf") .WithMany("MemberOf")
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("UserService.DatabaseLayer.DataModels.OrganizationUnit", b => modelBuilder.Entity("UserService.Infrastructure.DataModels.OrganizationUnit", b =>
{ {
b.HasOne("UserService.DatabaseLayer.DataModels.Member", "Manager") b.HasOne("UserService.Infrastructure.DataModels.Member", "Manager")
.WithMany() .WithMany()
.HasForeignKey("ManagerId"); .HasForeignKey("ManagerId");
}); });

View File

@ -5,9 +5,6 @@ namespace UserService.Infrastructure.DataModels
{ {
public abstract class Member : Node public abstract class Member : Node
{ {
[EmailAddress]
public string? EMail { get; set; }
public ICollection<UserMember> Members { get; set; } = new List<UserMember>(); public ICollection<UserMember> Members { get; set; } = new List<UserMember>();
} }
} }

View File

@ -1,4 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace UserService.Infrastructure.DataModels namespace UserService.Infrastructure.DataModels
{ {
@ -8,6 +10,9 @@ namespace UserService.Infrastructure.DataModels
public string? LastName { get; set; } public string? LastName { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
[EmailAddress]
public string? EMail { get; set; }
public string FullName => $"{FirstName} {LastName}"; public string FullName => $"{FirstName} {LastName}";
public IEnumerable<UserMember> MemberOf { get; set; } = new List<UserMember>(); public IEnumerable<UserMember> MemberOf { get; set; } = new List<UserMember>();

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UserService.Infrastructure.DataModels;
namespace UserService.Infrastructure
{
public static class NodeExtensions
{
public static void MapFields(this User user, Dictionary<string, object> values)
{
if (user == null) throw new ArgumentNullException(nameof(user));
if (values == null) throw new ArgumentNullException(nameof(values));
var properties = user.GetType().GetProperties();
foreach (var keyValuePair in values)
{
var propertyInfo = properties.FirstOrDefault(x => x.Name == keyValuePair.Key);
if (propertyInfo == null) continue;
propertyInfo.SetValue(user, keyValuePair.Value);
}
}
}
}

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -7,13 +7,13 @@ namespace UserService.Infrastructure
{ {
public static class Validators public static class Validators
{ {
public static bool? ValidateEmail(string mailAddress) public static bool? ValidateEmail(string? mailAddress)
{ {
if (string.IsNullOrEmpty(mailAddress)) return null; if (string.IsNullOrEmpty(mailAddress)) return null;
return new EmailAddressAttribute().IsValid(mailAddress); return new EmailAddressAttribute().IsValid(mailAddress);
} }
public static bool? ValidateCommonName(string commonName, IReadOnlyList<User> users) public static bool? ValidateCommonName(string? commonName, IEnumerable<Member> users)
{ {
if (string.IsNullOrEmpty(commonName)) return false; if (string.IsNullOrEmpty(commonName)) return false;
return users.All(x => x.CommonName != commonName); return users.All(x => x.CommonName != commonName);

Binary file not shown.

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Blazorise;
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components;
using UserService.Infrastructure;
using UserService.Infrastructure.DataModels;
namespace UserService.Pages
{
public abstract class MembersBase<T> : ComponentBase where T : Member
{
protected IReadOnlyList<OrganizationUnit>? OrganizationUnits { get; set; }
protected IReadOnlyList<T>? Members { get; set; }
protected string? CustomFilterValue { get; set; }
protected abstract Task RowInsertingCallback(CancellableRowChange<T, Dictionary<string, object>> arg);
protected abstract Task RowInsertedCallback(SavedRowItem<T, Dictionary<string, object>> arg);
protected abstract Task RowDeletingCallback(CancellableRowChange<T> arg);
protected abstract Task RowUpdatingCallback(CancellableRowChange<T, Dictionary<string, object>> arg);
protected abstract bool OnCustomFilter(T model);
protected void ValidateCommonName(ValidatorEventArgs e)
{
if (e == null) throw new ArgumentNullException(nameof(e));
var commonName = e.Value?.ToString();
var validationResult = Validators.ValidateCommonName(commonName, Members ?? Enumerable.Empty<Member>());
e.Status = validationResult == false ? ValidationStatus.Error : ValidationStatus.Success;
}
}
}

View File

@ -4,7 +4,7 @@
<h1>Table of all security groups</h1> <h1>Table of all security groups</h1>
@if (Groups is null) @if (Members is null)
{ {
<p> <p>
<em>Loading...</em> <em>Loading...</em>
@ -12,10 +12,76 @@
} }
else else
{ {
<DataGrid TItem="SecurityGroup" Data="@Groups"> <TextEdit Placeholder="Search" Size="Size.Large" @bind-Text="@CustomFilterValue" />
<DataGridCommandColumn TItem="User" />
<DataGrid
TItem="SecurityGroup"
RowSelectable="@(u => false)"
CustomFilter="@OnCustomFilter"
Sortable="true"
Editable="true"
EditMode="DataGridEditMode.Inline"
RowRemoving="RowDeletingCallback"
Data="@Members"
RowInserted="RowInsertedCallback"
RowInserting="RowInsertingCallback"
RowUpdating="RowUpdatingCallback">
<DataGridCommandColumn TItem="SecurityGroup">
<NewCommandTemplate>
<Button Color="Color.Success" Clicked="@context.Clicked" title="Create security group">
<i class="fas fa-users"></i>
</Button>
</NewCommandTemplate>
<EditCommandTemplate>
<Button Color="Color.Primary" Clicked="@context.Clicked" title="Edit security group">
<i class="fa fa-user-edit"></i>
</Button>
</EditCommandTemplate>
<DeleteCommandTemplate>
<Button Color="Color.Danger" Clicked="@context.Clicked" title="Delete security group">
<i class="fa fa-user-minus"></i>
</Button>
</DeleteCommandTemplate>
<SaveCommandTemplate>
<Button Color="Color.Success" Clicked="@context.Clicked" title="Save security group">
<i class="fas fa-save"></i>
</Button>
</SaveCommandTemplate>
<CancelCommandTemplate>
<Button Color="Color.Danger" Clicked="@context.Clicked" title="Cancel editing">
<i class="far fa-times-circle"></i>
</Button>
</CancelCommandTemplate>
</DataGridCommandColumn>
<DataGridColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.Id)" Caption="#" Sortable="false" /> <DataGridColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.Id)" Caption="#" Sortable="false" />
<DataGridColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.CommonName)" Caption="CN" Editable="true" />
<DataGridColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.EMail)" Caption="EMail" Editable="true" /> <DataGridColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.CommonName)" Caption="CN" CellsEditableOnEditCommand="false" Editable="true">
</DataGrid> <EditTemplate>
<Validation Validator="@ValidateCommonName">
<TextEdit Placeholder="Enter common name" Text="@((string)(((CellEditContext)context).CellValue))" TextChanged="@(v=>((CellEditContext)context).CellValue=v)">
<Feedback>
<ValidationSuccess></ValidationSuccess>
<ValidationError>Please enter a valid common name!</ValidationError>
</Feedback>
</TextEdit>
</Validation>
</EditTemplate>
</DataGridColumn>
<DataGridSelectColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.ParentId)" Caption="Parent" Editable="true">
<DisplayTemplate>
@{
var name = ((SecurityGroup) context ).Parent?.CommonName ?? "-";
@name
}
</DisplayTemplate>
<EditTemplate>
<Select TValue="int?" SelectedValue="@((int?)(context.CellValue))" SelectedValueChanged="@(v => context.CellValue = v)" >
@foreach (var item in OrganizationUnits ?? Enumerable.Empty<OrganizationUnit>())
{
<SelectItem TValue="int" Value="@(item.Id)">@item.CommonName</SelectItem>
}
</Select>
</EditTemplate>
</DataGridSelectColumn>
</DataGrid>
} }

View File

@ -1,47 +1,49 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using UserService.DatabaseLayer.Repository; using UserService.DatabaseLayer.Repository;
using UserService.Infrastructure.DataModels; using UserService.Infrastructure.DataModels;
namespace UserService.Pages namespace UserService.Pages
{ {
public class SecurityGroupsBase : ComponentBase public class SecurityGroupsBase : MembersBase<SecurityGroup>
{ {
[Inject] private ISecurityGroupsRepository SecurityGroupsRepository { get; set; } = null!; [Inject] private ISecurityGroupsRepository SecurityGroupsRepository { get; set; } = null!;
[Inject] private IOrganizationUnitsRepository OrganizationUnitsRepository { get; set; } = null!; [Inject] private IOrganizationUnitsRepository OrganizationUnitsRepository { get; set; } = null!;
protected bool DialogIsOpen { get; set; }
protected SecurityGroup? SecurityGroupToEdit { get; set; }
protected IReadOnlyList<SecurityGroup>? Groups { get; set; }
protected IReadOnlyList<OrganizationUnit>? OrganizationUnits { get; set; }
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
Groups = await SecurityGroupsRepository.GetAllAsync().ConfigureAwait(false); Members = await SecurityGroupsRepository.GetAllAsync().ConfigureAwait(false);
OrganizationUnits = await OrganizationUnitsRepository.GetAllAsync().ConfigureAwait(false); OrganizationUnits = await OrganizationUnitsRepository.GetAllAsync().ConfigureAwait(false);
} }
protected void EditSecurityGroup(SecurityGroup securityGroup) /// <inheritdoc />
protected override async Task RowInsertingCallback(CancellableRowChange<SecurityGroup, Dictionary<string, object>> arg)
{ {
SecurityGroupToEdit = securityGroup;
DialogIsOpen = true;
} }
protected async Task OkClick() /// <inheritdoc />
protected override async Task RowInsertedCallback(SavedRowItem<SecurityGroup, Dictionary<string, object>> arg)
{ {
if (!(SecurityGroupToEdit is null))
{
await SecurityGroupsRepository.UpdateAsync(SecurityGroupToEdit).ConfigureAwait(false);
} }
DialogIsOpen = false; /// <inheritdoc />
protected override async Task RowDeletingCallback(CancellableRowChange<SecurityGroup> arg)
{
} }
protected async Task DeleteSecurityGroup(SecurityGroup securityGroup) /// <inheritdoc />
protected override async Task RowUpdatingCallback(CancellableRowChange<SecurityGroup, Dictionary<string, object>> arg)
{ {
await SecurityGroupsRepository.DeleteAsync(securityGroup).ConfigureAwait(false); }
/// <inheritdoc />
protected override bool OnCustomFilter(SecurityGroup model)
{
return true;
} }
} }
} }

View File

@ -4,7 +4,7 @@
<h1>List of all users</h1> <h1>List of all users</h1>
@if (Users == null) @if (Members == null)
{ {
<p> <p>
<em>Loading...</em> <em>Loading...</em>
@ -14,7 +14,18 @@ else
{ {
<TextEdit Placeholder="Search" Size="Size.Large" @bind-Text="@CustomFilterValue" /> <TextEdit Placeholder="Search" Size="Size.Large" @bind-Text="@CustomFilterValue" />
<DataGrid TItem="User" RowSelectable="@(u => false)" CustomFilter="@OnCustomFilter" Sortable="true" Editable="true" EditMode="DataGridEditMode.Popup" RowRemoving="RowDeletingCallback" Data="@Users" RowInserted="RowInsertedCallback" RowInserting="RowInsertingCallback" RowUpdating="RowUpdatingCallback"> <DataGrid
TItem="User"
RowSelectable="@(u => false)"
CustomFilter="@OnCustomFilter"
Sortable="true"
Editable="true"
EditMode="DataGridEditMode.Inline"
RowRemoving="RowDeletingCallback"
Data="@Members"
RowInserted="RowInsertedCallback"
RowInserting="RowInsertingCallback"
RowUpdating="RowUpdatingCallback">
<DataGridCommandColumn TItem="User"> <DataGridCommandColumn TItem="User">
<NewCommandTemplate> <NewCommandTemplate>
<Button Color="Color.Success" Clicked="@context.Clicked" title="Create user"> <Button Color="Color.Success" Clicked="@context.Clicked" title="Create user">
@ -77,11 +88,10 @@ else
var name = ((User) context ).Parent?.CommonName ?? "-"; var name = ((User) context ).Parent?.CommonName ?? "-";
@name @name
} }
</DisplayTemplate> </DisplayTemplate>
<EditTemplate> <EditTemplate>
<Select TValue="int?" SelectedValue="@((int?)(context.CellValue))" SelectedValueChanged="@(v => context.CellValue = v)" > <Select TValue="int?" SelectedValue="@((int?)(context.CellValue))" SelectedValueChanged="@(v => context.CellValue = v)" >
@foreach (var item in OrganizationUnits) @foreach (var item in OrganizationUnits ?? Enumerable.Empty<OrganizationUnit>())
{ {
<SelectItem TValue="int" Value="@(item.Id)">@item.CommonName</SelectItem> <SelectItem TValue="int" Value="@(item.Id)">@item.CommonName</SelectItem>
} }

View File

@ -12,42 +12,40 @@ using UserService.Infrastructure.DataModels;
namespace UserService.Pages namespace UserService.Pages
{ {
public class UsersBase : ComponentBase public class UsersBase : MembersBase<User>
{ {
[Inject] private IUsersRepository UsersRepository { get; set; } = null!; [Inject] private IUsersRepository UsersRepository { get; set; } = null!;
[Inject] private IOrganizationUnitsRepository OrganizationUnitsRepository { get; set; } = null!; [Inject] private IOrganizationUnitsRepository OrganizationUnitsRepository { get; set; } = null!;
[Inject] private IJSRuntime JsRuntime { get; set; } = null!; [Inject] private IJSRuntime JsRuntime { get; set; } = null!;
protected IReadOnlyList<User>? Users { get; private set; }
protected IReadOnlyList<OrganizationUnit>? OrganizationUnits { get; private set; }
protected string? CustomFilterValue { get; set; }
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
Users = await UsersRepository.GetAllAsync().ConfigureAwait(false); Members = await UsersRepository.GetAllAsync().ConfigureAwait(false);
OrganizationUnits = await OrganizationUnitsRepository.GetAllAsync().ConfigureAwait(false); OrganizationUnits = await OrganizationUnitsRepository.GetAllAsync().ConfigureAwait(false);
} }
protected async Task RowInsertingCallback(CancellableRowChange<User, Dictionary<string, object>> arg) protected override async Task RowInsertingCallback(CancellableRowChange<User, Dictionary<string, object>> arg)
{ {
if (arg is null) throw new ArgumentNullException(nameof(arg)); if (arg is null) throw new ArgumentNullException(nameof(arg));
var mailValidation = Validators.ValidateEmail(arg.Values[nameof(User.EMail)]?.ToString()); var mailValidation = Validators.ValidateEmail(arg.Values[nameof(User.EMail)]?.ToString());
var commonNameValidation = Validators.ValidateCommonName(arg.Values[nameof(User.CommonName)]?.ToString(), Users); var commonNameValidation = Validators.ValidateCommonName(arg.Values[nameof(User.CommonName)]?.ToString(),
Members ?? Enumerable.Empty<User>());
if (mailValidation == true && commonNameValidation == true) return; if (mailValidation == true && commonNameValidation == true) return;
await JsRuntime.InvokeVoidAsync("alert", "User could not be added").ConfigureAwait(false); await JsRuntime.InvokeVoidAsync("alert", "User could not be added").ConfigureAwait(false);
arg.Cancel = true; arg.Cancel = true;
} }
protected async Task RowInsertedCallback(SavedRowItem<User, Dictionary<string, object>> arg) protected override async Task RowInsertedCallback(SavedRowItem<User, Dictionary<string, object>> arg)
{ {
if (arg is null) throw new ArgumentNullException(nameof(arg)); if (arg is null) throw new ArgumentNullException(nameof(arg));
var user = arg.Item; var user = arg.Item;
user.Parent = OrganizationUnits?.FirstOrDefault(x => x.Id == user.ParentId);
await UsersRepository.AddAsync(user).ConfigureAwait(false); await UsersRepository.AddAsync(user).ConfigureAwait(false);
user.Parent = OrganizationUnits?.FirstOrDefault(x => x.Id == user.ParentId);
} }
protected async Task RowDeletingCallback(CancellableRowChange<User> arg)
protected override async Task RowDeletingCallback(CancellableRowChange<User> arg)
{ {
if (arg == null) throw new ArgumentNullException(nameof(arg)); if (arg == null) throw new ArgumentNullException(nameof(arg));
var confirmed = await JsRuntime.InvokeAsync<bool>("confirm", var confirmed = await JsRuntime.InvokeAsync<bool>("confirm",
@ -61,14 +59,6 @@ namespace UserService.Pages
arg.Cancel = true; arg.Cancel = true;
} }
protected void ValidateCommonName(ValidatorEventArgs e)
{
if (e == null) throw new ArgumentNullException(nameof(e));
var commonName = e.Value?.ToString();
var validationResult = Validators.ValidateCommonName(commonName, Users);
e.Status = validationResult == false ? ValidationStatus.Error : ValidationStatus.Success;
}
protected static void ValidateEmail(ValidatorEventArgs e) protected static void ValidateEmail(ValidatorEventArgs e)
{ {
if (e == null) throw new ArgumentNullException(nameof(e)); if (e == null) throw new ArgumentNullException(nameof(e));
@ -82,25 +72,28 @@ namespace UserService.Pages
_ => ValidationStatus.Success _ => ValidationStatus.Success
}; };
} }
protected async Task RowUpdatingCallback(CancellableRowChange<User, Dictionary<string, object>> arg)
protected override async Task RowUpdatingCallback(CancellableRowChange<User, Dictionary<string, object>> arg)
{ {
if (arg == null) throw new ArgumentNullException(nameof(arg)); if (arg == null) throw new ArgumentNullException(nameof(arg));
var user = arg.Item; var user = arg.Item;
user.Parent = OrganizationUnits.FirstOrDefault(x => x.Id == (int?)arg.Values[nameof(Node.ParentId)]); user.MapFields(arg.Values);
user.Parent = OrganizationUnits?.FirstOrDefault(x => x.Id == (int?) arg.Values[nameof(Node.ParentId)]);
var result = await UsersRepository.UpdateAsync(user).ConfigureAwait(false); var result = await UsersRepository.UpdateAsync(user).ConfigureAwait(false);
arg.Cancel = !result; arg.Cancel = !result;
} }
protected bool OnCustomFilter(User model) protected override bool OnCustomFilter(User model)
{ {
if (model == null) throw new ArgumentNullException(nameof(model));
// We want to accept empty value as valid or otherwise // We want to accept empty value as valid or otherwise
// datagrid will not show anything. // datagrid will not show anything.
if (string.IsNullOrEmpty(CustomFilterValue) || CustomFilterValue.Length < 3) return true; if (string.IsNullOrEmpty(CustomFilterValue) || CustomFilterValue.Length < 3) return true;
return return
model?.FirstName?.Contains(CustomFilterValue, StringComparison.OrdinalIgnoreCase) == true model.FirstName?.Contains(CustomFilterValue, StringComparison.OrdinalIgnoreCase) == true
|| model?.LastName?.Contains(CustomFilterValue, StringComparison.OrdinalIgnoreCase) == true || model.LastName?.Contains(CustomFilterValue, StringComparison.OrdinalIgnoreCase) == true
|| model?.CommonName?.Contains(CustomFilterValue, StringComparison.OrdinalIgnoreCase) == true; || model.CommonName.Contains(CustomFilterValue, StringComparison.OrdinalIgnoreCase);
} }
} }
} }