397 lines
23 KiB
HTML
397 lines
23 KiB
HTML
<!doctype html>
|
|
<html lang="it" class="h-full scroll-smooth">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<link rel="icon" type="image/svg+xml" href="./favicon.svg" />
|
|
<title>Servizi Pubblici | home.lucasacchi.net</title>
|
|
<meta
|
|
name="description"
|
|
content="Directory moderna dei servizi pubblici sul dominio home.lucasacchi.net"
|
|
/>
|
|
|
|
<link rel="stylesheet" href="./tailwind.css" />
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Space+Grotesk:wght@500;700&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
|
|
<style>
|
|
:root {
|
|
--bg-0: #061124;
|
|
--bg-1: #0c1b34;
|
|
--bg-2: #13284d;
|
|
--card: rgba(10, 20, 40, 0.7);
|
|
--accent: #6ee7ff;
|
|
--accent-2: #7ef29a;
|
|
}
|
|
|
|
.bg-atmo {
|
|
background:
|
|
radial-gradient(1200px 500px at -10% -10%, rgba(110, 231, 255, 0.22), transparent 45%),
|
|
radial-gradient(900px 420px at 110% -20%, rgba(126, 242, 154, 0.14), transparent 40%),
|
|
linear-gradient(145deg, var(--bg-0), var(--bg-1) 45%, var(--bg-2));
|
|
}
|
|
|
|
.grid-pattern {
|
|
background-image:
|
|
linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
|
|
linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
|
|
background-size: 24px 24px;
|
|
}
|
|
|
|
@keyframes rise {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(12px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.reveal {
|
|
animation: rise 0.45s ease-out both;
|
|
}
|
|
|
|
.font-display {
|
|
font-family: "Space Grotesk", ui-sans-serif, system-ui;
|
|
}
|
|
|
|
.font-body {
|
|
font-family: "Manrope", ui-sans-serif, system-ui;
|
|
}
|
|
|
|
.shadow-glow {
|
|
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 12px 30px rgba(8, 20, 40, 0.28);
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body class="min-h-full bg-atmo text-slate-100 font-body antialiased">
|
|
<div class="min-h-screen grid-pattern">
|
|
<main class="mx-auto w-full max-w-6xl px-4 pb-16 pt-10 sm:px-6 lg:px-8">
|
|
<header class="reveal">
|
|
<p class="inline-flex items-center gap-2 rounded-full border border-cyan-200/20 bg-cyan-300/10 px-3 py-1 text-xs font-semibold tracking-wide text-cyan-100">
|
|
Public Service Directory
|
|
</p>
|
|
<div class="mt-4 flex items-start justify-between gap-4">
|
|
<h1 class="font-display text-4xl font-bold tracking-tight text-white sm:text-5xl">
|
|
home.lucasacchi.net
|
|
</h1>
|
|
<button id="edit-btn" class="mt-1 flex-shrink-0 rounded-xl border border-white/20 bg-slate-800/70 px-4 py-2 text-sm font-semibold text-slate-200 transition hover:border-cyan-300/50 hover:bg-slate-700/70 hover:text-white">
|
|
Modifica
|
|
</button>
|
|
</div>
|
|
<p class="mt-4 max-w-2xl text-sm text-slate-200/90 sm:text-base">
|
|
Elenco dei servizi pubblici individuati nel dominio <span class="font-semibold text-cyan-200">*.home.lucasacchi.net</span>.
|
|
Apertura rapida, ricerca istantanea e visual pulito per desktop e mobile.
|
|
</p>
|
|
</header>
|
|
|
|
<section class="reveal mt-8" style="animation-delay: 90ms">
|
|
<label for="search" class="sr-only">Cerca servizio</label>
|
|
<div class="relative">
|
|
<input
|
|
id="search"
|
|
type="search"
|
|
placeholder="Cerca per nome o URL..."
|
|
class="w-full rounded-2xl border border-white/15 bg-slate-900/60 px-4 py-3 pr-12 text-sm text-slate-100 placeholder:text-slate-400 focus:border-cyan-300/60 focus:outline-none focus:ring-2 focus:ring-cyan-300/40"
|
|
/>
|
|
<span class="pointer-events-none absolute right-4 top-1/2 -translate-y-1/2 text-slate-400">⌕</span>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="mt-8">
|
|
<ul id="service-list" class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
<li class="reveal" style="animation-delay: 140ms" data-name="LogWhispererAI" data-url="https://logwhispererai.lab.home.lucasacchi.net/">
|
|
<a href="https://logwhispererai.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">LogWhispererAI</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">logwhispererai.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 170ms" data-name="n8n Lab" data-url="https://n8n.lab.home.lucasacchi.net">
|
|
<a href="https://n8n.lab.home.lucasacchi.net" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">n8n Lab</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">n8n.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 200ms" data-name="Uptime Home" data-url="http://uptime.lab.home.lucasacchi.net/status/home">
|
|
<a href="http://uptime.lab.home.lucasacchi.net/status/home" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Uptime Home</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">uptime.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 230ms" data-name="Gitea" data-url="https://gitea.lab.home.lucasacchi.net/">
|
|
<a href="https://gitea.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Gitea</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">gitea.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 260ms" data-name="Pastebin" data-url="https://pastebin.lab.home.lucasacchi.net/">
|
|
<a href="https://pastebin.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Pastebin</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">pastebin.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 290ms" data-name="DrawIO" data-url="https://drawio.lab.home.lucasacchi.net/">
|
|
<a href="https://drawio.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">DrawIO</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">drawio.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 320ms" data-name="Tube Archivist" data-url="https://archive.lab.home.lucasacchi.net">
|
|
<a href="https://archive.lab.home.lucasacchi.net" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Tube Archivist</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">archive.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 350ms" data-name="Mattermost" data-url="https://mattermost.lab.home.lucasacchi.net/">
|
|
<a href="https://mattermost.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Mattermost</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">mattermost.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 380ms" data-name="Jitsi" data-url="https://jitsi.lab.home.lucasacchi.net/">
|
|
<a href="https://jitsi.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Jitsi</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">jitsi.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 410ms" data-name="ProxmoxVE" data-url="https://lab.home.lucasacchi.net/">
|
|
<a href="https://lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">ProxmoxVE</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 440ms" data-name="Chatbot OpenWeb-UI" data-url="https://friday.lab.home.lucasacchi.net/">
|
|
<a href="https://friday.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Chatbot OpenWeb-UI</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">friday.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 470ms" data-name="Vikunja" data-url="https://vikunja.lab.home.lucasacchi.net/">
|
|
<a href="https://vikunja.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Vikunja</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">vikunja.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 500ms" data-name="Guacamole" data-url="https://guacamole.lab.home.lucasacchi.net/">
|
|
<a href="https://guacamole.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Guacamole</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">guacamole.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 530ms" data-name="Nexterm" data-url="https://nexterm.home.lucasacchi.net/servers">
|
|
<a href="https://nexterm.home.lucasacchi.net/servers" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Nexterm</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">nexterm.home.lucasacchi.net/servers</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 560ms" data-name="Portainer" data-url="https://portainer.lab.home.lucasacchi.net/#!/auth">
|
|
<a href="https://portainer.lab.home.lucasacchi.net/#!/auth" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Portainer</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">portainer.lab.home.lucasacchi.net/#!/auth</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 590ms" data-name="IT-Tools" data-url="https://it-tools.lab.home.lucasacchi.net/">
|
|
<a href="https://it-tools.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">IT-Tools</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">it-tools.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 620ms" data-name="Proxy Manager" data-url="https://proxymanager.lab.home.lucasacchi.net/">
|
|
<a href="https://proxymanager.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Proxy Manager</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">proxymanager.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 650ms" data-name="Supabase Pinger" data-url="https://supabase-pinger.lab.home.lucasacchi.net/">
|
|
<a href="https://supabase-pinger.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">Supabase Pinger</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">supabase-pinger.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
|
|
<li class="reveal" style="animation-delay: 680ms" data-name="LLM Monitor" data-url="https://llm-monitor.lab.home.lucasacchi.net/">
|
|
<a href="https://llm-monitor.lab.home.lucasacchi.net/" target="_blank" rel="noopener noreferrer" class="group block h-full rounded-2xl border border-white/15 bg-slate-950/55 p-5 shadow-glow transition hover:-translate-y-0.5 hover:border-cyan-200/40 hover:bg-slate-900/70">
|
|
<p class="text-xs font-semibold uppercase tracking-wider text-cyan-200/80">Servizio pubblico</p>
|
|
<h2 class="mt-2 text-lg font-bold text-white">LLM Monitor</h2>
|
|
<p class="mt-2 break-all text-sm text-slate-300">llm-monitor.lab.home.lucasacchi.net</p>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<p id="empty-state" class="mt-6 hidden rounded-xl border border-amber-300/20 bg-amber-200/10 px-4 py-3 text-sm text-amber-100">
|
|
Nessun servizio trovato con il filtro attuale.
|
|
</p>
|
|
</section>
|
|
</main>
|
|
</div>
|
|
|
|
<script>
|
|
const STORAGE_KEY = "service-order";
|
|
const searchInput = document.getElementById("search");
|
|
const list = document.getElementById("service-list");
|
|
const emptyState = document.getElementById("empty-state");
|
|
const editBtn = document.getElementById("edit-btn");
|
|
|
|
// ── Restore saved order ──────────────────────────────────────────────
|
|
function restoreOrder() {
|
|
const saved = localStorage.getItem(STORAGE_KEY);
|
|
if (!saved) return;
|
|
try {
|
|
const order = JSON.parse(saved);
|
|
order.forEach((url) => {
|
|
const item = list.querySelector(`[data-url="${CSS.escape(url)}"]`);
|
|
if (item) list.appendChild(item);
|
|
});
|
|
} catch (_) {}
|
|
}
|
|
restoreOrder();
|
|
|
|
// ── Search ───────────────────────────────────────────────────────────
|
|
function getCards() {
|
|
return Array.from(list.querySelectorAll(":scope > li"));
|
|
}
|
|
|
|
function filterServices(term) {
|
|
const query = term.trim().toLowerCase();
|
|
let visible = 0;
|
|
for (const card of getCards()) {
|
|
const name = card.dataset.name.toLowerCase();
|
|
const url = card.dataset.url.toLowerCase();
|
|
const show = name.includes(query) || url.includes(query);
|
|
card.classList.toggle("hidden", !show);
|
|
if (show) visible += 1;
|
|
}
|
|
emptyState.classList.toggle("hidden", visible > 0);
|
|
}
|
|
|
|
searchInput.addEventListener("input", (e) => filterServices(e.target.value));
|
|
|
|
// ── Drag-and-drop reorder ────────────────────────────────────────────
|
|
let editMode = false;
|
|
let dragging = null;
|
|
|
|
function enableEdit() {
|
|
editMode = true;
|
|
editBtn.textContent = "Salva";
|
|
editBtn.classList.add("border-cyan-300/60", "text-cyan-200");
|
|
searchInput.disabled = true;
|
|
searchInput.classList.add("opacity-40", "pointer-events-none");
|
|
|
|
for (const item of getCards()) {
|
|
item.setAttribute("draggable", "true");
|
|
item.classList.add("cursor-grab", "select-none", "ring-1", "ring-cyan-300/20");
|
|
item.addEventListener("dragstart", onDragStart);
|
|
item.addEventListener("dragenter", onDragEnter);
|
|
item.addEventListener("dragover", onDragOver);
|
|
item.addEventListener("drop", onDrop);
|
|
item.addEventListener("dragend", onDragEnd);
|
|
}
|
|
}
|
|
|
|
function disableEdit() {
|
|
editMode = false;
|
|
editBtn.textContent = "Modifica";
|
|
editBtn.classList.remove("border-cyan-300/60", "text-cyan-200");
|
|
searchInput.disabled = false;
|
|
searchInput.classList.remove("opacity-40", "pointer-events-none");
|
|
|
|
const order = getCards().map((c) => c.dataset.url);
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(order));
|
|
|
|
for (const item of getCards()) {
|
|
item.removeAttribute("draggable");
|
|
item.classList.remove("cursor-grab", "select-none", "ring-1", "ring-cyan-300/20", "opacity-40");
|
|
item.removeEventListener("dragstart", onDragStart);
|
|
item.removeEventListener("dragenter", onDragEnter);
|
|
item.removeEventListener("dragover", onDragOver);
|
|
item.removeEventListener("drop", onDrop);
|
|
item.removeEventListener("dragend", onDragEnd);
|
|
}
|
|
}
|
|
|
|
function onDragStart(e) {
|
|
dragging = this;
|
|
this.classList.add("opacity-40");
|
|
e.dataTransfer.effectAllowed = "move";
|
|
}
|
|
|
|
function onDragEnter(e) {
|
|
e.preventDefault();
|
|
if (this !== dragging) this.classList.add("ring-cyan-300/70");
|
|
}
|
|
|
|
function onDragOver(e) {
|
|
e.preventDefault();
|
|
e.dataTransfer.dropEffect = "move";
|
|
}
|
|
|
|
function onDrop(e) {
|
|
e.preventDefault();
|
|
if (this !== dragging) {
|
|
const items = getCards();
|
|
const fromIdx = items.indexOf(dragging);
|
|
const toIdx = items.indexOf(this);
|
|
if (fromIdx < toIdx) {
|
|
list.insertBefore(dragging, this.nextSibling);
|
|
} else {
|
|
list.insertBefore(dragging, this);
|
|
}
|
|
}
|
|
this.classList.remove("ring-cyan-300/70");
|
|
}
|
|
|
|
function onDragEnd() {
|
|
this.classList.remove("opacity-40");
|
|
for (const item of getCards()) item.classList.remove("ring-cyan-300/70");
|
|
dragging = null;
|
|
}
|
|
|
|
editBtn.addEventListener("click", () => {
|
|
if (editMode) disableEdit(); else enableEdit();
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|