diff --git a/elementor/routes.py b/elementor/routes.py index 1181c67..bca05ef 100644 --- a/elementor/routes.py +++ b/elementor/routes.py @@ -1,4 +1,4 @@ -from flask import Blueprint, render_template, session, request, jsonify +from flask import Blueprint, render_template, session, request, jsonify, make_response import json from db import get_db from utils.theme_engine import get_theme_config @@ -13,7 +13,7 @@ elementor_bp = Blueprint( ) -def _render_builder(site_id, builder_mode='default', **_kwargs): +def _render_builder(site_id, builder_mode='default', preview_only=False, **_kwargs): conn = get_db() c = conn.cursor() c.execute('SELECT user_id, slug, theme, content_json FROM sites WHERE id = ?', (site_id,)) @@ -40,7 +40,7 @@ def _render_builder(site_id, builder_mode='default', **_kwargs): user_plan = user_data[0] if user_data else 'base' user_rubro = user_data[1] if user_data else 'restaurante' - return render_template( + html = render_template( 'elementor_builder.html', site_id=site_id, slug=site[1], @@ -49,8 +49,15 @@ def _render_builder(site_id, builder_mode='default', **_kwargs): theme_config=theme_config, user_plan=user_plan, rubro=user_rubro, - builder_mode=builder_mode + builder_mode=builder_mode, + preview_only=bool(preview_only) ) + response = make_response(html) + # Dynamic builder output should never be cached. + response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' + response.headers['Pragma'] = 'no-cache' + response.headers['Expires'] = '0' + return response @elementor_bp.route('/elementor/') @@ -58,11 +65,21 @@ def elementor_view(site_id): return _render_builder(site_id, builder_mode='default') +@elementor_bp.route('/elementor//preview-final') +def elementor_preview_final(site_id): + return _render_builder(site_id, builder_mode='default', preview_only=True) + + @elementor_bp.route('/ub24/') def ub24_view(site_id): return _render_builder(site_id, builder_mode='ub24') +@elementor_bp.route('/ub24//preview-final') +def ub24_preview_final(site_id): + return _render_builder(site_id, builder_mode='ub24', preview_only=True) + + @elementor_bp.route('/api/elementor/save', methods=['POST']) def save_elementor(): data = request.get_json(silent=True) or {} @@ -103,4 +120,9 @@ def save_elementor(): conn.commit() conn.close() - return jsonify({'success': True, 'published': publish}) + response = jsonify({'success': True, 'published': publish}) + response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' + response.headers['Pragma'] = 'no-cache' + response.headers['Expires'] = '0' + return response + diff --git a/elementor/templates/elementor_builder.html b/elementor/templates/elementor_builder.html index 0827681..52ff9dd 100644 --- a/elementor/templates/elementor_builder.html +++ b/elementor/templates/elementor_builder.html @@ -616,13 +616,13 @@ }, blocks: [ { id: makeId(), type: 'menu', data: { ...defaultData('menu'), width: 100 } }, - { id: makeId(), type: 'hero', data: { title: 'Hectarea en Obera + Chacra en Jardin America', subtitle: 'Presentacion comercial clara con contacto directo, mapas embebidos y cierre por WhatsApp.', kicker: 'Venta Directa', button_text: 'Hablar por WhatsApp', button_url: '#contacto', button_secondary_text: 'Ver propiedades', button_secondary_url: '#menu', image_url: '', align: 'left', width: 60 } }, - { id: makeId(), type: 'cards', data: { title: 'Propiedades destacadas', items: ['Obera|1 hectarea con excelente proyeccion.','Jardin America|25 hectareas con potencial productivo.','Documentacion|Informacion lista para visita y cierre.'], columns: 3, width: 60 } }, - { id: makeId(), type: 'gallery', data: { title: 'Galeria referencial', images: ['','',''], captions: ['Zona 1','Zona 2','Zona 3'], fit: 'cover', width: 60 } }, - { id: makeId(), type: 'review', data: { title: 'Resenas', name: 'Cliente verificado', text: 'Presentacion impecable y proceso de contacto muy claro.', rating: 5, style: 'card', width: 60 } }, - { id: makeId(), type: 'contact', data: { title: 'Contacto directo', email: '', phone: '', address: '', cta_text: 'Escribir ahora', cta_url: '#', width: 60 } }, - { id: makeId(), type: 'social', data: { instagram: '', facebook: '', whatsapp: '', tiktok: '', youtube: '', icon_size: 18, icon_color: '#1f1b17', show_text: true, icon_style: 'pill', social_preset: 'pro', width: 60 } }, - { id: makeId(), type: 'map', data: { title: 'Ubicacion', address: '', embed_url: '', height: 320, width: 60 } } + { id: makeId(), type: 'hero', data: { title: 'Cocina de autor con sabor local', subtitle: 'Menu de temporada, ingredientes frescos y una experiencia pensada para que quieras volver.', kicker: 'Restaurante', button_text: 'Reservar mesa', button_url: '#contacto', button_secondary_text: 'Ver menu', button_secondary_url: '#menu', image_url: '', align: 'left', width: 100 } }, + { id: makeId(), type: 'cards', data: { title: 'Especialidades de la casa', items: ['Entradas|Opciones frescas y para compartir.','Platos principales|Recetas de autor con producto local.','Postres|Cierre dulce hecho en casa.'], columns: 3, width: 100 } }, + { id: makeId(), type: 'gallery', data: { title: 'Nuestro espacio', images: ['','',''], captions: ['Salon principal','Plato destacado','Barra de tragos'], fit: 'cover', width: 100 } }, + { id: makeId(), type: 'review', data: { title: 'Resenas', name: 'Cliente frecuente', text: 'Excelente servicio, ambiente calido y platos que superan expectativas.', rating: 5, style: 'card', width: 100 } }, + { id: makeId(), type: 'contact', data: { title: 'Reserva y contacto', email: '', phone: '', address: '', cta_text: 'Reservar ahora', cta_url: '#', width: 100 } }, + { id: makeId(), type: 'social', data: { instagram: '', facebook: '', whatsapp: '', tiktok: '', youtube: '', icon_size: 18, icon_color: '#1f1b17', show_text: true, icon_style: 'pill', social_preset: 'pro', width: 100 } }, + { id: makeId(), type: 'map', data: { title: 'Como llegar', address: '', embed_url: '', height: 320, width: 100 } } ] }, cosmeticos: {