Pedido de Leo (27-oct): mover un pendiente a otra columna sin arrastrar y bajar a la vez, cambiar la columna desde el detalle, y un solo campeón por pendiente que es quien lo mueve. - backend/app.py: campo «campeon» (uno de los responsables; por omisión el primero). PATCH /api/tarea y POST /api/tareas/orden solo cambian la columna o el campeón si quien escribe es el campeón, un administrador o TAREAS_MUEVEN_SIEMPRE (claude, por los lotes). GET /api/tareas trae campeon y mueven_siempre. - kanban.js / tablero.css: avatar del campeón primero y con anillo; flechas ← → en la tarjeta; franja fija arriba con las 4 columnas mientras se arrastra; botones de Columna y selector de Campeón en el detalle; tarjetas de otros sin arrastre ni flechas. - tablero.py y lotes/README.md: «campeon» se puede poner en un lote. - tests-campeon.sh (25 pruebas); tests-1014.sh: el PATCH de bob ya no cambia la columna. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013SfRSvyewSyFLfK9mjbGL8
52 lines
3.4 KiB
Markdown
52 lines
3.4 KiB
Markdown
---
|
|
title: "Pendientes"
|
|
description: "El tablero de pendientes del equipo: por hacer, en curso, bloqueado y hecho."
|
|
template: tablero.html
|
|
hide:
|
|
- toc
|
|
---
|
|
|
|
<div class="tb tb-pendientes">
|
|
<header class="tb-cab">
|
|
<div class="tb-cab__t"><h1>Pendientes</h1><span class="meta" id="meta">Ingeniería, producción, mecánica, compras, campo y gestión · por sitio</span></div>
|
|
<div class="tb-cab__acc"><span id="acciones-kb"></span></div>
|
|
</header>
|
|
|
|
<details class="info tb-como">
|
|
<summary>Cómo se usa</summary>
|
|
<ol>
|
|
<li>Cada tarjeta del tablero es un <b>pendiente</b> (no confundir con la tarjeta EinarBoard). Léelo antes de empezar el trabajo.</li>
|
|
<li>Para cambiarlo de columna: arrástralo (arriba aparece una franja con las cuatro columnas, suéltalo ahí y no tienes que bajar), usa las flechas <b>← →</b> de la tarjeta o los botones de <b>Columna</b> en el detalle; en el teléfono, <b>Mover a…</b>. El tablero anota quién lo movió y cuándo.</li>
|
|
<li><b>Campeón:</b> aunque un pendiente tenga varios responsables, uno solo lo mueve entre columnas y responde por él (su avatar va primero, con anillo). Se elige en el detalle; sin elegir, es el primero de la lista. Los demás responsables editan todo lo demás; para moverlo, pídele al campeón que te lo pase. Leo (administrador) puede mover cualquiera.</li>
|
|
<li>Toca el título para ver el detalle: descripción, enlaces, de qué depende y su historial. Ahí mismo edita y guarda.</li>
|
|
<li><b>Nuevo pendiente</b>: título corto, pista, responsable y fecha límite. Si depende de otro, márcalo en «Bloqueado por».</li>
|
|
<li>Columna <b>Bloqueado</b>: solo si no puedes avanzar. Escribe en la descripción qué falta y quién lo destraba.</li>
|
|
<li>Al terminar, muévelo a <b>Hecho</b>. No lo borres: solo el administrador borra, y el historial sirve de bitácora.</li>
|
|
<li>Rojo = vencido. Filtra por pista, responsable o versión de tarjeta; los filtros no cambian nada en el servidor.</li>
|
|
<li><b>Sitio</b>: cada pendiente dice dónde pasa (ICAVE, TIMSA, EIT, LCT o Querétaro). Los botones de sitio dejan solo los de tu sitio (puedes elegir varios); <b>Por sitio</b> muestra una fila por sitio. Al crear un pendiente con un sitio filtrado, ese sitio ya viene marcado. La dirección (<code>?sitio=eit</code>) se puede compartir.</li>
|
|
<li><b>Por persona</b> muestra una fila por responsable con sus pendientes en cada estado: sirve para ver quién está cargado y quién está libre. La dirección (<code>?vista=persona</code>, <code>?mios=1</code>) se puede compartir tal cual.</li>
|
|
</ol>
|
|
</details>
|
|
|
|
<div id="kb"></div>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
Kanban.montar(document.getElementById('kb'), {
|
|
filtros: true,
|
|
vistas: true,
|
|
botonNuevoEn: document.getElementById('acciones-kb'),
|
|
onCargado: (tareas, meta) => {
|
|
const abiertas = tareas.filter(t => t.estado !== 'hecho').length;
|
|
const venc = tareas.filter(t => t.vencida).length;
|
|
const bloq = tareas.filter(t => t.estado === 'bloqueado').length;
|
|
const n = (k, uno, varios) => k + ' ' + (k === 1 ? uno : varios);
|
|
document.getElementById('meta').textContent = [n(abiertas, 'abierto', 'abiertos'), n(bloq, 'bloqueado', 'bloqueados'), n(venc, 'vencido', 'vencidos')].join(' · ')
|
|
+ ' · al día a las ' + new Date().toLocaleTimeString('es-MX', { hour: '2-digit', minute: '2-digit', hour12: false })
|
|
+ (meta.user ? ' · ' + meta.user + (meta.admin ? ' (admin)' : '') : '');
|
|
}
|
|
});
|
|
})();
|
|
</script>
|