浏览代码

done simplefox theme

Help-14 3 年之前
父节点
当前提交
4a7d6c1766

+ 13 - 0
src/languages/en.yaml

@@ -3,3 +3,16 @@ greeting:
     afternoon: Good afternoon!
     afternoon: Good afternoon!
     evening: Good evening!
     evening: Good evening!
     night: Good night!
     night: Good night!
+weather:
+    thunderstorm: Thunderstorm
+    drizzle: Drizzle
+    rain: Rain
+    snow: Snow
+    clear-day: Clear day
+    clear-night: Clear night
+    cloudy: Cloudy
+    partly-cloudy-day: Partly cloudy day
+    partly-cloudy-night: Partly cloudy night
+    sleet: Sleet
+    windy: Windy
+    foggy: Foggy

+ 13 - 0
src/languages/vi.yaml

@@ -3,3 +3,16 @@ greeting:
     afternoon: Chiều làm việc hiệu quả!
     afternoon: Chiều làm việc hiệu quả!
     evening: Chiều tối vui vẻ!
     evening: Chiều tối vui vẻ!
     night: Chúc ngủ ngon!
     night: Chúc ngủ ngon!
+weather:
+    thunderstorm: dông bão
+    drizzle: mưa phùn
+    rain: mưa lớn
+    snow: tuyết
+    clear-day: trời quang
+    clear-night: đêm trời quang
+    cloudy: nhiều mây
+    partly-cloudy-day: ngày có mây
+    partly-cloudy-night: đêm có mây
+    sleet: mưa đá
+    windy: gió todd
+    foggy: sương mù

+ 0 - 1
src/main.go

