Merge branch 'develop' of https://gitlab.steamware.net/steamware/mapo-core into develop
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
@using NLog;
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@inject HttpClient Http
|
||||
@inject SharedMemService MServ
|
||||
@inject IConfiguration config
|
||||
|
||||
|
||||
@@ -1,38 +1,12 @@
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
using global::System.Threading.Tasks;
|
||||
using global::Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.Web.Virtualization;
|
||||
using Microsoft.JSInterop;
|
||||
using MP_TAB_SERV;
|
||||
using MP_TAB_SERV.Shared;
|
||||
using MP_TAB_SERV.Components;
|
||||
using MP.Data;
|
||||
using MP.Data.DatabaseModels;
|
||||
using MP.Data.DTO;
|
||||
using MP.Data.Services;
|
||||
using NLog;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace MP_TAB_SERV.Components
|
||||
{
|
||||
public partial class TcHistoryFilter
|
||||
{
|
||||
[Parameter]
|
||||
public int MatrOpr { get; set; } = 102;
|
||||
|
||||
[Parameter]
|
||||
public string Title { get; set; } = "TC History";
|
||||
|
||||
[Parameter]
|
||||
public int SearchMinChar { get; set; }
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<string> E_CodArt { get; set; }
|
||||
@@ -40,49 +14,110 @@ namespace MP_TAB_SERV.Components
|
||||
[Parameter]
|
||||
public EventCallback<string> E_IdxMacc { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int MatrOpr { get; set; } = 102;
|
||||
|
||||
[Parameter]
|
||||
public int SearchMinChar { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Title { get; set; } = "TC History";
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected string BaseAddr = "";
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
BaseAddr = config.GetValue<string>("OptConf:BaseAddr") ?? "";
|
||||
await ReloadAllData();
|
||||
}
|
||||
|
||||
protected async Task ReloadAllData()
|
||||
{
|
||||
await ReloadArticoli();
|
||||
await ReloadMacchine();
|
||||
}
|
||||
#endregion Protected Fields
|
||||
|
||||
protected async Task ReloadArticoli()
|
||||
{
|
||||
await GetArticoli();
|
||||
FiltArticoli();
|
||||
}
|
||||
#region Protected Properties
|
||||
|
||||
protected async Task ReportArt()
|
||||
protected string CodArtSel
|
||||
{
|
||||
await E_CodArt.InvokeAsync(CodArtSel);
|
||||
}
|
||||
|
||||
protected async Task ReportMacc()
|
||||
{
|
||||
await E_IdxMacc.InvokeAsync(IdxMaccSel);
|
||||
}
|
||||
|
||||
protected async Task GetArticoli()
|
||||
{
|
||||
if (!ListArtDisabled)
|
||||
get => codArtSel;
|
||||
set
|
||||
{
|
||||
Log.Debug("GetArticoli");
|
||||
string ApiUrl = $"{BaseAddr}api/ListSelect/GetDictArticoli?SearchArt={SearchVal}";
|
||||
var rawData = await Http.GetFromJsonAsync<Dictionary<string, string>>(ApiUrl);
|
||||
if (rawData != null)
|
||||
if (codArtSel != value)
|
||||
{
|
||||
ListArticoliAll = rawData;
|
||||
codArtSel = value;
|
||||
var pUpd = Task.Run(async () =>
|
||||
{
|
||||
await ReportArt();
|
||||
});
|
||||
pUpd.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Inject]
|
||||
protected ListSelectDataSrv CtrDataServ { get; set; } = null!;
|
||||
|
||||
protected int DisplayCount { get; set; } = 0;
|
||||
|
||||
protected string IdxMaccSel
|
||||
{
|
||||
get => codArtSel;
|
||||
set
|
||||
{
|
||||
if (idxMaccSel != value)
|
||||
{
|
||||
idxMaccSel = value;
|
||||
var pUpd = Task.Run(async () =>
|
||||
{
|
||||
await ReportMacc();
|
||||
});
|
||||
pUpd.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
private string idxMaccSel { get; set; } = "";
|
||||
|
||||
protected bool ListArtDisabled { get => string.IsNullOrEmpty(SearchVal) || SearchVal.Length < SearchMinChar; }
|
||||
|
||||
protected Dictionary<string, string>? ListArticoli { get; set; } = null;
|
||||
|
||||
protected Dictionary<string, string> ListArticoliAll { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
protected Dictionary<string, string> ListMacchineAll { get => MServ.DictMacchine; set => MServ.DictMacchine = value; }
|
||||
|
||||
protected int Num2Displ
|
||||
{
|
||||
get => num2Displ;
|
||||
set
|
||||
{
|
||||
if (num2Displ != value)
|
||||
{
|
||||
num2Displ = value;
|
||||
FiltArticoli();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string SearchVal
|
||||
{
|
||||
get => searchVal;
|
||||
set
|
||||
{
|
||||
if (searchVal != value)
|
||||
{
|
||||
searchVal = value;
|
||||
var pUpd = Task.Run(async () =>
|
||||
{
|
||||
await ReloadArticoli();
|
||||
});
|
||||
pUpd.Wait();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected int TotalCount { get; set; } = 0;
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected void FiltArticoli()
|
||||
{
|
||||
bool done = false;
|
||||
@@ -105,63 +140,26 @@ namespace MP_TAB_SERV.Components
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task ReloadMacchine()
|
||||
protected async Task GetArticoli()
|
||||
{
|
||||
if (ListMacchineAll == null || ListMacchineAll.Count == 0)
|
||||
if (!ListArtDisabled)
|
||||
{
|
||||
Log.Debug("START ReloadMacchine");
|
||||
string ApiUrl = $"{BaseAddr}api/ListSelect/GetDictMacc?MatrOpr={MatrOpr}";
|
||||
var rawData = await Http.GetFromJsonAsync<Dictionary<string, string>>(ApiUrl);
|
||||
Log.Debug("GetArticoli");
|
||||
var rawData = await CtrDataServ.ArticoliGetSearch(10000, "*", searchVal);
|
||||
// trasformo!
|
||||
if (rawData != null)
|
||||
{
|
||||
ListMacchineAll = rawData;
|
||||
ListArticoliAll = rawData.ToDictionary(x => x.CodArticolo, x => $"{x.CodArticolo} | {x.DescArticolo} | {x.Disegno}");
|
||||
}
|
||||
|
||||
Log.Debug("END ReloadMacchine");
|
||||
}
|
||||
}
|
||||
|
||||
protected bool ListArtDisabled { get => string.IsNullOrEmpty(SearchVal) || SearchVal.Length < SearchMinChar; }
|
||||
|
||||
protected string SearchVal
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
get => searchVal;
|
||||
set
|
||||
{
|
||||
if (searchVal != value)
|
||||
{
|
||||
searchVal = value;
|
||||
}
|
||||
}
|
||||
BaseAddr = config.GetValue<string>("OptConf:BaseAddr") ?? "";
|
||||
await ReloadAllData();
|
||||
}
|
||||
|
||||
protected string CodArtSel
|
||||
{
|
||||
get => codArtSel;
|
||||
set
|
||||
{
|
||||
if (codArtSel != value)
|
||||
{
|
||||
codArtSel = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected int Num2Displ
|
||||
{
|
||||
get => num2Displ;
|
||||
set
|
||||
{
|
||||
if (num2Displ != value)
|
||||
{
|
||||
num2Displ = value;
|
||||
FiltArticoli();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string IdxMaccSel { get; set; } = "";
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
#if false
|
||||
@@ -172,20 +170,62 @@ namespace MP_TAB_SERV.Components
|
||||
await ReloadArticoli();
|
||||
|
||||
// updateCodArtSel
|
||||
await ReportArt();
|
||||
await ReportArt();
|
||||
#endif
|
||||
//return base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
protected Dictionary<string, string> ListMacchineAll { get => MServ.DictMacchine; set => MServ.DictMacchine = value; }
|
||||
protected Dictionary<string, string> ListArticoliAll { get; set; } = new Dictionary<string, string>();
|
||||
protected Dictionary<string, string>? ListArticoli { get; set; } = null;
|
||||
protected int TotalCount { get; set; } = 0;
|
||||
protected int DisplayCount { get; set; } = 0;
|
||||
private string searchVal { get; set; } = "";
|
||||
private string codArtSel { get; set; } = "";
|
||||
private int num2Displ { get; set; } = 20;
|
||||
protected async Task ReloadAllData()
|
||||
{
|
||||
await ReloadArticoli();
|
||||
await ReloadMacchine();
|
||||
}
|
||||
|
||||
protected async Task ReloadArticoli()
|
||||
{
|
||||
await GetArticoli();
|
||||
FiltArticoli();
|
||||
}
|
||||
|
||||
protected async Task ReloadMacchine()
|
||||
{
|
||||
if (ListMacchineAll == null || ListMacchineAll.Count == 0)
|
||||
{
|
||||
Log.Debug("START ReloadMacchine");
|
||||
var rawData = await CtrDataServ.MacchineByMatrOper(MatrOpr);
|
||||
// trasformo!
|
||||
if (rawData != null)
|
||||
{
|
||||
ListMacchineAll = rawData.ToDictionary(x => x.IdxMacchina, x => $"{x.IdxMacchina} | {x.Nome}");
|
||||
}
|
||||
Log.Debug("END ReloadMacchine");
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task ReportArt()
|
||||
{
|
||||
await E_CodArt.InvokeAsync(CodArtSel);
|
||||
}
|
||||
|
||||
protected async Task ReportMacc()
|
||||
{
|
||||
await E_IdxMacc.InvokeAsync(IdxMaccSel);
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string codArtSel { get; set; } = "";
|
||||
private int num2Displ { get; set; } = 20;
|
||||
private string searchVal { get; set; } = "";
|
||||
|
||||
#endregion Private Properties
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
@page "/tc-history"
|
||||
|
||||
@inject HttpClient Http
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header px-2">
|
||||
<TcHistoryFilter Title="Storico Tempi Ciclo" SearchMinChar="@SearchMinChar" E_CodArt="SelCodArt" E_IdxMacc="SelIdxMacc" MatrOpr="@MatrOpr"></TcHistoryFilter>
|
||||
@@ -97,92 +95,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public int MatrOpr { get; set; } = 0;
|
||||
|
||||
[Inject]
|
||||
protected IConfiguration config { get; set; } = null!;
|
||||
|
||||
protected int SearchMinChar = 3;
|
||||
protected string CodArt = "";
|
||||
protected string IdxMacc = "*";
|
||||
protected string BaseAddr = "";
|
||||
protected bool isLoading = false;
|
||||
|
||||
protected int NumRecPage = 5;
|
||||
protected int TotalCount = 0;
|
||||
protected int PageNum = 1;
|
||||
|
||||
protected List<ODLExpModel> ListComplete { get; set; } = new List<ODLExpModel>();
|
||||
protected List<ODLExpModel> ListODL { get; set; } = new List<ODLExpModel>();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
BaseAddr = config.GetValue<string>("OptConf:BaseAddr") ?? "";
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
protected async Task SelCodArt(string newCodArt)
|
||||
{
|
||||
CodArt = newCodArt;
|
||||
await ReloadData();
|
||||
}
|
||||
protected async Task SelIdxMacc(string newIdxMacc)
|
||||
{
|
||||
IdxMacc = newIdxMacc;
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
protected async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
if (!string.IsNullOrEmpty(CodArt))
|
||||
{
|
||||
string ApiUrl = $"{BaseAddr}api/ODL/GetODL?CodArt={CodArt}&IdxMacchina={IdxMacc}";
|
||||
try
|
||||
{
|
||||
var rawData = await Http.GetFromJsonAsync<List<ODLExpModel>>(ApiUrl);
|
||||
if (rawData != null)
|
||||
{
|
||||
ListComplete = rawData;
|
||||
TotalCount = ListComplete.Count;
|
||||
// esegue paginazione
|
||||
UpdateTable();
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Error on dataload{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
protected void UpdateTable()
|
||||
{
|
||||
// esegue paginazione
|
||||
if (TotalCount > NumRecPage)
|
||||
{
|
||||
ListODL = ListComplete.Skip((PageNum - 1) * NumRecPage).Take(NumRecPage).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
ListODL = ListComplete;
|
||||
}
|
||||
}
|
||||
|
||||
protected void SavePage(int newNum)
|
||||
{
|
||||
PageNum = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void SaveNumRec(int newNum)
|
||||
{
|
||||
NumRecPage = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
using global::System.Threading.Tasks;
|
||||
using global::Microsoft.AspNetCore.Components;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.Web.Virtualization;
|
||||
using Microsoft.JSInterop;
|
||||
using MP_TAB_SERV;
|
||||
using MP_TAB_SERV.Shared;
|
||||
using MP_TAB_SERV.Components;
|
||||
using MP.Data;
|
||||
using MP.Data.DatabaseModels;
|
||||
using MP.Data.DTO;
|
||||
using MP.Data.Services;
|
||||
using NLog;
|
||||
|
||||
namespace MP_TAB_SERV.Pages
|
||||
{
|
||||
public partial class TCHistory
|
||||
{
|
||||
[Parameter]
|
||||
public int MatrOpr { get; set; } = 0;
|
||||
|
||||
[Inject]
|
||||
protected IConfiguration config { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected OrderDataSrv CtrDataServ { get; set; } = null!;
|
||||
|
||||
protected int SearchMinChar = 3;
|
||||
protected string CodArt = "";
|
||||
protected string IdxMacc = "*";
|
||||
protected string BaseAddr = "";
|
||||
protected bool isLoading = false;
|
||||
protected int NumRecPage = 5;
|
||||
protected int TotalCount = 0;
|
||||
protected int PageNum = 1;
|
||||
protected List<ODLExpModel> ListComplete { get; set; } = new List<ODLExpModel>();
|
||||
protected List<ODLExpModel> ListODL { get; set; } = new List<ODLExpModel>();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
BaseAddr = config.GetValue<string>("OptConf:BaseAddr") ?? "";
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
protected async Task SelCodArt(string newCodArt)
|
||||
{
|
||||
CodArt = newCodArt;
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
protected async Task SelIdxMacc(string newIdxMacc)
|
||||
{
|
||||
IdxMacc = newIdxMacc;
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
protected async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
if (!string.IsNullOrEmpty(CodArt))
|
||||
{
|
||||
try
|
||||
{
|
||||
#if false
|
||||
string ApiUrl = $"{BaseAddr}api/ODL/GetODL?CodArt={CodArt}&IdxMacchina={IdxMacc}";
|
||||
var rawData = await Http.GetFromJsonAsync<List<ODLExpModel>>(ApiUrl);
|
||||
if (rawData != null)
|
||||
{
|
||||
ListComplete = rawData;
|
||||
TotalCount = ListComplete.Count;
|
||||
// esegue paginazione
|
||||
UpdateTable();
|
||||
}
|
||||
#endif
|
||||
ListComplete= await CtrDataServ.ListODLFilt(CodArt, IdxMacc);
|
||||
TotalCount = ListComplete.Count;
|
||||
// esegue paginazione
|
||||
UpdateTable();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Error on dataload{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
protected void UpdateTable()
|
||||
{
|
||||
// esegue paginazione
|
||||
if (TotalCount > NumRecPage)
|
||||
{
|
||||
ListODL = ListComplete.Skip((PageNum - 1) * NumRecPage).Take(NumRecPage).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
ListODL = ListComplete;
|
||||
}
|
||||
}
|
||||
|
||||
protected void SavePage(int newNum)
|
||||
{
|
||||
PageNum = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void SaveNumRec(int newNum)
|
||||
{
|
||||
NumRecPage = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
@page "/user"
|
||||
|
||||
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject IHttpContextAccessor httpContextAccessor
|
||||
|
||||
<h3>User</h3>
|
||||
|
||||
|
||||
|
||||
<div class="d-flex">
|
||||
<div class="col-3"></div>
|
||||
<div class="card col-6">
|
||||
<div class="card-header text-center">
|
||||
<div style="font-size: 4rem;">
|
||||
<i class="fa-solid fa-user"></i>
|
||||
</div>
|
||||
<div style="font-size: 1.5rem;">
|
||||
<span>USER DATA</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<div class="text-start">User</div>
|
||||
<div class="text-end"><b>USERNAME[999]</b></div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<div class="text-start">Server Time</div>
|
||||
<div class="text-end"><b>@($"{DateTime.Now.ToString("dddd dd.MM.yyyy HH:mm.ss")}")</b></div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<div class="text-start">Client IP</div>
|
||||
<div class="text-end"><b>@currIpv4</b></div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<div class="text-start">Browser Size</div>
|
||||
<div class="text-end"><b>@($"{Width}x{Height}")</b></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button class="w-100 btn btn-success">
|
||||
<i class="fa-solid fa-gear"></i> ABOUT PAGE
|
||||
</button>
|
||||
<hr />
|
||||
<button class="w-100 btn btn-danger">
|
||||
<i class="fa-solid fa-right-from-bracket"></i> LOGOUT
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3"></div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
public int Height { get; set; } = 0;
|
||||
public int Width { get; set; } = 0;
|
||||
public string currIpv4 { get; set; } = "";
|
||||
|
||||
public class WindowDimension
|
||||
{
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
}
|
||||
protected async override Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
//await Task.Delay(500);
|
||||
if (firstRender)
|
||||
{
|
||||
await getWDim();
|
||||
StateHasChanged();
|
||||
Log.Debug($"Dimensioni schermo: {Width}x{Height}");
|
||||
}
|
||||
}
|
||||
protected async override Task OnInitializedAsync()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
if (string.IsNullOrEmpty(currIpv4))
|
||||
{
|
||||
// ricalcolo e salvo...
|
||||
if (httpContextAccessor.HttpContext != null)
|
||||
{
|
||||
var remoteIp = $"{httpContextAccessor.HttpContext.Connection?.RemoteIpAddress}";
|
||||
// provo a recuperare ipV4...
|
||||
currIpv4 = EgwCoreLib.Razor.Data.IpUtils.getLocalIpv4(remoteIp);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected async Task getWDim()
|
||||
{
|
||||
var dimension = await JSRuntime.InvokeAsync<WindowDimension>("getWindowDimensions");
|
||||
Height = dimension.Height;
|
||||
Width = dimension.Width;
|
||||
}
|
||||
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user