Merge branch 'release/UpdateLoadingDataComp01'

This commit is contained in:
Samuele Locatelli
2023-07-29 12:05:56 +02:00
11 changed files with 772 additions and 5 deletions
@@ -0,0 +1,14 @@
@page "/TestLoading"
<h3>TestLoading</h3>
<div>
<label class="form-label">Tempo sim</label>
<input css="form-control" @bind="@expTime" type="number" />
</div>
<div>
<label class="form-label">Num steps</label>
<input css="form-control" @bind="@numSteps" type="number" />
</div>
<button class="btn btn-success" @onclick="StartLongTimer">Start</button>
<ProgressDisplay RefreshInterval="100" Title="@titleMsg" MaxVal="@maxVal" CurrVal="@currVal" NextVal="@nextVal" ExpTimeMSec="@expTimeMSec" DisplaySize="ProgressDisplay.ModalSize.Medium" ModalCss="card alert-primary"></ProgressDisplay>
@@ -0,0 +1,58 @@
namespace EgwCoreLib.BlazorTest.Pages
{
public partial class TestLoading
{
#region Protected Properties
protected double expTime { get; set; } = 6;
protected int numSteps { get; set; } = 4;
#endregion Protected Properties
#region Protected Methods
protected async Task StartLongTimer()
{
double stdWait = expTime / numSteps;
int nextWait = 1000;
int stepVal = maxVal / numSteps;
// imposto i valori x progress..
maxVal = 100;
expTimeMSec = (int)(stdWait * 1000);
//nextVal = stepVal;
//currVal = 0;
for (int currStep = 1; currStep <= numSteps; currStep++)
{
// aggiorno valori
currVal = (currStep - 1) * stepVal;
nextVal = currStep * stepVal;
// se max mi fermo...
if (nextVal > maxVal)
{
nextVal = maxVal;
}
await InvokeAsync(StateHasChanged);
// simulo ritardo importante (da 2 a 3 volte
nextWait = (int)(rnd.Next(2000, 3000) * stdWait);
// attendo step successivi...
await Task.Delay(nextWait);
}
await Task.Delay(1);
currVal = maxVal;
await InvokeAsync(StateHasChanged);
}
#endregion Protected Methods
#region Private Fields
private int currVal = 100;
private int expTimeMSec = 10000;
private int maxVal = 100;
private int nextVal = 100;
private Random rnd = new Random();
private string titleMsg = "SIM Progress";
#endregion Private Fields
}
}
@@ -17,3 +17,37 @@ else
</div>
}
<hr />
<div class="row">
<div class="col-4">
<LoadingData DisplaySize="LoadingData.CtrlSize.Small" DisplayMode="LoadingData.SpinMode.Normal"></LoadingData>
</div>
<div class="col-4">
<LoadingData DisplaySize="LoadingData.CtrlSize.Small" DisplayMode="LoadingData.SpinMode.Growl"></LoadingData>
</div>
<div class="col-4">
<LoadingData DisplaySize="LoadingData.CtrlSize.Small" DisplayMode="LoadingData.SpinMode.BounceLine"></LoadingData>
</div>
</div>
<div class="row">
<div class="col-4">
<LoadingData DisplaySize="LoadingData.CtrlSize.Normal" DisplayMode="LoadingData.SpinMode.Normal"></LoadingData>
</div>
<div class="col-4">
<LoadingData DisplaySize="LoadingData.CtrlSize.Normal" DisplayMode="LoadingData.SpinMode.Growl"></LoadingData>
</div>
<div class="col-4">
<LoadingData DisplaySize="LoadingData.CtrlSize.Normal" DisplayMode="LoadingData.SpinMode.BounceLine"></LoadingData>
</div>
</div>
<div class="row">
<div class="col-4">
<LoadingData DisplaySize="LoadingData.CtrlSize.Large" DisplayMode="LoadingData.SpinMode.Normal"></LoadingData>
</div>
<div class="col-4">
<LoadingData DisplaySize="LoadingData.CtrlSize.Large" DisplayMode="LoadingData.SpinMode.Growl"></LoadingData>
</div>
<div class="col-4">
<LoadingData DisplaySize="LoadingData.CtrlSize.Large" DisplayMode="LoadingData.SpinMode.BounceLine"></LoadingData>
</div>
</div>
+83 -5
View File
@@ -1,6 +1,84 @@
<div class="row p-3 m-2">
<div class="col-12 text-center mt-5 py-5 alert alert-primary">
<h3>loading data</h3>
<i class="fas fa-spinner fa-spin fa-5x"></i>
@if (DisplaySize == CtrlSize.Small)
{
<div class="@DisplayCss p-1 m-1">
<div class="w-100 d-flex justify-content-around text-center my-1 py-1">
<div class="d-flex text-center">
<div class="mx-1 text-nowrap">
<b>loading data</b>
</div>
@if (DisplayMode == SpinMode.Normal)
{
<i class="fas fa-spinner fa-spin"></i>
}
else if (DisplayMode == SpinMode.Growl)
{
<div class="spinner-grow" role="status" style="width: 1.3rem; height: 1.3rem;">
<span class="visually-hidden">Loading...</span>
</div>
}
else
{
<div class="modalOrd-content-small text-center">
<div class="loader">
<span class="load"></span>
</div>
</div>
}
</div>
</div>
</div>
</div>
}
else if (DisplaySize == CtrlSize.Normal)
{
<div class="@DisplayCss d-flex justify-content-around p-1 m-1">
<div class="w-100 text-center my-1 py-1">
<h3>loading data</h3>
@if (DisplayMode == SpinMode.Normal)
{
<i class="fas fa-spinner fa-spin fa-3x"></i>
}
else if (DisplayMode == SpinMode.Growl)
{
<div class="spinner-grow" role="status" style="width: 3rem; height: 3rem;">
<span class="visually-hidden">Loading...</span>
</div>
}
else
{
<div class="modalOrd-content text-center">
<div class="loader">
<span class="load"></span>
</div>
</div>
}
</div>
</div>
}
else if (DisplaySize == CtrlSize.Large)
{
<div class="row p-1 m-1">
<div class="@DisplayCss my-3 py-3">
<div class="col-12 text-center">
<h1>loading data</h1>
@if (DisplayMode == SpinMode.Normal)
{
<i class="fas fa-spinner fa-spin fa-5x"></i>
}
else if (DisplayMode == SpinMode.Growl)
{
<div class="spinner-grow" role="status" style="width: 5rem; height: 5rem;">
<span class="visually-hidden">Loading...</span>
</div>
}
else
{
<div class="modalOrd-content-large text-center">
<div class="loader">
<span class="load"></span>
</div>
</div>
}
</div>
</div>
</div>
}
+50
View File
@@ -0,0 +1,50 @@
using Microsoft.AspNetCore.Components;
namespace EgwCoreLib.Razor
{
public partial class LoadingData
{
#region Public Enums
public enum CtrlSize
{
Normal,
Small,
Large
}
public enum SpinMode
{
Normal,
Growl,
BounceLine
}
#endregion Public Enums
#region Public Properties
/// <summary>
/// Modalità display principale
/// default: alert alert-primary
/// </summary>
[Parameter]
public string DisplayCss { get; set; } = "alert alert-primary";
/// <summary>
/// Modalità animazione
/// default: Normal
/// </summary>
[Parameter]
public SpinMode DisplayMode { get; set; } = SpinMode.Normal;
/// <summary>
/// Dimensione display
/// default: Normal
/// </summary>
[Parameter]
public CtrlSize DisplaySize { get; set; } = CtrlSize.Normal;
#endregion Public Properties
}
}
+126
View File
@@ -0,0 +1,126 @@
.modalOrd {
position: relative;
z-index: 9999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: #000000;
background-color: rgba(0, 0, 0, 0.6);
}
.loader {
width: 5rem;
position: relative;
}
.loader-text {
position: relative;
top: 0;
padding: 0;
margin: 0;
color: #C8B6FF;
animation: text_713 3.5s ease both infinite;
font-size: 0.8rem;
letter-spacing: 1px;
}
.load {
background-color: #9A79FF;
border-radius: 3rem;
display: block;
height: 1rem;
width: 1rem;
bottom: 0;
position: relative;
transform: translateX(64px);
animation: loading_713 3.5s ease both infinite;
}
.load::before {
position: relative;
content: "";
width: 100%;
height: 100%;
background-color: #D1C2FF;
border-radius: inherit;
animation: loading2_713 3.5s ease both infinite;
}
@keyframes text_713 {
0% {
letter-spacing: 1px;
transform: translateX(0px);
}
40% {
letter-spacing: 2px;
transform: translateX(26px);
}
80% {
letter-spacing: 1px;
transform: translateX(32px);
}
90% {
letter-spacing: 2px;
transform: translateX(0px);
}
100% {
letter-spacing: 1px;
transform: translateX(0px);
}
}
@keyframes loading_713 {
0% {
width: 16px;
transform: translateX(0px);
}
40% {
width: 100%;
transform: translateX(0px);
}
80% {
width: 16px;
transform: translateX(64px);
}
90% {
width: 100%;
transform: translateX(0px);
}
100% {
width: 16px;
transform: translateX(0px);
}
}
@keyframes loading2_713 {
0% {
transform: translateX(0px);
width: 16px;
}
40% {
transform: translateX(0%);
width: 80%;
}
80% {
width: 100%;
transform: translateX(0px);
}
90% {
width: 80%;
transform: translateX(15px);
}
100% {
transform: translateX(0px);
width: 16px;
}
}
/* Modal Content/Box */
.modalOrd-content-small {
margin: 0.4rem auto;
width: 50%;
}
.modalOrd-content {
margin: 1.4rem auto;
padding-left: 20%;
width: 50%;
}
.modalOrd-content-large {
margin: 2.4rem auto;
padding-left: 20%;
width: 50%;
}
+147
View File
@@ -0,0 +1,147 @@
.modalOrd {
position: relative;
z-index: 9999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.6);
}
.loader {
width: 5rem;
position: relative;
}
.loader-text {
position: relative;
top: 0;
padding: 0;
margin: 0;
color: #C8B6FF;
animation: text_713 3.5s ease both infinite;
font-size: .8rem;
letter-spacing: 1px;
}
.load {
background-color: #9A79FF;
border-radius: 3rem;
display: block;
height: 1rem;
width: 1rem;
bottom: 0;
position: relative;
transform: translateX(64px);
animation: loading_713 3.5s ease both infinite;
}
.load::before {
position: relative;
content: "";
width: 100%;
height: 100%;
background-color: #D1C2FF;
border-radius: inherit;
animation: loading2_713 3.5s ease both infinite;
}
@keyframes text_713 {
0% {
letter-spacing: 1px;
transform: translateX(0px);
}
40% {
letter-spacing: 2px;
transform: translateX(26px);
}
80% {
letter-spacing: 1px;
transform: translateX(32px);
}
90% {
letter-spacing: 2px;
transform: translateX(0px);
}
100% {
letter-spacing: 1px;
transform: translateX(0px);
}
}
@keyframes loading_713 {
0% {
width: 16px;
transform: translateX(0px);
}
40% {
width: 100%;
transform: translateX(0px);
}
80% {
width: 16px;
transform: translateX(64px);
}
90% {
width: 100%;
transform: translateX(0px);
}
100% {
width: 16px;
transform: translateX(0px);
}
}
@keyframes loading2_713 {
0% {
transform: translateX(0px);
width: 16px;
}
40% {
transform: translateX(0%);
width: 80%;
}
80% {
width: 100%;
transform: translateX(0px);
}
90% {
width: 80%;
transform: translateX(15px);
}
100% {
transform: translateX(0px);
width: 16px;
}
}
/* Modal Content/Box */
.modalOrd-content-small {
margin: 0.4rem auto;
width: 50%;
}
.modalOrd-content {
margin: 1.4rem auto;
padding-left: 20%;
width: 50%;
}
.modalOrd-content-large {
margin: 2.4rem auto;
padding-left: 20%;
width: 50%;
}
+1
View File
@@ -0,0 +1 @@
.modalOrd{position:relative;z-index:9999;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,.6);}.loader{width:5rem;position:relative;}.loader-text{position:relative;top:0;padding:0;margin:0;color:#c8b6ff;animation:text_713 3.5s ease both infinite;font-size:.8rem;letter-spacing:1px;}.load{background-color:#9a79ff;border-radius:3rem;display:block;height:1rem;width:1rem;bottom:0;position:relative;transform:translateX(64px);animation:loading_713 3.5s ease both infinite;}.load::before{position:relative;content:"";width:100%;height:100%;background-color:#d1c2ff;border-radius:inherit;animation:loading2_713 3.5s ease both infinite;}@keyframes text_713{0%{letter-spacing:1px;transform:translateX(0);}40%{letter-spacing:2px;transform:translateX(26px);}80%{letter-spacing:1px;transform:translateX(32px);}90%{letter-spacing:2px;transform:translateX(0);}100%{letter-spacing:1px;transform:translateX(0);}}@keyframes loading_713{0%{width:16px;transform:translateX(0);}40%{width:100%;transform:translateX(0);}80%{width:16px;transform:translateX(64px);}90%{width:100%;transform:translateX(0);}100%{width:16px;transform:translateX(0);}}@keyframes loading2_713{0%{transform:translateX(0);width:16px;}40%{transform:translateX(0%);width:80%;}80%{width:100%;transform:translateX(0);}90%{width:80%;transform:translateX(15px);}100%{transform:translateX(0);width:16px;}}.modalOrd-content-small{margin:.4rem auto;width:50%;}.modalOrd-content{margin:1.4rem auto;padding-left:20%;width:50%;}.modalOrd-content-large{margin:2.4rem auto;padding-left:20%;width:50%;}
+32
View File
@@ -0,0 +1,32 @@
@if (isLoading)
{
<dialog class="modal fade show" tabindex="-1" style="display:block; background-color: rgba(10,10,10,.6);" aria-modal="true" role="dialog">
<div class="@modalDialogCss rounded shadow">
<div class="modal-content">
<div class="@ModalCss text-center">
<div class="card-header">
@if (!string.IsNullOrEmpty(Title))
{
<b>@Title</b>
}
</div>
<div class="card-body p-4 bg-light text-dark">
@if (ShowPercent)
{
<div class="d-flex justify-content-around">
<div>
@displayMsg
</div>
</div>
}
<div class="w-100">
<div class="progress">
<div class="@ProgressCss" style="width: @currWidth"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</dialog>
}
+223
View File
@@ -0,0 +1,223 @@
using Microsoft.AspNetCore.Components;
namespace EgwCoreLib.Razor
{
public partial class ProgressDisplay : IDisposable
{
#region Public Enums
public enum ModalSize
{
Small,
Medium,
Large
}
#endregion Public Enums
#region Public Properties
/// <summary>
/// Valore corrente
/// </summary>
[Parameter]
public double CurrVal
{
get => actVal;
set
{
actVal = value;
startVal = value;
isLoading = actVal < MaxVal;
}
}
/// <summary>
/// Dimensioni attese modale
/// default: ModalSize.Medium
/// </summary>
[Parameter]
public ModalSize DisplaySize { get; set; } = ModalSize.Medium;
/// <summary>
/// Tempo atteso per prossimo step
/// default: 10000
/// </summary>
[Parameter]
public int ExpTimeMSec { get; set; } = 10000;
/// <summary>
/// Valore massimo ammesso
/// default: 100
/// </summary>
[Parameter]
public double MaxVal { get; set; } = 100;
/// <summary>
/// Style modale
/// default: card
/// alternative: card alert-primary
/// </summary>
[Parameter]
public string ModalCss { get; set; } = "card";
/// <summary>
/// Prossimo valore ammesso (fino al max)
/// default: 100
/// </summary>
[Parameter]
public double NextVal { get; set; } = 100;
/// <summary>
/// Style progressbar
/// default: progress-bar progress-bar-striped progress-bar-animated
/// </summary>
[Parameter]
public string ProgressCss { get; set; } = "progress-bar progress-bar-striped progress-bar-animated";
/// <summary>
/// Intervallo interno per refresh percentuale avanzamento
/// default: 100ms
/// </summary>
[Parameter]
public int RefreshInterval { get; set; } = 100;
/// <summary>
/// Indica se mostrare la percentuale vanzamento
/// default: true
/// </summary>
[Parameter]
public bool ShowPercent { get; set; } = true;
/// <summary>
/// Numero di secondi prima (rispetto valore ExpTimeMsec) da cui iniziare rallentamento
/// </summary>
[Parameter]
public int SlowWindowMSec { get; set; } = 3000;
//Titolo da mostrare (se "" NON lo mostra)
[Parameter]
public string Title { get; set; } = "Progress";
#endregion Public Properties
#region Public Methods
public void Dispose()
{
uiTimer?.Dispose();
}
#endregion Public Methods
#region Protected Properties
protected string modalDialogCss
{
get
{
string answ = "modal-dialog";
switch (DisplaySize)
{
case ModalSize.Small:
answ = "modal-dialog modal-sm";
break;
case ModalSize.Large:
answ = "modal-dialog modal-xl";
break;
case ModalSize.Medium:
default:
break;
}
return answ;
}
}
#endregion Protected Properties
#region Protected Methods
protected override async Task OnParametersSetAsync()
{
// salvo valori aggiornamento...
if (ExpTimeMSec > 0)
{
lastUpdate = DateTime.Now;
nextUpdate = lastUpdate.AddMilliseconds(ExpTimeMSec);
await RefreshDisplay();
}
if (isLoading)
{
uiTimer?.Dispose();
uiTimer = new PeriodicTimer(TimeSpan.FromMilliseconds(RefreshInterval));
RunTimer();
}
else
{
uiTimer = null;
}
}
#endregion Protected Methods
#region Private Fields
private PeriodicTimer? uiTimer = null;
#endregion Private Fields
#region Private Properties
private double actVal { get; set; } = 100;
private string currWidth { get; set; } = "";
private string displayMsg { get; set; } = "Loading...";
private bool isLoading { get; set; } = false;
private DateTime lastUpdate { get; set; } = DateTime.Now.AddMinutes(-1);
private DateTime nextUpdate { get; set; } = DateTime.Now;
private double startVal { get; set; } = 100;
#endregion Private Properties
#region Private Methods
private async Task RefreshDisplay()
{
currWidth = $"{(double)actVal / MaxVal:P0}";
if (ShowPercent)
{
displayMsg = $"{actVal / MaxVal:P2}";
}
await InvokeAsync(StateHasChanged);
}
private async void RunTimer()
{
while (uiTimer != null && await uiTimer.WaitForNextTickAsync())
{
if (isLoading)
{
DateTime adesso = DateTime.Now;
if (nextUpdate <= adesso.AddMilliseconds(SlowWindowMSec))
{
nextUpdate = adesso.AddMilliseconds(RefreshInterval);
}
// calcolo delta ms...
var numMs = adesso.Subtract(lastUpdate).TotalMilliseconds;
var denMs = nextUpdate.Subtract(lastUpdate).TotalMilliseconds;
denMs = denMs > 0 ? denMs : 1;
// aggiorno display...
actVal = startVal + (NextVal - startVal) * (numMs / denMs);
await RefreshDisplay();
}
}
}
#endregion Private Methods
}
}
+4
View File
@@ -22,5 +22,9 @@
{
"outputFile": "CalWeekColumn.razor.css",
"inputFile": "CalWeekColumn.razor.less"
},
{
"outputFile": "LoadingData.razor.css",
"inputFile": "LoadingData.razor.less"
}
]