Added toggle to select actor tags or all tags in filters.

This commit is contained in:
2026-03-07 02:09:04 +01:00
parent b5726aec84
commit 6877ee75ed
5 changed files with 78 additions and 13 deletions

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generated by IcoMoon.io -->
<svg
version="1.1"
width="16"
height="16"
viewBox="0 0 16 16"
id="svg2"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<path
id="path2"
d="M 7 0 C 4 0 4 2.015 4 4.5 C 4 6.048 4.898 7.5957969 6 8.2167969 L 6 9.0410156 C 2.608 9.3180156 0 10.985 0 13 L 4.9726562 13 C 4.6689986 12.449922 4.7486357 11.731833 5.2109375 11.269531 L 8 8.4804688 L 8 8.2167969 C 9.102 7.5957969 10 6.048 10 4.5 C 10 2.015 10 0 7 0 z M 9 11.509766 L 8.2167969 12.292969 L 8.9238281 13 L 9 13 L 9 11.509766 z " />
<g
id="g2"
transform="matrix(0.51568847,0,0,0.51568847,5.8471254,8.4255678)">
<path
d="m 18.938,-1 h -6 c -0.412,0 -0.989,0.239 -1.28,0.53 L 4.219,6.969 c -0.292,0.292 -0.292,0.769 0,1.061 l 6.439,6.439 c 0.292,0.292 0.769,0.292 1.061,0 L 19.158,7.03 c 0.292,-0.292 0.53,-0.868 0.53,-1.28 v -6 c 0,-0.412 -0.337,-0.75 -0.75,-0.75 z m -3.75,6 c -0.828,0 -1.5,-0.672 -1.5,-1.5 0,-0.828 0.672,-1.5 1.5,-1.5 0.828,0 1.5,0.672 1.5,1.5 0,0.828 -0.672,1.5 -1.5,1.5 z"
id="path1-5" />
<path
d="m 1.688,7.5 8.5,-8.5 h -1.25 c -0.412,0 -0.989,0.239 -1.28,0.53 L 0.219,6.969 c -0.292,0.292 -0.292,0.769 0,1.061 l 6.439,6.439 c 0.292,0.292 0.769,0.292 1.061,0 l 0.47,-0.47 -6.5,-6.5 z"
id="path2-3" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -12,14 +12,30 @@
<Icon icon="search" /> <Icon icon="search" />
</label> </label>
<div
v-show="showActorTags"
v-tooltip="'Tags relevant to the selected actors'"
class="filter-sort order noselect"
@click="showActorTags = false"
>
<Icon icon="user-tags" />
</div>
<div
v-show="!showActorTags"
v-tooltip="'All tags'"
class="filter-sort order noselect"
@click="showActorTags = true"
>
<Icon icon="price-tags" />
</div>
<div <div
v-show="order === 'priority'" v-show="order === 'priority'"
class="filter-sort order noselect" class="filter-sort order noselect"
@click="order = 'count'" @click="order = 'count'"
> >
<Icon <Icon icon="star" />
icon="star"
/>
</div> </div>
<div <div
@@ -115,16 +131,21 @@ const props = defineProps({
type: Array, type: Array,
default: () => [], default: () => [],
}, },
actorTags: {
type: Array,
default: () => [],
},
}); });
const emit = defineEmits(['update']); const emit = defineEmits(['update']);
const { pageProps } = inject('pageContext');
const { tag: pageTag, actor: pageActor } = pageProps;
const search = ref(''); const search = ref('');
const searchRegexp = computed(() => new RegExp(search.value, 'i')); const searchRegexp = computed(() => new RegExp(search.value, 'i'));
const order = ref('priority'); const order = ref('priority');
const showActorTags = ref(true);
const { pageProps } = inject('pageContext');
const { tag: pageTag } = pageProps;
const priorityTags = [ const priorityTags = [
'anal', 'anal',
@@ -148,8 +169,12 @@ const priorityTags = [
]; ];
const groupedTags = computed(() => { const groupedTags = computed(() => {
const selected = props.tags.filter((tag) => props.filters.tags.includes(tag.slug)); const tags = showActorTags.value && props.actorTags && (props.filters.actors.length > 0 || pageActor)
const filtered = props.tags.filter((tag) => !props.filters.tags.includes(tag.slug) ? props.actorTags
: props.tags;
const selected = tags.filter((tag) => props.filters.tags.includes(tag.slug));
const filtered = tags.filter((tag) => !props.filters.tags.includes(tag.slug)
&& tag.id !== pageTag?.id && tag.id !== pageTag?.id
&& searchRegexp.value.test(tag.name)); && searchRegexp.value.test(tag.name));

View File

@@ -34,6 +34,7 @@
<TagsFilter <TagsFilter
:filters="filters" :filters="filters"
:tags="aggTags" :tags="aggTags"
:actor-tags="aggActorTags"
@update="updateFilter" @update="updateFilter"
/> />
@@ -263,6 +264,7 @@ const scenes = ref(pageProps.scenes);
const aggYears = ref(pageProps.aggYears || []); const aggYears = ref(pageProps.aggYears || []);
const aggActors = ref(pageProps.aggActors || []); const aggActors = ref(pageProps.aggActors || []);
const aggTags = ref(pageProps.aggTags || []); const aggTags = ref(pageProps.aggTags || []);
const aggActorTags = ref(pageProps.aggActorTags || []);
const aggChannels = ref(pageProps.aggChannels || []); const aggChannels = ref(pageProps.aggChannels || []);
const currentPage = ref(Number(routeParams.page)); const currentPage = ref(Number(routeParams.page));
@@ -363,6 +365,7 @@ async function search(options = {}) {
aggYears.value = res.aggYears; aggYears.value = res.aggYears;
aggActors.value = res.aggActors; aggActors.value = res.aggActors;
aggTags.value = res.aggTags; aggTags.value = res.aggTags;
aggActorTags.value = res.aggActorTags;
aggChannels.value = res.aggChannels; aggChannels.value = res.aggChannels;
total.value = res.total; total.value = res.total;

View File

@@ -424,6 +424,7 @@ async function queryManticoreSql(filters, options, _reqUser) {
:yearsFacet: :yearsFacet:
:actorsFacet: :actorsFacet:
:tagsFacet: :tagsFacet:
:actorTagsFacet:
:channelsFacet: :channelsFacet:
:studiosFacet:; :studiosFacet:;
show meta; show meta;
@@ -566,10 +567,9 @@ async function queryManticoreSql(filters, options, _reqUser) {
yearsFacet: options.aggregateYears ? knex.raw('facet effective_year as years_facet order by effective_year desc limit ?', [aggSize]) : null, yearsFacet: options.aggregateYears ? knex.raw('facet effective_year as years_facet order by effective_year desc limit ?', [aggSize]) : null,
actorsFacet: options.aggregateActors ? knex.raw('facet scenes.actor_ids as actors_facet distinct id order by count(distinct id) desc limit ?', [aggSize]) : null, actorsFacet: options.aggregateActors ? knex.raw('facet scenes.actor_ids as actors_facet distinct id order by count(distinct id) desc limit ?', [aggSize]) : null,
// don't facet tags associated to other actors, actor ID 0 means global // don't facet tags associated to other actors, actor ID 0 means global
tagsFacet: options.aggregateTags // eslint-disable-line no-nested-ternary tagsFacet: options.aggregateTags ? knex.raw('facet scenes.tag_ids as tags_facet order by count(distinct id) desc limit ?', [aggSize]) : null,
? (filters.stashId || !filters?.actorIds || filters.actorIds.length === 0 // we can't join the tags table as well as the stashes table actorTagsFacet: options.aggregateTags && !filters.stashId // eslint-disable-line no-nested-ternary
? knex.raw('facet scenes.tag_ids as tags_facet order by count(distinct id) desc limit ?', [aggSize]) ? knex.raw(`facet IF(IN(scenes_tags.actor_id, ${[0, ...filters?.actorIds || []]}), scenes_tags.tag_id, 0) actor_tags_facet distinct id order by count(distinct id) desc limit ?`, [aggSize])
: knex.raw(`facet IF(IN(scenes_tags.actor_id, ${[0, ...filters?.actorIds || []]}), scenes_tags.tag_id, 0) tags_facet distinct id order by count(distinct id) desc limit ?`, [aggSize]))
: null, : null,
channelsFacet: options.aggregateChannels ? knex.raw('facet scenes.channel_id as channels_facet distinct id order by count(distinct id) desc limit ?', [aggSize]) : null, channelsFacet: options.aggregateChannels ? knex.raw('facet scenes.channel_id as channels_facet distinct id order by count(distinct id) desc limit ?', [aggSize]) : null,
studiosFacet: options.aggregateChannels ? knex.raw('facet scenes.studio_id as studios_facet distinct id order by count(distinct id) desc limit ?', [aggSize]) : null, studiosFacet: options.aggregateChannels ? knex.raw('facet scenes.studio_id as studios_facet distinct id order by count(distinct id) desc limit ?', [aggSize]) : null,
@@ -607,6 +607,11 @@ async function queryManticoreSql(filters, options, _reqUser) {
?.data.map((row) => ({ key: row.tags_facet, doc_count: row['count(distinct id)'] || row['count(*)'] })) ?.data.map((row) => ({ key: row.tags_facet, doc_count: row['count(distinct id)'] || row['count(*)'] }))
|| []; || [];
const actorTagIds = results
.find((result) => result.columns[0].actor_tags_facet && result.columns[1]['count(distinct id)'])
?.data.map((row) => ({ key: row.actor_tags_facet, doc_count: row['count(distinct id)'] || row['count(*)'] }))
|| [];
const channelIds = results const channelIds = results
.find((result) => result.columns[0].channels_facet && result.columns[1]['count(distinct id)']) .find((result) => result.columns[0].channels_facet && result.columns[1]['count(distinct id)'])
?.data.map((row) => ({ key: row.channels_facet || row['scenes.channel_id'], doc_count: row['count(distinct id)'] })) ?.data.map((row) => ({ key: row.channels_facet || row['scenes.channel_id'], doc_count: row['count(distinct id)'] }))
@@ -626,6 +631,7 @@ async function queryManticoreSql(filters, options, _reqUser) {
years, years,
actorIds, actorIds,
tagIds, tagIds,
actorTagIds,
channelIds, channelIds,
studioIds, studioIds,
}, },
@@ -663,9 +669,10 @@ export async function fetchScenes(filters, rawOptions, reqUser, context) {
console.time('fetch aggregations'); console.time('fetch aggregations');
const [aggActors, aggTags, aggChannels] = await Promise.all([ const [aggActors, aggTags, aggActorTags, aggChannels] = await Promise.all([
options.aggregateActors ? fetchActorsById(result.aggregations.actorIds.map((bucket) => bucket.key), { shallow: true, order: ['slug', 'asc'], append: actorCounts }, reqUser) : [], options.aggregateActors ? fetchActorsById(result.aggregations.actorIds.map((bucket) => bucket.key), { shallow: true, order: ['slug', 'asc'], append: actorCounts }, reqUser) : [],
options.aggregateTags ? fetchTagsById(result.aggregations.tagIds.map((bucket) => bucket.key), { order: [knex.raw('lower(name)'), 'asc'], append: tagCounts }, reqUser, context) : [], options.aggregateTags ? fetchTagsById(result.aggregations.tagIds.map((bucket) => bucket.key), { order: [knex.raw('lower(name)'), 'asc'], append: tagCounts }, reqUser, context) : [],
options.aggregateTags ? fetchTagsById(result.aggregations.actorTagIds.map((bucket) => bucket.key), { order: [knex.raw('lower(name)'), 'asc'], append: tagCounts }, reqUser, context) : [],
options.aggregateChannels ? fetchEntitiesById(entityIds.map((bucket) => bucket.key), { order: ['slug', 'asc'], append: channelCounts }, reqUser, context) : [], options.aggregateChannels ? fetchEntitiesById(entityIds.map((bucket) => bucket.key), { order: ['slug', 'asc'], append: channelCounts }, reqUser, context) : [],
]); ]);
@@ -681,6 +688,7 @@ export async function fetchScenes(filters, rawOptions, reqUser, context) {
aggYears, aggYears,
aggActors, aggActors,
aggTags, aggTags,
aggActorTags,
aggChannels, aggChannels,
total: result.total, total: result.total,
limit: options.limit, limit: options.limit,

View File

@@ -59,6 +59,7 @@ async function fetchScenesApi(req, res) {
aggYears, aggYears,
aggActors, aggActors,
aggTags, aggTags,
aggActorTags,
aggChannels, aggChannels,
limit, limit,
total, total,
@@ -77,6 +78,7 @@ async function fetchScenesApi(req, res) {
aggYears, aggYears,
aggActors, aggActors,
aggTags, aggTags,
aggActorTags,
aggChannels, aggChannels,
limit, limit,
total, total,