Archive: System v4 - Estado al 2024-12-24
This commit is contained in:
42
v4-archive/mind-link/README.md
Normal file
42
v4-archive/mind-link/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# MIND LINK
|
||||
|
||||

|
||||
|
||||
> **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*
|
||||
253
v4-archive/mind-link/docs/MINDLINK-DOCUMENTACION.md
Normal file
253
v4-archive/mind-link/docs/MINDLINK-DOCUMENTACION.md
Normal 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 |
|
||||
86
v4-archive/mind-link/docs/interfaz_mindlink v0 bis.md
Normal file
86
v4-archive/mind-link/docs/interfaz_mindlink v0 bis.md
Normal 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 [...]
|
||||
|
||||
674
v4-archive/mind-link/docs/interfaz_mindlink v0.md
Normal file
674
v4-archive/mind-link/docs/interfaz_mindlink v0.md
Normal 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
|
||||
Reference in New Issue
Block a user