From 32ab726fe9e4e347519a835d626e62ad6dfa19a4 Mon Sep 17 00:00:00 2001 From: zipben Date: Thu, 5 Jun 2025 10:34:06 +0000 Subject: [PATCH] added server styling settings --- client/assets/app.css | 88 ++++++++++- client/components/app/ConfigSideNav.vue | 7 +- client/components/app/GlobalStyling.vue | 53 +++++++ client/components/app/ServerSettingsTab.vue | 68 ++++++++ client/layouts/default.vue | 6 + client/pages/config/styling.vue | 164 ++++++++++++++++++++ client/store/index.js | 4 + client/strings/en-us.json | 12 +- client/strings/en.json | 21 +++ readme.md | 25 +++ server/objects/settings/ServerSettings.js | 21 +++ 11 files changed, 466 insertions(+), 3 deletions(-) create mode 100644 client/components/app/GlobalStyling.vue create mode 100644 client/components/app/ServerSettingsTab.vue create mode 100644 client/pages/config/styling.vue diff --git a/client/assets/app.css b/client/assets/app.css index 36b3b4bad..7ad730842 100644 --- a/client/assets/app.css +++ b/client/assets/app.css @@ -7,6 +7,92 @@ :root { --bookshelf-texture-img: url(~static/textures/wood_default.jpg); --bookshelf-divider-bg: linear-gradient(180deg, rgba(149, 119, 90, 1) 0%, rgba(103, 70, 37, 1) 17%, rgba(103, 70, 37, 1) 88%, rgba(71, 48, 25, 1) 100%); + + /* Theme Colors */ + --color-primary: #1e293b; + --color-primary-dark: #0f172a; + --color-success: #22c55e; + --color-warning: #f59e0b; + --color-error: #ef4444; + --color-info: #3b82f6; + --color-bg: #111827; +} + +/* Color Classes */ +.bg-primary { + background-color: var(--color-primary) !important; +} + +.bg-primary-dark { + background-color: var(--color-primary-dark) !important; +} + +.bg-success { + background-color: var(--color-success) !important; +} + +.bg-warning { + background-color: var(--color-warning) !important; +} + +.bg-error { + background-color: var(--color-error) !important; +} + +.bg-info { + background-color: var(--color-info) !important; +} + +.bg-bg { + background-color: var(--color-bg) !important; +} + +.text-primary { + color: var(--color-primary) !important; +} + +.text-primary-dark { + color: var(--color-primary-dark) !important; +} + +.text-success { + color: var(--color-success) !important; +} + +.text-warning { + color: var(--color-warning) !important; +} + +.text-error { + color: var(--color-error) !important; +} + +.text-info { + color: var(--color-info) !important; +} + +.border-primary { + border-color: var(--color-primary) !important; +} + +.border-primary-dark { + border-color: var(--color-primary-dark) !important; +} + +.border-success { + border-color: var(--color-success) !important; +} + +.border-warning { + border-color: var(--color-warning) !important; +} + +.border-error { + border-color: var(--color-error) !important; +} + +.border-info { + border-color: var(--color-info) !important; } .page { @@ -249,4 +335,4 @@ Bookshelf Label .abs-btn:disabled::before { background-color: rgba(0, 0, 0, 0.2); -} +} \ No newline at end of file diff --git a/client/components/app/ConfigSideNav.vue b/client/components/app/ConfigSideNav.vue index 50fa7a06f..533e691d1 100644 --- a/client/components/app/ConfigSideNav.vue +++ b/client/components/app/ConfigSideNav.vue @@ -7,7 +7,7 @@

{{ route.title }}

-
+
@@ -109,6 +109,11 @@ export default { id: 'config-authentication', title: this.$strings.HeaderAuthentication, path: '/config/authentication' + }, + { + id: 'styling', + title: this.$strings.HeaderStyling, + path: '/config/styling' } ] diff --git a/client/components/app/GlobalStyling.vue b/client/components/app/GlobalStyling.vue new file mode 100644 index 000000000..b9cb7262e --- /dev/null +++ b/client/components/app/GlobalStyling.vue @@ -0,0 +1,53 @@ + + + \ No newline at end of file diff --git a/client/components/app/ServerSettingsTab.vue b/client/components/app/ServerSettingsTab.vue new file mode 100644 index 000000000..6621fb710 --- /dev/null +++ b/client/components/app/ServerSettingsTab.vue @@ -0,0 +1,68 @@ + + + \ No newline at end of file diff --git a/client/layouts/default.vue b/client/layouts/default.vue index 33e7aa15b..db858ceaa 100644 --- a/client/layouts/default.vue +++ b/client/layouts/default.vue @@ -1,5 +1,6 @@ \ No newline at end of file diff --git a/client/store/index.js b/client/store/index.js index b9feec8db..f7c78d5a8 100644 --- a/client/store/index.js +++ b/client/store/index.js @@ -36,6 +36,10 @@ export const getters = { if (!state.serverSettings) return null return state.serverSettings[key] }, + getServerStyling: (state) => { + if (!state.serverSettings?.styling) return null + return state.serverSettings.styling + }, getLibraryItemIdStreaming: (state) => { return state.streamLibraryItem?.id || null }, diff --git a/client/strings/en-us.json b/client/strings/en-us.json index 85eda5ee0..6574aeac6 100644 --- a/client/strings/en-us.json +++ b/client/strings/en-us.json @@ -1119,5 +1119,15 @@ "LabelRating": "Rating", "LabelStarRating": "{0} stars", "LabelNoRating": "No rating", - "LabelAverageRating": "Average rating: {0}" + "LabelAverageRating": "Average rating: {0}", + "HeaderStyling": "Styling", + "HeaderStylingColors": "Colors", + "HeaderStylingPreview": "Preview", + "LabelBackgroundColor": "Background Color", + "LabelErrorColor": "Error Color", + "LabelInfoColor": "Info Color", + "LabelPrimaryColor": "Primary Color", + "LabelPrimaryDarkColor": "Primary Dark Color", + "LabelSuccessColor": "Success Color", + "LabelWarningColor": "Warning Color" } diff --git a/client/strings/en.json b/client/strings/en.json index 13e3c213e..c8e51a5bb 100644 --- a/client/strings/en.json +++ b/client/strings/en.json @@ -1,4 +1,25 @@ { + "HeaderServerStyling": "Server Styling", + "DescriptionServerStyling": "Customize server appearance", + "HeaderSettings": "Settings", + "HeaderLibraries": "Libraries", + "HeaderUsers": "Users", + "HeaderListeningSessions": "Listening Sessions", + "HeaderBackups": "Backups", + "HeaderLogs": "Logs", + "HeaderNotifications": "Notifications", + "HeaderEmail": "Email", + "HeaderItemMetadataUtils": "Item Metadata Utils", + "HeaderRSSFeeds": "RSS Feeds", + "HeaderAuthentication": "Authentication", + "HeaderLibraryStats": "Library Stats", + "HeaderYourStats": "Your Stats", + "DescriptionAuthentication": "Configure authentication methods and settings", + "DescriptionLibraries": "Manage your libraries", + "DescriptionBackups": "Configure server backups", + "DescriptionEmail": "Configure email settings", + "DescriptionNotifications": "Configure notification settings", + "DescriptionServerLogs": "View server logs", "LabelSelectAll": "Select All", "LabelComments": "Comments", "PlaceholderAddComment": "Add a comment... (Ctrl+Enter to post)", diff --git a/readme.md b/readme.md index 3eb4cef7a..d2fc6b0c5 100644 --- a/readme.md +++ b/readme.md @@ -450,3 +450,28 @@ If you are using VSCode, this project includes a couple of pre-defined targets t # How to Support [See the incomplete "How to Support" page](https://www.audiobookshelf.org/support) + +# Development + +### Killing Running Processes +When developing locally, you might need to kill running instances of the client or server. Here are some helpful commands: + +```bash +# Kill process on port 3000 (client) +sudo kill $(lsof -t -i:3000) + +# Kill process on port 3333 (server) +sudo kill $(lsof -t -i:3333) +``` + +You can also find and kill processes manually: +```bash +# List all Node.js processes +ps aux | grep node + +# Kill processes by PID +kill + +# Force kill if process won't exit +kill -9 +``` diff --git a/server/objects/settings/ServerSettings.js b/server/objects/settings/ServerSettings.js index 29913e449..a8d2ce177 100644 --- a/server/objects/settings/ServerSettings.js +++ b/server/objects/settings/ServerSettings.js @@ -9,6 +9,17 @@ class ServerSettings { this.id = 'server-settings' this.tokenSecret = null + // Styling + this.styling = { + primary: '#1e293b', + primaryDark: '#0f172a', + success: '#22c55e', + warning: '#f59e0b', + error: '#ef4444', + info: '#3b82f6', + background: '#111827' + } + // Scanner this.scannerParseSubtitle = false this.scannerFindCovers = false @@ -88,6 +99,15 @@ class ServerSettings { construct(settings) { this.tokenSecret = settings.tokenSecret + + // Styling + if (settings.styling) { + this.styling = { + ...this.styling, + ...settings.styling + } + } + this.scannerFindCovers = !!settings.scannerFindCovers this.scannerCoverProvider = settings.scannerCoverProvider || 'google' this.scannerParseSubtitle = settings.scannerParseSubtitle @@ -204,6 +224,7 @@ class ServerSettings { return { id: this.id, tokenSecret: this.tokenSecret, // Do not return to client + styling: { ...this.styling }, scannerFindCovers: this.scannerFindCovers, scannerCoverProvider: this.scannerCoverProvider, scannerParseSubtitle: this.scannerParseSubtitle,