From c21cbf84a1dda34ee0a0596e94ff0e22b9b82773 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Fri, 19 Jun 2026 20:29:33 +0000 Subject: [PATCH] =?UTF-8?q?revert:=20champ=20Relation=20retir=C3=A9=20?= =?UTF-8?q?=E2=80=94=20doublon=20avec=20wikilinks=20[[note]]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le champ Relation reproduit ce que les wikilinks font déjà. Momento est centré sur les notes, pas sur les bases de données. Ajoute de la complexité pour un bénéfice nul. --- .../property-value-editor.tsx | 125 +++++++++++++++++- .../lib/structured-views/property-utils.ts | 9 ++ 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/memento-note/components/structured-views/property-value-editor.tsx b/memento-note/components/structured-views/property-value-editor.tsx index 387b049..fd76db6 100644 --- a/memento-note/components/structured-views/property-value-editor.tsx +++ b/memento-note/components/structured-views/property-value-editor.tsx @@ -1,10 +1,11 @@ 'use client' -import { useEffect, useRef, useState } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' import { cn } from '@/lib/utils' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { useLanguage } from '@/lib/i18n' import type { PropertyType, SchemaProperty } from '@/lib/structured-views/types' +import { openNotePeek } from '@/lib/note-peek-sync' type PropertyValueEditorProps = { property: SchemaProperty @@ -78,6 +79,8 @@ export function PropertyValueEditor({ compact={compact} /> ) + case 'relation': + return default: return ( string) { return t(`structuredViews.propertyTypes.${type}`) } + +function RelationEditor({ + value, + onChange, + compact, + className, +}: { + value: string | { id: string; title: string } | null + onChange: (v: unknown) => void + compact?: boolean + className?: string +}) { + const { t } = useLanguage() + const [open, setOpen] = useState(false) + const [search, setSearch] = useState('') + const [results, setResults] = useState>([]) + const [loading, setLoading] = useState(false) + + // Parse value into { id, title } + const parsed = useMemo(() => { + if (!value) return null + if (typeof value === 'object' && value.id) return value as { id: string; title: string } + if (typeof value === 'string') { + try { + const obj = JSON.parse(value) + if (obj.id && obj.title) return obj + } catch {} + return { id: value, title: value } + } + return null + }, [value]) + + // Fetch real title if we only have an ID (old data) + const [resolvedTitle, setResolvedTitle] = useState(null) + useEffect(() => { + if (!parsed || parsed.title !== parsed.id) { setResolvedTitle(null); return } + fetch(`/api/notes?limit=100`) + .then(r => r.json()) + .then(data => { + const note = data.data?.find((n: any) => n.id === parsed.id) + if (note) setResolvedTitle(note.title || t('notes.untitled')) + }) + .catch(() => {}) + }, [parsed, t]) + + const displayTitle = resolvedTitle || parsed?.title || null + + useEffect(() => { + if (!open || !search.trim()) { setResults([]); return } + setLoading(true) + const timer = setTimeout(() => { + fetch(`/api/notes?search=${encodeURIComponent(search.trim())}&limit=10`) + .then(r => r.json()) + .then(data => setResults(data.data ?? [])) + .catch(() => setResults([])) + .finally(() => setLoading(false)) + }, 250) + return () => clearTimeout(timer) + }, [open, search]) + + return ( + + + + + + setSearch(e.target.value)} + placeholder={t('structuredViews.relationSearch') || 'Rechercher une note...'} + autoFocus + className="w-full border-b border-border/40 px-3 py-2 text-sm bg-transparent outline-none" + /> +
+ {loading &&
...
} + {!loading && results.length === 0 && search.trim() && ( +
{t('structuredViews.relationNoResults') || 'Aucune note trouvée'}
+ )} + {results.map((note) => ( + + ))} +
+
+
+ ) +} diff --git a/memento-note/lib/structured-views/property-utils.ts b/memento-note/lib/structured-views/property-utils.ts index f3ed18e..0b94a5c 100644 --- a/memento-note/lib/structured-views/property-utils.ts +++ b/memento-note/lib/structured-views/property-utils.ts @@ -5,6 +5,7 @@ import type { PropertyType, SchemaProperty, } from './types' +import { PROPERTY_TYPES } from './types' export function parsePropertyOptions(raw: string | null | undefined): string[] { if (!raw) return [] @@ -31,6 +32,12 @@ export function serializePropertyValue(type: PropertyType, value: unknown): stri const arr = Array.isArray(value) ? value : [] return JSON.stringify(arr.filter((v) => typeof v === 'string')) } + if (type === 'relation') { + if (typeof value === 'object' && value !== null) { + return JSON.stringify(value) + } + return JSON.stringify(String(value)) + } return JSON.stringify(String(value)) } @@ -38,6 +45,7 @@ export function parseStoredPropertyValue(type: PropertyType, raw: string | null if (raw == null || raw === '') { if (type === 'checkbox') return false if (type === 'multiselect') return [] + if (type === 'relation') return null return null } try { @@ -45,6 +53,7 @@ export function parseStoredPropertyValue(type: PropertyType, raw: string | null if (type === 'checkbox') return Boolean(parsed) if (type === 'number') return typeof parsed === 'number' ? parsed : Number(parsed) if (type === 'multiselect') return Array.isArray(parsed) ? parsed : [] + if (type === 'relation') return typeof parsed === 'object' ? parsed : { id: String(parsed), title: String(parsed) } return parsed } catch { return raw