Added MatBlazor and list of users

This commit is contained in:
Holger Börchers 2020-07-24 21:06:35 +02:00
parent 268e366d08
commit 2a86c16b85
13 changed files with 214 additions and 63 deletions

View File

@ -16,7 +16,7 @@ namespace UserService.Test
[Test] [Test]
public async Task Test1() public async Task Test1()
{ {
using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
var user = await db.Users.FirstOrDefaultAsync(); var user = await db.Users.FirstOrDefaultAsync();
var secGroup = await db.SecurityGroups.FirstOrDefaultAsync(); var secGroup = await db.SecurityGroups.FirstOrDefaultAsync();
var ous = await db.OrganizationUnits.ToListAsync(); var ous = await db.OrganizationUnits.ToListAsync();
@ -25,7 +25,7 @@ namespace UserService.Test
//var testGroup = new SecurityGroup {CommonName = "Test", Parent = ous.Last()}; //var testGroup = new SecurityGroup {CommonName = "Test", Parent = ous.Last()};
//await db.SecurityGroups.AddAsync(testGroup); //await db.SecurityGroups.AddAsync(testGroup);
//var testgroup = await db.SecurityGroups.FindAsync(1); //var testgroup = await db.SecurityGroups.FindAsync(1);
//testgroup.Members.Add(new UserMember{MemberId = testgroup.Id, UserId = user.Id}); //testgroup.Members.AddAsync(new UserMember{MemberId = testgroup.Id, UserId = user.Id});
//await db.SaveChangesAsync(); //await db.SaveChangesAsync();
Assert.Pass(); Assert.Pass();
} }

Binary file not shown.

View File

