3rd ed.
This commit is contained in:
parent
dfaf542c4b
commit
045977f9fb
7 changed files with 933 additions and 762 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -18,9 +18,9 @@ ios/
|
||||||
www/
|
www/
|
||||||
|
|
||||||
# Environment files
|
# Environment files
|
||||||
.env
|
#.env
|
||||||
.env.*
|
#.env.*
|
||||||
!.env.example
|
#!.env.example
|
||||||
|
|
||||||
# System files
|
# System files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
|
||||||
701
app/app.js
701
app/app.js
File diff suppressed because it is too large
Load diff
|
|
@ -14,6 +14,8 @@
|
||||||
<div id="setup-page" class="hidden">
|
<div id="setup-page" class="hidden">
|
||||||
<h2>Configurazione</h2>
|
<h2>Configurazione</h2>
|
||||||
|
|
||||||
|
<button id="cfg-refresh">Aggiorna ora</button>
|
||||||
|
|
||||||
<label>URL</label>
|
<label>URL</label>
|
||||||
<input id="cfg-url" type="text">
|
<input id="cfg-url" type="text">
|
||||||
|
|
||||||
|
|
@ -37,5 +39,10 @@
|
||||||
</div>
|
</div>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
|
|
||||||
|
<!-- --> <script src="https://cdn.jsdelivr.net/npm/eruda"></script>
|
||||||
|
<script>
|
||||||
|
eruda.init();
|
||||||
|
</script> <!-- -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
4
app/start.sh
Executable file
4
app/start.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Avvia un server HTTP sulla porta 11002 senza cache
|
||||||
|
npx http-server . -c-1 -p 11002
|
||||||
|
|
@ -254,3 +254,6 @@ html, body {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#cfg-refresh {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
|
||||||
16
server/backend/.env
Normal file
16
server/backend/.env
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# === SERVER CONFIG ===
|
||||||
|
PORT=11001
|
||||||
|
|
||||||
|
# === JWT CONFIG ===
|
||||||
|
# Cambialo SEMPRE in produzione
|
||||||
|
JWT_SECRET=master66
|
||||||
|
|
||||||
|
# === MONGO CONFIG ===
|
||||||
|
# In locale:
|
||||||
|
# MONGO_URI=mongodb://localhost:27017/mydb
|
||||||
|
#
|
||||||
|
# In Docker (usato dal docker-compose):
|
||||||
|
MONGO_URI=mongodb://root:example@192.168.1.3:27017/myapphttps?authSource=admin
|
||||||
|
# === UPLOADS ===
|
||||||
|
# Cartella dove Express serve le icone
|
||||||
|
UPLOAD_DIR=uploads
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
import {
|
|
||||||
login,
|
|
||||||
register,
|
|
||||||
getLinks,
|
|
||||||
createLink,
|
|
||||||
deleteLink,
|
|
||||||
updateLink
|
|
||||||
} from "./api.js";
|
|
||||||
|
|
||||||
const authSection = document.getElementById("authSection");
|
|
||||||
const linkSection = document.getElementById("linkSection");
|
|
||||||
const authStatus = document.getElementById("authStatus");
|
|
||||||
const list = document.getElementById("list");
|
|
||||||
|
|
||||||
let token = null;
|
|
||||||
|
|
||||||
// ------------------------------
|
|
||||||
// AUTH
|
|
||||||
// ------------------------------
|
|
||||||
|
|
||||||
function setToken(t) {
|
|
||||||
token = t;
|
|
||||||
if (token) {
|
|
||||||
authSection.style.display = "none";
|
|
||||||
linkSection.style.display = "block";
|
|
||||||
loadLinks();
|
|
||||||
} else {
|
|
||||||
authSection.style.display = "block";
|
|
||||||
linkSection.style.display = "none";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("loginForm").addEventListener("submit", async e => {
|
|
||||||
e.preventDefault();
|
|
||||||
const email = e.target.email.value;
|
|
||||||
const password = e.target.password.value;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const t = await login(email, password);
|
|
||||||
setToken(t);
|
|
||||||
} catch (err) {
|
|
||||||
authStatus.textContent = err.message;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById("registerForm").addEventListener("submit", async e => {
|
|
||||||
e.preventDefault();
|
|
||||||
const email = e.target.email.value;
|
|
||||||
const password = e.target.password.value;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await register(email, password);
|
|
||||||
authStatus.textContent = "Registrato! Ora effettua il login.";
|
|
||||||
} catch (err) {
|
|
||||||
authStatus.textContent = err.message;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// ------------------------------
|
|
||||||
// LINKS
|
|
||||||
// ------------------------------
|
|
||||||
|
|
||||||
async function loadLinks() {
|
|
||||||
const links = await getLinks(token);
|
|
||||||
|
|
||||||
list.innerHTML = links
|
|
||||||
.map(
|
|
||||||
link => `
|
|
||||||
<div class="item">
|
|
||||||
${link.icon ? `<img src="http://192.168.1.3:3000${link.icon}">` : ""}
|
|
||||||
<div>
|
|
||||||
<strong>${link.name}</strong><br>
|
|
||||||
<a href="${link.url}" target="_blank">${link.url}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
)
|
|
||||||
.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("linkForm").addEventListener("submit", async e => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const formData = new FormData(e.target);
|
|
||||||
const iconFile = formData.get("icon");
|
|
||||||
|
|
||||||
await createLink(token, {
|
|
||||||
name: formData.get("name"),
|
|
||||||
url: formData.get("url"),
|
|
||||||
iconFile: iconFile.size > 0 ? iconFile : null
|
|
||||||
});
|
|
||||||
|
|
||||||
e.target.reset();
|
|
||||||
loadLinks();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Init
|
|
||||||
setToken(null);
|
|
||||||
Loading…
Reference in a new issue