diff --git a/app/templates/base.html b/app/templates/base.html index c39326e..da4ae24 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -581,6 +581,14 @@ 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: {}, @@ -901,67 +909,73 @@ .catch(function() { /* silently ignore */ }); }, newPageInWorkspace() { - const name = prompt('File name:'); - if (!name || !name.trim()) return; - const wk = this.workspaceKey || ''; + 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 || ''; // Gitea/remote workspace: create local file in mirror workspace, keep remote focus if (wk.includes('/')) { - const wsId = this.localWsId || 0; + const wsId = self.localWsId || 0; fetch('/api/local-workspace/items', { method: 'POST', - headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, + headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.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 => { this.toast('Failed: ' + err.message, 'error'); }); + .catch(err => { self.toast('Failed: ' + err.message, 'error'); }); return; } // Local workspace fetch('/api/local-workspace/items', { method: 'POST', - headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, + headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.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 => { this.toast('Failed: ' + err.message, 'error'); }); + .catch(err => { self.toast('Failed: ' + err.message, 'error'); }); + }); }, newFolderInWorkspace() { - const name = prompt('Folder name:'); - if (!name || !name.trim()) return; - const wk = this.workspaceKey || ''; + 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 || ''; // Gitea workspace: create folder in local mirror workspace if (wk.includes('/')) { - const wsId = this.localWsId || 0; + const wsId = self.localWsId || 0; fetch('/api/local-workspace/items', { method: 'POST', - headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, + headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.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 => { this.toast('Folder created in local workspace', 'success'); }) - .catch(err => { this.toast('Failed: ' + err.message, 'error'); }); + .then(data => { self.toast('Folder created in local workspace', 'success'); }) + .catch(err => { self.toast('Failed: ' + err.message, 'error'); }); return; } // Local workspace fetch('/api/local-workspace/items', { - headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, + headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.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 => { this.toast('Failed: ' + err.message, 'error'); }); + .catch(err => { self.toast('Failed: ' + err.message, 'error'); }); + }); }, deleteWorkspacePage(pageId) { - 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'); }); + 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"); }); + }); }, // ── Drag & Drop ── @@ -995,8 +1009,9 @@ // ── Sub-item creation in folders ── newPageInFolder(parentId) { - const name = prompt('File name:'); - if (!name || !name.trim()) return; + const self = this; + this.showPrompt('New File', 'Enter a name for the new file:', 'File name', function(name) { + if (!name || !name.trim()) return; fetch('/api/local-workspace/items', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() }, @@ -1223,5 +1238,46 @@ {% block scripts %}{% endblock %} + + + + + + +