feat: hierarchical notebook system - trash, selectors, breadcrumb, sidebar tree
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m9s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m9s
- Schema: soft delete with trashedAt on Notebook model - API: PATCH/GET notebooks support trashedAt filtering with cascade - Sidebar: recursive tree rendering with collapse/expand, visual guides, hover actions - HierarchicalNotebookSelector: portal-based dropdown with search, breadcrumbs, dropUp support - AI chat: context selector with Toutes mes notes + notebook selector - Agent detail: flat selects replaced with HierarchicalNotebookSelector - Breadcrumb: notebook path display on home page - Trash view: card grid with countdown, restore/permanent delete - CSS: design tokens (ink, paper, blueprint, concrete, etc.) - Types: parentId, trashedAt added to Notebook interface
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect, useCallback, useRef, useTransition, useMemo } from 'react'
|
||||
import React, { useState, useEffect, useCallback, useRef, useTransition, useMemo } from 'react'
|
||||
import { useSearchParams, useRouter } from 'next/navigation'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Note } from '@/lib/types'
|
||||
@@ -11,7 +11,7 @@ import { NotesEditorialView } from '@/components/notes-editorial-view'
|
||||
import { MemoryEchoNotification } from '@/components/memory-echo-notification'
|
||||
import { NotebookSuggestionToast } from '@/components/notebook-suggestion-toast'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Plus, ArrowUpDown, Search, Sparkles, FileText, FolderOpen } from 'lucide-react'
|
||||
import { Plus, ArrowUpDown, Search, Sparkles, FileText, FolderOpen, ChevronRight } from 'lucide-react'
|
||||
import { useNoteRefresh } from '@/context/NoteRefreshContext'
|
||||
import { useRefresh } from '@/lib/use-refresh'
|
||||
import { useReminderCheck } from '@/hooks/use-reminder-check'
|
||||
@@ -332,6 +332,20 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
|
||||
|
||||
const currentNotebook = notebooks.find((n: any) => n.id === searchParams.get('notebook'))
|
||||
|
||||
const notebookPath = useMemo(() => {
|
||||
if (!currentNotebook) return []
|
||||
const trail: any[] = []
|
||||
let current: any = currentNotebook
|
||||
while (current) {
|
||||
trail.unshift(current)
|
||||
if (!current.parentId) break
|
||||
const parent = notebooks.find((nb: any) => nb.id === current.parentId)
|
||||
if (!parent) break
|
||||
current = parent
|
||||
}
|
||||
return trail
|
||||
}, [currentNotebook, notebooks])
|
||||
|
||||
useEffect(() => {
|
||||
setControls({
|
||||
isTabsMode: notesViewMode === 'tabs',
|
||||
@@ -404,15 +418,29 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
|
||||
isEditorialMode ? 'sticky top-0 bg-memento-paper/90 backdrop-blur-md z-30' : ''
|
||||
)}>
|
||||
<div className="flex justify-between items-start">
|
||||
<h1 className="font-memento-serif text-4xl font-medium tracking-tight text-foreground leading-tight pr-12">
|
||||
{currentNotebook
|
||||
? currentNotebook.name
|
||||
: searchParams.get('shared') === '1'
|
||||
? (t('sidebar.sharedWithMe') || 'Partagées avec moi')
|
||||
: searchParams.get('reminders') === '1'
|
||||
? (t('sidebar.reminders') || 'Rappels')
|
||||
: t('notes.title')}
|
||||
</h1>
|
||||
<div>
|
||||
{currentNotebook && notebookPath.length > 0 && (
|
||||
<div className="flex items-center gap-2 text-base font-semibold mb-1">
|
||||
{notebookPath.map((nb: any, i: number) => (
|
||||
<React.Fragment key={nb.id}>
|
||||
{i > 0 && <ChevronRight size={16} className="text-foreground/40" />}
|
||||
<span className={i === notebookPath.length - 1 ? 'text-foreground' : 'text-foreground/60'}>
|
||||
{nb.name}
|
||||
</span>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<h1 className="font-memento-serif text-4xl font-medium tracking-tight text-foreground leading-tight pr-12">
|
||||
{currentNotebook
|
||||
? currentNotebook.name
|
||||
: searchParams.get('shared') === '1'
|
||||
? (t('sidebar.sharedWithMe') || 'Partagées avec moi')
|
||||
: searchParams.get('reminders') === '1'
|
||||
? (t('sidebar.reminders') || 'Rappels')
|
||||
: t('notes.title')}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between border-b border-foreground/5 pb-4">
|
||||
|
||||
Reference in New Issue
Block a user