7 Commits

Author SHA1 Message Date
naielv
def79a2015 update 2025-07-31 17:02:09 +02:00
naielv
64d11fe224 Add comedor to ResumenDiario & fix unclosed tags 2025-07-31 16:56:24 +02:00
naielv
a016e06557 General fixes 2025-07-31 16:43:01 +02:00
naielv
a274de3c4d Actualizar build.py 2025-07-30 23:04:01 +02:00
naielv
0f2b2df969 fix scrolltable 2025-07-30 22:47:37 +02:00
naielv
8052d21fcc oops 2025-07-30 22:46:42 +02:00
naielv
03c132a6bd update 2025-07-30 22:38:25 +02:00
19 changed files with 619 additions and 584 deletions

View File

@@ -1,85 +0,0 @@
[
"icon512_maskable.png",
"icon512_rounded.png",
"manifest.json",
"static/axe.js",
"static/doublescroll.js",
"static/gun.js",
"static/jquery.js",
"static/load.js",
"static/open.js",
"static/path.js",
"static/radisk.js",
"static/radix.js",
"static/rindexed.js",
"static/sea.js",
"static/showdown.min.js",
"static/simplemde.min.css",
"static/simplemde.min.js",
"static/store.js",
"static/synchronous.js",
"static/TeleSec.jpg",
"static/toastr.min.css",
"static/toastr.min.js",
"static/webrtc.js",
"static/yson.js",
"static/ico/add.png",
"static/ico/azucar-moreno.png",
"static/ico/azucar-blanco.jpg",
"static/ico/stevia.jpg",
"static/ico/stevia-gotas.webp",
"static/ico/sacarina.jpg",
"static/ico/arrow_down_blue.png",
"static/ico/arrow_left_green.png",
"static/ico/arrow_up_red.png",
"static/ico/camera2.png",
"static/ico/cereales.png",
"static/ico/checkbox.png",
"static/ico/checkbox_unchecked.png",
"static/ico/connect_ok.svg",
"static/ico/connect_ko.svg",
"static/ico/coffee_bean.png",
"static/ico/colacao.jpg",
"static/ico/cookies.png",
"static/ico/cow.png",
"static/ico/delete.png",
"static/ico/fire.png",
"static/ico/keyboard_key_g.png",
"static/ico/keyboard_key_p.png",
"static/ico/lollipop.png",
"static/ico/milk.png",
"static/ico/preferences.png",
"static/ico/sizes.png",
"static/ico/statusok.png",
"static/ico/snowflake.png",
"static/ico/tea_bag.png",
"static/ico/thermometer2.png",
"static/ico/user.png",
"static/ico/user_generic.png",
"static/ico/water_tap.png",
"static/ico/wheat.png",
"static/ico/layered1/Azucar-Az. Blanco.png",
"static/ico/layered1/Azucar-Az. Moreno.png",
"static/ico/layered1/Azucar-Edulcorante.png",
"static/ico/layered1/Azucar-Sacarina.png",
"static/ico/layered1/Azucar-Sin.png",
"static/ico/layered1/Azucar-Stevia (Gotas).png",
"static/ico/layered1/Azucar-Stevia (Pastillas).png",
"static/ico/layered1/Background.png",
"static/ico/layered1/Cafeina-Con.png",
"static/ico/layered1/Cafeina-Sin.png",
"static/ico/layered1/Leche-Agua.png",
"static/ico/layered1/Leche-Sin lactosa.png",
"static/ico/layered1/Leche-Vegetal.png",
"static/ico/layered1/Leche-de Vaca.png",
"static/ico/layered1/Selección-CafeSolo.png",
"static/ico/layered1/Selección-CaféLeche.png",
"static/ico/layered1/Selección-ColaCao.png",
"static/ico/layered1/Selección-Infusion.png",
"static/ico/layered1/Selección-Leche.png",
"static/ico/layered1/Tamaño-Grande.png",
"static/ico/layered1/Tamaño-Pequeño.png",
"static/ico/layered1/Temperatura-Caliente.png",
"static/ico/layered1/Temperatura-Frio.png",
"static/ico/layered1/Temperatura-Templado.png"
]

0
assets/page/.placeholder Normal file
View File

View File

@@ -1,10 +1,23 @@
import json
import os
def get_all_files(directory):
files = []
for root, _, filenames in os.walk(directory):
for filename in filenames:
path = os.path.join(root, filename)
# Convert to relative path and normalize separators
rel_path = os.path.relpath(path, directory)
files.append(rel_path.replace('\\', '/'))
return files
PREFETCH = ""
VERSIONCO = "2025-07-30_3"
HANDLEPARSE = os.listdir("src/")
ASSETS = json.load(open("_assets.json", "r")) + HANDLEPARSE
VERSIONCO = "2025-07-31_1"
HANDLEPARSE = get_all_files("src")
# Combine assets from JSON and recursively found files
ASSETS = get_all_files("assets")
for asset in ASSETS:
if asset != "sw.js":
PREFETCH += f'<link rel="prefetch" href="{asset}" />\n'
@@ -18,7 +31,8 @@ def replace_handles(string):
for file in HANDLEPARSE:
with open("src/" + file, "r") as f:
out = replace_handles(f.read())
with open("dist/" + file, "w") as f:
f.write(out)
print(file)
with open("src/" + file, "r") as f1:
out = replace_handles(f1.read())
with open("dist/" + file, "w") as f2:
f2.write(out)

View File

