Compare commits
2 Commits
08f91ac819
...
7211b678fd
| Author | SHA1 | Date |
|---|---|---|
|
|
7211b678fd | |
|
|
7efaa919b6 |
|
|
@ -17,6 +17,7 @@
|
|||
--warning: #d7ba7d;
|
||||
--sidebar-w: 290px;
|
||||
--topbar-h: 52px;
|
||||
--audio-bar-h: 64px;
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
|
@ -314,7 +315,7 @@ a:hover { text-decoration: underline; }
|
|||
PLAYER – CURSO
|
||||
============================================================ */
|
||||
.player-layout {
|
||||
display: flex;
|
||||
display: block;
|
||||
margin-top: var(--topbar-h);
|
||||
min-height: calc(100vh - var(--topbar-h));
|
||||
}
|
||||
|
|
@ -589,6 +590,63 @@ a:hover { text-decoration: underline; }
|
|||
accent-color: var(--accent);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
AUDIO BAR – barra fija inferior
|
||||
============================================================ */
|
||||
.audio-bar-fixed {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
min-height: var(--audio-bar-h);
|
||||
background: var(--bg-alt);
|
||||
border-top: 3px solid var(--accent);
|
||||
box-shadow: 0 -2px 12px rgba(0,0,0,.4);
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: .6rem 1rem;
|
||||
padding: .6rem 1.5rem;
|
||||
transition: transform .3s ease;
|
||||
}
|
||||
.audio-bar-fixed.audio-bar-hidden {
|
||||
transform: translateY(110%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.audio-bar-icon {
|
||||
color: var(--accent);
|
||||
font-size: 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.audio-bar-title {
|
||||
font-size: .75rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .06em;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.audio-bar-controls {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
flex: 1;
|
||||
}
|
||||
.audio-bar-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
}
|
||||
.audio-bar-fixed audio {
|
||||
height: 32px;
|
||||
accent-color: var(--accent);
|
||||
}
|
||||
body.has-audio-bar {
|
||||
padding-bottom: var(--audio-bar-h);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
CUESTIONARIOS
|
||||
============================================================ */
|
||||
|
|
|
|||
|
|
@ -115,20 +115,6 @@ function renderMarkdown(md, tema, bloque, bloqueId, temaNum) {
|
|||
|
||||
const html = marked.parse(md);
|
||||
|
||||
const audioHtml = (tema.audios && tema.audios.length)
|
||||
? `<div class="tema-audio-bar">
|
||||
<i class="fas fa-headphones"></i>
|
||||
<span class="tema-audio-label">Escuchar este tema</span>
|
||||
${tema.audios.map(a => `
|
||||
<div class="tema-audio-item">
|
||||
${tema.audios.length > 1 ? `<span class="tema-audio-tag">${a.label}</span>` : ''}
|
||||
<audio controls preload="none">
|
||||
<source src="${a.src}" type="audio/mpeg">
|
||||
</audio>
|
||||
</div>`).join('')}
|
||||
</div>`
|
||||
: '';
|
||||
|
||||
const leyesHtml = (tema.leyes && tema.leyes.length)
|
||||
? `<div class="tema-leyes-bar">
|
||||
<i class="fas fa-landmark"></i>
|
||||
|
|
@ -142,7 +128,6 @@ function renderMarkdown(md, tema, bloque, bloqueId, temaNum) {
|
|||
: '';
|
||||
|
||||
document.getElementById('lesson-content').innerHTML = `
|
||||
${audioHtml}
|
||||
${leyesHtml}
|
||||
<div class="md-body">${html}</div>
|
||||
<nav class="lesson-nav" aria-label="Navegación entre temas">
|
||||
|
|
@ -159,6 +144,65 @@ function renderMarkdown(md, tema, bloque, bloqueId, temaNum) {
|
|||
|
||||
// Actualizar progress en topbar
|
||||
updateTopbarProgress(pos, total);
|
||||
|
||||
// Barra de audio fija
|
||||
updateAudioBar(tema, bloqueId, temaNum);
|
||||
}
|
||||
|
||||
// ── Audio bar fija (bottom) ───────────────────────────────────
|
||||
function updateAudioBar(tema, bloqueId, temaNum) {
|
||||
const bar = document.getElementById('audio-bar');
|
||||
const titleEl = document.getElementById('audio-bar-title');
|
||||
const controlsEl = document.getElementById('audio-bar-controls');
|
||||
if (!bar || !titleEl || !controlsEl) return;
|
||||
|
||||
// Parar cualquier audio en curso
|
||||
bar.querySelectorAll('audio').forEach(a => a.pause());
|
||||
|
||||
if (!tema.audios || !tema.audios.length) {
|
||||
bar.classList.add('audio-bar-hidden');
|
||||
document.body.classList.remove('has-audio-bar');
|
||||
return;
|
||||
}
|
||||
|
||||
titleEl.textContent = `B${toRoman(bloqueId)} · T${temaNum}`;
|
||||
|
||||
controlsEl.innerHTML = tema.audios.map(a => `
|
||||
<div class="audio-bar-item">
|
||||
${tema.audios.length > 1 ? `<span class="tema-audio-tag">${a.label}</span>` : ''}
|
||||
<audio controls preload="none" data-key="audioPos:${a.src}">
|
||||
<source src="${a.src}" type="audio/mpeg">
|
||||
</audio>
|
||||
</div>`).join('');
|
||||
|
||||
// Restaurar y guardar posición por audio
|
||||
controlsEl.querySelectorAll('audio').forEach(audioEl => {
|
||||
const key = audioEl.dataset.key;
|
||||
audioEl.addEventListener('loadedmetadata', () => {
|
||||
const saved = parseFloat(localStorage.getItem(key) || '0');
|
||||
if (saved > 1 && saved < audioEl.duration - 2) {
|
||||
audioEl.currentTime = saved;
|
||||
}
|
||||
});
|
||||
let _saveTimer = null;
|
||||
audioEl.addEventListener('play', () => {
|
||||
clearInterval(_saveTimer);
|
||||
_saveTimer = setInterval(() => {
|
||||
localStorage.setItem(key, audioEl.currentTime.toString());
|
||||
}, 5000);
|
||||
});
|
||||
audioEl.addEventListener('pause', () => {
|
||||
clearInterval(_saveTimer);
|
||||
localStorage.setItem(key, audioEl.currentTime.toString());
|
||||
});
|
||||
audioEl.addEventListener('ended', () => {
|
||||
clearInterval(_saveTimer);
|
||||
localStorage.removeItem(key);
|
||||
});
|
||||
});
|
||||
|
||||
bar.classList.remove('audio-bar-hidden');
|
||||
document.body.classList.add('has-audio-bar');
|
||||
}
|
||||
|
||||
function showError(msg) {
|
||||
|
|
|
|||
|
|
@ -17,44 +17,114 @@
|
|||
<link>https://taiage.tatvil.es</link>
|
||||
</image>
|
||||
<item>
|
||||
<title>TEXTO REFUNDIDO DE LA LEY DEL ESTATUTO BÁSICO DEL EMPLEADO PÚBLICO</title>
|
||||
<description>TEXTO REFUNDIDO DE LA LEY DEL ESTATUTO BÁSICO DEL EMPLEADO PÚBLICO</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/B1T4-TREBEP.mp3" length="274628844" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/B1T4-TREBEP.mp3</guid>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/1-6-firma-electronica-BOE-A-2003-23399-consolidado.mp3" length="141757987" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/1-6-firma-electronica-BOE-A-2003-23399-consolidado.mp3</guid>
|
||||
<pubDate>Wed, 01 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>1</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Ley Orgánica 3/2007, de 22 de marzo, para la igualdad efectiva de mujeres y hombres.</title>
|
||||
<description>Ley Orgánica 3/2007, de 22 de marzo, para la igualdad efectiva de mujeres y hombres.</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/B1T5-igualdad-de-genero.mp3" length="316599900" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/B1T5-igualdad-de-genero.mp3</guid>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/1-6-Sociedad-de-la-informacion-BOE-A-2002-13758-consolidado.mp3" length="183336576" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/1-6-Sociedad-de-la-informacion-BOE-A-2002-13758-consolidado.mp3</guid>
|
||||
<pubDate>Thu, 02 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>2</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Ley 39/2006, de 14 de diciembre, de Promoción de la Autonomía Personal y Atención a las personas en situación de dependencia.</title>
|
||||
<description>Ley 39/2006, de 14 de diciembre, de Promoción de la Autonomía Personal y Atención a las personas en situación de dependencia.</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/B1T5-ley-dependencia.mp3" length="135383871" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/B1T5-ley-dependencia.mp3</guid>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/1-7-BOE-A-2018-16673-consolidado.mp3" length="363104973" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/1-7-BOE-A-2018-16673-consolidado.mp3</guid>
|
||||
<pubDate>Fri, 03 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>3</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Ley 4/2023, de 28 de febrero, para la igualdad real y efectiva de las personas trans y para la garantía de los derechos de las personas LGTBI.</title>
|
||||
<description>Ley 4/2023, de 28 de febrero, para la igualdad real y efectiva de las personas trans y para la garantía de los derechos de las personas LGTBI.</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/B1T5-ley-trans.mp3" length="302810372" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/B1T5-ley-trans.mp3</guid>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/BOE-A-1978-31229-consolidado.mp3" length="173240950" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/BOE-A-1978-31229-consolidado.mp3</guid>
|
||||
<pubDate>Sat, 04 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>4</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/BOE-A-1981-10325-consolidado-defensor-del-pueblo.mp3" length="39237195" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/BOE-A-1981-10325-consolidado-defensor-del-pueblo.mp3</guid>
|
||||
<pubDate>Sun, 05 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>5</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/BOE-A-1981-12774-consolidado-estados-alarma-excepcion-sitio.mp3" length="34965245" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/BOE-A-1981-12774-consolidado-estados-alarma-excepcion-sitio.mp3</guid>
|
||||
<pubDate>Mon, 06 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>6</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/BOE-A-1997-25336-consolidado-gobierno.mp3" length="81233932" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/BOE-A-1997-25336-consolidado-gobierno.mp3</guid>
|
||||
<pubDate>Tue, 07 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>7</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/BOE-A-2004-21760-consolidado-violencia-genero.mp3" length="232731187" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/BOE-A-2004-21760-consolidado-violencia-genero.mp3</guid>
|
||||
<pubDate>Wed, 08 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>8</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/BOE-A-2006-21990-consolidado-dependencia.mp3" length="135519309" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/BOE-A-2006-21990-consolidado-dependencia.mp3</guid>
|
||||
<pubDate>Thu, 09 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>9</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/BOE-A-2007-6115-consolidado igualdad de genero.mp3" length="320203567" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/BOE-A-2007-6115-consolidado igualdad de genero.mp3</guid>
|
||||
<pubDate>Fri, 10 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>10</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
<item>
|
||||
<title>Null</title>
|
||||
<description>Null</description>
|
||||
<enclosure url="https://taiage.tatvil.es/audios/leyes/BOE-A-2022-7191-consolidado.mp3" length="372174891" type="audio/mpeg"/>
|
||||
<guid>https://taiage.tatvil.es/audios/leyes/BOE-A-2022-7191-consolidado.mp3</guid>
|
||||
<pubDate>Sat, 11 Apr 2026 10:00:00 +0000</pubDate>
|
||||
<itunes:episode>11</itunes:episode>
|
||||
<itunes:season>1</itunes:season>
|
||||
<itunes:episodeType>full</itunes:episodeType>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
|
|
|
|||
|
|
@ -322,9 +322,7 @@ Mayor seguridad frente a ataques.
|
|||
|
||||
---
|
||||
|
||||
## 8. Gestión de usuarios
|
||||
|
||||
### 8.1. Introducción
|
||||
# 8. Gestión de usuarios
|
||||
|
||||
La gestión de usuarios consiste en administrar:
|
||||
|
||||
|
|
@ -388,7 +386,6 @@ Cada usuario debe tener:
|
|||
|
||||
- Solo los permisos necesarios.
|
||||
|
||||
---
|
||||
|
||||
## Tipos de permisos
|
||||
|
||||
|
|
@ -408,6 +405,15 @@ Ejecutar programas.
|
|||
|
||||
Administración completa.
|
||||
|
||||
## Linux/Unix
|
||||
- rwx (lectura, escritura, ejecución)
|
||||
- comandos: chmod, chown, chgrp
|
||||
## Windows
|
||||
- R (lectura)
|
||||
- W (escritura)
|
||||
- X (ejecución)
|
||||
- gestión mediante ACLs (Access Control Lists)
|
||||
|
||||
---
|
||||
|
||||
# 11. Políticas de seguridad
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
<span class="topbar-progress" id="topbar-progress">1 / 33</span>
|
||||
<!-- Usuario / sesión -->
|
||||
<div class="topbar-user">
|
||||
<span sec:authorize="isAuthenticated()" class="user-email" sec:authentication="principal.username"></span>
|
||||
<span sec:authorize="isAuthenticated()" class="user-email" th:text="${#strings.substringBefore(#authentication.name, '@')}"></span>
|
||||
<a sec:authorize="hasRole('ADMIN')" th:href="@{/admin/usuarios}" class="btn-login" style="margin-right:.5rem">Admin</a>
|
||||
<form sec:authorize="isAuthenticated()" th:action="@{/logout}" method="post" style="margin:0">
|
||||
<button type="submit" class="btn-logout">Salir</button>
|
||||
|
|
@ -56,6 +56,13 @@
|
|||
|
||||
</div>
|
||||
|
||||
<!-- ── Audio bar (fija, inferior) ──────────────────────── -->
|
||||
<div id="audio-bar" class="audio-bar-fixed audio-bar-hidden" aria-label="Reproductor de audio">
|
||||
<i class="fas fa-headphones audio-bar-icon"></i>
|
||||
<span class="audio-bar-title" id="audio-bar-title"></span>
|
||||
<div class="audio-bar-controls" id="audio-bar-controls"></div>
|
||||
</div>
|
||||
|
||||
<!-- ── Scripts ────────────────────────────────────────── -->
|
||||
<!-- marked.js para renderizar Markdown en el cliente -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked@12/marked.min.js"></script>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
</nav>
|
||||
<!-- Usuario / sesión -->
|
||||
<div class="topbar-user">
|
||||
<span sec:authorize="isAuthenticated()" class="user-email" sec:authentication="principal.username"></span>
|
||||
<span sec:authorize="isAuthenticated()" class="user-email" th:text="${#strings.substringBefore(#authentication.name, '@')}"></span>
|
||||
<a sec:authorize="hasRole('ADMIN')" th:href="@{/admin/usuarios}" class="btn-login" style="margin-right:.5rem">Admin</a>
|
||||
<form sec:authorize="isAuthenticated()" th:action="@{/logout}" method="post" style="margin:0">
|
||||
<button type="submit" class="btn-logout">Salir</button>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<a sec:authorize="hasAnyRole('PAGADO','ADMIN')" th:href="@{/flashcards.html}">Flashcards</a>
|
||||
</nav>
|
||||
<div class="topbar-user">
|
||||
<span sec:authorize="isAuthenticated()" class="user-email" sec:authentication="principal.username"></span>
|
||||
<span sec:authorize="isAuthenticated()" class="user-email" th:text="${#strings.substringBefore(#authentication.name, '@')}"></span>
|
||||
<form sec:authorize="isAuthenticated()" th:action="@{/logout}" method="post" style="margin:0">
|
||||
<button type="submit" class="btn-logout">Salir</button>
|
||||
</form>
|
||||
|
|
|
|||
Loading…
Reference in New Issue