Integrated e-mail alerts, added dialog option for release alerts.

This commit is contained in:
2026-07-21 04:31:12 +02:00
parent 6444cf21eb
commit 827566d57d
11 changed files with 487 additions and 308 deletions

View File

@@ -1,4 +1,5 @@
<script setup>
import { format } from 'date-fns';
import { inject, ref, useId } from 'vue';
import Dialog from '#/components/dialog/dialog.vue';
@@ -20,6 +21,10 @@ const props = defineProps({
type: Array,
default: () => [],
},
presetScenes: {
type: Array,
default: () => [],
},
});
const emit = defineEmits(['alert', 'close']);
@@ -45,6 +50,8 @@ const tagResults = ref([]);
const tagInput = ref(null);
const tagQuery = ref('');
const scenes = ref(props.presetScenes);
const matches = ref([]);
const matchProperty = ref('title');
const matchExpression = ref('');
@@ -61,8 +68,8 @@ const addEntityDropdownId = useId();
const addMatchDropdownId = useId();
const addStashDropdownId = useId();
const notify = ref(true);
const email = ref(false);
const notify = ref(JSON.parse(localStorage.getItem('alert_notify')) ?? true);
const email = ref(JSON.parse(localStorage.getItem('alert_email')) ?? false);
const stashes = ref([]);
@@ -72,6 +79,7 @@ async function createAlert() {
...tags.value.map((tag) => tag.name),
...entities.value.map((entity) => entity.name),
...matches.value.map((match) => match.expression),
...scenes.value.map((scene) => scene.title),
].filter(Boolean).join(', ');
const newAlert = await post('/alerts', {
@@ -81,6 +89,7 @@ async function createAlert() {
allMatches: matchAnd.value,
actors: actors.value.map((actor) => actor.id),
tagIds: tags.value.map((tag) => tag.id),
sceneIds: scenes.value.map((scene) => scene.id),
matches: matches.value,
entityIds: entities.value.map((entity) => entity.id),
notify: notify.value,
@@ -162,6 +171,10 @@ function selectStash(selectedStash) {
stashes.value.push(selectedStash);
}
}
function rememberThen(domain, checked) {
localStorage.setItem(`alert_${domain}`, checked);
}
</script>
<template>
@@ -173,7 +186,33 @@ function selectStash(selectedStash) {
class="dialog-body"
@submit.prevent="createAlert"
>
<div class="dialog-section">
<div
v-if="scenes.length > 0"
class="dialog-section"
>
<div class="section-header">
<h3 class="heading">WHEN RELEASED</h3>
</div>
<div
v-for="scene in scenes"
:key="`alert-scene-${scene.id}`"
class="scene"
>
<span class="scene-title">{{ scene.title }}</span>
<span class="scene-details">
<strong class="scene-date"><time :datetime="scene.date.toISOString()">{{ format(scene.date, 'yyyy-MM-dd') }}</time></strong> on
<span class="scene-channel">{{ scene.channel?.name || scene.network?.name }}</span>
</span>
</div>
</div>
<div
v-else
class="dialog-section"
>
<div class="section-header">
<h3 class="heading">IF</h3>
</div>
@@ -462,7 +501,7 @@ function selectStash(selectedStash) {
<span>Notify me in traxxx</span>
<Checkbox
:checked="notify"
@change="(checked) => notify = checked"
@change="(checked) => { notify = checked; rememberThen('notify', checked); }"
/>
</label>
@@ -474,11 +513,14 @@ function selectStash(selectedStash) {
<Checkbox
:checked="email"
@change="(checked) => email = checked"
@change="(checked) => { email = checked; rememberThen('email', checked); }"
/>
</label>
<div class="stash">
<div
v-if="scenes.length === 0"
class="stash"
>
<ul class="field-items nolist noselect">
<li
v-for="stash in stashes"
@@ -577,6 +619,20 @@ function selectStash(selectedStash) {
padding: 1rem;
}
.scene {
padding: 0 1rem;
}
.scene-title {
display: block;
line-height: 1.5;
margin-bottom: .5rem;
}
.scene-date {
color: var(--primary);
}
.field {
display: flex;
align-items: stretch;