feat(tags): show a character's fandom on its chip (truncated)
CI / lint (push) Successful in 3s
CI / frontend-build (push) Successful in 23s
CI / backend-lint-and-test (push) Successful in 43s
CI / integration (push) Successful in 3m27s

A character chip with a fandom only rendered a bare arrow. Surface the fandom
NAME inline, truncated to 15 chars (full name in the tooltip). Resolve the name
via a Tag self-join in both tag paths the modal uses — list_for_image
(/api/images/<id>/tags) and gallery get_image_with_tags
(/api/gallery/image/<id>) — so chips show the fandom on first open and after any
reload. Falls back to the bare arrow when only fandom_id is known. Operator-asked
2026-06-09.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 19:35:59 -04:00
parent e4cebf70d1
commit 978f49adcc
4 changed files with 53 additions and 10 deletions
+16 -3
View File
@@ -11,7 +11,10 @@
@click:close="$emit('remove', tag.id)"
>
<v-icon start size="x-small">{{ iconFor(tag.kind) }}</v-icon>
{{ tag.name }}<span v-if="tag.fandom_id"></span>
{{ tag.name }}<span
v-if="tag.fandom_id" class="fc-tag-chip__fandom"
:title="tag.fandom_name ? `Fandom: ${tag.fandom_name}` : 'Has a fandom'"
><template v-if="fandomLabel">&nbsp;{{ fandomLabel }}</template></span>
</v-chip>
<span class="fc-tag-chip__menu-wrap">
<v-btn
@@ -40,15 +43,24 @@
</template>
<script setup>
import { ref } from 'vue'
import { computed, ref } from 'vue'
import { useTagStore } from '../../stores/tags.js'
defineProps({ tag: { type: Object, required: true } })
const props = defineProps({ tag: { type: Object, required: true } })
defineEmits(['remove', 'rename', 'set-fandom'])
const store = useTagStore()
const menuOpen = ref(false)
// Show a character's fandom inline (truncated). Falls back to a bare arrow when
// only fandom_id is known but the name wasn't resolved (older payloads).
const FANDOM_MAX = 15
const fandomLabel = computed(() => {
const n = props.tag.fandom_name
if (!n) return ''
return n.length > FANDOM_MAX ? `${n.slice(0, FANDOM_MAX)}` : n
})
const KIND_ICONS = {
general: 'mdi-tag', character: 'mdi-account-circle',
fandom: 'mdi-book-open-page-variant', series: 'mdi-bookshelf',
@@ -62,4 +74,5 @@ function iconFor (k) { return KIND_ICONS[k] || 'mdi-tag' }
.fc-tag-chip__menu-wrap { display: inline-flex; align-items: center; }
.fc-tag-chip__kebab { opacity: 0.7; }
.fc-tag-chip:hover .fc-tag-chip__kebab { opacity: 1; }
.fc-tag-chip__fandom { opacity: 0.7; font-size: 0.85em; }
</style>