Pārlūkot izejas kodu

Merge branch 'main' into dev

Svilen Markov 4 mēneši atpakaļ
vecāks
revīzija
c33fe45d4c

+ 24 - 6
docs/configuration.md

@@ -97,9 +97,9 @@ Including config files from within your main config file is supported. This is d
 
 
 ```yaml
 ```yaml
 pages:
 pages:
-  !include home.yml
-  !include videos.yml
-  !include homelab.yml
+  !include: home.yml
+  !include: videos.yml
+  !include: homelab.yml
 ```
 ```
 
 
 The file you are including should not have any additional indentation, its values should be at the top level and the appropriate amount of indentation will be added automatically depending on where the file is included. Example:
 The file you are including should not have any additional indentation, its values should be at the top level and the appropriate amount of indentation will be added automatically depending on where the file is included. Example:
@@ -112,14 +112,14 @@ pages:
     columns:
     columns:
       - size: full
       - size: full
         widgets:
         widgets:
-          !include rss.yml
+          !include: rss.yml
   - name: News
   - name: News
     columns:
     columns:
       - size: full
       - size: full
         widgets:
         widgets:
           - type: group
           - type: group
             widgets:
             widgets:
-              !include rss.yml
+              !include: rss.yml
               - type: reddit
               - type: reddit
                 subreddit: news
                 subreddit: news
 ```
 ```
@@ -1672,7 +1672,7 @@ For services with multiple containers you can specify a `glance.id` on the "main
 <br>
 <br>
 
 
 ```yaml
 ```yaml
-servies:
+services:
   immich-server:
   immich-server:
     image: ghcr.io/immich-app/immich-server
     image: ghcr.io/immich-app/immich-server
     labels:
     labels:
@@ -1852,11 +1852,29 @@ Whether to hide the swap usage.
 | Name | Type | Required | Default |
 | Name | Type | Required | Default |
 | ---- | ---- | -------- | ------- |
 | ---- | ---- | -------- | ------- |
 | cpu-temp-sensor | string | no |  |
 | cpu-temp-sensor | string | no |  |
+| hide-mointpoints-by-default | boolean | no | false |
 | mountpoints | map\[string\]object | no |  |
 | mountpoints | map\[string\]object | no |  |
 
 
 ###### `cpu-temp-sensor`
 ###### `cpu-temp-sensor`
 The name of the sensor to use for the CPU temperature. When not provided the widget will attempt to find the correct one, if it fails to do so the temperature will not be displayed. To view the available sensors you can use `sensors` command.
 The name of the sensor to use for the CPU temperature. When not provided the widget will attempt to find the correct one, if it fails to do so the temperature will not be displayed. To view the available sensors you can use `sensors` command.
 
 
+###### `hide-mountpoints-by-default`
+If set to `true` you'll have to manually make each mountpoint visible by adding a `hide: false` property to it like so:
+
+```yaml
+- type: server-stats
+  servers:
+    - type: local
+      hide-mountpoints-by-default: true
+      mountpoints:
+        "/":
+          hide: false
+        "/mnt/data":
+          hide: false
+```
+
+This is useful if you're running Glance inside of a container which usually mounts a lot of irrelevant filesystems.
+
 ###### `mountpoints`
 ###### `mountpoints`
 A map of mountpoints to display disk usage for. The key is the path to the mountpoint and the value is an object with optional properties. Example:
 A map of mountpoints to display disk usage for. The key is the path to the mountpoint and the value is an object with optional properties. Example:
 
 

+ 2 - 2
internal/glance/config-fields.go

@@ -152,9 +152,9 @@ func newCustomIconField(value string) customIconField {
 		}
 		}
 
 
 		if prefix == "di" {
 		if prefix == "di" {
-			field.URL = "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/" + ext + "/" + basename + "." + ext
+			field.URL = "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/" + ext + "/" + basename + "." + ext
 		} else {
 		} else {
-			field.URL = "https://cdn.jsdelivr.net/gh/selfhst/icons@main/" + ext + "/" + basename + "." + ext
+			field.URL = "https://cdn.jsdelivr.net/gh/selfhst/icons/" + ext + "/" + basename + "." + ext
 		}
 		}
 	default:
 	default:
 		field.URL = value
 		field.URL = value

+ 2 - 1
internal/glance/static/js/popover.js

@@ -98,7 +98,6 @@ function showPopover() {
     }
     }
 
 
     contentElement.style.maxWidth = contentMaxWidth;
     contentElement.style.maxWidth = contentMaxWidth;
-    containerElement.style.display = "block";
     activeTarget.classList.add("popover-active");
     activeTarget.classList.add("popover-active");
     document.addEventListener("keydown", handleHidePopoverOnEscape);
     document.addEventListener("keydown", handleHidePopoverOnEscape);
     window.addEventListener("resize", queueRepositionContainer);
     window.addEventListener("resize", queueRepositionContainer);
