29 changed files with 478 additions and 100 deletions
@ -1,8 +0,0 @@ |
|||||||
namespace Components.Feedback; |
|
||||||
|
|
||||||
public enum SeverityType { |
|
||||||
Warning, |
|
||||||
Information, |
|
||||||
Error, |
|
||||||
Success |
|
||||||
} |
|
||||||
@ -0,0 +1,114 @@ |
|||||||
|
@using Services |
||||||
|
@inject IToastService toastService |
||||||
|
|
||||||
|
@implements IDisposable |
||||||
|
|
||||||
|
@if (Toast == null) |
||||||
|
{ |
||||||
|
<div>Add toast object...</div> |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
<div class="toastContainer @Toast.SeverityType.ToLower() @FadeoutStyle"> |
||||||
|
<div class="toastTitle"> |
||||||
|
@Toast.Title |
||||||
|
</div> |
||||||
|
<div> |
||||||
|
@Toast.Message |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
} |
||||||
|
|
||||||
|
<style> |
||||||
|
.toastContainer { |
||||||
|
border: 4px solid; |
||||||
|
border-radius: 4px; |
||||||
|
padding: 16px; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-items: stretch; |
||||||
|
width: 100%; |
||||||
|
|
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
|
||||||
|
.fadeout { |
||||||
|
transition: opacity 3s ease-in; |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.toastContainer.@SeverityType.Warning.ToLower() { |
||||||
|
background-color: var(--severity-warning-color); |
||||||
|
border-color: var(--severity-warning-border-color); |
||||||
|
} |
||||||
|
|
||||||
|
.toastContainer.@SeverityType.Error.ToLower() { |
||||||
|
background-color: var(--severity-error-color); |
||||||
|
border-color: var(--severity-error-border-color); |
||||||
|
} |
||||||
|
|
||||||
|
.toastContainer.@SeverityType.Information.ToLower() { |
||||||
|
background-color: var(--severity-information-color); |
||||||
|
border-color: var(--severity-information-border-color); |
||||||
|
} |
||||||
|
|
||||||
|
.toastContainer.@SeverityType.Success.ToLower() { |
||||||
|
background-color: var(--severity-success-color); |
||||||
|
border-color: var(--severity-success-border-color); |
||||||
|
} |
||||||
|
|
||||||
|
.toastTitle { |
||||||
|
font-weight: 800; |
||||||
|
} |
||||||
|
|
||||||
|
</style> |
||||||
|
|
||||||
|
@code { |
||||||
|
[Parameter] |
||||||
|
public ToastModel? Toast { get; set; } = default!; |
||||||
|
|
||||||
|
private bool isFadingOut = false; |
||||||
|
|
||||||
|
private string FadeoutStyle => isFadingOut ? "fadeout" : ""; |
||||||
|
|
||||||
|
private int removalTime = 150000; |
||||||
|
private int fadeoutTime = 4000; |
||||||
|
|
||||||
|
//private int fade |
||||||
|
|
||||||
|
private Timer removalTimer = null!; |
||||||
|
private Timer fadeoutTimer = null!; |
||||||
|
|
||||||
|
protected override void OnInitialized() |
||||||
|
{ |
||||||
|
#if DEBUG |
||||||
|
removalTime = 5000; |
||||||
|
#endif |
||||||
|
|
||||||
|
removalTimer = new Timer(removalTime); |
||||||
|
removalTimer.Elapsed += OnRemoval!; |
||||||
|
removalTimer.Enabled = true; |
||||||
|
|
||||||
|
fadeoutTimer = new Timer(removalTime - fadeoutTime); |
||||||
|
fadeoutTimer.Elapsed += OnFadeout!; |
||||||
|
fadeoutTimer.Enabled = true; |
||||||
|
} |
||||||
|
|
||||||
|
void OnFadeout(object source, ElapsedEventArgs eventArgs) |
||||||
|
{ |
||||||
|
isFadingOut = true; |
||||||
|
|
||||||
|
StateHasChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
void OnRemoval(object source, ElapsedEventArgs eventArgs) |
||||||
|
{ |
||||||
|
toastService.RemoveToast(Toast!); |
||||||
|
} |
||||||
|
|
||||||
|
public void Dispose() |
||||||
|
{ |
||||||
|
removalTimer.Dispose(); |
||||||
|
fadeoutTimer.Dispose(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
<a href="@Href" class="codeLinkButton"> |
||||||
|
View on GitHub |
||||||
|
</a> |
||||||
|
|
||||||
|
<style> |
||||||
|
.codeLinkButton { |
||||||
|
color: white; |
||||||
|
background-color: var(--info); |
||||||
|
border: 1px solid var(--info-border); |
||||||
|
padding: 16px; |
||||||
|
border-radius: 3px; |
||||||
|
display: block; |
||||||
|
width: 180px; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
.codeLinkButton:hover { |
||||||
|
color: white; |
||||||
|
background-color: var(--info-hover); |
||||||
|
border: 2px solid var(--info-border-hover); |
||||||
|
} |
||||||
|
</style> |
||||||
|
|
||||||
|
@code { |
||||||
|
|
||||||
|
[Parameter] |
||||||
|
public string Href { get; set; } = ""; |
||||||
|
} |
||||||
Binary file not shown.
@ -1,9 +1,20 @@ |
|||||||
@page "/" |
@page "/" |
||||||
|
@using Microsoft.Extensions.Localization |
||||||
|
|
||||||
@layout PageLayout |
@layout PageLayout |
||||||
|
|
||||||
|
|
||||||
|
@inject IStringLocalizer<Localizations> Loc |
||||||
|
|
||||||
<DevOnlyComponent> |
<DevOnlyComponent> |
||||||
<DocumentationIndexPage></DocumentationIndexPage> |
<DocumentationIndexPage></DocumentationIndexPage> |
||||||
|
|
||||||
|
@Loc["Greeting"].Value |
||||||
|
@Loc["Greeting"] |
||||||
|
@Loc["Greeting"].Name |
||||||
|
@Loc["Greeting"].ResourceNotFound |
||||||
</DevOnlyComponent> |
</DevOnlyComponent> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<HomePage></HomePage> |
<HomePage></HomePage> |
||||||
@ -0,0 +1,54 @@ |
|||||||
|
//------------------------------------------------------------------------------ |
||||||
|
// <auto-generated> |
||||||
|
// This code was generated by a tool. |
||||||
|
// |
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if |
||||||
|
// the code is regenerated. |
||||||
|
// </auto-generated> |
||||||
|
//------------------------------------------------------------------------------ |
||||||
|
|
||||||
|
namespace IGP { |
||||||
|
using System; |
||||||
|
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] |
||||||
|
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()] |
||||||
|
internal class Localizations { |
||||||
|
|
||||||
|
private static System.Resources.ResourceManager resourceMan; |
||||||
|
|
||||||
|
private static System.Globalization.CultureInfo resourceCulture; |
||||||
|
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] |
||||||
|
internal Localizations() { |
||||||
|
} |
||||||
|
|
||||||
|
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] |
||||||
|
internal static System.Resources.ResourceManager ResourceManager { |
||||||
|
get { |
||||||
|
if (object.Equals(null, resourceMan)) { |
||||||
|
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("IGP.Localizations", typeof(Localizations).Assembly); |
||||||
|
resourceMan = temp; |
||||||
|
} |
||||||
|
return resourceMan; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] |
||||||
|
internal static System.Globalization.CultureInfo Culture { |
||||||
|
get { |
||||||
|
return resourceCulture; |
||||||
|
} |
||||||
|
set { |
||||||
|
resourceCulture = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal static string Greeting { |
||||||
|
get { |
||||||
|
return ResourceManager.GetString("Greeting", resourceCulture); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
|
||||||
|
<root> |
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> |
||||||
|
<xsd:element name="root" msdata:IsDataSet="true"> |
||||||
|
|
||||||
|
</xsd:element> |
||||||
|
</xsd:schema> |
||||||
|
<resheader name="resmimetype"> |
||||||
|
<value>text/microsoft-resx</value> |
||||||
|
</resheader> |
||||||
|
<resheader name="version"> |
||||||
|
<value>1.3</value> |
||||||
|
</resheader> |
||||||
|
<resheader name="reader"> |
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
||||||
|
</resheader> |
||||||
|
<resheader name="writer"> |
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
||||||
|
</resheader> |
||||||
|
<data name="Greeting" xml:space="preserve"> |
||||||
|
<value>Hello</value> |
||||||
|
</data> |
||||||
|
</root> |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
@implements IDisposable; |
||||||
|
|
||||||
|
@inject IToastService toastService |
||||||
|
|
||||||
|
@if (toastService.HasToasts()) |
||||||
|
{ |
||||||
|
<div class="toastsContainer"> |
||||||
|
|
||||||
|
@foreach (var toast in toastService.GetToasts()) |
||||||
|
{ |
||||||
|
<ToastComponent Toast="toast"/> |
||||||
|
} |
||||||
|
</div> |
||||||
|
} |
||||||
|
|
||||||
|
<style> |
||||||
|
.toastsContainer { |
||||||
|
position: fixed; |
||||||
|
top: 64px; |
||||||
|
right: 64px; |
||||||
|
} |
||||||
|
</style> |
||||||
|
|
||||||
|
|
||||||
|
@code { |
||||||
|
|
||||||
|
protected override void OnInitialized() |
||||||
|
{ |
||||||
|
toastService.Subscribe(OnUpdate); |
||||||
|
} |
||||||
|
|
||||||
|
public void Dispose() |
||||||
|
{ |
||||||
|
toastService.Unsubscribe(OnUpdate); |
||||||
|
} |
||||||
|
|
||||||
|
void OnUpdate() |
||||||
|
{ |
||||||
|
StateHasChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,9 @@ |
|||||||
|
namespace Model.Feedback; |
||||||
|
|
||||||
|
public class SeverityType |
||||||
|
{ |
||||||
|
public static string Warning = "Warning"; |
||||||
|
public static string Information = "Information"; |
||||||
|
public static string Error = "Error"; |
||||||
|
public static string Success = "Success"; |
||||||
|
} |
||||||
@ -0,0 +1,8 @@ |
|||||||
|
namespace Model.Feedback; |
||||||
|
|
||||||
|
public class ToastModel |
||||||
|
{ |
||||||
|
public string Title { get; set; } = "addTitle"; |
||||||
|
public string Message { get; set; } = "addMessage"; |
||||||
|
public string SeverityType { get; set; } = "addType"; |
||||||
|
} |
||||||
@ -0,0 +1,64 @@ |
|||||||
|
using Model.Feedback; |
||||||
|
|
||||||
|
namespace Services.Website; |
||||||
|
|
||||||
|
public class ToastService : IToastService |
||||||
|
{ |
||||||
|
private readonly List<ToastModel> toasts = new(); |
||||||
|
|
||||||
|
private event Action OnChange = null!; |
||||||
|
|
||||||
|
#if DEBUG |
||||||
|
public ToastService() |
||||||
|
{ |
||||||
|
toasts.Add(new ToastModel(){Message = "Example message", SeverityType = SeverityType.Error, Title = "Example Error"}); |
||||||
|
toasts.Add(new ToastModel(){Message = "Example message", SeverityType = SeverityType.Information, Title = "Example Information"}); |
||||||
|
toasts.Add(new ToastModel(){Message = "Example message", SeverityType = SeverityType.Success, Title = "Example Success"}); |
||||||
|
toasts.Add(new ToastModel(){Message = "Example message", SeverityType = SeverityType.Warning, Title = "Example Warning"}); |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
private void NotifyDataChanged() { |
||||||
|
OnChange(); |
||||||
|
} |
||||||
|
|
||||||
|
public void Subscribe(Action action) { |
||||||
|
OnChange += action; |
||||||
|
} |
||||||
|
|
||||||
|
public void Unsubscribe(Action action) { |
||||||
|
OnChange += action; |
||||||
|
} |
||||||
|
|
||||||
|
public void AddToast(ToastModel toast) |
||||||
|
{ |
||||||
|
toasts.Add(toast); |
||||||
|
NotifyDataChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
public void RemoveToast(ToastModel toast) |
||||||
|
{ |
||||||
|
toasts.Remove(toast); |
||||||
|
NotifyDataChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
public bool HasToasts() |
||||||
|
{ |
||||||
|
return toasts.Count > 0; |
||||||
|
} |
||||||
|
|
||||||
|
public List<ToastModel> GetToasts() |
||||||
|
{ |
||||||
|
return toasts; |
||||||
|
} |
||||||
|
|
||||||
|
public void ClearAllToasts() |
||||||
|
{ |
||||||
|
toasts.Clear(); |
||||||
|
NotifyDataChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in new issue