feat(agents): refonte complète slide-generator + excalidraw-generator
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 3s
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 3s
Slide generator (generate_pptx): - Pivot vers génération PowerPoint natif (pptxgenjs) au lieu de Reveal.js HTML - 4 nouveaux layouts diagramme : timeline, process, comparison, metrics - 2 nouveaux layouts image : image-content (texte + image), image-full (plein cadre) - Redesign visuel de tous les layouts (cover split, section full-bleed, header band) - Palettes corrigées : bg blanc sur toutes les palettes, contrastes réels - fit:shrink systématique sur tous les textes pour éviter les débordements - Extraction automatique des images des notes (Markdown/HTML) et injection dans le prompt IA - Prompt IA renforcé : impose "style" et "theme" explicitement dans le JSON, impose ≥2 layouts diagramme - Fix overlap timeline : zones de texte calculées sans collision avec les cercles - Notification agent mise à jour : bouton download .pptx au lieu d'ouvrir HTML Excalidraw generator: - Layout Dagre/ELK pour graphes auto-positionnés - Styles visuels : coloré, austère, sketch-plus (Virgil font) - Zones/containers pour architecture-cloud - Sanitisation du graphe et métriques de qualité de layout Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { useState, useEffect, useCallback } from 'react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Bell, Check, X, Clock, AlertCircle, CheckCircle2, Circle, Share2, Bot, Trash2 } from 'lucide-react'
|
||||
import { Bell, Check, X, Clock, AlertCircle, CheckCircle2, Circle, Share2, Bot, Trash2, Download, Pencil, Presentation } from 'lucide-react'
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
@@ -196,26 +196,39 @@ export function NotificationPanel() {
|
||||
) : (
|
||||
<div className="max-h-96 overflow-y-auto">
|
||||
{/* App notifications (agents, system) */}
|
||||
{appNotifications.map((notif) => (
|
||||
{appNotifications.map((notif) => {
|
||||
const isSlides = notif.type === 'agent_slides_ready'
|
||||
const isCanvas = notif.type === 'agent_canvas_ready'
|
||||
const canvasId = notif.relatedId
|
||||
|
||||
return (
|
||||
<div
|
||||
key={notif.id}
|
||||
className="p-3 border-b last:border-0 hover:bg-accent/50 transition-colors duration-150 cursor-pointer"
|
||||
onClick={() => {
|
||||
if (notif.actionUrl) {
|
||||
handleMarkNotifRead(notif.id)
|
||||
setOpen(false)
|
||||
router.push(notif.actionUrl)
|
||||
}
|
||||
}}
|
||||
className="p-3 border-b last:border-0 hover:bg-accent/50 transition-colors duration-150"
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<div
|
||||
className="flex items-start gap-3 cursor-pointer"
|
||||
onClick={() => {
|
||||
if (notif.actionUrl) {
|
||||
handleMarkNotifRead(notif.id)
|
||||
setOpen(false)
|
||||
router.push(notif.actionUrl)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className={cn(
|
||||
"mt-0.5 flex-none rounded-full p-1",
|
||||
notif.type === 'agent_success' && 'bg-green-100 dark:bg-green-900/30 text-green-600',
|
||||
notif.type === 'agent_slides_ready' && 'bg-purple-100 dark:bg-purple-900/30 text-purple-600',
|
||||
notif.type === 'agent_canvas_ready' && 'bg-blue-100 dark:bg-blue-900/30 text-blue-600',
|
||||
notif.type === 'agent_failure' && 'bg-red-100 dark:bg-red-900/30 text-red-600',
|
||||
notif.type === 'system' && 'bg-blue-100 dark:bg-blue-900/30 text-blue-600',
|
||||
)}>
|
||||
{notif.type.startsWith('agent') ? (
|
||||
{isSlides ? (
|
||||
<Presentation className="w-3.5 h-3.5" />
|
||||
) : isCanvas ? (
|
||||
<Pencil className="w-3.5 h-3.5" />
|
||||
) : notif.type.startsWith('agent') ? (
|
||||
<Bot className="w-3.5 h-3.5" />
|
||||
) : (
|
||||
<AlertCircle className="w-3.5 h-3.5" />
|
||||
@@ -226,9 +239,13 @@ export function NotificationPanel() {
|
||||
<span className={cn(
|
||||
"text-[10px] font-semibold uppercase tracking-wider",
|
||||
notif.type === 'agent_success' && 'text-green-600 dark:text-green-400',
|
||||
notif.type === 'agent_slides_ready' && 'text-purple-600 dark:text-purple-400',
|
||||
notif.type === 'agent_canvas_ready' && 'text-blue-600 dark:text-blue-400',
|
||||
notif.type === 'agent_failure' && 'text-red-600 dark:text-red-400',
|
||||
notif.type === 'system' && 'text-blue-600 dark:text-blue-400',
|
||||
)}>
|
||||
{notif.type === 'agent_slides_ready' && (t('notification.slidesReady') || 'Slides Ready')}
|
||||
{notif.type === 'agent_canvas_ready' && (t('notification.canvasReady') || 'Diagram Ready')}
|
||||
{notif.type === 'agent_success' && (t('notification.agentSuccess') || 'Agent completed')}
|
||||
{notif.type === 'agent_failure' && (t('notification.agentFailed') || 'Agent failed')}
|
||||
{notif.type === 'system' && 'System'}
|
||||
@@ -251,8 +268,23 @@ export function NotificationPanel() {
|
||||
<X className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
{isSlides && canvasId && (
|
||||
<div className="mt-2 ml-8">
|
||||
<button
|
||||
onClick={async () => {
|
||||
handleMarkNotifRead(notif.id)
|
||||
window.open(`/api/canvas/download?id=${canvasId}`, '_blank')
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-semibold rounded-md bg-purple-500 text-white hover:bg-purple-600 shadow-sm transition-all active:scale-95"
|
||||
>
|
||||
<Download className="w-3 h-3" />
|
||||
{t('notification.downloadPptx') || 'Download .pptx'}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
)
|
||||
})}
|
||||
|
||||
{/* Overdue reminders */}
|
||||
{overdueReminders.map((note) => (
|
||||
|
||||
Reference in New Issue
Block a user