Unify all New Page / New Folder buttons across the app
- Add global window.FlowDeck namespace with createPage() and showCreateFolderModal() - createPage() creates a Notion-style page via /board/api/pages (same as sidebar bottom-right button) - showCreateFolderModal() opens a global themed modal (dark/light) instead of browser prompt() - All New Page buttons now call window.FlowDeck.createPage() - All New Folder buttons now call window.FlowDeck.showCreateFolderModal() - Global New Folder modal uses existing .flowdeck-modal CSS classes for theme consistency - Updated Ctrl+N keyboard shortcut to use unified createPage()
This commit is contained in:
+89
-8
@@ -123,8 +123,8 @@
|
||||
<span>{% if gitea_workspace %}📁 {{ active_ws_name }}{% elif workspace_key and '/' in workspace_key %}🔗{% else %}📁{% endif %} {{ active_ws_name if not gitea_workspace else '' }}</span>
|
||||
</div>
|
||||
<div class="sidebar-section-actions">
|
||||
<button class="section-action-btn" title="New Page" @click.stop="newPageInWorkspace()">📄</button>
|
||||
<button class="section-action-btn" title="New Folder" @click.stop="newFolderInWorkspace()">📁</button>
|
||||
<button class="section-action-btn" title="New Page" @click.stop="window.FlowDeck.createPage()">📄</button>
|
||||
<button class="section-action-btn" title="New Folder" @click.stop="window.FlowDeck.showCreateFolderModal()">📁</button>
|
||||
</div>
|
||||
</div>
|
||||
{% from '_workspace_tree_macro.html' import render_workspace_tree %}
|
||||
@@ -170,7 +170,7 @@
|
||||
<span>Meetings</span>
|
||||
</div>
|
||||
<div class="sidebar-section-actions">
|
||||
<button class="section-action-btn" title="Add" @click.stop="newPage('Meetings')">+</button>
|
||||
<button class="section-action-btn" title="Add" @click.stop="window.FlowDeck.createPage()">+</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-section-items" x-show="sectionsOpen.meetings" x-transition>
|
||||
@@ -332,7 +332,7 @@
|
||||
<span style="font-size:14px;">💬</span> New chat
|
||||
<span class="shortcut">Ctrl+O</span>
|
||||
</button>
|
||||
<button class="sidebar-footer-btn" style="width:36px; justify-content:center; background:var(--bg-hover); border-radius:8px;" @click="newPage('Private')" title="New page">
|
||||
<button class="sidebar-footer-btn" style="width:36px; justify-content:center; background:var(--bg-hover); border-radius:8px;" onclick="window.FlowDeck.createPage()" title="New page">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><line x1="9" y1="15" x2="15" y2="15"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
@@ -425,10 +425,10 @@
|
||||
@click.outside="wsCtx.visible = false">
|
||||
<template x-if="wsCtx.isFolder">
|
||||
<div class="context-menu-section">
|
||||
<div class="context-menu-item" @click="wsCtxAction('new-file')">
|
||||
<div class="context-menu-item" onclick="window.FlowDeck.createPage()">
|
||||
<span class="menu-icon">📄</span> New File
|
||||
</div>
|
||||
<div class="context-menu-item" @click="wsCtxAction('new-folder')">
|
||||
<div class="context-menu-item" onclick="window.FlowDeck.showCreateFolderModal()">
|
||||
<span class="menu-icon">📁</span> New Folder
|
||||
</div>
|
||||
</div>
|
||||
@@ -488,6 +488,70 @@
|
||||
});
|
||||
})();
|
||||
|
||||
// ── Global FlowDeck namespace ────────────────────────────────
|
||||
// All "New Page" and "New Folder" buttons across the app call
|
||||
// these functions for consistent behaviour.
|
||||
window.FlowDeck = {
|
||||
getCsrfToken: function() {
|
||||
var m = document.cookie.match(/csrf_token=([^;]+)/);
|
||||
return m ? m[1] : '';
|
||||
},
|
||||
|
||||
/** Create a new Notion-style page (same as sidebar bottom-right button). */
|
||||
createPage: function() {
|
||||
var project = (window.appState && window.appState.workspaceKey) || '';
|
||||
var url = '/board/api/pages?section=Private&project=' + encodeURIComponent(project);
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'X-CSRF-Token': this.getCsrfToken() }
|
||||
})
|
||||
.then(function(r) { if (!r.ok) throw new Error('CSRF or API error'); return r.json(); })
|
||||
.then(function(data) { window.location.href = '/pages/' + data.id; })
|
||||
.catch(function(err) {
|
||||
if (window.appState && window.appState.toast) window.appState.toast('Failed to create page: ' + err.message, 'error');
|
||||
else alert('Failed to create page: ' + err.message);
|
||||
});
|
||||
},
|
||||
|
||||
/** Show the global New Folder modal. */
|
||||
showCreateFolderModal: function() {
|
||||
var modal = document.getElementById('fd-global-folder-modal');
|
||||
if (!modal) return;
|
||||
modal.style.display = 'flex';
|
||||
var input = document.getElementById('fd-global-folder-input');
|
||||
if (input) { input.value = ''; setTimeout(function() { input.focus(); }, 100); }
|
||||
},
|
||||
|
||||
/** Called by the global New Folder modal's Create button. */
|
||||
_confirmCreateFolder: function() {
|
||||
var input = document.getElementById('fd-global-folder-input');
|
||||
var name = (input && input.value || '').trim();
|
||||
if (!name) return;
|
||||
var modal = document.getElementById('fd-global-folder-modal');
|
||||
if (modal) modal.style.display = 'none';
|
||||
var self = this;
|
||||
fetch('/api/local-workspace/items', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() },
|
||||
body: JSON.stringify({ name: name, type: 'folder' })
|
||||
})
|
||||
.then(function(r) { if (!r.ok) throw new Error('Failed'); return r.json(); })
|
||||
.then(function() {
|
||||
// Refresh sidebar tree
|
||||
if (window.appState && window.appState.refreshSidebarTree) window.appState.refreshSidebarTree();
|
||||
// Notify workspace page
|
||||
document.dispatchEvent(new CustomEvent('flowdeck:workspace-changed'));
|
||||
if (window._wsData && window._wsData._reloadAfterAction) window._wsData._reloadAfterAction();
|
||||
// Show toast
|
||||
if (window.appState && window.appState.toast) window.appState.toast('Folder created', 'success');
|
||||
})
|
||||
.catch(function(err) {
|
||||
if (window.appState && window.appState.toast) window.appState.toast('Failed: ' + err.message, 'error');
|
||||
else alert('Failed to create folder: ' + err.message);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function appState() {
|
||||
return {
|
||||
init() {
|
||||
@@ -1164,8 +1228,7 @@
|
||||
|
||||
if (e.ctrlKey && e.key === 'n') {
|
||||
e.preventDefault();
|
||||
if (data && data.newPageInWorkspace) data.newPageInWorkspace();
|
||||
else if (data && data.newPage) data.newPage('Private');
|
||||
window.FlowDeck.createPage();
|
||||
}
|
||||
else if (e.key === 'Enter' && !editable) {
|
||||
var activeSidebar = document.querySelector('.sidebar-item.active');
|
||||
@@ -1237,5 +1300,23 @@
|
||||
.flowdeck-modal-btn.confirm:hover{background:#2C8CEB;}
|
||||
</style>
|
||||
|
||||
<!-- Global New Folder Modal -->
|
||||
<div id="fd-global-folder-modal" class="flowdeck-modal-overlay" style="display:none" onclick="if(event.target===this)this.style.display='none'">
|
||||
<div class="flowdeck-modal">
|
||||
<div class="flowdeck-modal-header">
|
||||
<h3>📁 New Folder</h3>
|
||||
<button class="flowdeck-modal-close" onclick="document.getElementById('fd-global-folder-modal').style.display='none'">×</button>
|
||||
</div>
|
||||
<div class="flowdeck-modal-body">
|
||||
<p>Enter a name for the new folder.</p>
|
||||
<input class="flowdeck-modal-input" id="fd-global-folder-input" type="text" placeholder="Folder name" onkeydown="if(event.key==='Enter')window.FlowDeck._confirmCreateFolder()">
|
||||
</div>
|
||||
<div class="flowdeck-modal-footer">
|
||||
<button class="flowdeck-modal-btn cancel" onclick="document.getElementById('fd-global-folder-modal').style.display='none'">Cancel</button>
|
||||
<button class="flowdeck-modal-btn confirm" onclick="window.FlowDeck._confirmCreateFolder()">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user