Skip to content

Commit

Permalink
Simple alert created
Browse files Browse the repository at this point in the history
  • Loading branch information
goodtocode committed Jul 5, 2023
1 parent 05b7c1b commit 96dd10d
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 2 deletions.
117 changes: 117 additions & 0 deletions src/Subjects/Presentation.Shared.Rcl/Alert/Alert.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
@using Microsoft.AspNetCore.Components.Routing;
@implements IDisposable
@inject IAlertService AlertService
@inject NavigationManager NavigationManager

@foreach (var alert in alerts)
{
<div class="@CssClass(alert)">
<a class="close" @onclick="@(() => RemoveAlert(alert))">&times;</a>
<span>@alert.Message</span>
</div>
}

@code {
[Parameter]
public string Id { get; set; } = "default-alert";

[Parameter]
public bool Fade { get; set; } = true;

private List<AlertModel> alerts = new List<AlertModel>();

protected override void OnInitialized()
{
// subscribe to new alerts and location change events
AlertService.OnAlert += OnAlert;
NavigationManager.LocationChanged += OnLocationChange;

Check warning on line 27 in src/Subjects/Presentation.Shared.Rcl/Alert/Alert.razor

View workflow job for this annotation

GitHub Actions / Build, Test and Deploy .NET (7.0.x)

Nullability of reference types in type of parameter 'sender' of 'void Alert.OnLocationChange(object sender, LocationChangedEventArgs e)' doesn't match the target delegate 'EventHandler<LocationChangedEventArgs>' (possibly because of nullability attributes).
}

public void Dispose()
{
// unsubscribe from alerts and location change events
AlertService.OnAlert -= OnAlert;
NavigationManager.LocationChanged -= OnLocationChange;

Check warning on line 34 in src/Subjects/Presentation.Shared.Rcl/Alert/Alert.razor

View workflow job for this annotation

GitHub Actions / Build, Test and Deploy .NET (7.0.x)

Nullability of reference types in type of parameter 'sender' of 'void Alert.OnLocationChange(object sender, LocationChangedEventArgs e)' doesn't match the target delegate 'EventHandler<LocationChangedEventArgs>' (possibly because of nullability attributes).
}

private async void OnAlert(AlertModel alert)
{
// ignore alerts sent to other alert components
if (alert.Id != Id)
return;

// clear alerts when an empty alert is received
if (alert.Message == null)
{
// remove alerts without the 'KeepAfterRouteChange' flag set to true
alerts.RemoveAll(x => !x.KeepAfterRouteChange);

// set the 'KeepAfterRouteChange' flag to false for the
// remaining alerts so they are removed on the next clear
alerts.ForEach(x => x.KeepAfterRouteChange = false);
}
else
{
// add alert to array
alerts.Add(alert);
StateHasChanged();

// auto close alert if required
if (alert.AutoClose)
{
await Task.Delay(3000);
RemoveAlert(alert);
}
}

StateHasChanged();
}

private void OnLocationChange(object sender, LocationChangedEventArgs e)
{
AlertService.Clear(Id);
}

private async void RemoveAlert(AlertModel alert)
{
// check if already removed to prevent error on auto close
if (!alerts.Contains(alert)) return;

if (Fade)
{
// fade out alert
alert.Fade = true;

// remove alert after faded out
await Task.Delay(250);
alerts.Remove(alert);
}
else
{
// remove alert
alerts.Remove(alert);
}

StateHasChanged();
}

private string CssClass(AlertModel alert)
{
if (alert == null) return null;

var classes = new List<string> { "alert", "alert-dismissable", "mt-4", "container" };

var alertTypeClass = new Dictionary<AlertType, string>();
alertTypeClass[AlertType.Success] = "alert-success";
alertTypeClass[AlertType.Error] = "alert-danger";
alertTypeClass[AlertType.Info] = "alert-info";
alertTypeClass[AlertType.Warning] = "alert-warning";

classes.Add(alertTypeClass[alert.Type]);

if (alert.Fade)
classes.Add("fade");

return string.Join(' ', classes);
}
}
19 changes: 19 additions & 0 deletions src/Subjects/Presentation.Shared.Rcl/Alert/AlertModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Goodtocode.Subjects.Rcl;

public class AlertModel
{
public string Id { get; set; }

Check warning on line 5 in src/Subjects/Presentation.Shared.Rcl/Alert/AlertModel.cs

View workflow job for this annotation

GitHub Actions / Build, Test and Deploy .NET (7.0.x)

Non-nullable property 'Id' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public AlertType Type { get; set; }
public string Message { get; set; }

Check warning on line 7 in src/Subjects/Presentation.Shared.Rcl/Alert/AlertModel.cs

View workflow job for this annotation

GitHub Actions / Build, Test and Deploy .NET (7.0.x)

Non-nullable property 'Message' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public bool AutoClose { get; set; }
public bool KeepAfterRouteChange { get; set; }
public bool Fade { get; set; }
}

