fix: organisateur IA — apply tag utilise syncNoteLabels au lieu de properties
- applyTag faisait un PATCH sur /api/notes/[id]/properties avec { tags: [...] }
mais l'API properties attend { properties: { propId: value } }
- Maintenant: PATCH /api/ai/organize-notebook qui appelle syncNoteLabels()
- Les tags sont appliqués comme LABELS (système existant) sur les notes
- Merge avec labels existants (n'écrase pas)
This commit is contained in:
@@ -3,6 +3,7 @@ import { auth } from '@/auth'
|
|||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { notebookOrganizerService } from '@/lib/ai/services/notebook-organizer.service'
|
import { notebookOrganizerService } from '@/lib/ai/services/notebook-organizer.service'
|
||||||
import { checkEntitlementOrThrow, QuotaExceededError, incrementUsageAsync } from '@/lib/entitlements'
|
import { checkEntitlementOrThrow, QuotaExceededError, incrementUsageAsync } from '@/lib/entitlements'
|
||||||
|
import { syncNoteLabels } from '@/app/actions/notes'
|
||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
@@ -55,3 +56,41 @@ export async function POST(request: NextRequest) {
|
|||||||
return NextResponse.json({ error: error.message || 'Failed to organize notebook' }, { status: 500 })
|
return NextResponse.json({ error: error.message || 'Failed to organize notebook' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function PATCH(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const session = await auth()
|
||||||
|
if (!session?.user?.id) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const { action, tagName, noteIds, notebookId } = await request.json()
|
||||||
|
|
||||||
|
if (action === 'apply_tag' && tagName && Array.isArray(noteIds)) {
|
||||||
|
// Fetch existing labels for each note, merge with new tag
|
||||||
|
for (const noteId of noteIds) {
|
||||||
|
const note = await prisma.note.findUnique({
|
||||||
|
where: { id: noteId },
|
||||||
|
select: { labels: true, notebookId: true },
|
||||||
|
})
|
||||||
|
if (!note) continue
|
||||||
|
|
||||||
|
let existingLabels: string[] = []
|
||||||
|
try { existingLabels = note.labels ? JSON.parse(note.labels) : [] } catch {}
|
||||||
|
|
||||||
|
if (!existingLabels.includes(tagName)) {
|
||||||
|
existingLabels.push(tagName)
|
||||||
|
}
|
||||||
|
|
||||||
|
await syncNoteLabels(noteId, existingLabels, note.notebookId, session.user.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, applied: noteIds.length })
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ error: 'Invalid action' }, { status: 400 })
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('[Notebook Organizer PATCH] Error:', error)
|
||||||
|
return NextResponse.json({ error: error.message }, { status: 500 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1068,7 +1068,8 @@ export function HomeClient({
|
|||||||
>
|
>
|
||||||
<Wand2 size={14} />
|
<Wand2 size={14} />
|
||||||
<span>{t('structuredViews.organizer') || 'Organiser'}</span>
|
<span>{t('structuredViews.organizer') || 'Organiser'}</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{searchParams.get('notebook') && (
|
{searchParams.get('notebook') && (
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
|
|||||||
@@ -53,15 +53,14 @@ export function NotebookOrganizerDialog({
|
|||||||
|
|
||||||
const applyTag = async (tagName: string, noteIds: string[]) => {
|
const applyTag = async (tagName: string, noteIds: string[]) => {
|
||||||
try {
|
try {
|
||||||
for (const noteId of noteIds) {
|
const res = await fetch('/api/ai/organize-notebook', {
|
||||||
await fetch(`/api/notes/${noteId}/properties`, {
|
method: 'PATCH',
|
||||||
method: 'PATCH',
|
headers: { 'Content-Type': 'application/json' },
|
||||||
headers: { 'Content-Type': 'application/json' },
|
body: JSON.stringify({ action: 'apply_tag', tagName, noteIds, notebookId }),
|
||||||
body: JSON.stringify({ tags: [tagName] }),
|
})
|
||||||
}).catch(() => {})
|
if (!res.ok) throw new Error('Failed')
|
||||||
}
|
|
||||||
setAppliedTags(prev => new Set(prev).add(tagName))
|
setAppliedTags(prev => new Set(prev).add(tagName))
|
||||||
toast.success(t('wizard.tagApplied') || `Tag "${tagName}" appliqué à ${noteIds.length} notes`)
|
toast.success(t('structuredViews.tagApplied') || `Tag "${tagName}" appliqué à ${noteIds.length} notes`)
|
||||||
} catch {
|
} catch {
|
||||||
toast.error('Erreur')
|
toast.error('Erreur')
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user