Ajout gestion des toasts sur Blazor
This commit is contained in:
parent
cb3821e5ed
commit
5c98a14d91
32
Apps/Client/NotificationManager.cs
Normal file
32
Apps/Client/NotificationManager.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Client
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service permettant d'afficher des toasts dans l'application.
|
||||||
|
/// </summary>
|
||||||
|
public class NotificationManager
|
||||||
|
{
|
||||||
|
private Queue<string> _messages = new Queue<string>();
|
||||||
|
|
||||||
|
public IReadOnlyList<string> Messages => _messages.ToArray();
|
||||||
|
|
||||||
|
public event Action OnChange;
|
||||||
|
|
||||||
|
public void Add(string message)
|
||||||
|
{
|
||||||
|
_messages.Enqueue(message);
|
||||||
|
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(3000);
|
||||||
|
_messages.Dequeue();
|
||||||
|
OnChange?.Invoke();
|
||||||
|
});
|
||||||
|
|
||||||
|
OnChange?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,16 +0,0 @@
|
|||||||
@page "/counter"
|
|
||||||
|
|
||||||
<h1>Counter</h1>
|
|
||||||
|
|
||||||
<p>Current count: @currentCount</p>
|
|
||||||
|
|
||||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private int currentCount = 0;
|
|
||||||
|
|
||||||
private void IncrementCount()
|
|
||||||
{
|
|
||||||
currentCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
58
Apps/Client/Pages/Detail.razor
Normal file
58
Apps/Client/Pages/Detail.razor
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
@page "/links/{id:guid}"
|
||||||
|
@inject LinksClient Links
|
||||||
|
@inject CommentsClient Comments
|
||||||
|
@inject NotificationManager Notification
|
||||||
|
|
||||||
|
@if (_link == null)
|
||||||
|
{
|
||||||
|
<Title Value="Loading link detail..." />
|
||||||
|
<p>Loading link detail...</p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<Title Value="@($"Viewing link {_link.Url}")" />
|
||||||
|
|
||||||
|
<h1>Viewing link @_link.Url</h1>
|
||||||
|
|
||||||
|
@if(_comments == null)
|
||||||
|
{
|
||||||
|
<p>Loading link comments...</p>
|
||||||
|
}
|
||||||
|
else if (_comments.Count == 0)
|
||||||
|
{
|
||||||
|
<p>No comments yet.</p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<ul>
|
||||||
|
@foreach (var comment in _comments)
|
||||||
|
{
|
||||||
|
<li>@comment.Content</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
|
||||||
|
<CommentForm OnSubmit="PublishComment" />
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
private LinkDTO _link;
|
||||||
|
private ICollection<CommentDTO> _comments;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
_link = await Links.GetByIdAsync(Id);
|
||||||
|
_comments = await Links.CommentsAsync(Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PublishComment(PublishCommentCommand cmd)
|
||||||
|
{
|
||||||
|
cmd.LinkId = Id;
|
||||||
|
await Comments.CreateAsync(cmd);
|
||||||
|
Notification.Add("Your comment was published!");
|
||||||
|
_comments = await Links.CommentsAsync(Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,8 @@
|
|||||||
@page "/"
|
@page "/"
|
||||||
@inject LinksClient Links
|
@inject LinksClient Links
|
||||||
|
|
||||||
|
<Title Value="Latest links" />
|
||||||
|
|
||||||
<h1>Latest links</h1>
|
<h1>Latest links</h1>
|
||||||
|
|
||||||
@if (_links == null) {
|
@if (_links == null) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
@page "/links/new"
|
@page "/links/new"
|
||||||
@inject LinksClient Links
|
@inject LinksClient Links
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
|
@inject NotificationManager Notification
|
||||||
@using System.ComponentModel.DataAnnotations
|
@using System.ComponentModel.DataAnnotations
|
||||||
|
|
||||||
<h1>Publish a new link!</h1>
|
<h1>Publish a new link!</h1>
|
||||||
@ -29,6 +30,7 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Links.CreateAsync(_model.Command);
|
await Links.CreateAsync(_model.Command);
|
||||||
|
Notification.Add("Your link was published!");
|
||||||
Navigation.NavigateTo("/");
|
Navigation.NavigateTo("/");
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch(Exception ex)
|
||||||
|
|||||||
20
Apps/Client/Pages/Sandbox.razor
Normal file
20
Apps/Client/Pages/Sandbox.razor
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
@page "/sandbox"
|
||||||
|
|
||||||
|
<p>Current count: @currentCount</p>
|
||||||
|
|
||||||
|
<Counter @bind-Count="currentCount" />
|
||||||
|
|
||||||
|
@* <CascadingValue Value="45">
|
||||||
|
<Composant1 />
|
||||||
|
</CascadingValue>
|
||||||
|
|
||||||
|
<Composant2 /> *@
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private int currentCount = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
[CascadingParameter]
|
||||||
|
public int Valeur { get; set; }
|
||||||
|
*/
|
||||||
|
}
|
||||||
@ -19,6 +19,8 @@ namespace Client
|
|||||||
|
|
||||||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.Configuration["BaseUrl"]) });
|
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.Configuration["BaseUrl"]) });
|
||||||
builder.Services.AddScoped<LinksClient>();
|
builder.Services.AddScoped<LinksClient>();
|
||||||
|
builder.Services.AddScoped<CommentsClient>();
|
||||||
|
builder.Services.AddSingleton<NotificationManager>();
|
||||||
|
|
||||||
await builder.Build().RunAsync();
|
await builder.Build().RunAsync();
|
||||||
}
|
}
|
||||||
|
|||||||
22
Apps/Client/Shared/CommentForm.razor
Normal file
22
Apps/Client/Shared/CommentForm.razor
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<EditForm Model="_model" OnValidSubmit="OnValidSubmit">
|
||||||
|
<DataAnnotationsValidator />
|
||||||
|
<ValidationSummary />
|
||||||
|
|
||||||
|
<label for="content">Your comment</label>
|
||||||
|
<InputTextArea id="content" @bind-Value="_model.Content" />
|
||||||
|
|
||||||
|
<button type="submit">Post your comment</button>
|
||||||
|
</EditForm>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<PublishCommentCommand> OnSubmit { get; set; }
|
||||||
|
|
||||||
|
private PublishCommentCommand _model = new PublishCommentCommand();
|
||||||
|
|
||||||
|
private async Task OnValidSubmit()
|
||||||
|
{
|
||||||
|
await OnSubmit.InvokeAsync(_model);
|
||||||
|
_model = new PublishCommentCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Apps/Client/Shared/Counter.razor
Normal file
22
Apps/Client/Shared/Counter.razor
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<p>Current count in component: @Count</p>
|
||||||
|
|
||||||
|
<button @onclick="Increment">+</button>
|
||||||
|
<button @onclick="Decrement">-</button>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter]
|
||||||
|
public int Count { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<int> CountChanged { get; set; }
|
||||||
|
|
||||||
|
private void Increment()
|
||||||
|
{
|
||||||
|
CountChanged.InvokeAsync(Count + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Decrement()
|
||||||
|
{
|
||||||
|
CountChanged.InvokeAsync(Count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
<article>
|
<article>
|
||||||
<h2>@Item.Url</h2>
|
<h2>@Item.Url</h2>
|
||||||
<p>
|
<p>
|
||||||
|
<NavLink href="@($"/links/{Item.Id}")">Show</NavLink>
|
||||||
- Published at @Item.CreatedAt.DateTime.ToLongDateString()
|
- Published at @Item.CreatedAt.DateTime.ToLongDateString()
|
||||||
- 🗨 @Item.CommentsCount
|
- 🗨 @Item.CommentsCount
|
||||||
- 👍 @Item.UpvotesCount / 👎 @Item.DownvotesCount
|
- 👍 @Item.UpvotesCount / 👎 @Item.DownvotesCount
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content px-4">
|
<div class="content px-4">
|
||||||
|
<Notifications />
|
||||||
|
|
||||||
@Body
|
@Body
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
21
Apps/Client/Shared/Notifications.razor
Normal file
21
Apps/Client/Shared/Notifications.razor
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
@inject NotificationManager Notification
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
<div>
|
||||||
|
@foreach (var msg in Notification.Messages)
|
||||||
|
{
|
||||||
|
<p class="alert alert-success">@msg</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
Notification.OnChange += StateHasChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Notification.OnChange -= StateHasChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Apps/Client/Shared/Title.razor
Normal file
11
Apps/Client/Shared/Title.razor
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
@inject IJSRuntime JS
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter]
|
||||||
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
JS.InvokeVoidAsync("setTitle", Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,25 +1,32 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||||
|
/>
|
||||||
<title>Client</title>
|
<title>Client</title>
|
||||||
<base href="/" />
|
<base href="/" />
|
||||||
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
|
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
|
||||||
<link href="css/app.css" rel="stylesheet" />
|
<link href="css/app.css" rel="stylesheet" />
|
||||||
<link href="Client.styles.css" rel="stylesheet" />
|
<link href="Client.styles.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app">Loading...</div>
|
<div id="app">Loading...</div>
|
||||||
|
|
||||||
<div id="blazor-error-ui">
|
<div id="blazor-error-ui">
|
||||||
An unhandled error has occurred.
|
An unhandled error has occurred.
|
||||||
<a href="" class="reload">Reload</a>
|
<a href="" class="reload">Reload</a>
|
||||||
<a class="dismiss">🗙</a>
|
<a class="dismiss">🗙</a>
|
||||||
</div>
|
</div>
|
||||||
<script src="_framework/blazor.webassembly.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function setTitle(title) {
|
||||||
|
document.title = title;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script src="_framework/blazor.webassembly.js"></script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user