Added quick alert buttons to entity and tag headers.

This commit is contained in:
DebaucheryLibrarian 2025-03-09 06:00:18 +01:00
parent 61ed171c9d
commit c6c4dcad7c
9 changed files with 118 additions and 61 deletions

View File

@ -32,7 +32,7 @@
</div>
<VDropdown
v-if="showSecondary || (hasSecondaryStash && pageStash?.user.id !== user.id)"
v-if="itemStashes && (showSecondary || (hasSecondaryStash && pageStash?.user.id !== user.id))"
:shown="showStashes"
@hide="showStashes = false"
>
@ -55,7 +55,7 @@
</VDropdown>
<VDropdown
v-if="showSecondary || !hasSecondaryStash || pageStash?.user.id === user.id"
v-if="itemStashes && (showSecondary || !hasSecondaryStash || pageStash?.user.id === user.id)"
:triggers="[]"
:shown="showStashes"
:disabled="showSecondary"
@ -147,8 +147,6 @@ const pageContext = inject('pageContext');
const pageStash = pageContext.pageProps.stash;
const user = pageContext.user;
console.log(props.item, props.item.alerts);
const stashes = ref(pageContext.assets?.stashes);
const primaryStash = pageContext.assets?.primaryStash;
const itemStashes = ref(props.item.stashes);
@ -156,10 +154,6 @@ const itemAlerts = ref(props.item.alerts);
const itemAlerted = ref(props.item.alerts?.only.length > 0);
const hasSecondaryStash = computed(() => itemStashes.value.some((itemStash) => !itemStash.isPrimary));
if (props.domain === 'actors') {
console.log(itemAlerts.value);
}
const done = ref(true);
const showStashes = ref(false);
const showStashDialog = ref(false);

View File

