feat(channels): suggest your own tags for untagged channels from your tagging pattern (E8·S4)
Learn, per user tag, which auto TOPIC tags are characteristic of the channels you've tagged it, then suggest that tag for still-untagged subscribed channels whose topics cover enough of the profile. Language auto-tags are excluded from the signal — near-universal within a language, they flooded every channel. New GET /api/tags/suggestions (read-only, deterministic) backed by app/sync/tagsuggest.py. Surfaced in the Channel Manager as dashed "ghost" chips in the tags cell — one tap accepts (reuses the attach-tag endpoint), × dismisses for the session — plus a header badge and a bulk "Accept N confident" (the full-profile matches) behind a confirm. No silent writes (D4 = suggest-and-confirm). Also reflow a pre-existing prettier drift in dateFilter.ts from E8·S2.
This commit is contained in:
@@ -9,7 +9,7 @@ import Tooltip from "./Tooltip";
|
||||
import { PriorityStepper } from "./PriorityStepper";
|
||||
import ChannelLink from "./ChannelLink";
|
||||
import AboutCell from "./AboutCell";
|
||||
import { ChannelTagsControl } from "./ChannelTags";
|
||||
import { ChannelTagsControl, type SuggestedTag } from "./ChannelTags";
|
||||
|
||||
/** The shared "subscribers" DataTable column (right-aligned, sortable, em-dash for null) — identical
|
||||
* in the Channels manager and the ChannelDiscovery table, which show subscriber counts on different
|
||||
@@ -166,6 +166,10 @@ export interface ChannelColumnDeps {
|
||||
toggleTag: (channelId: string, tagId: number, hasTag: boolean) => void;
|
||||
createAndAttachTag: (channelId: string, name: string) => void;
|
||||
onFilterByTag: (tagId: number, name: string) => void;
|
||||
// E8·S4 — suggested user tags per channel (resolved to Tag + confidence), plus accept/dismiss.
|
||||
suggestionsFor: (channelId: string) => SuggestedTag[];
|
||||
onAcceptSuggestion: (channelId: string, tagId: number) => void;
|
||||
onDismissSuggestion: (channelId: string, tagId: number) => void;
|
||||
}
|
||||
|
||||
export function buildChannelColumns(deps: ChannelColumnDeps): Column<ManagedChannel>[] {
|
||||
@@ -185,6 +189,9 @@ export function buildChannelColumns(deps: ChannelColumnDeps): Column<ManagedChan
|
||||
toggleTag,
|
||||
createAndAttachTag,
|
||||
onFilterByTag,
|
||||
suggestionsFor,
|
||||
onAcceptSuggestion,
|
||||
onDismissSuggestion,
|
||||
} = deps;
|
||||
return [
|
||||
{
|
||||
@@ -306,6 +313,9 @@ export function buildChannelColumns(deps: ChannelColumnDeps): Column<ManagedChan
|
||||
onToggle={(tagId) => toggleTag(c.id, tagId, c.tag_ids.includes(tagId))}
|
||||
onCreate={(name) => createAndAttachTag(c.id, name)}
|
||||
onChipClick={onFilterByTag}
|
||||
suggestions={suggestionsFor(c.id)}
|
||||
onAcceptSuggestion={(tagId) => onAcceptSuggestion(c.id, tagId)}
|
||||
onDismissSuggestion={(tagId) => onDismissSuggestion(c.id, tagId)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user