diff --git a/memento-note/components/rich-text-editor.tsx b/memento-note/components/rich-text-editor.tsx index 78167bb..e66fa8b 100644 --- a/memento-note/components/rich-text-editor.tsx +++ b/memento-note/components/rich-text-editor.tsx @@ -33,6 +33,7 @@ import { FindReplaceBar, FindReplaceExtension } from './editor-find-replace-bar' import { LinkPreviewExtension, insertLinkPreview, isUrl } from './tiptap-link-preview-extension' import { MathEquationExtension, InlineMathExtension, insertMathEquation } from './tiptap-math-extension' import { ColumnsExtension, ColumnNode, insertColumnsBlock } from './tiptap-columns-extension' +import { SubPageExtension, insertSubPageBlock } from './tiptap-subpage-extension' import { RtlPreserveExtension } from './tiptap-rtl-preserve-extension' import { ClipArticleExtension } from './tiptap-clip-article-extension' import { BlockPicker, type BlockSuggestion } from './block-picker' @@ -69,7 +70,7 @@ import { FileText, Pilcrow, MessageSquare, AlignLeft, AlignCenter, AlignRight, Superscript as SuperscriptIcon, Subscript as SubscriptIcon, Expand, Plus, SpellCheck, Languages, BookOpen, Presentation, BarChart3, Database, - ChevronsRightLeft, MessageSquareWarning, ListTree, FunctionSquare, Columns3, Loader2 + ChevronsRightLeft, MessageSquareWarning, ListTree, FunctionSquare, Columns3, Loader2, FileOutput } from 'lucide-react' import { cn } from '@/lib/utils' import { toast } from 'sonner' @@ -241,6 +242,10 @@ const slashCommands: SlashItem[] = [ { title: 'Écrire avec l\'IA', description: 'Générer du contenu au curseur', icon: Sparkles, category: 'IA Note', isAi: true, aiOption: 'write', command: () => { } }, + { + title: 'Sub-page', description: 'Create a linked sub-page', icon: FileOutput, category: 'Basic blocks', shortcut: '/page', + command: () => { } + }, ] async function aiReformulate(text: string, option: string, t: any, language?: string): Promise { @@ -492,6 +497,7 @@ export const RichTextEditor = forwardRef { + const { t } = useLanguage() + const router = useRouter() + const noteId = node.attrs.noteId as string + const title = (node.attrs.title as string) || t('notes.untitled') || 'Sans titre' + + const open = () => { + if (noteId) router.push(`/home?openNote=${noteId}`) + } + + return ( + +
+
+ +
+
+
{title}
+
Sous-page
+
+ + +
+
+ ) +} + +export const SubPageExtension = Node.create({ + name: 'subPageBlock', + group: 'block', + atom: true, + defining: true, + + addAttributes() { + return { + noteId: { + default: '', + parseHTML: (el) => el.getAttribute('data-note-id') || '', + renderHTML: (attrs) => ({ 'data-note-id': attrs.noteId }), + }, + title: { + default: '', + parseHTML: (el) => el.getAttribute('data-title') || '', + renderHTML: (attrs) => ({ 'data-title': attrs.title }), + }, + } + }, + + parseHTML() { + return [{ tag: 'div[data-type="sub-page-block"]' }] + }, + + renderHTML({ node, HTMLAttributes }) { + return [ + 'div', + mergeAttributes(HTMLAttributes, { + 'data-type': 'sub-page-block', + 'data-note-id': node.attrs.noteId, + 'data-title': node.attrs.title, + class: 'sub-page-block', + }), + ] + }, + + addNodeView() { + return ReactNodeViewRenderer(SubPageView) + }, + + addKeyboardShortcuts() { + return { + 'Mod-Shift-P': () => this.editor.commands.insertContent({ + type: this.name, + attrs: { noteId: '', title: '' }, + }), + } + }, +}) + +export async function insertSubPageBlock(editor: any): Promise { + const notebookId = (editor.storage as any).structuredViewBlock?.notebookId as string | null + + try { + const res = await fetch('/api/notes', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + title: 'Sans titre', + content: '

', + notebookId: notebookId || undefined, + }), + }) + const data = await res.json() + + if (!res.ok || !data.data) return + + const note = data.data + editor.chain().focus().insertContent({ + type: 'subPageBlock', + attrs: { + noteId: note.id, + title: note.title || 'Sans titre', + }, + }).run() + } catch (e) { + console.error('[SubPage] Failed to create note:', e) + } +} diff --git a/memento-note/locales/en.json b/memento-note/locales/en.json index 207eecf..07002c5 100644 --- a/memento-note/locales/en.json +++ b/memento-note/locales/en.json @@ -2563,6 +2563,8 @@ "slashAiWriter": "Write with AI", "slashAiWriterDesc": "Generate content at cursor", "aiWriterPlaceholder": "Describe what you want to write...", + "slashSubPage": "Sub-page", + "slashSubPageDesc": "Create a linked note inside this note", "exercisesLoading": "Generating exercises...", "exercisesGenerated": "exercises created!", "aiGenerateExercises": "Generate exercises", diff --git a/memento-note/locales/fr.json b/memento-note/locales/fr.json index 007fb87..c5daf78 100644 --- a/memento-note/locales/fr.json +++ b/memento-note/locales/fr.json @@ -2567,6 +2567,8 @@ "slashAiWriter": "Écrire avec l'IA", "slashAiWriterDesc": "Générer du contenu au curseur", "aiWriterPlaceholder": "Décris ce que tu veux écrire...", + "slashSubPage": "Sous-page", + "slashSubPageDesc": "Créer une note liée dans cette note", "exercisesLoading": "Génération des exercices...", "exercisesGenerated": "exercices créés !", "aiGenerateExercises": "Générer des exercices",