- {userTags.map((tg) => {
- const on = c.tag_ids.includes(tg.id);
- return (
-
onToggleTag(tg.id)}
- className={`text-[10px] px-1.5 py-0.5 rounded-full border transition ${
- on
- ? "bg-accent text-accent-fg border-accent"
- : "bg-card border-border text-muted hover:border-accent"
- }`}
- >
- {tg.name}
-
- );
- })}
+
+ {attached.map((tg) => (
+
+ {tg.name}
+
+ ))}
+
setOpen((o) => !o)}
+ title={t("channels.row.editTags")}
+ aria-label={t("channels.row.editTags")}
+ className="w-5 h-5 inline-flex items-center justify-center rounded-full border border-dashed border-border text-muted hover:text-accent hover:border-accent transition"
+ >
+
+
+ {open && (
+
+ {userTags.map((tg) => {
+ const on = c.tag_ids.includes(tg.id);
+ return (
+ onToggleTag(tg.id)}
+ className={`w-full flex items-center gap-2 text-left text-xs px-2 py-1.5 rounded-md transition ${
+ on ? "text-fg" : "text-muted hover:bg-card"
+ }`}
+ >
+
+ {on && }
+
+ {tg.name}
+
+ );
+ })}
+
+ )}
);
}
diff --git a/frontend/src/components/DataTable.tsx b/frontend/src/components/DataTable.tsx
index ef1d5a8..1127b01 100644
--- a/frontend/src/components/DataTable.tsx
+++ b/frontend/src/components/DataTable.tsx
@@ -22,6 +22,8 @@ export interface Column
{
sortable?: boolean;
sortValue?: (row: T) => string | number;
filter?: ColumnFilter;
+ // Keep the cell on one line so the column auto-sizes to its content (table-layout: auto).
+ nowrap?: boolean;
// Card fallback (below md): `cardPrimary` renders as the card heading (no label); `hideInCard`
// omits the column; `cardLabel:false` shows the value without its header label.
cardPrimary?: boolean;
@@ -325,7 +327,7 @@ export default function DataTable({
({
}`}
>
{columns.map((col) => (
-
+
{col.render(row)}
))}
diff --git a/frontend/src/i18n/locales/de/channels.json b/frontend/src/i18n/locales/de/channels.json
index 94bfd9a..fca4e28 100644
--- a/frontend/src/i18n/locales/de/channels.json
+++ b/frontend/src/i18n/locales/de/channels.json
@@ -29,6 +29,10 @@
"channel": "Kanal",
"stored": "Gespeichert",
"subs": "Abonnenten",
+ "lastUpload": "Letzter Upload",
+ "length": "Länge",
+ "types": "N/S/L",
+ "typesHint": "Videos nach Typ: Normale / Shorts / Live",
"sync": "Sync",
"tags": "Tags",
"actions": "Aktionen"
@@ -51,6 +55,7 @@
"stored": "{{formatted}} gespeichert",
"subs": "{{formatted}} Abonnenten",
"openOnYouTube": "Auf YouTube öffnen",
+ "editTags": "Tags bearbeiten",
"priorityHint": "Deine Einstufung für diesen Kanal. Sortiere den Feed nach „Kanalpriorität“, um Kanäle mit höherer Priorität nach oben zu bringen.",
"raisePriority": "Priorität erhöhen",
"lowerPriority": "Priorität senken",
diff --git a/frontend/src/i18n/locales/en/channels.json b/frontend/src/i18n/locales/en/channels.json
index f5adebd..182599b 100644
--- a/frontend/src/i18n/locales/en/channels.json
+++ b/frontend/src/i18n/locales/en/channels.json
@@ -29,6 +29,10 @@
"channel": "Channel",
"stored": "Stored",
"subs": "Subscribers",
+ "lastUpload": "Last upload",
+ "length": "Length",
+ "types": "N/S/L",
+ "typesHint": "Videos by type: Normal / Shorts / Live",
"sync": "Sync",
"tags": "Tags",
"actions": "Actions"
@@ -51,6 +55,7 @@
"stored": "{{formatted}} stored",
"subs": "{{formatted}} subs",
"openOnYouTube": "Open on YouTube",
+ "editTags": "Edit tags",
"priorityHint": "Your ranking for this channel. Sort the feed by “Channel priority” to bring higher-priority channels to the top.",
"raisePriority": "Raise priority",
"lowerPriority": "Lower priority",
diff --git a/frontend/src/i18n/locales/hu/channels.json b/frontend/src/i18n/locales/hu/channels.json
index 802bb13..b40c0b8 100644
--- a/frontend/src/i18n/locales/hu/channels.json
+++ b/frontend/src/i18n/locales/hu/channels.json
@@ -29,6 +29,10 @@
"channel": "Csatorna",
"stored": "Tárolt",
"subs": "Feliratkozók",
+ "lastUpload": "Utolsó feltöltés",
+ "length": "Hossz",
+ "types": "N/S/L",
+ "typesHint": "Videók típusonként: Normál / Short / Live",
"sync": "Szinkron",
"tags": "Címkék",
"actions": "Műveletek"
@@ -51,6 +55,7 @@
"stored": "{{formatted}} tárolt",
"subs": "{{formatted}} feliratkozó",
"openOnYouTube": "Megnyitás a YouTube-on",
+ "editTags": "Címkék szerkesztése",
"priorityHint": "A te rangsorod ehhez a csatornához. Rendezd a hírfolyamot „Csatorna prioritás” szerint, hogy a magasabb prioritású csatornák felülre kerüljenek.",
"raisePriority": "Prioritás növelése",
"lowerPriority": "Prioritás csökkentése",
diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts
index e13f097..aa17661 100644
--- a/frontend/src/lib/api.ts
+++ b/frontend/src/lib/api.ts
@@ -293,6 +293,11 @@ export interface ManagedChannel {
subscriber_count: number | null;
video_count: number | null;
stored_videos: number;
+ last_video_at: string | null;
+ total_duration_seconds: number;
+ count_normal: number;
+ count_short: number;
+ count_live: number;
priority: number;
hidden: boolean;
deep_requested: boolean;