Bozza pagina da testare in ufficio
This commit is contained in:
+1
-1
@@ -5,7 +5,7 @@ VisualStudioVersion = 17.4.33213.308
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StockMan.CORE", "StockMan.CORE\StockMan.CORE.csproj", "{3D23F328-E6B6-4EDB-B2DE-00E39E953757}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StockMan.Data", "StockMan.Data\StockMan.Data.csproj", "{5C4C9C5C-9478-424A-B68C-C3C04C5E2165}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StockMan.Data", "StockMan.Data\StockMan.Data.csproj", "{5C4C9C5C-9478-424A-B68C-C3C04C5E2165}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using StackExchange.Redis;
|
||||
using StockMan.Data.Controllers;
|
||||
using StockMan.Data.DbModels;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace StockMan.CORE.Data
|
||||
{
|
||||
public class StockDataService : IDisposable
|
||||
{
|
||||
#region Protected Fields
|
||||
|
||||
protected Random rnd = new Random();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private const string passPhrase = "53DBA37E-257D-4276-BAC2-C0BF7E04BBD6";
|
||||
private const string redisBaseAddr = "STOCKMAN:STEAM";
|
||||
private const string rKeyCounters = $"{redisBaseAddr}:Cache:Counters";
|
||||
private const string rKeyItemFamily = $"{redisBaseAddr}:Cache:ItemFamily";
|
||||
private const string rKeyItemFlux = $"{redisBaseAddr}:Cache:ItemFlux";
|
||||
private const string rKeyItems = $"{redisBaseAddr}:Cache:Items";
|
||||
private const string rKeyItemStock = $"{redisBaseAddr}:Cache:Item:Stock";
|
||||
private const string rKeyLocation = $"{redisBaseAddr}:Cache:Location";
|
||||
private const string rKeyLocType = $"{redisBaseAddr}:Cache:LocType";
|
||||
private const string rKeyMovType = $"{redisBaseAddr}:Cache:MovType";
|
||||
private const string rKeyOperator = $"{redisBaseAddr}:Cache:Operator";
|
||||
private static IConfiguration _configuration = null!;
|
||||
private static ILogger<StockDataService> _logger = null!;
|
||||
private static StoManController dbController = null!;
|
||||
private static JsonSerializerSettings? JSSettings;
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly IEmailSender _emailSender;
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache lunga IN SECONDI
|
||||
/// </summary>
|
||||
private int cacheTtlLong = 60 * 5;
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache breve IN SECONDI
|
||||
/// </summary>
|
||||
private int cacheTtlShort = 60 * 1;
|
||||
|
||||
/// <summary>
|
||||
/// Oggetto per connessione a REDIS
|
||||
/// </summary>
|
||||
private IConnectionMultiplexer redisConn;
|
||||
|
||||
//ISubscriber sub = redis.GetSubscriber();
|
||||
/// <summary>
|
||||
/// Oggetto DB redis da impiegare x chiamate R/W
|
||||
/// </summary>
|
||||
private IDatabase redisDb = null!;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
public StockDataService(IConfiguration configuration, ILogger<StockDataService> logger, IConnectionMultiplexer redisConnMult, IEmailSender emailSender)
|
||||
{
|
||||
_logger = logger;
|
||||
_configuration = configuration;
|
||||
_emailSender = emailSender;
|
||||
// Conf cache
|
||||
redisConn = redisConnMult;// ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis"));
|
||||
//redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis"));
|
||||
redisDb = this.redisConn.GetDatabase();
|
||||
|
||||
// json serializer... FIX errore loop circolare https://www.ryadel.com/en/jsonserializationexception-self-referencing-loop-detected-error-fix-entity-framework-asp-net-core/
|
||||
JSSettings = new JsonSerializerSettings()
|
||||
{
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
||||
};
|
||||
|
||||
// cod app
|
||||
CodApp = _configuration["CodApp"];
|
||||
// Conf DB
|
||||
string connStr = _configuration.GetConnectionString("StockMan.DB");
|
||||
if (string.IsNullOrEmpty(connStr))
|
||||
{
|
||||
_logger.LogError("ConnString empty!");
|
||||
}
|
||||
else
|
||||
{
|
||||
dbController = new StoManController(configuration);
|
||||
}
|
||||
_logger.LogInformation("Avviata classe StockDataService");
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected string CodApp { get; set; } = "";
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
|
||||
/// </summary>
|
||||
private TimeSpan FastCache
|
||||
{
|
||||
get => TimeSpan.FromSeconds(cacheTtlShort * rnd.Next(900, 1100) / 1000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
|
||||
/// </summary>
|
||||
private TimeSpan LongCache
|
||||
{
|
||||
get => TimeSpan.FromSeconds(cacheTtlLong * rnd.Next(900, 1100) / 1000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
|
||||
/// </summary>
|
||||
private TimeSpan UltraLongCache
|
||||
{
|
||||
get => TimeSpan.FromSeconds(cacheTtlLong * 10 * rnd.Next(900, 1100) / 1000);
|
||||
}
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Clear database controller
|
||||
dbController.Dispose();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Svuotamento comleto cache REDIS
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FlushRedisCache()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
RedisValue pattern = new RedisValue($"{redisBaseAddr}:*");
|
||||
bool answ = await ExecFlushRedisPattern(pattern);
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lista Famiglie Articoli
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<ItemFamilyModel>> ItemFamilyGetAll()
|
||||
{
|
||||
string source = "DB";
|
||||
List<ItemFamilyModel>? dbResult = new List<ItemFamilyModel>();
|
||||
string currKey = $"{rKeyItemFamily}";
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
string? rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (!string.IsNullOrEmpty(rawData))
|
||||
{
|
||||
source = "REDIS";
|
||||
var tempResult = JsonConvert.DeserializeObject<List<ItemFamilyModel>>(rawData);
|
||||
if (tempResult == null)
|
||||
{
|
||||
dbResult = new List<ItemFamilyModel>();
|
||||
}
|
||||
else
|
||||
{
|
||||
dbResult = tempResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbResult = dbController.ItemFamilyGetAll();
|
||||
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
|
||||
await redisDb.StringSetAsync(currKey, rawData, LongCache);
|
||||
}
|
||||
if (dbResult == null)
|
||||
{
|
||||
dbResult = new List<ItemFamilyModel>();
|
||||
}
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Debug($"ItemFamilyGetAll | {source} in: {ts.TotalMilliseconds} ms");
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Esegue flush memoria redis dato pattern
|
||||
/// </summary>
|
||||
/// <param name="pattern"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<bool> ExecFlushRedisPattern(RedisValue pattern)
|
||||
{
|
||||
bool answ = false;
|
||||
var listEndpoints = redisConn.GetEndPoints();
|
||||
foreach (var endPoint in listEndpoints)
|
||||
{
|
||||
//var server = redisConnAdmin.GetServer(listEndpoints[0]);
|
||||
var server = redisConn.GetServer(endPoint);
|
||||
if (server != null)
|
||||
{
|
||||
var keyList = server.Keys(redisDb.Database, pattern);
|
||||
foreach (var item in keyList)
|
||||
{
|
||||
await redisDb.KeyDeleteAsync(item);
|
||||
}
|
||||
answ = true;
|
||||
}
|
||||
}
|
||||
|
||||
return answ;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
@page "/ItemFamily"
|
||||
|
||||
<h3>ItemFamily</h3>
|
||||
|
||||
|
||||
@if (isLoading)
|
||||
{
|
||||
<i>...loading...</i>
|
||||
}
|
||||
@if (ListRecord == null || ListRecord.Count == 0)
|
||||
{
|
||||
<b>nessun record</b>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ul>
|
||||
|
||||
@foreach (var item in ListRecord)
|
||||
{
|
||||
<li>@item.Descr</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using StockMan.CORE.Data;
|
||||
using StockMan.Data.DbModels;
|
||||
|
||||
namespace StockMan.CORE.Pages
|
||||
{
|
||||
public partial class ItemFamily
|
||||
{
|
||||
#region Protected Properties
|
||||
|
||||
protected List<ItemFamilyModel>? ListRecord { get; set; } = null;
|
||||
|
||||
[Inject]
|
||||
protected StockDataService SDService { get; set; } = null!;
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private bool isLoading { get; set; } = false;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
ListRecord = await SDService.ItemFamilyGetAll();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,56 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using StackExchange.Redis;
|
||||
using StockMan.CORE.Data;
|
||||
using StockMan.Data;
|
||||
using System.Globalization;
|
||||
using Blazored.LocalStorage;
|
||||
using Blazored.SessionStorage;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
//builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
|
||||
// .AddNegotiate();
|
||||
|
||||
//builder.Services.AddAuthorization(options =>
|
||||
//{
|
||||
// // By default, all incoming requests will be authorized according to the default policy.
|
||||
// options.FallbackPolicy = options.DefaultPolicy;
|
||||
//});
|
||||
|
||||
// configuration setup
|
||||
ConfigurationManager configuration = builder.Configuration;
|
||||
|
||||
// REDIS setup
|
||||
string connStringRedis = configuration.GetConnectionString("Redis");
|
||||
string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":"));
|
||||
// avvio oggetto shared x redis...
|
||||
var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis);
|
||||
|
||||
// abilitazione x email management con MailKit
|
||||
builder.Services.AddTransient<IEmailSender, MailKitEmailSender>();
|
||||
builder.Services.Configure<MailKitEmailSenderOptions>(options =>
|
||||
{
|
||||
options.Host_Address = configuration["ExternalProviders:MailKit:SMTP:Address"];
|
||||
options.Host_Port = Convert.ToInt32(configuration["ExternalProviders:MailKit:SMTP:Port"]);
|
||||
options.Host_Username = configuration["ExternalProviders:MailKit:SMTP:Account"];
|
||||
options.Host_Password = configuration["ExternalProviders:MailKit:SMTP:Password"];
|
||||
options.Sender_EMail = configuration["ExternalProviders:MailKit:SMTP:SenderEmail"];
|
||||
options.Sender_Name = configuration["ExternalProviders:MailKit:SMTP:SenderName"];
|
||||
});
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorPages();
|
||||
builder.Services.AddServerSideBlazor();
|
||||
builder.Services.AddSingleton<StockDataService>();
|
||||
//builder.Services.AddScoped<MessageService>();
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.AddSingleton<IConnectionMultiplexer>(redisMultiplexer);
|
||||
|
||||
builder.Services.AddBlazoredLocalStorage();
|
||||
builder.Services.AddBlazoredSessionStorage();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
@@ -18,6 +62,18 @@ if (!app.Environment.IsDevelopment())
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
// cultura IT...
|
||||
var supportedCultures = new[]{
|
||||
new CultureInfo("it-IT")
|
||||
};
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("it-IT"),
|
||||
SupportedCultures = supportedCultures,
|
||||
FallBackToParentCultures = false
|
||||
});
|
||||
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("it-IT");
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseStaticFiles();
|
||||
@@ -27,4 +83,4 @@ app.UseRouting();
|
||||
app.MapBlazorHub();
|
||||
app.MapFallbackToPage("/_Host");
|
||||
|
||||
app.Run();
|
||||
app.Run();
|
||||
@@ -5,18 +5,24 @@ namespace StockMan.CORE.Shared
|
||||
{
|
||||
public partial class MainLayout
|
||||
{
|
||||
#region Protected Properties
|
||||
|
||||
protected List<LinkMan> navMenuLinks { get; set; } = new List<LinkMan>();
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
navMenuLinks.Clear();
|
||||
navMenuLinks.Add(new LinkMan() { Title = "Articolo", Icon = "fa-solid fa-box", hasChildren = true, linkChildren = new List<string>() { "Anagrafica articoli", "Famiglia articoli" } });
|
||||
navMenuLinks.Add(new LinkMan() { Title = "Magazzino", Icon = "fa-solid fa-boxes-stacked" });
|
||||
navMenuLinks.Add(new LinkMan() { Title = "Aagrafiche", Icon = "fa-solid fa-clipboard-list" });
|
||||
navMenuLinks.Add(new LinkMan() { Title = "Anagrafiche", Icon = "fa-solid fa-clipboard-list" });
|
||||
navMenuLinks.Add(new LinkMan() { Title = "Admin", Icon = "fa-solid fa-id-card-clip" });
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,11 @@
|
||||
<None Include="compilerconfig.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.6.90" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StockMan.Data\StockMan.Data.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using StockMan.CORE
|
||||
@using StockMan.CORE.Data
|
||||
@using StockMan.CORE.Shared
|
||||
|
||||
Reference in New Issue
Block a user