feat: redesign agents page (architectural-grid style), add image description, fix AI limits, remove dead code
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 53s
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 53s
- Redesign agents page with architectural-grid (8) design system: rounded-2xl cards, serif headings, motion tabs, dashed templates section - Replace agent form popup with full-page detail view (SettingsView style) with dark planning card, section tooltips, and help button - Hide advanced mode for slide/excalidraw generators - Add 'describe images' action to contextual AI assistant - Add copy button to action/resource preview with HTTP fallback - Add delete history button to agent run log panel - Increase AI word limit from 2000 to 5000 (reformulate + transform-markdown) - Increase max steps slider from 25 to 50 - Fix image description error with clear model compatibility message - Fix doubled execution count display in agent detail view - Remove dead files: notes-list-view.tsx, notes-view-toggle.tsx - Remove 'list' view mode from NotesViewMode type - Add missing i18n keys (back, configuration, options, copy, cleared)
This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
Maximize2, ImageIcon, Link2, Download, ArrowDownToLine,
|
||||
GitMerge, PlusCircle, Eye, Code, Languages,
|
||||
Presentation, PenTool, ExternalLink, ImagePlus,
|
||||
ChevronRight, MessageSquare, History, Scissors, Zap, Layout, ArrowRightLeft,
|
||||
ChevronRight, MessageSquare, History, Scissors, Zap, Layout, ArrowRightLeft, Copy, CheckCircle,
|
||||
} from 'lucide-react'
|
||||
import { motion, AnimatePresence } from 'motion/react'
|
||||
import { exportExcalidrawSceneToPngBlob } from '@/lib/client/excalidraw-export-image'
|
||||
@@ -120,6 +120,40 @@ interface ContextualAIChatProps {
|
||||
onGenerateTitle?: () => void
|
||||
}
|
||||
|
||||
function CopyPreviewButton({ text }: { text: string }) {
|
||||
const { t } = useLanguage()
|
||||
const [copied, setCopied] = useState(false)
|
||||
const handleCopy = () => {
|
||||
if (!text) return
|
||||
const ta = document.createElement('textarea')
|
||||
ta.value = text
|
||||
ta.style.position = 'fixed'
|
||||
ta.style.left = '-9999px'
|
||||
ta.style.top = '-9999px'
|
||||
ta.style.opacity = '0'
|
||||
document.body.appendChild(ta)
|
||||
ta.focus()
|
||||
ta.setSelectionRange(0, ta.value.length)
|
||||
let ok = false
|
||||
try { ok = document.execCommand('copy') } catch {}
|
||||
document.body.removeChild(ta)
|
||||
if (!ok) {
|
||||
try { navigator.clipboard.writeText(text) } catch {}
|
||||
}
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
}
|
||||
return (
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
className="flex-1 py-3.5 border border-border rounded-xl text-[10px] font-bold uppercase tracking-widest flex items-center justify-center gap-2 hover:bg-muted transition-all"
|
||||
>
|
||||
{copied ? <CheckCircle size={14} className="text-primary" /> : <Copy size={14} />}
|
||||
{copied ? t('ai.copied') : t('ai.copy')}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
// ── Component ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export function ContextualAIChat({
|
||||
@@ -561,8 +595,9 @@ export function ContextualAIChat({
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 border-t border-border flex gap-3 shrink-0">
|
||||
<button onClick={handleDiscardPreview} className="flex-1 py-3.5 text-[10px] font-bold uppercase tracking-widest text-foreground/40 hover:text-foreground transition-all">ANNULER</button>
|
||||
<button onClick={handleApplyPreview} className="flex-1 py-3.5 bg-foreground text-background rounded-xl text-[10px] font-bold uppercase tracking-widest shadow-lg transition-all hover:opacity-90">APPLIQUER À LA NOTE</button>
|
||||
<button onClick={handleDiscardPreview} className="flex-1 py-3.5 text-[10px] font-bold uppercase tracking-widest text-foreground/40 hover:text-foreground transition-all">{t('ai.cancel')}</button>
|
||||
<CopyPreviewButton text={actionPreview.text} />
|
||||
<button onClick={handleApplyPreview} className="flex-1 py-3.5 bg-foreground text-background rounded-xl text-[10px] font-bold uppercase tracking-widest shadow-lg transition-all hover:opacity-90">{t('ai.applyToNote')}</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -583,8 +618,9 @@ export function ContextualAIChat({
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 border-t border-border flex gap-3 shrink-0">
|
||||
<button onClick={() => setResourcePreview(null)} className="flex-1 py-3.5 text-[10px] font-bold uppercase tracking-widest text-foreground/40 hover:text-foreground transition-all">ANNULER</button>
|
||||
<button onClick={handleApplyResourcePreview} className="flex-1 py-3.5 bg-memento-blue text-white rounded-xl text-[10px] font-bold uppercase tracking-widest shadow-lg shadow-memento-blue/20 transition-all hover:opacity-90">APPLIQUER À LA NOTE</button>
|
||||
<button onClick={() => setResourcePreview(null)} className="flex-1 py-3.5 text-[10px] font-bold uppercase tracking-widest text-foreground/40 hover:text-foreground transition-all">{t('ai.cancel')}</button>
|
||||
<CopyPreviewButton text={resourcePreview.text} />
|
||||
<button onClick={handleApplyResourcePreview} className="flex-1 py-3.5 bg-memento-blue text-white rounded-xl text-[10px] font-bold uppercase tracking-widest shadow-lg shadow-memento-blue/20 transition-all hover:opacity-90">{t('ai.applyToNote')}</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -739,7 +775,7 @@ export function ContextualAIChat({
|
||||
</motion.button>
|
||||
)}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{ACTION_IDS.filter(a => a.id !== 'markdown' && a.id !== 'describe-images').map((action, i) => {
|
||||
{ACTION_IDS.filter(a => a.id !== 'markdown').map((action, i) => {
|
||||
const loading = actionLoading === action.id
|
||||
const isActive = action.id === 'translate' && showLangPicker
|
||||
const Icon = action.icon
|
||||
|
||||
Reference in New Issue
Block a user