Aggiunta planner vuoto

This commit is contained in:
Samuele Locatelli
2026-01-14 17:20:53 +01:00
parent 716f091a1c
commit b8aa2312fa
18 changed files with 617 additions and 13 deletions
+141
View File
@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EgwCoreLib.Lux.Core.Generic
{
public class EventDto
{
public string CodTipo { get; set; } = "";
public int IdxEv { get; set; } = 0;
public int IdxDipendente { get; set; } = 0;
public string CognomeNome { get; set; } = "";
public string Abbrev { get; set; } = "";
public string Titolo { get; set; } = "";
public string Descrizione { get; set; } = "";
public string Tooltip { get; set; } = "";
public DateTime DtStart { get; set; } = DateTime.Today.AddHours(9);
public DateTime DtEnd { get; set; } = DateTime.Today.AddHours(17);
public string Note { get; set; } = "";
public bool Conf { get; set; } = false;
public bool IsDraggable { get; set; } = false;
public bool IsCompany { get; set; } = false;
public EventDto Clone()
{
return new EventDto()
{
CodTipo = this.CodTipo,
IdxEv = this.IdxEv,
IdxDipendente = this.IdxDipendente,
CognomeNome = this.CognomeNome,
Abbrev = this.Abbrev,
Titolo = this.Titolo,
Descrizione = this.Descrizione,
Tooltip = this.Tooltip,
DtStart = this.DtStart,
DtEnd = this.DtEnd,
Note = this.Note,
Conf = this.Conf,
IsDraggable = this.IsDraggable,
IsCompany = this.IsCompany
};
}
public string Durata
{
get
{
string answ = "-";
var durata = DtEnd.Subtract(DtStart);
if (CodTipo == "FER")
{
answ = $"{durata.TotalDays + 1:N0}gg";
}
else
{
answ = $"{durata.TotalHours:N1}h";
}
return answ;
}
}
public static string DateForm(string Tipo, DateTime DtEvent)
{
return (Tipo == "PERM" || Tipo == "104") ? $"{DtEvent:HH:mm}" : $"{DtEvent:ddd yyyy-MM-dd}";
}
public string Color
{
get => calcColor(CodTipo, Conf, IsCompany);
}
public string? ForeColor
{
get => calcText(CodTipo, Conf, IsCompany);
}
private string calcColor(string codGiust, bool conf, bool isComp)
{
string answ = "#EDEDED";
switch (codGiust)
{
case "FER":
answ = isComp ? "#EEDD11" : conf ? "#11CD44" : "#AAFFCD";
break;
case "FEST":
answ = "#DD0033";
break;
case "104":
answ = conf ? "#DE00AB" : "#FFAACD";
break;
case "MAL":
answ = conf ? "#000" : "#696969";
break;
case "PERM":
answ = conf ? "#9966DE" : "#CDAAFF";
break;
default:
break;
}
return answ;
}
private string calcText(string codGiust, bool conf, bool isComp)
{
string answ = "#EDEDED";
switch (codGiust)
{
case "FER":
answ = isComp ? "#000000" : conf ? "#FFFFFF" : "#000000";
break;
case "FEST":
answ = "#EEDD11";
break;
case "104":
answ = conf ? "#DEDEDE" : "#000000";
break;
case "MAL":
answ = conf ? "#DEDEDE" : "#ABABAB";
break;
case "PERM":
answ = conf ? "#DEDEDE" : "#000000";
break;
default:
break;
}
return answ;
}
}
}
+2 -1
View File
@@ -34,7 +34,8 @@ namespace EgwCoreLib.Lux.Data.Services
public enum QueueType
{
waiting,
running
running,
done
}
#endregion Public Enums
+1 -1
View File
@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>0.9.2601.1415</Version>
<Version>0.9.2601.1417</Version>
</PropertyGroup>
<ItemGroup>
+4
View File
@@ -3,6 +3,7 @@
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Lux UI Interface" />
<meta name="author" content="EgalWare" />
@@ -13,6 +14,7 @@
<link rel="stylesheet" href="lib/bootstrap-icons/font/bootstrap-icons.min.css" />
<link rel="stylesheet" href="css/site.min.css" />
<link rel="stylesheet" href="css/fonts.min.css" />
<link rel="stylesheet" href="css/BlazorCal.min.css" />
<link rel="stylesheet" href="css/textures.min.css" />
@* <link rel="stylesheet" href="app.css" /> *@
@@ -21,6 +23,7 @@
<link rel="manifest" href="manifest.json" />
@* <HeadOutlet /> *@
<HeadOutlet @rendermode="@(new InteractiveServerRenderMode(prerender: false))" />
<RadzenTheme Theme="material" @rendermode="@(new InteractiveServerRenderMode(prerender: false))" />
</head>
<body>
@@ -45,6 +48,7 @@
}
});
</script> *@
<script src="_content/Radzen.Blazor/Radzen.Blazor.js?v=@(typeof(Radzen.Colors).Assembly.GetName().Version)"></script>
<script type="text/javascript" src="lib/chart.js/chart.umd.js"></script>
<script type="text/javascript" src="lib/moment.js/moment.min.js"></script>
<script type="text/javascript" src="lib/chartjs-adapter-moment/chartjs-adapter-moment.js"></script>
@@ -0,0 +1,30 @@
@using EgwCoreLib.Lux.Core.Generic
<div style="@schedHeight">
<RadzenScheduler @ref=@scheduler style="height: 100%;" Culture=@(new System.Globalization.CultureInfo("it-IT"))
TItem="EventDto" Data="@EvDtoFilt" SelectedIndex="@selectedIndex" Date="@SelDate"
StartProperty="DtStart" EndProperty="DtEnd" TextProperty="CodTipo"
SlotRender=@OnSlotRender SlotSelect=@OnSlotSelect TodayText="Oggi"
AppointmentSelect=@OnAppointmentSelect AppointmentRender=@OnAppointmentRender
LoadData=OnLoadData>
<Template Context="EvDTO">
<div>
<strong>@EvDTO.CodTipo</strong> | @EvDTO.Abbrev
</div>
<small>
@if (EvDTO.CodTipo == "PERM" || EvDTO.CodTipo == "104")
{
@($"{EventDto.DateForm(EvDTO.CodTipo, EvDTO.DtStart)} --> {EventDto.DateForm(EvDTO.CodTipo, EvDTO.DtEnd)}")
}
</small>
</Template>
<ChildContent>
<RadzenDayView />
<RadzenWeekView />
<RadzenMonthView MaxAppointmentsInSlot="4" />
<RadzenYearPlannerView StartMonth="Month.January" MaxAppointmentsInSlot="3" />
<RadzenYearView StartMonth="Month.January" />
</ChildContent>
</RadzenScheduler>
</div>
@@ -0,0 +1,194 @@
using EgwCoreLib.Lux.Core.Generic;
using EgwCoreLib.Utils;
using Microsoft.AspNetCore.Components;
using Radzen;
using Radzen.Blazor;
using static WebWindowComplex.TableComp;
namespace Lux.UI.Components.Compo.Planner
{
public partial class CalendarPlanner
{
#region Public Properties
[Parameter]
public DtUtils.Periodo CurrPeriodo { get; set; } = null!;
[Parameter]
public EventCallback<DateTime> EC_DtReq { get; set; }
[Parameter]
public List<EventDto> EvDtoList { get; set; } = null!;
[Parameter]
public DateTime firstDate { get; set; } = new DateTime(DateTime.Today.Year, 1, 1);
[Parameter]
public DateTime maxDate { get; set; } = new DateTime(DateTime.Today.Year + 1, 1, 1);
[Parameter]
public DateTime minDate { get; set; } = new DateTime(DateTime.Today.Year, 1, 1);
[Parameter]
public int MonthDispl
{
get => cMonth;
set => cMonth = value;
}
[Parameter]
public EventCallback<int> MonthReq { get; set; }
[Parameter]
public bool ShowNeedConf { get; set; } = false;
#endregion Public Properties
#region Protected Fields
protected RadzenScheduler<EventDto> scheduler = null!;
#endregion Protected Fields
#region Protected Properties
[Inject]
protected DialogService DialogService { get; set; } = null!;
#endregion Protected Properties
#region Private Fields
private int selectedIndex = 2;
#endregion Private Fields
#region Private Properties
private int cMonth { get; set; } = 3;
private List<EventDto> EvDtoFilt { get; set; } = new List<EventDto>();
private string schedHeight { get; set; } = "height: 50rem;";
private DateTime SelDate { get; set; } = DateTime.Today;
#endregion Private Properties
#region Private Methods
/// <summary>
/// Sistemazione colore sfonto di ogni evento mostrato
/// </summary>
/// <param name="args"></param>
private void OnAppointmentRender(SchedulerAppointmentRenderEventArgs<EventDto> args)
{
// Never call StateHasChanged in AppointmentRender - would lead to infinite loop
args.Attributes["style"] = $"background: {args.Data.Color}; color: {args.Data.ForeColor};";
}
/// <summary>
/// Selezione evento per display
/// </summary>
/// <param name="selEv"></param>
/// <returns></returns>
private async Task OnAppointmentSelect(SchedulerAppointmentSelectEventArgs<EventDto> selEv)
{
var copy = selEv.Data.Clone();
await Task.Delay(1);
var data = await DialogService.OpenAsync<TaskDetail>("", new Dictionary<string, object> { { "ThisTask", copy } });
}
private string currView { get; set; } = "";
/// <summary>
/// Gestione richeista caricamento dati dal controllo x avere nuovo set da mostrare
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private async Task OnLoadData(SchedulerLoadDataEventArgs args)
{
await Task.Delay(1);
currView = scheduler.SelectedView.Text.ToLowerInvariant();
DateTime dtMid = args.Start.AddDays(args.End.Subtract(args.Start).TotalDays / 2);
// controllo se sia cambiata data anno precedente...
if (dtMid.Year != SelDate.Year)
{
SelDate = dtMid;
await EC_DtReq.InvokeAsync(SelDate);
}
// di almeno 1 anno in questo caso...
else if (SelDate != scheduler.Date || Math.Abs(scheduler.Date.Subtract(args.Start).TotalDays) > 365)
{
SelDate = args.Start.AddDays(4);
await EC_DtReq.InvokeAsync(SelDate);
}
//schedHeight = (currView == "year" || currView == "planner") ? "height: 60rem;" : "height: 50rem;";
// // Get the appointments for between the Start and End
// data = await MyAppointmentService.GetData(selEv.Start, selEv.End);
}
private void OnSlotRender(SchedulerSlotRenderEventArgs args)
{
// Highlight today in month view
if (args.View.Text == "Month" && args.Start.Date == DateTime.Today)
{
args.Attributes["style"] = "background: var(--rz-scheduler-highlight-background-color, rgba(255,220,40,.2));";
}
// Highlight working hours (9-18)
if ((args.View.Text == "Week" || args.View.Text == "Day") && args.Start.Hour > 8 && args.Start.Hour < 19)
{
args.Attributes["style"] = "background: var(--rz-scheduler-highlight-background-color, rgba(255,220,40,.2));";
}
}
private async Task OnSlotSelect(SchedulerSlotSelectEventArgs args)
{
int prevIdx = selectedIndex;
await Task.Delay(1);
// verifico indice corretto della vista...
switch (args.View.Text)
{
case "Day":
selectedIndex = 0;
break;
case "Week":
selectedIndex = 1;
break;
case "Month":
selectedIndex = 2;
break;
case "Planner":
selectedIndex = 3;
break;
case "Year":
selectedIndex = 4;
break;
default:
break;
}
if (prevIdx != selectedIndex)
{
await scheduler.Reload();
}
await Task.Delay(1);
if (selectedIndex > 0)
{
selectedIndex--;
}
// imposto al data selezionata
SelDate = args.Start;
// riporto data al controller parent...
await EC_DtReq.InvokeAsync(SelDate);
}
#endregion Private Methods
}
}
@@ -0,0 +1,82 @@
@using EgwCoreLib.Lux.Core.Generic
@inject DialogService DialogService
<div class="card">
<div class="card-header" style="@($"background: {model.Color}; color: {model.ForeColor};")">
<div class="d-flex justify-content-between">
<div class="px-0">Tipologia:</div>
<div class="px-0"><b>@model.CodTipo</b></div>
</div>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">
<div class="d-flex justify-content-between">
<div class="px-0">Nome:</div>
@if (@model.IdxDipendente > 0)
{
<div class="px-0"><b>@model.Abbrev</b></div>
}
else
{
<div class="px-0"><b>@model.Descrizione</b></div>
}
</div>
</li>
@if (model.DtEnd.Subtract(model.DtStart).TotalDays < 1 && model.CodTipo != "FER")
{
<li class="list-group-item">
<div class="d-flex justify-content-between">
<div class="px-0">Data:</div>
<div class="px-0"><b>@($"{model.DtStart:ddd yyyy-MM-dd}")</b></div>
</div>
</li>
}
<li class="list-group-item">
<div class="d-flex justify-content-between">
<div class="px-0">Inizio:</div>
<div class="px-0"><b>@(EventDto.DateForm(model.CodTipo, model.DtStart))</b></div>
</div>
</li>
<li class="list-group-item">
<div class="d-flex justify-content-between">
<div class="px-0">Fine:</div>
<div class="px-0"><b>@(EventDto.DateForm(model.CodTipo, model.DtEnd))</b></div>
</div>
</li>
@if (model.IdxDipendente == idxDipendente)
{
<li class="list-group-item">
<div class="d-flex justify-content-between">
<div class="px-0">Note:</div>
<div class="px-0"><b>@model.Note</b></div>
</div>
</li>
}
@if (!model.Conf)
{
<li class="list-group-item text-center bg-danger text-warning">
<b>NON CONFERMATO</b>
</li>
}
</ul>
</div>
@code {
[Parameter]
public EventDto ThisTask { get; set; } = null!;
// [Inject]
// protected MessageService AppMServ { get; set; } = null!;
EventDto model = new EventDto();
protected override void OnParametersSet()
{
model = ThisTask;
}
protected int idxDipendente
{
// get => AppMServ.IdxDipendente;
get => 0;
}
}
@@ -0,0 +1,136 @@
<div class="row">
<div class="col-12 my-1">
<ol class="list-group">
<li class="list-group-item align-items-lg-start bg-success text-light d-flex justify-content-between">
<div class="px-0">Job Eseguiti</div>
@if (QueueAll.Count > 0 && EnableReset)
{
<div class="px-0">
<button class="btn btn-sm btn-warning" @onclick="() => ResetQueue()">Reset All <i class="fa-solid fa-arrow-turn-up"></i></button>
</div>
}
</li>
@if (QueuePaged == null || QueuePaged?.Count() == 0)
{
<li class="list-group-item align-items-lg-start">Nessun Job Eseguito!</li>
}
else
{
foreach (var item in QueuePaged)
{
<li class="list-group-item align-items-lg-start">
<div class="d-flex justify-content-between">
<div class="px-0">
@item
</div>
<div class="px-0">
<button class="btn btn-sm btn-primary" @onclick="() => ReRunJob(item)"><i class="fa-solid fa-share-from-square" title="Riesecuzione Estimate"></i> Re-Run</button>
</div>
</div>
</li>
}
}
</ol>
@if (totalCount >= numRecord)
{
<nav>
<EgwCoreLib.Razor.DataPager currPage="@currPage" PageSize="@numRecord" totalCount="@totalCount" numPageChanged="SavePage" numRecordChanged="SaveNumRec"></EgwCoreLib.Razor.DataPager>
</nav>
}
</div>
</div>
@code {
#region Public Properties
[Parameter]
public EventCallback<string> EC_ReRunJob { get; set; }
[Parameter]
public EventCallback<string> EC_ResetQueue { get; set; }
[Parameter]
public List<string> QueueAll { get; set; } = new List<string>();
[Parameter]
public string QueueType { get; set; } = "Run";
[Parameter]
public bool EnableReset { get; set; } = false;
#endregion Public Properties
#region Protected Methods
protected override void OnParametersSet()
{
UpdateTable();
}
protected async Task ReRunJob(string? JobCode)
{
await EC_ReRunJob.InvokeAsync(JobCode);
}
protected async Task ResetQueue()
{
await EC_ResetQueue.InvokeAsync(QueueType);
}
protected void SaveNumRec(int newNum)
{
numRecord = newNum;
UpdateTable();
}
protected void SavePage(int newNum)
{
currPage = newNum;
UpdateTable();
}
#endregion Protected Methods
#region Private Fields
/// <summary>
/// pagina attuale
/// </summary>
private int currPage = 1;
/// <summary>
/// elementi per pagina
/// </summary>
private int numRecord = 10;
/// <summary>
/// Numero tot records
/// </summary>
private int totalCount = 0;
#endregion Private Fields
#region Private Properties
private IEnumerable<string>? QueuePaged { get; set; } = null;
#endregion Private Properties
#region Private Methods
/// <summary>
/// Filtro e paginazione
/// </summary>
private void UpdateTable()
{
// fix paginazione
QueuePaged = QueueAll
.Skip(numRecord * (currPage - 1))
.Take(numRecord);
totalCount = QueueAll.Count();
}
#endregion Private Methods
}
@@ -32,13 +32,13 @@
</div>
}
</li>
@if (ListRecords == null || ListRecords?.Count() == 0)
@if (QueueRunPaged == null || QueueRunPaged?.Count() == 0)
{
<li class="list-group-item align-items-lg-start">Nessun Job Eseguito!</li>
}
else
{
foreach (var item in ListRecords)
foreach (var item in QueueRunPaged)
{
<li class="list-group-item align-items-lg-start">
<div class="d-flex justify-content-between">
@@ -14,11 +14,14 @@ namespace Lux.UI.Components.Compo.WorkLoad
[Parameter]
public EventCallback<string> EC_ResetQueue { get; set; }
[Parameter]
public List<string> QueueWait { get; set; } = new List<string>();
[Parameter]
public List<string> QueueRun { get; set; } = new List<string>();
[Parameter]
public List<string> QueueWait { get; set; } = new List<string>();
public List<string> QueueDone { get; set; } = new List<string>();
#endregion Public Properties
@@ -79,7 +82,8 @@ namespace Lux.UI.Components.Compo.WorkLoad
#region Private Properties
private IEnumerable<string>? ListRecords { get; set; } = null;
private IEnumerable<string>? QueueRunPaged { get; set; } = null;
private IEnumerable<string>? QueueDonePaged { get; set; } = null;
#endregion Private Properties
@@ -91,7 +95,7 @@ namespace Lux.UI.Components.Compo.WorkLoad
private void UpdateTable()
{
// fix paginazione
ListRecords = QueueRun
QueueRunPaged = QueueRun
.Skip(numRecord * (currPage - 1))
.Take(numRecord);
totalCount = QueueRun.Count();
+6 -2
View File
@@ -327,6 +327,7 @@ namespace Lux.UI.Components.Pages
private bool isLoading = false;
private List<string> JobQueueDone = new List<string>();
private List<string> JobQueueRun = new List<string>();
private List<string> JobQueueWait = new List<string>();
@@ -545,12 +546,15 @@ namespace Lux.UI.Components.Pages
// aggiorno coda corrente x display...
var currQueueWait = await PService.QueueListAllAsync(ProdService.QueueType.waiting);
var currQueueRun = await PService.QueueListAllAsync(ProdService.QueueType.running);
var currQueueDone = await PService.QueueListAllAsync(ProdService.QueueType.done);
// converto x display...
JobQueueRun = currQueueRun.Select(x => $"{x}").ToList();
JobQueueWait = currQueueWait.Select(x => $"{x}").ToList();
JobQueueRun = currQueueRun.Select(x => $"{x}").ToList();
JobQueueDone = currQueueDone.Select(x => $"{x}").ToList();
// inverto ordine delle liste!
JobQueueRun.Reverse();
JobQueueWait.Reverse();
JobQueueRun.Reverse();
JobQueueDone.Reverse();
}
@@ -11,6 +11,7 @@
</div>
</div>
<div class="card-body">
<CalendarPlanner></CalendarPlanner>
</div>
</div>
+2
View File
@@ -24,3 +24,5 @@
@using Lux.UI.Components.Compo.JobTask
@using Lux.UI.Components.Compo.Planner
@using Lux.UI.Components.Compo.WorkLoad
@using Radzen
@using Radzen.Blazor
+2 -1
View File
@@ -5,7 +5,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>aspnet-Lux.UI-a758c101-a2f4-4e38-977d-1c4887dbbd50</UserSecretsId>
<Version>0.9.2601.1415</Version>
<Version>0.9.2601.1417</Version>
</PropertyGroup>
<ItemGroup>
@@ -30,6 +30,7 @@
</PackageReference>
<PackageReference Include="NLog" Version="6.0.1" />
<PackageReference Include="NLog.Web.AspNetCore" Version="6.0.1" />
<PackageReference Include="Radzen.Blazor" Version="8.6.0" />
</ItemGroup>
<ItemGroup>
+4
View File
@@ -10,6 +10,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using NLog;
using NLog.Web;
using Radzen;
using StackExchange.Redis;
using System.Globalization;
@@ -89,6 +90,9 @@ builder.Services.AddSingleton(new CalcRuidService(
builder.Services.AddHostedService<StatsCollectService>();
#endif
// aggiunta componenti Radzen
builder.Services.AddRadzenComponents();
var app = builder.Build();
// aggiunt base URL x routing corretto
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>LUX - Web Windows MES</i>
<h4>Versione: 0.9.2601.1415</h4>
<h4>Versione: 0.9.2601.1417</h4>
<br /> Note di rilascio:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
0.9.2601.1415
0.9.2601.1417
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>0.9.2601.1415</version>
<version>0.9.2601.1417</version>
<url>http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.UI.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/GPW/stable/ChangeLog.html</changelog>
<mandatory>false</mandatory>