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, useMemo, useRef, useCallback, useEffect } from 'react'
|
||||
import React, { useState, useMemo, useRef, useCallback, useEffect } from 'react'
|
||||
import { motion } from 'motion/react'
|
||||
import {
|
||||
ArrowLeft,
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
BookOpen,
|
||||
LifeBuoy,
|
||||
} from 'lucide-react'
|
||||
import { HierarchicalNotebookSelector } from '@/components/hierarchical-notebook-selector'
|
||||
import { toast } from 'sonner'
|
||||
import { useLanguage } from '@/lib/i18n'
|
||||
import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip'
|
||||
@@ -488,21 +489,12 @@ export function AgentDetailView({
|
||||
{showSourceNotebook && (
|
||||
<div className="space-y-4">
|
||||
<label className={labelCls}>{t('agents.form.sourceNotebook')}<FieldHelp tooltip={t('agents.help.tooltips.sourceNotebook')} /></label>
|
||||
<select
|
||||
value={sourceNotebookId}
|
||||
onChange={e => { setSourceNotebookId(e.target.value); setSourceNoteIds([]) }}
|
||||
className={selectCls}
|
||||
>
|
||||
<option value="">{t('agents.form.selectNotebook')}</option>
|
||||
{notebooks.filter(nb => !nb.parentId).map(nb => (
|
||||
<>
|
||||
<option key={nb.id} value={nb.id}>{nb.name}</option>
|
||||
{notebooks.filter(c => c.parentId === nb.id).map(child => (
|
||||
<option key={child.id} value={child.id}> └ {child.name}</option>
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
</select>
|
||||
<HierarchicalNotebookSelector
|
||||
notebooks={notebooks.filter((nb: any) => !nb.trashedAt)}
|
||||
selectedId={sourceNotebookId || null}
|
||||
onSelect={(id) => { setSourceNotebookId(id); setSourceNoteIds([]) }}
|
||||
placeholder={t('agents.form.selectNotebook') || 'Select notebook...'}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -648,17 +640,12 @@ export function AgentDetailView({
|
||||
{type !== 'slide-generator' && type !== 'excalidraw-generator' && (
|
||||
<div className="space-y-4">
|
||||
<label className={labelCls}>{t('agents.form.targetNotebook')}<FieldHelp tooltip={t('agents.help.tooltips.targetNotebook')} /></label>
|
||||
<select value={targetNotebookId} onChange={e => setTargetNotebookId(e.target.value)} className={selectCls}>
|
||||
<option value="">{t('agents.form.inbox')}</option>
|
||||
{notebooks.filter(nb => !nb.parentId).map(nb => (
|
||||
<>
|
||||
<option key={nb.id} value={nb.id}>{nb.name}</option>
|
||||
{notebooks.filter(c => c.parentId === nb.id).map(child => (
|
||||
<option key={child.id} value={child.id}> └ {child.name}</option>
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
</select>
|
||||
<HierarchicalNotebookSelector
|
||||
notebooks={notebooks.filter((nb: any) => !nb.trashedAt)}
|
||||
selectedId={targetNotebookId || null}
|
||||
onSelect={(id) => setTargetNotebookId(id)}
|
||||
placeholder={t('agents.form.inbox') || 'Inbox'}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user