Archive: System v4 - Estado al 2024-12-24

This commit is contained in:
ARCHITECT
2025-12-24 17:28:34 +00:00
parent a92d41c846
commit 1b392803fd
81 changed files with 24560 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
# MIND LINK
![Estado](https://img.shields.io/badge/Estado-ARCHIVADO-red)
> **ARCHIVADO:** Este proyecto esta temporalmente pausado. Se retomara despues de completar el pipeline principal (FASE 4 del plan de implementacion).
## Concepto Original
Interfaz para conectar ideas y conceptos. Visualizacion de relaciones entre elementos.
## Funciones Planificadas
- Conexion de conceptos
- Grafos de conocimiento
- Navegacion visual
- Busqueda semantica
## Contenido Existente
```
mind-link/
├── src/
│ └── mindlink-v11.jsx # Prototipo React (incompleto)
└── docs/
├── MINDLINK-DOCUMENTACION.md
└── interfaz_mindlink v0.md
```
## Dependencias para Retomar
- Pipeline completo funcionando (CLARA, MASON, FELDMAN)
- Sistema de embeddings (GRACE) operativo
- Base de datos de grafos o PostgreSQL con extensiones
## Prioridad
BAJA - Se implementara despues de las fases 0-4 del plan de implementacion.
---
*Archivado: 2025-12-24*
*Ver: tzzr/system-plan para el plan completo*

View File

@@ -0,0 +1,253 @@
# MindLink v11 - Documentación
## Descripción General
MindLink es una interfaz de comunicación visual tipo mindmap/linktree para entregar documentos a clientes. Presenta nodos principales (categorías) con subnodos desplegables (documentos) conectados por líneas animadas.
---
## Estructura de Datos
### Configuración General
| Campo | Tipo | Ejemplo | Descripción |
|-------|------|---------|-------------|
| `titulo` | Texto | "Proyecto Demo HST" | Título principal de la página |
| `mostrar_titulo` | Booleano | true | Mostrar/ocultar el título |
| `colores` | Texto | "#FF6B35, #E5A000, #06D6A0" | Colores en hexadecimal separados por comas |
| `fuente` | Texto | "Inter" | Nombre de la fuente tipográfica |
### Fuentes Disponibles
| Valor | Descripción |
|-------|-------------|
| `Inter` | Moderna, muy legible (recomendada) |
| `Roboto` | Google, neutra |
| `Open Sans` | Google, amigable |
| `Montserrat` | Geométrica, elegante |
| `Lato` | Equilibrada, profesional |
| `SF Pro Display` | Apple, premium |
| `system` | Fuente nativa del sistema |
---
### Nodos (Categorías)
| Campo | Tipo | Ejemplo | Descripción |
|-------|------|---------|-------------|
| `id` | Texto | "n1" | Identificador único |
| `titulo` | Texto | "Arquitectura" | Nombre de la categoría |
| `imagen` | URL | "https://..." | Imagen cuadrada (se muestra 120×120px) |
| `subnodos` | Array | [...] | Lista de documentos |
### Subnodos (Documentos)
| Campo | Tipo | Ejemplo | Descripción |
|-------|------|---------|-------------|
| `id` | Texto | "s1" | Identificador único |
| `titulo` | Texto | "Plano General" | Nombre del documento |
| `imagen` | URL | "https://..." | Miniatura 16:9 (se muestra 180×101px) |
| `tiene_preview` | Booleano | true | Icono ojo (esquina superior derecha) |
| `tiene_descarga` | Booleano | true | Icono descarga (esquina inferior izquierda) |
| `tiene_enlace` | Booleano | true | Icono enlace (esquina inferior derecha) |
| `tiene_historial` | Booleano | false | Icono reloj (esquina superior izquierda) |
---
## Iconos de Acción
Los iconos se posicionan en las **4 esquinas** del subnodo para facilitar el uso en móviles:
```
┌─────────────────────┐
│ 🕐 👁 │ 🕐 = historial (tiene_historial)
│ │ 👁 = preview (tiene_preview)
│ │
│ ⬇ 🔗 │ ⬇ = descarga (tiene_descarga)
└─────────────────────┘ 🔗 = enlace (tiene_enlace)
```
**Estilo visual:**
- Fondo: negro semi-transparente `rgba(0,0,0,0.5)`
- Icono: blanco
- Tamaño: 26×26px
- Radio: 4px
- Opacidad: 50% (aumenta al hacer hover)
---
## Especificaciones Visuales
### Dimensiones
| Elemento | Valor | Notas |
|----------|-------|-------|
| Nodo principal | 120×120 px | Cuadrado |
| Subnodo | 180×101 px | Ratio 16:9 |
| Radio esquinas nodo | 20px | |
| Radio esquinas subnodo | 15px | |
| Grosor líneas/bordes | 3px | |
| Gap entre subnodos | 20px | Vertical |
| Gap entre grupos | 50px | Vertical |
| Gap nodo a subnodo | 70px | Horizontal |
### Tipografía
| Elemento | Tamaño | Peso | Color |
|----------|--------|------|-------|
| Título página | 32px | 600 | #1a1a1a |
| Título nodo | 18px | 500 | Color del nodo |
| Título subnodo | 16px | 500 | Color del nodo |
### Colores por Defecto
```
#FF6B35 - Naranja (nodo 1)
#E5A000 - Amarillo (nodo 2)
#06D6A0 - Verde (nodo 3)
#0891B2 - Cyan (nodo 4)
#3B82F6 - Azul (nodo 5)
#8B5CF6 - Violeta (nodo 6)
#EC4899 - Rosa (nodo 7)
```
Los colores rotan automáticamente: nodo 8 usa color 1, etc.
### Fondo de Fallback
Cuando una imagen no carga, se muestra fondo gris `#ccc`. Esto evita espacios en blanco y texto fantasma.
---
## Animaciones
| Elemento | Duración | Función | Delay |
|----------|----------|---------|-------|
| Movimiento vertical del nodo | 400ms | ease-out | - |
| Revelado de líneas | 450ms | linear | 80ms |
| Aparición subnodos | instantánea | - | 30ms |
### Secuencia al Expandir
1. El nodo se desplaza verticalmente para centrarse con sus subnodos
2. Las líneas se revelan con efecto de máscara deslizante
3. Los subnodos aparecen instantáneamente
### Secuencia al Colapsar
1. Las líneas desaparecen
2. Los subnodos se ocultan
3. El nodo vuelve a su posición
---
## Centrado Automático
El contenedor principal se centra horizontalmente con flexbox:
- **Con subnodos expandidos**: Ancho = nodo + gap + subnodo (~400px)
- **Todo colapsado**: Ancho = solo nodos (~180px)
El ancho cambia con transición suave (400ms).
---
## Integración con NocoDB
### Estructura de Tablas Recomendada
**Tabla: `proyectos`**
```
id | titulo | mostrar_titulo | colores | fuente
```
**Tabla: `nodos`**
```
id | proyecto_id | titulo | imagen | orden
```
**Tabla: `subnodos`**
```
id | nodo_id | titulo | imagen | tiene_preview | tiene_descarga | tiene_enlace | tiene_historial | orden
```
### Campo de Imagen
Usar campo tipo **Attachment** de NocoDB. La URL del archivo se usa directamente.
Para optimizar imágenes automáticamente, considerar:
- **Cloudinary**: `https://res.cloudinary.com/cuenta/image/upload/w_180,h_101,c_fill/imagen.jpg`
- **Redimensionado manual** antes de subir
### Tamaños de Imagen Recomendados
| Tipo | Subir | Se muestra como |
|------|-------|-----------------|
| Nodo | 240×240 px | 120×120 px |
| Subnodo | 360×202 px | 180×101 px |
Subir al doble para pantallas retina.
---
## Ejemplo JSON Completo
```json
{
"titulo": "Proyecto Cliente X",
"mostrar_titulo": true,
"colores": "#FF6B35, #06D6A0, #3B82F6",
"fuente": "Montserrat",
"nodos": [
{
"id": "n1",
"titulo": "Planos",
"imagen": "https://ejemplo.com/planos-thumb.jpg",
"subnodos": [
{
"id": "s1",
"titulo": "Planta Baja",
"imagen": "https://ejemplo.com/planta-baja.jpg",
"tiene_preview": true,
"tiene_descarga": true,
"tiene_enlace": false,
"tiene_historial": true
},
{
"id": "s2",
"titulo": "Planta Alta",
"imagen": "https://ejemplo.com/planta-alta.jpg",
"tiene_preview": true,
"tiene_descarga": true,
"tiene_enlace": true,
"tiene_historial": false
}
]
}
]
}
```
---
## Pendiente de Implementar
- [ ] Conexión real con API de NocoDB
- [ ] Sistema de autenticación con PIN
- [ ] Funcionalidad real de iconos:
- [ ] Preview: abrir modal con documento
- [ ] Descarga: descargar archivo
- [ ] Enlace: copiar URL al portapapeles
- [ ] Historial: mostrar versiones anteriores
- [ ] Responsive móvil (adaptar a pantallas pequeñas)
- [ ] Integración en aplicación empresarial
---
## Historial de Versiones
| Versión | Cambios principales |
|---------|---------------------|
| v11 | Colores/fuentes configurables, centrado mejorado, iconos en 4 esquinas, fix texto duplicado |
| v10 | Imágenes base64 incrustadas (demo) |
| v9 | Esquinas redondeadas 20px/15px, iconos 50% opacidad |
| v8 | Subnodos aparecen instantáneamente |
| v7-v1 | Iteraciones de diseño y animación |

View File

@@ -0,0 +1,86 @@
# Resumen de la conversación sobre la interfaz MindMap
A continuación se recoge un resumen estructurado de todos los elementos definidos para la interfaz tipo MindMap:
## 1. Acceso e Identificación
- El usuario accede mediante un enlace que actúa como llave pública.
- Se muestra un diálogo inicial simple con:
- Imagen de referencia (desde RT / Airtable).
- Imagen de fondo (también desde RT).
- Título (desde RT).
- Fuente de red.
- Primera vez: el sistema solicita un PIN.
- El PIN se guarda en la tabla.
- Si se olvida: no hay recuperación; debe solicitarse el borrado para reconfigurarlo.
## 2. Estructura General del Interfaz
- Funciona como un LinkTree avanzado.
- Representación equivalente a un mindmap.
- El nodo principal es implícito (no mostrado).
- Se muestran nodos principales en columna.
- Al pulsar un nodo, se realiza un zoom-out suave y se despliegan los subnodos.
## 3. Diseño de Nodos y Subnodos
- Cada nodo/subnodo muestra:
- Imagen (nodos cuadrados; subnodos rectangulares 16:9 con esquinas redondeadas).
- Título situado **debajo** de la imagen (configuración por defecto).
- Espacio configurable para fuente tipográfica.
- Fondo del área de despliegue configurable mediante imagen almacenada en RT.
## 4. Interacciones (Iconos en las esquinas)
Cada subnodo incluye interacciones en las esquinas de la imagen:
- **Esquina superior derecha**: icono de ojo → previsualización (JPG, PDF, etc.).
- **Esquina inferior izquierda**: icono de descarga.
- **Esquina inferior derecha**: icono de eslabones → copiar enlace al portapapeles.
- **Esquina superior izquierda**: reservada para futuras interacciones.
- Los iconos:
- Son estáticos (sin animación).
- Solo aparecen si la funcionalidad existe en ese nodo.
## 5. Ramas y Animaciones
- Las ramas funcionan como líneas que subrayan el título de cada nodo.
- De la línea subrayada del nodo principal salen curvas NURBS animadas.
- Las curvas:
- Salen del subrayado del nodo principal.
- Bajan de manera orgánica.
- Llegan al subrayado del subnodo.
- No se conectan al centro del recuadro (evitamos comportamiento mecánico).
- Las animaciones deben sentirse de calidad, como en un buen mindmap.
---
# Transcripción literal de la conversación
(Nota: Se incluye solo la parte relevante a la interfaz MindMap según lo solicitado.)
Usuario: Vamos a hablar de interfaces. Quiero hablar de ello a nivel genérico [...]
Asistente: ¡Entendido! Vamos a mantenerlo entonces en un nivel general [...]
Usuario: Vamos a empezar por el primer interfaz. El primer interfaz es para hacer algo parecido a un LinkTree [...]
Asistente: Sí, te sigo perfectamente. Básicamente estás describiendo una interfaz tipo link tree [...]
Usuario: Seguimos con la definición. Dentro de estas imágenes rectangulares de los subnodos veremos arriba a la derecha [...]
Asistente: Perfecto, lo tenemos entonces bastante definido [...]
Usuario: Igual que tenemos que guardarnos la posibilidad de que no haya ningún tipo de interacción [...]
Asistente: ¡Claro! Entonces dejamos el diseño preparado para la posibilidad de futuras interacciones [...]
Usuario: Sí, sí, de hecho ya se me está ocurriendo otra interacción [...]
Asistente: ¡Perfecto, me encanta la idea! [...]
Usuario: Respecto a esto, no quiero animaciones respecto a estos iconitos [...]
Asistente: ¡Entendido! Entonces lo ajustamos así [...]
Usuario: No acabo de tener todo claro si quiero que los títulos estén en la parte inferior [...]
Asistente: ¡Genial! Entonces lo dejamos así [...]
Usuario: Es importante subrayar que las líneas se unen con otras líneas [...]
Asistente: Entendido, queda clarísimo [...]
Usuario: No, con esto tenemos la interfaz de MindMap perfectamente clara [...]
Asistente: Perfecto, entonces dejamos esta interfaz bien clara [...]
Usuario: Vale, ahora mismo puedo cerrar la conversación sin que haya pérdida [...]
Asistente: Sí, no te preocupes [...]

View File

@@ -0,0 +1,674 @@
# INTERFAZ MML
## Mindmap Linking - Capa de Interfaz
---
## 1. Concepto Visual
### 1.1 Referencia
Estética tipo **MindNode**:
- Diseño limpio y minimalista
- Líneas curvas orgánicas (bezier)
- Colores vibrantes por rama
- Tipografía sans-serif moderna
### 1.2 Principios
| Principio | Aplicación |
|-----------|------------|
| Simplicidad | Sin elementos decorativos innecesarios |
| Jerarquía | Nodos nivel 1 destacan, subnodos secundarios |
| Color | Cada rama tiene identidad cromática |
| Espacio | Generoso, respira |
---
## 2. Estructura Visual
### 2.1 Elementos
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ [Header - Título del proyecto (opcional)] │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ NODOS NIVEL 1 LÍNEAS SUBNODOS │
│ (izquierda) (curvas) (derecha) │
│ │
│ Texto subrayado ────────────────► Imagen 16:9 │
│ con color + título │
│ + botones │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 2.2 Layout Desktop (>768px)
```
╭─────────────────────────────────────────────────────────────────╮
│ Proyecto Demo HST │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ╭─────────────╮ │
│ ╭─────│ IMAGEN │ │
│ Arquitectura ───────────────┤ ╰─────────────╯ │
│ │ plano.pdf │
│ │ │
│ │ ╭─────────────╮ │
│ ╰─────│ IMAGEN │ │
│ ╰─────────────╯ │
│ secciones.pdf │
│ │
│ ╭─────────────╮ │
│ ╭─────│ IMAGEN │ │
│ Renders ────────────────────┤ ╰─────────────╯ │
│ │ exterior.jpg │
│ │ │
│ ╰─────╭─────────────╮ │
│ │ IMAGEN │ │
│ ╰─────────────╯ │
│ interior.jpg │
│ │
╰─────────────────────────────────────────────────────────────────╯
```
### 2.3 Layout Mobile (<768px)
```
╭──────────────────────╮
│ Proyecto Demo │
├──────────────────────┤
│ │
│ Arquitectura │
│ │ │
│ ┌────┴────┐ │
│ ▼ ▼ │
│ ╭─────╮ ╭─────╮ │
│ │ IMG │ │ IMG │ │
│ ╰─────╯ ╰─────╯ │
│ plano secciones │
│ │
│ Renders │
│ │ │
│ ┌────┴────┐ │
│ ▼ ▼ │
│ ╭─────╮ ╭─────╮ │
│ │ IMG │ │ IMG │ │
│ ╰─────╯ ╰─────╯ │
│ exterior interior │
│ │
│ ↕ scroll vertical │
╰──────────────────────╯
```
---
## 3. Componentes
### 3.1 Header (opcional)
```html
<header id="header">Proyecto Demo HST</header>
```
```css
#header {
font-size: 24px;
font-weight: 600;
color: #333;
margin-bottom: 40px;
padding-left: 20px;
}
```
**Visibilidad:** Controlada por `mostrar_titulo` en JSON.
### 3.2 Nodo Nivel 1
```html
<div class="level1-node" data-color="orange" data-node-id="n1">
<span class="node-text">Arquitectura</span>
</div>
```
```css
.level1-node {
position: relative;
cursor: pointer;
padding: 8px 0;
}
.level1-node .node-text {
font-size: 18px;
font-weight: 500;
color: #333;
border-bottom: 3px solid currentColor;
padding-bottom: 4px;
display: inline-block;
}
/* Colores por data-color */
.level1-node[data-color="orange"] .node-text {
color: #FF6B35;
border-color: #FF6B35;
}
```
**Características:**
- Solo texto, sin caja ni fondo
- Subrayado del color de la rama
- Click para expandir/contraer
### 3.3 Subnodo
```html
<div class="subnode" data-color="orange" data-parent-id="n1">
<div class="subnode-image-container">
<img src="http://72.62.2.84:8090/arc_arquitectura.png" alt="plano.pdf">
<a href="#" download class="btn-download"></a>
<a href="#" target="_blank" class="btn-preview">👁</a>
</div>
<div class="subnode-title">plano.pdf</div>
</div>
```
```css
.subnode {
position: relative;
width: 200px;
}
.subnode-image-container {
position: relative;
width: 100%;
aspect-ratio: 16/9;
border-radius: 8px;
overflow: hidden;
border: 3px solid #ddd;
}
.subnode-image-container img {
width: 100%;
height: 100%;
object-fit: cover;
}
.subnode-title {
font-size: 14px;
color: #555;
margin-top: 8px;
text-align: center;
}
```
**Características:**
- Imagen 16:9 con bordes redondeados
- Borde del color de la rama padre
- Título debajo, centrado
- Botones siempre visibles
### 3.4 Botones de Acción
```css
.btn-download, .btn-preview {
position: absolute;
width: 28px;
height: 28px;
border-radius: 6px;
background: rgba(0,0,0,0.6);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
cursor: pointer;
text-decoration: none;
}
.btn-download {
bottom: 6px;
left: 6px;
}
.btn-preview {
top: 6px;
right: 6px;
}
.btn-download:hover, .btn-preview:hover {
background: rgba(0,0,0,0.8);
}
```
| Botón | Icono | Posición | Visible |
|-------|-------|----------|---------|
| Descarga | ↓ | Esquina inferior izquierda | Siempre |
| Preview | 👁 | Esquina superior derecha | Solo PDF/imágenes |
**Archivos con preview:**
- `.pdf`
- `.png`
- `.jpg` / `.jpeg`
- `.gif`
- `.webp`
### 3.5 Líneas SVG
```html
<svg id="lines-svg">
<path d="M 150,50 C 200,50 200,120 250,120" stroke="#FF6B35" />
</svg>
```
```css
#lines-svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
overflow: visible;
}
#lines-svg path {
fill: none;
stroke-width: 3;
stroke-linecap: round;
}
```
**Curva Bezier:**
```
M x1,y1 C cx1,cy1 cx2,cy2 x2,y2
Donde:
- (x1,y1) = Punto inicio (borde derecho del nodo nivel 1)
- (cx1,cy1) = Primer punto de control
- (cx2,cy2) = Segundo punto de control
- (x2,y2) = Punto final (borde izquierdo del subnodo)
```
---
## 4. Paleta de Colores
### 4.1 Colores de ramas
| Nombre | Hex | Muestra |
|--------|-----|---------|
| Orange | #FF6B35 | 🟠 |
| Yellow | #E5A000 | 🟡 |
| Green | #06D6A0 | 🟢 |
| Cyan | #0891B2 | 🔵 |
| Blue | #3B82F6 | 🔷 |
| Purple | #8B5CF6 | 🟣 |
| Pink | #EC4899 | 🩷 |
### 4.2 Colores base
| Uso | Hex |
|-----|-----|
| Fondo | #f5f5f7 |
| Texto principal | #333333 |
| Texto secundario | #555555 |
| Borde default | #dddddd |
### 4.3 Asignación automática
```javascript
const COLORS = ['orange', 'yellow', 'green', 'cyan', 'blue', 'purple', 'pink'];
// Cada nodo nivel 1 recibe un color según su índice
const color = COLORS[index % COLORS.length];
```
---
## 5. Tipografía
### 5.1 Familia
```css
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
```
### 5.2 Tamaños
| Elemento | Tamaño | Peso |
|----------|--------|------|
| Header | 24px | 600 |
| Nodo nivel 1 | 18px | 500 |
| Título subnodo | 14px | 400 |
---
## 6. Interactividad
### 6.1 Click en nodo nivel 1
```javascript
node.addEventListener('click', () => {
const nodeId = node.dataset.nodeId;
const subnodes = document.querySelectorAll(`[data-parent-id="${nodeId}"]`);
subnodes.forEach(sub => {
sub.classList.toggle('hidden');
});
// Redibujar líneas
drawLines();
});
```
**Comportamiento:**
- Toggle: muestra/oculta subnodos
- Recalcula posiciones de líneas SVG
- Animación suave (opcional)
### 6.2 Cálculo de líneas
```javascript
function drawLines() {
const svg = document.getElementById('lines-svg');
svg.innerHTML = '';
const containerRect = document.getElementById('mindmap-container').getBoundingClientRect();
document.querySelectorAll('.level1-node').forEach(node => {
const nodeId = node.dataset.nodeId;
const color = node.dataset.color;
const nodeRect = node.getBoundingClientRect();
// Punto inicio: borde derecho del subrayado
const startX = nodeRect.right - containerRect.left;
const startY = nodeRect.bottom - containerRect.top - 2;
// Encontrar subnodos visibles
const subnodes = document.querySelectorAll(
`.subnode[data-parent-id="${nodeId}"]:not(.hidden)`
);
subnodes.forEach(subnode => {
const subRect = subnode.querySelector('.subnode-image-container')
.getBoundingClientRect();
// Punto final: borde izquierdo del subnodo
const endX = subRect.left - containerRect.left;
const endY = subRect.top + subRect.height/2 - containerRect.top;
// Puntos de control para curva suave
const midX = startX + (endX - startX) / 2;
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d',
`M ${startX},${startY} C ${midX},${startY} ${midX},${endY} ${endX},${endY}`
);
path.setAttribute('stroke', getColorValue(color));
svg.appendChild(path);
});
});
}
```
### 6.3 Responsive
```javascript
// Redibujar en resize
window.addEventListener('resize', drawLines);
// Detectar mobile
const isMobile = window.innerWidth < 768;
```
---
## 7. Estructura JSON
### 7.1 Formato completo
```json
{
"slug": "proyecto-demo",
"titulo": "Proyecto Demo HST",
"mostrar_titulo": true,
"tema": "light",
"nodos": [
{
"id": "n1",
"titulo": "Arquitectura",
"color": "#FF6B35",
"subnodos": [
{
"titulo": "plano_general.pdf",
"icono_hst": "arc_arquitectura",
"url_archivo": "https://git.tzzr.pro/.../plano.pdf",
"url_corta": "https://tzzr.pro/abc123"
},
{
"titulo": "secciones.pdf",
"icono_hst": "pln_plano",
"url_archivo": "https://git.tzzr.pro/.../secciones.pdf",
"url_corta": "https://tzzr.pro/def456"
}
]
},
{
"id": "n2",
"titulo": "Renders",
"color": "#E5A000",
"subnodos": [
{
"titulo": "exterior.jpg",
"icono_hst": "ren_render",
"url_archivo": "https://git.tzzr.pro/.../exterior.jpg"
}
]
}
]
}
```
### 7.2 Campos
| Campo | Tipo | Requerido | Descripción |
|-------|------|-----------|-------------|
| slug | string | ✅ | Identificador URL |
| titulo | string | ✅ | Nombre del proyecto |
| mostrar_titulo | boolean | ❌ | Si mostrar header (default: true) |
| tema | string | ❌ | "light" o "dark" |
| nodos | array | ✅ | Lista de nodos nivel 1 |
**Nodo:**
| Campo | Tipo | Requerido | Descripción |
|-------|------|-----------|-------------|
| id | string | ✅ | Identificador único |
| titulo | string | ✅ | Nombre de la carpeta |
| color | string | ❌ | Color hex (si no, se asigna auto) |
| subnodos | array | ✅ | Lista de subnodos |
**Subnodo:**
| Campo | Tipo | Requerido | Descripción |
|-------|------|-----------|-------------|
| titulo | string | ✅ | Nombre del archivo |
| icono_hst | string | ✅ | Referencia imagen HST |
| url_archivo | string | ✅ | URL de descarga |
| url_corta | string | ❌ | URL acortada |
---
## 8. Código Base
### 8.1 index.html
```html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MML - Mindmap Linking</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div id="app">
<header id="header"></header>
<div id="mindmap-container">
<svg id="lines-svg"></svg>
<div id="nodes-container"></div>
</div>
</div>
<script src="js/app.js" type="module"></script>
</body>
</html>
```
### 8.2 Variables CSS
```css
:root {
--bg-primary: #f5f5f7;
--text-primary: #333;
--text-secondary: #555;
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--line-width: 3px;
--image-radius: 8px;
--transition-speed: 0.3s;
/* Colores de ramas */
--color-orange: #FF6B35;
--color-yellow: #E5A000;
--color-green: #06D6A0;
--color-cyan: #0891B2;
--color-blue: #3B82F6;
--color-purple: #8B5CF6;
--color-pink: #EC4899;
}
```
---
## 9. Imágenes HST
### 9.1 URL Base
```javascript
const HST_BASE = 'http://72.62.2.84:8090/';
```
### 9.2 Construcción de URL
```javascript
function getImageUrl(icono_hst) {
if (!icono_hst) return null;
return `${HST_BASE}${icono_hst}.png`;
}
```
### 9.3 Formato de nombres
```
{codigo}_{nombre}.png
Ejemplos:
- arc_arquitectura.png
- pln_plano.png
- doc_documento.png
- fto_foto.png
```
### 9.4 Fallback si imagen no existe
```javascript
img.onerror = function() {
this.src = '/assets/placeholder.png';
// O ocultar el contenedor de imagen
this.parentElement.style.display = 'none';
};
```
---
## 10. Tests de Interfaz
### 10.1 Checklist visual
| Test | Criterio |
|------|----------|
| Carga | Página muestra contenido en <2s |
| Header | Título visible si `mostrar_titulo: true` |
| Nodos | Todos los nodos nivel 1 visibles |
| Imágenes | Ninguna imagen rota |
| Líneas | Curvas conectan correctamente |
| Click | Expandir/contraer funciona |
| Responsive | Layout adapta a mobile |
### 10.2 Tests Puppeteer
```javascript
// Test de imágenes
const images = await page.$$eval('img', imgs =>
imgs.map(img => ({
src: img.src,
loaded: img.complete && img.naturalWidth > 0
}))
);
const broken = images.filter(i => !i.loaded);
if (broken.length > 0) {
errors.push(`Imágenes rotas: ${broken.map(i => i.src).join(', ')}`);
}
// Test de líneas
const paths = await page.$$('svg path');
if (paths.length === 0) {
errors.push('No hay curvas SVG');
}
// Test de interactividad
await page.click('.level1-node');
await page.waitForTimeout(300);
const visibleSubnodes = await page.$$('.subnode:not(.hidden)');
```
---
## 11. Accesibilidad
### 11.1 Básico
```html
<!-- Alt text en imágenes -->
<img src="..." alt="plano_general.pdf">
<!-- Roles semánticos -->
<nav role="navigation">
<main role="main">
<!-- Focus visible -->
.level1-node:focus {
outline: 2px solid var(--color-blue);
}
```
### 11.2 Navegación por teclado
```javascript
// Enter/Space para expandir
node.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
node.click();
}
});
// Tab order
node.setAttribute('tabindex', '0');
```
---
**Versión:** 1.0
**Fecha:** 2025-12-11