Update x gestioen scadenza lunga SVG porte TPL
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>WebDoorCreator - Egalware</i>
|
||||
<h4>Version: 0.9.2306.2808</h4>
|
||||
<h4>Version: 0.9.2306.2810</h4>
|
||||
<br /> Release note:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.9.2306.2808
|
||||
0.9.2306.2810
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>0.9.2306.2808</version>
|
||||
<version>0.9.2306.2810</version>
|
||||
<url>http://nexus.steamware.net/repository/SWS/WDC/stable/WDC.UI.zip</url>
|
||||
<changelog>http://nexus.steamware.net/repository/SWS/WDC/stable/ChangeLog.html</changelog>
|
||||
<mandatory>false</mandatory>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.VisualBasic;
|
||||
using NLog;
|
||||
using StackExchange.Redis;
|
||||
using WebDoorCreator.Data.DTO;
|
||||
using WebDoorCreator.Data.Services;
|
||||
|
||||
@@ -94,16 +92,16 @@ namespace WebDoorCreator.API.Controllers
|
||||
string answ = "NA";
|
||||
// fixme todo
|
||||
|
||||
/* --------------
|
||||
/* --------------
|
||||
* da riscrivere
|
||||
* - server record x cancellazione logica delle porte OK
|
||||
* - server record x cancellazione logica delle porte OK
|
||||
* - il record (boolean, toDelete...) indica azione richiesta OK
|
||||
* - si prendono TUTTE le porte da DB con toDelete == true OK
|
||||
* - si eliminano su REDIS dalle 4 code (req, processing, error, done) OK
|
||||
* - check delle code processing, SE ci sono record rimasti li cerco sul DB
|
||||
* - si eliminano su REDIS dalle 4 code (req, processing, error, done) OK
|
||||
* - check delle code processing, SE ci sono record rimasti li cerco sul DB
|
||||
* - se NON ci sono sul db --> li elimino da processing
|
||||
* - effettivo delete sul db di toDelete
|
||||
*
|
||||
* - effettivo delete sul db di toDelete
|
||||
*
|
||||
* - proseguo come ora (sposto tra code processing --> request)
|
||||
*/
|
||||
|
||||
@@ -119,7 +117,6 @@ namespace WebDoorCreator.API.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool fatto = await QDataServ.ResetQueueProcessing();
|
||||
answ = fatto ? "OK" : "NO";
|
||||
return answ;
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace WebDoorCreator.Core
|
||||
public static readonly string CALC_REQ_PROC = $"{BASE_HASH}:CalcRequests:Processing";
|
||||
public static readonly string CALC_REQ_DDF_CACHE = $"{BASE_HASH}:CalcRequests:CacheDDF";
|
||||
public static readonly string CALC_REQ_SVG_CACHE = $"{BASE_HASH}:CalcRequests:CacheSVG";
|
||||
public static readonly string DOOR_TPL_LIST = $"{BASE_HASH}:Template:DoorList";
|
||||
|
||||
|
||||
// REDIS Channels messaggi x QueueMan (verso UI/srv)
|
||||
public static readonly string CALC_REQ_QUEUE = $"CalcRequest";
|
||||
|
||||
@@ -135,26 +135,11 @@ namespace WebDoorCreator.Data.Services
|
||||
if (doorData.Length == 2)
|
||||
{
|
||||
RedisKey currErrKey = new RedisKey($"{Constants.CALC_REQ_ERRS}");
|
||||
int currId = await RedHashGet(currErrKey, doorData[0]);
|
||||
int currId = await RedHashGetInt(currErrKey, doorData[0]);
|
||||
hasErr = doorData[1] == $"{currId}";
|
||||
}
|
||||
return hasErr;
|
||||
}
|
||||
/// <summary>
|
||||
/// Restitusice gli errori della porta in oggetto
|
||||
/// </summary>
|
||||
/// <param name="doorIdVers">formato DoorId:Versione</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> RedisBulkDelHashByKey(int doorId)
|
||||
{
|
||||
await DoorRefreshRemove($"{doorId}");
|
||||
await RequestDoneRemove($"{doorId}");
|
||||
await RequestErrRemove($"{doorId}");
|
||||
await RequestPendingRemove($"{doorId}");
|
||||
await RequestProcessingRemove($"{doorId}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restitusice gli errori della porta in oggetto
|
||||
@@ -266,6 +251,36 @@ namespace WebDoorCreator.Data.Services
|
||||
return svgVal.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if specified DoorId is in Template door list
|
||||
/// </summary>
|
||||
/// <param name="DoorId">Door Id to search</param>
|
||||
/// <returns>Found (true/false)</returns>
|
||||
public async Task<bool> DoorTplListContainsDoor(string DoorId)
|
||||
{
|
||||
bool found = false;
|
||||
RedisKey currKey = new RedisKey(Constants.DOOR_TPL_LIST);
|
||||
var rawVal = await RedHashGetString(currKey, DoorId);
|
||||
found = !string.IsNullOrEmpty(rawVal) && (rawVal == DoorId);
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add specified DoorIdList to Template door list
|
||||
/// </summary>
|
||||
/// <param name="DoorIdList">List to add</param>
|
||||
/// <returns>Num of items in list</returns>
|
||||
public async Task<long> DoorTplListUpsert(List<string> DoorIdList)
|
||||
{
|
||||
RedisKey currKey = new RedisKey(Constants.DOOR_TPL_LIST);
|
||||
long numReq = 0;
|
||||
foreach (var item in DoorIdList)
|
||||
{
|
||||
numReq = await RedHashUpsert(currKey, item, item);
|
||||
}
|
||||
return numReq;
|
||||
}
|
||||
|
||||
public async Task<bool> FlushRedisCache()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
@@ -351,12 +366,12 @@ namespace WebDoorCreator.Data.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify existence for single hash record
|
||||
/// Get single hash record
|
||||
/// </summary>
|
||||
/// <param name="currKey">Chiave redis della Hashlist</param>
|
||||
/// <param name="chiave">Chiave nella HashList</param>
|
||||
/// <returns>Esito rimozione</returns>
|
||||
public async Task<int> RedHashGet(RedisKey currKey, string chiave)
|
||||
/// <param name="currKey">Redis Key for Hashlist</param>
|
||||
/// <param name="chiave">Requested key on list</param>
|
||||
/// <returns>Value as Int</returns>
|
||||
public async Task<int> RedHashGetInt(RedisKey currKey, string chiave)
|
||||
{
|
||||
int result = 0;
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
@@ -372,7 +387,33 @@ namespace WebDoorCreator.Data.Services
|
||||
}
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"RedHashGet | {currKey} | in: {ts.TotalMilliseconds} ms");
|
||||
Log.Trace($"RedHashGetInt | {currKey} | in: {ts.TotalMilliseconds} ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get single hash record
|
||||
/// </summary>
|
||||
/// <param name="currKey">Redis Key for Hashlist</param>
|
||||
/// <param name="chiave">Requested key on list</param>
|
||||
/// <returns>Value as string</returns>
|
||||
public async Task<string> RedHashGetString(RedisKey currKey, string chiave)
|
||||
{
|
||||
string result = "";
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
var hasVal = await redisDb.HashExistsAsync(currKey, chiave);
|
||||
if (hasVal)
|
||||
{
|
||||
var rawRes = await redisDb.HashGetAsync(currKey, chiave);
|
||||
if (rawRes.HasValue)
|
||||
{
|
||||
result = $"{rawRes}";
|
||||
}
|
||||
}
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"RedHashGetString | {currKey} | in: {ts.TotalMilliseconds} ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -394,6 +435,22 @@ namespace WebDoorCreator.Data.Services
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restitusice gli errori della porta in oggetto
|
||||
/// </summary>
|
||||
/// <param name="doorIdVers">formato DoorId:Versione</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> RedisBulkDelHashByKey(int doorId)
|
||||
{
|
||||
await DoorRefreshRemove($"{doorId}");
|
||||
await RequestDoneRemove($"{doorId}");
|
||||
await RequestErrRemove($"{doorId}");
|
||||
await RequestPendingRemove($"{doorId}");
|
||||
await RequestProcessingRemove($"{doorId}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Queue request done
|
||||
/// </summary>
|
||||
@@ -723,7 +780,7 @@ namespace WebDoorCreator.Data.Services
|
||||
foreach (var item in listDone)
|
||||
{
|
||||
DoorIdList.Remove(item);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
@@ -771,23 +828,33 @@ namespace WebDoorCreator.Data.Services
|
||||
public async Task<bool> SaveProcessingResult(List<CalcResultDTO> calcResults)
|
||||
{
|
||||
bool answ = true;
|
||||
await Task.Delay(1);
|
||||
if (calcResults != null && calcResults.Count > 0)
|
||||
{
|
||||
string sDoorId = "";
|
||||
string sCurrVers = "";
|
||||
bool doorIsTpl = false;
|
||||
foreach (var calcTask in calcResults)
|
||||
{
|
||||
RedisKey currSvgKey = new RedisKey("");
|
||||
var doorData = calcTask.DoorIdVers.Split(".");
|
||||
sDoorId = doorData.Length > 0 ? doorData[0] : "";
|
||||
sCurrVers = doorData.Length > 0 ? doorData[1] : "";
|
||||
// verifico se sia template --> durata indefinita...
|
||||
doorIsTpl = await DoorTplListContainsDoor(sDoorId);
|
||||
// se valido salvo SVG...
|
||||
if (calcTask.Validated)
|
||||
{
|
||||
// salvo in area REDIS
|
||||
currSvgKey = new RedisKey($"{Constants.CALC_REQ_SVG_CACHE}:{sDoorId}:{sCurrVers}");
|
||||
await redisDb.StringSetAsync(currSvgKey, calcTask.SvgGen, WeekLongCache);
|
||||
// se template --> no scadenza
|
||||
if (doorIsTpl)
|
||||
{
|
||||
await redisDb.StringSetAsync(currSvgKey, calcTask.SvgGen);
|
||||
}
|
||||
else
|
||||
{
|
||||
await redisDb.StringSetAsync(currSvgKey, calcTask.SvgGen, WeekLongCache);
|
||||
}
|
||||
// elimino dalle code proc/err
|
||||
await RequestProcessingRemove(sDoorId);
|
||||
await RequestErrRemove(sDoorId);
|
||||
@@ -799,7 +866,14 @@ namespace WebDoorCreator.Data.Services
|
||||
{
|
||||
// salvo in area REDIS
|
||||
currSvgKey = new RedisKey($"{Constants.CALC_REQ_ERRS}:{sDoorId}:{sCurrVers}");
|
||||
await redisDb.StringSetAsync(currSvgKey, calcTask.ErrorMsg, WeekLongCache);
|
||||
if (doorIsTpl)
|
||||
{
|
||||
await redisDb.StringSetAsync(currSvgKey, calcTask.ErrorMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
await redisDb.StringSetAsync(currSvgKey, calcTask.ErrorMsg, WeekLongCache);
|
||||
}
|
||||
// elimino dalle code proc/done
|
||||
await RequestProcessingRemove(sDoorId);
|
||||
await RequestDoneRemove(sDoorId);
|
||||
@@ -810,6 +884,10 @@ namespace WebDoorCreator.Data.Services
|
||||
CalcDonePipe.saveAndSendMessage(Constants.LAST_CALC_DONE_KEY, calcTask.DoorIdVers);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Delay(1);
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using System.Collections.Generic;
|
||||
using WebDoorCreator.Data.DbModels;
|
||||
using WebDoorCreator.Data.Services;
|
||||
using WebDoorCreator.UI.Components.SvgComp;
|
||||
@@ -17,8 +16,6 @@ namespace WebDoorCreator.UI.Components.DoorMan
|
||||
|
||||
[Parameter]
|
||||
public int currOrderId { get; set; } = 0;
|
||||
[Parameter]
|
||||
public decimal orderTotCost { get; set; } = 0;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<DoorModel> E_CurrDoor { get; set; }
|
||||
@@ -29,6 +26,15 @@ namespace WebDoorCreator.UI.Components.DoorMan
|
||||
[Parameter]
|
||||
public EventCallback<bool> E_DoorChanged { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public bool isTplPage { get; set; } = false;
|
||||
|
||||
[CascadingParameter]
|
||||
public int orderStatus { get; set; } = 10;
|
||||
|
||||
[Parameter]
|
||||
public decimal orderTotCost { get; set; } = 0;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<int> updateRecordCount { get; set; }
|
||||
|
||||
@@ -59,29 +65,23 @@ namespace WebDoorCreator.UI.Components.DoorMan
|
||||
protected DoorModel? currDoor { get; set; } = null;
|
||||
protected List<DoorOpModel>? DoorOpsList { get; set; } = null;
|
||||
protected List<DoorModel>? DoorsList { get; set; } = null;
|
||||
protected List<ListValuesModel>? OrderSteps { get; set; } = null;
|
||||
protected bool isAddNew { get; set; } = false;
|
||||
protected string nextStepLabel { get; set; } = "Send to DCA";
|
||||
protected string nextStepColor { get; set; } = "";
|
||||
protected bool isAddRemMode { get; set; }
|
||||
protected bool IsChanged { get; set; } = false;
|
||||
|
||||
protected bool isCloneMode { get; set; }
|
||||
protected bool isRecalc { get; set; } = false;
|
||||
protected bool isTpl { get; set; } = false;
|
||||
|
||||
[CascadingParameter]
|
||||
public bool isTplPage { get; set; } = false;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected NavigationManager NavManager { get; set; } = null!;
|
||||
|
||||
[CascadingParameter]
|
||||
public int orderStatus { get; set; } = 10;
|
||||
protected string nextStepColor { get; set; } = "";
|
||||
protected string nextStepLabel { get; set; } = "Send to DCA";
|
||||
protected string orderPrice { get; set; } = "";
|
||||
protected List<ListValuesModel>? OrderSteps { get; set; } = null;
|
||||
|
||||
[Inject]
|
||||
protected QueueDataService QDService { get; set; } = null!;
|
||||
@@ -99,6 +99,16 @@ namespace WebDoorCreator.UI.Components.DoorMan
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected async void back2Draft(int ordId)
|
||||
{
|
||||
var confirm = await JSRuntime.InvokeAsync<bool>("confirm", $"Are you sure you want to set the current order status to ORDER DRAFT");
|
||||
if (confirm)
|
||||
{
|
||||
bool done = await WDService.OrderUpdateStatus(ordId, 10);
|
||||
NavManager.NavigateTo(NavManager.Uri, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task catchDoorChange(bool isChanged)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
@@ -109,6 +119,25 @@ namespace WebDoorCreator.UI.Components.DoorMan
|
||||
}
|
||||
}
|
||||
|
||||
protected async void changeOrderStatus(int ordId)
|
||||
{
|
||||
if (OrderSteps != null)
|
||||
{
|
||||
var stepsArray = OrderSteps.ToArray();
|
||||
var currStepInList = OrderSteps.Where(x => x.Value == orderStatus.ToString()).FirstOrDefault();
|
||||
var stepIndex = Array.IndexOf(stepsArray, currStepInList);
|
||||
if (stepIndex != -1)
|
||||
{
|
||||
if (currStepInList?.Value != "70")
|
||||
{
|
||||
var nextStep = stepsArray[stepIndex + 1];
|
||||
bool done = await WDService.OrderUpdateStatus(ordId, int.Parse(nextStep.Value));
|
||||
NavManager.NavigateTo(NavManager.Uri, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task createDoor()
|
||||
{
|
||||
int doorId = await WDService.createDoor(currOrderId, userId, "mm");
|
||||
@@ -184,6 +213,43 @@ namespace WebDoorCreator.UI.Components.DoorMan
|
||||
}
|
||||
}
|
||||
|
||||
protected string getStepColor()
|
||||
{
|
||||
string answ = "";
|
||||
if (OrderSteps != null)
|
||||
{
|
||||
var stepsArray = OrderSteps.ToArray();
|
||||
var currStepInList = OrderSteps.Where(x => x.Value == orderStatus.ToString()).FirstOrDefault();
|
||||
var stepIndex = Array.IndexOf(stepsArray, currStepInList);
|
||||
if (stepIndex != -1)
|
||||
{
|
||||
var nextStep = stepsArray[stepIndex + 1];
|
||||
answ = nextStep.DefaultVal;
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
protected string getStepLabel()
|
||||
{
|
||||
string answ = "";
|
||||
if (OrderSteps != null)
|
||||
{
|
||||
var stepsArray = OrderSteps.ToArray();
|
||||
var currStepInList = OrderSteps.Where(x => x.Value == orderStatus.ToString()).FirstOrDefault();
|
||||
var stepIndex = Array.IndexOf(stepsArray, currStepInList);
|
||||
if (stepIndex != -1)
|
||||
{
|
||||
if (currStepInList?.Value != "70")
|
||||
{
|
||||
var nextStep = stepsArray[stepIndex + 1];
|
||||
answ = nextStep.Label;
|
||||
}
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
protected async Task modalClose(bool isClose)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
@@ -208,6 +274,9 @@ namespace WebDoorCreator.UI.Components.DoorMan
|
||||
List<string> doorIdList = DoorsList
|
||||
.Select(x => $"{x.DoorId}")
|
||||
.ToList();
|
||||
|
||||
// faccio upsert porte nell'elenco door tipo template...
|
||||
var numTplDoor = await QDService.DoorTplListUpsert(doorIdList);
|
||||
// chiamo reset
|
||||
var list2Proc = await QDService.ResetQueueByDoorList(doorIdList);
|
||||
// se ho porte da processare --> chiamo save...
|
||||
@@ -304,7 +373,7 @@ namespace WebDoorCreator.UI.Components.DoorMan
|
||||
{
|
||||
//orderStatus = currDoor.OrderNav.Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -323,72 +392,6 @@ namespace WebDoorCreator.UI.Components.DoorMan
|
||||
await JSRuntime.InvokeAsync<object>("open", url, "_blank");
|
||||
}
|
||||
|
||||
|
||||
protected string getStepColor()
|
||||
{
|
||||
string answ = "";
|
||||
if (OrderSteps != null)
|
||||
{
|
||||
var stepsArray = OrderSteps.ToArray();
|
||||
var currStepInList = OrderSteps.Where(x => x.Value == orderStatus.ToString()).FirstOrDefault();
|
||||
var stepIndex = Array.IndexOf(stepsArray, currStepInList);
|
||||
if (stepIndex != -1)
|
||||
{
|
||||
var nextStep = stepsArray[stepIndex + 1];
|
||||
answ = nextStep.DefaultVal;
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
protected string getStepLabel()
|
||||
{
|
||||
string answ = "";
|
||||
if (OrderSteps != null)
|
||||
{
|
||||
var stepsArray = OrderSteps.ToArray();
|
||||
var currStepInList = OrderSteps.Where(x => x.Value == orderStatus.ToString()).FirstOrDefault();
|
||||
var stepIndex = Array.IndexOf(stepsArray, currStepInList);
|
||||
if (stepIndex != -1)
|
||||
{
|
||||
if (currStepInList?.Value != "70")
|
||||
{
|
||||
var nextStep = stepsArray[stepIndex + 1];
|
||||
answ = nextStep.Label;
|
||||
}
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
protected async void changeOrderStatus(int ordId)
|
||||
{
|
||||
if (OrderSteps != null)
|
||||
{
|
||||
var stepsArray = OrderSteps.ToArray();
|
||||
var currStepInList = OrderSteps.Where(x => x.Value == orderStatus.ToString()).FirstOrDefault();
|
||||
var stepIndex = Array.IndexOf(stepsArray, currStepInList);
|
||||
if (stepIndex != -1)
|
||||
{
|
||||
if (currStepInList?.Value != "70")
|
||||
{
|
||||
var nextStep = stepsArray[stepIndex + 1];
|
||||
bool done = await WDService.OrderUpdateStatus(ordId, int.Parse(nextStep.Value));
|
||||
NavManager.NavigateTo(NavManager.Uri, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
protected async void back2Draft(int ordId)
|
||||
{
|
||||
var confirm = await JSRuntime.InvokeAsync<bool>("confirm", $"Are you sure you want to set the current order status to ORDER DRAFT");
|
||||
if (confirm)
|
||||
{
|
||||
bool done = await WDService.OrderUpdateStatus(ordId, 10);
|
||||
NavManager.NavigateTo(NavManager.Uri, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task setModalShow(int doorId)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>0.9.2306.2808</Version>
|
||||
<Version>0.9.2306.2810</Version>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>aspnet-WebDoorCreator.UI-dfe95fed-1398-4144-bd43-8b3a765d6608</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
Reference in New Issue
Block a user