Compare commits
24 Commits
v2025-07-1
...
v2025-07-3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e35428f3ee | ||
|
|
def79a2015 | ||
|
|
64d11fe224 | ||
|
|
a016e06557 | ||
|
|
a274de3c4d | ||
|
|
0f2b2df969 | ||
|
|
8052d21fcc | ||
|
|
03c132a6bd | ||
|
|
970b1dddf7 | ||
|
|
b38156cc3a | ||
|
|
09c05bb81d | ||
|
|
97650659a7 | ||
|
|
d05a63e68d | ||
|
|
c800ea7c1b | ||
|
|
55eda485ed | ||
|
|
92d3522f98 | ||
|
|
1fcff4c2b2 | ||
|
|
f032e0f243 | ||
|
|
8ee724ba14 | ||
|
|
5e92452699 | ||
|
|
659c1f8cc5 | ||
|
|
ce7fe7cd6b | ||
|
|
9bc08a76e8 | ||
|
|
2c277bb12d |
@@ -3,6 +3,8 @@ name: Build server
|
||||
on:
|
||||
push:
|
||||
tags: ["v*-*-*_*"]
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
@@ -27,6 +29,14 @@ jobs:
|
||||
# Upload built files
|
||||
name: 'TeleSec-dist'
|
||||
path: ./dist
|
||||
- uses: mdallasanta/ssh-scp-deploy@v1.2.0
|
||||
with:
|
||||
local: './dist/' # Local file path - REQUIRED false - DEFAULT ./
|
||||
remote: '${{ secrets.FOLDER }}' # Remote file path - REQUIRED false - DEFAULT ~/
|
||||
host: ${{secrets.HOST}} # Remote server address - REQUIRED true
|
||||
port: 22 # Remote server port - REQUIRED false - DEFAULT 22
|
||||
user: ${{secrets.USER}} # Remote server user - REQUIRED true
|
||||
key: ${{secrets.KEY}} # Remote server private key - REQUIRED at least one of "password" or "key"
|
||||
- name: "zip-it-up"
|
||||
run: "zip -r TeleSec-dist.zip ./dist"
|
||||
- name: Upload as release
|
||||
@@ -34,21 +44,4 @@ jobs:
|
||||
with:
|
||||
files: |-
|
||||
TeleSec-dist.zip
|
||||
api_key: '${{secrets.TOKEN_PUSH_PLUS}}'
|
||||
- name: Copy files via SSH
|
||||
uses: appleboy/scp-action@v1
|
||||
with:
|
||||
host: ${{ secrets.HOST }}
|
||||
username: ${{ secrets.USERNAME }}
|
||||
key: ${{ secrets.KEY }}
|
||||
source: "TeleSec-dist.zip"
|
||||
target: ${{ secrets.FOLDER }}TeleSec.zip
|
||||
- name: Execute remote SSH commands using password
|
||||
uses: appleboy/ssh-action@v1
|
||||
with:
|
||||
host: ${{ secrets.HOST }}
|
||||
username: ${{ secrets.USERNAME }}
|
||||
key: ${{ secrets.KEY }}
|
||||
script: |
|
||||
cd ${{ secrets.FOLDER }}
|
||||
unzip TeleSec.zip
|
||||
api_key: '${{secrets.TOKEN_PUSH_PLUS}}'
|
||||
3
.gitignore
vendored
@@ -1,2 +1 @@
|
||||
dist/index.html
|
||||
dist/sw.js
|
||||
dist/*
|
||||
4
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "dist/static/euskaditech-css"]
|
||||
path = dist/static/euskaditech-css
|
||||
[submodule "assets/static/euskaditech-css"]
|
||||
path = assets/static/euskaditech-css
|
||||
url = https://git.tech.eus/EuskadiTech/css.git
|
||||
|
||||
86
_assets.json
@@ -1,86 +0,0 @@
|
||||
[
|
||||
"icon512_maskable.png",
|
||||
"icon512_rounded.png",
|
||||
"index.html",
|
||||
"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"
|
||||
]
|
||||
|
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 210 KiB |
|
Before Width: | Height: | Size: 378 KiB After Width: | Height: | Size: 378 KiB |
|
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 300 KiB |
252
assets/index.html
Normal file
@@ -0,0 +1,252 @@
|
||||
<!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" />
|
||||
|
||||
<link rel="prefetch" href="icon512_maskable.png" />
|
||||
<link rel="prefetch" href="icon512_rounded.png" />
|
||||
<link rel="prefetch" href="manifest.json" />
|
||||
<link rel="prefetch" href="static/axe.js" />
|
||||
<link rel="prefetch" href="static/doublescroll.js" />
|
||||
<link rel="prefetch" href="static/gun.js" />
|
||||
<link rel="prefetch" href="static/jquery.js" />
|
||||
<link rel="prefetch" href="static/load.js" />
|
||||
<link rel="prefetch" href="static/open.js" />
|
||||
<link rel="prefetch" href="static/path.js" />
|
||||
<link rel="prefetch" href="static/radisk.js" />
|
||||
<link rel="prefetch" href="static/radix.js" />
|
||||
<link rel="prefetch" href="static/rindexed.js" />
|
||||
<link rel="prefetch" href="static/sea.js" />
|
||||
<link rel="prefetch" href="static/showdown.min.js" />
|
||||
<link rel="prefetch" href="static/simplemde.min.css" />
|
||||
<link rel="prefetch" href="static/simplemde.min.js" />
|
||||
<link rel="prefetch" href="static/store.js" />
|
||||
<link rel="prefetch" href="static/synchronous.js" />
|
||||
<link rel="prefetch" href="static/TeleSec.jpg" />
|
||||
<link rel="prefetch" href="static/toastr.min.css" />
|
||||
<link rel="prefetch" href="static/toastr.min.js" />
|
||||
<link rel="prefetch" href="static/webrtc.js" />
|
||||
<link rel="prefetch" href="static/yson.js" />
|
||||
<link rel="prefetch" href="static/ico/add.png" />
|
||||
<link rel="prefetch" href="static/ico/azucar-moreno.png" />
|
||||
<link rel="prefetch" href="static/ico/azucar-blanco.jpg" />
|
||||
<link rel="prefetch" href="static/ico/stevia.jpg" />
|
||||
<link rel="prefetch" href="static/ico/stevia-gotas.webp" />
|
||||
<link rel="prefetch" href="static/ico/sacarina.jpg" />
|
||||
<link rel="prefetch" href="static/ico/arrow_down_blue.png" />
|
||||
<link rel="prefetch" href="static/ico/arrow_left_green.png" />
|
||||
<link rel="prefetch" href="static/ico/arrow_up_red.png" />
|
||||
<link rel="prefetch" href="static/ico/camera2.png" />
|
||||
<link rel="prefetch" href="static/ico/cereales.png" />
|
||||
<link rel="prefetch" href="static/ico/checkbox.png" />
|
||||
<link rel="prefetch" href="static/ico/checkbox_unchecked.png" />
|
||||
<link rel="prefetch" href="static/ico/connect_ok.svg" />
|
||||
<link rel="prefetch" href="static/ico/connect_ko.svg" />
|
||||
<link rel="prefetch" href="static/ico/coffee_bean.png" />
|
||||
<link rel="prefetch" href="static/ico/colacao.jpg" />
|
||||
<link rel="prefetch" href="static/ico/cookies.png" />
|
||||
<link rel="prefetch" href="static/ico/cow.png" />
|
||||
<link rel="prefetch" href="static/ico/delete.png" />
|
||||
<link rel="prefetch" href="static/ico/fire.png" />
|
||||
<link rel="prefetch" href="static/ico/keyboard_key_g.png" />
|
||||
<link rel="prefetch" href="static/ico/keyboard_key_p.png" />
|
||||
<link rel="prefetch" href="static/ico/lollipop.png" />
|
||||
<link rel="prefetch" href="static/ico/milk.png" />
|
||||
<link rel="prefetch" href="static/ico/preferences.png" />
|
||||
<link rel="prefetch" href="static/ico/sizes.png" />
|
||||
<link rel="prefetch" href="static/ico/statusok.png" />
|
||||
<link rel="prefetch" href="static/ico/snowflake.png" />
|
||||
<link rel="prefetch" href="static/ico/tea_bag.png" />
|
||||
<link rel="prefetch" href="static/ico/thermometer2.png" />
|
||||
<link rel="prefetch" href="static/ico/user.png" />
|
||||
<link rel="prefetch" href="static/ico/user_generic.png" />
|
||||
<link rel="prefetch" href="static/ico/water_tap.png" />
|
||||
<link rel="prefetch" href="static/ico/wheat.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Azucar-Az. Blanco.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Azucar-Az. Moreno.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Azucar-Edulcorante.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Azucar-Sacarina.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Azucar-Sin.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Azucar-Stevia (Gotas).png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Azucar-Stevia (Pastillas).png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Background.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Cafeina-Con.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Cafeina-Sin.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Leche-Agua.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Leche-Sin lactosa.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Leche-Vegetal.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Leche-de Vaca.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Selección-CafeSolo.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Selección-CaféLeche.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Selección-ColaCao.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Selección-Infusion.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Selección-Leche.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Tamaño-Grande.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Tamaño-Pequeño.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Temperatura-Caliente.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Temperatura-Frio.png" />
|
||||
<link rel="prefetch" href="static/ico/layered1/Temperatura-Templado.png" />
|
||||
<link rel="prefetch" href="page__supercafe.js" />
|
||||
<link rel="prefetch" href="app_logic.js" />
|
||||
<link rel="prefetch" href="page__index.js" />
|
||||
<link rel="prefetch" href="page__notificaciones.js" />
|
||||
<link rel="prefetch" href="page__materiales.js" />
|
||||
<link rel="prefetch" href="index.html" />
|
||||
<link rel="prefetch" href="page__exportar.js" />
|
||||
<link rel="prefetch" href="gun_init.js" />
|
||||
<link rel="prefetch" href="page__personas.js" />
|
||||
<link rel="prefetch" href="page__importar.js" />
|
||||
<link rel="prefetch" href="config.js" />
|
||||
<link rel="prefetch" href="app_modules.js" />
|
||||
<link rel="prefetch" href="page__comedor.js" />
|
||||
<link rel="prefetch" href="page__resumen_diario.js" />
|
||||
<link rel="prefetch" href="pwa.js" />
|
||||
|
||||
</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>
|
||||
0
assets/page/.placeholder
Normal file
|
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 185 KiB |
@@ -1827,7 +1827,7 @@
|
||||
root.on('put', function(msg){
|
||||
this.to.next(msg); // remember to call next middleware adapter
|
||||
var put = msg.put, soul = put['#'], key = put['.'], id = msg['#'], ok = msg.ok||'', tmp; // pull data off wire envelope
|
||||
if (!(soul.startsWith(TABLE))) return; // fix https://github.com/amark/gun/issues/1377
|
||||
if (!(root.next || '')[soul]){ return } // fix https://github.com/amark/gun/issues/1377
|
||||
disk[soul] = Gun.state.ify(disk[soul], key, put['>'], put[':'], soul); // merge into disk object
|
||||
if(stop && size > (4999880)){ root.on('in', {'@': id, err: "localStorage max!"}); return; }
|
||||
//if(!msg['@']){ acks.push(id) } // then ack any non-ack write. // TODO: use batch id.
|
||||
@@ -2310,4 +2310,4 @@
|
||||
var obj = Type.obj, obj_is = obj.is, obj_del = obj.del, obj_has = obj.has, obj_empty = obj.empty, obj_put = obj.put, obj_map = obj.map, obj_copy = obj.copy;
|
||||
var u;
|
||||
Type.graph = Type.graph || Graph;
|
||||
}());
|
||||
}());
|
||||
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 210 KiB |
|
Before Width: | Height: | Size: 884 B After Width: | Height: | Size: 884 B |
|
Before Width: | Height: | Size: 653 B After Width: | Height: | Size: 653 B |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 246 B After Width: | Height: | Size: 246 B |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
40
build.py
@@ -1,20 +1,38 @@
|
||||
import json
|
||||
ASSETS = json.load(open("_assets.json", "r"))
|
||||
PREFETCH = ""
|
||||
VERSIONCO = "2025-06-27_1"
|
||||
HANDLEPARSE = ["index.html", "sw.js"]
|
||||
for asset in ASSETS:
|
||||
PREFETCH += f'<link rel="prefetch" href="{asset}" />\n'
|
||||
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-31_2"
|
||||
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'
|
||||
|
||||
os.system("rm -r dist ; mkdir -p dist ; cp -r assets/* dist/")
|
||||
def replace_handles(string):
|
||||
string = string.replace("%%PREFETCH%%", PREFETCH)
|
||||
string = string.replace("%%VERSIONCO%%", VERSIONCO)
|
||||
string = string.replace("%%ASSETSJSON%%", json.dumps(ASSETS, ensure_ascii=False))
|
||||
return 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)
|
||||
for file in HANDLEPARSE:
|
||||
print(file)
|
||||
with open("src/" + file, "r") as f1:
|
||||
out = replace_handles(f1.read())
|
||||
with open("dist/" + file, "w") as f2:
|
||||
f2.write(out)
|
||||
|
||||
164
src/app_logic.js
Normal file
@@ -0,0 +1,164 @@
|
||||
function tableScroll(query) {
|
||||
$(query).doubleScroll();
|
||||
}
|
||||
//var secretTokenEl = document.getElementById("secretToken");
|
||||
var groupIdEl = document.getElementById("groupId");
|
||||
var container = document.getElementById("container");
|
||||
function LinkAccount(LinkAccount_group, LinkAccount_secret, refresh = false) {
|
||||
GROUPID = LinkAccount_group.toUpperCase();
|
||||
SECRET = LinkAccount_secret.toUpperCase();
|
||||
|
||||
localStorage.setItem("TELESEC_AUTO", "YES");
|
||||
localStorage.setItem("TELESEC_groupid", GROUPID);
|
||||
localStorage.setItem("TELESEC_secret", SECRET);
|
||||
|
||||
TABLE = GROUPID + ":telesec.tech.eus";
|
||||
//secretTokenEl.innerText = SECRET;
|
||||
groupIdEl.innerText = GROUPID;
|
||||
document.getElementById("LinkAccount_details").open = false;
|
||||
if (refresh == true) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
if (localStorage.getItem("TELESEC_AUTO") == "YES") {
|
||||
LinkAccount(
|
||||
localStorage.getItem("TELESEC_groupid"),
|
||||
localStorage.getItem("TELESEC_secret")
|
||||
);
|
||||
}
|
||||
if (urlParams.get("login") != null) {
|
||||
LinkAccount(
|
||||
urlParams.get("login").split(":")[0],
|
||||
urlParams.get("login").split(":")[1]
|
||||
);
|
||||
//location.search = "";
|
||||
}
|
||||
function open_page(params) {
|
||||
if (SUB_LOGGED_IN != true) {
|
||||
PAGES["login"].index();
|
||||
return;
|
||||
}
|
||||
if (params == "") {
|
||||
params = "index";
|
||||
}
|
||||
var path = params.split(",");
|
||||
var app = path[0];
|
||||
if (path[1] == undefined) {
|
||||
PAGES[app].index();
|
||||
return;
|
||||
}
|
||||
PAGES[app].edit(path[1]);
|
||||
}
|
||||
function setUrlHash(hash) {
|
||||
location.hash = "#" + hash;
|
||||
}
|
||||
window.onhashchange = () => {
|
||||
try {
|
||||
if (EVENTLISTENER != null) {
|
||||
try {
|
||||
EVENTLISTENER.off();
|
||||
EVENTLISTENER = null;
|
||||
EVENTLISTENER2.off();
|
||||
EVENTLISTENER2 = null;
|
||||
// TypeError: Cannot read properties of null (reading 'off')
|
||||
} catch (error) {
|
||||
if (!error.name == "TypeError") {
|
||||
console.debug("EVENTLISTENER error", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.debug("EVENTLISTENER onhashchange", e);
|
||||
}
|
||||
|
||||
open_page(location.hash.replace("#", ""));
|
||||
};
|
||||
function download(filename, text) {
|
||||
var element = document.createElement("a");
|
||||
element.setAttribute(
|
||||
"href",
|
||||
"data:application/octet-stream;charset=utf-8," + encodeURIComponent(text)
|
||||
);
|
||||
element.setAttribute("download", filename);
|
||||
|
||||
element.style.display = "none";
|
||||
document.body.appendChild(element);
|
||||
|
||||
element.click();
|
||||
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
function resizeInputImage(
|
||||
file,
|
||||
callback,
|
||||
targetHeight = 256,
|
||||
targetQuality = 0.75
|
||||
) {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = function (event) {
|
||||
const img = new Image();
|
||||
img.onload = function () {
|
||||
const aspectRatio = img.width / img.height;
|
||||
const targetWidth = targetHeight * aspectRatio;
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = targetWidth;
|
||||
canvas.height = targetHeight;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
ctx.fillStyle = "#ffffff";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.drawImage(img, 0, 0, targetWidth, targetHeight);
|
||||
|
||||
// Get resized image as Blob
|
||||
const dataURL = canvas.toDataURL("image/jpeg", targetQuality);
|
||||
callback(dataURL);
|
||||
};
|
||||
img.src = event.target.result;
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
function CurrentISODate() {
|
||||
return new Date().toISOString().split("T")[0].replace("T", " ");
|
||||
}
|
||||
function CurrentISOTime() {
|
||||
return new Date().toISOString();
|
||||
}
|
||||
function fixGunLocalStorage() {
|
||||
localStorage.removeItem("radata");
|
||||
removeCache();
|
||||
location.reload();
|
||||
}
|
||||
function betterGunPut(ref, data) {
|
||||
ref.put(data, (ack) => {
|
||||
if (ack.err) {
|
||||
toastr.error(
|
||||
ack.err + "<br>Pulsa aqui para reiniciar la app",
|
||||
"Error al guardar",
|
||||
{ onclick: () => fixGunLocalStorage() }
|
||||
);
|
||||
} else {
|
||||
console.debug("Guardado correctamente");
|
||||
}
|
||||
});
|
||||
setTimeout(() => {
|
||||
ref.put(data);
|
||||
}, 250);
|
||||
setTimeout(() => {
|
||||
ref.put(data);
|
||||
}, 500);
|
||||
}
|
||||
setInterval(() => {
|
||||
betterGunPut(
|
||||
gun.get(TABLE).get("heartbeat"),
|
||||
"heartbeat-" + CurrentISOTime()
|
||||
);
|
||||
gun.get(TABLE).get("heartbeat").load(console.debug);
|
||||
}, 5000);
|
||||
gun.get(TABLE).on((data) => {
|
||||
var e = true;
|
||||
});
|
||||
960
src/app_modules.js
Normal file
@@ -0,0 +1,960 @@
|
||||
try {
|
||||
navigator.wakeLock.request("screen");
|
||||
} catch {
|
||||
console.log("ScreenLock Failed");
|
||||
}
|
||||
const debounce = (callback, wait) => {
|
||||
let isLocked = false;
|
||||
let lastArgs = null;
|
||||
let timeoutId = null;
|
||||
|
||||
return (...args) => {
|
||||
if (!isLocked) {
|
||||
// First call: run immediately
|
||||
callback(...args);
|
||||
isLocked = true;
|
||||
|
||||
// Start lock period
|
||||
timeoutId = setTimeout(() => {
|
||||
isLocked = false;
|
||||
if (lastArgs) {
|
||||
callback(...lastArgs);
|
||||
lastArgs = null;
|
||||
}
|
||||
}, wait);
|
||||
} else {
|
||||
// During lock: save latest args
|
||||
lastArgs = args;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
String.prototype.toHex = function () {
|
||||
var s = this + "0123456789";
|
||||
var colors = [
|
||||
"#ff0000",
|
||||
"#ff00ff",
|
||||
"#00ff00",
|
||||
"#0000ff",
|
||||
"#00ffff",
|
||||
"#000000",
|
||||
];
|
||||
var color =
|
||||
(((((s.charCodeAt(1) * s.charCodeAt(2)) / s.charCodeAt(s.length - 1)) *
|
||||
s.charCodeAt(s.length - 2)) /
|
||||
s.charCodeAt(s.length - 2)) *
|
||||
s.charCodeAt(s.length - 3)) /
|
||||
s.charCodeAt(s.length - 3);
|
||||
var cid = colors[Math.round(color) % colors.length];
|
||||
console.log(color, cid, colors);
|
||||
return cid;
|
||||
};
|
||||
function stringToColour(str) {
|
||||
return str.toHex();
|
||||
}
|
||||
function colorIsDarkAdvanced(bgColor) {
|
||||
let color = bgColor.charAt(0) === "#" ? bgColor.substring(1, 7) : bgColor;
|
||||
let r = parseInt(color.substring(0, 2), 16); // hexToR
|
||||
let g = parseInt(color.substring(2, 4), 16); // hexToG
|
||||
let b = parseInt(color.substring(4, 6), 16); // hexToB
|
||||
let uicolors = [r / 255, g / 255, b / 255];
|
||||
let c = uicolors.map((col) => {
|
||||
if (col <= 0.03928) {
|
||||
return col / 12.92;
|
||||
}
|
||||
return Math.pow((col + 0.055) / 1.055, 2.4);
|
||||
});
|
||||
let L = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];
|
||||
return L <= 0.179 ? "#FFFFFF" : "#000000";
|
||||
}
|
||||
function setLayeredImages(comanda, key) {
|
||||
// Base paths for each layer type (adjust paths as needed)
|
||||
const basePaths = {
|
||||
Selección: "static/ico/layered1/",
|
||||
Café: "static/ico/layered1/",
|
||||
Endulzante: "static/ico/layered1/",
|
||||
Cafeina: "static/ico/layered1/",
|
||||
Leche: "static/ico/layered1/",
|
||||
};
|
||||
|
||||
// Map for Selección to filenames
|
||||
const selectionMap = {
|
||||
"ColaCao con leche": "Selección-ColaCao.png",
|
||||
Infusión: "Selección-Infusion.png",
|
||||
"Café con leche": "Selección-CaféLeche.png",
|
||||
"Solo Leche": "Selección-Leche.png",
|
||||
"Solo café (sin leche)": "Selección-CaféSolo.png",
|
||||
};
|
||||
|
||||
// Start div with relative positioning for layering
|
||||
let html = `<div style="position: relative; width: 200px; height: 200px; background: white; display: inline-block; border: 1px dotted black;">`;
|
||||
|
||||
// Layer 1: Selección image
|
||||
const selection = comanda["Selección"];
|
||||
if (selectionMap[selection]) {
|
||||
html += `<img id="img1-${key}" src="${
|
||||
basePaths.Selección + selectionMap[selection]
|
||||
}" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||
}
|
||||
|
||||
// Layer 2: Café
|
||||
if (comanda.Café) {
|
||||
html += `<img id="img2-${key}" src="${basePaths.Café}Café-${comanda.Café}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||
}
|
||||
|
||||
// Layer 3: Endulzante
|
||||
if (comanda.Endulzante) {
|
||||
html += `<img id="img3-${key}" src="${basePaths.Endulzante}Azucar-${comanda.Endulzante}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||
}
|
||||
|
||||
// Layer 4: Cafeina
|
||||
if (comanda.Cafeina) {
|
||||
html += `<img id="img4-${key}" src="${basePaths.Cafeina}Cafeina-${comanda.Cafeina}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||
}
|
||||
// Layer 5: Leche
|
||||
if (comanda.Leche) {
|
||||
html += `<img id="img5-${key}" src="${basePaths.Leche}Leche-${comanda.Leche}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||
}
|
||||
// Layer 6: Temperatura
|
||||
if (comanda.Temperatura) {
|
||||
html += `<img id="img6-${key}" src="${basePaths.Leche}Temperatura-${comanda.Temperatura}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||
}
|
||||
// Layer 7: Tamaño
|
||||
if (comanda.Tamaño) {
|
||||
html += `<img id="img7-${key}" src="${basePaths.Leche}Tamaño-${comanda.Tamaño}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||
}
|
||||
|
||||
// Close div
|
||||
html += "</div>";
|
||||
|
||||
return html;
|
||||
}
|
||||
function addCategory(
|
||||
parent,
|
||||
name,
|
||||
icon,
|
||||
options,
|
||||
values,
|
||||
change_cb = () => {}
|
||||
) {
|
||||
var details_0 = document.createElement("details"); // children: img_0, summary_0
|
||||
//details_0.open = true;
|
||||
var img_0 = document.createElement("img");
|
||||
img_0.src = "static/ico/checkbox_unchecked.png";
|
||||
img_0.style.height = "30px";
|
||||
if (values[name] != undefined) {
|
||||
//details_0.open = true;
|
||||
img_0.src = "static/ico/checkbox.png";
|
||||
}
|
||||
var summary_0 = document.createElement("summary");
|
||||
var span_0 = document.createElement("span");
|
||||
span_0.style.float = "right";
|
||||
span_0.append(values[name] || "", " ", img_0);
|
||||
summary_0.append(name, span_0);
|
||||
details_0.append(summary_0, document.createElement("br"));
|
||||
details_0.style.textAlign = "center";
|
||||
details_0.style.margin = "5px";
|
||||
details_0.style.padding = "5px";
|
||||
details_0.style.border = "2px solid black";
|
||||
details_0.style.borderRadius = "5px";
|
||||
details_0.style.backgroundColor = "white";
|
||||
details_0.style.cursor = "pointer";
|
||||
details_0.style.width = "calc(100% - 25px)";
|
||||
details_0.style.display = "inline-block";
|
||||
summary_0.style.padding = "10px";
|
||||
// background image at the start of summary_0:
|
||||
summary_0.style.backgroundImage = "url('" + icon + "')";
|
||||
summary_0.style.backgroundSize = "contain";
|
||||
summary_0.style.backgroundPosition = "left";
|
||||
summary_0.style.backgroundRepeat = "no-repeat";
|
||||
summary_0.style.textAlign = "left";
|
||||
summary_0.style.paddingLeft = "55px";
|
||||
parent.append(details_0);
|
||||
|
||||
options.forEach((option) => {
|
||||
var btn = document.createElement("button");
|
||||
var br1 = document.createElement("br");
|
||||
//btn.innerText = option.key + ": " + option.value
|
||||
btn.append(option.value);
|
||||
// for each image in option.img:
|
||||
|
||||
if (option.img) {
|
||||
var br2 = document.createElement("br");
|
||||
btn.append(br2);
|
||||
option.img.forEach((imgsrc) => {
|
||||
var img = document.createElement("img");
|
||||
img.src = imgsrc;
|
||||
img.style.height = "50px";
|
||||
img.style.padding = "5px";
|
||||
img.style.backgroundColor = "white";
|
||||
btn.append(img, " ");
|
||||
});
|
||||
}
|
||||
btn.className = option.className;
|
||||
if (values[option.key] == option.value) {
|
||||
btn.classList.add("activeSCButton");
|
||||
}
|
||||
btn.onclick = (event) => {
|
||||
var items = details_0.getElementsByClassName("activeSCButton");
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
items[i].classList.remove("activeSCButton");
|
||||
}
|
||||
btn.classList.add("activeSCButton");
|
||||
values[option.key] = option.value;
|
||||
span_0.innerText = option.value;
|
||||
change_cb(values);
|
||||
img_0.src = "static/ico/checkbox.png";
|
||||
};
|
||||
btn.style.borderRadius = "20px";
|
||||
//btn.style.fontSize="17.5px"
|
||||
details_0.append(btn);
|
||||
});
|
||||
}
|
||||
function addCategory_Personas(
|
||||
parent,
|
||||
options,
|
||||
defaultval,
|
||||
change_cb = () => {},
|
||||
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;
|
||||
var img_0 = document.createElement("img");
|
||||
img_0.src = "static/ico/checkbox_unchecked.png";
|
||||
img_0.style.height = "30px";
|
||||
if (defaultval != "") {
|
||||
details_0.open = false;
|
||||
img_0.src = "static/ico/checkbox.png";
|
||||
}
|
||||
var summary_0 = document.createElement("summary");
|
||||
var span_0 = document.createElement("span");
|
||||
span_0.style.float = "right";
|
||||
var p = SC_Personas[defaultval] || {};
|
||||
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";
|
||||
details_0.style.border = "2px solid black";
|
||||
details_0.style.borderRadius = "5px";
|
||||
details_0.style.backgroundColor = "white";
|
||||
details_0.style.cursor = "pointer";
|
||||
details_0.style.width = "calc(100% - 25px)";
|
||||
details_0.style.display = "inline-block";
|
||||
summary_0.style.padding = "10px";
|
||||
// background image at the start of summary_0:
|
||||
summary_0.style.backgroundImage = "url('static/ico/user.png')";
|
||||
summary_0.style.backgroundSize = "contain";
|
||||
summary_0.style.backgroundPosition = "left";
|
||||
summary_0.style.backgroundRepeat = "no-repeat";
|
||||
summary_0.style.textAlign = "left";
|
||||
summary_0.style.paddingLeft = "55px";
|
||||
parent.append(details_0);
|
||||
var lastreg = "";
|
||||
Object.entries(options)
|
||||
.sort(PERSONAS_Sorter)
|
||||
.map((entry) => {
|
||||
var key = entry[0];
|
||||
var value = entry[1];
|
||||
if (lastreg != value.Region.toUpperCase()) {
|
||||
lastreg = value.Region.toUpperCase();
|
||||
var h3_0 = document.createElement("h2");
|
||||
h3_0.style.margin = "0";
|
||||
h3_0.style.marginTop = "15px";
|
||||
h3_0.innerText = lastreg;
|
||||
details_0.append(h3_0);
|
||||
}
|
||||
var option = value.Nombre;
|
||||
var btn = document.createElement("button");
|
||||
var br1 = document.createElement("br");
|
||||
//btn.innerText = option.key + ": " + option.value
|
||||
btn.append(option);
|
||||
|
||||
var br2 = document.createElement("br");
|
||||
btn.append(br2);
|
||||
var img = document.createElement("img");
|
||||
img.src = value.Foto;
|
||||
img.style.height = "60px";
|
||||
img.style.padding = "5px";
|
||||
img.style.backgroundColor = "white";
|
||||
btn.append(img, " ");
|
||||
|
||||
if (defaultval == key) {
|
||||
btn.classList.add("activeSCButton");
|
||||
}
|
||||
btn.onclick = (event) => {
|
||||
var items = details_0.getElementsByClassName("activeSCButton");
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
items[i].classList.remove("activeSCButton");
|
||||
}
|
||||
btn.classList.add("activeSCButton");
|
||||
defaultval = key;
|
||||
span_0.innerText = "";
|
||||
var img_5 = document.createElement("img");
|
||||
img_5.src = value.Foto;
|
||||
img_5.style.height = "30px";
|
||||
span_0.append(img_5, value.Nombre);
|
||||
change_cb(defaultval);
|
||||
img_0.src = "static/ico/checkbox.png";
|
||||
};
|
||||
btn.style.borderRadius = "20px";
|
||||
//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",
|
||||
Temperatura: "static/ico/thermometer2.png",
|
||||
Leche: "static/ico/milk.png",
|
||||
Selección: "static/ico/preferences.png",
|
||||
Cafeina: "static/ico/coffee_bean.png",
|
||||
Endulzante: "static/ico/lollipop.png",
|
||||
Receta: "static/ico/cookies.png",
|
||||
};
|
||||
const SC_actions = {
|
||||
Selección: [
|
||||
{
|
||||
value: "Solo Leche",
|
||||
key: "Selección",
|
||||
className: "btn4",
|
||||
img: ["static/ico/milk.png"],
|
||||
},
|
||||
{
|
||||
value: "Solo café (sin leche)",
|
||||
key: "Selección",
|
||||
className: "btn4",
|
||||
img: ["static/ico/coffee_bean.png"],
|
||||
},
|
||||
{
|
||||
value: "Café con leche",
|
||||
key: "Selección",
|
||||
className: "btn4",
|
||||
img: ["static/ico/coffee_bean.png", "static/ico/milk.png"],
|
||||
},
|
||||
{
|
||||
value: "ColaCao con leche",
|
||||
key: "Selección",
|
||||
className: "btn4",
|
||||
img: ["static/ico/colacao.jpg", "static/ico/milk.png"],
|
||||
},
|
||||
{
|
||||
value: "Leche con cereales",
|
||||
key: "Selección",
|
||||
className: "btn4",
|
||||
img: ["static/ico/cereales.png", "static/ico/milk.png"],
|
||||
},
|
||||
{
|
||||
value: "Infusión",
|
||||
key: "Selección",
|
||||
className: "btn4",
|
||||
img: ["static/ico/tea_bag.png"],
|
||||
},
|
||||
],
|
||||
Tamaño: [
|
||||
{
|
||||
value: "Grande",
|
||||
key: "Tamaño",
|
||||
className: "btn1",
|
||||
img: ["static/ico/keyboard_key_g.png"],
|
||||
},
|
||||
{
|
||||
value: "Pequeño",
|
||||
key: "Tamaño",
|
||||
className: "btn1",
|
||||
img: ["static/ico/keyboard_key_p.png"],
|
||||
},
|
||||
],
|
||||
Temperatura: [
|
||||
{
|
||||
value: "Caliente",
|
||||
key: "Temperatura",
|
||||
className: "btn2",
|
||||
img: [
|
||||
"static/ico/thermometer2.png",
|
||||
"static/ico/arrow_up_red.png",
|
||||
"static/ico/fire.png",
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "Templado",
|
||||
key: "Temperatura",
|
||||
className: "btn2",
|
||||
img: ["static/ico/thermometer2.png", "static/ico/arrow_left_green.png"],
|
||||
},
|
||||
{
|
||||
value: "Frio",
|
||||
key: "Temperatura",
|
||||
className: "btn2",
|
||||
img: [
|
||||
"static/ico/thermometer2.png",
|
||||
"static/ico/arrow_down_blue.png",
|
||||
"static/ico/snowflake.png",
|
||||
],
|
||||
},
|
||||
],
|
||||
Leche: [
|
||||
{
|
||||
value: "de Vaca",
|
||||
key: "Leche",
|
||||
className: "btn3",
|
||||
img: ["static/ico/cow.png", "static/ico/add.png"],
|
||||
},
|
||||
{
|
||||
value: "Sin lactosa",
|
||||
key: "Leche",
|
||||
className: "btn3",
|
||||
img: ["static/ico/cow.png", "static/ico/delete.png"],
|
||||
},
|
||||
{
|
||||
value: "Vegetal",
|
||||
key: "Leche",
|
||||
className: "btn3",
|
||||
img: ["static/ico/milk.png", "static/ico/wheat.png"],
|
||||
},
|
||||
{
|
||||
value: "Agua",
|
||||
key: "Leche",
|
||||
className: "btn3",
|
||||
img: ["static/ico/water_tap.png"],
|
||||
},
|
||||
],
|
||||
Cafeina: [
|
||||
{
|
||||
value: "Con",
|
||||
key: "Cafeina",
|
||||
className: "btn5",
|
||||
img: ["static/ico/coffee_bean.png", "static/ico/add.png"],
|
||||
},
|
||||
{
|
||||
value: "Sin",
|
||||
key: "Cafeina",
|
||||
className: "btn5",
|
||||
img: ["static/ico/coffee_bean.png", "static/ico/delete.png"],
|
||||
},
|
||||
],
|
||||
Endulzante: [
|
||||
{
|
||||
value: "Az. Blanco",
|
||||
key: "Endulzante",
|
||||
className: "btn6",
|
||||
img: ["static/ico/azucar-blanco.jpg"],
|
||||
},
|
||||
{
|
||||
value: "Az. Moreno",
|
||||
key: "Endulzante",
|
||||
className: "btn6",
|
||||
img: ["static/ico/azucar-moreno.png"],
|
||||
},
|
||||
{
|
||||
value: "Sacarina",
|
||||
key: "Endulzante",
|
||||
className: "btn6",
|
||||
img: ["static/ico/sacarina.jpg"],
|
||||
},
|
||||
{
|
||||
value: "Stevia (Pastillas)",
|
||||
key: "Endulzante",
|
||||
className: "btn6",
|
||||
img: ["static/ico/stevia.jpg"],
|
||||
},
|
||||
{
|
||||
value: "Stevia (Gotas)",
|
||||
key: "Endulzante",
|
||||
className: "btn6",
|
||||
img: ["static/ico/stevia-gotas.webp"],
|
||||
},
|
||||
{
|
||||
value: "Sin",
|
||||
key: "Endulzante",
|
||||
className: "btn6",
|
||||
img: ["static/ico/delete.png"],
|
||||
},
|
||||
],
|
||||
Receta: [
|
||||
{
|
||||
value: "Si",
|
||||
key: "Receta",
|
||||
className: "btn7",
|
||||
img: ["static/ico/add.png"],
|
||||
},
|
||||
{
|
||||
value: "No",
|
||||
key: "Receta",
|
||||
className: "btn7",
|
||||
img: ["static/ico/delete.png"],
|
||||
},
|
||||
],
|
||||
};
|
||||
var SC_Personas = {};
|
||||
// Listado precargado de personas:
|
||||
gun
|
||||
.get(TABLE)
|
||||
.get("personas")
|
||||
.map()
|
||||
.on((data, key, _msg, _ev) => {
|
||||
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);
|
||||
});
|
||||
} else {
|
||||
add_row(data, key);
|
||||
}
|
||||
});
|
||||
|
||||
function SC_parse(json) {
|
||||
var out = "";
|
||||
Object.entries(json).forEach((entry) => {
|
||||
out += entry[0] + ": " + entry[1] + "\n";
|
||||
});
|
||||
return out;
|
||||
}
|
||||
function SC_parse_short(json) {
|
||||
var valores = "<small style='font-size: 60%;'>Servicio base (10c)</small>\n";
|
||||
|
||||
Object.entries(json).forEach((entry) => {
|
||||
valores +=
|
||||
"<small style='font-size: 60%;'>" +
|
||||
entry[0] +
|
||||
":</small> " +
|
||||
entry[1] +
|
||||
" ";
|
||||
var combo = entry[0] + ";" + entry[1];
|
||||
switch (entry[0]) {
|
||||
case "Leche":
|
||||
// Leche pequeña = 10c
|
||||
if (
|
||||
json["Tamaño"] == "Pequeño" &&
|
||||
["de Vaca", "Sin lactosa", "Vegetal"].includes(json["Leche"])
|
||||
) {
|
||||
valores += "<small>(P = 10c)</small>";
|
||||
}
|
||||
// Leche grande = 20c
|
||||
if (
|
||||
json["Tamaño"] == "Grande" &&
|
||||
["de Vaca", "Sin lactosa", "Vegetal"].includes(json["Leche"])
|
||||
) {
|
||||
valores += "<small>(G = 20c)</small>";
|
||||
}
|
||||
break;
|
||||
case "Selección":
|
||||
// Café = 20c
|
||||
if (
|
||||
["Café con leche", "Solo café (sin leche)"].includes(
|
||||
json["Selección"]
|
||||
)
|
||||
) {
|
||||
valores += "<small>(20c)</small>";
|
||||
}
|
||||
// ColaCao = 20c
|
||||
if (json["Selección"] == "ColaCao con leche") {
|
||||
valores += "<small>(20c)</small>";
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
valores += "\n";
|
||||
});
|
||||
return valores;
|
||||
}
|
||||
function SC_priceCalc(json) {
|
||||
var precio = 0;
|
||||
var valores = "";
|
||||
// Servicio base = 10c
|
||||
precio += 10;
|
||||
valores += "Servicio base = 10c\n";
|
||||
// Leche pequeña = 10c
|
||||
if (
|
||||
json["Tamaño"] == "Pequeño" &&
|
||||
["de Vaca", "Sin lactosa", "Vegetal"].includes(json["Leche"])
|
||||
) {
|
||||
precio += 10;
|
||||
valores += "Leche pequeña = 10c\n";
|
||||
}
|
||||
// Leche grande = 20c
|
||||
if (
|
||||
json["Tamaño"] == "Grande" &&
|
||||
["de Vaca", "Sin lactosa", "Vegetal"].includes(json["Leche"])
|
||||
) {
|
||||
precio += 20;
|
||||
valores += "Leche grande = 20c\n";
|
||||
}
|
||||
// Café = 20c
|
||||
if (["Café con leche", "Solo café (sin leche)"].includes(json["Selección"])) {
|
||||
precio += 20;
|
||||
valores += "Café = 20c\n";
|
||||
}
|
||||
// ColaCao = 20c
|
||||
if (json["Selección"] == "ColaCao con leche") {
|
||||
precio += 20;
|
||||
valores += "ColaCao = 20c\n";
|
||||
}
|
||||
valores += "<hr>Total: " + precio + "c\n";
|
||||
return [precio, valores];
|
||||
}
|
||||
function PERSONAS_Sorter(a, b) {
|
||||
if (a[1].Region < b[1].Region) {
|
||||
return -1;
|
||||
}
|
||||
if (a[1].Region > b[1].Region) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function TS_IndexElement(
|
||||
pageco,
|
||||
config,
|
||||
ref,
|
||||
container,
|
||||
rowCallback = undefined,
|
||||
canAddCallback = undefined,
|
||||
globalSearchBar = true,
|
||||
) {
|
||||
// Every item in config should have:
|
||||
// key: string
|
||||
// type: string
|
||||
// default: string
|
||||
// label: string
|
||||
var tablebody = safeuuid();
|
||||
var tablehead = safeuuid();
|
||||
var scrolltable = safeuuid();
|
||||
var searchKeyInput = safeuuid();
|
||||
|
||||
// Create the container with search bar and table
|
||||
container.innerHTML = `
|
||||
<div id="${scrolltable}">
|
||||
<input type="text" id="${searchKeyInput}" placeholder="🔍 Buscar..." style="width: 100%; max-width: 20rem; padding: 8px; border: 1px solid #ccc; border-radius: 4px; background-color: rebeccapurple; color: white;">
|
||||
<table>
|
||||
<thead>
|
||||
<tr id="${tablehead}"></tr>
|
||||
</thead>
|
||||
<tbody id="${tablebody}">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`;
|
||||
tableScroll("#" + scrolltable); // id="scrolltable"
|
||||
var tablehead_EL = document.getElementById(tablehead);
|
||||
var tablebody_EL = document.getElementById(tablebody);
|
||||
var rows = {};
|
||||
config.forEach((key) => {
|
||||
tablehead_EL.innerHTML += `<th>${key.label}</th>`;
|
||||
});
|
||||
// Add search functionality
|
||||
const searchKeyEl = document.getElementById(searchKeyInput);
|
||||
searchKeyEl.addEventListener('input', debounce(() => render(), 300));
|
||||
|
||||
function searchInData(data, searchValue, config) {
|
||||
if (!searchValue) return true;
|
||||
|
||||
// Search in ID
|
||||
if (data._key.toLowerCase().includes(searchValue)) return true;
|
||||
|
||||
// Search in configured fields
|
||||
for (const field of config) {
|
||||
const value = data[field.key];
|
||||
if (!value) continue;
|
||||
|
||||
// Handle different field types
|
||||
switch (field.type) {
|
||||
case "comanda":
|
||||
try {
|
||||
const comandaData = JSON.parse(data.Comanda);
|
||||
// Search in all comanda fields
|
||||
if (Object.values(comandaData).some(v =>
|
||||
String(v).toLowerCase().includes(searchValue)
|
||||
)) return true;
|
||||
} catch (e) {
|
||||
// If JSON parse fails, search in raw string
|
||||
if (data.Comanda.toLowerCase().includes(searchValue)) return true;
|
||||
}
|
||||
break;
|
||||
case "persona":
|
||||
const persona = SC_Personas[value];
|
||||
if (persona) {
|
||||
// Search in persona fields
|
||||
if (persona.Nombre?.toLowerCase().includes(searchValue)) return true;
|
||||
if (persona.Region?.toLowerCase().includes(searchValue)) return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// For raw and other types, search in the direct value
|
||||
if (String(value).toLowerCase().includes(searchValue)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function render() {
|
||||
function sorter(a, b) {
|
||||
if (a.Fecha < b.Fecha) {
|
||||
return -1;
|
||||
}
|
||||
if (a.Fecha > b.Fecha) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const searchValue = searchKeyEl.value.toLowerCase().trim();
|
||||
tablebody_EL.innerHTML = "";
|
||||
Object.entries(rows)
|
||||
.filter(([_, data]) => searchInData(data, searchValue, config))
|
||||
.map(([_, data]) => data)
|
||||
.sort(sorter)
|
||||
.forEach((data) => {
|
||||
var new_tr = document.createElement("tr");
|
||||
|
||||
if (canAddCallback != undefined) {
|
||||
if (canAddCallback(data) == true) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
tablebody_EL.append(new_tr);
|
||||
if (rowCallback != undefined) {
|
||||
rowCallback(data, new_tr);
|
||||
}
|
||||
config.forEach((key) => {
|
||||
switch (key.type) {
|
||||
case "raw":
|
||||
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 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");
|
||||
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 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;
|
||||
|
||||
tdComanda.appendChild(pre);
|
||||
new_tr.appendChild(tdComanda);
|
||||
break;
|
||||
case "comanda-status":
|
||||
var sc_nobtn = "";
|
||||
if (urlParams.get("sc_nobtn") == "yes") {
|
||||
sc_nobtn = "pointer-events: none; opacity: 0.5";
|
||||
}
|
||||
const td = document.createElement("td");
|
||||
td.style.fontSize = "17px";
|
||||
if (sc_nobtn) {
|
||||
td.style.pointerEvents = "none";
|
||||
td.style.opacity = "0.5";
|
||||
}
|
||||
|
||||
// Create buttons
|
||||
const createButton = (text, state) => {
|
||||
const button = document.createElement("button");
|
||||
button.textContent = text;
|
||||
if (data.Estado === state) {
|
||||
button.className = "rojo";
|
||||
}
|
||||
button.onclick = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
data.Estado = state;
|
||||
var enc = SEA.encrypt(data, SECRET, (encrypted) => {
|
||||
betterGunPut(ref.get(data._key), encrypted);
|
||||
toastr.success("Guardado!");
|
||||
});
|
||||
return false;
|
||||
};
|
||||
return button;
|
||||
};
|
||||
|
||||
// Create all buttons
|
||||
const buttons = [
|
||||
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";
|
||||
paidButton.onclick = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (
|
||||
!confirm(
|
||||
"¿Quieres marcar como pagado? - Se borrara la comanda y se actualizarán los puntos."
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
data.Estado = "Pagado";
|
||||
betterGunPut(ref.get(data._key), null);
|
||||
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 +
|
||||
"!"
|
||||
);
|
||||
} 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
|
||||
);
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
// Add all buttons to td with line breaks between
|
||||
buttons.forEach((button) => {
|
||||
td.appendChild(button);
|
||||
td.appendChild(document.createElement("br"));
|
||||
});
|
||||
td.appendChild(paidButton);
|
||||
new_tr.appendChild(td);
|
||||
|
||||
// Event handlers are now attached during button creation
|
||||
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";
|
||||
tdPersona.style.backgroundColor = regco;
|
||||
tdPersona.style.color = colorIsDarkAdvanced(regco);
|
||||
|
||||
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";
|
||||
|
||||
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";
|
||||
pointsSpan.textContent = (persona.Puntos || "0") + " puntos.";
|
||||
infoSpan.appendChild(pointsSpan);
|
||||
|
||||
tdPersona.appendChild(infoSpan);
|
||||
new_tr.appendChild(tdPersona);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
new_tr.onclick = (event) => {
|
||||
setUrlHash(pageco + "," + data._key);
|
||||
};
|
||||
});
|
||||
}
|
||||
ref.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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
a.innerText = PAGES[key].Title;
|
||||
document.getElementById("appendApps").append(a);
|
||||
});
|
||||
open_page(location.hash.replace("#", ""));
|
||||
});
|
||||
25
src/config.js
Normal file
@@ -0,0 +1,25 @@
|
||||
var EVENTLISTENER = null;
|
||||
var EVENTLISTENER2 = null;
|
||||
var urlParams = new URLSearchParams(location.search);
|
||||
if (urlParams.get("hidenav") == "yes") {
|
||||
document.getElementById("header_hide_query").style.display = "none";
|
||||
}
|
||||
var GROUPID = "";
|
||||
// const PUBLIC_KEY = "~cppGiuA4UFUPGTDoC-4r2izVC3F7MfpaCmF3iZdESN4.vntmjgbAVUpF_zfinYY6EKVFuuTYxh5xOrL4KmtdTmc"
|
||||
var TABLE = GROUPID + ":telesec.tech.eus";
|
||||
const RELAYS = [
|
||||
"https://gun-es01.tech.eus/gun",
|
||||
"https://gun-es02.tech.eus/gun",
|
||||
"https://gun-es03.tech.eus/gun",
|
||||
"https://gun-es04.tech.eus/gun",
|
||||
"https://gun-es05.tech.eus/gun",
|
||||
"https://gun-es06.tech.eus/gun",
|
||||
// "https://gun-es07.tech.eus/gun", // No he podido instalar el nodo.
|
||||
"https://gun-manhattan.herokuapp.com/gun",
|
||||
"https://peer.wallie.io/gun",
|
||||
"https://gun.defucc.me/gun",
|
||||
];
|
||||
var SECRET = "";
|
||||
var SUB_LOGGED_IN = false;
|
||||
var SUB_LOGGED_IN_DETAILS = false;
|
||||
var SUB_LOGGED_IN_ID = false;
|
||||
61
src/gun_init.js
Normal file
@@ -0,0 +1,61 @@
|
||||
window.rtcRoom = "telesec.tech.eus";
|
||||
var gun = Gun(RELAYS, {
|
||||
axe: false,
|
||||
localStorage: true,
|
||||
// radisk: true,
|
||||
});
|
||||
var SEA = Gun.SEA;
|
||||
var user = gun.user();
|
||||
function removeCache() {
|
||||
caches.keys().then(function (names) {
|
||||
for (let name of names) caches.delete(name);
|
||||
console.log("Removing cache " + name);
|
||||
console.log("OK");
|
||||
location.reload(true);
|
||||
});
|
||||
}
|
||||
function getPeers() {
|
||||
var peerCount = 0;
|
||||
var peerCountEl = document.getElementById("peerCount");
|
||||
var peerListEl = document.getElementById("peerList");
|
||||
var list = document.createElement("ul");
|
||||
document.getElementById("peerPID").innerText = "PID " + gun.back("opt.pid");
|
||||
Object.values(gun.back("opt.peers")).forEach((peer) => {
|
||||
if (
|
||||
peer.wire != undefined &&
|
||||
(peer.wire.readyState == 1 || peer.wire.readyState == "open")
|
||||
) {
|
||||
peerCount += 1;
|
||||
var wireType = peer.wire.constructor.name;
|
||||
var wireHType = peer.wire.constructor.name;
|
||||
var wireID = peer.id;
|
||||
switch (wireType) {
|
||||
case "WebSocket":
|
||||
wireHType = "Web";
|
||||
wireID = wireID.split("/")[2];
|
||||
break;
|
||||
case "RTCDataChannel":
|
||||
wireHType = "Mesh";
|
||||
wireID = peer.id;
|
||||
}
|
||||
var el = document.createElement("li");
|
||||
el.innerText = `Nodo ${wireHType}: ${wireID}`;
|
||||
list.append(el);
|
||||
}
|
||||
});
|
||||
peerListEl.innerHTML = list.innerHTML;
|
||||
peerCountEl.innerText = peerCount;
|
||||
if (peerCount < 3) {
|
||||
document.getElementById("connectStatus").src = "static/ico/connect_ko.svg";
|
||||
gun.opt({ peers: RELAYS });
|
||||
} else {
|
||||
document.getElementById("connectStatus").src = "static/ico/connect_ok.svg";
|
||||
}
|
||||
}
|
||||
getPeers();
|
||||
setInterval(() => {
|
||||
getPeers();
|
||||
}, 2500);
|
||||
function safeuuid(prefix = "AXLUID_") {
|
||||
return prefix + crypto.randomUUID().split("-")[4];
|
||||
}
|
||||
2778
src/index.html
114
src/page/comedor.js
Normal file
@@ -0,0 +1,114 @@
|
||||
PAGES.comedor = {
|
||||
navcss: "btn7",
|
||||
Title: "Menú comedor",
|
||||
edit: function (mid) {
|
||||
var nameh1 = safeuuid();
|
||||
var field_fecha = safeuuid();
|
||||
var field_platos = safeuuid();
|
||||
var btn_guardar = safeuuid();
|
||||
var btn_borrar = safeuuid();
|
||||
container.innerHTML = `
|
||||
<h1>Entrada del menú <code id="${nameh1}"></code></h1>
|
||||
<fieldset style="float: left;">
|
||||
<legend>Valores</legend>
|
||||
<label>
|
||||
Fecha<br>
|
||||
<input type="date" id="${field_fecha}" value="${CurrentISODate()}"><br><br>
|
||||
</label>
|
||||
<label>
|
||||
Platos<br>
|
||||
<textarea id="${field_platos}"></textarea><br><br>
|
||||
</label>
|
||||
<button class="btn5" id="${btn_guardar}">Guardar</button>
|
||||
<button class="rojo" id="${btn_borrar}">Borrar</button>
|
||||
</fieldset>
|
||||
`;
|
||||
gun
|
||||
.get(TABLE)
|
||||
.get("comedor")
|
||||
.get(mid)
|
||||
.once((data, key) => {
|
||||
function load_data(data, ENC = "") {
|
||||
document.getElementById(nameh1).innerText = key;
|
||||
document.getElementById(field_fecha).value = data["Fecha"];
|
||||
document.getElementById(field_platos).value =
|
||||
data["Platos"] || "";
|
||||
}
|
||||
if (typeof data == "string") {
|
||||
SEA.decrypt(data, SECRET, (data) => {
|
||||
load_data(data, "%E");
|
||||
});
|
||||
} else {
|
||||
load_data(data);
|
||||
}
|
||||
});
|
||||
document.getElementById(btn_guardar).onclick = () => {
|
||||
const newDate = document.getElementById(field_fecha).value;
|
||||
var data = {
|
||||
Fecha: newDate,
|
||||
Platos: document.getElementById(field_platos).value,
|
||||
};
|
||||
|
||||
// If the date has changed, we need to delete the old entry
|
||||
if (mid !== newDate && mid !== "") {
|
||||
betterGunPut(gun.get(TABLE).get("comedor").get(mid), null);
|
||||
}
|
||||
|
||||
var enc = SEA.encrypt(data, SECRET, (encrypted) => {
|
||||
document.getElementById("actionStatus").style.display = "block";
|
||||
betterGunPut(gun.get(TABLE).get("comedor").get(newDate), encrypted);
|
||||
toastr.success("Guardado!");
|
||||
setTimeout(() => {
|
||||
document.getElementById("actionStatus").style.display = "none";
|
||||
setUrlHash("comedor");
|
||||
}, 1500);
|
||||
});
|
||||
};
|
||||
document.getElementById(btn_borrar).onclick = () => {
|
||||
if (confirm("¿Quieres borrar esta entrada?") == true) {
|
||||
betterGunPut(gun.get(TABLE).get("comedor").get(mid), null);
|
||||
toastr.error("Borrado!");
|
||||
setTimeout(() => {
|
||||
setUrlHash("comedor");
|
||||
}, 1500);
|
||||
}
|
||||
};
|
||||
},
|
||||
index: function () {
|
||||
const tablebody = safeuuid();
|
||||
var btn_new = safeuuid();
|
||||
container.innerHTML = `
|
||||
<h1>Menú del comedor</h1>
|
||||
<button id="${btn_new}">Nueva entrada</button>
|
||||
<div id="cont"></div>
|
||||
`;
|
||||
TS_IndexElement(
|
||||
"comedor",
|
||||
[
|
||||
{
|
||||
key: "Fecha",
|
||||
type: "raw",
|
||||
default: "",
|
||||
label: "Fecha",
|
||||
},
|
||||
{
|
||||
key: "Platos",
|
||||
type: "raw",
|
||||
default: "",
|
||||
label: "Platos",
|
||||
}
|
||||
],
|
||||
gun.get(TABLE).get("comedor"),
|
||||
document.querySelector("#cont"),
|
||||
(data, new_tr) => {
|
||||
// new_tr.style.backgroundColor = "#FFCCCB";
|
||||
if (data.Fecha == CurrentISODate()) {
|
||||
new_tr.style.backgroundColor = "lightgreen";
|
||||
}
|
||||
}
|
||||
);
|
||||
document.getElementById(btn_new).onclick = () => {
|
||||
setUrlHash("comedor," + safeuuid(""));
|
||||
};
|
||||
},
|
||||
};
|
||||
89
src/page/exportar.js
Normal file
@@ -0,0 +1,89 @@
|
||||
PAGES.exportar = {
|
||||
navcss: "btn1",
|
||||
Title: "Exportar",
|
||||
index: function () {
|
||||
var select_type = safeuuid();
|
||||
var textarea_content = safeuuid();
|
||||
var button_export_local = safeuuid();
|
||||
var button_export_safe = safeuuid();
|
||||
var button_export_safe_cloud = safeuuid();
|
||||
var button_clear = safeuuid();
|
||||
container.innerHTML = `
|
||||
<h1>Exportar Datos</h1>
|
||||
<fieldset>
|
||||
<legend>Exportar datos</legend>
|
||||
<em>Al pulsar, Espera hasta que salga una notificacion verde.</em>
|
||||
<br>
|
||||
<br>
|
||||
<button id="${button_export_local}" type="button">Exportar sin cifrar</button>
|
||||
<button id="${button_export_safe}" type="button">Exportar con cifrado</button>
|
||||
<button id="${button_export_safe_cloud}" style="display: none;" type="button">Exportar a EuskadiTech - cifrado</button>
|
||||
<!--<br><br><em>Para descargar envia un correo a telesec@tech.eus con el asunto "TSBK %${GROUPID}".</em>-->
|
||||
</fieldset>
|
||||
`;
|
||||
document.getElementById(button_export_local).onclick = () => {
|
||||
var data_export = {};
|
||||
var output = {
|
||||
materiales: {},
|
||||
personas: {},
|
||||
};
|
||||
var download_data = (DATA) => {
|
||||
Object.keys(DATA).forEach((modul) => {
|
||||
Object.entries(DATA[modul] || {}).forEach((entry) => {
|
||||
var key = entry[0];
|
||||
var value = entry[1];
|
||||
if (value != null) {
|
||||
if (typeof value == "string") {
|
||||
SEA.decrypt(value, SECRET, (data) => {
|
||||
output[modul][key] = data;
|
||||
});
|
||||
} else {
|
||||
output[modul][key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
toastr.success("Exportado todo, descargando!");
|
||||
console.error(output);
|
||||
download(
|
||||
`Export TeleSec ${GROUPID}.json.txt`,
|
||||
JSON.stringify(output)
|
||||
);
|
||||
//setUrlHash(sel);
|
||||
}, 2500);
|
||||
};
|
||||
gun.get(TABLE).load(download_data);
|
||||
};
|
||||
document.getElementById(button_export_safe).onclick = () => {
|
||||
var download_data = (DATA) => {
|
||||
toastr.success("Exportado todo, descargado!");
|
||||
console.error(DATA);
|
||||
download(
|
||||
`Export TeleSec Encriptado ${GROUPID}.json.txt`,
|
||||
JSON.stringify(DATA)
|
||||
);
|
||||
//setUrlHash(sel);
|
||||
};
|
||||
gun.get(TABLE).load(download_data);
|
||||
};
|
||||
document.getElementById(button_export_safe_cloud).onclick = () => {
|
||||
var download_data = (DATA) => {
|
||||
toastr.info("Exportado todo, subiendo!");
|
||||
console.error(DATA);
|
||||
fetch(
|
||||
"https://telesec-sync.tech.eus/upload_backup.php?table=" + GROUPID,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify(DATA),
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
toastr.success("Subido correctamente!");
|
||||
})
|
||||
.catch(() => {
|
||||
toastr.error("Ha ocurrido un error en la subida.");
|
||||
});
|
||||
};
|
||||
gun.get(TABLE).load(download_data);
|
||||
};
|
||||
},
|
||||
};
|
||||