Skip to content

Commit

Permalink
#218 - Events for managing sign-in and out notifications on client.
Browse files Browse the repository at this point in the history
  • Loading branch information
maraf committed Mar 6, 2019
1 parent c3ea040 commit 37f8dac
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 37 deletions.
1 change: 1 addition & 0 deletions src/Money.UI.Blazor/Bootstrap/BootstrapTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public void Initialize()
.AddTransient(typeof(ILog<>), typeof(DefaultLog<>))
.AddSingleton(eventDispatcher)
.AddSingleton(eventDispatcher.Handlers)
.AddSingleton(eventDispatcher.Dispatcher)
.AddSingleton(exceptionHandler)
.AddSingleton(exceptionHandler.Handler)
.AddSingleton(exceptionHandler.HandlerBuilder);
Expand Down
14 changes: 14 additions & 0 deletions src/Money.UI.Blazor/Events/UserSignedIn.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Money.Events
{
/// <summary>
/// An event raised when a user has signed in.
/// </summary>
public class UserSignedIn : UserEvent
{ }
}
14 changes: 14 additions & 0 deletions src/Money.UI.Blazor/Events/UserSignedOut.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Money.Events
{
/// <summary>
/// An event raised when a user has signed in.
/// </summary>
public class UserSignedOut : UserEvent
{ }
}
30 changes: 5 additions & 25 deletions src/Money.UI.Blazor/Layouts/LoginInfo.cshtml
Original file line number Diff line number Diff line change
@@ -1,37 +1,17 @@
@inject IQueryDispatcher Queries
@inject Navigator Navigator
@inject ApiClient ApiClient
@using Money.Layouts
@inherits LoginInfoBase

<form class="navbar-right" onsubmit="@OnLogoutAsync">
<ul class="nav navbar-nav navbar-right">
<li>
<a href="@Navigator.UrlUserManage()" onclick="@(() => Navigator.OpenUserManage())">
<a href="@Navigator.UrlUserManage()">
<Loading Context="@Loading">
User: @Profile.UserName
User: @(Profile?.UserName ?? "---")
</Loading>
</a>
</li>
<li>
<button type="submit" class="btn btn-link navbar-btn navbar-link">Log out</button>
<button type="button" class="btn btn-link navbar-btn navbar-link" onclick="@OnLogoutAsync">Log out</button>
</li>
</ul>
</form>

@functions
{
public ProfileModel Profile { get; private set; }

protected LoadingContext Loading { get; } = new LoadingContext();

protected override async Task OnInitAsync()
{
using (Loading.Start())
Profile = await Queries.QueryAsync(new GetProfile());
}

protected async Task OnLogoutAsync()
{
await ApiClient.LogoutAsync();
Navigator.OpenLogin();
}
}
90 changes: 90 additions & 0 deletions src/Money.UI.Blazor/Layouts/LoginInfo.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using Microsoft.AspNetCore.Blazor.Components;
using Money.Events;
using Money.Models;
using Money.Models.Loading;
using Money.Queries;
using Money.Services;
using Neptuo.Events;
using Neptuo.Events.Handlers;
using Neptuo.Queries;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Money.Layouts
{
public class LoginInfoBase : BlazorComponent, IDisposable, IEventHandler<UserSignedIn>, IEventHandler<UserSignedOut>
{
[Inject]
public IQueryDispatcher Queries { get; set; }

[Inject]
public IEventHandlerCollection EventHandlers { get; set; }

[Inject]
internal Navigator Navigator { get; set; }

[Inject]
public ApiClient ApiClient { get; set; }

public ProfileModel Profile { get; private set; }
protected LoadingContext Loading { get; } = new LoadingContext();

protected async override Task OnInitAsync()
{
BindEvents();

await LoadProfileAsync();
}

private async Task LoadProfileAsync()
{
using (Loading.Start())
Profile = await Queries.QueryAsync(new GetProfile());
}

protected async Task OnLogoutAsync()
{
await ApiClient.LogoutAsync();
Navigator.OpenLogin();
}

public void Dispose()
{
UnBindEvents();
}

#region Events

private void BindEvents()
{
EventHandlers
.Add<UserSignedIn>(this)
.Add<UserSignedOut>(this);
}

private void UnBindEvents()
{
EventHandlers
.Remove<UserSignedIn>(this)
.Remove<UserSignedOut>(this);
}

async Task IEventHandler<UserSignedIn>.HandleAsync(UserSignedIn payload)
{
await LoadProfileAsync();
StateHasChanged();
}

Task IEventHandler<UserSignedOut>.HandleAsync(UserSignedOut payload)
{
Profile = null;
StateHasChanged();
return Task.CompletedTask;
}

#endregion
}
}
22 changes: 17 additions & 5 deletions src/Money.UI.Blazor/Services/ApiClient.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Blazor;
using Money.Events;
using Money.Models.Api;
using Money.Users.Models;
using Neptuo;
using Neptuo.Events;
using Neptuo.Exceptions.Handlers;
using System;
using System.Collections.Generic;
Expand All @@ -23,28 +25,36 @@ public class ApiClient
private readonly CommandMapper commandMapper;
private readonly QueryMapper queryMapper;
private readonly IExceptionHandler exceptionHandler;
private readonly IEventDispatcher eventDispatcher;

