Files
jobbi-bewerbung/views/settings.ejs
T
thomasandClaude 97b48f9841 Einstellungen-Seite: .env-Werte in DB (app_state), keine .env mehr
Neue /einstellungen-Seite (Zahnrad im Header) mit allen bisherigen .env-Werten
(Ollama, E-Mail, CalDAV, REST-API), gespeichert in SQLite (app_state, cfg:-Prefix).
Libs lesen per lib/config.js zur Laufzeit statt beim Start -> Aenderungen
wirken sofort, kein Neustart. Bestehende .env wird beim ersten Start einmalig
migriert.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-13 20:57:31 +02:00

112 lines
7.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<%- include('partials/head') %>
</head>
<body class="min-h-screen flex flex-col transition-colors duration-300 bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100" id="body">
<%- include('partials/header') %>
<main class="flex-1 container mx-auto px-4 py-8 max-w-4xl">
<!-- Back link -->
<a href="/" class="inline-flex items-center gap-2 text-sm text-blue-600 dark:text-blue-400 hover:underline mb-6">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
</svg>
Zurück zur Übersicht
</a>
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 mb-8">
<div class="flex items-start gap-3">
<svg class="w-6 h-6 text-gray-500 dark:text-gray-400 shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
<div>
<h2 class="text-lg font-semibold text-gray-800 dark:text-white">Einstellungen</h2>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1 max-w-2xl">
Hier liegen alle Werte, die früher über die <code class="px-1 rounded bg-gray-100 dark:bg-gray-700">.env</code>-Datei
gesetzt wurden Ollama, E-Mail, Kalender und die REST-API. Gespeichert wird in der Datenbank;
Änderungen wirken <em>sofort</em>, ein Neustart ist nicht nötig. Lediglich die Abruf-/Sync-Intervalle
(E-Mail &amp; Kalender) greifen erst nach einem Neustart.
</p>
</div>
</div>
</div>
<form action="/einstellungen" method="POST" class="space-y-6">
<% felder.forEach(function(sektion){ %>
<section class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h3 class="text-base font-semibold text-gray-800 dark:text-white"><%= sektion.titel %></h3>
<% if (sektion.beschreibung) { %>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1 mb-5 max-w-2xl"><%= sektion.beschreibung %></p>
<% } else { %>
<div class="mb-5"></div>
<% } %>
<div class="grid gap-4 sm:grid-cols-2">
<% sektion.items.forEach(function(f){
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';
%>
<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 %>
<code class="ml-1 text-[11px] font-normal text-gray-400 dark:text-gray-500"><%= f.key %></code>
</label>
<div class="relative">
<input id="cfg-<%= f.key %>" name="<%= f.key %>" type="<%= inputType %>" autocomplete="off"
spellcheck="false" class="<%= inputClass %>" value="<%= val %>">
<% if (f.secret) { %>
<button type="button" data-toggle="cfg-<%= f.key %>"
class="absolute inset-y-0 right-0 flex items-center px-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200"
title="Wert anzeigen/verbergen" tabindex="-1">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
</button>
<% } %>
</div>
<% if (f.help) { %>
<p class="text-xs text-gray-400 dark:text-gray-500 mt-1"><%= f.help %></p>
<% } %>
</div>
<% }); %>
</div>
</section>
<% }); %>
<div class="flex items-center justify-end gap-3">
<a href="/einstellungen" class="px-4 py-2 text-sm border border-gray-300 dark:border-gray-600 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors">
Verwerfen
</a>
<button type="submit"
class="inline-flex items-center gap-2 px-4 py-2 text-sm bg-blue-600 hover:bg-blue-700 text-white rounded-md transition-colors">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
Speichern
</button>
</div>
</form>
</main>
<%- include('partials/footer') %>
<script>
(function () {
const cy = document.getElementById('currentYear');
if (cy) cy.textContent = new Date().getFullYear();
// Toggle reveal for secret (password) fields.
document.querySelectorAll('[data-toggle]').forEach(function (btn) {
btn.addEventListener('click', function () {
const input = document.getElementById(btn.getAttribute('data-toggle'));
if (input) input.type = input.type === 'password' ? 'text' : 'password';
});
});
})();
</script>
</body>
</html>