Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions docs/Settings.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
# Settings

## Purpose
## Übersicht
Das Settings-Feature ermöglicht es Benutzern, ihre persönlichen Einstellungen zu konfigurieren. Alle Einstellungen werden persistent im Browser-localStorage gespeichert.

The Settings view stores basic user preferences in browser `localStorage`.

## What This View Provides

- A dialog that can be opened and closed
- A gender selector with values `none`, `male`, and `female`
- Persistent settings storage under `userSettings`
- A separate graph type toggle feature stored under `graphType` (`bar` or `line`)
### Beschreibung
Verwaltet benutzerspezifische Einstellungen wie das Geschlecht oder das Datumsformat. Nach jeder Änderung werden die Daten automatisch im localStorage gespeichert und bleiben auch nach einem Neustart der Anwendung erhalten.

## Data Model

### `userSettings`

```json
{
"gender": "none"
"gender": "none" | "male" | "female",
"dateFormat": "YYYY-MM-DD" / "YYYY-MM-DD HH:mm"
}
```

### `graphType`

Saved by the graph type toggle feature:
#### Initialisierung
```javascript
// Standard-Einstellungen
let settings = {
gender: 'none',
dateFormat: 'YYYY-MM-DD'
};
```

- `bar`
- `line`
Expand All @@ -35,7 +42,17 @@ Saved by the graph type toggle feature:
3. Close the dialog
4. Re-open the app and confirm the setting is still selected

Graph type flow (separate view):
// Bei Änderung der Einstellungen
function updateGender(newGender) {
settings.gender = newGender;
saveSettingsToStorage();
}

