from flask import Blueprint, render_template, session, request, jsonify, make_response import json from pathlib import Path from datetime import datetime from db import get_db from utils.theme_engine import get_theme_config elementor_bp = Blueprint( 'elementor', __name__, template_folder='templates', static_folder='static', static_url_path='/elementor/static' ) 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,)) site = c.fetchone() if not site: conn.close() return 'Sitio no encontrado', 404 if 'user_id' in session and site[0] != session['user_id']: conn.close() return 'No autorizado', 403 content = json.loads(site[3]) if site[3] else {} if not isinstance(content, dict): content = {} theme = site[2] theme_config = get_theme_config(theme) c.execute('SELECT plan, rubro FROM users WHERE id = ?', (site[0],)) user_data = c.fetchone() conn.close() user_plan = user_data[0] if user_data else 'base' user_rubro = user_data[1] if user_data else 'restaurante' html = render_template( 'elementor_builder.html', site_id=site_id, slug=site[1], theme=theme, content=content, theme_config=theme_config, user_plan=user_plan, rubro=user_rubro, 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/') 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 {} site_id = data.get('site_id') content = data.get('content') publish = bool(data.get('publish')) if not site_id or not isinstance(content, dict): return jsonify({'success': False, 'error': 'Payload invalido'}), 400 conn = get_db() c = conn.cursor() c.execute('SELECT user_id, content_json FROM sites WHERE id = ?', (site_id,)) row = c.fetchone() if not row: conn.close() return jsonify({'success': False, 'error': 'Sitio no encontrado'}), 404 owner_id = row[0] if 'user_id' in session and session['user_id'] != owner_id: conn.close() return jsonify({'success': False, 'error': 'No autorizado'}), 403 current_content = {} try: if row[1]: current_content = json.loads(row[1]) or {} except Exception: current_content = {} merged = dict(current_content) merged.update(content) # Debug trace para capturar presets/menus que llegan del front try: log_dir = Path('logs') log_dir.mkdir(exist_ok=True) log_path = log_dir / 'elementor_save.log' snapshot = { "ts": datetime.utcnow().isoformat() + "Z", "site_id": site_id, "keys": list(content.keys()) if isinstance(content, dict) else [], "menu_preset": content.get('menu_preset') if isinstance(content, dict) else None, "menu_icon_style": content.get('menu_icon_style') if isinstance(content, dict) else None, "menu_card_bg": content.get('menu_card_bg') if isinstance(content, dict) else None, "social_preset": content.get('social_preset') if isinstance(content, dict) else None, } with log_path.open('a', encoding='utf-8') as f: f.write(json.dumps(snapshot, ensure_ascii=False) + "\n") except Exception: pass if publish: c.execute('UPDATE sites SET content_json = ?, status = ? WHERE id = ?', (json.dumps(merged), 'published', site_id)) else: c.execute('UPDATE sites SET content_json = ? WHERE id = ?', (json.dumps(merged), site_id)) conn.commit() conn.close() 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