From 1d446ace04b18db19c6323bcb9e2de5a89a8c6e5 Mon Sep 17 00:00:00 2001 From: James Read Date: Tue, 9 Apr 2024 09:26:18 +0100 Subject: [PATCH] custom-webui and faster theme loading (#262) * feature: custom-webui and faster theme loading * feature: custom-webui and faster theme loading --- cmd/OliveTin/main.go | 7 ++--- internal/config/config.go | 2 ++ internal/config/config_helpers.go | 8 +++++ internal/httpservers/webuiServer.go | 47 +++++++++++++++++++++++++++-- webui.dev/.parcelrc | 4 +++ webui.dev/index.html | 1 + webui.dev/main.js | 9 ------ webui.dev/package-lock.json | 25 +++++++++++++++ webui.dev/package.json | 4 +++ 9 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 webui.dev/.parcelrc diff --git a/cmd/OliveTin/main.go b/cmd/OliveTin/main.go index 92641a1..d097e6e 100644 --- a/cmd/OliveTin/main.go +++ b/cmd/OliveTin/main.go @@ -136,14 +136,13 @@ func reloadConfig() { os.Exit(1) } + cfg.SetDir(path.Dir(viper.ConfigFileUsed())) cfg.Sanitize() } func main() { - configDir := path.Dir(viper.ConfigFileUsed()) - log.WithFields(log.Fields{ - "configDir": configDir, + "configDir": cfg.GetDir(), }).Infof("OliveTin started") log.Debugf("Config: %+v", cfg) @@ -158,7 +157,7 @@ func main() { go entityfiles.SetupEntityFileWatchers(cfg) - go updatecheck.StartUpdateChecker(version, commit, cfg, configDir) + go updatecheck.StartUpdateChecker(version, commit, cfg, cfg.GetDir()) go grpcapi.Start(cfg, executor) diff --git a/internal/config/config.go b/internal/config/config.go index e8fe85a..6c6580f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -98,6 +98,8 @@ type Config struct { InsecureAllowDumpVars bool InsecureAllowDumpSos bool InsecureAllowDumpActionMap bool + + usedConfigDir string } type DashboardComponent struct { diff --git a/internal/config/config_helpers.go b/internal/config/config_helpers.go index 39f8f52..84769d6 100644 --- a/internal/config/config_helpers.go +++ b/internal/config/config_helpers.go @@ -42,3 +42,11 @@ func (cfg *Config) FindAcl(aclTitle string) *AccessControlList { return nil } + +func (cfg *Config) SetDir(dir string) { + cfg.usedConfigDir = dir +} + +func (cfg *Config) GetDir() string { + return cfg.usedConfigDir +} diff --git a/internal/httpservers/webuiServer.go b/internal/httpservers/webuiServer.go index b97b8b6..4a93a4d 100644 --- a/internal/httpservers/webuiServer.go +++ b/internal/httpservers/webuiServer.go @@ -4,16 +4,22 @@ import ( "encoding/json" // cors "github.com/OliveTin/OliveTin/internal/cors" log "github.com/sirupsen/logrus" + "io/ioutil" "net/http" "os" + "path" config "github.com/OliveTin/OliveTin/internal/config" updatecheck "github.com/OliveTin/OliveTin/internal/updatecheck" ) +var ( + customThemeCss []byte + customThemeCssRead = false +) + type webUISettings struct { Rest string - ThemeName string ShowFooter bool ShowNavigation bool ShowNewVersions bool @@ -52,10 +58,43 @@ func findWebuiDir() string { return "./webui" // Should not exist } +func findCustomWebuiDir() string { + dir := path.Join(cfg.GetDir(), "custom-webui") + + return dir +} + +func setupCustomWebuiDir() { + dir := findCustomWebuiDir() + + err := os.MkdirAll(path.Join(dir, "themes/"), 0775) + + if err != nil { + log.Warnf("Could not create themes directory: %v", err) + } +} + +func generateThemeCss(w http.ResponseWriter, r *http.Request) { + themeCssFilename := path.Join(findCustomWebuiDir(), "themes", cfg.ThemeName, "theme.css") + + if !customThemeCssRead { + customThemeCssRead = true + + if _, err := os.Stat(themeCssFilename); err == nil { + customThemeCss, err = ioutil.ReadFile(themeCssFilename) + } else { + log.Debugf("Theme CSS not read: %v", err) + customThemeCss = []byte("/* not found */") + } + } + + w.Header().Add("Content-Type", "text/css") + w.Write(customThemeCss) +} + func generateWebUISettings(w http.ResponseWriter, r *http.Request) { jsonRet, _ := json.Marshal(webUISettings{ Rest: cfg.ExternalRestAddress + "/api/", - ThemeName: cfg.ThemeName, ShowFooter: cfg.ShowFooter, ShowNavigation: cfg.ShowNavigation, ShowNewVersions: cfg.ShowNewVersions, @@ -77,8 +116,12 @@ func startWebUIServer(cfg *config.Config) { "address": cfg.ListenAddressWebUI, }).Info("Starting WebUI server") + setupCustomWebuiDir() + mux := http.NewServeMux() mux.Handle("/", http.FileServer(http.Dir(findWebuiDir()))) + mux.Handle("/custom-webui/", http.FileServer(http.Dir(findCustomWebuiDir()))) + mux.HandleFunc("/theme.css", generateThemeCss) mux.HandleFunc("/webUiSettings.json", generateWebUISettings) srv := &http.Server{ diff --git a/webui.dev/.parcelrc b/webui.dev/.parcelrc new file mode 100644 index 0000000..d459a24 --- /dev/null +++ b/webui.dev/.parcelrc @@ -0,0 +1,4 @@ +{ + "extends": "@parcel/config-default", + "resolvers": ["parcel-resolver-ignore", "..."] +} diff --git a/webui.dev/index.html b/webui.dev/index.html index e852584..29807c3 100644 --- a/webui.dev/index.html +++ b/webui.dev/index.html @@ -8,6 +8,7 @@ OliveTin + diff --git a/webui.dev/main.js b/webui.dev/main.js index 09aa488..6895065 100644 --- a/webui.dev/main.js +++ b/webui.dev/main.js @@ -103,15 +103,6 @@ function processWebuiSettingsJson (settings) { window.restBaseUrl = settings.Rest - if (settings.ThemeName) { - const themeCss = document.createElement('link') - themeCss.setAttribute('rel', 'stylesheet') - themeCss.setAttribute('type', 'text/css') - themeCss.setAttribute('href', '/themes/' + settings.ThemeName + '/theme.css') - - document.head.appendChild(themeCss) - } - document.querySelector('#currentVersion').innerText = settings.CurrentVersion if (settings.ShowNewVersions && settings.AvailableVersion !== 'none') { diff --git a/webui.dev/package-lock.json b/webui.dev/package-lock.json index 37a32d0..5233a58 100644 --- a/webui.dev/package-lock.json +++ b/webui.dev/package-lock.json @@ -15,6 +15,7 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.3.1", "parcel": "^2.11.0", + "parcel-resolver-ignore": "^2.2.0", "stylelint": "^15.6.0", "stylelint-config-standard": "^33.0.0" } @@ -5132,6 +5133,21 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/parcel-resolver-ignore": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parcel-resolver-ignore/-/parcel-resolver-ignore-2.2.0.tgz", + "integrity": "sha512-srQwekxRIiKVvAf9ljoFTw3WCrZVOhOcxOgHsWJ6FBK4yCD/w+7eNHvqWgtACVwVGkjyU6eVcy9eN9m2+Co6GA==", + "dev": true, + "dependencies": { + "@parcel/plugin": "^2.10.3" + }, + "engines": { + "parcel": ">=2.9.0" + }, + "funding": { + "url": "https://ko-fi.com/vladimirmikulic" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -9754,6 +9770,15 @@ "get-port": "^4.2.0" } }, + "parcel-resolver-ignore": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parcel-resolver-ignore/-/parcel-resolver-ignore-2.2.0.tgz", + "integrity": "sha512-srQwekxRIiKVvAf9ljoFTw3WCrZVOhOcxOgHsWJ6FBK4yCD/w+7eNHvqWgtACVwVGkjyU6eVcy9eN9m2+Co6GA==", + "dev": true, + "requires": { + "@parcel/plugin": "^2.10.3" + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", diff --git a/webui.dev/package.json b/webui.dev/package.json index 43d73f7..c404ebf 100644 --- a/webui.dev/package.json +++ b/webui.dev/package.json @@ -11,6 +11,7 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.3.1", "parcel": "^2.11.0", + "parcel-resolver-ignore": "^2.2.0", "stylelint": "^15.6.0", "stylelint-config-standard": "^33.0.0" }, @@ -18,5 +19,8 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", + "parcelIgnore": [ + "theme.css" + ], "license": "ISC" }