- Svelte 53.3%
- TypeScript 43.8%
- CSS 1.7%
- Nix 0.7%
- HTML 0.4%
- Other 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| docs | ||
| public | ||
| scripts | ||
| src | ||
| .envrc | ||
| .gitignore | ||
| bun.lock | ||
| flake.lock | ||
| flake.nix | ||
| index.html | ||
| package.json | ||
| README.md | ||
| svelte.config.js | ||
| tsconfig.json | ||
| vite.config.ts | ||
| title |
|---|
| Línea de tiempo de entregables |
Aplicación web que muestra los entregables de un semestre en carriles apilados, uno por materia, sobre un eje temporal desplazable, y resalta automáticamente los períodos de alta carga.
Construida con Vite, Svelte 5 y TypeScript, sin librerías de gráficos. Los datos se sirven como
JSON estático desde public/data/ y se cargan en runtime: añadir un semestre no requiere recompilar.
Puesta en marcha
El flake provee Bun y miniserve, de modo que no hace falta instalar nada en el sistema.
nix develop
bun install
bun dev
Sin Nix basta con Bun 1.2 o superior.
Scripts disponibles:
bun dev # servidor de desarrollo
bun run build # svelte-check + bundle de producción en dist/
bun run preview # sirve dist/
bun run check # sólo verificación de tipos
bun run test # tests de la detección de carga
bun run migrate # regenera public/data/ desde el data.json original
Despliegue
bun run build produce en dist/ un sitio completamente estático: HTML, un bundle JS, una hoja de
estilos y la copia de public/data/. No hay servidor de aplicación ni API detrás, así que publicar
consiste en copiar esa carpeta a cualquier servidor de archivos.
El bundle es reubicable. vite.config.ts fija base: "./" y los datos se piden con rutas relativas,
de modo que el mismo dist/ sirve tanto en la raíz de un dominio como en un subdirectorio, sin
reconstruir por destino. La única condición es que la URL del subdirectorio termine en barra, para que
el navegador resuelva data/index.json dentro de él y no un nivel más arriba.
dist/ no se versiona: se regenera en cada despliegue. Un contenedor de dos etapas basta para
construirlo y servirlo sin dejar la cadena de herramientas en la imagen final.
FROM oven/bun:1-alpine AS build
WORKDIR /src
COPY . .
RUN bun install --frozen-lockfile && bun run build
FROM nginx:alpine
COPY --from=build /src/dist /usr/share/nginx/html
Antes de publicar conviene probar el bundle tal como quedará servido, con bun run preview o con
miniserve --index index.html dist. Para reproducir una publicación en subdirectorio, copiarlo bajo
una carpeta y servir el nivel superior:
mkdir -p /tmp/pub/timeline && cp -r dist/* /tmp/pub/timeline/ && miniserve /tmp/pub
Uso
La barra superior controla toda la vista y su estado se guarda en localStorage; el semestre, el
zoom, el umbral y la ventana viajan además en la query string, así que un enlace reproduce la
vista exacta.
Eje temporal — el lienzo mide días × px/día y nunca se comprime al ancho de la pantalla: se
recorre con scroll horizontal. La rejilla marca los meses en la banda superior y las semanas
naturales (S1, S2, …) en la inferior. La línea punteada señala el día de hoy y el botón
Ir a hoy centra la vista en él.
Carriles — cada materia ocupa una fila con su color. El fondo son las semanas del sílabo: al pasar el cursor muestran el temario y, cuando existe, los temas de laboratorio. Los entregables que se solapan se apilan en sub-filas, de modo que ninguno queda oculto.
Entregables — un hito puntual se dibuja como marcador y un entregable con rango como barra de
date a end. La forma distingue el tipo (rombo para exámenes y parciales, cuadrado para talleres
y defensas, círculo para el resto) porque el color queda reservado a la materia. Un contorno
punteado indica una fecha aproximada, inferida del número de semana. El lienzo no lleva texto: el
título y el detalle aparecen al pasar el cursor y, al hacer clic, en el panel derecho junto al
temario de esa semana.
Avance — cada entregable puede marcarse como hecho, y una vez llega la calificación se le asigna una nota. Lo entregado se apaga a gris; una nota A, B o C convierte el marcador en oro, plata o bronce, mientras que D y F quedan grises y muestran su letra en el panel. El resumen de la barra superior lleva la cuenta de entregas y de cada medalla sobre lo que está visible.
Con un entregable seleccionado el teclado basta: d alterna hecho, a b c x f asignan la
nota (x es la D, porque d ya está tomada), ← y → saltan al entregable anterior o siguiente de
la misma materia y Escape cierra el panel.
Alta carga — las cajas rojas cubren verticalmente todos los carriles sobre los rangos de fechas donde se acumulan los entregables. La etiqueta superior indica cuántos hay y abre la lista completa en el panel derecho.
Detección de alta carga
La carga de un día es la suma de los pesos de los entregables visibles desde una ventana centrada en él. Cada entregable cuenta una sola vez por ventana, así que un proyecto de tres semanas no se comporta como veinte entregas. Los días que alcanzan el umbral forman intervalos contiguos, y los intervalos cercanos se fusionan.
Los controles de la barra ajustan la métrica en vivo:
- Umbral — carga mínima para marcar un día. Por defecto 5.
- Ventana — radio en días de la ventana. Por defecto ±2.
- Fusionar — separación máxima entre intervalos que se unen en uno. Por defecto 1 día.
- Ponderar por tipo — usa el
weightdetypes.json(un parcial pesa 2, un deber 1) en lugar de contar 1 por entregable. - Rangos completos — un entregable con rango ocupa todos sus días en vez de sólo el de entrega.
- Ignorar lo hecho — lo ya entregado deja de pesar, de modo que las cajas miden carga pendiente. Apagarlo devuelve la carga planificada del semestre. Activo por defecto.
Los filtros de materia y de tipo se aplican antes de la detección: ocultar una materia recalcula los períodos con las restantes.
La implementación vive en src/lib/burst.ts como función pura y está cubierta por
src/lib/burst.test.ts.
Datos
Los archivos de public/data/ son la única fuente de entregables de la aplicación; el avance del
usuario es el único dato que ella produce y vive en el navegador. Para añadir un semestre nuevo
basta con dejar su JSON en esa carpeta y registrarlo en index.json. Los botones Exportar e
Importar de la barra superior mueven el avance entre navegadores como un archivo JSON. Reference el
formato de datos para ambos esquemas.