Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions frontend/src/components/ui/StyleStamp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';

// Provenance stamp for a poster's build style, overlaid on the poster corner.
// A dark solid chip so it reads over any artwork, with brand-coloured text so
// CL2K / MM2K / other styles stay distinguishable. Shared by the Unmatched,
// Asset Search, and CL2K Maker grids so the stamp is identical everywhere.
// The caller supplies position + text size via `className`.
const STYLE_COLOR = {
CL2K: { text: '#c9bcff', border: 'rgba(135,103,247,0.55)' },
MM2K: { text: '#ffd257', border: 'rgba(255,201,68,0.5)' },
};
const DEFAULT_COLOR = { text: '#ffffff', border: 'rgba(255,255,255,0.25)' };

export const StyleStamp = ({ style, className = '' }) => {
if (!style) return null;
const color = STYLE_COLOR[String(style).toUpperCase()] || DEFAULT_COLOR;
return (
<span
className={`font-mono font-bold tracking-[0.4px] px-1.5 py-0.5 rounded-[4px] border backdrop-blur-sm ${className}`}
style={{
color: color.text,
borderColor: color.border,
background: 'rgba(13,10,26,0.8)',
}}
title={`Style: ${style}`}
>
{style}
</span>
);
};

export default StyleStamp;
11 changes: 5 additions & 6 deletions frontend/src/pages/poster/PosterAssetsSearchPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { postersAPI } from '../../utils/api/posters.js';
import { Modal } from '../../components/modals/Modal';
import { Button, LoadingButton, IconButton, Pagination } from '../../components/ui/index.js';
import Spinner from '../../components/ui/Spinner.jsx';
import { StyleStamp } from '../../components/ui/StyleStamp.jsx';

// Compact "5d ago" relative time for the GDrive last-sync stat.
const relTime = ts => {
Expand Down Expand Up @@ -713,12 +714,10 @@ const PosterAssetsSearchPage = () => {
</button>
)}
{item.style && (
<span
className="absolute top-1.5 left-1.5 z-10 px-1.5 py-0.5 rounded text-[10px] font-semibold bg-black/65 text-white backdrop-blur-sm pointer-events-none"
title={`Style: ${item.style}`}
>
{item.style}
</span>
<StyleStamp
style={item.style}
className="absolute top-1.5 left-1.5 z-10 text-[10px] pointer-events-none"
/>
)}
<div className="absolute top-1.5 right-1.5 z-10 flex items-center gap-0.5 rounded-lg bg-black/55 backdrop-blur-sm p-0.5 opacity-0 group-hover:opacity-100 transition-fast">
<IconButton
Expand Down
26 changes: 11 additions & 15 deletions frontend/src/pages/poster/UnmatchedAssetsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { buildPosterRequestText, formatId } from '../../utils/posterRequest.js';
import { extensionCapability } from '../../extensions/index.js';
import { Button, IconButton, Modal } from '../../components/ui/index.js';
import Spinner from '../../components/ui/Spinner.jsx';
import { StyleStamp } from '../../components/ui/StyleStamp.jsx';

// Optional extension hook: (item) => { to, title, ariaLabel, icon } | null.
// Renders an extra per-row action link (e.g. a poster-maker shortcut) when an
Expand Down Expand Up @@ -46,19 +47,16 @@ const REEL_FILTERS = [
];
const REEL_PAGE_SIZE = 10;

// CL2K / MM2K are the *built* poster styles whose provenance matters — they
// carry a real author. Other styles (GDrive / local fetches) get no tag.
const BUILT_STYLE_TAG = {
CL2K: ['#a99eff', 'rgba(135,103,247,.32)'],
MM2K: ['#ffc944', 'rgba(255,201,68,.22)'],
};
// CL2K / MM2K are the *built* poster styles whose provenance matters (they
// carry a real author); other styles (GDrive / local fetches) get no tag.
const BUILT_STYLES = new Set(['CL2K', 'MM2K']);

/** A single poster in the reel: thumbnail + (for CL2K/MM2K) a source tag and
* the builder it came from. */
const ReelPosterCard = ({ poster }) => {
const [failed, setFailed] = useState(false);
const styleTag = BUILT_STYLE_TAG[poster.style];
const builtBy = styleTag ? poster.folder : null;
const isBuilt = BUILT_STYLES.has(poster.style);
const builtBy = isBuilt ? poster.folder : null;
return (
<div className="shrink-0" style={{ width: 112 }}>
<div
Expand All @@ -80,13 +78,11 @@ const ReelPosterCard = ({ poster }) => {
onError={() => setFailed(true)}
/>
)}
{styleTag && (
<span
className="absolute top-1.5 left-1.5 font-mono text-[8px] font-bold tracking-[0.4px] px-1.5 py-0.5 rounded-[4px]"
style={{ color: styleTag[0], background: styleTag[1] }}
>
{poster.style}
</span>
{isBuilt && (
<StyleStamp
style={poster.style}
className="absolute top-1.5 left-1.5 text-[8px]"
/>
)}
</div>
<p className="mt-1.5 text-xs font-medium text-fg-muted text-center truncate">
Expand Down
15 changes: 13 additions & 2 deletions frontend/src/pages/settings/JobsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ const TRIGGER_STYLE = {
const triggerOf = job =>
job.trigger || (job.type === 'webhook' || job.job_type === 'webhook' ? 'webhook' : 'manual');

// A job type can carry a trigger prefix (e.g. "scheduled:upgradinatorr_profiles").
// The trigger is already shown as its own pill, so drop the prefix and humanize.
const prettyType = raw => {
if (!raw) return '-';
const s = String(raw);
const name = s.includes(':') ? s.split(':').pop() : s;
return name.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
};

// Status-dot colour for the table's STATUS cell.
const STATUS_DOT = {
pending: 'bg-warning',
Expand Down Expand Up @@ -421,7 +430,7 @@ export const JobsPage = () => {
<div className="flex flex-col gap-2">
{jobs.map(job => {
const isOpen = expandedJobId === job.id;
const typeLabel = job.module_name || job.job_type || job.type || '-';
const typeLabel = prettyType(job.module_name || job.job_type || job.type);
return (
<div
key={job.id}
Expand Down Expand Up @@ -543,7 +552,9 @@ export const JobsPage = () => {
#{job.id}
</td>
<td className="px-2 sm:px-4 py-3 text-fg text-sm font-semibold break-all">
{job.module_name || job.job_type || job.type || '-'}
{prettyType(
job.module_name || job.job_type || job.type
)}
</td>
<td className="hidden sm:table-cell px-4 py-3">
<span
Expand Down
Loading