feat: add optional reply address to communication threads and enhance email transport status handling
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 52s

This commit is contained in:
Torsten Schulz (local)
2026-07-22 15:28:39 +02:00
parent fd0b3020bf
commit d190c2cb70
8 changed files with 140 additions and 4 deletions

View File

@@ -211,6 +211,7 @@
<h3>{{ threadForm.id ? 'Vorgang bearbeiten' : 'Neuer Vorgang' }}</h3>
</div>
<p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Vorgänge lassen sich prüfen, aber nicht ändern.</p>
<p v-if="transport && !transport.configured" class="state-banner state-banner-error">{{ transport.message }}</p>
<form class="thread-form" @submit.prevent="saveThread">
<div class="form-grid">
@@ -238,6 +239,19 @@
<input v-model.trim="threadForm.subject" type="text" :disabled="!canEdit" required />
</label>
<label>
<span>Antwortadresse (optional)</span>
<input v-model.trim="threadForm.replyTo" type="email" :disabled="!canEdit" placeholder="vorstand@verein.de" />
</label>
<label>
<span>Dokumentanhänge</span>
<select v-model="threadForm.attachmentDocumentIds" multiple :disabled="!canEdit || availableDocuments.length === 0">
<option v-for="document in availableDocuments" :key="document.id" :value="document.id">{{ document.title }}</option>
</select>
<small v-if="availableDocuments.length === 0">Keine aktiven Vereinsdokumente verfügbar.</small>
</label>
<div v-if="threadForm.threadType === 'direct'">
<label>
<span>Empfänger</span>
@@ -546,6 +560,8 @@ function normalizeThread(thread = {}) {
id: Number(thread.id),
threadType: thread.threadType || thread.thread_type || 'direct',
subject: thread.subject || '',
replyTo: thread.replyTo || thread.reply_to || '',
attachments: Array.isArray(thread.attachments) ? thread.attachments : [],
status: thread.status || 'draft',
recipientMemberId: Number(thread.recipientMemberId || thread.recipient_member_id || 0) || null,
distributionGroupId: Number(thread.distributionGroupId || thread.distribution_group_id || 0) || null,
@@ -608,6 +624,8 @@ function createEmptyThreadForm() {
id: null,
threadType: 'direct',
subject: '',
replyTo: '',
attachmentDocumentIds: [],
status: 'draft',
recipientMemberId: '',
distributionGroupId: '',
@@ -679,6 +697,8 @@ export default {
groups: [],
members: [],
templates: [],
availableDocuments: [],
transport: null,
selectedThreadId: null,
selectedGroupId: null,
selectedTemplateId: null,
@@ -772,6 +792,8 @@ export default {
id: thread.id,
threadType: thread.threadType,
subject: thread.subject,
replyTo: thread.replyTo || '',
attachmentDocumentIds: (thread.attachments || []).map((attachment) => Number(attachment.id)),
status: thread.status,
recipientMemberId: thread.recipientMemberId || '',
distributionGroupId: thread.distributionGroupId || '',
@@ -811,6 +833,8 @@ export default {
this.groups = [];
this.members = [];
this.templates = [];
this.availableDocuments = [];
this.transport = null;
this.selectedThreadId = null;
this.selectedGroupId = null;
this.selectedTemplateId = null;
@@ -941,6 +965,8 @@ export default {
this.groups = Array.isArray(response.data?.groups) ? response.data.groups.map(normalizeGroup) : [];
this.members = Array.isArray(response.data?.members) ? response.data.members.map(normalizeMember) : [];
this.templates = Array.isArray(response.data?.templates) ? response.data.templates.map(normalizeTemplate) : [];
this.availableDocuments = Array.isArray(response.data?.availableDocuments) ? response.data.availableDocuments : [];
this.transport = response.data?.transport || null;
if (this.selectedThreadId && !this.threads.some((thread) => thread.id === this.selectedThreadId)) {
this.selectedThreadId = null;
}