diff --git a/elementor/templates/elementor_builder.html b/elementor/templates/elementor_builder.html
index 67e9040..9d4750d 100644
--- a/elementor/templates/elementor_builder.html
+++ b/elementor/templates/elementor_builder.html
@@ -19,6 +19,10 @@
.block-item{background:var(--panel2);border:1px solid var(--border);padding:8px 10px;border-radius:10px;margin-bottom:8px;cursor:grab}
.main{padding:18px}
.topbar{display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap}
+ .save-status{font-size:12px;color:var(--muted);min-width:150px;text-align:right}
+ .save-status.ok{color:#34d399}
+ .save-status.error{color:#f87171}
+ .save-status.busy{color:#fbbf24}
.btn{background:var(--accent);color:#09121a;border:0;padding:8px 12px;border-radius:999px;font-weight:700;cursor:pointer;transition:transform .2s ease,box-shadow .2s ease}
.btn:hover{transform:translateY(-1px);box-shadow:0 10px 22px rgba(15,23,42,.15)}
.btn.secondary{background:transparent;color:var(--text);border:1px solid var(--border)}
@@ -253,6 +257,7 @@
+
Listo
@@ -447,6 +452,7 @@ const state = {
let pendingMove = null;
let pendingResize = null;
let previewStateBefore = null;
+ let isSaving = false;
function makeId(){ return "block_" + Date.now() + "_" + Math.floor(Math.random()*1000); }
function getDefaultPos(){
@@ -1657,19 +1663,64 @@ const state = {
});
renderPreview();
}
+ function setSaveStatus(msg, kind=""){
+ const status = document.getElementById("saveStatus");
+ if (!status) return;
+ status.textContent = msg;
+ status.className = `save-status${kind ? ` ${kind}` : ""}`;
+ }
+ function normalizeLoadedBlocks(blocks){
+ if (!Array.isArray(blocks)) return [];
+ return blocks
+ .filter((b)=>b && typeof b === "object")
+ .map((b)=>({
+ ...b,
+ id: b.id || makeId(),
+ data: (b.data && typeof b.data === "object") ? b.data : {}
+ }));
+ }
async function saveContent(){
- const payload={ site_id: SITE_ID, content: { ...SERVER_CONTENT, settings: state.settings, blocks: state.blocks } };
- try{ const res=await fetch("/api/customizer/save",{ method:"POST", headers:{ "Content-Type":"application/json" }, body: JSON.stringify(payload) }); const data=await res.json(); if (!data.success) throw new Error("save failed"); alert("Cambios guardados"); }
- catch(err){ console.error(err); alert("No se pudo guardar"); }
+ if (isSaving) return;
+ isSaving = true;
+ const btn = document.getElementById("btnSave");
+ if (btn){
+ btn.disabled = true;
+ btn.textContent = "Publicando...";
+ }
+ setSaveStatus("Guardando cambios...", "busy");
+ const payload = {
+ site_id: SITE_ID,
+ publish: true,
+ content: { ...SERVER_CONTENT, settings: state.settings, blocks: state.blocks }
+ };
+ try{
+ const res = await fetch("/api/elementor/save",{
+ method:"POST",
+ headers:{ "Content-Type":"application/json" },
+ body: JSON.stringify(payload)
+ });
+ const data = await res.json();
+ if (!res.ok || !data.success) throw new Error(data.error || "save failed");
+ setSaveStatus("Publicado", "ok");
+ } catch(err){
+ console.error(err);
+ setSaveStatus("Error al publicar", "error");
+ } finally {
+ isSaving = false;
+ if (btn){
+ btn.disabled = false;
+ btn.textContent = "Publicar";
+ }
+ }
}
function init(){
+ state.blocks = normalizeLoadedBlocks(state.blocks);
if (BUILDER_MODE === "ub24"){
state.blocks.forEach(b=>{ if (!b.page) b.page = "home"; });
}
if (BUILDER_MODE === "ub24"){
state.settings.free_drag = false;
}
- state.blocks = [];
selectedBlockId = null;
wireSidebar(); wirePreviewDrop(); wireInlineEditing(); wireSettings(); wireFreeDragToggle(); wireJumpSelect(); wirePreviewSize(); wireThemeToggle();
const backBtn = document.getElementById("btnBack");