public ApiClient(HttpClient http, CommandMapper commandMapper, QueryMapper queryMapper, IExceptionHandler exceptionHandler)
public ApiClient(HttpClient http, CommandMapper commandMapper, QueryMapper queryMapper, IExceptionHandler exceptionHandler, IEventDispatcher eventDispatcher)
{
Ensure.NotNull(http, "http");
Ensure.NotNull(commandMapper, "commandMapper");
Ensure.NotNull(queryMapper, "queryMapper");
Ensure.NotNull(exceptionHandler, "exceptionHandler");
Ensure.NotNull(eventDispatcher, "eventDispatcher");
this.http = http;
this.commandMapper = commandMapper;
this.queryMapper = queryMapper;
this.exceptionHandler = exceptionHandler;
this.eventDispatcher = eventDispatcher;
http.BaseAddress = new Uri(rootUrl);

EnsureAuthorization();
}

private void ClearAuthorization()
{
token = null;
http.DefaultRequestHeaders.Authorization = null;
Interop.SaveToken(null);
Interop.StopSignalR();
if (token != null)
{
token = null;
http.DefaultRequestHeaders.Authorization = null;
Interop.SaveToken(null);
Interop.StopSignalR();

eventDispatcher.PublishAsync(new UserSignedOut());
}
}

private void EnsureAuthorization()
Expand All @@ -53,6 +63,8 @@ private void EnsureAuthorization()
{
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
Interop.StartSignalR(rootUrl + "/api", token);

eventDispatcher.PublishAsync(new UserSignedIn());
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/Money.UI.Blazor/Services/CategoryMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ internal class CategoryMiddleware : HttpQueryDispatcher.IMiddleware,
IEventHandler<CategoryDescriptionChanged>,
IEventHandler<CategoryIconChanged>,
IEventHandler<CategoryColorChanged>,
IEventHandler<CategoryDeleted>
IEventHandler<CategoryDeleted>,
IEventHandler<UserSignedOut>
{
private readonly List<CategoryModel> models = new List<CategoryModel>();
private Task listAllTask;
Expand Down Expand Up @@ -108,5 +109,11 @@ Task IEventHandler<CategoryColorChanged>.HandleAsync(CategoryColorChanged payloa

Task IEventHandler<CategoryDeleted>.HandleAsync(CategoryDeleted payload)
=> Update(payload.AggregateKey, model => models.Remove(model));

Task IEventHandler<UserSignedOut>.HandleAsync(UserSignedOut payload)
{
models.Clear();
return Task.CompletedTask;
}
}
}
9 changes: 8 additions & 1 deletion src/Money.UI.Blazor/Services/CurrencyMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ internal class CurrencyMiddleware : HttpQueryDispatcher.IMiddleware,
IEventHandler<CurrencyCreated>,
IEventHandler<CurrencyDefaultChanged>,
IEventHandler<CurrencySymbolChanged>,
IEventHandler<CurrencyDeleted>
IEventHandler<CurrencyDeleted>,
IEventHandler<UserSignedOut>
{
private readonly List<CurrencyModel> models = new List<CurrencyModel>();
private Task listAllTask;
Expand Down Expand Up @@ -88,5 +89,11 @@ Task IEventHandler<CurrencySymbolChanged>.HandleAsync(CurrencySymbolChanged payl

Task IEventHandler<CurrencyDeleted>.HandleAsync(CurrencyDeleted payload)
=> Update(payload.UniqueCode, model => models.Remove(model));

Task IEventHandler<UserSignedOut>.HandleAsync(UserSignedOut payload)
{
models.Clear();
return Task.CompletedTask;
}
}
}
6 changes: 2 additions & 4 deletions src/Money.UI.Blazor/Services/Events/BrowserEventDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ public BrowserEventDispatcher(FormatterContainer formatters, ILogFactory logFact
this.log = logFactory.Scope("BrowserEventDispatcher");
}

public IEventHandlerCollection Handlers
{
get => manager;
}
public IEventHandlerCollection Handlers => manager;
public IEventDispatcher Dispatcher => manager;

public void Raise(string rawPayload)
{
Expand Down
10 changes: 9 additions & 1 deletion src/Money.UI.Blazor/Services/UserMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
namespace Money.Services
{
internal class UserMiddleware : HttpQueryDispatcher.IMiddleware,
IEventHandler<EmailChanged>
IEventHandler<EmailChanged>,
IEventHandler<UserSignedOut>
{
private ProfileModel profile;
private Task getProfileTask;
Expand Down Expand Up @@ -47,5 +48,12 @@ Task IEventHandler<EmailChanged>.HandleAsync(EmailChanged payload)

return Task.CompletedTask;
}

Task IEventHandler<UserSignedOut>.HandleAsync(UserSignedOut payload)
{
profile = null;

return Task.CompletedTask;
}
}
}

0 comments on commit 37f8dac

Please sign in to comment.