@ -5,11 +5,11 @@ namespace UserService.DataModels
{ {
public class OrganizationUnit : Node public class OrganizationUnit : Node
{ {
public Member? Manager { get; set; }
} }
public class SecurityGroup : Member public class SecurityGroup : Member
{ {
//public ICollection<UserSecurityGroup> Members { get; set; } = new List<UserSecurityGroup>();
} }
@ -19,16 +19,29 @@ namespace UserService.DataModels
public string? LastName { get; set; } public string? LastName { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
public IEnumerable<UserMember> MemberOf { get; set; } = new List<UserMember>(); public string FullName => $"{FirstName} {LastName}";
}
//public class UserSecurityGroup public IEnumerable<UserMember> MemberOf { get; set; } = new List<UserMember>();
//{
// public int UserId { get; set; } public User Clone()
// public User? User { get; set; } {
// public int SecurityGroupId { get; set; } return new User
// public SecurityGroup? SecurityGroup { get; set; } {
//} Children = Children,
CommonName = CommonName,
Description = Description,
EMail = EMail,
FirstName = FirstName,
Id = Id,
IsActive = IsActive,
LastName = LastName,
MemberOf = MemberOf,
Members = Members,
Parent = Parent,
ParentId = ParentId
};
}
}
public class UserMember public class UserMember
{ {
@ -42,6 +55,7 @@ namespace UserService.DataModels
public abstract class Member : Node public abstract class Member : Node
{ {
[EmailAddress]
public string? EMail { get; set; } public string? EMail { get; set; }
public ICollection<UserMember> Members { get; set; } = new List<UserMember>(); public ICollection<UserMember> Members { get; set; } = new List<UserMember>();
@ -52,7 +66,6 @@ namespace UserService.DataModels
public int Id { get; set; } public int Id { get; set; }
[Required] public string CommonName { get; set; } = "commonName"; [Required] public string CommonName { get; set; } = "commonName";
public string? Description { get; set; } public string? Description { get; set; }
public ICollection<Node> Children { get; set; } = new List<Node>(); public ICollection<Node> Children { get; set; } = new List<Node>();
public Node? Parent { get; set; } //Parent public Node? Parent { get; set; } //Parent
public int? ParentId { get; set; } public int? ParentId { get; set; }

View File

@ -2,7 +2,7 @@
namespace UserService.DataModels namespace UserService.DataModels
{ {
public class GroupsContext : DbContext public class UserServiceDbContext : DbContext
{ {
public DbSet<User> Users { get; set; } = null!; public DbSet<User> Users { get; set; } = null!;
public DbSet<SecurityGroup> SecurityGroups { get; set; } = null!; public DbSet<SecurityGroup> SecurityGroups { get; set; } = null!;

View File

@ -8,9 +8,9 @@ using UserService.DataModels;
namespace UserService.Migrations namespace UserService.Migrations
{ {
[DbContext(typeof(GroupsContext))] [DbContext(typeof(UserServiceDbContext))]
[Migration("20200723192940_intitial")] [Migration("20200724180034_initial")]
partial class intitial partial class initial
{ {
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
{ {
@ -83,6 +83,11 @@ namespace UserService.Migrations
{ {
b.HasBaseType("UserService.DataModels.Node"); b.HasBaseType("UserService.DataModels.Node");
b.Property<int?>("ManagerId")
.HasColumnType("INTEGER");
b.HasIndex("ManagerId");
b.HasDiscriminator().HasValue("OrganizationUnit"); b.HasDiscriminator().HasValue("OrganizationUnit");
b.HasData( b.HasData(
@ -159,6 +164,13 @@ namespace UserService.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("UserService.DataModels.OrganizationUnit", b =>
{
b.HasOne("UserService.DataModels.Member", "Manager")
.WithMany()
.HasForeignKey("ManagerId");
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }

View File

@ -2,7 +2,7 @@
namespace UserService.Migrations namespace UserService.Migrations
{ {
public partial class intitial : Migration public partial class initial : Migration
{ {
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
@ -19,7 +19,8 @@ namespace UserService.Migrations
EMail = table.Column<string>(nullable: true), EMail = table.Column<string>(nullable: true),
FirstName = table.Column<string>(nullable: true), FirstName = table.Column<string>(nullable: true),
LastName = table.Column<string>(nullable: true), LastName = table.Column<string>(nullable: true),
IsActive = table.Column<bool>(nullable: true) IsActive = table.Column<bool>(nullable: true),
ManagerId = table.Column<int>(nullable: true)
}, },
constraints: table => constraints: table =>
{ {
@ -30,6 +31,12 @@ namespace UserService.Migrations
principalTable: "Node", principalTable: "Node",
principalColumn: "Id", principalColumn: "Id",
onDelete: ReferentialAction.Restrict); onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_Node_Node_ManagerId",
column: x => x.ManagerId,
principalTable: "Node",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}); });
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
@ -58,13 +65,13 @@ namespace UserService.Migrations
migrationBuilder.InsertData( migrationBuilder.InsertData(
table: "Node", table: "Node",
columns: new[] { "Id", "CommonName", "Description", "Discriminator", "ParentId" }, columns: new[] { "Id", "CommonName", "Description", "Discriminator", "ParentId", "ManagerId" },
values: new object[] { -2, "Users", null, "OrganizationUnit", null }); values: new object[] { -2, "Users", null, "OrganizationUnit", null, null });
migrationBuilder.InsertData( migrationBuilder.InsertData(
table: "Node", table: "Node",
columns: new[] { "Id", "CommonName", "Description", "Discriminator", "ParentId" }, columns: new[] { "Id", "CommonName", "Description", "Discriminator", "ParentId", "ManagerId" },
values: new object[] { -1, "Groups", null, "OrganizationUnit", null }); values: new object[] { -1, "Groups", null, "OrganizationUnit", null, null });
migrationBuilder.InsertData( migrationBuilder.InsertData(
table: "Node", table: "Node",
@ -86,6 +93,11 @@ namespace UserService.Migrations
table: "Node", table: "Node",
column: "ParentId"); column: "ParentId");
migrationBuilder.CreateIndex(
name: "IX_Node_ManagerId",
table: "Node",
column: "ManagerId");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_UserMembers_UserId", name: "IX_UserMembers_UserId",
table: "UserMembers", table: "UserMembers",

View File

@ -7,8 +7,8 @@ using UserService.DataModels;
namespace UserService.Migrations namespace UserService.Migrations
{ {
[DbContext(typeof(GroupsContext))] [DbContext(typeof(UserServiceDbContext))]
partial class GroupsContextModelSnapshot : ModelSnapshot partial class UserServiceDbContextModelSnapshot : ModelSnapshot
{ {
protected override void BuildModel(ModelBuilder modelBuilder) protected override void BuildModel(ModelBuilder modelBuilder)
{ {
@ -81,6 +81,11 @@ namespace UserService.Migrations
{ {
b.HasBaseType("UserService.DataModels.Node"); b.HasBaseType("UserService.DataModels.Node");
b.Property<int?>("ManagerId")
.HasColumnType("INTEGER");
b.HasIndex("ManagerId");
b.HasDiscriminator().HasValue("OrganizationUnit"); b.HasDiscriminator().HasValue("OrganizationUnit");
b.HasData( b.HasData(
@ -157,6 +162,13 @@ namespace UserService.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("UserService.DataModels.OrganizationUnit", b =>
{
b.HasOne("UserService.DataModels.Member", "Manager")
.WithMany()
.HasForeignKey("ManagerId");
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }

View File

@ -1,7 +1,105 @@
@page "/" @page "/"
@using UserService.Repository
@using UserService.DataModels
@inject IUsersRepository UsersRepository
<h1>Hello, world!</h1>
Welcome to your new app. <h1>User service</h1>
<SurveyPrompt Title="How is Blazor working for you?" /> @if (_users == null)
{
<p>
<em>Loading...</em>
</p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Common Name</th>
<th>Full name</th>
<th>Description</th>
<th>E-Mail</th>
<th>Is active</th>
<th> </th>
<th> </th>
</tr>
</thead>
<tbody>
@foreach (var user in _users)
{
<tr>
<td>@user.CommonName</td>
<td>@user.FullName</td>
<td>@user.Description</td>
<td>@user.EMail</td>
<td>@user.IsActive</td>
<td><a href="" @onclick="@(e => EditUser(user))">edit</a></td>
<td><a href="" @onclick="@(e => DeleteUser(user))">delete</a></td>
</tr>
}
</tbody>
</table>
<MatButton @onclick="@(e => EditUser(new User()))">Create user</MatButton>
}
<MatDialog @bind-IsOpen="@_dialogIsOpen">
@if (_userToEdit != null)
{
<MatDialogTitle>@(_userToEdit.Id == 0 ? "New" : "Edit") @_userToEdit.CommonName (@_userToEdit.Id)</MatDialogTitle>
<MatDialogContent>
<MatTextField Label="Common name" @bind-Value="@_userToEdit.CommonName" ReadOnly="@(_userToEdit.Id != 0)"></MatTextField>
<p />
<MatTextField Label="First name" @bind-Value="@_userToEdit.FirstName"></MatTextField>
<MatTextField Label="Last name" @bind-Value="@_userToEdit.LastName"></MatTextField>
<p />
<MatTextField Label="Description" @bind-Value="@_userToEdit.Description"></MatTextField>
<p />
<MatTextField Label="E-Mail" @bind-Value="@_userToEdit.EMail"></MatTextField>
<MatCheckbox Label="Is active" @bind-Value="@_userToEdit.IsActive"></MatCheckbox>
</MatDialogContent>
}
else
{
<MatDialogTitle>No user selected</MatDialogTitle>
}
<MatDialogActions>
<MatButton OnClick="@(e => { _dialogIsOpen = false; })">No Thanks</MatButton>
<MatButton OnClick="@OkClick">OK</MatButton>
</MatDialogActions>
</MatDialog>
@code {
bool _dialogIsOpen;
User _userToEdit;
private IReadOnlyList<User> _users;
protected override async Task OnInitializedAsync()
{
_users = await UsersRepository.GetAllAsync();
}
private void EditUser(User user)
{
_dialogIsOpen = true;
_userToEdit = user.Clone();
}
async Task OkClick()
{
await UsersRepository.UpdateAsync(_userToEdit).ConfigureAwait(false);
await OnInitializedAsync().ConfigureAwait(false);
_dialogIsOpen = false;
}
private async Task DeleteUser(User user)
{
await UsersRepository.DeleteAsync(user).ConfigureAwait(false);
await OnInitializedAsync().ConfigureAwait(false);
}
}

View File

@ -14,6 +14,8 @@
<base href="~/" /> <base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" /> <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" /> <link href="css/site.css" rel="stylesheet" />
<script src="_content/MatBlazor/dist/matBlazor.js"></script>
<link href="_content/MatBlazor/dist/matBlazor.css" rel="stylesheet" />
</head> </head>
<body> <body>
<app> <app>

View File

@ -10,37 +10,37 @@ namespace UserService.Repository
{ {
public class OrganizationUnitRepository : IOrganizationUnitRepository public class OrganizationUnitRepository : IOrganizationUnitRepository
{ {
public async Task<IReadOnlyList<OrganizationUnit>> GetAll(CancellationToken token = default) public async Task<IReadOnlyList<OrganizationUnit>> GetAllAsync(CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
return await db.OrganizationUnits.ToListAsync(token); return await db.OrganizationUnits.ToListAsync(token);
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task<OrganizationUnit?> Get(Func<OrganizationUnit, bool> predicate, public async Task<OrganizationUnit?> GetAsync(Func<OrganizationUnit, bool> predicate,
CancellationToken token = default) CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
return db.OrganizationUnits.Where(predicate).FirstOrDefault(); return db.OrganizationUnits.Where(predicate).FirstOrDefault();
} }
public async Task Add(OrganizationUnit entity, CancellationToken token = default) public async Task AddAsync(OrganizationUnit entity, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
await db.OrganizationUnits.AddAsync(@entity, token); await db.OrganizationUnits.AddAsync(@entity, token);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
} }
public async Task Update(OrganizationUnit entity, CancellationToken token = default) public async Task UpdateAsync(OrganizationUnit entity, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
db.OrganizationUnits.Update(entity); db.OrganizationUnits.Update(entity);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
} }
public async Task Delete(OrganizationUnit entity, CancellationToken token = default) public async Task DeleteAsync(OrganizationUnit entity, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
db.OrganizationUnits.Remove(entity); db.OrganizationUnits.Remove(entity);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
} }
@ -49,36 +49,36 @@ namespace UserService.Repository
public class SecurityGroupsRepository : ISecurityGroupsRepository public class SecurityGroupsRepository : ISecurityGroupsRepository
{ {
public async Task<IReadOnlyList<SecurityGroup>> GetAll(CancellationToken token = default) public async Task<IReadOnlyList<SecurityGroup>> GetAllAsync(CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
return await db.SecurityGroups.ToListAsync(token); return await db.SecurityGroups.ToListAsync(token);
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task<SecurityGroup?> Get(Func<SecurityGroup, bool> predicate, CancellationToken token = default) public async Task<SecurityGroup?> GetAsync(Func<SecurityGroup, bool> predicate, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
return db.SecurityGroups.Where(predicate).FirstOrDefault(); return db.SecurityGroups.Where(predicate).FirstOrDefault();
} }
public async Task Add(SecurityGroup entity, CancellationToken token = default) public async Task AddAsync(SecurityGroup entity, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
await db.SecurityGroups.AddAsync(@entity, token); await db.SecurityGroups.AddAsync(@entity, token);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
} }
public async Task Update(SecurityGroup entity, CancellationToken token = default) public async Task UpdateAsync(SecurityGroup entity, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
db.SecurityGroups.Update(entity); db.SecurityGroups.Update(entity);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
} }
public async Task Delete(SecurityGroup entity, CancellationToken token = default) public async Task DeleteAsync(SecurityGroup entity, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
db.SecurityGroups.Remove(entity); db.SecurityGroups.Remove(entity);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
} }
@ -87,36 +87,36 @@ namespace UserService.Repository
public class UsersRepository : IUsersRepository public class UsersRepository : IUsersRepository
{ {
public async Task<IReadOnlyList<User>> GetAll(CancellationToken token = default) public async Task<IReadOnlyList<User>> GetAllAsync(CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
return await db.Users.ToListAsync(token); return await db.Users.ToListAsync(token);
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task<User?> Get(Func<User, bool> predicate, CancellationToken token = default) public async Task<User?> GetAsync(Func<User, bool> predicate, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
return db.Users.Where(predicate).FirstOrDefault(); return db.Users.Where(predicate).FirstOrDefault();
} }
public async Task Add(User entity, CancellationToken token = default) public async Task AddAsync(User entity, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
await db.Users.AddAsync(@entity, token); await db.Users.AddAsync(@entity, token);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
} }
public async Task Update(User entity, CancellationToken token = default) public async Task UpdateAsync(User entity, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
db.Users.Update(entity); db.Users.Update(entity);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
} }
public async Task Delete(User entity, CancellationToken token = default) public async Task DeleteAsync(User entity, CancellationToken token = default)
{ {
await using var db = new GroupsContext(); await using var db = new UserServiceDbContext();
db.Users.Remove(entity); db.Users.Remove(entity);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
} }

View File

@ -8,11 +8,11 @@ namespace UserService.Repository
{ {
public interface IRepository<T> where T : Node public interface IRepository<T> where T : Node
{ {
Task<IReadOnlyList<T>> GetAll(CancellationToken token = default); Task<IReadOnlyList<T>> GetAllAsync(CancellationToken token = default);
Task<T?> Get(Func<T, bool> predicate, CancellationToken token = default); Task<T?> GetAsync(Func<T, bool> predicate, CancellationToken token = default);
Task Add(T entity, CancellationToken token = default); Task AddAsync(T entity, CancellationToken token = default);
Task Update(T entity, CancellationToken token = default); Task UpdateAsync(T entity, CancellationToken token = default);
Task Delete(T entity, CancellationToken token = default); Task DeleteAsync(T entity, CancellationToken token = default);
} }
public interface IOrganizationUnitRepository : IRepository<OrganizationUnit> public interface IOrganizationUnitRepository : IRepository<OrganizationUnit>

View File

@ -6,6 +6,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MatBlazor" Version="2.6.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.6"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View File

@ -7,3 +7,4 @@
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using UserService @using UserService
@using UserService.Shared @using UserService.Shared
@using MatBlazor