Einstellungen: Vorauswahl für KI-Generierung (Dokumente + Anlagen)

Zwei neue, pro Benutzer gespeicherte Konfigurationswerte:
GEN_DOKUMENTE_DEFAULT (Standard: Anschreiben + Lebenslauf) und
GEN_ANLAGEN_DEFAULT (Standard: keine). Sie belegen die Häkchen auf der
Bewerbungsseite vor; eine bereits getroffene Dokumentenauswahl der
Bewerbung gewinnt weiterhin. Die REST-API nutzt die Vorauswahl, wenn
dokumente/anlagen im Body fehlen.

Die Einstellungsseite kennt dafür jetzt Checkbox-Gruppen, deren Optionen
auch erst zur Renderzeit feststehen dürfen (die eigenen Anlagen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 22:31:19 +02:00
co-authored by Claude Opus 4.8
parent d20a265ebc
commit 1dd4807ca6
7 changed files with 145 additions and 29 deletions
+8 -5
View File
@@ -343,11 +343,12 @@
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-800 dark:text-white leading-relaxed"
placeholder="z. B.&#10;Musterfirma GmbH&#10;Musterstraße 12&#10;10115 Berlin&#10;Ansprechpartner: Frau Müller"><%= application.llm_notizen || '' %></textarea>
<!-- Which documents to generate (both by default). -->
<!-- Which documents to generate (vorbelegt aus den Einstellungen). -->
<div class="mt-4" id="dokumentAuswahl">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Was soll generiert werden?</label>
<p class="text-xs text-gray-500 dark:text-gray-400 mb-2">
Standardmäßig werden Anschreiben und Lebenslauf erstellt. Wird der Lebenslauf abgewählt,
Vorbelegt ist deine Auswahl aus den <a href="/einstellungen" class="text-blue-600 dark:text-blue-400 hover:underline">Einstellungen</a>
(Standard: Anschreiben und Lebenslauf). Wird der Lebenslauf abgewählt,
führt ihn das Anschreiben auch nicht mehr unter „Anlagen“ auf.
</p>
<div class="flex flex-wrap gap-4">
@@ -369,18 +370,20 @@
</p>
</div>
<!-- Optional extra attachments to enclose (none by default). -->
<!-- Optional extra attachments to enclose (vorbelegt aus den Einstellungen). -->
<div class="mt-4">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Zusätzliche Anlagen</label>
<% if (basisAnhaenge && basisAnhaenge.length) { %>
<p class="text-xs text-gray-500 dark:text-gray-400 mb-2">
Wähle aus, welche Anlagen (z. B. Zeugnisse) mitgeschickt werden. Standardmäßig
ist nichts ausgewählt; die Auswahl wird auch im Anschreiben unter „Anlagen“ berücksichtigt.
Wähle aus, welche Anlagen (z. B. Zeugnisse) mitgeschickt werden. Vorbelegt ist deine Auswahl
aus den <a href="/einstellungen" class="text-blue-600 dark:text-blue-400 hover:underline">Einstellungen</a>
(Standard: keine); die Auswahl wird auch im Anschreiben unter „Anlagen“ berücksichtigt.
</p>
<div class="space-y-1.5">
<% basisAnhaenge.forEach(function(ba){ %>
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-200">
<input type="checkbox" name="anlage" value="<%= ba.id %>"
<%= anlagenAuswahl.includes(ba.id) ? 'checked' : '' %>
class="rounded border-gray-300 dark:border-gray-600 text-blue-600">
<%= ba.name || ba.dateiname %>
<% if (ba.name && ba.dateiname && ba.name !== ba.dateiname) { %>
+31
View File
@@ -48,7 +48,38 @@
var val = werte[f.key] != null ? werte[f.key] : '';
var inputType = f.secret ? 'password' : 'text';
var inputClass = 'w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm pr-10';
var gewaehlt = String(val).split(',').map(function(s){ return s.trim(); });
// Feste Optionen aus der Feld-Definition oder bei „optionsFrom“
// die zur Renderzeit geladenen Listen (z. B. die eigenen Anlagen).
var optionen = f.options || (f.optionsFrom ? (auswahllisten[f.optionsFrom] || []) : []);
%>
<% if (f.type === 'checkboxes') { %>
<div class="sm:col-span-2">
<span class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
<%= f.label %>
<code class="ml-1 text-[11px] font-normal text-gray-400 dark:text-gray-500"><%= f.key %></code>
</span>
<!-- Leerer Wert, damit „nichts angehakt“ auch gespeichert wird. -->
<input type="hidden" name="<%= f.key %>" value="">
<% if (!optionen.length) { %>
<p class="text-sm text-gray-400 dark:text-gray-500"><%= f.leerHinweis || 'Keine Auswahl verfügbar.' %></p>
<% } else { %>
<div class="flex flex-wrap gap-x-6 gap-y-2">
<% optionen.forEach(function(o){ %>
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
<input type="checkbox" name="<%= f.key %>" value="<%= o.value %>"
<%= gewaehlt.includes(String(o.value)) ? 'checked' : '' %>
class="rounded border-gray-300 dark:border-gray-600 text-blue-600">
<%= o.label %>
</label>
<% }); %>
</div>
<% } %>
<% if (f.help) { %>
<p class="text-xs text-gray-400 dark:text-gray-500 mt-2"><%= f.help %></p>
<% } %>
</div>
<% return; } %>
<div class="<%= f.secret ? 'sm:col-span-2' : '' %>">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1" for="cfg-<%= f.key %>">
<%= f.label %>