@@ -106,6 +105,8 @@ function showPopover() {
 }
 }
 
 
 function repositionContainer() {
 function repositionContainer() {
+    containerElement.style.display = "block";
+
     const targetBounds = activeTarget.dataset.popoverAnchor !== undefined
     const targetBounds = activeTarget.dataset.popoverAnchor !== undefined
         ? activeTarget.querySelector(activeTarget.dataset.popoverAnchor).getBoundingClientRect()
         ? activeTarget.querySelector(activeTarget.dataset.popoverAnchor).getBoundingClientRect()
         : activeTarget.getBoundingClientRect();
         : activeTarget.getBoundingClientRect();

+ 2 - 1
internal/glance/widget-videos.go

@@ -52,10 +52,11 @@ func (widget *videosWidget) initialize() error {
 	// playlists are separate things rather than specifying a list of channels and some of
 	// playlists are separate things rather than specifying a list of channels and some of
 	// them awkwardly have a "playlist:" prefix
 	// them awkwardly have a "playlist:" prefix
 	if len(widget.Playlists) > 0 {
 	if len(widget.Playlists) > 0 {
+		initialLen := len(widget.Channels)
 		widget.Channels = append(widget.Channels, make([]string, len(widget.Playlists))...)
 		widget.Channels = append(widget.Channels, make([]string, len(widget.Playlists))...)
 
 
 		for i := range widget.Playlists {
 		for i := range widget.Playlists {
-			widget.Channels[len(widget.Channels)-1+i] = "playlist:" + widget.Playlists[i]
+			widget.Channels[initialLen+i] = "playlist:" + widget.Playlists[i]
 		}
 		}
 	}
 	}
 
 

+ 41 - 12
pkg/sysinfo/sysinfo.go

@@ -3,6 +3,7 @@ package sysinfo
 import (
 import (
 	"fmt"
 	"fmt"
 	"math"
 	"math"
+	"os"
 	"runtime"
 	"runtime"
 	"sort"
 	"sort"
 	"strconv"
 	"strconv"
@@ -73,24 +74,52 @@ type MountpointInfo struct {
 }
 }
 
 
 type SystemInfoRequest struct {
 type SystemInfoRequest struct {
-	CPUTempSensor string                       `yaml:"cpu-temp-sensor"`
-	Mountpoints   map[string]MointpointRequest `yaml:"mountpoints"`
+	CPUTempSensor            string                       `yaml:"cpu-temp-sensor"`
+	HideMountpointsByDefault bool                         `yaml:"hide-mountpoints-by-default"`
+	Mountpoints              map[string]MointpointRequest `yaml:"mountpoints"`
 }
 }
 
 
 type MointpointRequest struct {
 type MointpointRequest struct {
 	Name string `yaml:"name"`
 	Name string `yaml:"name"`
-	Hide bool   `yaml:"hide"`
+	Hide *bool  `yaml:"hide"`
 }
 }
 
 
 // Currently caches hostname indefinitely which isn't ideal
 // Currently caches hostname indefinitely which isn't ideal
 // Potential issue with caching boot time as it may not initially get reported correctly:
 // Potential issue with caching boot time as it may not initially get reported correctly:
 // https://github.com/shirou/gopsutil/issues/842#issuecomment-1908972344
 // https://github.com/shirou/gopsutil/issues/842#issuecomment-1908972344
-var cachedHostInfo = struct {
+type cacheableHostInfo struct {
 	available bool
 	available bool
 	hostname  string
 	hostname  string
 	platform  string
 	platform  string
 	bootTime  timestampJSON
 	bootTime  timestampJSON
-}{}
+}
+
+var cachedHostInfo cacheableHostInfo
+
+func getHostInfo() (cacheableHostInfo, error) {
+	var err error
+	info := cacheableHostInfo{}
+
+	info.hostname, err = os.Hostname()
+	if err != nil {
+		return info, err
+	}
+
+	info.platform, _, _, err = host.PlatformInformation()
+	if err != nil {
+		return info, err
+	}
+
+	bootTime, err := host.BootTime()
+	if err != nil {
+		return info, err
+	}
+
+	info.bootTime = timestampJSON{time.Unix(int64(bootTime), 0)}
+	info.available = true
+
+	return info, nil
+}
 
 
 func Collect(req *SystemInfoRequest) (*SystemInfo, []error) {
 func Collect(req *SystemInfoRequest) (*SystemInfo, []error) {
 	if req == nil {
 	if req == nil {
@@ -117,13 +146,9 @@ func Collect(req *SystemInfoRequest) (*SystemInfo, []error) {
 	if cachedHostInfo.available {
 	if cachedHostInfo.available {
 		applyCachedHostInfo()
 		applyCachedHostInfo()
 	} else {
 	} else {
-		hostInfo, err := host.Info()
+		hostInfo, err := getHostInfo()
 		if err == nil {
 		if err == nil {
-			cachedHostInfo.available = true
-			cachedHostInfo.bootTime = timestampJSON{time.Unix(int64(hostInfo.BootTime), 0)}
-			cachedHostInfo.hostname = hostInfo.Hostname
-			cachedHostInfo.platform = hostInfo.Platform
-
+			cachedHostInfo = hostInfo
 			applyCachedHostInfo()
 			applyCachedHostInfo()
 		} else {
 		} else {
 			addErr(fmt.Errorf("getting host info: %v", err))
 			addErr(fmt.Errorf("getting host info: %v", err))
@@ -205,7 +230,11 @@ func Collect(req *SystemInfoRequest) (*SystemInfo, []error) {
 	if err == nil {
 	if err == nil {
 		for _, fs := range filesystems {
 		for _, fs := range filesystems {
 			mpReq, ok := req.Mountpoints[fs.Mountpoint]
 			mpReq, ok := req.Mountpoints[fs.Mountpoint]
-			if ok && mpReq.Hide {
+			isHidden := req.HideMountpointsByDefault
+			if ok && mpReq.Hide != nil {
+				isHidden = *mpReq.Hide
+			}
+			if isHidden {
 				continue
 				continue
 			}
 			}