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

- 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:
Antigravity
2026-05-09 17:18:47 +00:00
parent 79381a4cc9
commit 2fd435df6f
33 changed files with 1441 additions and 745 deletions

View File

@@ -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