forked from DebaucheryLibrarian/traxxx
Added AND/OR toggle to alerts.
This commit is contained in:
parent
238dce78b5
commit
0369446681
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<router-link
|
<RouterLink
|
||||||
:to="`/actor/${actor.id}/${actor.slug}`"
|
:to="`/actor/${actor.id}/${actor.slug}`"
|
||||||
|
:target="target"
|
||||||
class="actor nolink"
|
class="actor nolink"
|
||||||
>
|
>
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
|
@ -18,7 +19,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="name">{{ actor.name }}</span>
|
<span class="name">{{ actor.name }}</span>
|
||||||
</router-link>
|
</RouterLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -36,6 +37,10 @@ export default {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
target: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
unstashActor,
|
unstashActor,
|
||||||
|
|
|
@ -14,7 +14,17 @@
|
||||||
>
|
>
|
||||||
<div class="dialog-section">
|
<div class="dialog-section">
|
||||||
<h3 class="dialog-heading">
|
<h3 class="dialog-heading">
|
||||||
When<span class="dialog-description">All to appear in the same scene</span>
|
When
|
||||||
|
|
||||||
|
<label class="dialog-description noselect">
|
||||||
|
<template v-if="all">Scene must match <strong>all</strong> fields</template>
|
||||||
|
<template v-else>Scene must match <strong>any</strong> field</template>
|
||||||
|
|
||||||
|
<Toggle
|
||||||
|
:checked="all"
|
||||||
|
@change="(checked) => all = checked"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="alert-section">
|
<div class="alert-section">
|
||||||
|
@ -34,7 +44,10 @@
|
||||||
:key="`actor-${actor.id}`"
|
:key="`actor-${actor.id}`"
|
||||||
class="actor"
|
class="actor"
|
||||||
>
|
>
|
||||||
<ActorPreview :actor="actor" />
|
<ActorPreview
|
||||||
|
:actor="actor"
|
||||||
|
target="_blank"
|
||||||
|
/>
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
icon="cross3"
|
icon="cross3"
|
||||||
|
@ -109,10 +122,15 @@
|
||||||
|
|
||||||
<div class="entities">
|
<div class="entities">
|
||||||
<div
|
<div
|
||||||
v-if="entity"
|
v-for="(entity, index) in entities"
|
||||||
|
:key="`entity-${entity.id}`"
|
||||||
|
:class="{ invalid: all && index > 0 }"
|
||||||
class="entity"
|
class="entity"
|
||||||
>
|
>
|
||||||
<Entity :entity="entity" />
|
<Entity
|
||||||
|
:entity="entity"
|
||||||
|
target="_blank"
|
||||||
|
/>
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
icon="cross3"
|
icon="cross3"
|
||||||
|
@ -121,7 +139,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Tooltip v-if="!entity">
|
<Tooltip v-if="entities.length < 1 || !all">
|
||||||
<div class="entity placeholder">
|
<div class="entity placeholder">
|
||||||
Any channel
|
Any channel
|
||||||
|
|
||||||
|
@ -278,6 +296,7 @@
|
||||||
import ActorPreview from '../actors/preview.vue';
|
import ActorPreview from '../actors/preview.vue';
|
||||||
import Entity from '../entities/tile.vue';
|
import Entity from '../entities/tile.vue';
|
||||||
import Checkbox from '../form/checkbox.vue';
|
import Checkbox from '../form/checkbox.vue';
|
||||||
|
import Toggle from '../form/toggle.vue';
|
||||||
import Search from './search.vue';
|
import Search from './search.vue';
|
||||||
|
|
||||||
async function addAlert() {
|
async function addAlert() {
|
||||||
|
@ -285,10 +304,11 @@ async function addAlert() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('addAlert', {
|
await this.$store.dispatch('addAlert', {
|
||||||
|
all: this.all,
|
||||||
actors: this.actors.map((actor) => actor.id),
|
actors: this.actors.map((actor) => actor.id),
|
||||||
tags: this.tags.map((tag) => tag.id),
|
tags: this.tags.map((tag) => tag.id),
|
||||||
matches: this.matches,
|
matches: this.matches,
|
||||||
entity: this.entity?.id,
|
entities: this.entities.map((entity) => entity.id),
|
||||||
notify: this.notify,
|
notify: this.notify,
|
||||||
email: this.email,
|
email: this.email,
|
||||||
stashes: this.stashes.map((stash) => stash.id),
|
stashes: this.stashes.map((stash) => stash.id),
|
||||||
|
@ -309,7 +329,7 @@ function addActor(actor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addEntity(entity) {
|
function addEntity(entity) {
|
||||||
this.entity = entity;
|
this.entities = this.entities.concat(entity);
|
||||||
this.events.emit('blur');
|
this.events.emit('blur');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,8 +345,8 @@ function removeActor(actor) {
|
||||||
this.actors = this.actors.filter((listedActor) => listedActor.id !== actor.id);
|
this.actors = this.actors.filter((listedActor) => listedActor.id !== actor.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeEntity() {
|
function removeEntity(entity) {
|
||||||
this.entity = null;
|
this.entities = this.entities.filter((alertEntity) => alertEntity.id !== entity.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeTag(tag) {
|
function removeTag(tag) {
|
||||||
|
@ -371,6 +391,7 @@ export default {
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Entity,
|
Entity,
|
||||||
Search,
|
Search,
|
||||||
|
Toggle,
|
||||||
},
|
},
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
data() {
|
data() {
|
||||||
|
@ -378,7 +399,8 @@ export default {
|
||||||
error: null,
|
error: null,
|
||||||
actors: [],
|
actors: [],
|
||||||
tags: [],
|
tags: [],
|
||||||
entity: null,
|
all: true,
|
||||||
|
entities: [],
|
||||||
matches: [],
|
matches: [],
|
||||||
matchProperty: 'title',
|
matchProperty: 'title',
|
||||||
matchExpression: null,
|
matchExpression: null,
|
||||||
|
@ -424,9 +446,15 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-description {
|
.dialog-description {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
color: var(--shadow);
|
color: var(--shadow);
|
||||||
font-size: .9rem;
|
font-size: .9rem;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
|
||||||
|
.toggle-container {
|
||||||
|
margin-left: .5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-error {
|
.dialog-error {
|
||||||
|
@ -488,6 +516,11 @@ export default {
|
||||||
margin: 0 .5rem .5rem 0;
|
margin: 0 .5rem .5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entity.invalid {
|
||||||
|
opacity: .5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.entity .tile {
|
.entity .tile {
|
||||||
width: 10rem;
|
width: 10rem;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<router-link
|
<RouterLink
|
||||||
:to="`/${entity.type}/${entity.slug}`"
|
:to="`/${entity.type}/${entity.slug}`"
|
||||||
:title="entity.name"
|
:title="entity.name"
|
||||||
|
:target="target"
|
||||||
class="tile"
|
class="tile"
|
||||||
>
|
>
|
||||||
<div class="tile-logo">
|
<div class="tile-logo">
|
||||||
|
@ -47,7 +48,7 @@
|
||||||
<span v-if="typeof entity.sceneTotal !== 'undefined'">{{ entity.sceneTotal }} scenes</span>
|
<span v-if="typeof entity.sceneTotal !== 'undefined'">{{ entity.sceneTotal }} scenes</span>
|
||||||
<span v-if="entity.type === 'network'">{{ entity.childrenTotal }} channels</span>
|
<span v-if="entity.type === 'network'">{{ entity.childrenTotal }} channels</span>
|
||||||
</span>
|
</span>
|
||||||
</router-link>
|
</RouterLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -57,6 +58,10 @@ export default {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
target: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
emits: ['load'],
|
emits: ['load'],
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
v-if="notification.alert"
|
v-if="notification.alert"
|
||||||
v-tooltip="`You set an alert for <strong>${notification.alert.tags.map(tag => tag.name).join(', ') || 'all'}</strong> scenes with <strong>${notification.alert.actors.map(actor => actor.name).join(', ') || 'any actor'}</strong> from <strong>${notification.alert.entities.map((entity) => entity.name).join(', ') || 'any channel'}</strong> matching <strong>${notification.alert.matches.map((match) => `${match.property}: ${match.expression}`).join(', ') || 'anything'}</strong>`"
|
v-tooltip="`You set an alert for scenes with <strong>${notification.alert.all ? 'all of' : 'any of'}</strong> <strong>${notification.alert.actors.map(actor => actor.name).join(', ') || 'any actor'}</strong> containing <strong>${notification.alert.tags.map(tag => tag.name).join(', ') || 'any tags'}</strong> from <strong>${notification.alert.entities.map((entity) => entity.name).join(', ') || 'any channel'}</strong> matching <strong>${notification.alert.matches.map((match) => `${match.property}: ${match.expression}`).join(', ') || 'any text'}</strong>`"
|
||||||
icon="question5"
|
icon="question5"
|
||||||
@click.prevent.stop
|
@click.prevent.stop
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -68,6 +68,7 @@ function initUiActions(store, _router) {
|
||||||
${releaseFields}
|
${releaseFields}
|
||||||
}
|
}
|
||||||
alert {
|
alert {
|
||||||
|
all
|
||||||
tags: alertsTags {
|
tags: alertsTags {
|
||||||
tag {
|
tag {
|
||||||
id
|
id
|
||||||
|
|
|
@ -71,6 +71,7 @@ function initUsersActions(store, _router) {
|
||||||
id
|
id
|
||||||
notify
|
notify
|
||||||
email
|
email
|
||||||
|
all
|
||||||
stashes: alertsStashes {
|
stashes: alertsStashes {
|
||||||
stash {
|
stash {
|
||||||
id
|
id
|
||||||
|
|
|
@ -34,5 +34,9 @@ exports.down = async (knex) => {
|
||||||
table.dropColumn('all');
|
table.dropColumn('all');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('alerts_entities', (table) => {
|
||||||
|
table.unique('alert_id');
|
||||||
|
});
|
||||||
|
|
||||||
await knex.schema.dropTable('alerts_matches');
|
await knex.schema.dropTable('alerts_matches');
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,7 @@ async function addAlert(alert, sessionUser) {
|
||||||
user_id: sessionUser.id,
|
user_id: sessionUser.id,
|
||||||
notify: alert.notify,
|
notify: alert.notify,
|
||||||
email: alert.email,
|
email: alert.email,
|
||||||
|
all: alert.all,
|
||||||
})
|
})
|
||||||
.returning('id');
|
.returning('id');
|
||||||
|
|
||||||
|
@ -45,10 +46,10 @@ async function addAlert(alert, sessionUser) {
|
||||||
alert_id: alertId,
|
alert_id: alertId,
|
||||||
stash_id: stashId,
|
stash_id: stashId,
|
||||||
})), false),
|
})), false),
|
||||||
alert.entity && bulkInsert('alerts_entities', [{
|
alert.entities && bulkInsert('alerts_entities', alert.entities.map((entityId) => ({
|
||||||
alert_id: alertId,
|
alert_id: alertId,
|
||||||
entity_id: alert.entity,
|
entity_id: entityId,
|
||||||
}], false),
|
})).slice(0, alert.all ? 1 : Infinity), false), // one scene can never match multiple entities in AND mode
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return alertId;
|
return alertId;
|
||||||
|
@ -121,8 +122,6 @@ async function notify(scenes) {
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
console.log(alertsStashesByAlertId);
|
|
||||||
|
|
||||||
const alerts = rawAlerts.map((alert) => ({
|
const alerts = rawAlerts.map((alert) => ({
|
||||||
id: alert.id,
|
id: alert.id,
|
||||||
userId: alert.user_id,
|
userId: alert.user_id,
|
||||||
|
@ -148,32 +147,45 @@ async function notify(scenes) {
|
||||||
|
|
||||||
const triggers = alerts.flatMap((alert) => {
|
const triggers = alerts.flatMap((alert) => {
|
||||||
const alertScenes = curatedScenes.filter((scene) => {
|
const alertScenes = curatedScenes.filter((scene) => {
|
||||||
console.log(scene.title, alert.tags, scene.tagIds);
|
if (alert.all) {
|
||||||
|
if (alert.actors.length > 0 && !alert.actors.every((actorId) => scene.actorIds.includes(actorId))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (alert.actors.length > 0 && !alert.actors.every((actorId) => scene.actorIds.includes(actorId))) {
|
if (alert.tags.length > 0 && !alert.tags.every((tagId) => scene.tagIds.includes(tagId))) {
|
||||||
console.log('THROW ACTORS');
|
return false;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
// multiple entities can only be matched in OR mode
|
||||||
|
if (alert.entities.length > 0 && !alert.entities.some((alertEntityId) => alertEntityId === scene.entityId || alertEntityId === scene.parentEntityId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alert.matches.length > 0 && !alert.matches.every((match) => match.expression.test(scene[match.property]))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alert.tags.length > 0 && !alert.tags.every((tagId) => scene.tagIds.includes(tagId))) {
|
if (alert.actors.some((actorId) => scene.actorIds.includes(actorId))) {
|
||||||
console.log('THROW TAGS');
|
return true;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
if (alert.tags.some((tagId) => scene.tagIds.includes(tagId))) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiple entities can only be matched in OR mode
|
// multiple entities can only be matched in OR mode
|
||||||
if (alert.entities.length > 0 && !alert.entities.some((alertEntityId) => alertEntityId === scene.entityId || alertEntityId === scene.parentEntityId)) {
|
if (alert.entities.some((alertEntityId) => alertEntityId === scene.entityId || alertEntityId === scene.parentEntityId)) {
|
||||||
console.log('THROW ENTITIES');
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alert.matches.length > 0 && !alert.matches.every((match) => match.expression.test(scene[match.property]))) {
|
if (alert.matches.some((match) => match.expression.test(scene[match.property]))) {
|
||||||
console.log('THROW MATCHES');
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('OK');
|
return false;
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return alertScenes.map((scene) => ({
|
return alertScenes.map((scene) => ({
|
||||||
|
@ -191,15 +203,11 @@ async function notify(scenes) {
|
||||||
scene_id: trigger.sceneId,
|
scene_id: trigger.sceneId,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
console.log('triggers', triggers);
|
|
||||||
|
|
||||||
const stashes = Object.values(Object.fromEntries(triggers.flatMap((trigger) => trigger.alert.stashes.map((stashId) => ({
|
const stashes = Object.values(Object.fromEntries(triggers.flatMap((trigger) => trigger.alert.stashes.map((stashId) => ({
|
||||||
scene_id: trigger.sceneId,
|
scene_id: trigger.sceneId,
|
||||||
stash_id: stashId,
|
stash_id: stashId,
|
||||||
}))).map((stash) => [`${stash.stash_id}:${stash.scene_id}`, stash])));
|
}))).map((stash) => [`${stash.stash_id}:${stash.scene_id}`, stash])));
|
||||||
|
|
||||||
console.log('stashes', stashes);
|
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
bulkInsert('notifications', notifications, false),
|
bulkInsert('notifications', notifications, false),
|
||||||
bulkInsert('stashes_scenes', stashes, false),
|
bulkInsert('stashes_scenes', stashes, false),
|
||||||
|
|
Loading…
Reference in New Issue