@ -1,46 +1,54 @@
<template>
<div class="page">
<div class="header">
<a
:href="entityUrl"
target="_blank"
rel="noopener"
class="link-child nolink"
:data-umami-event="entity.affiliate ? 'entity-click-aff' : 'entity-click'"
:data-umami-event-aff-id="entity.affiliate?.id"
:data-umami-event-entity="entity.slug"
>
<template v-if="entity.hasLogo">
<img
v-if="entity.type === 'network'"
class="logo logo-child"
:alt="entity.name"
:title="`${entity.name} (#${entity.id})`"
:src="`/logos/${entity.slug}/thumbs/network.png`"
>
<div class="entity-container">
<a
:href="entityUrl"
target="_blank"
rel="noopener"
class="link-child nolink"
:data-umami-event="entity.affiliate ? 'entity-click-aff' : 'entity-click'"
:data-umami-event-aff-id="entity.affiliate?.id"
:data-umami-event-entity="entity.slug"
>
<template v-if="entity.hasLogo">
<img
v-if="entity.type === 'network'"
class="logo logo-child"
:alt="entity.name"
:title="`${entity.name} (#${entity.id})`"
:src="`/logos/${entity.slug}/thumbs/network.png`"
>
<img
v-else-if="entity.parent && !entity.isIndependent"
class="logo logo-child"
:alt="entity.name"
:title="`${entity.name} (#${entity.id})`"
:src="`/logos/${entity.parent.slug}/thumbs/${entity.slug}.png`"
>
<img
v-else-if="entity.parent && !entity.isIndependent"
class="logo logo-child"
:alt="entity.name"
:title="`${entity.name} (#${entity.id})`"
:src="`/logos/${entity.parent.slug}/thumbs/${entity.slug}.png`"
>
<img
<img
v-else
class="logo logo-child"
:alt="entity.name"
:title="`${entity.name} (#${entity.id})`"
:src="`/logos/${entity.slug}/thumbs/${entity.slug}.png`"
>
</template>
<h2
v-else
class="logo logo-child"
:alt="entity.name"
:title="`${entity.name} (#${entity.id})`"
:src="`/logos/${entity.slug}/thumbs/${entity.slug}.png`"
>
</template>
class="name"
>{{ entity.name }}</h2>
</a>
<h2
v-else
class="name"
>{{ entity.name }}</h2>
</a>
<Heart
domain="entities"
:item="entity"
class="light"
/>
</div>
<Domains
:domain="domain"
@ -144,6 +152,7 @@ import EntityTile from '#/components/entities/tile.vue';
import Scenes from '#/components/scenes/scenes.vue';
import Movies from '#/components/movies/movies.vue';
import Domains from '#/components/domains/domains.vue';
import Heart from '#/components/stashes/heart.vue';
const { pageProps, routeParams } = inject('pageContext');
const { entity } = pageProps;
@ -201,6 +210,11 @@ const entityUrl = (() => {
}
}
.entity-container {
display: flex;
align-items: center;
}
.name {
display: block;
padding: 1rem;
@ -229,6 +243,10 @@ const entityUrl = (() => {
position: relative;
}
.bookmarks {
margin: -.25rem 0 0 .25rem;
}
.children {
background: var(--grey-dark-50);
display: flex;

View File

@ -47,7 +47,7 @@ export async function onBeforeRender(pageContext) {
[entity],
entityReleases,
] = await Promise.all([
fetchEntitiesById([Number(entityId)], { includeChildren: true }),
fetchEntitiesById([Number(entityId)], { includeChildren: true }, pageContext.user),
fetchReleases(pageContext, entityId),
]);

View File

@ -2,6 +2,12 @@
<div class="page">
<div class="header">
<h2 class="title">{{ tag.name }}</h2>
<Heart
domain="tags"
:item="tag"
class="light"
/>
</div>
<div class="content">
@ -30,6 +36,7 @@ import { inject } from 'vue';
import Scenes from '#/components/scenes/scenes.vue';
import Movies from '#/components/movies/movies.vue';
import Domains from '#/components/domains/domains.vue';
import Heart from '#/components/stashes/heart.vue';
const pageContext = inject('pageContext');
const { tag, description } = pageContext.pageProps;
@ -59,11 +66,23 @@ const domain = pageContext.routeParams.domain;
}
.header {
padding: .5rem 1rem;
display: flex;
align-items: center;
padding: .25rem 1rem;
color: var(--text-light);
background: var(--grey-dark-40);
}
.bookmarks {
margin-left: .5rem;
:deep(.icon.alert) {
height: 1.25rem;
padding: .5rem .5rem .25rem .5rem;
overflow: hidden;
}
}
.title {
margin: 0;
text-transform: capitalize;

View File

@ -40,7 +40,7 @@ export async function onBeforeRender(pageContext) {
const tagSlug = pageContext.routeParams.tagSlug;
const [[tag], tagReleases, campaigns] = await Promise.all([
fetchTagsById([tagSlug]),
fetchTagsById([tagSlug], {}, pageContext.user),
fetchReleases(pageContext),
getRandomCampaigns([
{ tagSlugs: [tagSlug], minRatio: 1.5 },

View File

@ -485,10 +485,6 @@ async function queryManticoreSql(filters, options, _reqUser) {
export async function fetchActors(filters, rawOptions, reqUser) {
const options = curateOptions(rawOptions);
console.log('filters', filters);
console.log('options', options);
const result = await queryManticoreSql(filters, options, reqUser);
// console.log('result', result);

View File

@ -175,8 +175,6 @@ export async function removeAlert(alertId, reqUser) {
.groupBy('alerts.id')
.first();
console.log(alertId, alert);
await knex('alerts')
.where('id', alertId)
.where('user_id', reqUser.id)

View File

@ -26,6 +26,10 @@ export function curateEntity(entity, context) {
parameters: entity.affiliate.parameters,
} : null,
...context?.append?.[entity.id],
alerts: {
only: context?.alerts?.filter((alert) => alert.is_only).flatMap((alert) => alert.alert_ids) || [],
multi: context?.alerts?.filter((alert) => !alert.is_only).flatMap((alert) => alert.alert_ids) || [],
},
};
}
@ -74,8 +78,8 @@ export async function fetchEntities(options = {}) {
return entities.map((entityEntry) => curateEntity(entityEntry));
}
export async function fetchEntitiesById(entityIds, options = {}) {
const [entities, children] = await Promise.all([
export async function fetchEntitiesById(entityIds, options = {}, reqUser) {
const [entities, children, alerts] = await Promise.all([
knex('entities')
.select(
'entities.*',
@ -95,12 +99,18 @@ export async function fetchEntitiesById(entityIds, options = {}) {
.whereIn('entities.parent_id', entityIds)
.whereNot('type', 'info')
.orderBy('slug') : [],
reqUser
? knex('alerts_users_entities')
.where('user_id', reqUser.id)
.whereIn('entity_id', entityIds)
: [],
]);
if (options.order) {
return entities.map((entityEntry) => curateEntity(entityEntry, {
append: options.append,
children,
children: children.filter((channel) => channel.parent_id === entityEntry.id),
alerts: alerts.filter((alert) => alert.entity_id === entityEntry.id),
}));
}
@ -114,7 +124,8 @@ export async function fetchEntitiesById(entityIds, options = {}) {
return curateEntity(entity, {
append: options.append,
children,
children: children.filter((channel) => channel.parent_id === entity.id),
alerts: alerts.filter((alert) => alert.entity_id === entity.id),
});
}).filter(Boolean);

View File

@ -25,6 +25,10 @@ function curateTag(tag, context) {
parent: tag.poster.entity_parent,
}),
},
alerts: {
only: context?.alerts?.filter((alert) => alert.is_only).flatMap((alert) => alert.alert_ids) || [],
multi: context?.alerts?.filter((alert) => !alert.is_only).flatMap((alert) => alert.alert_ids) || [],
},
...context?.append?.[tag.id],
};
}
@ -75,8 +79,8 @@ export async function fetchTags(options = {}) {
}));
}
export async function fetchTagsById(tagIds, options = {}) {
const [tags, posters] = await Promise.all([
export async function fetchTagsById(tagIds, options = {}, reqUser) {
const [tags, posters, alerts] = await Promise.all([
knex('tags')
.whereIn('tags.id', tagIds.filter((tagId) => typeof tagId === 'number'))
.orWhereIn('tags.slug', tagIds.filter((tagId) => typeof tagId === 'string'))
@ -93,6 +97,17 @@ export async function fetchTagsById(tagIds, options = {}) {
.leftJoin('entities as parents', 'parents.id', 'entities.parent_id')
.whereIn('tags.id', tagIds.filter((tagId) => typeof tagId === 'number'))
.orWhereIn('tags.slug', tagIds.filter((tagId) => typeof tagId === 'string')),
reqUser
? knex('alerts_users_tags')
.select('alerts_users_tags.*')
.leftJoin('tags', 'tags.id', 'alerts_users_tags.tag_id')
.where('user_id', reqUser.id)
.where((whereBuilder) => {
whereBuilder
.whereIn('tags.id', tagIds.filter((tagId) => typeof tagId === 'number'))
.orWhereIn('tags.slug', tagIds.filter((tagId) => typeof tagId === 'string'));
})
: [],
]);
const postersByTagId = Object.fromEntries(posters.map((poster) => [poster.tag_id, poster]));
@ -101,7 +116,10 @@ export async function fetchTagsById(tagIds, options = {}) {
return tags.map((tagEntry) => curateTag({
...tagEntry,
poster: postersByTagId[tagEntry.id],
}, { append: options.append }));
}, {
alerts: alerts.filter((alert) => alert.tag_id === tagEntry.id),
append: options.append,
}));
}
const curatedTags = tagIds.map((tagId) => {
@ -115,7 +133,10 @@ export async function fetchTagsById(tagIds, options = {}) {
return curateTag({
...tag,
poster: postersByTagId[tag.id],
}, { append: options.append });
}, {
alerts: alerts.filter((alert) => alert.tag_id === tag.id),
append: options.append,
});
}).filter(Boolean);
return curatedTags;