Ellenőrzés lezárása
This commit is contained in:
@@ -130,8 +130,25 @@ namespace WorkFlowCheck.API.Controllers
|
|||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
[HttpPost("CloseCheckListHeader")]
|
||||||
|
public async Task<ApiResponseDTO<bool>> CloseCheckListHeader([FromBody] CheckListHeaderCloseDTO checkListHeaderCloseDTO)
|
||||||
|
{
|
||||||
|
var retVal = new ApiResponseDTO<bool>() { IsSuccess = false };
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _checkListService.CloseCheckListHeader(checkListHeaderCloseDTO);
|
||||||
|
retVal.Data = result;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
retVal.IsSuccess = false;
|
||||||
|
Log.Error(ex.Message);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("AcceptCheckListHeader/{id}/{userId}")]
|
[HttpGet("AcceptCheckListHeader/{id}/{userId}")]
|
||||||
public async Task<ApiResponseDTO<bool>> AcceptCheckListHeader(int id, int userId)
|
public async Task<ApiResponseDTO<bool>> AcceptCheckListHeader(int id, int userId)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using DocumentFormat.OpenXml.Office.CustomUI;
|
using DocumentFormat.OpenXml.Office.CustomUI;
|
||||||
|
using DocumentFormat.OpenXml.Office2010.Excel;
|
||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -362,7 +363,38 @@ namespace WorkFlowCheck.BL.Services
|
|||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
public async Task<bool> CloseCheckListHeader(CheckListHeaderCloseDTO closeCheckListHeaderCloseDTO)
|
||||||
|
{
|
||||||
|
var retVal = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var checkListHeader = await _dbContext.CheckListHeaders
|
||||||
|
.Where(w => w.Id == closeCheckListHeaderCloseDTO.Id &&
|
||||||
|
(w.CheckStatus == CheckStatus.Blocked ||
|
||||||
|
w.CheckStatus == CheckStatus.InProgress ||
|
||||||
|
w.CheckStatus == CheckStatus.Open
|
||||||
|
))
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (checkListHeader != null)
|
||||||
|
{
|
||||||
|
checkListHeader.CheckStatus = CheckStatus.Closed;
|
||||||
|
checkListHeader.IsEditable = true;
|
||||||
|
|
||||||
|
Log.Warning($"Ellenőrzési lap lezárva: Ellenőrzés:{closeCheckListHeaderCloseDTO.Id}, " +
|
||||||
|
$" Felhasználó:{closeCheckListHeaderCloseDTO.UserId}");
|
||||||
|
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
retVal = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
retVal = false;
|
||||||
|
Log.Error(ex.Message);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
public async Task<CheckListTemplateHeaderDTO> GetCheckListTemplateHeaderAsync(int Id)
|
public async Task<CheckListTemplateHeaderDTO> GetCheckListTemplateHeaderAsync(int Id)
|
||||||
{
|
{
|
||||||
var retVal = new CheckListTemplateHeaderDTO()
|
var retVal = new CheckListTemplateHeaderDTO()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace WorkFlowCheck.BL.Services.Interfaces
|
|||||||
Task<bool> AcceptCheckListHeaderAsync(int id, int userid);
|
Task<bool> AcceptCheckListHeaderAsync(int id, int userid);
|
||||||
Task<bool> BlockCheckListHeaderAsync(int id, int userid);
|
Task<bool> BlockCheckListHeaderAsync(int id, int userid);
|
||||||
Task<bool> UnBlockCheckListHeaderAsync(int id, int userid);
|
Task<bool> UnBlockCheckListHeaderAsync(int id, int userid);
|
||||||
|
Task<bool> CloseCheckListHeader(CheckListHeaderCloseDTO closeCheckListHeaderCloseDTO);
|
||||||
Task<byte[]> CreateCheckListHeaderPDFAsync(int checkListHeaderId);
|
Task<byte[]> CreateCheckListHeaderPDFAsync(int checkListHeaderId);
|
||||||
Task<CheckListHeaderDTO> StartNewCheckListAsync(CheckListHeaderNewDTO checkListHeaderNewDTO);
|
Task<CheckListHeaderDTO> StartNewCheckListAsync(CheckListHeaderNewDTO checkListHeaderNewDTO);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WorkFlowCheck.Common.DTO
|
||||||
|
{
|
||||||
|
public class CheckListHeaderCloseDTO
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string CloseReason { get; set; } = null!;
|
||||||
|
public int UserId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,13 @@
|
|||||||
@model WorkFlowCheck.Web.Pages.CheckList.CheckListHeader.CheckListHeaderPageModel
|
@model WorkFlowCheck.Web.Pages.CheckList.CheckListHeader.CheckListHeaderPageModel
|
||||||
@using WorkFlowCheck.Common.Helper
|
@using WorkFlowCheck.Common.Helper
|
||||||
@using WorkFlowCheck.Common.DTO
|
@using WorkFlowCheck.Common.DTO
|
||||||
|
@using Microsoft.AspNetCore.Antiforgery
|
||||||
|
@inject IAntiforgery Antiforgery
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Ellenőrzések";
|
ViewData["Title"] = "Ellenőrzések";
|
||||||
}
|
}
|
||||||
<h1>@ViewData["Title"]</h1>
|
<h1>@ViewData["Title"]</h1>
|
||||||
|
<meta name="csrf-token" content="@Antiforgery.GetAndStoreTokens(HttpContext).RequestToken" />
|
||||||
<div class="card shadow p-4">
|
<div class="card shadow p-4">
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<button id="newCheckListHeaderBtn" class="btn btn-primary float-right new-btn" data-bs-toggle="tooltip" data-bs-placement="top" title="Új elem hozzáadása">
|
<button id="newCheckListHeaderBtn" class="btn btn-primary float-right new-btn" data-bs-toggle="tooltip" data-bs-placement="top" title="Új elem hozzáadása">
|
||||||
@@ -123,6 +125,60 @@
|
|||||||
window.location.href = `@Url.Page("./CheckListHeaderPage")?handler=CreatePDF&id=${row.id}`;
|
window.location.href = `@Url.Page("./CheckListHeaderPage")?handler=CreatePDF&id=${row.id}`;
|
||||||
|
|
||||||
});
|
});
|
||||||
|
$('#tbCheckListHeadersPage').on('click', '.close-btn', function ()
|
||||||
|
{
|
||||||
|
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||||
|
const row = table.row($(this).closest('tr')).data();
|
||||||
|
const title = `Biztosan le akarja zárni az ellenőrzést? (${row.documentNumber})`;
|
||||||
|
const url = `@Url.Page("./CheckListHeaderPage")?handler=Close`;
|
||||||
|
showConfirmModalWithMessage({
|
||||||
|
title: title,
|
||||||
|
message: 'Kérlek, indokold meg:',
|
||||||
|
okText: 'Elküld',
|
||||||
|
cancelText: 'Mégsem'
|
||||||
|
}).then(function (result) {
|
||||||
|
if (result.action === 'ok') {
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
type: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': csrfToken,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data: JSON.stringify({
|
||||||
|
Id: row.id,
|
||||||
|
CloseReason: result.text,
|
||||||
|
UserId: 0,
|
||||||
|
}),
|
||||||
|
success: function(data) {
|
||||||
|
if (data) {
|
||||||
|
showMessageModal({
|
||||||
|
title: 'Információ',
|
||||||
|
message: 'A lezárás sikerült!',
|
||||||
|
okText: 'Értettem'
|
||||||
|
});
|
||||||
|
table.ajax.reload();
|
||||||
|
} else {
|
||||||
|
showMessageModal({
|
||||||
|
title: 'Hiba!',
|
||||||
|
message: 'A lezárás NEM sikerült!',
|
||||||
|
okText: 'Értettem'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
showMessageModal({
|
||||||
|
title: 'Hiba!',
|
||||||
|
message: 'A lezárás NEM sikerült!',
|
||||||
|
okText: 'Értettem'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$('#tbCheckListHeadersPage').on('click', '.accept-btn', function ()
|
$('#tbCheckListHeadersPage').on('click', '.accept-btn', function ()
|
||||||
{
|
{
|
||||||
@@ -253,20 +309,6 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#tbCheckListHeadersPage').on('click', '.delete-btn', function ()
|
|
||||||
{
|
|
||||||
const row = table.row($(this).closest('tr')).data();
|
|
||||||
|
|
||||||
showConfirmModal({
|
|
||||||
title: 'Törlés megerősítése',
|
|
||||||
message: 'Biztosan törölni szeretnéd ezt az elemet?',
|
|
||||||
okText: 'Törlés',
|
|
||||||
cancelText: 'Mégsem'
|
|
||||||
}).then(function(result) {
|
|
||||||
if(result === 'ok') {
|
|
||||||
console.log('Törlés végrehajtva');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Reflection;
|
|||||||
using WorkFlowCheck.Common.Enums;
|
using WorkFlowCheck.Common.Enums;
|
||||||
using WorkFlowCheck.Web.Services.Interfaces;
|
using WorkFlowCheck.Web.Services.Interfaces;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using WorkFlowCheck.Common.DTO;
|
||||||
namespace WorkFlowCheck.Web.Pages.CheckList.CheckListHeader
|
namespace WorkFlowCheck.Web.Pages.CheckList.CheckListHeader
|
||||||
{
|
{
|
||||||
public class CheckListHeaderPageModel : PageModel
|
public class CheckListHeaderPageModel : PageModel
|
||||||
@@ -87,6 +88,22 @@ namespace WorkFlowCheck.Web.Pages.CheckList.CheckListHeader
|
|||||||
var userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
var userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
var response = await _checkListService.UnBlockCheckListHeader(id, int.Parse(userid));
|
var response = await _checkListService.UnBlockCheckListHeader(id, int.Parse(userid));
|
||||||
|
|
||||||
|
if (response.IsSuccess)
|
||||||
|
{
|
||||||
|
return new JsonResult(new { success = response.Data });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new JsonResult(new { success = false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task<IActionResult> OnPostClose([FromBody] CheckListHeaderCloseDTO checkListHeaderCloseDTO)
|
||||||
|
{
|
||||||
|
var userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
checkListHeaderCloseDTO.UserId=int.Parse(userid); ;
|
||||||
|
|
||||||
|
var response = await _checkListService.CloseCheckListHeader(checkListHeaderCloseDTO);
|
||||||
|
|
||||||
if (response.IsSuccess)
|
if (response.IsSuccess)
|
||||||
{
|
{
|
||||||
return new JsonResult(new { success = response.Data });
|
return new JsonResult(new { success = response.Data });
|
||||||
|
|||||||
@@ -133,6 +133,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Confirm Modal With Message-->
|
||||||
|
<div class="modal fade" id="confirmModalWithMessage" tabindex="-1" aria-labelledby="confirmModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="confirmModalLabel">Megerősítés</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Bezárás"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" id="confirmModalBody">
|
||||||
|
<label for="confirmModalTextarea" class="form-label">Írd le a megjegyzést vagy indoklást:</label>
|
||||||
|
<textarea class="form-control" id="confirmModalTextarea" rows="4" placeholder="Írd ide..."></textarea>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
A mező kitöltése kötelező.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" id="confirmModalCancelBtn" data-bs-dismiss="modal">Mégsem</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="confirmModalOkBtn">Igen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Message Modal -->
|
<!-- Message Modal -->
|
||||||
<div class="modal fade" id="messageModal" tabindex="-1" aria-labelledby="messageModalLabel" aria-hidden="true">
|
<div class="modal fade" id="messageModal" tabindex="-1" aria-labelledby="messageModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
|||||||
@@ -123,7 +123,34 @@ namespace WorkFlowCheck.Web.Services
|
|||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
public async Task<ApiResponseDTO<bool>> CloseCheckListHeader(CheckListHeaderCloseDTO checkListHeaderCloseDTO)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string endpoint = $"{_httpClient.BaseAddress}api/CheckList/CloseCheckListHeader";
|
||||||
|
|
||||||
|
using (HttpResponseMessage httpResponseMessage = await _httpClient.PostAsJsonAsync(endpoint, checkListHeaderCloseDTO))
|
||||||
|
{
|
||||||
|
httpResponseMessage.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var jsonString = await httpResponseMessage.Content.ReadAsStringAsync();
|
||||||
|
var response = JsonConvert.DeserializeObject<ApiResponseDTO<bool>>(jsonString);
|
||||||
|
|
||||||
|
return response ?? new ApiResponseDTO<bool>
|
||||||
|
{
|
||||||
|
IsSuccess = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Hiba visszaadása
|
||||||
|
return new ApiResponseDTO<bool>
|
||||||
|
{
|
||||||
|
IsSuccess = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
public async Task<ApiResponseDTO<byte[]>> CreatePDF(int id)
|
public async Task<ApiResponseDTO<byte[]>> CreatePDF(int id)
|
||||||
{
|
{
|
||||||
var retVal = new ApiResponseDTO<byte[]>();
|
var retVal = new ApiResponseDTO<byte[]>();
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace WorkFlowCheck.Web.Services.Interfaces
|
|||||||
Task<ApiResponseDTO<bool>> AcceptCheckListHeader(int id, int userid);
|
Task<ApiResponseDTO<bool>> AcceptCheckListHeader(int id, int userid);
|
||||||
Task<ApiResponseDTO<bool>> BlockCheckListHeader(int id, int userid);
|
Task<ApiResponseDTO<bool>> BlockCheckListHeader(int id, int userid);
|
||||||
Task<ApiResponseDTO<bool>> UnBlockCheckListHeader(int id, int userid);
|
Task<ApiResponseDTO<bool>> UnBlockCheckListHeader(int id, int userid);
|
||||||
|
Task<ApiResponseDTO<bool>> CloseCheckListHeader(CheckListHeaderCloseDTO checkListHeaderCloseDTO);
|
||||||
|
|
||||||
|
|
||||||
Task<CheckListTemplateHeaderDTO> GetCheckListTemplateHeader(int id);
|
Task<CheckListTemplateHeaderDTO> GetCheckListTemplateHeader(int id);
|
||||||
|
|||||||
@@ -72,6 +72,62 @@ function showConfirmModal(options) {
|
|||||||
modal.show();
|
modal.show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showConfirmModalWithMessage(options) {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
// Alapértelmezett értékek
|
||||||
|
var defaults = {
|
||||||
|
title: 'Megerősítés',
|
||||||
|
message: 'Biztos vagy benne?',
|
||||||
|
okText: 'Igen',
|
||||||
|
cancelText: 'Mégsem'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Opciók összeolvasztása
|
||||||
|
var settings = $.extend({}, defaults, options);
|
||||||
|
|
||||||
|
// Beállítások betöltése a modalba
|
||||||
|
$('#confirmModalLabel').text(settings.title);
|
||||||
|
$('#confirmModalBody').html(`
|
||||||
|
<label for="confirmModalTextarea" class="form-label">${settings.message}</label>
|
||||||
|
<textarea class="form-control" id="confirmModalTextarea" rows="4" placeholder="Írd ide..."></textarea>
|
||||||
|
<div class="invalid-feedback">A mező kitöltése kötelező.</div>
|
||||||
|
`);
|
||||||
|
$('#confirmModalOkBtn').text(settings.okText);
|
||||||
|
$('#confirmModalCancelBtn').text(settings.cancelText);
|
||||||
|
|
||||||
|
// Események letisztítása
|
||||||
|
$('#confirmModalOkBtn').off('click');
|
||||||
|
$('#confirmModalCancelBtn').off('click');
|
||||||
|
|
||||||
|
// OK gomb esemény
|
||||||
|
$('#confirmModalOkBtn').on('click', function () {
|
||||||
|
var text = $('#confirmModalTextarea').val().trim();
|
||||||
|
if (text === '') {
|
||||||
|
$('#confirmModalTextarea').addClass('is-invalid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$('#confirmModalTextarea').removeClass('is-invalid');
|
||||||
|
|
||||||
|
$('#confirmModal').modal('hide');
|
||||||
|
resolve({ action: 'ok', text: text });
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cancel gomb esemény
|
||||||
|
$('#confirmModalCancelBtn').on('click', function () {
|
||||||
|
$('#confirmModal').modal('hide');
|
||||||
|
resolve({ action: 'cancel' });
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modal megjelenítése
|
||||||
|
var modal = new bootstrap.Modal(document.getElementById('confirmModal'), {
|
||||||
|
backdrop: 'static',
|
||||||
|
keyboard: false
|
||||||
|
});
|
||||||
|
modal.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function showMessageModal(options) {
|
function showMessageModal(options) {
|
||||||
// Alapértelmezett értékek
|
// Alapértelmezett értékek
|
||||||
var defaults = {
|
var defaults = {
|
||||||
@@ -132,6 +188,9 @@ function renderActionButtonsforCheckListHeader(data, rowId) {
|
|||||||
</button>
|
</button>
|
||||||
<button class="btn btn-success unblock-btn btn-sm" data-id="${rowId}">
|
<button class="btn btn-success unblock-btn btn-sm" data-id="${rowId}">
|
||||||
<i class="bi bi-arrow-clockwise"></i>
|
<i class="bi bi-arrow-clockwise"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary close-btn btn-sm" data-id="${rowId}">
|
||||||
|
<i class="bi bi-x-lg"></i>
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
if (data === 1) {
|
if (data === 1) {
|
||||||
@@ -149,12 +208,15 @@ function renderActionButtonsforCheckListHeader(data, rowId) {
|
|||||||
<i class="bi bi-file-earmark-pdf-fill"></i>
|
<i class="bi bi-file-earmark-pdf-fill"></i>
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
if (data === 3) {
|
if (data === 3 || data === 6) {
|
||||||
return ``;
|
return ``;
|
||||||
}
|
}
|
||||||
return `
|
return `
|
||||||
<button class="btn btn-primary edit-btn btn-sm" data-id="${rowId}">
|
<button class="btn btn-primary edit-btn btn-sm" data-id="${rowId}">
|
||||||
<i class="bi bi-pencil-fill"></i>
|
<i class="bi bi-pencil-fill"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary close-btn btn-sm" data-id="${rowId}">
|
||||||
|
<i class="bi bi-x-lg"></i>
|
||||||
</button>`;
|
</button>`;
|
||||||
//<button class="btn btn-danger delete-btn btn-sm" data-id="${rowId}">
|
//<button class="btn btn-danger delete-btn btn-sm" data-id="${rowId}">
|
||||||
// <i class="bi bi-trash-fill"></i>
|
// <i class="bi bi-trash-fill"></i>
|
||||||
|
|||||||
Reference in New Issue
Block a user