Added quick alert button to actor bio.
This commit is contained in:
parent
45a0631c9b
commit
61ed171c9d
|
@ -418,6 +418,13 @@ const email = ref(false);
|
||||||
const stashes = ref([]);
|
const stashes = ref([]);
|
||||||
|
|
||||||
async function createAlert() {
|
async function createAlert() {
|
||||||
|
const alertLabel = [
|
||||||
|
...actors.value.map((actor) => actor.name),
|
||||||
|
...tags.value.map((tag) => tag.name),
|
||||||
|
...entities.value.map((entity) => entity.name),
|
||||||
|
...matches.value.map((match) => match.expression),
|
||||||
|
].filter(Boolean).join(', ');
|
||||||
|
|
||||||
await post('/alerts', {
|
await post('/alerts', {
|
||||||
all: fieldsAnd.value,
|
all: fieldsAnd.value,
|
||||||
allActors: actorAnd.value,
|
allActors: actorAnd.value,
|
||||||
|
@ -430,7 +437,11 @@ async function createAlert() {
|
||||||
notify: notify.value,
|
notify: notify.value,
|
||||||
email: email.value,
|
email: email.value,
|
||||||
stashes: stashes.value.map((stash) => stash.id),
|
stashes: stashes.value.map((stash) => stash.id),
|
||||||
}, { appendErrorMessage: true });
|
}, {
|
||||||
|
successFeedback: `Alert for '${alertLabel}' set`,
|
||||||
|
errorFeedback: `Failed to set alert for '${alertLabel}'`,
|
||||||
|
appendErrorMessage: true,
|
||||||
|
});
|
||||||
|
|
||||||
emit('close', true);
|
emit('close', true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,34 @@
|
||||||
v-if="user"
|
v-if="user"
|
||||||
class="bookmarks"
|
class="bookmarks"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
v-if="showSecondary && !!itemAlerts"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
v-if="itemAlerted"
|
||||||
|
icon="bell2"
|
||||||
|
:title="`Remove alerts for '${item.title || item.name}'`"
|
||||||
|
class="alert active noselect"
|
||||||
|
@click="removeAlert"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
v-else-if="itemAlerts.multi.length > 0"
|
||||||
|
icon="bell-plus"
|
||||||
|
:title="`Set alert for '${item.title || item.name}', ${itemAlerts.multi.length} combined alert${itemAlerts.multi.length > 1 ? 's' : ''} active`"
|
||||||
|
class="alert partial noselect"
|
||||||
|
@click="alertItem"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
v-else
|
||||||
|
icon="bell-plus"
|
||||||
|
:title="`Set alert for '${item.title || item.name}' releases`"
|
||||||
|
class="alert noselect"
|
||||||
|
@click="alertItem"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<VDropdown
|
<VDropdown
|
||||||
v-if="showSecondary || (hasSecondaryStash && pageStash?.user.id !== user.id)"
|
v-if="showSecondary || (hasSecondaryStash && pageStash?.user.id !== user.id)"
|
||||||
:shown="showStashes"
|
:shown="showStashes"
|
||||||
|
@ -119,11 +147,19 @@ const pageContext = inject('pageContext');
|
||||||
const pageStash = pageContext.pageProps.stash;
|
const pageStash = pageContext.pageProps.stash;
|
||||||
const user = pageContext.user;
|
const user = pageContext.user;
|
||||||
|
|
||||||
|
console.log(props.item, props.item.alerts);
|
||||||
|
|
||||||
const stashes = ref(pageContext.assets?.stashes);
|
const stashes = ref(pageContext.assets?.stashes);
|
||||||
const primaryStash = pageContext.assets?.primaryStash;
|
const primaryStash = pageContext.assets?.primaryStash;
|
||||||
const itemStashes = ref(props.item.stashes);
|
const itemStashes = ref(props.item.stashes);
|
||||||
|
const itemAlerts = ref(props.item.alerts);
|
||||||
|
const itemAlerted = ref(props.item.alerts?.only.length > 0);
|
||||||
const hasSecondaryStash = computed(() => itemStashes.value.some((itemStash) => !itemStash.isPrimary));
|
const hasSecondaryStash = computed(() => itemStashes.value.some((itemStash) => !itemStash.isPrimary));
|
||||||
|
|
||||||
|
if (props.domain === 'actors') {
|
||||||
|
console.log(itemAlerts.value);
|
||||||
|
}
|
||||||
|
|
||||||
const done = ref(true);
|
const done = ref(true);
|
||||||
const showStashes = ref(false);
|
const showStashes = ref(false);
|
||||||
const showStashDialog = ref(false);
|
const showStashDialog = ref(false);
|
||||||
|
@ -154,9 +190,9 @@ async function stashItem(stash) {
|
||||||
emit('stashed', stash);
|
emit('stashed', stash);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
itemStashes.value = stashState;
|
itemStashes.value = stashState;
|
||||||
|
} finally {
|
||||||
|
done.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
done.value = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function unstashItem(stash) {
|
async function unstashItem(stash) {
|
||||||
|
@ -178,9 +214,68 @@ async function unstashItem(stash) {
|
||||||
emit('unstashed', stash);
|
emit('unstashed', stash);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
itemStashes.value = stashState;
|
itemStashes.value = stashState;
|
||||||
|
} finally {
|
||||||
|
done.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function alertItem() {
|
||||||
|
if (!done.value) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
done.value = true;
|
const alertLabel = props.item.title || props.item.name;
|
||||||
|
|
||||||
|
done.value = false;
|
||||||
|
itemAlerted.value = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const newAlert = await post('/alerts', {
|
||||||
|
...(props.domain === 'actors' && { actors: [props.item.id] }),
|
||||||
|
...(props.domain === 'tags' && { tags: [props.item.id] }),
|
||||||
|
...(props.domain === 'entities' && { entities: [props.item.id] }),
|
||||||
|
notify: true,
|
||||||
|
email: false,
|
||||||
|
preset: true,
|
||||||
|
}, {
|
||||||
|
successFeedback: `Alert set for '${alertLabel}'`,
|
||||||
|
errorFeedback: `Failed to set alert for '${alertLabel}'`,
|
||||||
|
appendErrorMessage: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
itemAlerts.value.only = itemAlerts.value.only.concat(newAlert.id);
|
||||||
|
} catch (error) {
|
||||||
|
itemAlerted.value = false;
|
||||||
|
} finally {
|
||||||
|
done.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeAlert() {
|
||||||
|
if (done.value === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const alertLabel = props.item.title || props.item.name;
|
||||||
|
const alertIds = itemAlerts.value.only;
|
||||||
|
|
||||||
|
done.value = false;
|
||||||
|
|
||||||
|
itemAlerted.value = false;
|
||||||
|
itemAlerts.value.only = itemAlerts.value.only.filter((alertId) => !alertIds.includes(alertId));
|
||||||
|
|
||||||
|
try {
|
||||||
|
await del(`/alerts/${alertIds.join(',')}`, {
|
||||||
|
undoFeedback: `Removed alert for '${alertLabel}'`,
|
||||||
|
errorFeedback: `Failed to remove alert for '${alertLabel}'`,
|
||||||
|
appendErrorMessage: true,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
itemAlerted.value = true;
|
||||||
|
itemAlerts.value.only = itemAlerts.value.only.concat(alertIds);
|
||||||
|
} finally {
|
||||||
|
done.value = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleShowStashes(state) {
|
function toggleShowStashes(state) {
|
||||||
|
@ -229,10 +324,22 @@ async function reloadStashes(newStash) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon.alert {
|
||||||
|
width: 1.3rem;
|
||||||
|
padding: .7rem .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.icon.heart:hover,
|
.icon.heart:hover,
|
||||||
.icon.heart.favorited {
|
.icon.alert:hover,
|
||||||
|
.icon.heart.favorited,
|
||||||
|
.icon.alert.active {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
fill: var(--primary);
|
fill: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon.alert.partial {
|
||||||
|
cursor: pointer;
|
||||||
|
fill: var(--text-light);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -357,8 +357,6 @@ const pageContext = inject('pageContext');
|
||||||
const user = pageContext.user;
|
const user = pageContext.user;
|
||||||
const actor = ref(pageContext.pageProps.actor);
|
const actor = ref(pageContext.pageProps.actor);
|
||||||
|
|
||||||
// console.log(actor.value);
|
|
||||||
|
|
||||||
const fields = computed(() => [
|
const fields = computed(() => [
|
||||||
...(actor.value.photos.length > 0 ? [{
|
...(actor.value.photos.length > 0 ? [{
|
||||||
key: 'avatar',
|
key: 'avatar',
|
||||||
|
|
|
@ -166,6 +166,10 @@ export function curateActor(actor, context = {}) {
|
||||||
scenes: actor.scenes,
|
scenes: actor.scenes,
|
||||||
likes: actor.stashed,
|
likes: actor.stashed,
|
||||||
stashes: context.stashes?.map((stash) => curateStash(stash)) || [],
|
stashes: context.stashes?.map((stash) => curateStash(stash)) || [],
|
||||||
|
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?.[actor.id],
|
...context.append?.[actor.id],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -198,7 +202,7 @@ export function sortActorsByGender(actors, context = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchActorsById(actorIds, options = {}, reqUser) {
|
export async function fetchActorsById(actorIds, options = {}, reqUser) {
|
||||||
const [actors, profiles, photos, socials, stashes] = await Promise.all([
|
const [actors, profiles, photos, socials, stashes, alerts] = await Promise.all([
|
||||||
knex('actors')
|
knex('actors')
|
||||||
.select(
|
.select(
|
||||||
'actors.*',
|
'actors.*',
|
||||||
|
@ -253,11 +257,17 @@ export async function fetchActorsById(actorIds, options = {}, reqUser) {
|
||||||
.where('stashes.user_id', reqUser.id)
|
.where('stashes.user_id', reqUser.id)
|
||||||
.whereIn('stashes_actors.actor_id', actorIds)
|
.whereIn('stashes_actors.actor_id', actorIds)
|
||||||
: [],
|
: [],
|
||||||
|
reqUser
|
||||||
|
? knex('alerts_users_actors')
|
||||||
|
.where('user_id', reqUser.id)
|
||||||
|
.whereIn('actor_id', actorIds)
|
||||||
|
: [],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (options.order) {
|
if (options.order) {
|
||||||
return actors.map((actorEntry) => curateActor(actorEntry, {
|
return actors.map((actorEntry) => curateActor(actorEntry, {
|
||||||
stashes: stashes.filter((stash) => stash.actor_id === actorEntry.id),
|
stashes: stashes.filter((stash) => stash.actor_id === actorEntry.id),
|
||||||
|
alerts: alerts.filter((alert) => alert.actor_id === actorEntry.id),
|
||||||
append: options.append,
|
append: options.append,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -272,6 +282,7 @@ export async function fetchActorsById(actorIds, options = {}, reqUser) {
|
||||||
|
|
||||||
return curateActor(actor, {
|
return curateActor(actor, {
|
||||||
stashes: stashes.filter((stash) => stash.actor_id === actor.id),
|
stashes: stashes.filter((stash) => stash.actor_id === actor.id),
|
||||||
|
alerts: alerts.filter((alert) => alert.actor_id === actor.id),
|
||||||
profiles: profiles.filter((profile) => profile.actor_id === actor.id),
|
profiles: profiles.filter((profile) => profile.actor_id === actor.id),
|
||||||
photos: photos.filter((photo) => photo.actor_id === actor.id),
|
photos: photos.filter((photo) => photo.actor_id === actor.id),
|
||||||
socials: socials.filter((social) => social.actor_id === actor.id),
|
socials: socials.filter((social) => social.actor_id === actor.id),
|
||||||
|
|
|
@ -120,6 +120,7 @@ export async function createAlert(alert, reqUser) {
|
||||||
all_entities: alert.allEntities,
|
all_entities: alert.allEntities,
|
||||||
all_tags: alert.allTags,
|
all_tags: alert.allTags,
|
||||||
all_matches: alert.allMatches,
|
all_matches: alert.allMatches,
|
||||||
|
from_preset: alert.preset,
|
||||||
})
|
})
|
||||||
.returning('id');
|
.returning('id');
|
||||||
|
|
||||||
|
@ -149,14 +150,43 @@ export async function createAlert(alert, reqUser) {
|
||||||
})).slice(0, alert.allEntities ? 1 : Infinity)), // one scene can never match multiple entities in AND mode
|
})).slice(0, alert.allEntities ? 1 : Infinity)), // one scene can never match multiple entities in AND mode
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
alert.actors?.length > 0 && knex.schema.refreshMaterializedView('alerts_users_actors'),
|
||||||
|
alert.tags?.length > 0 && knex.schema.refreshMaterializedView('alerts_users_tags'),
|
||||||
|
alert.entities?.length > 0 && knex.schema.refreshMaterializedView('alerts_users_entities'),
|
||||||
|
]);
|
||||||
|
|
||||||
return alertId;
|
return alertId;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeAlert(alertId, reqUser) {
|
export async function removeAlert(alertId, reqUser) {
|
||||||
|
const alert = await knex('alerts')
|
||||||
|
.where('alerts.id', alertId)
|
||||||
|
.select(
|
||||||
|
'alerts.id',
|
||||||
|
knex.raw('coalesce(array_agg(distinct alerts_actors.actor_id) filter (where alerts_actors.actor_id is not null), \'{}\') as actor_ids'),
|
||||||
|
knex.raw('coalesce(array_agg(distinct alerts_entities.entity_id) filter (where alerts_entities.entity_id is not null), \'{}\') as entity_ids'),
|
||||||
|
knex.raw('coalesce(array_agg(distinct alerts_tags.tag_id) filter (where alerts_tags.tag_id is not null), \'{}\') as tag_ids'),
|
||||||
|
)
|
||||||
|
.leftJoin('alerts_actors', 'alerts_actors.alert_id', 'alerts.id')
|
||||||
|
.leftJoin('alerts_entities', 'alerts_entities.alert_id', 'alerts.id')
|
||||||
|
.leftJoin('alerts_tags', 'alerts_tags.alert_id', 'alerts.id')
|
||||||
|
.leftJoin('alerts_matches', 'alerts_matches.alert_id', 'alerts.id')
|
||||||
|
.groupBy('alerts.id')
|
||||||
|
.first();
|
||||||
|
|
||||||
|
console.log(alertId, alert);
|
||||||
|
|
||||||
await knex('alerts')
|
await knex('alerts')
|
||||||
.where('id', alertId)
|
.where('id', alertId)
|
||||||
.where('user_id', reqUser.id)
|
.where('user_id', reqUser.id)
|
||||||
.delete();
|
.delete();
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
alert.actor_ids.length > 0 && knex.schema.refreshMaterializedView('alerts_users_actors'),
|
||||||
|
alert.tag_ids.length > 0 && knex.schema.refreshMaterializedView('alerts_users_tags'),
|
||||||
|
alert.entity_ids?.length > 0 && knex.schema.refreshMaterializedView('alerts_users_entities'),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchUnseenNotificationsCount(reqUser) {
|
export async function fetchUnseenNotificationsCount(reqUser) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ export async function createAlertApi(req, res) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeAlertApi(req, res) {
|
export async function removeAlertApi(req, res) {
|
||||||
await removeAlert(req.params.alertId, req.user);
|
await Promise.all(req.params.alertId.split(',').map(async (alertId) => removeAlert(alertId, req.user)));
|
||||||
|
|
||||||
res.status(204).send();
|
res.status(204).send();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue