fix: Alpine.data registration BEFORE x-data element — init order
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped

Alpine processes DOM top-to-bottom. x-data='wsInit()' was evaluated
before the script defining wsInit() was parsed. Moved Alpine.data
registration to a script tag BEFORE the x-data div. Also removed
duplicate script block at the bottom.
This commit is contained in:
2026-07-10 21:53:55 -04:00
parent 46e7c1d815
commit b01c5bbfe3
+79 -7
View File
@@ -55,6 +55,79 @@
.delete-confirm{padding:12px;background:rgba(255,80,80,.08);border-radius:8px;margin-top:12px;font-size:13px;color:var(--text-secondary);}
</style>
<script>
document.addEventListener('alpine:init', function() {
Alpine.data('wsInit', function() {
return {
tree:[],
loaded:false,
showCreate:false, showRename:false, showDelete:false,
createType:'file', newName:'', parentFolder:null, target:null,
async init() {
try {
var r = await fetch('/api/local-workspace/tree');
var d = await r.json();
this.tree = flatten(d.tree||[],0);
this.loaded = true;
} catch(e) { this.loaded = true; }
},
openModal(type, parent) {
this.createType = type; this.parentFolder = parent||null; this.newName = '';
this.showCreate = true;
var self = this;
this.$nextTick(function() {
var el = self.$refs.cinp;
if (el) setTimeout(function() { el.focus(); }, 100);
});
},
async doCreate() {
var n = this.newName.trim(); if (!n) return;
var body = { name:n, type:this.createType };
if (this.parentFolder) body.parent_id = this.parentFolder.db_id;
var r = await fetch('/api/local-workspace/items', {
method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(body)
});
if (r.ok) {
this.showCreate = false; this.parentFolder = null; this.newName = '';
window.location.reload();
}
},
openPage(id) { window.location = '/pages/'+id; },
startRename(node) {
this.target = node; this.newName = node.name.trim(); this.showRename = true;
var self = this;
this.$nextTick(function() {
var el = self.$refs.rinp;
if (el) setTimeout(function() { el.focus(); }, 100);
});
},
async doRename() {
var n = this.newName.trim(); if (!n||!this.target) return;
await fetch('/api/local-workspace/items/'+this.target.db_id, {
method:'PUT', headers:{'Content-Type':'application/json'}, body:JSON.stringify({name:n})
});
this.showRename = false; this.target = null; this.newName = '';
await this.init();
},
startDelete(node) { this.target = node; this.showDelete = true; },
async doDelete() {
if (!this.target) return;
await fetch('/api/local-workspace/items/'+this.target.db_id, {method:'DELETE'});
this.showDelete = false; this.target = null;
await this.init();
}
};});
});
</script>
<div class="ws-layout" x-data="wsInit()">
<div class="ws-header">
@@ -141,8 +214,9 @@
</div>
<script>
function wsInit() {
return {
document.addEventListener('alpine:init', function() {
Alpine.data('wsInit', function() {
return {
tree:[],
loaded:false,
showCreate:false,
@@ -231,8 +305,8 @@ function wsInit() {
this.target = null;
await this.init();
}
};
}
};});
});
function flatten(nodes, depth) {
var result = [];
@@ -240,9 +314,7 @@ function flatten(nodes, depth) {
var n = nodes[i];
var isFolder = n.type==='folder';
result.push({db_id:n.id, name:n.name, icon:isFolder?'📁':'📄', is_folder:isFolder, depth:depth});
if (n.children) {
result = result.concat(flatten(n.children, depth+1));
}
if (n.children) result = result.concat(flatten(n.children, depth+1));
}
return result;
}