Added tag actor editing.

This commit is contained in:
2026-03-04 03:57:04 +01:00
parent f4447b23de
commit 46839b48cf
4 changed files with 130 additions and 64 deletions

View File

@@ -1,43 +1,56 @@
<template> <template>
<ul <div class="tags-sections">
class="tags nolist" <div
:class="{ disabled: !editing.has(item.key) }" v-for="actorTags in tags"
> :key="`tags-${actorTags.actor?.slug || 'scene'}`"
<li class="tags-section"
v-for="tag in [...item.value, ...newTags]"
:key="`tag-${tag.id}`"
class="tag"
:class="{ deleted: edits.tags && !edits.tags.some((tagId) => tagId === tag.id) }"
> >
<span class="tag-name">{{ tag.name }}</span> <ul
class="tags nolist"
<Icon :class="{ disabled: !editing.has(item.key) }"
v-if="edits.tags && !edits.tags.some((tagId) => tagId === tag.id)"
icon="checkmark"
class="add"
@click="emit('tags', edits.tags.concat(tag.id))"
/>
<Icon
v-else
icon="cross2"
class="remove"
@click="emit('tags', edits.tags.filter((tagId) => tagId !== tag.id))"
/>
</li>
<li class="new">
<TagSearch
:disabled="!editing.has(item.key)"
@tag="addTag"
> >
<Icon <li
icon="plus3" v-if="actorTags.actor"
class="add" class="tags-actor"
/> >{{ actorTags.actor.name }}:</li>
</TagSearch>
</li> <li
</ul> v-for="tag in [...actorTags.tags, ...newTags.filter((newTag) => newTag.actorId === actorTags.actorId)]"
:key="`tag-${tag.id}`"
class="tag"
:class="{ deleted: edits.tags && !edits.tags.some((sceneTag) => sceneTag.id === tag.id && sceneTag.actorId === actorTags.actorId) }"
>
<span class="tag-name">{{ tag.name }}</span>
<Icon
v-if="edits.tags && !edits.tags.some((sceneTag) => sceneTag.id === tag.id && sceneTag.actorId === actorTags.actorId)"
icon="checkmark"
class="add"
@click="emit('tags', edits.tags.concat(tag))"
/>
<Icon
v-else
icon="cross2"
class="remove"
@click="emit('tags', edits.tags.filter((sceneTag) => !(sceneTag.id === tag.id && sceneTag.actorId === actorTags.actorId)))"
/>
</li>
<li class="new">
<TagSearch
:disabled="!editing.has(item.key)"
@tag="(tag) => addTag(tag, actorTags.actor)"
>
<Icon
icon="plus3"
class="add"
/>
</TagSearch>
</li>
</ul>
</div>
</div>
</template> </template>
<script setup> <script setup>
@@ -70,8 +83,23 @@ const props = defineProps({
const emit = defineEmits(['tags']); const emit = defineEmits(['tags']);
function addTag(tag) { const tags = [
if (props.edits.tags.some((tagId) => tagId === tag.id)) { {
tags: props.item.value.filter((tag) => tag.actorId === null),
actor: null,
actorId: null,
},
...props.scene.actors.map((actor) => ({
tags: props.item.value.filter((tag) => tag.actorId === actor.id),
actor,
actorId: actor?.id || null,
})),
];
function addTag(newTag, actor) {
const actorId = actor?.id || null;
if (props.edits.tags.some((sceneTag) => sceneTag.id === newTag.id && sceneTag.actorId === actorId)) {
events.emit('feedback', { events.emit('feedback', {
type: 'error', type: 'error',
message: 'Tag already added', message: 'Tag already added',
@@ -80,9 +108,13 @@ function addTag(tag) {
return; return;
} }
newTags.value = newTags.value.concat(tag); const newTagWithActorId = {
...newTag,
actorId,
};
emit('tags', props.edits.tags.concat(tag.id)); newTags.value = newTags.value.concat(newTagWithActorId);
emit('tags', props.edits.tags.concat(newTagWithActorId));
} }
watch(() => props.scene, () => { newTags.value = []; }); watch(() => props.scene, () => { newTags.value = []; });
@@ -116,7 +148,7 @@ watch(() => props.scene, () => { newTags.value = []; });
align-items: center; align-items: center;
margin-left: .25rem; margin-left: .25rem;
&:hover { &:hover .icon {
box-shadow: 0 0 3px var(--shadow-weak-20); box-shadow: 0 0 3px var(--shadow-weak-20);
} }
@@ -129,6 +161,18 @@ watch(() => props.scene, () => { newTags.value = []; });
} }
} }
.tags-sections {
display: flex;
flex-direction: column;
gap: .75rem;
margin: .5rem 0;
}
.tags-actor {
margin-right: .5rem;
font-weight: bold;
}
.tag { .tag {
display: flex; display: flex;
align-items: stretch; align-items: stretch;
@@ -145,9 +189,11 @@ watch(() => props.scene, () => { newTags.value = []; });
.tag, .tag,
.new { .new {
.remove, .remove,
.add { .add,
.actor {
height: auto; height: auto;
padding: .25rem .3rem; padding: .25rem .3rem;
margin-left: .25rem;
border-radius: .25rem; border-radius: .25rem;
fill: var(--highlight-strong-10); fill: var(--highlight-strong-10);

View File

@@ -140,26 +140,30 @@
</li> </li>
</ul> </ul>
<div <div class="tags">
v-for="actorTags in tags" <div
:key="`tags-${actorTags.actor?.name || 'scene'}`" v-for="(actorTags, index) in tags"
> :key="`tags-${actorTags.actor?.slug || 'scene'}`"
<ul class="tags nolist"> class="tags-section"
<li :class="{ space: index > 1 }"
v-if="actorTags.actor" >
class="tags-actor" <ul class="nolist">
>{{ actorTags.actor.name }}:</li> <li
v-if="actorTags.actor"
class="tags-actor"
>{{ actorTags.actor.name }}:</li>
<li <li
v-for="tag in actorTags.tags" v-for="tag in actorTags.tags"
:key="`tag-${tag.id}`" :key="`tag-${tag.id}`"
> >
<Link <Link
:href="`/tag/${tag.slug}`" :href="`/tag/${tag.slug}`"
class="tag nolink" class="tag nolink"
>{{ tag.name }}</Link> >{{ tag.name }}</Link>
</li> </li>
</ul> </ul>
</div>
</div> </div>
<div <div
@@ -658,6 +662,20 @@ function copySummary() {
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.tags {
display: flex;
flex-wrap: wrap;
gap: .25rem;
}
.tags-section {
display: inline-flex;
&.space {
margin-left: .5rem;
}
}
.tags-actor { .tags-actor {
margin-right: .5rem; margin-right: .5rem;
font-weight: bold; font-weight: bold;

View File

@@ -261,6 +261,7 @@ const fields = computed(() => [
key: 'tags', key: 'tags',
type: 'tags', type: 'tags',
value: scene.value.tags.toSorted((tagA, tagB) => tagA.name.localeCompare(tagB.name)), value: scene.value.tags.toSorted((tagA, tagB) => tagA.name.localeCompare(tagB.name)),
simplify: false,
}, },
{ {
key: 'movies', key: 'movies',

View File

@@ -785,9 +785,10 @@ async function applySceneTagsDelta(sceneId, delta, trx) {
if (delta.value.length > 0) { if (delta.value.length > 0) {
await knexOwner('releases_tags') await knexOwner('releases_tags')
.insert(delta.value.map((tagId) => ({ .insert(delta.value.map((tag) => ({
release_id: sceneId, release_id: sceneId,
tag_id: tagId, tag_id: tag.id,
actor_id: tag.actorId,
source: 'editor', source: 'editor',
}))) })))
.transacting(trx); .transacting(trx);