Files
gkachele-saas/demo/utils/theme_engine.py
2026-01-17 11:40:17 +01:00

180 lines
6.4 KiB
Python

import os
import json
import sqlite3
from flask import current_app
from config import THEMES_DIR, MAIN_DB
def scan_available_themes():
"""Escanear todos los templates disponibles y cargar sus configuraciones"""
themes = {}
if not os.path.exists(THEMES_DIR):
return themes
for theme_dir in os.listdir(THEMES_DIR):
theme_path = os.path.join(THEMES_DIR, theme_dir)
if not os.path.isdir(theme_path) or theme_dir.startswith('_'):
continue
config_path = os.path.join(theme_path, 'config.json')
template_path = os.path.join(theme_path, 'template.html')
if not os.path.exists(config_path) or not os.path.exists(template_path):
continue
try:
with open(config_path, 'r', encoding='utf-8') as f:
config = json.load(f)
themes[theme_dir] = {
'id': theme_dir,
'name': config.get('name', theme_dir),
'description': config.get('description', ''),
'rubro': config.get('rubro', 'general'),
'sections': config.get('sections', []),
'colors': config.get('colors', {}),
'typography': config.get('typography', {}),
'features': config.get('features', {}),
'preview': f'/themes/{theme_dir}/preview.jpg' if os.path.exists(os.path.join(theme_path, 'preview.jpg')) else None
}
except Exception as e:
print(f"⚠️ Error cargando template {theme_dir}: {e}")
continue
return themes
def get_theme_config(theme_id):
"""Obtener configuración de un template específico"""
config_path = os.path.join(THEMES_DIR, theme_id, 'config.json')
if not os.path.exists(config_path):
return None
try:
with open(config_path, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
print(f"⚠️ Error cargando config de {theme_id}: {e}")
return None
def get_themes_by_rubro(rubro):
"""Obtener templates filtrados por rubro"""
all_themes = scan_available_themes()
return {k: v for k, v in all_themes.items() if v.get('rubro') == rubro or v.get('rubro') == 'general'}
def get_site_menus(site_id, user_id):
"""Obtener menús del sitio organizados por ubicación"""
conn = sqlite3.connect(MAIN_DB)
c = conn.cursor()
c.execute('''SELECT location, title, url, order_index, parent_id
FROM menus
WHERE site_id = ? AND user_id = ?
ORDER BY location, order_index''', (site_id, user_id))
rows = c.fetchall()
conn.close()
menus = {'header': [], 'footer': [], 'sidebar': []}
for row in rows:
location, title, url, order_index, parent_id = row
menu_item = {
'title': title,
'url': url,
'order': order_index,
'parent_id': parent_id
}
if location in menus:
menus[location].append(menu_item)
return menus
def get_site_widgets(site_id, user_id, area='sidebar'):
"""Obtener widgets del sitio por área"""
conn = sqlite3.connect(MAIN_DB)
c = conn.cursor()
c.execute('''SELECT type, title, content, order_index
FROM widgets
WHERE site_id = ? AND user_id = ? AND area = ?
ORDER BY order_index''', (site_id, user_id, area))
rows = c.fetchall()
conn.close()
widgets = []
for row in rows:
widget_type, title, content, order_index = row
widgets.append({
'type': widget_type,
'title': title,
'content': content,
'order': order_index
})
return widgets
def render_gkachele_template(theme, content, site_id=None, user_id=None):
"""Renderizar template usando estructura GKACHELE (header.php, footer.php, sidebar.php)"""
menus = {'header': [], 'footer': [], 'sidebar': []}
widgets = []
if site_id and user_id:
try:
menus = get_site_menus(site_id, user_id)
widgets = get_site_widgets(site_id, user_id)
except Exception as e:
print(f"⚠️ Error obteniendo menús/widgets: {e}")
theme_template = ''
theme_path = os.path.join(THEMES_DIR, theme, 'template.html')
if os.path.exists(theme_path):
with open(theme_path, 'r', encoding='utf-8') as f:
theme_template = f.read()
else:
theme_template = '<div class="container"><h1>{{ hero_title or "Bienvenido" }}</h1></div>'
header = ''
footer = ''
sidebar = ''
header_path = os.path.join(THEMES_DIR, '_gkachele', 'header.php')
footer_path = os.path.join(THEMES_DIR, '_gkachele', 'footer.php')
sidebar_path = os.path.join(THEMES_DIR, '_gkachele', 'sidebar.php')
if os.path.exists(header_path):
with open(header_path, 'r', encoding='utf-8') as f:
header = f.read()
else:
header = '<html><body>' # Fallback simplificado
if os.path.exists(footer_path):
with open(footer_path, 'r', encoding='utf-8') as f:
footer = f.read()
else:
footer = '</body></html>'
if os.path.exists(sidebar_path):
with open(sidebar_path, 'r', encoding='utf-8') as f:
sidebar = f.read()
template_data = {
'site_name': content.get('site_name', 'GKACHELE Site'),
'hero_title': content.get('hero_title', 'Bienvenido'),
'colors': content.get('colors', {}),
'typography': content.get('typography', {}),
'horarios': content.get('horarios', {}),
'redes_sociales': content.get('redes_sociales', {}),
'blocks': content.get('blocks', []),
'menus': menus,
'widgets': widgets,
**content
}
from jinja2 import Template
is_full_page = False
if theme == 'restaurante-moderno' or '<!DOCTYPE html>' in theme_template:
is_full_page = True
if is_full_page:
template = Template(theme_template)
return template.render(**template_data)
full_template = header + theme_template + sidebar + footer
template = Template(full_template)
return template.render(**template_data)