done simplefox theme
This commit is contained in:
parent
137eb1cd91
commit
4a7d6c1766
12 changed files with 377 additions and 14 deletions
|
@ -3,3 +3,16 @@ greeting:
|
|||
afternoon: Good afternoon!
|
||||
evening: Good evening!
|
||||
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
|
||||
|
|
|
@ -3,3 +3,16 @@ greeting:
|
|||
afternoon: Chiều làm việc hiệu quả!
|
||||
evening: Chiều tối vui vẻ!
|
||||
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ù
|
||||
|
|
|
@ -84,7 +84,6 @@ func loadData() {
|
|||
|
||||
// Load template engine
|
||||
themeDir := filepath.Join(pwd, "themes", appConfig.Website.Theme)
|
||||
log.Println(themeDir)
|
||||
themefs = http.FileServer(http.Dir(themeDir))
|
||||
tmpl, _ := template.ParseFiles(filepath.Join(themeDir, "index.html"))
|
||||
webTemplate = tmpl
|
||||
|
|
|
@ -18,11 +18,13 @@ type ContentData struct {
|
|||
type GroupData struct {
|
||||
Title string `yaml:"title"`
|
||||
Columns []ColumnData `yaml:"columns"`
|
||||
Icon string `yaml:"icon"`
|
||||
}
|
||||
|
||||
type ColumnData struct {
|
||||
Title string `yaml:"title"`
|
||||
Bookmarks []BookmarkData `yaml:"bookmarks"`
|
||||
Icon string `yaml:"icon"`
|
||||
}
|
||||
|
||||
type BookmarkData struct {
|
||||
|
@ -32,14 +34,6 @@ type BookmarkData struct {
|
|||
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 {
|
||||
emptyData := ContentData{}
|
||||
|
||||
|
@ -80,3 +74,27 @@ func contains(str string, subStrs ...string) bool {
|
|||
}
|
||||
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")
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
type Language struct {
|
||||
Greeting LanguageGreeting `yaml:"greeting"`
|
||||
Weather LanguageWeather `yaml:"weather"`
|
||||
}
|
||||
|
||||
type LanguageGreeting struct {
|
||||
|
@ -19,6 +20,21 @@ type LanguageGreeting struct {
|
|||
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 {
|
||||
yamlFile, err := ioutil.ReadFile(filepath.Join("languages", language+".yaml"))
|
||||
if err != nil {
|
||||
|
|
|
@ -6,15 +6,16 @@
|
|||
<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 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>
|
||||
|
||||
<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>
|
||||
|
||||
</html>
|
40
src/themes/simplefox/css/simplefox.css
Normal file
40
src/themes/simplefox/css/simplefox.css
Normal file
|
@ -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;
|
||||
}
|
1
src/themes/simplefox/css/tailwind.min.css
vendored
Normal file
1
src/themes/simplefox/css/tailwind.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
192
src/themes/simplefox/index.html
Normal file
192
src/themes/simplefox/index.html
Normal file
|
@ -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>
|
1
src/themes/simplefox/js/skycons.min.js
vendored
Normal file
1
src/themes/simplefox/js/skycons.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
12
tools/screenshot/config/simplefox/config.yaml
Normal file
12
tools/screenshot/config/simplefox/config.yaml
Normal file
|
@ -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
tools/screenshot/config/simplefox/data.yaml
Normal file
57
tools/screenshot/config/simplefox/data.yaml
Normal file
|
@ -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/#
|
Loading…
Add table
Reference in a new issue