feat(notes): liens internes, onglet Réseau, living blocks et consentement IA
Rend les liens entre notes visibles et persistants (sync NoteLink au save, auto-save, graphe réseau rafraîchi), ajoute living blocks, Memory Echo, recherche globale, consentement IA explicite et consolide les prototypes design en architectural-grid. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { Download, Upload, Trash2, Loader2, RefreshCw, Sparkles, Database, ShieldAlert } from 'lucide-react'
|
||||
import { Download, Upload, Trash2, Loader2, RefreshCw, Sparkles, Database, ShieldAlert, FolderArchive } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { useLanguage } from '@/lib/i18n'
|
||||
import { useSession } from 'next-auth/react'
|
||||
@@ -20,6 +20,39 @@ export default function DataSettingsPage() {
|
||||
const [isDeleting, setIsDeleting] = useState(false)
|
||||
const [isReindexing, setIsReindexing] = useState(false)
|
||||
const [isCleaningUp, setIsCleaningUp] = useState(false)
|
||||
const [isZipExporting, setIsZipExporting] = useState(false)
|
||||
|
||||
const handleZipExport = async () => {
|
||||
setIsZipExporting(true)
|
||||
try {
|
||||
const response = await fetch('/api/user/export')
|
||||
if (!response.ok) {
|
||||
let message = t('dataManagement.zipExport.failed')
|
||||
try {
|
||||
const body = (await response.json()) as { error?: string }
|
||||
if (body.error) message = body.error
|
||||
} catch {
|
||||
/* non-JSON error body */
|
||||
}
|
||||
toast.error(message)
|
||||
return
|
||||
}
|
||||
const blob = await response.blob()
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = `memento-workspace-export-${new Date().toISOString().split('T')[0]}.zip`
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
window.URL.revokeObjectURL(url)
|
||||
toast.success(t('dataManagement.zipExport.success'))
|
||||
} catch {
|
||||
toast.error(t('dataManagement.zipExport.failed'))
|
||||
} finally {
|
||||
setIsZipExporting(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleExport = async () => {
|
||||
setIsExporting(true)
|
||||
@@ -135,6 +168,18 @@ export default function DataSettingsPage() {
|
||||
onAction: handleExport,
|
||||
btnClass: 'bg-ink text-paper shadow-xl shadow-ink/20 hover:scale-[1.02] active:scale-95',
|
||||
},
|
||||
{
|
||||
icon: FolderArchive,
|
||||
iconColor: 'text-amber-600 dark:text-amber-400',
|
||||
iconBg: 'bg-amber-500/10 dark:bg-amber-500/20',
|
||||
title: t('dataManagement.zipExport.title'),
|
||||
description: t('dataManagement.zipExport.description'),
|
||||
loading: isZipExporting,
|
||||
loadingText: t('dataManagement.zipExporting'),
|
||||
buttonText: t('dataManagement.zipExport.button'),
|
||||
onAction: handleZipExport,
|
||||
btnClass: 'bg-ink text-paper shadow-xl shadow-ink/20 hover:scale-[1.02] active:scale-95',
|
||||
},
|
||||
{
|
||||
icon: Upload,
|
||||
iconColor: 'text-emerald-600 dark:text-emerald-400',
|
||||
|
||||
Reference in New Issue
Block a user