feat: filter metadata refresh to ongoing series & improve job action buttons

- Metadata refresh now skips series with ended/cancelled status
- Add xs size to Button component
- Unify view/cancel button sizes (h-7) with icons (eye & cross)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-23 18:59:33 +01:00
parent b6422fbf3e
commit eab7f2e21b
3 changed files with 32 additions and 13 deletions

View File

@@ -110,9 +110,16 @@ pub async fn start_refresh(
}))); })));
} }
// Check there are approved links to refresh // Check there are approved links to refresh (only ongoing series)
let link_count: i64 = sqlx::query_scalar( let link_count: i64 = sqlx::query_scalar(
"SELECT COUNT(*) FROM external_metadata_links WHERE library_id = $1 AND status = 'approved'", r#"
SELECT COUNT(*) FROM external_metadata_links eml
LEFT JOIN series_metadata sm
ON sm.library_id = eml.library_id AND sm.name = eml.series_name
WHERE eml.library_id = $1
AND eml.status = 'approved'
AND COALESCE(sm.status, 'ongoing') NOT IN ('ended', 'cancelled')
"#,
) )
.bind(library_id) .bind(library_id)
.fetch_one(&state.pool) .fetch_one(&state.pool)
@@ -234,13 +241,17 @@ pub(crate) async fn process_metadata_refresh(
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
// Get all approved links for this library // Get approved links for this library, only for ongoing series (not ended/cancelled)
let links: Vec<(Uuid, String, String, String)> = sqlx::query_as( let links: Vec<(Uuid, String, String, String)> = sqlx::query_as(
r#" r#"
SELECT id, series_name, provider, external_id SELECT eml.id, eml.series_name, eml.provider, eml.external_id
FROM external_metadata_links FROM external_metadata_links eml
WHERE library_id = $1 AND status = 'approved' LEFT JOIN series_metadata sm
ORDER BY series_name ON sm.library_id = eml.library_id AND sm.name = eml.series_name
WHERE eml.library_id = $1
AND eml.status = 'approved'
AND COALESCE(sm.status, 'ongoing') NOT IN ('ended', 'cancelled')
ORDER BY eml.series_name
"#, "#,
) )
.bind(library_id) .bind(library_id)

View File

@@ -205,16 +205,23 @@ export function JobRow({ job, libraryName, highlighted, onCancel, formatDate, fo
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Link <Link
href={`/jobs/${job.id}`} href={`/jobs/${job.id}`}
className="inline-flex items-center px-3 py-1.5 text-xs font-medium rounded-lg bg-primary text-white hover:bg-primary/90 transition-colors" className="inline-flex items-center justify-center gap-1.5 h-7 px-2.5 text-xs font-medium rounded-md bg-primary text-white hover:bg-primary/90 transition-colors"
> >
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
</svg>
{t("jobRow.view")} {t("jobRow.view")}
</Link> </Link>
{(job.status === "pending" || job.status === "running" || job.status === "extracting_pages" || job.status === "generating_thumbnails") && ( {(job.status === "pending" || job.status === "running" || job.status === "extracting_pages" || job.status === "generating_thumbnails") && (
<Button <Button
variant="danger" variant="danger"
size="sm" size="xs"
onClick={() => onCancel(job.id)} onClick={() => onCancel(job.id)}
> >
<svg className="w-3.5 h-3.5 mr-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
{t("common.cancel")} {t("common.cancel")}
</Button> </Button>
)} )}

View File

@@ -14,7 +14,7 @@ type ButtonVariant =
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: ReactNode; children: ReactNode;
variant?: ButtonVariant; variant?: ButtonVariant;
size?: "sm" | "md" | "lg"; size?: "xs" | "sm" | "md" | "lg";
} }
const variantStyles: Record<ButtonVariant, string> = { const variantStyles: Record<ButtonVariant, string> = {
@@ -33,6 +33,7 @@ const variantStyles: Record<ButtonVariant, string> = {
}; };
const sizeStyles: Record<string, string> = { const sizeStyles: Record<string, string> = {
xs: "h-7 px-2.5 text-xs rounded-md",
sm: "h-9 px-3 text-xs rounded-md", sm: "h-9 px-3 text-xs rounded-md",
md: "h-10 px-4 py-2 text-sm rounded-md", md: "h-10 px-4 py-2 text-sm rounded-md",
lg: "h-11 px-8 text-base rounded-md", lg: "h-11 px-8 text-base rounded-md",