public enum AlertType
{
Success,
Error,
Info,
Warning
}
73 changes: 73 additions & 0 deletions src/Subjects/Presentation.Shared.Rcl/Alert/AlertService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
namespace Goodtocode.Subjects.Rcl;

public interface IAlertService
{
event Action<AlertModel> OnAlert;
void Success(string message, bool keepAfterRouteChange = false, bool autoClose = true);
void Error(string message, bool keepAfterRouteChange = false, bool autoClose = true);
void Info(string message, bool keepAfterRouteChange = false, bool autoClose = true);
void Warn(string message, bool keepAfterRouteChange = false, bool autoClose = true);
void Alert(AlertModel alert);
void Clear(string id = null);

Check warning on line 11 in src/Subjects/Presentation.Shared.Rcl/Alert/AlertService.cs

View workflow job for this annotation

GitHub Actions / Build, Test and Deploy .NET (7.0.x)

Cannot convert null literal to non-nullable reference type.
}

public class AlertService : IAlertService
{
private const string _defaultId = "default-alert";
public event Action<AlertModel> OnAlert;

Check warning on line 17 in src/Subjects/Presentation.Shared.Rcl/Alert/AlertService.cs

View workflow job for this annotation

GitHub Actions / Build, Test and Deploy .NET (7.0.x)

Non-nullable event 'OnAlert' must contain a non-null value when exiting constructor. Consider declaring the event as nullable.

public void Success(string message, bool keepAfterRouteChange = false, bool autoClose = true)
{
this.Alert(new AlertModel
{
Type = AlertType.Success,
Message = message,
KeepAfterRouteChange = keepAfterRouteChange,
AutoClose = autoClose
});
}

public void Error(string message, bool keepAfterRouteChange = false, bool autoClose = true)
{
this.Alert(new AlertModel
{
Type = AlertType.Error,
Message = message,
KeepAfterRouteChange = keepAfterRouteChange,
AutoClose = autoClose
});
}

public void Info(string message, bool keepAfterRouteChange = false, bool autoClose = true)
{
this.Alert(new AlertModel
{
Type = AlertType.Info,
Message = message,
KeepAfterRouteChange = keepAfterRouteChange,
AutoClose = autoClose
});
}

public void Warn(string message, bool keepAfterRouteChange = false, bool autoClose = true)
{
this.Alert(new AlertModel
{
Type = AlertType.Warning,
Message = message,
KeepAfterRouteChange = keepAfterRouteChange,
AutoClose = autoClose
});
}

public void Alert(AlertModel alert)
{
alert.Id = alert.Id ?? _defaultId;
this.OnAlert?.Invoke(alert);
}

public void Clear(string id = _defaultId)
{
this.OnAlert?.Invoke(new AlertModel { Id = id });
}
}
12 changes: 12 additions & 0 deletions src/Subjects/Presentation.Shared.Rcl/Alert/SimpleAlert.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@using Goodtocode.Common.Extensions;

<div hidden="@string.IsNullOrEmpty(Message)" class="alert alert-danger m-4" role="alert">@Message</div>

@code {
[Parameter]
public string Message { get; set; }

Check warning on line 7 in src/Subjects/Presentation.Shared.Rcl/Alert/SimpleAlert.razor

View workflow job for this annotation

GitHub Actions / Build, Test and Deploy .NET (7.0.x)

Non-nullable property 'Message' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

protected override async Task OnParametersSetAsync()

Check warning on line 9 in src/Subjects/Presentation.Shared.Rcl/Alert/SimpleAlert.razor

View workflow job for this annotation

GitHub Actions / Build, Test and Deploy .NET (7.0.x)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
}
}
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@using Goodtocode.Subjects.BlazorServer.Models;
@using Goodtocode.Subjects.Domain;
@using System.ComponentModel.DataAnnotations;
@using Goodtocode.Subjects.Rcl.Alert

@inject BusinessService Service

Expand All @@ -25,7 +26,7 @@
</div>
<button type="submit" class="btn btn-primary" @onclick="CreateBusineses">Create</button>
<ValidationSummary class="mt-3" />
<div hidden="@string.IsNullOrEmpty(alertMessage)" class="alert alert-danger" role="alert">@alertMessage</div>
<SimpleAlert Message="@alertMessage" />
</EditForm>

@code {
Expand Down
3 changes: 2 additions & 1 deletion src/Subjects/Presentation.Web.BlazorServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@
builder.Configuration["Subjects:Scope"])
);

builder.Services.AddSingleton<BusinessService>();
builder.Services.AddSingleton<PageHistoryState>();
builder.Services.AddScoped<IAlertService, AlertService>();
builder.Services.AddSingleton<BusinessService>();

var app = builder.Build();

Expand Down

0 comments on commit 96dd10d

Please sign in to comment.