Add cover URL edit button and modal

Rows without a cover (cover_url NULL or N/A) show a + button.
Clicking it opens a modal to enter a URL which is saved via new
PATCH /api/records/{id}/cover_url endpoint. cover_image is cleared
so n8n picks it up on the next backfill run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Housemann
2026-07-17 21:19:58 +02:00
co-authored by Claude Sonnet 4.6
parent 50548d44c4
commit 7a7a997f15
7 changed files with 293 additions and 7 deletions
+35 -1
View File
@@ -17,8 +17,13 @@ const props = defineProps<{
const emit = defineEmits<{
delete: [id: number]
'toggle-seen': [record: MediaRecord]
'edit-cover': [record: MediaRecord]
}>()
function needsCover(record: MediaRecord): boolean {
return !record.cover_mime_type && (!record.cover_url || record.cover_url === 'N/A')
}
function onCardClick(record: MediaRecord, event: MouseEvent) {
const target = event.target as HTMLElement
if (target.closest('button, a, input, select, dl')) return
@@ -74,7 +79,15 @@ const detailFields: { key: keyof MediaRecord; label: string }[] = [
@click="onCardClick(row, $event)"
>
<div class="card__hero">
<CoverImage :url="row.cover_url" :id="row.id" :has-cover-in-db="Boolean(row.cover_mime_type)" size="card" />
<div class="cover-wrap">
<CoverImage :url="row.cover_url" :id="row.id" :has-cover-in-db="Boolean(row.cover_mime_type)" size="card" />
<button
v-if="needsCover(row)"
class="cover-edit-btn"
title="Cover-URL eingeben"
@click.stop="emit('edit-cover', row)"
></button>
</div>
<div class="card__hero-text">
<header class="card__header">
<div class="card__meta">
@@ -153,6 +166,27 @@ const detailFields: { key: keyof MediaRecord; label: string }[] = [
align-items: flex-start;
}
.cover-wrap {
position: relative;
flex-shrink: 0;
}
.cover-edit-btn {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.45);
border: 2px dashed var(--border);
border-radius: var(--radius);
color: var(--text-muted);
font-size: 1.4rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.card__hero-text {
flex: 1;
min-width: 0;