feat: menu New page (Empty/Database/Kanban) + slash commands / dans l'éditeur
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped

- Topbar bouton New ▾ avec dropdown: Empty page, Database, Kanban board
- page_editor: commandes slash / (/h1, /h2, /list, /todo, /code, /table, /quote...)
- Fonctions JS: createEmptyPage, createDatabase, createBoard
- State showNewPageMenu dans Alpine.js
This commit is contained in:
2026-07-08 15:26:36 -04:00
parent e3180c6255
commit bed326ee9b
2 changed files with 61 additions and 3 deletions
+39 -2
View File
@@ -36,10 +36,11 @@
<div style="padding:4px 12px; background:var(--bg-tertiary); font-size:12px; color:var(--text-dim);">Markdown</div>
<textarea x-ref="editor" x-model="content"
@input="autoSave()"
@keydown="handleSlash($event)"
style="flex:1; width:100%; min-height:400px; background:var(--bg-secondary);
border:none; padding:12px; color:var(--text-primary); font-family:var(--font-mono);
font-size:13px; line-height:1.6; resize:none; outline:none; tab-size:2;"
placeholder="Start writing in Markdown..."></textarea>
placeholder="Type '/' for commands, or start writing in Markdown..."></textarea>
</div>
<!-- Preview -->
<div style="flex:1; border-left:1px solid var(--border); display:flex; flex-direction:column;">
@@ -145,7 +146,43 @@
},
saveTitle(newTitle) {
fetch(`/board/api/pages/{{ page.id }}?title=${encodeURIComponent(newTitle)}`, { method: 'PUT' });
}
},
handleSlash(e) {
if (e.key === '/' && !e.ctrlKey && !e.metaKey) {
const el = this.$refs.editor;
const cursor = el.selectionStart;
const lineStart = this.content.lastIndexOf('\n', cursor - 1) + 1;
const charsBefore = this.content.substring(lineStart, cursor);
// Only trigger at start of line or after whitespace
if (charsBefore.trim() === '') {
e.preventDefault();
this.content = this.content.substring(0, cursor) + '/';
// Simple menu: insert template after short delay
const cmd = prompt('Slash command:\n /h1 - Heading 1\n /h2 - Heading 2\n /h3 - Heading 3\n /bold - Bold\n /list - Bullet list\n /num - Numbered list\n /code - Code block\n /quote - Quote\n /todo - To-do list\n /table - Table\n /divider - Divider\n /link - Link\n /img - Image\n /date - Date');
if (!cmd) { this.content = this.content.substring(0, cursor); return; }
const templates = {
h1: '# ',
h2: '## ',
h3: '### ',
bold: '**bold text**',
list: '- ',
num: '1. ',
code: '```\ncode\n```',
quote: '> ',
todo: '- [ ] ',
table: '| Col 1 | Col 2 |\n|-------|-------|\n| | |',
divider: '---\n',
link: '[text](url)',
img: '![alt](url)',
date: new Date().toISOString().slice(0, 10),
};
const insert = templates[cmd.replace('/','')] || '';
const before = this.content.substring(0, cursor);
this.content = before + insert + this.content.substring(cursor + 1);
setTimeout(() => { el.focus(); el.selectionStart = el.selectionEnd = before.length + insert.length; }, 50);
}
}
},
};
}
</script>