multi_static_website/home/settings.html
2025-12-23 13:06:25 +01:00

242 lines
8 KiB
HTML

<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Sites Dashboard</title>
<link rel="stylesheet" href="style1.css">
</head>
<body>
<h1>Sites Settings</h1>
<div id="grid" class="grid"></div>
<!-- Modal: Aggiungi (esistente) -->
<div id="addModal" class="modal hidden">
<div class="modal-content">
<h2>Aggiungi nuovo sito</h2>
<form id="addForm">
<label>
URL:
<input type="text" id="siteUrl" required />
</label>
<label>
Dir:
<input type="text" id="siteDir" required />
</label>
<div class="actions">
<button type="submit">Salva</button>
<button type="button" id="closeModal">Chiudi</button>
</div>
</form>
</div>
</div>
<!-- Modal: Conferma cancellazione -->
<div id="delModal" class="modal hidden" data-modal>
<div class="modal-content">
<h2>Conferma cancellazione</h2>
<p id="delQuestion">Vuoi davvero cancellare questo sito?</p>
<div class="actions">
<button type="button" id="confirmDelete" class="danger">Sì, cancella</button>
<button type="button" data-close="delModal">Annulla</button>
</div>
</div>
</div>
<script type="module">
// ------------ Helpers: modal handling ------------
function openModal(id) {
const m = document.getElementById(id);
if (!m) return;
m.classList.remove('hidden');
}
function closeModal(id) {
const m = document.getElementById(id);
if (!m) return;
m.classList.add('hidden');
}
// Close modal when clicking on overlay
document.addEventListener('click', (e) => {
const modalEl = e.target.closest('[data-modal]');
if (!modalEl && e.target.classList.contains('modal')) {
e.target.classList.add('hidden');
}
});
// Close modal by buttons with data-close
document.addEventListener('click', (e) => {
const closeId = e.target.getAttribute('data-close');
if (closeId) closeModal(closeId);
});
// Close on Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
document.querySelectorAll('.modal').forEach(m => m.classList.add('hidden'));
}
});
// ------------ State for selected site ------------
let selectedSite = null; // the site object currently selected for delete/edit
// ------------ Load and render sites ------------
async function loadSites() {
const res = await fetch('./sites.json', { cache: 'no-store' });
const sites = await res.json();
const grid = document.getElementById('grid');
grid.innerHTML = '';
sites.forEach(site => {
// Expecting: site.name, site.icon, site.url (optional), site.dir, and maybe site.shortName/defaultFile
const card = document.createElement('div');
card.className = 'card';
const img = document.createElement('img');
img.src = site.icon;
img.alt = site.name;
// mostra mod.png quando sei sopra la card
const originalSrc = site.icon;
card.addEventListener('mouseenter', () => {
if (!card.classList.contains('add-card')) {
img.src = 'mod.png';
}
});
card.addEventListener('mouseleave', () => {
img.src = originalSrc;
});
const title = document.createElement('div');
title.className = 'title';
title.textContent = site.name;
card.appendChild(img);
card.appendChild(title);
// --- Interaction rules (excluding + card) ---
// 1) Click/tap → open Delete modal
// 2) Long-press → open Edit manifest modal
// Robust long-press with pointer events (mouse & touch)
let pressTimer = null;
let longPressed = false;
const LONG_PRESS_MS = 600;
const startPress = async (e) => {
longPressed = false;
clearTimeout(pressTimer);
pressTimer = setTimeout(async () => {
longPressed = true;
selectedSite = site;
const url = new URL('/manifest', window.location.origin);
url.searchParams.set('dir',selectedSite.dir);
window.location.assign(url.toString());
}, LONG_PRESS_MS);
};
const endPress = (e) => {
clearTimeout(pressTimer);
if (!longPressed) {
// treat as click → delete
selectedSite = site;
const q = document.getElementById('delQuestion');
q.textContent = `Vuoi davvero cancellare il sito "${site.name}" (dir: ${site.dir})?`;
openModal('delModal');
}
};
const cancelPress = () => {
clearTimeout(pressTimer);
};
card.addEventListener('pointerdown', startPress);
card.addEventListener('pointerup', endPress);
card.addEventListener('pointerleave', cancelPress);
card.addEventListener('pointercancel', cancelPress);
// prevent context menu from interfering on desktop long-press
card.addEventListener('contextmenu', (e) => e.preventDefault());
grid.appendChild(card);
});
// --- "+" Add card ---
const addCard = document.createElement('div');
addCard.className = 'card add-card';
const plus = document.createElement('div');
plus.className = 'plus-icon';
plus.textContent = '+';
const addTitle = document.createElement('div');
addTitle.className = 'title';
addTitle.textContent = 'Aggiungi';
addCard.appendChild(plus);
addCard.appendChild(addTitle);
addCard.addEventListener('click', () => {
document.getElementById('addModal').classList.remove('hidden');
});
grid.appendChild(addCard);
}
// Initial load
loadSites();
// ------------ Add-site modal handlers (existing) ------------
const addModal = document.getElementById('addModal');
const closeBtn = document.getElementById('closeModal');
closeBtn.addEventListener('click', () => addModal.classList.add('hidden'));
const addForm = document.getElementById('addForm');
addForm.addEventListener('submit', async (e) => {
e.preventDefault();
const url = document.getElementById('siteUrl').value.trim();
const dir = document.getElementById('siteDir').value.trim();
if (!url || !dir) return;
const res = await fetch('/add-site', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url, dir })
});
if (res.ok) {
alert('Sito aggiunto con successo!');
addModal.classList.add('hidden');
await loadSites();
//window.parent.refreshSideBar();
window.parent.postMessage("refreshSideBar", "*");
} else {
const msg = await safeText(res);
alert('Errore nell\'aggiunta del sito: ' + msg);
}
});
async function safeText(res) {
try { return await res.text(); } catch { return ''; }
}
// ------------ Delete confirmation handlers ------------
document.getElementById('confirmDelete').addEventListener('click', async () => {
if (!selectedSite || !selectedSite.dir) {
alert('Nessun sito selezionato o dir mancante.');
return;
}
const res = await fetch('/del-site', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ dir: selectedSite.dir })
});
if (res.ok) {
closeModal('delModal');
selectedSite = null;
await loadSites();
//window.parent.refreshSideBar();
window.parent.postMessage("refreshSideBar", "*");
} else {
const msg = await safeText(res);
alert('Errore nella cancellazione: ' + msg);
}
});
</script>
</body>