Files
gkachele-saas/memoria/SISTEMA_BLOQUES_EDITABLES.md
2026-01-17 11:40:17 +01:00

6.0 KiB
Raw Permalink Blame History

🧩 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

{
  "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)

# 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)

// 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)

<!-- 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

.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