feat(workspace,editor): creation dans le dossier courant + sync live du titre (sidebar/header)
- creation fichier/dossier a la racine du dossier courant ou d'un dossier cible (context-menu, boutons de survol) via createPage/showCreateFolderModal(parentId)
- instances de modeles en tant qu'enfant d'un dossier (parent_id) ; nom vide -> 'Untitled'
- sidebar de la librairie rafraichi apres delete/move/duplicate/rename (_syncSidebar)
- editeur: le titre se synchronise en direct dans le sidebar, le breadcrumb et l'onglet (pages et fichiers) et persiste via PUT /board/api/pages/{id}
This commit is contained in:
+15
-4
@@ -292,6 +292,12 @@ async def use_page_template(request: Request, template_id: int):
|
|||||||
body_ws = (body.get("workspace") or "").strip()
|
body_ws = (body.get("workspace") or "").strip()
|
||||||
if body_ws:
|
if body_ws:
|
||||||
ws_key = body_ws
|
ws_key = body_ws
|
||||||
|
# Optional target folder: instantiate the template as a child of it.
|
||||||
|
parent_id = body.get("parent_id")
|
||||||
|
try:
|
||||||
|
parent_id = int(parent_id) if parent_id not in (None, "", 0, "0") else None
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
parent_id = None
|
||||||
try:
|
try:
|
||||||
parsed_blocks = json.loads(blocks_json)
|
parsed_blocks = json.loads(blocks_json)
|
||||||
except (json.JSONDecodeError, TypeError):
|
except (json.JSONDecodeError, TypeError):
|
||||||
@@ -299,7 +305,12 @@ async def use_page_template(request: Request, template_id: int):
|
|||||||
_ensure_block_ids(parsed_blocks)
|
_ensure_block_ids(parsed_blocks)
|
||||||
blocks_json = json.dumps(parsed_blocks)
|
blocks_json = json.dumps(parsed_blocks)
|
||||||
with get_conn() as conn:
|
with get_conn() as conn:
|
||||||
if ws_id is not None:
|
if parent_id is not None:
|
||||||
|
next_order = conn.execute(
|
||||||
|
"SELECT COALESCE(MAX(sort_order), -1) + 1 FROM pages WHERE parent_id=?",
|
||||||
|
(parent_id,),
|
||||||
|
).fetchone()[0]
|
||||||
|
elif ws_id is not None:
|
||||||
next_order = conn.execute(
|
next_order = conn.execute(
|
||||||
"SELECT COALESCE(MAX(sort_order), -1) + 1 FROM pages WHERE workspace_id=? AND parent_id IS NULL",
|
"SELECT COALESCE(MAX(sort_order), -1) + 1 FROM pages WHERE workspace_id=? AND parent_id IS NULL",
|
||||||
(ws_id,),
|
(ws_id,),
|
||||||
@@ -310,9 +321,9 @@ async def use_page_template(request: Request, template_id: int):
|
|||||||
(ws_key,),
|
(ws_key,),
|
||||||
).fetchone()[0]
|
).fetchone()[0]
|
||||||
cur = conn.execute(
|
cur = conn.execute(
|
||||||
"""INSERT INTO pages (workspace, workspace_id, title, content, content_format, parent_section, sort_order)
|
"""INSERT INTO pages (workspace, workspace_id, title, content, content_format, parent_section, parent_id, sort_order)
|
||||||
VALUES (?,?,?,?,?, 'Private', ?)""",
|
VALUES (?,?,?,?,?, 'Private', ?, ?)""",
|
||||||
(ws_key, ws_id, title or name, blocks_json, "blocks", next_order),
|
(ws_key, ws_id, title or name, blocks_json, "blocks", parent_id, next_order),
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
page_id = cur.lastrowid
|
page_id = cur.lastrowid
|
||||||
|
|||||||
@@ -1352,7 +1352,7 @@ async def nav_menu(request: Request, workspace_id: int = None, parent_id: int =
|
|||||||
async def create_local_workspace_item(request: Request):
|
async def create_local_workspace_item(request: Request):
|
||||||
"""Create a new file in the active workspace."""
|
"""Create a new file in the active workspace."""
|
||||||
body = await request.json()
|
body = await request.json()
|
||||||
name = body.get("name", "Untitled").strip()
|
name = (body.get("name") or "").strip() or "Untitled"
|
||||||
item_type = body.get("type", "page")
|
item_type = body.get("type", "page")
|
||||||
parent_id = body.get("parent_id")
|
parent_id = body.get("parent_id")
|
||||||
explicit_ws_id = body.get("workspace_id")
|
explicit_ws_id = body.get("workspace_id")
|
||||||
|
|||||||
@@ -168,6 +168,16 @@ document.addEventListener('alpine:init', function () {
|
|||||||
this.wsId = d.workspace_id || 0;
|
this.wsId = d.workspace_id || 0;
|
||||||
} catch (e) { this.crumbs = []; }
|
} catch (e) { this.crumbs = []; }
|
||||||
}
|
}
|
||||||
|
// Keep the breadcrumb in sync when the open page is renamed in the editor.
|
||||||
|
var self = this;
|
||||||
|
window.addEventListener('flowdeck:page-renamed', function (e) {
|
||||||
|
var d = e && e.detail;
|
||||||
|
if (!d || d.id == null) return;
|
||||||
|
var id = String(d.id);
|
||||||
|
self.crumbs = self.crumbs.map(function (c) {
|
||||||
|
return String(c.id) === id ? Object.assign({}, c, { label: d.title || 'Untitled' }) : c;
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
get display() {
|
get display() {
|
||||||
|
|||||||
@@ -2274,16 +2274,45 @@ applyAIBlocks(text){
|
|||||||
setTimeout(()=>{const fe=this.getEl(focusId);if(fe){fe.focus();ce(fe);}},60);
|
setTimeout(()=>{const fe=this.getEl(focusId);if(fe){fe.focus();ce(fe);}},60);
|
||||||
},
|
},
|
||||||
autoSave(){if(this.fileData)return;clearTimeout(this.st);this.st=setTimeout(()=>this.save(),1500);},
|
autoSave(){if(this.fileData)return;clearTimeout(this.st);this.st=setTimeout(()=>this.save(),1500);},
|
||||||
|
// Reflect the page title in the left navigation, the header breadcrumb
|
||||||
|
// and the browser tab as soon as it changes.
|
||||||
|
_syncTitleUI(){
|
||||||
|
const title=(this.pageTitle||'').trim()||'Untitled';
|
||||||
|
document.querySelectorAll(`.sidebar-item[data-page-id="page/${this.pid}"]`).forEach(item=>{const n=item.querySelector('.page-name');if(n)n.textContent=title;});
|
||||||
|
document.querySelectorAll(`.sidebar-item.ws-tree-item[data-id="${this.pid}"]`).forEach(item=>{item.setAttribute('data-name',title);const n=item.querySelector('.page-name');if(n)n.textContent=title;});
|
||||||
|
document.title='FlowDeck — '+title;
|
||||||
|
window.dispatchEvent(new CustomEvent('flowdeck:page-renamed',{detail:{id:this.pid,title:title}}));
|
||||||
|
if(window.parent&&window.parent!==window){try{window.parent.postMessage({type:'fd-page-renamed',id:this.pid,title:title},window.location.origin);}catch(e){}}
|
||||||
|
},
|
||||||
save(cb){
|
save(cb){
|
||||||
if(this.fileData)return;
|
if(this.fileData){
|
||||||
|
// File page: only the title is editable here. Sync the sidebar,
|
||||||
|
// header breadcrumb and browser tab live, and persist the title
|
||||||
|
// without rewriting the file's blocks.
|
||||||
|
const t=document.getElementById('_titleEl');if(t)this.pageTitle=t.textContent?.trim()||'';
|
||||||
|
this._syncTitleUI();
|
||||||
|
if(this._fileTitleT)clearTimeout(this._fileTitleT);
|
||||||
|
this._fileTitleT=setTimeout(()=>{
|
||||||
|
this._fileTitleT=null;
|
||||||
|
const title=(this.pageTitle||'').trim();
|
||||||
|
if(!title)return;
|
||||||
|
const csrf=document.cookie.match(/csrf_token=([^;]+)/);
|
||||||
|
fetch(`/board/api/pages/${this.pid}?title=${encodeURIComponent(title)}`,{method:'PUT',headers:{'X-CSRF-Token':csrf?csrf[1]:''}})
|
||||||
|
.then(()=>{this.dirty=false;})
|
||||||
|
.catch(()=>{});
|
||||||
|
},600);
|
||||||
|
if(cb)cb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const t=document.getElementById('_titleEl');if(t)this.pageTitle=t.textContent?.trim()||'';
|
||||||
|
this._syncTitleUI();
|
||||||
if(this.saving){ if(cb) cb(); return; }
|
if(this.saving){ if(cb) cb(); return; }
|
||||||
this.sync();
|
this.sync();
|
||||||
const t=document.getElementById('_titleEl');if(t)this.pageTitle=t.textContent?.trim()||'';
|
|
||||||
this.saving=true;
|
this.saving=true;
|
||||||
const csrf=document.cookie.match(/csrf_token=([^;]+)/);
|
const csrf=document.cookie.match(/csrf_token=([^;]+)/);
|
||||||
fetch(`/board/api/pages/${this.pid}/blocks`,{method:'POST',headers:{'Content-Type':'application/json','X-CSRF-Token':csrf?csrf[1]:''},body:JSON.stringify({title:this.pageTitle,blocks:this.blocks.map(b=>{const c={id:b.id,type:b.type,content:b.content};['checked','expanded','language','icon','src','embed_src','embed_provider','alt','style','embed_type','collection_id','dbs','file_name','file_size','file_mime','children','rows','align','has_header','first_col_header','colsW','meeting','automation_id','automation_name'].forEach(k=>{if(b[k]!=null)c[k]=b[k];});return c;})})})
|
fetch(`/board/api/pages/${this.pid}/blocks`,{method:'POST',headers:{'Content-Type':'application/json','X-CSRF-Token':csrf?csrf[1]:''},body:JSON.stringify({title:this.pageTitle,blocks:this.blocks.map(b=>{const c={id:b.id,type:b.type,content:b.content};['checked','expanded','language','icon','src','embed_src','embed_provider','alt','style','embed_type','collection_id','dbs','file_name','file_size','file_mime','children','rows','align','has_header','first_col_header','colsW','meeting','automation_id','automation_name'].forEach(k=>{if(b[k]!=null)c[k]=b[k];});return c;})})})
|
||||||
.then(r=>r.json()).then(()=>{this.saving=false;this.dirty=false;this.lastSaved=new Date().toLocaleTimeString();
|
.then(r=>r.json()).then(()=>{this.saving=false;this.dirty=false;this.lastSaved=new Date().toLocaleTimeString();
|
||||||
document.querySelectorAll(`.sidebar-item[data-page-id="page/${this.pid}"]`).forEach(item=>{const n=item.querySelector('.page-name');if(n)n.textContent=this.pageTitle||'New page';});
|
this._syncTitleUI();
|
||||||
if(cb)cb();
|
if(cb)cb();
|
||||||
}).catch(()=>{this.saving=false;});
|
}).catch(()=>{this.saving=false;});
|
||||||
},
|
},
|
||||||
|
|||||||
+22
-3
@@ -897,6 +897,15 @@
|
|||||||
return { wsId: 0, isGitea: false, workspaceKey: wk };
|
return { wsId: 0, isGitea: false, workspaceKey: wk };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** Folder currently open on the local-workspace page (0 when at root). */
|
||||||
|
_currentFolderId: function() {
|
||||||
|
var ws = window._wsData;
|
||||||
|
if (ws && typeof ws.currentFolder === 'number' && ws.currentFolder > 0) {
|
||||||
|
return ws.currentFolder;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
|
||||||
/** Return a toast function that works across pages. */
|
/** Return a toast function that works across pages. */
|
||||||
_toast: function(msg, type) {
|
_toast: function(msg, type) {
|
||||||
if (window.appState && window.appState.toast) window.appState.toast(msg, type);
|
if (window.appState && window.appState.toast) window.appState.toast(msg, type);
|
||||||
@@ -907,14 +916,19 @@
|
|||||||
* Create a new page: opens the v5.12.0 template picker (built-in + the
|
* Create a new page: opens the v5.12.0 template picker (built-in + the
|
||||||
* user's saved templates), then instantiates the chosen one.
|
* user's saved templates), then instantiates the chosen one.
|
||||||
*/
|
*/
|
||||||
createPage: function() {
|
createPage: function(parentId) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
// Explicit folder (row/context-menu button) wins; otherwise create in the
|
||||||
|
// folder the user is currently browsing on the local-workspace page.
|
||||||
|
if (parentId == null || parentId === '') parentId = this._currentFolderId();
|
||||||
|
this._createParentId = parentId || 0;
|
||||||
// Direct creation path (fallback / no-template choice).
|
// Direct creation path (fallback / no-template choice).
|
||||||
this._createPlainPage = function() {
|
this._createPlainPage = function() {
|
||||||
var ctx = self._getContext();
|
var ctx = self._getContext();
|
||||||
if (ctx.wsId > 0) {
|
if (ctx.wsId > 0) {
|
||||||
var body = { name: '', type: 'page' };
|
var body = { name: '', type: 'page' };
|
||||||
if (ctx.isGitea) body.workspace_id = ctx.wsId;
|
if (ctx.isGitea) body.workspace_id = ctx.wsId;
|
||||||
|
if (self._createParentId) body.parent_id = self._createParentId;
|
||||||
fetch('/api/local-workspace/items', {
|
fetch('/api/local-workspace/items', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.getCsrfToken() },
|
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': self.getCsrfToken() },
|
||||||
@@ -986,6 +1000,7 @@
|
|||||||
var ctx = self._getContext();
|
var ctx = self._getContext();
|
||||||
if (ctx.wsId > 0) { body.workspace_id = ctx.wsId; }
|
if (ctx.wsId > 0) { body.workspace_id = ctx.wsId; }
|
||||||
else if (ctx.workspaceKey) { body.workspace = ctx.workspaceKey; }
|
else if (ctx.workspaceKey) { body.workspace = ctx.workspaceKey; }
|
||||||
|
if (self._createParentId) { body.parent_id = self._createParentId; }
|
||||||
if (parts[0] === 'key') { body.key = parts.slice(1).join(':'); url = '/board/api/page-templates/0/use'; }
|
if (parts[0] === 'key') { body.key = parts.slice(1).join(':'); url = '/board/api/page-templates/0/use'; }
|
||||||
else { url = '/board/api/page-templates/' + parts[1] + '/use'; }
|
else { url = '/board/api/page-templates/' + parts[1] + '/use'; }
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
@@ -999,8 +1014,10 @@
|
|||||||
.catch(function(){ self._createPlainPage(); });
|
.catch(function(){ self._createPlainPage(); });
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Show the global New Folder modal. */
|
/** Show the global New Folder modal (parentId = target folder, optional). */
|
||||||
showCreateFolderModal: function() {
|
showCreateFolderModal: function(parentId) {
|
||||||
|
if (parentId == null || parentId === '') parentId = this._currentFolderId();
|
||||||
|
this._folderParentId = parentId || 0;
|
||||||
var modal = document.getElementById('fd-global-folder-modal');
|
var modal = document.getElementById('fd-global-folder-modal');
|
||||||
if (!modal) return;
|
if (!modal) return;
|
||||||
modal.style.display = 'flex';
|
modal.style.display = 'flex';
|
||||||
@@ -1019,6 +1036,8 @@
|
|||||||
var ctx = this._getContext();
|
var ctx = this._getContext();
|
||||||
var body = { name: name, type: 'folder' };
|
var body = { name: name, type: 'folder' };
|
||||||
if (ctx.wsId > 0 && ctx.isGitea) body.workspace_id = ctx.wsId;
|
if (ctx.wsId > 0 && ctx.isGitea) body.workspace_id = ctx.wsId;
|
||||||
|
if (this._folderParentId) body.parent_id = this._folderParentId;
|
||||||
|
this._folderParentId = 0;
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
fetch('/api/local-workspace/items', {
|
fetch('/api/local-workspace/items', {
|
||||||
|
|||||||
@@ -824,6 +824,11 @@ function libraryPage() {
|
|||||||
return m ? m[1] : '';
|
return m ? m[1] : '';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_syncSidebar() {
|
||||||
|
if (window.appState && window.appState.refreshSidebarTree) window.appState.refreshSidebarTree();
|
||||||
|
if (window.appState && window.appState.refreshFavorites) window.appState.refreshFavorites();
|
||||||
|
},
|
||||||
|
|
||||||
_isDescendant(node, targetId) {
|
_isDescendant(node, targetId) {
|
||||||
if (!node || !node.children) return false;
|
if (!node || !node.children) return false;
|
||||||
for (var i = 0; i < node.children.length; i++) {
|
for (var i = 0; i < node.children.length; i++) {
|
||||||
@@ -846,6 +851,7 @@ function libraryPage() {
|
|||||||
}
|
}
|
||||||
this.clearSelection();
|
this.clearSelection();
|
||||||
this.loadTab();
|
this.loadTab();
|
||||||
|
this._syncSidebar();
|
||||||
},
|
},
|
||||||
|
|
||||||
// ── Empty states ──
|
// ── Empty states ──
|
||||||
@@ -1088,6 +1094,7 @@ function libraryPage() {
|
|||||||
}
|
}
|
||||||
this.clearSelection();
|
this.clearSelection();
|
||||||
this.loadTab();
|
this.loadTab();
|
||||||
|
this._syncSidebar();
|
||||||
if (window.showToast) window.showToast('Moved to trash', 'success');
|
if (window.showToast) window.showToast('Moved to trash', 'success');
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1097,6 +1104,7 @@ function libraryPage() {
|
|||||||
var csrf = this._getCsrf();
|
var csrf = this._getCsrf();
|
||||||
await fetch('/board/api/pages/' + item.id, {method:'DELETE', headers:{'X-CSRF-Token': csrf}});
|
await fetch('/board/api/pages/' + item.id, {method:'DELETE', headers:{'X-CSRF-Token': csrf}});
|
||||||
this.loadTab();
|
this.loadTab();
|
||||||
|
this._syncSidebar();
|
||||||
if (window.showToast) window.showToast('Moved to trash', 'success');
|
if (window.showToast) window.showToast('Moved to trash', 'success');
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1257,6 +1265,7 @@ function libraryPage() {
|
|||||||
await fetch(updUrl, { method: 'PUT', headers: {'X-CSRF-Token': csrf} });
|
await fetch(updUrl, { method: 'PUT', headers: {'X-CSRF-Token': csrf} });
|
||||||
}
|
}
|
||||||
this.loadTab();
|
this.loadTab();
|
||||||
|
this._syncSidebar();
|
||||||
if (window.showToast) window.showToast('Page duplicated', 'success');
|
if (window.showToast) window.showToast('Page duplicated', 'success');
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (window.showToast) window.showToast('Failed to duplicate page', 'error');
|
if (window.showToast) window.showToast('Failed to duplicate page', 'error');
|
||||||
@@ -1332,6 +1341,7 @@ function libraryPage() {
|
|||||||
}
|
}
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
this._renderTable();
|
this._renderTable();
|
||||||
|
this._syncSidebar();
|
||||||
},
|
},
|
||||||
|
|
||||||
// ── Add new ──
|
// ── Add new ──
|
||||||
@@ -1423,6 +1433,7 @@ function libraryPage() {
|
|||||||
await fetch('/board/api/pages/' + this.peekItem.id, {method:'DELETE', headers:{'X-CSRF-Token': csrf}});
|
await fetch('/board/api/pages/' + this.peekItem.id, {method:'DELETE', headers:{'X-CSRF-Token': csrf}});
|
||||||
this.closePeek();
|
this.closePeek();
|
||||||
this.loadTab();
|
this.loadTab();
|
||||||
|
this._syncSidebar();
|
||||||
if (window.showToast) window.showToast('Moved to trash', 'success');
|
if (window.showToast) window.showToast('Moved to trash', 'success');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -648,6 +648,19 @@ window._wsInitData = (function() {
|
|||||||
var self = this;
|
var self = this;
|
||||||
window.addEventListener('online', function() { self.online = true; });
|
window.addEventListener('online', function() { self.online = true; });
|
||||||
window.addEventListener('offline', function() { self.online = false; });
|
window.addEventListener('offline', function() { self.online = false; });
|
||||||
|
// Side-peek editor posts renames here so the tree/peek title stay in sync.
|
||||||
|
window.addEventListener('message', function(ev) {
|
||||||
|
if (ev.origin !== window.location.origin) return;
|
||||||
|
var m = ev.data;
|
||||||
|
if (!m || m.type !== 'fd-page-renamed' || m.id == null) return;
|
||||||
|
var node = self._findNodeById(self.tree, m.id);
|
||||||
|
if (node) node.name = m.title || 'Untitled';
|
||||||
|
self.displayTree = self.displayTree.slice();
|
||||||
|
var t = document.getElementById('ws-preview-title');
|
||||||
|
if (t && self.previewItem && self.previewItem.id === m.id) t.textContent = m.title || 'Untitled';
|
||||||
|
var side = document.querySelector('.sidebar-item.ws-tree-item[data-id="' + m.id + '"] .page-name');
|
||||||
|
if (side) side.textContent = m.title || 'Untitled';
|
||||||
|
});
|
||||||
// Load workspace tags
|
// Load workspace tags
|
||||||
this.loadWorkspaceTags();
|
this.loadWorkspaceTags();
|
||||||
} catch(e) { console.error('Tree load error:', e); this.loaded = true; }
|
} catch(e) { console.error('Tree load error:', e); this.loaded = true; }
|
||||||
@@ -864,6 +877,7 @@ window._wsInitData = (function() {
|
|||||||
selectForPreview(node) {
|
selectForPreview(node) {
|
||||||
var panel = document.getElementById('ws-preview-panel');
|
var panel = document.getElementById('ws-preview-panel');
|
||||||
if (!panel) return;
|
if (!panel) return;
|
||||||
|
this.previewItem = node;
|
||||||
document.getElementById('ws-preview-icon').innerHTML = this._fileIcon(node.name, node.is_folder, node.content_format, node.page_icon);
|
document.getElementById('ws-preview-icon').innerHTML = this._fileIcon(node.name, node.is_folder, node.content_format, node.page_icon);
|
||||||
document.getElementById('ws-preview-title').textContent = node.name;
|
document.getElementById('ws-preview-title').textContent = node.name;
|
||||||
var openBtn = document.getElementById('ws-preview-open-btn');
|
var openBtn = document.getElementById('ws-preview-open-btn');
|
||||||
@@ -1360,10 +1374,10 @@ window._wsInitData = (function() {
|
|||||||
|
|
||||||
switch(action) {
|
switch(action) {
|
||||||
case 'new-file':
|
case 'new-file':
|
||||||
window.FlowDeck.createPage();
|
window.FlowDeck.createPage(id);
|
||||||
break;
|
break;
|
||||||
case 'new-folder':
|
case 'new-folder':
|
||||||
window.FlowDeck.showCreateFolderModal();
|
window.FlowDeck.showCreateFolderModal(id);
|
||||||
break;
|
break;
|
||||||
case 'rename':
|
case 'rename':
|
||||||
this.startRename({db_id: id, name: name});
|
this.startRename({db_id: id, name: name});
|
||||||
@@ -2724,8 +2738,8 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
|||||||
<div class="actions">
|
<div class="actions">
|
||||||
<template x-if="node.is_folder">
|
<template x-if="node.is_folder">
|
||||||
<span style="display:flex;gap:2px">
|
<span style="display:flex;gap:2px">
|
||||||
<button class="ws-act" @click.stop="window.FlowDeck.createPage()" title="New file">{{ fd_icon("file",14) }}</button>
|
<button class="ws-act" @click.stop="window.FlowDeck.createPage(node.id)" title="New file">{{ fd_icon("file",14) }}</button>
|
||||||
<button class="ws-act" @click.stop="window.FlowDeck.showCreateFolderModal()" title="New folder">{{ fd_icon("folder",14) }}</button>
|
<button class="ws-act" @click.stop="window.FlowDeck.showCreateFolderModal(node.id)" title="New folder">{{ fd_icon("folder",14) }}</button>
|
||||||
<a class="ws-act" href="/local-workspace" title="Open workspace page" style="text-decoration:none;display:inline-flex;align-items:center;">{{ fd_icon("external-link",14) }}</a>
|
<a class="ws-act" href="/local-workspace" title="Open workspace page" style="text-decoration:none;display:inline-flex;align-items:center;">{{ fd_icon("external-link",14) }}</a>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
page_title %}{{ page.title }}{% endblock %} {% block topbar %}
|
page_title %}{{ page.title }}{% endblock %} {% block topbar %}
|
||||||
{% set page_icon = "file" if page.content_format != 'file' else "paperclip" %}
|
{% set page_icon = "file" if page.content_format != 'file' else "paperclip" %}
|
||||||
{% set page_title = page.title %}
|
{% set page_title = page.title %}
|
||||||
|
{% set nav_page_id = page.id %}
|
||||||
{% set right_actions = '<span class="topbar-edited" style="cursor:pointer;" @click="window.E && window.E.toggleActivityOpen()">Edited <span x-text="window.E && window.E.timeAgo || \'\'"></span> ▾</span><button class="topbar-btn" @click="window.E && window.E.toggleComments()" title="Comments"><span class="fd-comment-btn-ico">💬</span><span class="fd-comment-count" x-text="window.E && window.E.commentCount>0 ? window.E.commentCount : \'\'"></span></button><button class="topbar-btn share-btn" @click="window.E && window.E.toggleShareOpen()"><span x-show="!window.E || !window.E.pageIsShared">' ~ fd_icon("lock",14) ~ ' Share ▾</span><span x-show="window.E && window.E.pageIsShared" title="This page is shared">👥 Shared ▾</span></button><button class="topbar-btn" @click="window.E && window.E.copyPageLink()" title="Copy link">' ~ fd_icon("link",14) ~ '</button><button class="topbar-btn star-btn" @click="window.E && window.E.toggleFavorite()" x-html="(window.E && window.E.favorited) ? getSvgIcon(\'star\',14) : getSvgIcon(\'star\',14)"></button><button class="topbar-btn relative" @click="window.E && window.E.toggleMoreOpen()">⋯</button>' %}
|
{% set right_actions = '<span class="topbar-edited" style="cursor:pointer;" @click="window.E && window.E.toggleActivityOpen()">Edited <span x-text="window.E && window.E.timeAgo || \'\'"></span> ▾</span><button class="topbar-btn" @click="window.E && window.E.toggleComments()" title="Comments"><span class="fd-comment-btn-ico">💬</span><span class="fd-comment-count" x-text="window.E && window.E.commentCount>0 ? window.E.commentCount : \'\'"></span></button><button class="topbar-btn share-btn" @click="window.E && window.E.toggleShareOpen()"><span x-show="!window.E || !window.E.pageIsShared">' ~ fd_icon("lock",14) ~ ' Share ▾</span><span x-show="window.E && window.E.pageIsShared" title="This page is shared">👥 Shared ▾</span></button><button class="topbar-btn" @click="window.E && window.E.copyPageLink()" title="Copy link">' ~ fd_icon("link",14) ~ '</button><button class="topbar-btn star-btn" @click="window.E && window.E.toggleFavorite()" x-html="(window.E && window.E.favorited) ? getSvgIcon(\'star\',14) : getSvgIcon(\'star\',14)"></button><button class="topbar-btn relative" @click="window.E && window.E.toggleMoreOpen()">⋯</button>' %}
|
||||||
{% include '_header.html' %}
|
{% include '_header.html' %}
|
||||||
{% endblock %} {% block content %}
|
{% endblock %} {% block content %}
|
||||||
|
|||||||
Reference in New Issue
Block a user