- Bloc Link Preview : colle une URL → carte avec titre, description, image, favicon - API /api/link-preview : extraction OpenGraph + meta tags - API /api/image-proxy : contourne le hotlinking (Referer spoofing) - Métadonnées persistées en HTML (data-preview JSON) — pas de refetch au reload - Texte indexable : titre + description + URL inclus pour recherche/embeddings - Modal propre pour saisir l'URL (plus de prompt()) - Slash menu + smart paste 'Coller comme carte aperçu' - i18n FR/EN complet - Fix: bouton calendrier retiré du sélecteur de vue
120 lines
3.2 KiB
TypeScript
120 lines
3.2 KiB
TypeScript
'use client'
|
|
|
|
import { useCallback, useRef } from 'react'
|
|
import type { Note } from '@/lib/types'
|
|
import type { NotebookSchemaPayload, NotePropertyValues, StructuredViewMode } from '@/lib/structured-views/types'
|
|
import { NotesStructuredTable } from './notes-structured-table'
|
|
import { NotesKanbanView } from './notes-kanban-view'
|
|
import { NotesGalleryView } from './notes-gallery-view'
|
|
import { NotesCalendarView } from './notes-calendar-view'
|
|
|
|
type StructuredViewsContainerProps = {
|
|
mode: StructuredViewMode
|
|
notes: Note[]
|
|
schema: NotebookSchemaPayload
|
|
noteValues: Record<string, NotePropertyValues>
|
|
notebookColor?: string | null
|
|
onOpen: (note: Note) => void
|
|
onNoteValuesPatch: (noteId: string, patch: NotePropertyValues) => void
|
|
onCreateNote: (prefill: Record<string, unknown>) => void
|
|
onSetKanbanGroupProperty: (propertyId: string) => void
|
|
onQuickAddKanbanStatus?: () => void
|
|
onDeleteProperty?: (propertyId: string) => Promise<void>
|
|
}
|
|
|
|
export function StructuredViewsContainer({
|
|
mode,
|
|
notes,
|
|
schema,
|
|
noteValues,
|
|
notebookColor,
|
|
onOpen,
|
|
onNoteValuesPatch,
|
|
onCreateNote,
|
|
onSetKanbanGroupProperty,
|
|
onQuickAddKanbanStatus,
|
|
onDeleteProperty,
|
|
}: StructuredViewsContainerProps) {
|
|
const timersRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map())
|
|
|
|
const saveProperty = useCallback(
|
|
(noteId: string, propertyId: string, value: unknown) => {
|
|
onNoteValuesPatch(noteId, { [propertyId]: value })
|
|
const key = `${noteId}:${propertyId}`
|
|
const existing = timersRef.current.get(key)
|
|
if (existing) clearTimeout(existing)
|
|
timersRef.current.set(
|
|
key,
|
|
setTimeout(async () => {
|
|
try {
|
|
await fetch(`/api/notes/${noteId}/properties`, {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ properties: { [propertyId]: value } }),
|
|
})
|
|
} catch (e) {
|
|
console.error(e)
|
|
}
|
|
timersRef.current.delete(key)
|
|
}, 500),
|
|
)
|
|
},
|
|
[onNoteValuesPatch],
|
|
)
|
|
|
|
if (mode === 'table') {
|
|
return (
|
|
<NotesStructuredTable
|
|
notes={notes}
|
|
schema={schema}
|
|
noteValues={noteValues}
|
|
onOpen={onOpen}
|
|
onPropertyChange={saveProperty}
|
|
onDeleteProperty={onDeleteProperty}
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (mode === 'kanban') {
|
|
return (
|
|
<NotesKanbanView
|
|
notes={notes}
|
|
schema={schema}
|
|
noteValues={noteValues}
|
|
onOpen={onOpen}
|
|
onPropertyChange={saveProperty}
|
|
onCreateNote={onCreateNote}
|
|
onSetGroupProperty={onSetKanbanGroupProperty}
|
|
onQuickAddKanbanStatus={onQuickAddKanbanStatus}
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (mode === 'gallery') {
|
|
return (
|
|
<NotesGalleryView
|
|
notes={notes}
|
|
schema={schema}
|
|
noteValues={noteValues}
|
|
notebookColor={notebookColor}
|
|
onOpen={onOpen}
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (mode === 'calendar') {
|
|
return (
|
|
<NotesCalendarView
|
|
notes={notes}
|
|
schema={schema}
|
|
noteValues={noteValues}
|
|
notebookColor={notebookColor}
|
|
onOpen={onOpen}
|
|
onPropertyChange={saveProperty}
|
|
/>
|
|
)
|
|
}
|
|
|
|
return null
|
|
}
|