Modularización de GKACHELE SaaS
This commit is contained in:
247
memoria/SISTEMA_BLOQUES_EDITABLES.md
Normal file
247
memoria/SISTEMA_BLOQUES_EDITABLES.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# 🧩 Sistema de Bloques Editables - GKACHELE™
|
||||
|
||||
**© 2025 GKACHELE™. Todos los derechos reservados.**
|
||||
|
||||
**Hash:** `gkachele-bloques-editables-20250115-001`
|
||||
|
||||
---
|
||||
|
||||
## 📋 OBJETIVO
|
||||
|
||||
Implementar sistema completo de bloques editables similar a WordPress Gutenberg:
|
||||
- ✅ Añadir/eliminar bloques (videos, imágenes, texto, redes sociales)
|
||||
- ✅ Mover bloques (drag & drop)
|
||||
- ✅ Edición inline (click con lápiz) + sidebar
|
||||
- ✅ Iconos de redes sociales automáticos
|
||||
- ✅ Mapa embed sin API key
|
||||
- ✅ Todo sincronizado en tiempo real
|
||||
|
||||
---
|
||||
|
||||
## 🎯 FUNCIONALIDADES REQUERIDAS
|
||||
|
||||
### 1. Añadir Bloques
|
||||
- Botón "➕ Añadir Bloque" en sidebar
|
||||
- Tipos: Video (YouTube/Vimeo), Imagen, Texto, Redes Sociales, Mapa
|
||||
- Cada bloque se añade al preview y al sidebar
|
||||
|
||||
### 2. Eliminar Bloques
|
||||
- Botón "🗑️" en cada bloque del preview
|
||||
- Confirmación antes de eliminar
|
||||
- Sincronización automática
|
||||
|
||||
### 3. Mover Bloques
|
||||
- Drag & drop usando HTML5 Drag API
|
||||
- Indicadores visuales al arrastrar
|
||||
- Guardado automático del orden
|
||||
|
||||
### 4. Redes Sociales con Iconos
|
||||
- Al añadir URL de red social, mostrar icono automático
|
||||
- Iconos: Facebook, Instagram, Twitter/X, WhatsApp, YouTube
|
||||
- Usar Font Awesome o SVG inline
|
||||
|
||||
### 5. Mapa Embed
|
||||
- Campo para URL de Google Maps (compartir → insertar mapa)
|
||||
- Renderizar iframe sin necesidad de API key
|
||||
- Validación de URL
|
||||
|
||||
### 6. Edición Híbrida
|
||||
- Click en elemento → editar inline (modal)
|
||||
- Cambios en sidebar → actualizar preview
|
||||
- Bidireccional siempre
|
||||
|
||||
---
|
||||
|
||||
## 🔧 IMPLEMENTACIÓN
|
||||
|
||||
### Estructura de Datos
|
||||
|
||||
```json
|
||||
{
|
||||
"blocks": [
|
||||
{
|
||||
"id": "block_1234567890",
|
||||
"type": "video",
|
||||
"content": {
|
||||
"url": "https://www.youtube.com/embed/...",
|
||||
"title": "Video Tutorial"
|
||||
},
|
||||
"order": 0
|
||||
},
|
||||
{
|
||||
"id": "block_1234567891",
|
||||
"type": "redes_sociales",
|
||||
"content": {
|
||||
"facebook": "https://facebook.com/...",
|
||||
"instagram": "https://instagram.com/..."
|
||||
},
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"id": "block_1234567892",
|
||||
"type": "mapa",
|
||||
"content": {
|
||||
"url": "https://www.google.com/maps/embed?pb=..."
|
||||
},
|
||||
"order": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Backend (app.py)
|
||||
|
||||
```python
|
||||
# Endpoint para añadir bloque
|
||||
@app.route('/api/customizer/add-block', methods=['POST'])
|
||||
def add_block():
|
||||
# Añadir nuevo bloque a content_json['blocks']
|
||||
pass
|
||||
|
||||
# Endpoint para eliminar bloque
|
||||
@app.route('/api/customizer/remove-block', methods=['POST'])
|
||||
def remove_block():
|
||||
# Eliminar bloque por ID
|
||||
pass
|
||||
|
||||
# Endpoint para reordenar bloques
|
||||
@app.route('/api/customizer/reorder-blocks', methods=['POST'])
|
||||
def reorder_blocks():
|
||||
# Actualizar orden de bloques
|
||||
pass
|
||||
```
|
||||
|
||||
### Frontend (customizer.html)
|
||||
|
||||
```javascript
|
||||
// Añadir bloque
|
||||
function addBlock(type) {
|
||||
const blockId = 'block_' + Date.now();
|
||||
const newBlock = {
|
||||
id: blockId,
|
||||
type: type,
|
||||
content: getDefaultContentForType(type),
|
||||
order: blocks.length
|
||||
};
|
||||
// Añadir a preview y sidebar
|
||||
renderBlock(newBlock);
|
||||
saveBlocks();
|
||||
}
|
||||
|
||||
// Eliminar bloque
|
||||
function removeBlock(blockId) {
|
||||
if (confirm('¿Eliminar este bloque?')) {
|
||||
// Remover del DOM y del array
|
||||
saveBlocks();
|
||||
}
|
||||
}
|
||||
|
||||
// Drag & Drop
|
||||
function initDragDrop() {
|
||||
document.querySelectorAll('.gk-block').forEach(block => {
|
||||
block.draggable = true;
|
||||
block.addEventListener('dragstart', handleDragStart);
|
||||
block.addEventListener('dragover', handleDragOver);
|
||||
block.addEventListener('drop', handleDrop);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Template (template.html)
|
||||
|
||||
```html
|
||||
<!-- Renderizar bloques dinámicamente -->
|
||||
{% if blocks %}
|
||||
{% for block in blocks|sort(attribute='order') %}
|
||||
{% if block.type == 'video' %}
|
||||
<div class="gk-block" data-block-id="{{ block.id }}" draggable="true">
|
||||
<button class="gk-block-delete" onclick="removeBlock('{{ block.id }}')">🗑️</button>
|
||||
<iframe src="{{ block.content.url }}" frameborder="0"></iframe>
|
||||
</div>
|
||||
{% elif block.type == 'redes_sociales' %}
|
||||
<div class="gk-block" data-block-id="{{ block.id }}" draggable="true">
|
||||
<button class="gk-block-delete" onclick="removeBlock('{{ block.id }}')">🗑️</button>
|
||||
<div class="social-icons">
|
||||
{% if block.content.facebook %}
|
||||
<a href="{{ block.content.facebook }}"><i class="fab fa-facebook"></i></a>
|
||||
{% endif %}
|
||||
<!-- Más redes... -->
|
||||
</div>
|
||||
</div>
|
||||
{% elif block.type == 'mapa' %}
|
||||
<div class="gk-block" data-block-id="{{ block.id }}" draggable="true">
|
||||
<button class="gk-block-delete" onclick="removeBlock('{{ block.id }}')">🗑️</button>
|
||||
<iframe src="{{ block.content.url }}" width="100%" height="450" frameborder="0"></iframe>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 CHECKLIST
|
||||
|
||||
- [ ] Sistema de bloques en backend (añadir/eliminar/reordenar)
|
||||
- [ ] UI para añadir bloques en sidebar
|
||||
- [ ] Renderizado de bloques en template
|
||||
- [ ] Drag & drop funcional
|
||||
- [ ] Iconos de redes sociales (Font Awesome o SVG)
|
||||
- [ ] Mapa embed sin API
|
||||
- [ ] Edición inline de bloques
|
||||
- [ ] Sincronización bidireccional
|
||||
- [ ] Guardado automático
|
||||
- [ ] Indicadores visuales (hover, drag)
|
||||
|
||||
---
|
||||
|
||||
## 🎨 ESTILOS
|
||||
|
||||
```css
|
||||
.gk-block {
|
||||
position: relative;
|
||||
margin: 20px 0;
|
||||
padding: 15px;
|
||||
border: 2px dashed transparent;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.gk-block:hover {
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.gk-block.dragging {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.gk-block-delete {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
background: #d63638;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.gk-block:hover .gk-block-delete {
|
||||
opacity: 1;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔗 REFERENCIAS
|
||||
|
||||
- WordPress Gutenberg: Sistema de bloques
|
||||
- Elementor: Drag & drop visual
|
||||
- Google Maps Embed: Sin API key necesario
|
||||
|
||||
---
|
||||
|
||||
**Última actualización:** 2025-01-15
|
||||
**Estado:** En desarrollo
|
||||
Reference in New Issue
Block a user