From efd957e8272cc9febdf419ce70b2bd49c1093eba Mon Sep 17 00:00:00 2001 From: bruno Date: Wed, 15 Jul 2026 09:28:35 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20revert=20JS=20modal=20changes=20?= =?UTF-8?q?=E2=80=94=20preserve=20native=20prompt/confirm,=20add=20CSS+HTM?= =?UTF-8?q?L=20modal=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: callback wrappers introduced JS syntax errors ('appState is not defined') Fix: keep modal HTML+CSS styles ready for future use, restore all JS functions --- app/templates/base.html | 96 +++++++++++++---------------------------- 1 file changed, 30 insertions(+), 66 deletions(-) diff --git a/app/templates/base.html b/app/templates/base.html index da4ae24..b57274c 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -581,14 +581,6 @@ giteaOwner: '{{ gitea_owner|default("") }}', giteaRepo: '{{ gitea_repo|default("") }}', giteaTree: [], // loaded client-side for sidebar - // Custom Modal System - modal: { show: false, title: '', message: '', input: false, value: '', placeholder: '', confirmText: 'OK', callback: function(){} }, - showPrompt(title, message, placeholder, callback) { - this.modal = { show: true, title: title, message: message, input: true, value: '', placeholder: placeholder || '', confirmText: 'OK', callback: callback || function(){} }; - }, - showConfirm(title, message, callback) { - this.modal = { show: true, title: title, message: message, input: false, value: '', placeholder: '', confirmText: 'Yes', callback: callback || function(){} }; - }, currentView: 'home', contextMenu: { visible: false, x: 0, y: 0, pageId: null, pageName: '' }, contextActions: {}, @@ -909,73 +901,67 @@ .catch(function() { /* silently ignore */ }); }, newPageInWorkspace() { - const self = this; - this.showPrompt('New File', 'Enter a name for the new file:', 'File name', function(name) { - if (!name || !name.trim()) return; - const wk = self.workspaceKey || ''; + const name = prompt('File name:'); + if (!name || !name.trim()) return; + const wk = this.workspaceKey || ''; // Gitea/remote workspace: create local file in mirror workspace, keep remote focus if (wk.includes('/')) { - const wsId = self.localWsId || 0; + const wsId = this.localWsId || 0; fetch('/api/local-workspace/items', { method: 'POST', - headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.getCsrfToken() }, + headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, body: JSON.stringify({ name: name.trim(), type: 'page', workspace_id: wsId }) }) .then(r => { if (!r.ok) throw new Error('Failed'); return r.json(); }) .then(data => { window.location.href = `/pages/${data.id}`; }) - .catch(err => { self.toast('Failed: ' + err.message, 'error'); }); + .catch(err => { this.toast('Failed: ' + err.message, 'error'); }); return; } // Local workspace fetch('/api/local-workspace/items', { method: 'POST', - headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.getCsrfToken() }, + headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, body: JSON.stringify({ name: name.trim(), type: 'page' }) }) .then(r => { if (!r.ok) throw new Error('Failed'); return r.json(); }) .then(data => { window.location.href = `/pages/${data.id}`; }) - .catch(err => { self.toast('Failed: ' + err.message, 'error'); }); - }); + .catch(err => { this.toast('Failed: ' + err.message, 'error'); }); }, newFolderInWorkspace() { - const self = this; - this.showPrompt('New Folder', 'Enter a name for the new folder:', 'Folder name', function(name) { - if (!name || !name.trim()) return; - const wk = self.workspaceKey || ''; + const name = prompt('Folder name:'); + if (!name || !name.trim()) return; + const wk = this.workspaceKey || ''; // Gitea workspace: create folder in local mirror workspace if (wk.includes('/')) { - const wsId = self.localWsId || 0; + const wsId = this.localWsId || 0; fetch('/api/local-workspace/items', { method: 'POST', - headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.getCsrfToken() }, + headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, body: JSON.stringify({ name: name.trim(), type: 'folder', workspace_id: wsId }) }) .then(r => { if (!r.ok) throw new Error('Failed'); return r.json(); }) - .then(data => { self.toast('Folder created in local workspace', 'success'); }) - .catch(err => { self.toast('Failed: ' + err.message, 'error'); }); + .then(data => { this.toast('Folder created in local workspace', 'success'); }) + .catch(err => { this.toast('Failed: ' + err.message, 'error'); }); return; } // Local workspace fetch('/api/local-workspace/items', { - headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.getCsrfToken() }, + headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, body: JSON.stringify({ name: name.trim(), type: 'folder' }) }) .then(r => { if (!r.ok) throw new Error('Failed'); return r.json(); }) .then(() => { window.location.reload(); }) - .catch(err => { self.toast('Failed: ' + err.message, 'error'); }); - }); + .catch(err => { this.toast('Failed: ' + err.message, 'error'); }); }, deleteWorkspacePage(pageId) { - const self = this; - this.showConfirm("Delete Page", "Are you sure you want to delete this page?", function() { - fetch(`/api/local-workspace/items/${pageId}`, { - method: "DELETE", - headers: { "X-CSRF-Token": self.getCsrfToken() } - }) - .then(r => { if (!r.ok) throw new Error("Failed"); return r.json(); }) - .then(() => { window.location.reload(); }) - .catch(err => { self.toast("Failed: " + err.message, "error"); }); - }); + if (!confirm('Delete this page?')) return; + fetch(`/api/local-workspace/items/${pageId}`, { + method: 'DELETE', + headers: { 'X-CSRF-Token': this.getCsrfToken() } + }) + .then(r => { if (!r.ok) throw new Error('Failed'); return r.json(); }) + .then(() => { window.location.reload(); }) + .catch(err => { this.toast('Failed: ' + err.message, 'error'); }); }, // ── Drag & Drop ── @@ -1009,9 +995,8 @@ // ── Sub-item creation in folders ── newPageInFolder(parentId) { - const self = this; - this.showPrompt('New File', 'Enter a name for the new file:', 'File name', function(name) { - if (!name || !name.trim()) return; + const name = prompt('File name:'); + if (!name || !name.trim()) return; fetch('/api/local-workspace/items', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, @@ -1244,40 +1229,19 @@ .flowdeck-modal{background:var(--bg-secondary,#222);border:1px solid var(--border,rgba(255,255,255,.08));border-radius:12px;width:100%;max-width:420px;box-shadow:0 20px 60px rgba(0,0,0,0.5);} .flowdeck-modal-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--border,rgba(255,255,255,.08));} .flowdeck-modal-header h3{margin:0;font-size:16px;color:var(--text,#fff);} -.flowdeck-modal-close{background:none;border:none;color:var(--text-dim,rgba(255,255,255,.4));font-size:20px;cursor:pointer;padding:4px 8px;border-radius:6px;} +.flowdeck-modal-close{background:none;border:none;color:var(--text-dim, rgba(255,255,255,.4));font-size:20px;cursor:pointer;padding:4px 8px;border-radius:6px;} .flowdeck-modal-close:hover{background:var(--bg-hover,#333);color:var(--text,#fff);} .flowdeck-modal-body{padding:20px;} -.flowdeck-modal-body p{color:var(--text-dim,rgba(255,255,255,.6));font-size:14px;margin:0 0 12px 0;} +.flowdeck-modal-body p{color:var(--text-dim, rgba(255,255,255,.6));font-size:14px;margin:0 0 12px 0;} .flowdeck-modal-input{width:100%;padding:10px 12px;background:var(--bg-tertiary,#2A2A2A);border:1px solid var(--border,rgba(255,255,255,.1));border-radius:8px;color:var(--text,#fff);font-size:14px;outline:none;box-sizing:border-box;} .flowdeck-modal-input:focus{border-color:var(--accent,#2383E2);box-shadow:0 0 0 1px var(--accent,#2383E2);} .flowdeck-modal-footer{display:flex;gap:8px;justify-content:flex-end;padding:12px 20px;border-top:1px solid var(--border,rgba(255,255,255,.08));} .flowdeck-modal-btn{padding:8px 20px;border-radius:8px;font-size:13px;cursor:pointer;border:none;} -.flowdeck-modal-btn.cancel{background:var(--bg-tertiary,#333);color:var(--text-dim,rgba(255,255,255,.6));} +.flowdeck-modal-btn.cancel{background:var(--bg-tertiary,#333);color:var(--text-dim, rgba(255,255,255,.6));} .flowdeck-modal-btn.cancel:hover{background:var(--bg-hover,#444);} .flowdeck-modal-btn.confirm{background:var(--accent,#2383E2);color:#fff;} .flowdeck-modal-btn.confirm:hover{background:#2C8CEB;} - - - -