function updateDateFormat(newFormat) {
settings.dateFormat = newFormat;
saveSettingsToStorage();
}
```

1. Open `settings/graphType/graphTypeBtn.html`
2. Click the button to toggle between bar and line
Expand Down
31 changes: 31 additions & 0 deletions src/settings/graphType/graphType-http-test-host.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GraphType Button Test Host</title>
<link rel="stylesheet" href="../../../public/bootstrap-5.3.8-dist/css/bootstrap.min.css">
<link rel="stylesheet" href="./graphTypeBtn.css">
</head>
<body>
<button id="graphTypeBtn" onclick="toggleGraphType()" aria-describedby="graphTypeHelp graphTypeStatus">
Balkendiagramm
</button>
<p id="graphTypeHelp" class="sr-only">
Schaltet zwischen Balken- und Liniendiagramm um. Die Auswahl wird gespeichert.
</p>
<p id="graphTypeStatus" class="sr-only" role="status" aria-live="polite"></p>

<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div id="errorToast" class="toast text-bg-danger border-0" role="alert">
<div class="d-flex">
<div class="toast-body" id="errorToastBody">Fehler</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Fehlermeldung schliessen"></button>
</div>
</div>
</div>

<script src="../../../public/bootstrap-5.3.8-dist/js/bootstrap.bundle.min.js"></script>
<script src="./graphTypeBtn.js" defer></script>
</body>
</html>
8 changes: 4 additions & 4 deletions src/settings/graphType/graphTypeBtn.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Button Styling */
button {
background-color: #4caf50;
#graphTypeBtn {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
Expand All @@ -11,11 +11,11 @@ button {
margin: 5px;
}

button:hover {
#graphTypeBtn:hover {
background-color: #45a049;
}

button:active {
#graphTypeBtn:active {
transform: scale(0.98);
}

Expand Down
11 changes: 10 additions & 1 deletion src/settings/graphType/graphTypeBtn.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,21 @@

<body>
<button id="graphTypeBtn" onclick="toggleGraphType()" aria-describedby="graphTypeHelp graphTypeStatus">
Balkendiagramm
Liniendiagramm
</button>
<p id="graphTypeHelp" class="sr-only">
Schaltet zwischen Balken- und Liniendiagramm um. Die Auswahl wird gespeichert.
</p>
<p id="graphTypeStatus" class="sr-only" role="status" aria-live="polite"></p>

<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div id="errorToast" class="toast text-bg-danger border-0" role="alert">
<div class="d-flex">
<div class="toast-body" id="errorToastBody">Fehler</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Fehlermeldung schließen"></button>
</div>
</div>
</div>
</body>

</html>
39 changes: 35 additions & 4 deletions src/settings/graphType/graphTypeBtn.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
// Saved Settings
let graphType = "bar";
let graphType = "line";

// Load Settings from local storage
function loadGraphTypeFromStorage() {
try {
const savedGraphType = localStorage.getItem("graphType");
if (savedGraphType) {
graphType = JSON.parse(savedGraphType);
} else {
// Persist default graph type immediately.
localStorage.setItem("graphType", JSON.stringify(graphType));
}
} catch (e) {
console.log("Fehler beim Laden des Graphtypens aus dem LocalStorage:\n" + e)
console.log("Fehler beim Laden des Graphtypens aus dem LocalStorage:\n" + e);
showErrorToast("Fehler beim Laden des Graphtypens aus dem LocalStorage.");

try {
localStorage.setItem("graphType", JSON.stringify(graphType));
} catch (storageError) {
console.log("Fehler beim Setzen des Standard-Graphtypens im LocalStorage:\n" + storageError);
}
}
}

Expand All @@ -29,13 +39,16 @@ function saveGraphType() {
// Save GraphType in local storage
localStorage.setItem("graphType", JSON.stringify(graphType));
} catch (e) {
console.log("Fehler beim Speichern des Graphtypens im LocalStorage:\n" + e)
console.log("Fehler beim Speichern des Graphtypens im LocalStorage:\n" + e);
showErrorToast("Fehler beim Speichern des Graphtypens im LocalStorage.");
}
}

function updateButtonText() {
const button = document.getElementById("graphTypeBtn");
const status = document.getElementById("graphTypeStatus");
if (!button) return;

if (graphType === "bar") {
button.textContent = "Balkendiagramm";
button.setAttribute("aria-label", "Graphtyp: Balkendiagramm");
Expand All @@ -57,8 +70,26 @@ function updateButtonText() {
}
}

/* =========================================================
Toast
========================================================= */

function showErrorToast(message) {
const toastEl = document.getElementById("errorToast");
const toastBody = document.getElementById("errorToastBody");

if (!toastEl || !toastBody) return;

toastBody.textContent = message;

const toast = new bootstrap.Toast(toastEl);
toast.show();
}

// Persist default as soon as this script is loaded.
loadGraphTypeFromStorage();

// Loads Settings into Btn
document.addEventListener("DOMContentLoaded", () => {
loadGraphTypeFromStorage();
updateButtonText();
});
163 changes: 163 additions & 0 deletions src/settings/settings-http-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Settings HTTP Test</title>
<style>
body {
margin: 0;
padding: 20px;
font-family: Arial, sans-serif;
background: #f2f4f8;
color: #1f2937;
}

.layout {
display: grid;
gap: 16px;
grid-template-columns: 1fr;
max-width: 980px;
margin: 0 auto;
}

.card {
background: #fff;
border: 1px solid #d1d5db;
border-radius: 10px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

h1, h2 {
margin: 0 0 10px;
font-weight: 700;
}

.actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 10px;
}

button {
border: none;
border-radius: 6px;
padding: 8px 12px;
background: #2563eb;
color: #fff;
cursor: pointer;
}

button:hover {
background: #1d4ed8;
}

#clearBtn,
#clearGraphTypeBtn {
background: #dc2626;
}

#clearBtn:hover,
#clearGraphTypeBtn:hover {
background: #b91c1c;
}

pre {
margin: 0;
min-height: 44px;
padding: 10px;
background: #0f172a;
color: #e2e8f0;
border-radius: 6px;
overflow: auto;
white-space: pre-wrap;
word-break: break-word;
}

iframe {
width: 100%;
min-height: 520px;
border: 1px solid #d1d5db;
border-radius: 8px;
background: #fff;
}
</style>
</head>
<body>
<main class="layout">
<section class="card">
<h1>HTTP-Test fuer Einstellungen</h1>
<p>Diese Seite ist nur zum Testen. Das eigentliche Konstrukt von settings und graphTypeBtn bleibt unveraendert.</p>
</section>

<section class="card" aria-labelledby="storageTitle">
<h2 id="storageTitle">LocalStorage Kontrolle: userSettings</h2>
<div class="actions">
<button id="refreshBtn" type="button">Storage neu laden</button>
<button id="clearBtn" type="button">userSettings loeschen</button>
</div>
<pre id="storagePreview">(keine Daten im LocalStorage)</pre>
</section>

<section class="card" aria-labelledby="graphTypeStorageTitle">
<h2 id="graphTypeStorageTitle">LocalStorage Kontrolle: graphType</h2>
<div class="actions">
<button id="refreshGraphTypeBtn" type="button">graphType neu laden</button>
<button id="clearGraphTypeBtn" type="button">graphType loeschen</button>
</div>
<pre id="graphTypeStoragePreview">(keine Daten im LocalStorage)</pre>
</section>

<section class="card" aria-labelledby="componentTitle">
<h2 id="componentTitle">Eingebettete Settings-Komponente</h2>
<p>Oeffne im eingebetteten Bereich den Einstellungen-Button, aendere Werte und schliesse den Dialog. Danach oben auf "Storage neu laden" klicken.</p>
<iframe src="./settings.html" title="Settings Komponente"></iframe>
</section>

<section class="card" aria-labelledby="graphTypeComponentTitle">
<h2 id="graphTypeComponentTitle">Eingebetteter GraphType-Button</h2>
<p>Klicke den Button, um zwischen Balken- und Liniendiagramm umzuschalten. Danach oben auf "graphType neu laden" klicken.</p>
<iframe src="./graphType/graphType-http-test-host.html" title="GraphType Button"></iframe>
</section>
</main>

<script>
const SETTINGS_KEY = "userSettings";
const GRAPH_TYPE_KEY = "graphType";

function updatePreview() {
const preview = document.getElementById("storagePreview");
const raw = localStorage.getItem(SETTINGS_KEY);
preview.textContent = raw || "(keine Daten im LocalStorage)";
}

function updateGraphTypePreview() {
const preview = document.getElementById("graphTypeStoragePreview");
const raw = localStorage.getItem(GRAPH_TYPE_KEY);
preview.textContent = raw || "(keine Daten im LocalStorage)";
}

document.getElementById("refreshBtn").addEventListener("click", updatePreview);
document.getElementById("clearBtn").addEventListener("click", () => {
localStorage.removeItem(SETTINGS_KEY);
updatePreview();
});

document.getElementById("refreshGraphTypeBtn").addEventListener("click", updateGraphTypePreview);
document.getElementById("clearGraphTypeBtn").addEventListener("click", () => {
localStorage.removeItem(GRAPH_TYPE_KEY);
updateGraphTypePreview();
});

window.addEventListener("storage", () => {
updatePreview();
updateGraphTypePreview();
});

updatePreview();
updateGraphTypePreview();
</script>
</body>
</html>
Loading