From 46bd235afc40f1004c199fb9497a8924c53b3c13 Mon Sep 17 00:00:00 2001 From: mboehmlaender Date: Tue, 17 Mar 2026 11:58:04 +0000 Subject: [PATCH] 0.10.2-19 Frontend --- backend/package-lock.json | 4 +- backend/package.json | 2 +- backend/src/db/database.js | 8 + backend/src/routes/settingsRoutes.js | 28 +++ db/schema.sql | 6 + frontend/package-lock.json | 4 +- frontend/package.json | 2 +- frontend/src/api/client.js | 9 + frontend/src/components/JobDetailDialog.jsx | 191 +++++++++++--------- frontend/src/pages/HistoryPage.jsx | 15 +- frontend/src/styles/app.css | 52 ++++++ package-lock.json | 4 +- package.json | 2 +- 13 files changed, 227 insertions(+), 100 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index eef3cbd..94ca1a1 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -1,12 +1,12 @@ { "name": "ripster-backend", - "version": "0.10.2-18", + "version": "0.10.2-19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ripster-backend", - "version": "0.10.2-18", + "version": "0.10.2-19", "dependencies": { "archiver": "^7.0.1", "cors": "^2.8.5", diff --git a/backend/package.json b/backend/package.json index 870b052..7a41ff7 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "ripster-backend", - "version": "0.10.2-18", + "version": "0.10.2-19", "private": true, "type": "commonjs", "scripts": { diff --git a/backend/src/db/database.js b/backend/src/db/database.js index 0477029..7d76cc5 100644 --- a/backend/src/db/database.js +++ b/backend/src/db/database.js @@ -967,6 +967,14 @@ async function migrateSettingsSchemaMetadata(db) { VALUES ('auto_eject_after_rip', 'Laufwerk', 'Laufwerk nach Rip auswerfen', 'boolean', 1, 'Wenn aktiv, wird das Laufwerk nach erfolgreichem Abschluss eines Rip-Vorgangs automatisch ausgeworfen (eject).', 'false', '[]', '{}', 45)` ); await db.run(`INSERT OR IGNORE INTO settings_values (key, value) VALUES ('auto_eject_after_rip', 'false')`); + + await db.run(` + CREATE TABLE IF NOT EXISTS user_prefs ( + key TEXT PRIMARY KEY, + value TEXT, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + ) + `); } async function getDb() { diff --git a/backend/src/routes/settingsRoutes.js b/backend/src/routes/settingsRoutes.js index 83147ea..d4b4993 100644 --- a/backend/src/routes/settingsRoutes.js +++ b/backend/src/routes/settingsRoutes.js @@ -11,6 +11,8 @@ const userPresetService = require('../services/userPresetService'); const activationBytesService = require('../services/activationBytesService'); const logger = require('../services/logger').child('SETTINGS_ROUTE'); +const { getDb } = require('../db/database'); + const router = express.Router(); function isSensitiveSettingKey(key) { @@ -400,4 +402,30 @@ router.post( }) ); +// User preferences (UI state, persisted per-installation) +router.get( + '/prefs/:key', + asyncHandler(async (req, res) => { + const { key } = req.params; + const db = await getDb(); + const row = await db.get('SELECT value FROM user_prefs WHERE key = ?', [key]); + res.json({ key, value: row ? row.value : null }); + }) +); + +router.put( + '/prefs/:key', + asyncHandler(async (req, res) => { + const { key } = req.params; + const { value } = req.body || {}; + const db = await getDb(); + await db.run( + `INSERT INTO user_prefs (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP) + ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`, + [key, value ?? null] + ); + res.json({ key, value: value ?? null }); + }) +); + module.exports = router; diff --git a/db/schema.sql b/db/schema.sql index 1b8f659..771c983 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -171,6 +171,12 @@ CREATE TABLE IF NOT EXISTS aax_activation_bytes ( created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP ); +CREATE TABLE IF NOT EXISTS user_prefs ( + key TEXT PRIMARY KEY, + value TEXT, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP +); + -- ============================================================================= -- Default Settings Seed -- ============================================================================= diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 79f01eb..013a69a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "ripster-frontend", - "version": "0.10.2-18", + "version": "0.10.2-19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ripster-frontend", - "version": "0.10.2-18", + "version": "0.10.2-19", "dependencies": { "primeicons": "^7.0.0", "primereact": "^10.9.2", diff --git a/frontend/package.json b/frontend/package.json index 56783e3..78c37bd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "ripster-frontend", - "version": "0.10.2-18", + "version": "0.10.2-19", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/api/client.js b/frontend/src/api/client.js index e3fda71..83e6983 100644 --- a/frontend/src/api/client.js +++ b/frontend/src/api/client.js @@ -415,6 +415,15 @@ export const api = { method: 'POST' }); }, + async getPref(key) { + return request(`/settings/prefs/${encodeURIComponent(key)}`); + }, + async setPref(key, value) { + return request(`/settings/prefs/${encodeURIComponent(key)}`, { + method: 'PUT', + body: JSON.stringify({ value }) + }); + }, async updateSetting(key, value) { const result = await request(`/settings/${encodeURIComponent(key)}`, { method: 'PUT', diff --git a/frontend/src/components/JobDetailDialog.jsx b/frontend/src/components/JobDetailDialog.jsx index db01dd0..ec65c70 100644 --- a/frontend/src/components/JobDetailDialog.jsx +++ b/frontend/src/components/JobDetailDialog.jsx @@ -878,8 +878,8 @@ export default function JobDetailDialog({ ) : null}

Aktionen

-
- {queueLocked ? ( + {queueLocked ? ( +
+ ) : ( +
+ {!isCd ? ( +
+
Kodierung
+ {canResumeReady ? ( +
+
+ ) : null} + {typeof onRestartEncode === 'function' ? ( +
+
+ ) : null} + {!isAudiobook && typeof onRestartReview === 'function' ? ( +
+
+ ) : null} + {!isAudiobook ? ( +
+
+ ) : null} +
+ ) : null} + +
+
Dateien löschen
+
+
+
+
+ +
+ Entfernt diesen Eintrag aus der Verlaufsliste — Dateien auf der Festplatte bleiben erhalten.
+
+
+ )}

Log

{showFinalLog ? ( diff --git a/frontend/src/pages/HistoryPage.jsx b/frontend/src/pages/HistoryPage.jsx index 4c02a32..0f55247 100644 --- a/frontend/src/pages/HistoryPage.jsx +++ b/frontend/src/pages/HistoryPage.jsx @@ -354,7 +354,7 @@ export default function HistoryPage({ refreshToken = 0 }) { const [search, setSearch] = useState(''); const [status, setStatus] = useState(''); const [mediumFilter, setMediumFilter] = useState(''); - const [layout, setLayout] = useState('list'); + const [layout, setLayout] = useState('grid'); const [sortKey, setSortKey] = useState('!start_time'); const [sortField, setSortField] = useState('start_time'); const [sortOrder, setSortOrder] = useState(-1); @@ -432,6 +432,14 @@ export default function HistoryPage({ refreshToken = 0 }) { } }; + useEffect(() => { + api.getPref('history_layout').then((res) => { + if (res?.value === 'list' || res?.value === 'grid') { + setLayout(res.value); + } + }).catch(() => {}); + }, []); + useEffect(() => { const timer = setTimeout(() => { load(); @@ -1169,7 +1177,10 @@ export default function HistoryPage({ refreshToken = 0 }) {