# DECK Frontend - Vite + TypeScript Frontend modular para visualización de tags semánticos TZZR (HST/FLG/ITM/LOC/PLY). ## Stack - **Vite** - Bundler con HMR - **TypeScript** - Tipado estático - **ES6 Modules** - import/export - **D3.js** - Lazy loading solo en GraphView ## Estructura ``` src/ ├── main.ts # Bootstrap y App principal ├── types/ # Interfaces TypeScript │ ├── tag.ts # Tag, Group, Library, ChildTag, RelatedTag │ ├── state.ts # AppState, ViewType, BaseType │ └── graph.ts # GraphNode, GraphEdge, EdgeType ├── config/ # Constantes │ ├── api.ts # API_BASE │ ├── categories.ts # CATS (colores por categoría) │ └── edges.ts # EDGE_COLORS ├── state/ # Store reactivo │ ├── store.ts # createStore() │ └── index.ts # Estado inicial ├── api/ # Fetch tipado │ ├── client.ts # apiClient(), apiClientSafe() │ ├── tags.ts # fetchTags, fetchHstTags, fetchChildren, fetchRelated │ ├── groups.ts # fetchGroups │ ├── libraries.ts # fetchLibraries, fetchLibraryMembers │ └── graph.ts # fetchGraphEdges, fetchTreeEdges ├── utils/ # Helpers puros │ ├── dom.ts # $, $$, createElement, delegateEvent │ ├── i18n.ts # getName, getImg, createNameMap, resolveGroupName │ ├── filters.ts # filterTags │ ├── clipboard.ts # copyToClipboard, copyMrf │ └── toast.ts # toast() ├── components/ # Componentes reutilizables │ ├── Component.ts # Clase base │ ├── Card/ │ ├── TagChip/ │ └── Toast/ ├── views/ # Vistas principales │ ├── View.ts # Clase base │ ├── GridView/ # Vista de tarjetas │ ├── TreeView/ # Vista de árbol agrupado │ ├── GraphView/ # Grafo D3 (lazy load) │ └── DetailPanel/ # Panel lateral de detalle ├── router/ # Hash routing │ └── index.ts # Router con parseHash/updateHash └── styles/ └── main.css # Estilos globales ``` ## Resolución de Nombres ### Prioridad de campos para mostrar nombres 1. `name_es` / `name_en` / `name_ch` (según idioma) 2. `alias` 3. `ref` 4. `mrf.slice(0, 8)` (fallback a hash truncado) ### Resolución de grupos (set_hst) El campo `set_hst` contiene el MRF de un tag HST que representa la categoría. Para resolver el nombre del grupo: 1. Se cargan siempre los tags de HST (`fetchHstTags`) 2. Se crea un mapa `mrf → nombre` con `createNameMap(hstTags, lang)` 3. Se resuelve el nombre con `resolveGroupName(set_hst, nameMap)` Esto permite que al ver cualquier base (flg, itm, loc, ply), los grupos muestren nombres legibles en lugar de hashes. ## API Endpoints | Endpoint | Descripción | |----------|-------------| | `GET /api/{base}` | Lista tags (hst, flg, itm, loc, ply) | | `GET /api/hst?select=...` | Tags HST para resolver nombres | | `POST /api/rpc/api_children` | Hijos de un tag | | `POST /api/rpc/api_related` | Tags relacionados | | `GET /api/graph_hst` | Relaciones del grafo | | `GET /api/tree_hst` | Jerarquías | | `GET /api/groups` | Grupos disponibles | | `GET /api/library_hst` | Bibliotecas | | `POST /api/rpc/library_members` | Miembros de biblioteca | ## Comandos ```bash # Desarrollo npm run dev # Build producción npm run build # Preview build npm run preview # Lint npm run lint ``` ## Despliegue ```bash # Build npm run build # Deploy a DECK scp -r dist/* root@72.62.1.113:/opt/hst/web/ ``` ## URLs - **DECK**: https://tzzrdeck.me - **HST**: https://hst.tzzrdeck.me - **API**: https://tzzrdeck.me/api/ ## Layout ``` ┌─────────────────────────────────────────────────────────────┐ │ TOPBAR: Logo | Lang | API | SEL | GET | Bases | Search | View │ ├─────────────────────────────────────────────────────────────┤ │ GROUPS BAR: Todos | Grupo1 | Grupo2 | ... │ ├────────┬────────────────────────────────────┬───────────────┤ │ │ │ │ │ LEFT │ CONTENT AREA │ DETAIL │ │ PANEL │ (Grid / Tree / Graph) │ PANEL │ │ │ │ │ │ Libs │ │ (slide-in) │ │ │ │ │ └────────┴────────────────────────────────────┴───────────────┘ ``` ## State ```typescript interface AppState { // Navegación base: 'hst' | 'flg' | 'itm' | 'loc' | 'ply'; lang: 'es' | 'en' | 'ch'; view: 'grid' | 'tree' | 'graph'; // Filtros search: string; group: string; // MRF del grupo o 'all' library: string; // MRF de biblioteca o 'all' libraryMembers: Set; // Selección selectionMode: boolean; selected: Set; selectedTag: Tag | null; // Datos tags: Tag[]; // Tags de la base actual hstTags: Tag[]; // Tags HST para resolver nombres de grupos groups: Group[]; libraries: Library[]; graphEdges: GraphEdge[]; treeEdges: TreeEdge[]; // Grafo graphFilters: { cats: Set, edges: Set }; graphSettings: { nodeSize, linkDist, showImg, showLbl }; } ``` ## Seguridad ### Lock Screen (PIN) El frontend incluye una pantalla de bloqueo con PIN de 4 dígitos. - **PIN actual**: `1451` - **Almacenamiento**: `sessionStorage` (persiste durante la sesión del navegador) - **Ubicación código**: `Lock` module en el HTML Para cambiar el PIN, editar `Lock.PIN` en `deck-v4.6.html`. ### Bloqueo de Buscadores - Meta tags `robots: noindex, nofollow` - `robots.txt` con `Disallow: /` ## Changelog ### 2026-01-18 - Añadida pantalla de bloqueo PIN (1451) - Añadido bloqueo de indexación para buscadores - Implementada clasificación de categorías data-driven via `hst_rules` - Fix: sidebar de graph ahora muestra solo categorías con datos ### 2026-01-13 - Migrado de vanilla JS a Vite + TypeScript - Añadido panel izquierdo de bibliotecas - Implementada resolución de nombres para grupos (set_hst → nombre) - Prioridad de nombres: name_es → alias → ref → hash - D3 lazy loading en GraphView - Layout de 3 paneles (left, center, detail)