added multiple imballaggi
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class CreateWorkSheetPackages extends AbstractMigration
|
||||
{
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('work_sheet_packages', ['id' => 'id'])
|
||||
->addColumn('worksheet_id', 'integer', ['limit' => 11])
|
||||
->addColumn('package_code', 'integer', ['limit' => 11, 'comment' => 'FK -> packaging_items.id'])
|
||||
->addColumn('package_position', 'integer', ['default' => 1])
|
||||
->addColumn('created_at', 'timestamp', ['default' => 'CURRENT_TIMESTAMP'])
|
||||
->addColumn('updated_at', 'timestamp', ['default' => 'CURRENT_TIMESTAMP', 'update' => 'CURRENT_TIMESTAMP'])
|
||||
->addIndex(['worksheet_id'], ['name' => 'idx_wsp_ws'])
|
||||
->addIndex(['package_code'], ['name' => 'idx_wsp_pkg'])
|
||||
->addIndex(['worksheet_id', 'package_code'], ['unique' => true, 'name' => 'uk_wsp_ws_pkg'])
|
||||
->addIndex(['worksheet_id', 'package_position'], ['unique' => true, 'name' => 'uk_wsp_ws_position'])
|
||||
->addForeignKey('worksheet_id', 'work_sheets', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
|
||||
->addForeignKey('package_code', 'packaging_items', 'id', ['update' => 'CASCADE'])
|
||||
->create();
|
||||
}
|
||||
}
|
||||
@@ -61,3 +61,11 @@ require_once(__DIR__ . '/../../languages/en/general.php');
|
||||
//include("generalsettings.php");
|
||||
require_once __DIR__ . '/permissions_helper.php';
|
||||
require_once(__DIR__ . '/popup-moved.php');
|
||||
|
||||
// Timbra la sessione dell'utente a ogni pagina (rolling manuale)
|
||||
try {
|
||||
$pdoSess = DBHandlerSelect::getInstance()->getConnection();
|
||||
$pdoSess->prepare("UPDATE auth_sessions SET last_activity = ? WHERE user_id = ? ORDER BY last_activity DESC LIMIT 1")
|
||||
->execute([time(), $iduserlogin]);
|
||||
} catch (\Throwable $e) { /* non bloccare la pagina */
|
||||
}
|
||||
|
||||
@@ -327,6 +327,68 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['aj
|
||||
exit;
|
||||
}
|
||||
|
||||
// Add package row
|
||||
if ($action === 'save_package_row') {
|
||||
$worksheet_id = (int)($_POST['worksheet_id'] ?? 0);
|
||||
if ($worksheet_id <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Salva prima il foglio (testata)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$package_code = (int)($_POST['package_code'] ?? 0);
|
||||
if ($package_code <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Seleziona un imballo']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$stmtPos = $pdo->prepare("
|
||||
SELECT IFNULL(MAX(package_position), 0) + 1
|
||||
FROM work_sheet_packages
|
||||
WHERE worksheet_id = ?
|
||||
FOR UPDATE
|
||||
");
|
||||
$stmtPos->execute([$worksheet_id]);
|
||||
$pos = (int)$stmtPos->fetchColumn();
|
||||
if ($pos <= 0) $pos = 1;
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO work_sheet_packages
|
||||
(worksheet_id, package_code, package_position)
|
||||
VALUES (?, ?, ?)
|
||||
");
|
||||
$stmt->execute([$worksheet_id, $package_code, $pos]);
|
||||
} catch (PDOException $ex) {
|
||||
$pdo->rollBack();
|
||||
if ((int)$ex->errorInfo[1] === 1062) {
|
||||
echo json_encode(['success' => false, 'message' => 'Imballo già presente in questo foglio']);
|
||||
exit;
|
||||
}
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Delete package row
|
||||
if ($action === 'delete_package_row') {
|
||||
$row_id = (int)($_POST['row_id'] ?? 0);
|
||||
if ($row_id <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'ID riga non valido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM work_sheet_packages WHERE id = ?");
|
||||
$stmt->execute([$row_id]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => false, 'message' => 'Azione sconosciuta']);
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
@@ -406,6 +468,7 @@ $mescole = $pdo->query("
|
||||
// Load worksheet (edit)
|
||||
$worksheet = null;
|
||||
$mixRows = [];
|
||||
$packageRows = [];
|
||||
|
||||
if ($worksheet_id > 0) {
|
||||
$stmt = $pdo->prepare("
|
||||
@@ -430,6 +493,20 @@ if ($worksheet_id > 0) {
|
||||
");
|
||||
$stmt->execute([$worksheet_id]);
|
||||
$mixRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT
|
||||
wsp.*,
|
||||
pi.item_name AS package_name,
|
||||
pi.item_code AS package_item_code,
|
||||
pi.category AS package_category
|
||||
FROM work_sheet_packages wsp
|
||||
LEFT JOIN packaging_items pi ON pi.id = wsp.package_code
|
||||
WHERE wsp.worksheet_id = ?
|
||||
ORDER BY wsp.package_position ASC, wsp.id ASC
|
||||
");
|
||||
$stmt->execute([$worksheet_id]);
|
||||
$packageRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} else {
|
||||
$worksheet_id = 0;
|
||||
}
|
||||
@@ -1079,10 +1156,56 @@ $isEdit = ($worksheet_id > 0);
|
||||
|
||||
<div class="col-lg-4">
|
||||
<label class="form-label">Elemento imballo</label>
|
||||
<select class="form-select" name="requested_package_code" id="requested_package_code">
|
||||
<select class="form-select" id="requested_package_code">
|
||||
<option value="">-- Prima scegli una categoria --</option>
|
||||
</select>
|
||||
<div class="input-tip">Il valore salvato è il codice dell'elemento</div>
|
||||
<div class="input-tip">Scegli l'elemento e premi "Aggiungi imballo"</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
<label class="form-label d-none d-lg-block"> </label>
|
||||
<button type="button" class="btn w-100" id="btnAddPackage" disabled
|
||||
style="background:linear-gradient(135deg,#ea580c,#f97316);color:#fff;border:0;border-radius:12px;min-height:46px;font-weight:800;box-shadow:0 10px 24px rgba(249,115,22,0.18);">
|
||||
➕ Aggiungi imballo
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="table-wrap">
|
||||
<table class="table table-striped table-bordered mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:70px;">Pos</th>
|
||||
<th>Categoria</th>
|
||||
<th>Imballo</th>
|
||||
<th style="width:120px;">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="packageRowsBody">
|
||||
<?php foreach ($packageRows as $pr): ?>
|
||||
<tr>
|
||||
<td><?= (int)$pr['package_position'] ?></td>
|
||||
<td><?= h($pr['package_category'] ?? '-') ?></td>
|
||||
<td>
|
||||
<div class="fw-bold"><?= h($pr['package_name'] ?? '-') ?></div>
|
||||
<?php if (!empty($pr['package_item_code'])): ?>
|
||||
<div class="text-muted small"><?= h($pr['package_item_code']) ?></div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger delete-package"
|
||||
data-id="<?= (int)$pr['id'] ?>">🗑️</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="input-tip mt-2">Puoi aggiungere più imballi. I dati "metri per confezione", tolleranza, note, ecc. restano unici per il foglio.</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<hr class="my-1">
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-md-6">
|
||||
@@ -1613,6 +1736,121 @@ $isEdit = ($worksheet_id > 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ---- IMBALLI ----
|
||||
const btnAddPackage = $('#btnAddPackage');
|
||||
|
||||
// Sblocca il bottone imballo se la testata è salvata
|
||||
function enablePackageButtonIfSaved() {
|
||||
const id = parseInt(wsIdInput.val() || '0', 10);
|
||||
btnAddPackage.prop('disabled', id <= 0);
|
||||
}
|
||||
enablePackageButtonIfSaved();
|
||||
|
||||
// Ogni volta che salvi la testata, riabilita anche questo bottone
|
||||
const _origEnableMix = enableMixButtonIfSaved;
|
||||
enableMixButtonIfSaved = function() {
|
||||
_origEnableMix();
|
||||
enablePackageButtonIfSaved();
|
||||
};
|
||||
enableMixButtonIfSaved();
|
||||
|
||||
// Click: aggiungi imballo
|
||||
btnAddPackage.on('click', function() {
|
||||
const wsId = parseInt(wsIdInput.val() || '0', 10);
|
||||
if (wsId <= 0) {
|
||||
Swal.fire({
|
||||
icon: 'warning',
|
||||
title: 'Salva prima la testata',
|
||||
timer: 1500
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const packageCode = $('#requested_package_code').val();
|
||||
if (!packageCode) {
|
||||
Swal.fire({
|
||||
icon: 'warning',
|
||||
title: 'Seleziona un imballo',
|
||||
timer: 1500
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: `ajax=1&action=save_package_row&worksheet_id=${wsId}&package_code=${encodeURIComponent(packageCode)}`
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Imballo aggiunto!',
|
||||
timer: 800
|
||||
})
|
||||
.then(() => location.reload());
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: err.message
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Click: elimina imballo
|
||||
$(document).on('click', '.delete-package', function() {
|
||||
const rowId = $(this).data('id');
|
||||
|
||||
Swal.fire({
|
||||
title: 'Eliminare questo imballo dal foglio?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#6c757d',
|
||||
confirmButtonText: 'Sì, elimina',
|
||||
cancelButtonText: 'Annulla'
|
||||
}).then(result => {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
fetch('', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: `ajax=1&action=delete_package_row&row_id=${rowId}`
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Eliminato!',
|
||||
timer: 800
|
||||
})
|
||||
.then(() => location.reload());
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Errore',
|
||||
text: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -9,6 +9,17 @@ $pdo = $db->getConnection();
|
||||
// --- LISTE LINEE ---
|
||||
$linee = $pdo->query("SELECT id, name, color FROM production_lines ORDER BY line_number")->fetchAll();
|
||||
|
||||
// --- LINEA PREFERITA DELL'UTENTE (NULL = Tutte) ---
|
||||
$preferredLineId = null;
|
||||
if (!empty($iduserlogin)) {
|
||||
$stmtPref = $pdo->prepare("SELECT preferred_line_id FROM auth_users WHERE id = :uid LIMIT 1");
|
||||
$stmtPref->execute(['uid' => (int)$iduserlogin]);
|
||||
$val = $stmtPref->fetchColumn();
|
||||
if ($val !== false && $val !== null) {
|
||||
$preferredLineId = (int)$val;
|
||||
}
|
||||
}
|
||||
|
||||
// --- STATUS DINAMICI ---
|
||||
$statusProgrammato = $pdo->query("SELECT id, nome, badge_color, line_color FROM production_status WHERE id = 6 LIMIT 1")->fetch();
|
||||
$statusProduzione = $pdo->query("SELECT id, nome, badge_color, line_color FROM production_status WHERE id = 2 LIMIT 1")->fetch();
|
||||
@@ -988,6 +999,38 @@ if (!empty($_GET['ajax'])) {
|
||||
color: #475569 !important;
|
||||
}
|
||||
|
||||
/* --- TAB LINEE (selezione singola) --- */
|
||||
.line-tab {
|
||||
flex: 1 1 auto;
|
||||
min-width: 130px;
|
||||
padding: 0.9rem 0.5rem;
|
||||
font-size: 1.3rem;
|
||||
font-weight: 800;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 0.9rem 0.9rem 0 0;
|
||||
background: #f1f5f9;
|
||||
color: #64748b;
|
||||
cursor: pointer;
|
||||
transition: 0.15s;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.line-tab:hover {
|
||||
background: #e2e8f0;
|
||||
}
|
||||
|
||||
.line-tab.active {
|
||||
background: var(--line-color, #1d4ed8);
|
||||
color: #fff;
|
||||
border-color: transparent;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
/* il tab "TUTTI" attivo usa un blu neutro */
|
||||
.line-tab[data-line="all"].active {
|
||||
background: #1d4ed8;
|
||||
}
|
||||
|
||||
|
||||
/* Modale più grande e ottimizzata */
|
||||
.custom-modal .modal-content.final-wide {
|
||||
@@ -1329,25 +1372,21 @@ if (!empty($_GET['ajax'])) {
|
||||
</div>
|
||||
|
||||
<div class="filters">
|
||||
<div class="filter-group">
|
||||
<label>Linee</label>
|
||||
|
||||
<div id="lineButtons" style="display:flex; gap:0.8rem;">
|
||||
<div class="filter-group" style="flex:1 1 100%;">
|
||||
<div id="lineTabs" style="display:flex; gap:0.6rem; flex-wrap:wrap;">
|
||||
<button class="line-tab" data-line="all">TUTTI</button>
|
||||
<?php foreach ($linee as $l): ?>
|
||||
<button
|
||||
class="line-btn active"
|
||||
data-line="<?= $l['id'] ?>"
|
||||
<button class="line-tab"
|
||||
data-line="<?= (int)$l['id'] ?>"
|
||||
style="--line-color: <?= htmlspecialchars($l['color']) ?>;">
|
||||
<?= htmlspecialchars($l['name']) ?>
|
||||
</button>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Campo nascosto che userà JS per passare le linee selezionate -->
|
||||
<input type="hidden" id="filterLine" value="">
|
||||
<input type="hidden" id="preferredLine" value="<?= $preferredLineId !== null ? (int)$preferredLineId : '' ?>">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="recordsContainer">
|
||||
@@ -1671,43 +1710,32 @@ if (!empty($_GET['ajax'])) {
|
||||
beep.play().catch(() => {});
|
||||
}
|
||||
|
||||
// --- BOTTONI LINEE ---
|
||||
let selectedLines = [];
|
||||
// --- TAB LINEE (selezione singola) ---
|
||||
// Imposta il filtro nascosto in base al tab: "all" = vuoto (tutte), altrimenti l'id.
|
||||
function setActiveTab($tab) {
|
||||
$('#lineTabs .line-tab').removeClass('active');
|
||||
$tab.addClass('active');
|
||||
const line = $tab.data('line');
|
||||
$('#filterLine').val(line === 'all' ? '' : String(line));
|
||||
}
|
||||
|
||||
// inizialmente selezioniamo tutte
|
||||
$('#lineButtons .line-btn').each(function() {
|
||||
selectedLines.push($(this).data('line'));
|
||||
});
|
||||
$('#filterLine').val(selectedLines.join(','));
|
||||
|
||||
|
||||
// logica pulsanti
|
||||
$(document).on('click', '.line-btn', function() {
|
||||
const id = $(this).data('line');
|
||||
|
||||
if ($(this).hasClass('active')) {
|
||||
// se la deseleziono
|
||||
$(this).removeClass('active').addClass('inactive');
|
||||
selectedLines = selectedLines.filter(l => l !== id);
|
||||
} else {
|
||||
// se la seleziono
|
||||
$(this).removeClass('inactive').addClass('active');
|
||||
selectedLines.push(id);
|
||||
}
|
||||
|
||||
// assicurati che non sia vuoto
|
||||
if (selectedLines.length === 0) {
|
||||
// se deselezionano tutto → riseleziona tutto
|
||||
$('#lineButtons .line-btn').removeClass('inactive').addClass('active');
|
||||
selectedLines = $('#lineButtons .line-btn').map(function() {
|
||||
return $(this).data('line');
|
||||
}).get();
|
||||
}
|
||||
|
||||
$('#filterLine').val(selectedLines.join(','));
|
||||
// Click sui tab
|
||||
$(document).on('click', '.line-tab', function() {
|
||||
setActiveTab($(this));
|
||||
loadRecords();
|
||||
});
|
||||
|
||||
// Tab iniziale: preferita dell'utente se impostata, altrimenti "TUTTI"
|
||||
(function initLineTab() {
|
||||
const pref = $('#preferredLine').val();
|
||||
let $start = $('#lineTabs .line-tab[data-line="all"]');
|
||||
if (pref !== '') {
|
||||
const $prefTab = $('#lineTabs .line-tab[data-line="' + pref + '"]');
|
||||
if ($prefTab.length) $start = $prefTab;
|
||||
}
|
||||
setActiveTab($start);
|
||||
})();
|
||||
|
||||
function escapeHtml(str) {
|
||||
return String(str || '')
|
||||
.replace(/&/g, '&')
|
||||
|
||||
@@ -35,6 +35,15 @@ try {
|
||||
$countries = [];
|
||||
}
|
||||
|
||||
// Load production lines (per la preferenza "Linea preferita").
|
||||
$productionLines = [];
|
||||
try {
|
||||
$productionLines = $pdo->query("SELECT id, name FROM production_lines ORDER BY line_number ASC")
|
||||
->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch (Exception $e) {
|
||||
$productionLines = [];
|
||||
}
|
||||
|
||||
// Load current user.
|
||||
$stmtProfileUser = $pdo->prepare("
|
||||
SELECT
|
||||
@@ -48,6 +57,7 @@ $stmtProfileUser = $pdo->prepare("
|
||||
address,
|
||||
country_id,
|
||||
birthday,
|
||||
preferred_line_id,
|
||||
role_id,
|
||||
status,
|
||||
last_login
|
||||
@@ -126,6 +136,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$address = trim($_POST['address'] ?? '');
|
||||
$countryId = $_POST['country_id'] !== '' ? (int)$_POST['country_id'] : null;
|
||||
$birthday = trim($_POST['birthday'] ?? '');
|
||||
$preferredLineId = (isset($_POST['preferred_line_id']) && $_POST['preferred_line_id'] !== '')
|
||||
? (int)$_POST['preferred_line_id']
|
||||
: null;
|
||||
|
||||
$currentPassword = $_POST['current_password'] ?? '';
|
||||
$newPassword = $_POST['new_password'] ?? '';
|
||||
@@ -240,7 +253,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (!$errorMessage) {
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$stmtUpdate = $pdo->prepare("
|
||||
UPDATE auth_users
|
||||
SET
|
||||
@@ -252,6 +264,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
address = :address,
|
||||
country_id = :country_id,
|
||||
birthday = :birthday,
|
||||
preferred_line_id = :preferred_line_id,
|
||||
updated_at = NOW()
|
||||
WHERE id = :id
|
||||
LIMIT 1
|
||||
@@ -266,6 +279,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
':address' => $address !== '' ? $address : null,
|
||||
':country_id' => $countryId,
|
||||
':birthday' => $birthdayValue,
|
||||
':preferred_line_id' => $preferredLineId,
|
||||
':id' => $userId,
|
||||
]);
|
||||
|
||||
@@ -745,6 +759,20 @@ $avatarPath = normalizeAvatarPath($profileUser['avatar'] ?? '');
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="preferred_line_id">Linea preferita (Line View)</label>
|
||||
<select class="form-select" id="preferred_line_id" name="preferred_line_id">
|
||||
<option value="">Tutte (nessuna preferenza)</option>
|
||||
<?php foreach ($productionLines as $pl): ?>
|
||||
<option value="<?= (int)$pl['id']; ?>"
|
||||
<?= ((int)($profileUser['preferred_line_id'] ?? 0) === (int)$pl['id']) ? 'selected' : ''; ?>>
|
||||
<?= e($pl['name']); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="help-text">La pagina Line View si aprirà su questa linea.</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label class="form-label" for="address">Indirizzo</label>
|
||||
<input type="text"
|
||||
|
||||
Reference in New Issue
Block a user