Blazorise #4
@ -1,8 +1,8 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -12,43 +12,46 @@ namespace UserService.DatabaseLayer.Repository
|
||||
{
|
||||
public class BaseRepository<T> where T : Node
|
||||
{
|
||||
protected readonly Func<UserServiceDbContext, DbSet<T>> _context;
|
||||
protected readonly Func<UserServiceDbContext, DbSet<T>> Context;
|
||||
|
||||
protected BaseRepository(Func<UserServiceDbContext, DbSet<T>> context)
|
||||
{
|
||||
_context = context;
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public virtual async Task<IReadOnlyList<T>> GetAllAsync(CancellationToken token = default)
|
||||
public virtual async Task<IReadOnlyList<T>> GetAllAsync(Expression<Func<T, bool>>? predicate = null, CancellationToken token = default)
|
||||
{
|
||||
await using var db = new UserServiceDbContext();
|
||||
return await _context(db).Include(x => x.Parent).ToListAsync(token);
|
||||
|
||||
IQueryable<T> queryable = Context(db).Include(x => x.Parent);
|
||||
if(queryable != null) queryable = queryable.Where(predicate);
|
||||
return await queryable.ToListAsync(token);
|
||||
}
|
||||
|
||||
public async Task<T?> GetAsync(Expression<Func<T, bool>> predicate, CancellationToken token = default)
|
||||
{
|
||||
await using var db = new UserServiceDbContext();
|
||||
return await _context(db).FirstOrDefaultAsync(predicate, token);
|
||||
return await Context(db).FirstOrDefaultAsync(predicate, token);
|
||||
}
|
||||
|
||||
public async Task AddAsync(T entity, CancellationToken token = default)
|
||||
{
|
||||
await using var db = new UserServiceDbContext();
|
||||
await _context(db).AddAsync(@entity, token);
|
||||
await Context(db).AddAsync(@entity, token);
|
||||
await db.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public async Task UpdateAsync(T entity, CancellationToken token = default)
|
||||
{
|
||||
await using var db = new UserServiceDbContext();
|
||||
_context(db).Update(entity);
|
||||
Context(db).Update(entity);
|
||||
await db.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(T entity, CancellationToken token = default)
|
||||
{
|
||||
await using var db = new UserServiceDbContext();
|
||||
_context(db).Remove(entity);
|
||||
Context(db).Remove(entity);
|
||||
await db.SaveChangesAsync(token);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading;
|
||||
@ -9,7 +10,7 @@ namespace UserService.DatabaseLayer.Repository
|
||||
{
|
||||
public interface IRepository<T> where T : Node
|
||||
{
|
||||
Task<IReadOnlyList<T>> GetAllAsync(CancellationToken token = default);
|
||||
Task<IReadOnlyList<T>> GetAllAsync(Expression<Func<T, bool>>? predicate = null, CancellationToken token = default);
|
||||
Task<T?> GetAsync(Expression<Func<T, bool>> predicate, CancellationToken token = default);
|
||||
Task AddAsync(T entity, CancellationToken token = default);
|
||||
Task UpdateAsync(T entity, CancellationToken token = default);
|
||||
|
@ -23,7 +23,7 @@ namespace UserService.DatabaseLayer.Repository
|
||||
|
||||
await using var db = new UserServiceDbContext();
|
||||
var result = new List<OrganizationUnit>();
|
||||
var rootOus = await _context(db)
|
||||
var rootOus = await Context(db)
|
||||
.Include(x => x.Parent)
|
||||
.ToListAsync(token);
|
||||
|
||||
|
@ -1,11 +1,20 @@
|
||||
@page "/directory"
|
||||
@using UserService.DatabaseLayer.DataModels
|
||||
@using UserService.DatabaseLayer.Repository
|
||||
@inject IOrganizationUnitsRepository OuRepository
|
||||
@inherits DirectoryBase
|
||||
|
||||
@functions {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
<Row>
|
||||
<Column ColumnSize="ColumnSize.Is12">
|
||||
<h1>TODO</h1>
|
||||
|
||||
@if (_organizationUnits == null)
|
||||
</Column>
|
||||
</Row>
|
||||
@if (OrganizationUnits == null)
|
||||
{
|
||||
<p>
|
||||
<em>Loading...</em>
|
||||
@ -13,17 +22,20 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<Row>
|
||||
<Column ColumnSize="ColumnSize.Is4">
|
||||
<TreeView Nodes="OrganizationUnits"
|
||||
GetChildNodes="@(item => item?.Children)"
|
||||
HasChildNodes="@(item => item?.Children?.Any() == true)"
|
||||
@bind-SelectedNode="@SelectedNode">
|
||||
<NodeContent>
|
||||
<Icon Name="IconName.Folder"/>
|
||||
@context?.CommonName
|
||||
</NodeContent> </TreeView>
|
||||
</Column>
|
||||
<Column ColumnSize="ColumnSize.Is4">
|
||||
|
||||
|
||||
}
|
||||
@code {
|
||||
private IReadOnlyList<OrganizationUnit> _organizationUnits;
|
||||
private OrganizationUnit _selectedOu;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_organizationUnits = (await OuRepository.GetAllAsync().ConfigureAwait(false)).Where(x=> x.Parent is null).ToList();
|
||||
}
|
||||
|
||||
</Column>
|
||||
</Row>
|
||||
|
||||
}
|
45
UserService/Pages/Directory.razor.cs
Normal file
45
UserService/Pages/Directory.razor.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using UserService.DatabaseLayer.DataModels;
|
||||
using UserService.DatabaseLayer.Repository;
|
||||
|
||||
namespace UserService.Pages
|
||||
{
|
||||
public class DirectoryBase : ComponentBase
|
||||
{
|
||||
private Node? _selectedNode;
|
||||
public IReadOnlyList<Node>? OrganizationUnits { get; set; }
|
||||
|
||||
public Node? SelectedNode
|
||||
{
|
||||
get => _selectedNode;
|
||||
set
|
||||
{
|
||||
if(Equals(_selectedNode, value)) return;
|
||||
_selectedNode = value;
|
||||
OnSelectedNodeChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnSelectedNodeChanged(Node? value)
|
||||
{
|
||||
Members = await UsersRepository.GetAllAsync();
|
||||
}
|
||||
|
||||
[Inject] public IOrganizationUnitsRepository OuRepository { get; set; }
|
||||
|
||||
[Inject] public IUsersRepository UsersRepository { get; set; }
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
OrganizationUnits = (await OuRepository.GetAllAsync().ConfigureAwait(false))
|
||||
.Where(x => x.Parent is null)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -12,7 +12,10 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<MatTable Items="@OrganizationUnits" class="mat-elevation-z5">
|
||||
|
||||
|
||||
|
||||
@*<MatTable Items="@OrganizationUnits" class="mat-elevation-z5">
|
||||
<MatTableHeader>
|
||||
<th style="width: 20%">Common Name</th>
|
||||
<th style="width: 20%">Description</th>
|
||||
@ -33,12 +36,12 @@ else
|
||||
<a href="organizationUnits" @onclick="@(e => Delete(context))">delete</a>
|
||||
</td>
|
||||
</MatTableRow>
|
||||
</MatTable>
|
||||
</MatTable>*@
|
||||
|
||||
<MatButton @onclick="@(e => Edit(new OrganizationUnit()))">Create organization unit</MatButton>
|
||||
}
|
||||
|
||||
<MatDialog @bind-IsOpen="@DialogIsOpen">
|
||||
@*<MatDialog @bind-IsOpen="@DialogIsOpen">
|
||||
@if (OuToEdit != null)
|
||||
{
|
||||
<MatDialogTitle>@(OuToEdit.Id == 0 ? "New" : "Edit") @OuToEdit.CommonName (@OuToEdit.Id)</MatDialogTitle>
|
||||
@ -47,7 +50,7 @@ else
|
||||
<p/>
|
||||
<MatTextField Label="Description" @bind-Value="@OuToEdit.Description"/>
|
||||
@*<MatTextField Label="Manager" @bind-Value="@OuToEdit.Manager"/>*@
|
||||
<p/>
|
||||
@*<p />
|
||||
<MatSelectItem Items="@OrganizationUnits" Label="Parent" @bind-Value="@OuToEdit.Parent" />
|
||||
</MatDialogContent>
|
||||
}
|
||||
@ -59,4 +62,4 @@ else
|
||||
<MatButton OnClick="@(e => { DialogIsOpen = false; })">No Thanks</MatButton>
|
||||
<MatButton OnClick="@OkClick">OK</MatButton>
|
||||
</MatDialogActions>
|
||||
</MatDialog>
|
||||
</MatDialog>*@
|
@ -13,7 +13,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<MatTable Items="@SecurityGroups" class="mat-elevation-z5">
|
||||
@*<MatTable Items="@SecurityGroups" class="mat-elevation-z5">
|
||||
<MatTableHeader>
|
||||
<th style="width: 30%">Common Name</th>
|
||||
<th style="width: 20%">Description</th>
|
||||
@ -32,10 +32,10 @@ else
|
||||
|
||||
</MatTableRow>
|
||||
</MatTable>
|
||||
<MatButton @onclick="@(e => EditSecurityGroup(new SecurityGroup()))">Create new group</MatButton>
|
||||
<MatButton @onclick="@(e => EditSecurityGroup(new SecurityGroup()))">Create new group</MatButton>*@
|
||||
}
|
||||
|
||||
<MatDialog @bind-IsOpen="@DialogIsOpen">
|
||||
@*<MatDialog @bind-IsOpen="@DialogIsOpen">
|
||||
@if (SecurityGroupToEdit != null)
|
||||
{
|
||||
<MatDialogTitle>@(SecurityGroupToEdit.Id == 0 ? "New" : "Edit") @SecurityGroupToEdit.CommonName (@SecurityGroupToEdit.Id)</MatDialogTitle>
|
||||
@ -56,4 +56,4 @@ else
|
||||
<MatButton OnClick="@(e => { DialogIsOpen = false; })">No Thanks</MatButton>
|
||||
<MatButton OnClick="@OkClick">OK</MatButton>
|
||||
</MatDialogActions>
|
||||
</MatDialog>
|
||||
</MatDialog>*@
|
@ -12,7 +12,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<MatTable Items="@Users" class="mat-elevation-z5">
|
||||
@*<MatTable Items="@Users" class="mat-elevation-z5">
|
||||
<MatTableHeader>
|
||||
<th style="width: 20%">Common Name</th>
|
||||
<th style="width: 30%">Full name</th>
|
||||
@ -35,10 +35,10 @@ else
|
||||
</MatTableRow>
|
||||
</MatTable>
|
||||
|
||||
<MatButton @onclick="@(e => EditUser(new User()))">Create user</MatButton>
|
||||
<MatButton @onclick="@(e => EditUser(new User()))">Create user</MatButton>*@
|
||||
}
|
||||
|
||||
<MatDialog @bind-IsOpen="@DialogIsOpen">
|
||||
@*<MatDialog @bind-IsOpen="@DialogIsOpen">
|
||||
@if (UserToEdit != null)
|
||||
{
|
||||
<MatDialogTitle>@(UserToEdit.Id == 0 ? "New" : "Edit") @UserToEdit.CommonName (@UserToEdit.Id)</MatDialogTitle>
|
||||
@ -63,4 +63,4 @@ else
|
||||
<MatButton OnClick="@(e => { DialogIsOpen = false; })">No Thanks</MatButton>
|
||||
<MatButton OnClick="@OkClick">OK</MatButton>
|
||||
</MatDialogActions>
|
||||
</MatDialog>
|
||||
</MatDialog>*@
|
@ -12,10 +12,15 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>UserService</title>
|
||||
<base href="~/" />
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
|
||||
<link href="css/site.css" rel="stylesheet" />
|
||||
<script src="_content/MatBlazor/dist/matBlazor.js"></script>
|
||||
<link href="_content/MatBlazor/dist/matBlazor.css" rel="stylesheet"/>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.0/css/all.css">
|
||||
|
||||
<link href="_content/Blazorise/blazorise.css" rel="stylesheet" />
|
||||
<link href="_content/Blazorise.Bootstrap/blazorise.bootstrap.css" rel="stylesheet" />
|
||||
<link href="_content/Blazorise.Sidebar/blazorise.sidebar.css" rel="stylesheet" />
|
||||
<link href="_content/Blazorise.TreeView/blazorise.treeview.css" rel="stylesheet" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<app>
|
||||
@ -32,9 +37,12 @@
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
|
||||
<script src="_content/Blazorise/blazorise.js"></script>
|
||||
<script src="_content/Blazorise.Bootstrap/blazorise.bootstrap.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,49 +1,26 @@
|
||||
<div class="top-row pl-4 navbar navbar-dark">
|
||||
<a class="navbar-brand" href="">UserService</a>
|
||||
<button class="navbar-toggler" @onclick="ToggleNavMenu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
||||
<span class="oi oi-home" aria-hidden="true"></span> Home
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="users">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Users
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="securitygroups">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Security groups
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="organizationUnits">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Organization units
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="directory">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Directory
|
||||
</NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Sidebar Data="@_sidebarInfo" />
|
||||
|
||||
@code {
|
||||
private bool _collapseNavMenu = true;
|
||||
private SidebarInfo _sidebarInfo;
|
||||
|
||||
private string NavMenuCssClass => _collapseNavMenu ? "collapse" : null;
|
||||
|
||||
private void ToggleNavMenu()
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_collapseNavMenu = !_collapseNavMenu;
|
||||
_sidebarInfo = new SidebarInfo
|
||||
{
|
||||
Brand = new SidebarBrandInfo
|
||||
{
|
||||
Text = "SidebarBrand",
|
||||
To = "/"
|
||||
}, Items = new List<SidebarItemInfo>
|
||||
{
|
||||
new SidebarItemInfo
|
||||
{
|
||||
Text = "Directory",
|
||||
Icon = IconName.Folder,
|
||||
To = "/directory"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
<div class="alert alert-secondary mt-4" role="alert">
|
||||
<span class="oi oi-pencil mr-2" aria-hidden="true"></span>
|
||||
<strong>@Title</strong>
|
||||
|
||||
<span class="text-nowrap">
|
||||
Please take our
|
||||
<a target="_blank" class="font-weight-bold" href="https://go.microsoft.com/fwlink/?linkid=2112271">brief survey</a>
|
||||
</span>
|
||||
and tell us what you think.
|
||||
</div>
|
||||
|
||||
@code {
|
||||
// Demonstrates how a parent component can supply parameters
|
||||
[Parameter]
|
||||
public string Title { get; set; }
|
||||
}
|
@ -1,4 +1,7 @@
|
||||
using System.Net.Http;
|
||||
using Blazorise;
|
||||
using Blazorise.Bootstrap;
|
||||
using Blazorise.Icons.FontAwesome;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -26,7 +29,13 @@ namespace UserService
|
||||
services.AddSingleton<IUsersRepository, UsersRepository>();
|
||||
services.AddSingleton<ISecurityGroupsRepository, SecurityGroupsRepository>();
|
||||
services.AddSingleton<IOrganizationUnitsRepository, OrganizationUnitsRepository>();
|
||||
services.AddScoped<HttpClient>();
|
||||
services
|
||||
.AddBlazorise(options =>
|
||||
{
|
||||
options.ChangeTextOnKeyPress = true; // optional
|
||||
})
|
||||
.AddBootstrapProviders()
|
||||
.AddFontAwesomeIcons();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
@ -48,6 +57,10 @@ namespace UserService
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.ApplicationServices
|
||||
.UseBootstrapProviders()
|
||||
.UseFontAwesomeIcons();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapBlazorHub();
|
||||
|
@ -5,12 +5,15 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MatBlazor" Version="2.6.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\UserService.DatabaseLayer\UserService.DatabaseLayer.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Blazorise.Bootstrap" Version="0.9.1.2" />
|
||||
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="0.9.1.2" />
|
||||
<PackageReference Include="Blazorise.Sidebar" Version="0.9.1.2" />
|
||||
<PackageReference Include="Blazorise.TreeView" Version="0.9.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -7,4 +7,7 @@
|
||||
@using Microsoft.JSInterop
|
||||
@using UserService
|
||||
@using UserService.Shared
|
||||
@using MatBlazor
|
||||
@using Blazorise
|
||||
@using Blazorise.Sidebar
|
||||
@using Blazorise.TreeView
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user