Profile: store covers in object storage (WebP); add covers config; remember artworks categories content-type preference

This commit is contained in:
2026-03-29 09:22:36 +02:00
parent cab4fbd83e
commit 1da7d3bf88
27 changed files with 703 additions and 448 deletions

View File

@@ -50,6 +50,7 @@ export default function PublishPanel({
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone,
visibility = 'public', // 'public' | 'unlisted' | 'private'
showRightsConfirmation = true,
showVisibility = false,
onPublishModeChange,
onScheduleAt,
onVisibilityChange,
@@ -59,6 +60,7 @@ export default function PublishPanel({
onCancel,
// Navigation helpers (for checklist quick-links)
onGoToStep,
allRootCategoryOptions = [],
}) {
const pill = STATUS_PILL[machineState] ?? null
const hasPreview = Boolean(primaryPreviewUrl && !isArchive)
@@ -67,7 +69,13 @@ export default function PublishPanel({
const title = String(metadata.title || '').trim()
const hasTitle = Boolean(title)
const hasCategory = Boolean(metadata.rootCategoryId)
const selectedRoot = allRootCategoryOptions.find(
(item) => String(item.id) === String(metadata.rootCategoryId || '')
) ?? null
const requiresSubCategory = Boolean(selectedRoot?.children?.length)
const hasCompleteCategory = Boolean(
metadata.rootCategoryId && (!requiresSubCategory || metadata.subCategoryId)
)
const hasTag = Array.isArray(metadata.tags) && metadata.tags.length > 0
const hasRights = Boolean(metadata.rightsAccepted)
const hasScreenshot = !isArchiveRequiresScreenshot || screenshots.length > 0
@@ -75,7 +83,7 @@ export default function PublishPanel({
const checklist = [
{ label: 'File uploaded & processed', ok: uploadReady },
{ label: 'Title', ok: hasTitle, onClick: () => onGoToStep?.(2) },
{ label: 'Category', ok: hasCategory, onClick: () => onGoToStep?.(2) },
{ label: 'Category', ok: hasCompleteCategory, onClick: () => onGoToStep?.(2) },
{ label: 'Rights confirmed', ok: hasRights, onClick: () => onGoToStep?.(2) },
...( isArchiveRequiresScreenshot
? [{ label: 'Screenshot (required for pack)', ok: hasScreenshot, onClick: () => onGoToStep?.(1) }]
@@ -162,7 +170,8 @@ export default function PublishPanel({
<ReadinessChecklist items={checklist} />
</div>
{/* Visibility */}
{/* Visibility (only when showVisibility=true) */}
{showVisibility && (
<div>
<label className="mb-2 block text-[10px] uppercase tracking-wider text-white/40" htmlFor="publish-visibility">
Visibility
@@ -198,9 +207,10 @@ export default function PublishPanel({
})}
</div>
</div>
)}
{/* Schedule picker only shows when upload is ready */}
{uploadReady && machineState !== 'complete' && (
{/* Schedule picker only shows when enabled for this panel */}
{showVisibility && uploadReady && machineState !== 'complete' && (
<SchedulePublishPicker
mode={publishMode}
scheduledAt={scheduledAt}