Przeglądaj źródła

custom-webui and faster theme loading (#262)

* feature: custom-webui and faster theme loading

* feature: custom-webui and faster theme loading
James Read 2 lat temu
rodzic
commit
1d446ace04

+ 3 - 4
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)
 

+ 2 - 0
internal/config/config.go

@@ -98,6 +98,8 @@ type Config struct {
 	InsecureAllowDumpVars           bool
 	InsecureAllowDumpSos            bool
 	InsecureAllowDumpActionMap      bool
+
+	usedConfigDir string
 }
 
 type DashboardComponent struct {

+ 8 - 0
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
+}

+ 45 - 2
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{

+ 4 - 0
webui.dev/.parcelrc

@@ -0,0 +1,4 @@
+{
+  "extends": "@parcel/config-default",
+  "resolvers": ["parcel-resolver-ignore", "..."]
+}

+ 1 - 0
webui.dev/index.html

@@ -8,6 +8,7 @@
 		<title>OliveTin</title>
 
 		<link rel = "stylesheet" type = "text/css" href = "style.css" />
+		<link rel = "stylesheet" type = "text/css" href = "theme.css" />
 		<link rel = "shortcut icon" type = "image/png" href = "OliveTinLogo.png" />
 
 		<link rel = "apple-touch-icon" sizes="57x57" href="OliveTinLogo-57px.png" />

+ 0 - 9
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') {

+ 25 - 0
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",

+ 4 - 0
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"
 }