@@ -84,7 +84,6 @@ func loadData() {
 
 
 	// Load template engine
 	// Load template engine
 	themeDir := filepath.Join(pwd, "themes", appConfig.Website.Theme)
 	themeDir := filepath.Join(pwd, "themes", appConfig.Website.Theme)
-	log.Println(themeDir)
 	themefs = http.FileServer(http.Dir(themeDir))
 	themefs = http.FileServer(http.Dir(themeDir))
 	tmpl, _ := template.ParseFiles(filepath.Join(themeDir, "index.html"))
 	tmpl, _ := template.ParseFiles(filepath.Join(themeDir, "index.html"))
 	webTemplate = tmpl
 	webTemplate = tmpl

+ 26 - 8
src/modules/content.go

@@ -18,11 +18,13 @@ type ContentData struct {
 type GroupData struct {
 type GroupData struct {
 	Title   string       `yaml:"title"`
 	Title   string       `yaml:"title"`
 	Columns []ColumnData `yaml:"columns"`
 	Columns []ColumnData `yaml:"columns"`
+	Icon    string       `yaml:"icon"`
 }
 }
 
 
 type ColumnData struct {
 type ColumnData struct {
 	Title     string         `yaml:"title"`
 	Title     string         `yaml:"title"`
 	Bookmarks []BookmarkData `yaml:"bookmarks"`
 	Bookmarks []BookmarkData `yaml:"bookmarks"`
+	Icon      string         `yaml:"icon"`
 }
 }
 
 
 type BookmarkData struct {
 type BookmarkData struct {
@@ -32,14 +34,6 @@ type BookmarkData struct {
 	Icon string `yaml:"icon"`
 	Icon string `yaml:"icon"`
 }
 }
 
 
-func (b *BookmarkData) IsSVG() bool {
-	return strings.Contains(b.Icon, ".svg")
-}
-
-func (b *BookmarkData) IsImage() bool {
-	return contains(b.Icon, ".jpg", ".jpeg", ".png", ".gif", ".apng", ".bmp", ".ico", ".webp")
-}
-
 func LoadContent() ContentData {
 func LoadContent() ContentData {
 	emptyData := ContentData{}
 	emptyData := ContentData{}
 
 
@@ -80,3 +74,27 @@ func contains(str string, subStrs ...string) bool {
 	}
 	}
 	return true
 	return true
 }
 }
+
+func (b *BookmarkData) IsSVG() bool {
+	return strings.Contains(b.Icon, ".svg")
+}
+
+func (b *BookmarkData) IsImage() bool {
+	return contains(b.Icon, ".jpg", ".jpeg", ".png", ".gif", ".apng", ".bmp", ".ico", ".webp")
+}
+
+func (b *GroupData) IsSVG() bool {
+	return strings.Contains(b.Icon, ".svg")
+}
+
+func (b *GroupData) IsImage() bool {
+	return contains(b.Icon, ".jpg", ".jpeg", ".png", ".gif", ".apng", ".bmp", ".ico", ".webp")
+}
+
+func (b *ColumnData) IsSVG() bool {
+	return strings.Contains(b.Icon, ".svg")
+}
+
+func (b *ColumnData) IsImage() bool {
+	return contains(b.Icon, ".jpg", ".jpeg", ".png", ".gif", ".apng", ".bmp", ".ico", ".webp")
+}

+ 16 - 0
src/modules/language.go

@@ -10,6 +10,7 @@ import (
 
 
 type Language struct {
 type Language struct {
 	Greeting LanguageGreeting `yaml:"greeting"`
 	Greeting LanguageGreeting `yaml:"greeting"`
+	Weather  LanguageWeather  `yaml:"weather"`
 }
 }
 
 
 type LanguageGreeting struct {
 type LanguageGreeting struct {
@@ -19,6 +20,21 @@ type LanguageGreeting struct {
 	Night     string `yaml:"night"`
 	Night     string `yaml:"night"`
 }
 }
 
 
+type LanguageWeather struct {
+	Thunderstorm      string `yaml:"thunderstorm"`
+	Drizzle           string `yaml:"drizzle"`
+	Rain              string `yaml:"rain"`
+	Snow              string `yaml:"snow"`
+	ClearDay          string `yaml:"clear-day"`
+	ClearNight        string `yaml:"clear-night"`
+	Cloudy            string `yaml:"cloudy"`
+	PartlyCloudyDay   string `yaml:"partly-cloudy-day"`
+	PartlyCloudyNight string `yaml:"partly-cloudy-night"`
+	Sleet             string `yaml:"sleet"`
+	Windy             string `yaml:"windy"`
+	Foggy             string `yaml:"foggy"`
+}
+
 func LoadLanguage(language string) Language {
 func LoadLanguage(language string) Language {
 	yamlFile, err := ioutil.ReadFile(filepath.Join("languages", language+".yaml"))
 	yamlFile, err := ioutil.ReadFile(filepath.Join("languages", language+".yaml"))
 	if err != nil {
 	if err != nil {

+ 6 - 5
src/themes/custom/index.html

@@ -6,15 +6,16 @@
     <title>{{.Config.Title}}</title>
     <title>{{.Config.Title}}</title>
     <meta name="description" content="{{.Config.Description}}" />
     <meta name="description" content="{{.Config.Description}}" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="icon" type="image/png" href="common/assets/favicon.ico" />
-    <link rel="stylesheet" href="common/css/core.css">
-    <link rel="stylesheet" href="common/css/custom.css">
+    <link rel="icon" type="image/png" href="/common/assets/favicon.ico" />
+    <link rel="stylesheet" href="/common/css/all.min.css">
+    <link rel="stylesheet" href="/common/css/core.css">
+    <link rel="stylesheet" href="/common/css/custom.css">
 </head>
 </head>
 
 
 <body>
 <body>
 
 
-    <script src="common/js/core.js"></script>
-    <script src="common/js/custom.js"></script>
+    <script src="/common/js/core.js"></script>
+    <script src="/common/js/custom.js"></script>
 </body>
 </body>
 
 
 </html>
 </html>

+ 40 - 0
src/themes/simplefox/css/simplefox.css

@@ -0,0 +1,40 @@
+body {
+    background-color: var(--bgColor);
+    color: var(--foreground);
+    z-index: -999;
+}
+
+.foreground {
+    color: var(--foreground);
+}
+
+.box {
+    background-color: #201E21;
+    border: 1px solid rgba(0, 0, 0, 0) !important;
+}
+
+.box-hover {
+    background-color: var(--accentColor) !important;
+}
+
+.icon-container {
+    width: 32px;
+    height: 32px;
+}
+
+.icon-container-small {
+    width: 24px;
+    height: 24px;
+    align-content: center;
+}
+
+.icon {
+    vertical-align: middle;
+}
+
+.svg-icon {
+    vertical-align: middle;
+    fill: var(--foreground) !important;
+    width: 32px !important;
+    height: 32px !important;
+}

文件差异内容过多而无法显示
+ 0 - 0
src/themes/simplefox/css/tailwind.min.css


+ 192 - 0
src/themes/simplefox/index.html

@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<html lang="{{.Config.Language}}">
+
+<head>
+    <meta charset="UTF-8">
+    <title>{{.Config.Title}}</title>
+    <meta name="description" content="{{.Config.Description}}" />
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="icon" type="image/png" href="/common/assets/favicon.ico" />
+    <link href="/theme/css/tailwind.min.css" rel="stylesheet">
+    <link rel="stylesheet" href="/common/css/all.min.css">
+    <link rel="stylesheet" href="/common/css/core.css">
+    <link rel="stylesheet" href="/theme/css/simplefox.css">
+    <link rel="stylesheet" href="/common/css/custom.css">
+
+    <script>
+        customElements.define("svg-file", class extends HTMLElement {
+            async connectedCallback(
+                src = this.getAttribute("src"),
+                shadowRoot = this.shadowRoot || this.attachShadow({ mode: "open" })
+            ) {
+                shadowRoot.innerHTML = await (await fetch(src)).text()
+                shadowRoot.append(...this.querySelectorAll("[shadowRoot]"))
+                this.hasAttribute("replaceWith") && this.replaceWith(...shadowRoot.childNodes)
+            }
+        })
+    </script>
+</head>
+
+<body>
+    <div class="grid place-items-center h-screen">
+        <div class="flex">
+            <div class="shrink place-items-center inset-0">
+                <div class="grid gap-4 grid-cols-2 grid-rows-2">
+                    <div class="content-center">
+                        <p id="clock" class="text-6xl font-bold text-center"></p>
+                        <p id="greeting" class="text-2xl font-bold text-center"></p>
+                    </div>
+                    <div class="content-center">
+                        <p id="date" class="text-6xl font-bold text-center"></p>
+                        <div id="weather-info" class="flex place-items-center gap-3 justify-center">
+                            <div></div>
+                            <canvas id="weather-icon" width="40" height="40"></canvas>
+                            <p id="temp" class="text-2xl font-bold text-center"></p>
+                            <p id="weather-desc" class="text-center"></p>
+                            <div></div>
+                        </div>
+                    </div>
+                    <div class="grid grid-cols-4 gap-4">
+                        {{range (index (index .Contents 0).Columns 0).Bookmarks}}
+                        <div class="hover:bg-gray-800 box rounded-lg p-10 drop-shadow-xl cursor-pointer" onclick="window.location.href='{{.Url}}'">
+                            <div class="icon-container">
+                                {{if .IsImage}}
+                                <img src="{{.Icon}}" class="icon">
+                                {{else if .IsSVG}}
+                                <svg-file src="{{.Icon}}" class="svg-icon"></svg-file>
+                                {{else}}
+                                <i class="{{.Icon}} fa-2xl icon"></i>
+                                {{end}}
+                            </div>
+                        </div>
+                        {{end}}
+                    </div>
+                    <div class="grid gap-4 grid-cols-2">
+                        {{range (index .Contents 1).Columns}}
+                        <div class="box rounded-lg drop-shadow-xl gap-2 p-5 grid grid-flow-row auto-rows-max justify-center">
+                            <div class="icon-container-small mb-4">
+                                <center>
+                                    {{if .IsImage}}
+                                    <img src="{{.Icon}}" class="icon">
+                                    {{else if .IsSVG}}
+                                    <svg-file src="{{.Icon}}" class="svg-icon"></svg-file>
+                                    {{else}}
+                                    <i class="{{.Icon}} fa-xl icon"></i>
+                                    {{end}}
+                                </center>
+                            </div>
+                            {{range .Bookmarks}}
+                            <a href="{{.Url}}" class="text-center">{{.Name}}</a>
+                            {{end}}
+                        </div>
+                        {{end}}
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <script src="/theme/js/skycons.min.js"></script>
+    <script src="/common/js/core.js"></script>
+    <script>
+        window.config = {
+            localization: {{.Config.Localization}},
+            language: {{.Config.Language}},
+            useMetric: {{.Config.UseMetric}}
+        };
+
+        (function setTimer() {
+            const clock = document.querySelector("#clock");
+            const datetb = document.querySelector("#date");
+            const clockOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' };
+            (function clockTick() {
+                const now = new Date();
+                clock.innerText = `${now.getHours()}:${now.getMinutes().toLocaleString(window.config.localization, { minimumIntegerDigits: 2, useGrouping: false })}`;
+                datetb.innerText = now.toLocaleTimeString(window.config.localization, { month: 'short', day: 'numeric' }).split(',')[0];
+                setTimeout(clockTick, 2000);
+            })();
+            //Set greeting
+            const greeting = document.querySelector("#greeting");
+            const hour = new Date().getHours();
+            if (hour >= 5 && hour < 12) {
+                greeting.innerText = {{.Language.Greeting.Morning}};
+            }
+            else if (hour >= 12 && hour < 17) {
+                greeting.innerText = {{.Language.Greeting.Afternoon}};
+            }
+            else if (hour >= 17 && hour < 20) {
+                greeting.innerText = {{.Language.Greeting.Evening}};
+            }
+            else {
+                greeting.innerText = {{.Language.Greeting.Night}};
+            }
+        }) ();
+
+        async function loadWeather() {
+            // Get info from api
+            const weather = await (await fetch("./weather")).json();
+            if (!weather) return;
+            // Parse weather id
+            let icon = null;
+            let weatherDesc = "";
+            let hour = new Date().getHours();
+            let isDay = hour >= 6 && hour < 18;
+            const weatherCode = weather.weather[0].id;
+            if ([200, 201, 202, 210, 211, 212, 221, 230, 231, 232].includes(weatherCode)) {
+                icon = Skycons.RAIN; //Thunderstorm
+                weatherDesc = {{.Language.Weather.Thunderstorm}};
+            } else if ([300, 301, 302, 310, 311, 312, 313, 314, 321].includes(weatherCode)) {
+                icon = Skycons.RAIN; //Drizzle
+                weatherDesc = {{.Language.Weather.Drizzle}};
+            } else if ([500, 501, 502, 503, 504, 511, 520, 521, 522, 531].includes(weatherCode)) {
+                icon = Skycons.RAIN;
+                weatherDesc = {{.Language.Weather.Rain}};
+            } else if ([600, 601, 602, 611, 612, 613, 615, 616, 620, 621, 622].includes(weatherCode)) {
+                icon = Skycons.SNOW;
+                weatherDesc = {{.Language.Weather.Snow}};
+            } else if (weatherCode === 800) {
+                icon = isDay ? Skycons.CLEAR_DAY : Skycons.CLEAR_NIGHT;
+                weatherDesc = isDay ? {{.Language.Weather.ClearDay}} : {{.Language.Weather.ClearNight}};
+            } else if ([801, 802, 803, 804].includes(weatherCode)) {
+                if (weatherCode >= 803) {
+                    icon = Skycons.CLOUDY;
+                    weatherDesc = {{.Language.Weather.Cloudy}};
+                } else {
+                    icon = isDay ? Skycons.PARTLY_CLOUDY_DAY : Skycons.PARTLY_CLOUDY_NIGHT;
+                    weatherDesc = isDay ? {{.Language.Weather.PartlyCloudyDay}} : {{.Language.Weather.PartlyCloudyNight}};
+                }
+            } else if ([762, 761, 751, 731, 721].includes(weatherCode)) {
+                icon = Skycons.SLEET;
+                weatherDesc = {{.Language.Weather.Sleet}};
+            } else if ([771, 781].includes(weatherCode)) {
+                icon = Skycons.WIND;
+                weatherDesc = {{.Language.Weather.Windy}};
+            } else if ([701, 711, 741].includes(weatherCode)) {
+                icon = Skycons.FOG;
+                weatherDesc = {{.Language.Weather.Foggy}};
+            } else {
+                return;
+            }
+            // Set weather icon to canvas
+            var skycons = new Skycons({ "color": window.cssRoot["--accentColor"] });
+            skycons.add("weather-icon", icon);
+            skycons.play();
+            // Set weather info
+            if (window.config.useMetric) {
+                document.querySelector("#temp").innerText = Math.floor(weather.main.temp - 273.15) + "°C";
+            } else {
+                document.querySelector("#temp").innerText = Math.floor((weather.main.temp - 32) * 5 / 9) + "°F";
+            }
+            document.querySelector("#weather-info").style.visibility = "visible";
+            document.querySelector("#weather-desc").innerText = weatherDesc;
+        }
+
+        (function weatherTick() {
+            loadWeather();
+            setTimeout(weatherTick, 3600000);
+        })();
+    </script>
+    <script src="/common/js/custom.js"></script>
+</body>
+
+</html>

文件差异内容过多而无法显示
+ 0 - 0
src/themes/simplefox/js/skycons.min.js


+ 12 - 0
tools/screenshot/config/simplefox/config.yaml

@@ -0,0 +1,12 @@
+website:
+  theme: "simplefox"
+  title: "Magma Dashboard"
+  description: ""
+  language: "en"
+  localization: "en-US"
+  useMetric: true
+openweathermap:
+  apiKey: demo
+  lon: 0
+  lat: 0
+addons:

+ 57 - 0
tools/screenshot/config/simplefox/data.yaml

@@ -0,0 +1,57 @@
+data:
+  - title: Applications
+    columns:
+      - bookmarks:
+          - name: OpenWRT
+            icon: fa-solid fa-wifi
+            url: http://192.168.2.1
+          - name: Proxmox
+            icon: https://iconape.com/wp-content/files/pk/18549/svg/cib-proxmox.svg
+            url: http://192.168.2.200
+          - name: Home Assistant
+            icon: fa-solid fa-house
+            url: http://huawei.lan:8123/
+          - name: Docker
+            icon: fa-brands fa-docker
+            url: http://docker.lan/#!/2/docker/containers
+          - name: OpenWRT
+            icon: fa-solid fa-wifi
+            url: http://192.168.2.1
+          - name: Proxmox
+            icon: https://iconape.com/wp-content/files/pk/18549/svg/cib-proxmox.svg
+            url: http://192.168.2.200
+          - name: Home Assistant
+            icon: fa-solid fa-house
+            url: http://huawei.lan:8123/
+          - name: Docker
+            icon: fa-brands fa-docker
+            url: http://docker.lan/#!/2/docker/containers
+  - title: Bookmarks
+    columns:
+      - title: Social Media
+        icon: fa-solid fa-user-group
+        bookmarks:
+          - name: Facebook
+            icon: fa-brands fa-facebook
+            url: https://www.facebook.com
+          - name: Reddit
+            icon: fa-brands fa-reddit
+            url: https://www.reddit.com
+          - name: Voz
+            icon: https://files.help14.com/voz.svg
+            url: https://voz.vn
+          - name: Youtube
+            icon: fa-brands fa-youtube
+            url: https://www.youtube.com
+      - title: Shopping
+        icon: fa-solid fa-cart-shopping
+        bookmarks:
+          - name: Shopee
+            icon: fa-solid fa-bag-shopping
+            url: https://shopee.vn
+          - name: Lazada
+            icon: fa-solid fa-heart
+            url: https://www.lazada.vn/
+          - name: Shipping
+            icon: fa-solid fa-truck
+            url: http://nhaphang.com/i/#

部分文件因为文件数量过多而无法显示