@@ -34,6 +34,10 @@ if (urlParams.get("login") != null) {
//location.search = "";
}
function open_page(params) {
if (SUB_LOGGED_IN != true) {
PAGES["login"].index();
return;
}
if (params == "") {
params = "index";
}

View File

@@ -215,7 +215,9 @@ function addCategory_Personas(
options,
defaultval,
change_cb = () => {},
label = "Persona"
label = "Persona",
open_default = false,
default_empty_text = "- Lista Vacia -"
) {
var details_0 = document.createElement("details"); // children: img_0, summary_0
//details_0.open = true;
@@ -233,6 +235,9 @@ function addCategory_Personas(
span_0.append(p.Nombre || "", " ", img_0);
summary_0.append(label, span_0);
details_0.append(summary_0, document.createElement("br"));
if (open_default == true) {
details_0.open = true;
}
details_0.style.textAlign = "center";
details_0.style.margin = "5px";
details_0.style.padding = "5px";
@@ -302,6 +307,11 @@ function addCategory_Personas(
//btn.style.fontSize="17.5px"
details_0.append(btn);
});
if (Object.entries(options).length == 0) {
var btn = document.createElement("b");
btn.append(default_empty_text);
details_0.append(btn);
}
}
const SC_actions_icons = {
Tamaño: "static/ico/sizes.png",
@@ -493,23 +503,21 @@ gun
.get("personas")
.map()
.on((data, key, _msg, _ev) => {
if (data != null) {
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
SC_Personas[key] = data;
} else {
delete SC_Personas[key];
}
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
SC_Personas[key] = data;
} else {
add_row(data, key);
delete SC_Personas[key];
}
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
} else {
add_row(data, key);
}
});
function SC_parse(json) {
@@ -628,8 +636,9 @@ function TS_IndexElement(
// label: string
var tablebody = safeuuid();
var tablehead = safeuuid();
var scrolltable = safeuuid();
container.innerHTML = `
<div id="scrolltable">
<div id="${scrolltable}">
<table>
<thead>
<tr id="${tablehead}"></tr>
@@ -639,7 +648,7 @@ function TS_IndexElement(
</table>
</div>
`;
tableScroll("#scrolltable"); // id="scrolltable"
tableScroll("#" + scrolltable); // id="scrolltable"
var tablehead_EL = document.getElementById(tablehead);
var tablebody_EL = document.getElementById(tablebody);
var rows = {};
@@ -656,7 +665,6 @@ function TS_IndexElement(
}
return 0;
}
var tablebody_EL = document.getElementById(tablebody);
tablebody_EL.innerHTML = "";
Object.values(rows)
.sort(sorter)
@@ -675,34 +683,39 @@ function TS_IndexElement(
config.forEach((key) => {
switch (key.type) {
case "raw":
const tdRaw = document.createElement('td');
const rawContent = (data[key.key] || key.default || "").replace(/\n/g, '<br>');
const tdRaw = document.createElement("td");
const rawContent = (data[key.key] || key.default || "").replace(
/\n/g,
"<br>"
);
tdRaw.innerHTML = rawContent;
new_tr.appendChild(tdRaw);
break;
case "comanda":
const tdComanda = document.createElement('td');
const tdComanda = document.createElement("td");
const parsedComanda = JSON.parse(data.Comanda);
const precio = SC_priceCalc(parsedComanda)[0];
// Create a temporary div to parse the HTML from setLayeredImages
const tempDiv = document.createElement('div');
const tempDiv = document.createElement("div");
tempDiv.innerHTML = setLayeredImages(parsedComanda, data._key);
tdComanda.appendChild(tempDiv.firstChild);
const pre = document.createElement('pre');
pre.style.fontSize = '15px';
pre.style.display = 'inline-block';
const pre = document.createElement("pre");
pre.style.fontSize = "15px";
pre.style.display = "inline-block";
const spanPrecio = document.createElement("span");
spanPrecio.style.fontSize = "20px";
spanPrecio.innerHTML =
SC_Personas[data.Persona].Puntos >= 10
? `Total: Gratis!(${precio}c)`
: `Total: ${precio}c`;
const spanPrecio = document.createElement('span');
spanPrecio.style.fontSize = '20px';
spanPrecio.innerHTML = SC_Personas[data.Persona].Puntos >= 10 ?
`Total: Gratis!(${precio}c)` :
`Total: ${precio}c`;
pre.appendChild(spanPrecio);
pre.appendChild(document.createTextNode('\n'));
pre.innerHTML += SC_parse_short(parsedComanda) + "<hr>" + data.Notas;
pre.appendChild(document.createTextNode("\n"));
pre.innerHTML +=
SC_parse_short(parsedComanda) + "<hr>" + data.Notas;
tdComanda.appendChild(pre);
new_tr.appendChild(tdComanda);
@@ -712,19 +725,19 @@ function TS_IndexElement(
if (urlParams.get("sc_nobtn") == "yes") {
sc_nobtn = "pointer-events: none; opacity: 0.5";
}
const td = document.createElement('td');
td.style.fontSize = '17px';
const td = document.createElement("td");
td.style.fontSize = "17px";
if (sc_nobtn) {
td.style.pointerEvents = 'none';
td.style.opacity = '0.5';
td.style.pointerEvents = "none";
td.style.opacity = "0.5";
}
// Create buttons
const createButton = (text, state) => {
const button = document.createElement('button');
const button = document.createElement("button");
button.textContent = text;
if (data.Estado === state) {
button.className = 'rojo';
button.className = "rojo";
}
button.onclick = (event) => {
event.preventDefault();
@@ -741,20 +754,24 @@ function TS_IndexElement(
// Create all buttons
const buttons = [
createButton('Pedido', 'Pedido'),
createButton('En preparación', 'En preparación'),
createButton('Listo', 'Listo'),
createButton('Entregado', 'Entregado'),
createButton('Deuda', 'Deuda')
createButton("Pedido", "Pedido"),
createButton("En preparación", "En preparación"),
createButton("Listo", "Listo"),
createButton("Entregado", "Entregado"),
createButton("Deuda", "Deuda"),
];
// Create paid button separately due to different behavior
const paidButton = document.createElement('button');
paidButton.textContent = 'Pagado';
const paidButton = document.createElement("button");
paidButton.textContent = "Pagado";
paidButton.onclick = (event) => {
event.preventDefault();
event.stopPropagation();
if (!confirm("¿Quieres marcar como pagado? - Se borrara la comanda y se actualizarán los puntos.")) {
if (
!confirm(
"¿Quieres marcar como pagado? - Se borrara la comanda y se actualizarán los puntos."
)
) {
return false;
}
data.Estado = "Pagado";
@@ -762,22 +779,33 @@ function TS_IndexElement(
toastr.success("Guardado!");
if (SC_Personas[data.Persona].Puntos >= 10) {
SC_Personas[data.Persona].Puntos -= 10;
toastr.success("¡Comada gratis para " + SC_Personas[data.Persona].Nombre + "!");
toastr.success("¡Comada gratis para " + SC_Personas[data.Persona].Nombre + "!");
toastr.success(
"¡Comada gratis para " +
SC_Personas[data.Persona].Nombre +
"!"
);
toastr.success(
"¡Comada gratis para " +
SC_Personas[data.Persona].Nombre +
"!"
);
} else {
SC_Personas[data.Persona].Puntos += 1;
toastr.success("¡Comada DE PAGO!");
}
SEA.encrypt(SC_Personas[data.Persona], SECRET, (encrypted) => {
betterGunPut(gun.get(TABLE).get("personas").get(data.Persona), encrypted);
betterGunPut(
gun.get(TABLE).get("personas").get(data.Persona),
encrypted
);
});
return false;
};
// Add all buttons to td with line breaks between
buttons.forEach(button => {
buttons.forEach((button) => {
td.appendChild(button);
td.appendChild(document.createElement('br'));
td.appendChild(document.createElement("br"));
});
td.appendChild(paidButton);
new_tr.appendChild(td);
@@ -786,41 +814,45 @@ function TS_IndexElement(
break;
case "persona":
const persona = SC_Personas[data[key.key]];
const regco = stringToColour((persona.Region || "?").toLowerCase());
const tdPersona = document.createElement('td');
tdPersona.style.textAlign = 'center';
tdPersona.style.fontSize = '20px';
const regco = stringToColour(
(persona.Region || "?").toLowerCase()
);
const tdPersona = document.createElement("td");
tdPersona.style.textAlign = "center";
tdPersona.style.fontSize = "20px";
tdPersona.style.backgroundColor = regco;
tdPersona.style.color = colorIsDarkAdvanced(regco);
const regionSpan = document.createElement('span');
regionSpan.style.fontSize = '40px';
regionSpan.style.textTransform = 'capitalize';
const regionSpan = document.createElement("span");
regionSpan.style.fontSize = "40px";
regionSpan.style.textTransform = "capitalize";
regionSpan.textContent = (persona.Region || "?").toLowerCase();
tdPersona.appendChild(regionSpan);
tdPersona.appendChild(document.createElement('br'));
const infoSpan = document.createElement('span');
infoSpan.style.backgroundColor = 'white';
infoSpan.style.border = '2px solid black';
infoSpan.style.borderRadius = '5px';
infoSpan.style.display = 'inline-block';
infoSpan.style.padding = '5px';
infoSpan.style.color = 'black';
tdPersona.appendChild(document.createElement("br"));
const img = document.createElement('img');
const infoSpan = document.createElement("span");
infoSpan.style.backgroundColor = "white";
infoSpan.style.border = "2px solid black";
infoSpan.style.borderRadius = "5px";
infoSpan.style.display = "inline-block";
infoSpan.style.padding = "5px";
infoSpan.style.color = "black";
const img = document.createElement("img");
img.src = persona.Foto || "static/ico/user_generic.png";
img.height = 70;
infoSpan.appendChild(img);
infoSpan.appendChild(document.createElement('br'));
infoSpan.appendChild(document.createTextNode(persona.Nombre || ""));
infoSpan.appendChild(document.createElement('br'));
const pointsSpan = document.createElement('span');
pointsSpan.style.fontSize = '17px';
infoSpan.appendChild(document.createElement("br"));
infoSpan.appendChild(
document.createTextNode(persona.Nombre || "")
);
infoSpan.appendChild(document.createElement("br"));
const pointsSpan = document.createElement("span");
pointsSpan.style.fontSize = "17px";
pointsSpan.textContent = (persona.Puntos || "0") + " puntos.";
infoSpan.appendChild(pointsSpan);
@@ -839,23 +871,21 @@ function TS_IndexElement(
}
ref.map().on((data, key, _msg, _ev) => {
EVENTLISTENER = _ev;
if (data != null) {
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
rows[key] = data;
} else {
delete rows[key];
}
render();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
rows[key] = data;
} else {
add_row(data, key);
delete rows[key];
}
render();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
} else {
add_row(data, key);
}
});
}
@@ -863,6 +893,9 @@ function TS_IndexElement(
const PAGES = {};
document.addEventListener("DOMContentLoaded", () => {
Object.keys(PAGES).forEach((key) => {
if (PAGES[key].Esconder == true) {
return;
}
var a = document.createElement("a");
a.className = "button " + PAGES[key].navcss;
a.href = "#" + key;

View File

@@ -20,3 +20,6 @@ const RELAYS = [
"https://gun.defucc.me/gun",
];
var SECRET = "";
var SUB_LOGGED_IN = false;
var SUB_LOGGED_IN_DETAILS = false;
var SUB_LOGGED_IN_ID = false;

View File

@@ -1,154 +1,154 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="manifest" href="manifest.json" />
<title>TeleSec</title>
<link rel="icon" type="image/png" href="static/TeleSec.jpg" />
<link href="static/euskaditech-css/simple.css" rel="stylesheet" />
<link href="static/toastr.min.css" rel="stylesheet" />
%%PREFETCH%%
</head>
<body>
<details class="supermesh-indicator">
<summary>
<b>SuperMesh</b><br />
<br /><small id="peerPID" style="font-family: monospace"
>PID ??????????</small
>
</summary>
<ul id="peerList"></ul>
<i>Todos los datos están encriptados.</i>
</details>
<main>
<header class="no_print" id="header_hide_query">
<details id="LinkAccount_details" open>
<summary>
<b
>TeleSec - <span id="groupId">???</span> - (<span id="peerCount"
>?</span
>
nodos)</b
>
</summary>
<fieldset id="auth_fieldSet">
<legend>Credenciales</legend>
<br />
<label
>Codigo de grupo:<br />
<input type="text" id="LinkAccount_group"
/></label>
<br />
<br />
<label
>Clave secreta:<br />
<input type="text" id="LinkAccount_secret"
/></label>
<br /><br />
<button
type="button"
onclick='LinkAccount(document.getElementById("LinkAccount_group").value, document.getElementById("LinkAccount_secret").value, true)'
>
Iniciar sesión
</button>
</fieldset>
</details>
<!-- <button onclick="displayPost('index')">Ir a la pagina de inicio</button> -->
<div id="appendApps">
<!--<a class="button nav-supercafe nav-disabled" disabled>SuperCafé</a>
<a class="button nav-comedor nav-disabled" disabled>Menú Comedor</a>
<a class="button nav-recetas nav-disabled" disabled>Recetas</a>-->
</div>
<hr />
</header>
<div id="container"></div>
<!-- <br><br><br>
<footer>
<hr>
<details>
<summary><b>Apps SuperMesh</b></summary>
<button type="button">
<img src="static/TeleSec.jpg" alt="" width="100px">
<br>TeleSec
</button>
</details>
</footer> -->
<img
id="connectStatus"
style="bottom: 15px; right: 15px; position: fixed; width: 50px"
/>
</main>
<img
id="actionStatus"
src="static/ico/statusok.png"
style="
z-index: 2048;
margin: 0px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100px;
height: 100px;
display: none;
"
/>
<div id="snackbar">
Hay una nueva versión de TeleSec.<br /><a id="reload"
>Pulsa aqui para actualizar.</a
>
</div>
<script src="static/showdown.min.js"></script>
<script src="static/jquery.js"></script>
<script src="static/gun.js"></script>
<script src="static/webrtc.js"></script>
<script src="static/sea.js"></script>
<script src="static/yson.js"></script>
<script src="static/radix.js"></script>
<!-- <script src="static/radisk.js"></script> -->
<!-- <script src="static/store.js"></script> -->
<script src="static/rindexed.js"></script>
<script src="static/path.js"></script>
<script src="static/open.js"></script>
<script src="static/load.js"></script>
<!--<script src="static/synchronous.js"></script>-->
<!--<script src="static/axe.js"></script>-->
<script src="static/toastr.min.js"></script>
<script src="static/doublescroll.js"></script>
<!--<script src="static/simplemde.min.js"></script>-->
<script async>
async function getQuota(cb = () => {}) {
if (navigator.storage && navigator.storage.estimate) {
const quota = await navigator.storage.estimate();
// quota.usage -> Number of bytes used.
// quota.quota -> Maximum number of bytes available.
const percentageUsed = (quota.usage / quota.quota) * 100;
console.log(
`You've used ${percentageUsed}% of the available storage.`
);
const remaining = quota.quota - quota.usage;
cb(percentageUsed, remaining);
console.log(`You can write up to ${remaining} more bytes.`);
}
}
getQuota();
</script>
<script src="pwa.js"></script>
<script src="config.js"></script>
<script src="gun_init.js"></script>
<script src="app_logic.js"></script>
<script src="app_modules.js"></script>
<script src="page__index.js"></script>
<script src="page__importar.js"></script>
<script src="page__exportar.js"></script>
<script src="page__materiales.js"></script>
<script src="page__resumen_diario.js"></script>
<script src="page__personas.js"></script>
<script src="page__supercafe.js"></script>
<script src="page__notificaciones.js"></script>
<script src="page__comedor.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="manifest" href="manifest.json" />
<title>TeleSec</title>
<link rel="icon" type="image/png" href="static/TeleSec.jpg" />
<link href="static/euskaditech-css/simple.css" rel="stylesheet" />
<link href="static/toastr.min.css" rel="stylesheet" />
%%PREFETCH%%
</head>
<body>
<details class="supermesh-indicator">
<summary>
<b>SuperMesh</b><br />
<br /><small id="peerPID" style="font-family: monospace"
>PID ??????????</small
>
</summary>
<ul id="peerList"></ul>
<i>Todos los datos están encriptados.</i>
</details>
<main>
<header class="no_print" id="header_hide_query">
<details id="LinkAccount_details" open>
<summary>
<b
>TeleSec - <span id="groupId">???</span> - (<span id="peerCount"
>?</span
>
nodos)</b
>
</summary>
<fieldset id="auth_fieldSet">
<legend>Credenciales</legend>
<br />
<label
>Codigo de grupo:<br />
<input type="text" id="LinkAccount_group"
/></label>
<br />
<br />
<label
>Clave secreta:<br />
<input type="text" id="LinkAccount_secret"
/></label>
<br /><br />
<button
type="button"
onclick='LinkAccount(document.getElementById("LinkAccount_group").value, document.getElementById("LinkAccount_secret").value, true)'
>
Iniciar sesión
</button>
</fieldset>
</details>
<!-- <button onclick="displayPost('index')">Ir a la pagina de inicio</button> -->
<div id="appendApps">
<!--<a class="button nav-supercafe nav-disabled" disabled>SuperCafé</a>
<a class="button nav-comedor nav-disabled" disabled>Menú Comedor</a>
<a class="button nav-recetas nav-disabled" disabled>Recetas</a>-->
</div>
<hr />
</header>
<div id="container"></div>
<!-- <br><br><br>
<footer>
<hr>
<details>
<summary><b>Apps SuperMesh</b></summary>
<button type="button">
<img src="static/TeleSec.jpg" alt="" width="100px">
<br>TeleSec
</button>
</details>
</footer> -->
<img
id="connectStatus"
style="bottom: 15px; right: 15px; position: fixed; width: 50px"
/>
</main>
<img
id="actionStatus"
src="static/ico/statusok.png"
style="
z-index: 2048;
margin: 0px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100px;
height: 100px;
display: none;
"
/>
<div id="snackbar">
Hay una nueva versión de TeleSec.<br /><a id="reload"
>Pulsa aqui para actualizar.</a
>
</div>
<script src="static/showdown.min.js"></script>
<script src="static/jquery.js"></script>
<script src="static/gun.js"></script>
<script src="static/webrtc.js"></script>
<script src="static/sea.js"></script>
<script src="static/yson.js"></script>
<script src="static/radix.js"></script>
<!-- <script src="static/radisk.js"></script> -->
<!-- <script src="static/store.js"></script> -->
<script src="static/rindexed.js"></script>
<script src="static/path.js"></script>
<script src="static/open.js"></script>
<script src="static/load.js"></script>
<!--<script src="static/synchronous.js"></script>-->
<!--<script src="static/axe.js"></script>-->
<script src="static/toastr.min.js"></script>
<script src="static/doublescroll.js"></script>
<!--<script src="static/simplemde.min.js"></script>-->
<script async>
async function getQuota(cb = () => {}) {
if (navigator.storage && navigator.storage.estimate) {
const quota = await navigator.storage.estimate();
// quota.usage -> Number of bytes used.
// quota.quota -> Maximum number of bytes available.
const percentageUsed = (quota.usage / quota.quota) * 100;
console.log(
`You've used ${percentageUsed}% of the available storage.`
);
const remaining = quota.quota - quota.usage;
cb(percentageUsed, remaining);
console.log(`You can write up to ${remaining} more bytes.`);
}
}
getQuota();
</script>
<script src="pwa.js"></script>
<script src="config.js"></script>
<script src="gun_init.js"></script>
<script src="app_logic.js"></script>
<script src="app_modules.js"></script>
<script src="page/login.js"></script>
<script src="page/index.js"></script>
<script src="page/importar.js"></script>
<script src="page/exportar.js"></script>
<script src="page/materiales.js"></script>
<script src="page/resumen_diario.js"></script>
<script src="page/personas.js"></script>
<script src="page/supercafe.js"></script>
<script src="page/notificaciones.js"></script>
<script src="page/comedor.js"></script>
</body>
</html>

View File

@@ -8,7 +8,7 @@ PAGES.comedor = {
var btn_guardar = safeuuid();
var btn_borrar = safeuuid();
container.innerHTML = `
<h1>Menú del Comedor <code id="${nameh1}"></code></h1>
<h1>Entrada del menú <code id="${nameh1}"></code></h1>
<fieldset style="float: left;">
<legend>Valores</legend>
<label>
@@ -80,7 +80,7 @@ PAGES.comedor = {
container.innerHTML = `
<h1>Menú del comedor</h1>
<button id="${btn_new}">Nueva entrada</button>
<div id="cont">
<div id="cont"></div>
`;
TS_IndexElement(
"comedor",

50
src/page/login.js Normal file
View File

@@ -0,0 +1,50 @@
PAGES.login = {
Esconder: true,
Title: "Login",
index: function (mid) {
var field_persona = safeuuid();
var btn_guardar = safeuuid();
var btn_reload = safeuuid();
var div_actions = safeuuid();
container.innerHTML = `
<h1>Iniciar sesión</h1>
<fieldset>
<legend>Valores</legend>
<input type="hidden" id="${field_persona}">
<div id="${div_actions}"></div>
<button class="btn5" id="${btn_guardar}">Acceder</button>
<button class="btn1" id="${btn_reload}">Recargar lista</button>
</fieldset>
<a style="color: rgb(240,240,240)">Acceso sin cuenta</a>
`;
var divact = document.getElementById(div_actions);
addCategory_Personas(
divact,
SC_Personas,
"",
(value) => {
document.getElementById(field_persona).value = value;
},
"¿Quién eres?",
true,
"- Pulsa recargar -"
);
document.getElementById("appendApps").style.display = "none"
document.getElementById(btn_guardar).onclick = () => {
if (document.getElementById(field_persona).value == "") {
alert("Tienes que elegir tu cuenta!");
return;
}
SUB_LOGGED_IN_ID = document.getElementById(field_persona).value
SUB_LOGGED_IN_DETAILS = SC_Personas[SUB_LOGGED_IN_ID]
SUB_LOGGED_IN = true
setUrlHash("index")
document.getElementById("appendApps").style.display = "unset"
};
document.getElementById(btn_reload).onclick = () => {
setUrlHash("login," + safeuuid(""))
};
},
}

192
src/page/materiales.js Normal file
View File

@@ -0,0 +1,192 @@
PAGES.materiales = {
navcss: "btn2",
Title: "Materiales",
edit: function (mid) {
var nameh1 = safeuuid();
var field_nombre = safeuuid();
var field_cantidad = safeuuid();
var field_unidad = safeuuid();
var field_cantidad_min = safeuuid();
var field_abierto = safeuuid();
var field_ubicacion = safeuuid();
var field_referencia = safeuuid();
var field_notas = safeuuid();
var btn_guardar = safeuuid();
var btn_borrar = safeuuid();
container.innerHTML = `
<h1>Material <code id="${nameh1}"></code></h1>
<fieldset>
<label>
Referencia<br>
<input type="text" id="${field_referencia}" value="?"><br><br>
</label>
<label>
Nombre<br>
<input type="text" id="${field_nombre}"><br><br>
</label>
<label>
Unidad<br>
<input type="text" id="${field_unidad}"><br><br>
</label>
<label>
Cantidad Actual<br>
<input type="number" step="0.5" id="${field_cantidad}"><br><br>
</label>
<label>
Cantidad Minima<br>
<input type="number" step="0.5" id="${field_cantidad_min}"><br><br>
</label>
<label>
Ubicación<br>
<input type="text" id="${field_ubicacion}" value="-"><br><br>
</label>
<label>
Notas<br>
<textarea id="${field_notas}"></textarea><br><br>
</label><hr>
<button class="btn5" id="${btn_guardar}">Guardar</button>
<button class="rojo" id="${btn_borrar}">Borrar</button>
</fieldset>
`;
gun
.get(TABLE)
.get("materiales")
.get(mid)
.once((data, key) => {
function load_data(data, ENC = "") {
document.getElementById(nameh1).innerText = key;
document.getElementById(field_nombre).value = data["Nombre"] || "";
document.getElementById(field_unidad).value = data["Unidad"] || "";
document.getElementById(field_cantidad).value =
data["Cantidad"] || "";
document.getElementById(field_cantidad_min).value =
data["Cantidad_Minima"] || "";
document.getElementById(field_ubicacion).value =
data["Ubicacion"] || "-";
document.getElementById(field_referencia).value =
data["Referencia"] || "?";
document.getElementById(field_notas).value = data["Notas"] || "";
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
load_data(data, "%E");
});
} else {
load_data(data);
}
});
document.getElementById(btn_guardar).onclick = () => {
var data = {
Nombre: document.getElementById(field_nombre).value,
Unidad: document.getElementById(field_unidad).value,
Cantidad: document.getElementById(field_cantidad).value,
Cantidad_Minima: document.getElementById(field_cantidad_min).value,
Ubicacion: document.getElementById(field_ubicacion).value,
Referencia: document.getElementById(field_referencia).value,
Notas: document.getElementById(field_notas).value,
};
var enc = SEA.encrypt(data, SECRET, (encrypted) => {
document.getElementById("actionStatus").style.display = "block";
betterGunPut(gun.get(TABLE).get("materiales").get(mid), encrypted);
toastr.success("Guardado!");
setTimeout(() => {
document.getElementById("actionStatus").style.display = "none";
setUrlHash("materiales");
}, 1500);
});
};
document.getElementById(btn_borrar).onclick = () => {
if (confirm("¿Quieres borrar este material?") == true) {
betterGunPut(gun.get(TABLE).get("materiales").get(mid), null);
toastr.error("Borrado!");
setTimeout(() => {
setUrlHash("materiales");
}, 1500);
}
};
},
index: function () {
const tablebody = safeuuid();
var btn_new = safeuuid();
container.innerHTML = `
<h1>Materiales</h1>
<button id="${btn_new}">Nuevo Material</button>
<div id="scrolltable"><table>
<thead>
<tr>
<th>Referencia</th>
<th>Nombre</th>
<th>Ubicación</th>
<th>Cantidad</th>
<th>Notas</th>
</tr>
</thead>
<tbody id="${tablebody}">
</tbody>
</table></div>
`;
tableScroll("#scrolltable");
var tablebody_EL = document.getElementById(tablebody);
var rows = {};
function render() {
function sorter(a, b) {
if (a.Nombre < b.Nombre) {
return -1;
}
if (a.Nombre > b.Nombre) {
return 1;
}
return 0;
}
var tablebody_EL = document.getElementById(tablebody);
tablebody_EL.innerHTML = "";
Object.values(rows)
.sort(sorter)
.forEach((data) => {
var new_tr = document.createElement("tr");
new_tr.innerHTML = `
<td>${data.Referencia || "?"}</td>
<td>${data.Nombre || "?"}</td>
<td>${data.Ubicacion || "?"}</td>
<td>${data.Cantidad || "?"} ${data.Unidad || "?"}</td>
<td>${data.Notas || "?"}</td>
`;
var min = parseFloat(data.Cantidad_Minima);
var act = parseFloat(data.Cantidad);
if (act < min) {
new_tr.style.backgroundColor = "lightcoral";
}
new_tr.onclick = () => {
setUrlHash("materiales," + data._key);
};
tablebody_EL.append(new_tr);
});
}
gun
.get(TABLE)
.get("materiales")
.map()
.on((data, key, _msg, _ev) => {
EVENTLISTENER = _ev;
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
rows[key] = data;
} else {
delete rows[key];
}
render();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
} else {
add_row(data, key);
}
});
document.getElementById(btn_new).onclick = () => {
setUrlHash("materiales," + safeuuid(""));
};
},
};

View File

@@ -171,7 +171,7 @@ PAGES.notificaciones = {
container.innerHTML = `
<h1>Notificaciones</h1>
<button id="${btn_new}">Nueva notificación</button>
<div id="cont">
<div id="cont"></div>
`;
TS_IndexElement(
"notificaciones",

View File

@@ -198,23 +198,21 @@ PAGES.personas = {
.map()
.on((data, key, _msg, _ev) => {
EVENTLISTENER = _ev;
if (data != null) {
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
rows[key] = data;
} else {
delete rows[key];
}
render();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
rows[key] = data;
} else {
add_row(data, key);
delete rows[key];
}
render();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
} else {
add_row(data, key);
}
});
document.getElementById(btn_new).onclick = () => {

View File

@@ -1,11 +1,14 @@
PAGES.resumen_diario = {
navcss: "btn3",
Title: "Resumen Semanal",
Title: "Resumen Diario",
index: function () {
var table_materialesLow = safeuuid();
var table_personasHigh = safeuuid();
var table_comedor = safeuuid();
container.innerHTML = `
<h1>Resumen Semanal</h1>
<h1>Resumen Diario</h1>
<h2>Menú del comedor de hoy</h2>
<span class="btn7" style="display: inline-block; margin: 5px; padding: 5px; border-radius: 5px; border: 2px solid black;" id="${table_comedor}"></span>
<h2>Personas con café gratis (para el Viernes)</h2>
<div id="${table_personasHigh}"></div>
<h2>Materiales faltantes (o por llegar)</h2>
@@ -58,23 +61,21 @@ PAGES.resumen_diario = {
.map()
.on((data, key, _msg, _ev) => {
EVENTLISTENER2 = _ev;
if (data != null) {
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
materiales_low[key] = data;
} else {
delete materiales_low[key];
}
render_materialesLow();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
materiales_low[key] = data;
} else {
add_row(data, key);
delete materiales_low[key];
}
render_materialesLow();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
} else {
add_row(data, key);
}
});
function render_personasHigh() {
@@ -123,24 +124,44 @@ PAGES.resumen_diario = {
.map()
.on((data, key, _msg, _ev) => {
EVENTLISTENER = _ev;
if (data != null) {
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
personas_high[key] = data;
} else {
delete personas_high[key];
}
render_personasHigh();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
personas_high[key] = data;
} else {
add_row(data, key);
delete personas_high[key];
}
render_personasHigh();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
} else {
add_row(data, key);
}
});
// Comedor (.get("comedor").get(<current iso day>))
gun
.get(TABLE)
.get("comedor")
.get(CurrentISODate())
.once((data, key) => {
function add_row(data) {
// Fix newlines
data.Platos = data.Platos.replace(/\n/g, "<br>");
// Display platos
document.getElementById(table_comedor).innerHTML += data.Platos || "No hay platos registrados para hoy.";
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data);
});
} else {
add_row(data);
}
});
},
};

View File

@@ -167,7 +167,6 @@ PAGES.supercafe = {
<br>
<details style="background: lightpink; padding: 15px; border-radius: 15px; border: 2px solid black" open>
<summary>Deudas</summary>
<div id="scrolltable2">
<div id="cont2"></div>
</details>
`;

View File

@@ -1,194 +0,0 @@
PAGES.materiales = {
navcss: "btn2",
Title: "Materiales",
edit: function (mid) {
var nameh1 = safeuuid();
var field_nombre = safeuuid();
var field_cantidad = safeuuid();
var field_unidad = safeuuid();
var field_cantidad_min = safeuuid();
var field_abierto = safeuuid();
var field_ubicacion = safeuuid();
var field_referencia = safeuuid();
var field_notas = safeuuid();
var btn_guardar = safeuuid();
var btn_borrar = safeuuid();
container.innerHTML = `
<h1>Material <code id="${nameh1}"></code></h1>
<fieldset>
<label>
Referencia<br>
<input type="text" id="${field_referencia}" value="?"><br><br>
</label>
<label>
Nombre<br>
<input type="text" id="${field_nombre}"><br><br>
</label>
<label>
Unidad<br>
<input type="text" id="${field_unidad}"><br><br>
</label>
<label>
Cantidad Actual<br>
<input type="number" step="0.5" id="${field_cantidad}"><br><br>
</label>
<label>
Cantidad Minima<br>
<input type="number" step="0.5" id="${field_cantidad_min}"><br><br>
</label>
<label>
Ubicación<br>
<input type="text" id="${field_ubicacion}" value="-"><br><br>
</label>
<label>
Notas<br>
<textarea id="${field_notas}"></textarea><br><br>
</label><hr>
<button class="btn5" id="${btn_guardar}">Guardar</button>
<button class="rojo" id="${btn_borrar}">Borrar</button>
</fieldset>
`;
gun
.get(TABLE)
.get("materiales")
.get(mid)
.once((data, key) => {
function load_data(data, ENC = "") {
document.getElementById(nameh1).innerText = key;
document.getElementById(field_nombre).value = data["Nombre"] || "";
document.getElementById(field_unidad).value = data["Unidad"] || "";
document.getElementById(field_cantidad).value =
data["Cantidad"] || "";
document.getElementById(field_cantidad_min).value =
data["Cantidad_Minima"] || "";
document.getElementById(field_ubicacion).value =
data["Ubicacion"] || "-";
document.getElementById(field_referencia).value =
data["Referencia"] || "?";
document.getElementById(field_notas).value = data["Notas"] || "";
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
load_data(data, "%E");
});
} else {
load_data(data);
}
});
document.getElementById(btn_guardar).onclick = () => {
var data = {
Nombre: document.getElementById(field_nombre).value,
Unidad: document.getElementById(field_unidad).value,
Cantidad: document.getElementById(field_cantidad).value,
Cantidad_Minima: document.getElementById(field_cantidad_min).value,
Ubicacion: document.getElementById(field_ubicacion).value,
Referencia: document.getElementById(field_referencia).value,
Notas: document.getElementById(field_notas).value,
};
var enc = SEA.encrypt(data, SECRET, (encrypted) => {
document.getElementById("actionStatus").style.display = "block";
betterGunPut(gun.get(TABLE).get("materiales").get(mid), encrypted);
toastr.success("Guardado!");
setTimeout(() => {
document.getElementById("actionStatus").style.display = "none";
setUrlHash("materiales");
}, 1500);
});
};
document.getElementById(btn_borrar).onclick = () => {
if (confirm("¿Quieres borrar este material?") == true) {
betterGunPut(gun.get(TABLE).get("materiales").get(mid), null);
toastr.error("Borrado!");
setTimeout(() => {
setUrlHash("materiales");
}, 1500);
}
};
},
index: function () {
const tablebody = safeuuid();
var btn_new = safeuuid();
container.innerHTML = `
<h1>Materiales</h1>
<button id="${btn_new}">Nuevo Material</button>
<div id="scrolltable"><table>
<thead>
<tr>
<th>Referencia</th>
<th>Nombre</th>
<th>Ubicación</th>
<th>Cantidad</th>
<th>Notas</th>
</tr>
</thead>
<tbody id="${tablebody}">
</tbody>
</table></div>
`;
tableScroll("#scrolltable");
var tablebody_EL = document.getElementById(tablebody);
var rows = {};
function render() {
function sorter(a, b) {
if (a.Nombre < b.Nombre) {
return -1;
}
if (a.Nombre > b.Nombre) {
return 1;
}
return 0;
}
var tablebody_EL = document.getElementById(tablebody);
tablebody_EL.innerHTML = "";
Object.values(rows)
.sort(sorter)
.forEach((data) => {
var new_tr = document.createElement("tr");
new_tr.innerHTML = `
<td>${data.Referencia || "?"}</td>
<td>${data.Nombre || "?"}</td>
<td>${data.Ubicacion || "?"}</td>
<td>${data.Cantidad || "?"} ${data.Unidad || "?"}</td>
<td>${data.Notas || "?"}</td>
`;
var min = parseFloat(data.Cantidad_Minima);
var act = parseFloat(data.Cantidad);
if (act < min) {
new_tr.style.backgroundColor = "lightcoral";
}
new_tr.onclick = () => {
setUrlHash("materiales," + data._key);
};
tablebody_EL.append(new_tr);
});
}
gun
.get(TABLE)
.get("materiales")
.map()
.on((data, key, _msg, _ev) => {
EVENTLISTENER = _ev;
if (data != null) {
function add_row(data, key) {
if (data != null) {
data["_key"] = key;
rows[key] = data;
} else {
delete rows[key];
}
render();
}
if (typeof data == "string") {
SEA.decrypt(data, SECRET, (data) => {
add_row(data, key);
});
} else {
add_row(data, key);
}
}
});
document.getElementById(btn_new).onclick = () => {
setUrlHash("materiales," + safeuuid(""));
};
},
}

View File

@@ -1,10 +1,10 @@
var cacheName = 'telesec_%%VERSIONCO%%';
var cacheName = 'telesec_2025-07-30_4';
self.addEventListener('install', event => {
event.waitUntil(
caches.open(cacheName)
.then(cache => cache.addAll(%%ASSETSJSON%%))
.then(cache => cache.addAll(["index.html", "icon512_maskable.png", "icon512_rounded.png", "cola_cao.jpg", "manifest.json", "static/webrtc.js", "static/synchronous.js", "static/sea.js", "static/gun.js", "static/toastr.min.css", "static/store.js", "static/simplemde.min.css", "static/doublescroll.js", "static/rindexed.js", "static/yson.js", "static/toastr.min.js", "static/showdown.min.js", "static/load.js", "static/radix.js", "static/axe.js", "static/TeleSec.jpg", "static/path.js", "static/radisk.js", "static/open.js", "static/simplemde.min.js", "static/jquery.js", "static/euskaditech-css/README.md", "static/euskaditech-css/.gitignore", "static/euskaditech-css/simple.css", "static/euskaditech-css/.git", "static/euskaditech-css/logos/EuskadiTech/long nobg color.svg", "static/euskaditech-css/logos/EuskadiTech/nobg color.png", "static/euskaditech-css/logos/EuskadiTech/nobg color.svg", "static/euskaditech-css/logos/EuskadiTech/long nobg color.png", "static/ico/add.png", "static/ico/user_generic.png", "static/ico/keyboard_key_g.png", "static/ico/keyboard_key_p.png", "static/ico/snowflake.png", "static/ico/coffee_bean.png", "static/ico/arrow_up_red.png", "static/ico/milk (1).png", "static/ico/azucar-moreno.png", "static/ico/arrow_down_blue.png", "static/ico/camera2.png", "static/ico/fire.png", "static/ico/cookies.png", "static/ico/checkbox_unchecked.png", "static/ico/wheat.png", "static/ico/sacarina.jpg", "static/ico/arrow_left_green.png", "static/ico/tea_bag.png", "static/ico/cow.png", "static/ico/connect_ko.svg", "static/ico/milk.png", "static/ico/user.png", "static/ico/stevia.jpg", "static/ico/water_tap.png", "static/ico/thermometer2.png", "static/ico/statusok.png", "static/ico/lollipop.png", "static/ico/colacao.jpg", "static/ico/delete.png", "static/ico/cereales.png", "static/ico/checkbox.png", "static/ico/azucar-blanco.jpg", "static/ico/preferences.png", "static/ico/sizes.png", "static/ico/stevia-gotas.webp", "static/ico/connect_ok.svg", "static/ico/layered1/Azucar-Az. Moreno.png", "static/ico/layered1/Azucar-Stevia (Pastillas).png", "static/ico/layered1/Azucar-Sacarina.png", "static/ico/layered1/Selección-ColaCao.png", "static/ico/layered1/Temperatura-Templado.png", "static/ico/layered1/Tamaño-Pequeño.png", "static/ico/layered1/Leche-Sin lactosa.png", "static/ico/layered1/Cafeina-Sin.png", "static/ico/layered1/Leche-Vegetal.png", "static/ico/layered1/Leche-de Vaca.png", "static/ico/layered1/Selección-Infusion.png", "static/ico/layered1/Azucar-Sin.png", "static/ico/layered1/Selección-Leche.png", "static/ico/layered1/Temperatura-Frio.png", "static/ico/layered1/Background.png", "static/ico/layered1/Azucar-Edulcorante.png", "static/ico/layered1/Cafeina-Con.png", "static/ico/layered1/Selección-CaféLeche.png", "static/ico/layered1/Tamaño-Grande.png", "static/ico/layered1/Selección-CafeSolo.png", "static/ico/layered1/Leche-Agua.png", "static/ico/layered1/Temperatura-Caliente.png", "static/ico/layered1/Azucar-Stevia (Gotas).png", "static/ico/layered1/Azucar-Az. Blanco.png"]))
);
});