first commit
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<section class="page-grid">
|
||||
<article class="glass-panel archive-list">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Archiv</p>
|
||||
<h3>Alle gespeicherten Tage</h3>
|
||||
</div>
|
||||
<span class="chart-chip"><?= e((string) count($entries)) ?> Eintraege</span>
|
||||
</div>
|
||||
|
||||
<?php if ($entries === []): ?>
|
||||
<p class="empty-state">Noch keine Eintraege vorhanden. Auf der Tracking-Seite kannst du den ersten Tag anlegen.</p>
|
||||
<?php else: ?>
|
||||
<div class="archive-items">
|
||||
<?php foreach ($entries as $entry): ?>
|
||||
<a class="archive-item <?= $selectedEntry !== null && $selectedEntry['date'] === $entry['date'] ? 'active' : '' ?>" href="/archive?date=<?= e(rawurlencode($entry['date'])) ?>">
|
||||
<div>
|
||||
<strong><?= e($entry['date']) ?></strong>
|
||||
<span><?= e($entry['evaluation']['label']) ?></span>
|
||||
</div>
|
||||
<div class="archive-item__meta">
|
||||
<span><?= e(format_points((float) $entry['evaluation']['total'])) ?></span>
|
||||
<span>Stimmung <?= e((string) $entry['mood']) ?>/10</span>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</article>
|
||||
|
||||
<aside class="stack-column">
|
||||
<?php if ($selectedEntry !== null): ?>
|
||||
<article class="glass-panel detail-card">
|
||||
<p class="eyebrow">Ausgewaehlt</p>
|
||||
<h3><?= e($selectedEntry['date']) ?></h3>
|
||||
<p class="hero-label"><?= e($selectedEntry['evaluation']['label']) ?> · <?= e(format_points((float) $selectedEntry['evaluation']['total'])) ?> Punkte</p>
|
||||
|
||||
<dl class="detail-grid">
|
||||
<div><dt>Stimmung</dt><dd><?= e((string) $selectedEntry['mood']) ?>/10</dd></div>
|
||||
<div><dt>Energie</dt><dd><?= e((string) $selectedEntry['energy']) ?>/10</dd></div>
|
||||
<div><dt>Stress</dt><dd><?= e((string) $selectedEntry['stress']) ?>/10</dd></div>
|
||||
<div><dt>Schlaf</dt><dd><?= e((string) $selectedEntry['sleep_hours']) ?> h</dd></div>
|
||||
<div><dt>Schlafgefuehl</dt><dd><?= e((string) $selectedEntry['sleep_feeling']) ?>/5</dd></div>
|
||||
<div><dt>Sport</dt><dd><?= e((string) $selectedEntry['sport_minutes']) ?> min</dd></div>
|
||||
<div><dt>Spaziergang</dt><dd><?= e((string) $selectedEntry['walk_minutes']) ?> min</dd></div>
|
||||
</dl>
|
||||
|
||||
<div class="note-box">
|
||||
<h4>Notiz</h4>
|
||||
<p><?= nl2br(e($selectedEntry['note'] !== '' ? $selectedEntry['note'] : 'Keine Notiz hinterlegt.')) ?></p>
|
||||
</div>
|
||||
</article>
|
||||
<?php else: ?>
|
||||
<article class="glass-panel detail-card">
|
||||
<p class="eyebrow">Details</p>
|
||||
<h3>Archivansicht</h3>
|
||||
<p>Waehle links einen Tag aus, um alle Werte und die Tagebuchnotiz anzuzeigen.</p>
|
||||
</article>
|
||||
<?php endif; ?>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<section class="hero-grid">
|
||||
<article class="hero-card hero-card--wide glass-panel">
|
||||
<p class="eyebrow">Stimmung im Blick</p>
|
||||
<h3>Dein Dashboard verbindet Verlauf, Score und Bewegungsdaten in einer schnellen Uebersicht.</h3>
|
||||
<p class="hero-copy">Die Bewertung basiert auf deiner konfigurierbaren Logik. Sobald du die Regeln in den Optionen aenderst, spiegeln Archiv und Statistiken die neue Gewichtung wider.</p>
|
||||
</article>
|
||||
|
||||
<article class="hero-card glass-panel">
|
||||
<p class="eyebrow">Heute</p>
|
||||
<?php if ($summary['today'] !== null): ?>
|
||||
<div class="hero-score"><?= e(format_points((float) $summary['today']['evaluation']['total'])) ?></div>
|
||||
<p class="hero-label"><?= e($summary['today']['evaluation']['label']) ?></p>
|
||||
<?php else: ?>
|
||||
<div class="hero-score">-</div>
|
||||
<p class="hero-label">Noch kein Eintrag fuer heute</p>
|
||||
<?php endif; ?>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="stats-grid">
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Getrackte Tage</span>
|
||||
<strong><?= e((string) $summary['tracked_days']) ?></strong>
|
||||
</article>
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Ø Score</span>
|
||||
<strong><?= e(format_points((float) $summary['average_score'])) ?></strong>
|
||||
</article>
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Ø Stimmung</span>
|
||||
<strong><?= e(format_points((float) $summary['average_mood'])) ?>/10</strong>
|
||||
</article>
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Ø Stress</span>
|
||||
<strong><?= e(format_points((float) $summary['average_stress'])) ?>/10</strong>
|
||||
</article>
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Serie</span>
|
||||
<strong><?= e((string) $summary['streak']) ?> Tage</strong>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="dashboard-grid">
|
||||
<article class="glass-panel chart-card chart-card--calendar">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Kalender</p>
|
||||
<h3>Gesamtstimmung pro Tag</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div id="calendar-heatmap" class="calendar-heatmap" data-payload="<?= e($chartPayload) ?>"></div>
|
||||
</article>
|
||||
|
||||
<article class="glass-panel chart-card">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Trend</p>
|
||||
<h3>Tagesstimmung</h3>
|
||||
</div>
|
||||
<span class="chart-chip">letzte 30 Eintraege</span>
|
||||
</div>
|
||||
<div class="line-chart" data-chart-type="line" data-series="mood" data-payload="<?= e($chartPayload) ?>"></div>
|
||||
</article>
|
||||
|
||||
<article class="glass-panel chart-card">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Belastung</p>
|
||||
<h3>Stressverlauf</h3>
|
||||
</div>
|
||||
<span class="chart-chip chart-chip--warm">letzte 30 Eintraege</span>
|
||||
</div>
|
||||
<div class="line-chart" data-chart-type="line" data-series="stress" data-payload="<?= e($chartPayload) ?>"></div>
|
||||
</article>
|
||||
|
||||
<article class="glass-panel chart-card chart-card--wide">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Aktivitaet</p>
|
||||
<h3>Sport und Spaziergang</h3>
|
||||
</div>
|
||||
<span class="chart-chip chart-chip--cool">Minuten pro Tag</span>
|
||||
</div>
|
||||
<div class="bar-chart" data-chart-type="bars" data-series="sport" data-payload="<?= e($chartPayload) ?>"></div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<section class="auth-shell">
|
||||
<div class="auth-card glass-panel">
|
||||
<p class="eyebrow">Geschuetzt und dateibasiert</p>
|
||||
<h1>Einloggen</h1>
|
||||
<p class="auth-copy">Die Eintraege liegen als Markdown-TXT-Dateien im geschuetzten Speicher und sind nur nach Login sichtbar.</p>
|
||||
|
||||
<form method="post" action="/login" class="stack-form">
|
||||
<?= csrf_field() ?>
|
||||
<label>
|
||||
<span>Benutzername</span>
|
||||
<input type="text" name="username" autocomplete="username" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span>Passwort</span>
|
||||
<input type="password" name="password" autocomplete="current-password" required>
|
||||
</label>
|
||||
|
||||
<button class="primary-button" type="submit">Anmelden</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<section class="auth-shell">
|
||||
<div class="auth-card glass-panel">
|
||||
<p class="eyebrow">404</p>
|
||||
<h1>Diese Seite gibt es nicht</h1>
|
||||
<p class="auth-copy">Der angeforderte Bereich wurde nicht gefunden.</p>
|
||||
<a class="primary-button button-link" href="/">Zur Startseite</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
<section class="page-grid">
|
||||
<article class="glass-panel form-panel form-panel--wide">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Bewertungslogik</p>
|
||||
<h3>Score und Schutzregeln anpassen</h3>
|
||||
</div>
|
||||
<span class="chart-chip">Maximal <?= e(format_points((float) $maxScore)) ?> Punkte</span>
|
||||
</div>
|
||||
|
||||
<form method="post" action="/options" class="stack-form stack-form--spacious">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="form_name" value="settings">
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>Multiplikatoren</h4>
|
||||
<div class="field-grid field-grid--four">
|
||||
<label><span>Stimmung</span><input type="number" name="settings[scoring][mood_multiplier]" value="<?= e((string) $settings['scoring']['mood_multiplier']) ?>" min="0" max="10"></label>
|
||||
<label><span>Energie</span><input type="number" name="settings[scoring][energy_multiplier]" value="<?= e((string) $settings['scoring']['energy_multiplier']) ?>" min="0" max="10"></label>
|
||||
<label><span>Stress</span><input type="number" name="settings[scoring][stress_multiplier]" value="<?= e((string) $settings['scoring']['stress_multiplier']) ?>" min="0" max="10"></label>
|
||||
<label><span>Schlafgefuehl</span><input type="number" name="settings[scoring][sleep_feeling_multiplier]" value="<?= e((string) $settings['scoring']['sleep_feeling_multiplier']) ?>" min="0" max="10"></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>Schlafdauerpunkte</h4>
|
||||
<div class="field-grid field-grid--four">
|
||||
<?php foreach ($settings['scoring']['sleep_duration_points'] as $key => $value): ?>
|
||||
<label>
|
||||
<span><?= e($key) ?></span>
|
||||
<input type="number" name="settings[scoring][sleep_duration_points][<?= e($key) ?>]" value="<?= e((string) $value) ?>" min="0" max="20">
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>Sport-Baender</h4>
|
||||
<div class="band-grid">
|
||||
<?php foreach ($settings['scoring']['sport_bands'] as $index => $band): ?>
|
||||
<div class="band-card">
|
||||
<label><span>Min</span><input type="number" name="settings[scoring][sport_bands][<?= e((string) $index) ?>][min]" value="<?= e((string) $band['min']) ?>"></label>
|
||||
<label><span>Max</span><input type="number" name="settings[scoring][sport_bands][<?= e((string) $index) ?>][max]" value="<?= e((string) $band['max']) ?>"></label>
|
||||
<label><span>Punkte</span><input type="number" name="settings[scoring][sport_bands][<?= e((string) $index) ?>][points]" value="<?= e((string) $band['points']) ?>"></label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>Spaziergang-Baender</h4>
|
||||
<div class="band-grid">
|
||||
<?php foreach ($settings['scoring']['walk_bands'] as $index => $band): ?>
|
||||
<div class="band-card">
|
||||
<label><span>Min</span><input type="number" name="settings[scoring][walk_bands][<?= e((string) $index) ?>][min]" value="<?= e((string) $band['min']) ?>"></label>
|
||||
<label><span>Max</span><input type="number" name="settings[scoring][walk_bands][<?= e((string) $index) ?>][max]" value="<?= e((string) $band['max']) ?>"></label>
|
||||
<label><span>Punkte</span><input type="number" name="settings[scoring][walk_bands][<?= e((string) $index) ?>][points]" value="<?= e((string) $band['points']) ?>"></label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>Bewertungsskala</h4>
|
||||
<div class="band-grid">
|
||||
<?php foreach ($settings['ratings'] as $index => $rating): ?>
|
||||
<div class="band-card">
|
||||
<label><span>Label</span><input type="text" name="settings[ratings][<?= e((string) $index) ?>][label]" value="<?= e($rating['label']) ?>"></label>
|
||||
<label><span>Min</span><input type="number" name="settings[ratings][<?= e((string) $index) ?>][min]" value="<?= e((string) $rating['min']) ?>"></label>
|
||||
<label><span>Max</span><input type="number" name="settings[ratings][<?= e((string) $index) ?>][max]" value="<?= e((string) $rating['max']) ?>"></label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>Schutzregeln</h4>
|
||||
<div class="band-grid">
|
||||
<?php foreach ($settings['guardrails'] as $index => $guardrail): ?>
|
||||
<div class="band-card">
|
||||
<label><span>Stimmung max</span><input type="number" name="settings[guardrails][<?= e((string) $index) ?>][mood_max]" value="<?= e((string) $guardrail['mood_max']) ?>" min="1" max="10"></label>
|
||||
<label><span>Energie max</span><input type="number" name="settings[guardrails][<?= e((string) $index) ?>][energy_max]" value="<?= e((string) ($guardrail['energy_max'] ?? '')) ?>" min="1" max="10"></label>
|
||||
<label><span>Maximales Label</span><input type="text" name="settings[guardrails][<?= e((string) $index) ?>][cap_label]" value="<?= e($guardrail['cap_label']) ?>"></label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label>
|
||||
<span>Tagebuchpunkte bei nicht-leerer Notiz</span>
|
||||
<input type="number" name="settings[scoring][journal_points]" value="<?= e((string) $settings['scoring']['journal_points']) ?>" min="0" max="20">
|
||||
</label>
|
||||
|
||||
<button class="primary-button" type="submit">Bewertung speichern</button>
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<aside class="stack-column">
|
||||
<article class="glass-panel detail-card">
|
||||
<p class="eyebrow">Sicherheit</p>
|
||||
<h3>Passwort aendern</h3>
|
||||
<form method="post" action="/options" class="stack-form">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="form_name" value="password">
|
||||
<label><span>Aktuelles Passwort</span><input type="password" name="current_password" required></label>
|
||||
<label><span>Neues Passwort</span><input type="password" name="new_password" minlength="10" required></label>
|
||||
<label><span>Neues Passwort wiederholen</span><input type="password" name="new_password_confirm" minlength="10" required></label>
|
||||
<button class="primary-button" type="submit">Passwort aktualisieren</button>
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<?php if (!empty($authUser['is_admin'])): ?>
|
||||
<article class="glass-panel detail-card">
|
||||
<p class="eyebrow">Mehrere Accounts</p>
|
||||
<h3>Neuen Nutzer anlegen</h3>
|
||||
<form method="post" action="/options" class="stack-form">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="form_name" value="create_user">
|
||||
<label><span>Benutzername</span><input type="text" name="username" required></label>
|
||||
<label><span>Startpasswort</span><input type="password" name="password" minlength="10" required></label>
|
||||
<label class="checkbox-row"><input type="checkbox" name="is_admin" value="1"><span>Als Admin anlegen</span></label>
|
||||
<button class="primary-button" type="submit">Account erstellen</button>
|
||||
</form>
|
||||
|
||||
<?php if ($users !== []): ?>
|
||||
<div class="user-list">
|
||||
<?php foreach ($users as $account): ?>
|
||||
<div class="user-row">
|
||||
<strong><?= e($account['username']) ?></strong>
|
||||
<span><?= !empty($account['is_admin']) ? 'Admin' : 'Nutzer' ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</article>
|
||||
<?php endif; ?>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<section class="auth-shell">
|
||||
<div class="auth-card glass-panel">
|
||||
<p class="eyebrow">Erste Einrichtung</p>
|
||||
<h1>Mood initialisieren</h1>
|
||||
<p class="auth-copy">Lege den ersten Admin-Account an. Danach ist die Anwendung sofort geschuetzt und weitere Accounts koennen spaeter in den Optionen erstellt werden.</p>
|
||||
|
||||
<form method="post" action="/setup" class="stack-form">
|
||||
<?= csrf_field() ?>
|
||||
<label>
|
||||
<span>Admin-Benutzername</span>
|
||||
<input type="text" name="username" autocomplete="username" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span>Passwort</span>
|
||||
<input type="password" name="password" autocomplete="new-password" minlength="10" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span>Passwort wiederholen</span>
|
||||
<input type="password" name="password_confirm" autocomplete="new-password" minlength="10" required>
|
||||
</label>
|
||||
|
||||
<button class="primary-button" type="submit">Setup abschliessen</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
<section class="page-grid">
|
||||
<article class="glass-panel form-panel form-panel--wide">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Tag erfassen</p>
|
||||
<h3>Eintrag fuer <?= e($entry['date']) ?></h3>
|
||||
</div>
|
||||
<a class="ghost-link" href="/archive?date=<?= e(rawurlencode($entry['date'])) ?>">Im Archiv ansehen</a>
|
||||
</div>
|
||||
|
||||
<form method="post" action="/track" class="tracker-form" id="tracker-form">
|
||||
<?= csrf_field() ?>
|
||||
|
||||
<div class="field-grid field-grid--single">
|
||||
<label>
|
||||
<span>Datum</span>
|
||||
<input type="date" name="date" value="<?= e($entry['date']) ?>" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-grid field-grid--three">
|
||||
<label class="range-card">
|
||||
<span>Stimmung</span>
|
||||
<output data-output-for="mood"><?= e((string) $entry['mood']) ?></output>
|
||||
<input type="range" min="1" max="10" step="1" name="mood" value="<?= e((string) $entry['mood']) ?>">
|
||||
</label>
|
||||
|
||||
<label class="range-card">
|
||||
<span>Energie</span>
|
||||
<output data-output-for="energy"><?= e((string) $entry['energy']) ?></output>
|
||||
<input type="range" min="1" max="10" step="1" name="energy" value="<?= e((string) $entry['energy']) ?>">
|
||||
</label>
|
||||
|
||||
<label class="range-card">
|
||||
<span>Stress</span>
|
||||
<output data-output-for="stress"><?= e((string) $entry['stress']) ?></output>
|
||||
<input type="range" min="1" max="10" step="1" name="stress" value="<?= e((string) $entry['stress']) ?>">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-grid field-grid--two">
|
||||
<label>
|
||||
<span>Schlafdauer in Stunden</span>
|
||||
<input type="number" min="0" max="24" step="0.25" name="sleep_hours" value="<?= e((string) $entry['sleep_hours']) ?>" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span>Schlafgefuehl</span>
|
||||
<select name="sleep_feeling">
|
||||
<?php foreach ($settings['labels']['sleep_feeling'] as $value => $label): ?>
|
||||
<option value="<?= e((string) $value) ?>" <?= (int) $entry['sleep_feeling'] === (int) $value ? 'selected' : '' ?>>
|
||||
<?= e((string) $value) ?> · <?= e($label) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-grid field-grid--two">
|
||||
<label>
|
||||
<span>Sport in Minuten</span>
|
||||
<input type="number" min="0" max="1440" step="1" name="sport_minutes" value="<?= e((string) $entry['sport_minutes']) ?>" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span>Spaziergang in Minuten</span>
|
||||
<input type="number" min="0" max="1440" step="1" name="walk_minutes" value="<?= e((string) $entry['walk_minutes']) ?>" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label>
|
||||
<span>Tagebuchnotiz</span>
|
||||
<textarea name="note" rows="8" placeholder="Was war heute wichtig, schwer oder schoen?"><?= e($entry['note']) ?></textarea>
|
||||
</label>
|
||||
|
||||
<div class="form-actions">
|
||||
<a class="ghost-link" href="/track?date=<?= e(today()) ?>">Heute laden</a>
|
||||
<button class="primary-button" type="submit">Tag speichern</button>
|
||||
</div>
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<aside class="stack-column">
|
||||
<article class="glass-panel preview-card" id="live-score-card" data-payload="<?= e($trackPayload) ?>">
|
||||
<p class="eyebrow">Live-Bewertung</p>
|
||||
<div class="hero-score" data-preview-total><?= e(format_points((float) $evaluation['total'])) ?></div>
|
||||
<p class="hero-label" data-preview-label><?= e($evaluation['label']) ?></p>
|
||||
<p class="helper-text">Die Einschaetzung passt sich beim Aendern der Werte sofort an.</p>
|
||||
<dl class="component-list" data-preview-components>
|
||||
<?php foreach ($evaluation['components'] as $name => $value): ?>
|
||||
<div>
|
||||
<dt><?= e($name) ?></dt>
|
||||
<dd><?= e(format_points((float) $value)) ?></dd>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</dl>
|
||||
</article>
|
||||
|
||||
<article class="glass-panel info-card">
|
||||
<p class="eyebrow">Dateiformat</p>
|
||||
<h3>Markdown in `YYYY-MM-DD.txt`</h3>
|
||||
<p>Jeder Tag wird als menschenlesbare Datei gespeichert. Das macht Backups, Portabilitaet und manuelle Kontrolle einfach.</p>
|
||||
</article>
|
||||
</aside>
|
||||
</section>
|
||||
Reference in New Issue
Block a user