242 lines
8 KiB
HTML
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>
|