mirror of
https://github.com/henrygd/beszel.git
synced 2025-12-17 10:46:16 +01:00
update favicon to show down count in bubble
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70" fill="#22c55e"><path d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 906 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70" fill="#dc2626"><path d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 906 B |
@@ -1 +1,9 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70" fill="#888"><path d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="gradient" x1="0%" y1="20%" x2="100%" y2="120%">
|
||||||
|
<stop offset="0%" style="stop-color:#747bff"/>
|
||||||
|
<stop offset="100%" style="stop-color:#24eb5c"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path fill="url(#gradient)" d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/>
|
||||||
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 903 B After Width: | Height: | Size: 1.1 KiB |
@@ -3,7 +3,7 @@ import PocketBase from "pocketbase"
|
|||||||
import { basePath } from "@/components/router"
|
import { basePath } from "@/components/router"
|
||||||
import { toast } from "@/components/ui/use-toast"
|
import { toast } from "@/components/ui/use-toast"
|
||||||
import type { ChartTimes, UserSettings } from "@/types"
|
import type { ChartTimes, UserSettings } from "@/types"
|
||||||
import { $alerts, $allSystemsByName, $userSettings } from "./stores"
|
import { $alerts, $allSystemsById, $allSystemsByName, $userSettings } from "./stores"
|
||||||
import { chartTimeData } from "./utils"
|
import { chartTimeData } from "./utils"
|
||||||
|
|
||||||
/** PocketBase JS Client */
|
/** PocketBase JS Client */
|
||||||
@@ -28,6 +28,7 @@ export const verifyAuth = () => {
|
|||||||
/** Logs the user out by clearing the auth store and unsubscribing from realtime updates. */
|
/** Logs the user out by clearing the auth store and unsubscribing from realtime updates. */
|
||||||
export function logOut() {
|
export function logOut() {
|
||||||
$allSystemsByName.set({})
|
$allSystemsByName.set({})
|
||||||
|
$allSystemsById.set({})
|
||||||
$alerts.set({})
|
$alerts.set({})
|
||||||
$userSettings.set({} as UserSettings)
|
$userSettings.set({} as UserSettings)
|
||||||
sessionStorage.setItem("lo", "t") // prevent auto login on logout
|
sessionStorage.setItem("lo", "t") // prevent auto login on logout
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
$pausedSystems,
|
$pausedSystems,
|
||||||
$upSystems,
|
$upSystems,
|
||||||
} from "@/lib/stores"
|
} from "@/lib/stores"
|
||||||
import { FAVICON_DEFAULT, FAVICON_GREEN, FAVICON_RED, updateFavicon } from "@/lib/utils"
|
import { updateFavicon } from "@/lib/utils"
|
||||||
import type { SystemRecord } from "@/types"
|
import type { SystemRecord } from "@/types"
|
||||||
import { SystemStatus } from "./enums"
|
import { SystemStatus } from "./enums"
|
||||||
|
|
||||||
@@ -74,9 +74,7 @@ export function init() {
|
|||||||
|
|
||||||
/** Update the longest system name length and favicon based on system status */
|
/** Update the longest system name length and favicon based on system status */
|
||||||
function onSystemsChanged(_: Record<string, SystemRecord>, changedSystem: SystemRecord | undefined) {
|
function onSystemsChanged(_: Record<string, SystemRecord>, changedSystem: SystemRecord | undefined) {
|
||||||
const upSystemsStore = $upSystems.get()
|
|
||||||
const downSystemsStore = $downSystems.get()
|
const downSystemsStore = $downSystems.get()
|
||||||
const upSystems = Object.values(upSystemsStore)
|
|
||||||
const downSystems = Object.values(downSystemsStore)
|
const downSystems = Object.values(downSystemsStore)
|
||||||
|
|
||||||
// Update longest system name length
|
// Update longest system name length
|
||||||
@@ -86,14 +84,7 @@ function onSystemsChanged(_: Record<string, SystemRecord>, changedSystem: System
|
|||||||
$longestSystemNameLen.set(nameLen)
|
$longestSystemNameLen.set(nameLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update favicon based on system status
|
updateFavicon(downSystems.length)
|
||||||
if (downSystems.length > 0) {
|
|
||||||
updateFavicon(FAVICON_RED)
|
|
||||||
} else if (upSystems.length > 0) {
|
|
||||||
updateFavicon(FAVICON_GREEN)
|
|
||||||
} else {
|
|
||||||
updateFavicon(FAVICON_DEFAULT)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fetch systems from collection */
|
/** Fetch systems from collection */
|
||||||
|
|||||||
@@ -4,16 +4,11 @@ import { listenKeys } from "nanostores"
|
|||||||
import { timeDay, timeHour, timeMinute } from "d3-time"
|
import { timeDay, timeHour, timeMinute } from "d3-time"
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import { twMerge } from "tailwind-merge"
|
import { twMerge } from "tailwind-merge"
|
||||||
import { prependBasePath } from "@/components/router"
|
|
||||||
import { toast } from "@/components/ui/use-toast"
|
import { toast } from "@/components/ui/use-toast"
|
||||||
import type { ChartTimeData, FingerprintRecord, SemVer, SystemRecord } from "@/types"
|
import type { ChartTimeData, FingerprintRecord, SemVer, SystemRecord } from "@/types"
|
||||||
import { HourFormat, MeterState, Unit } from "./enums"
|
import { HourFormat, MeterState, Unit } from "./enums"
|
||||||
import { $copyContent, $userSettings } from "./stores"
|
import { $copyContent, $userSettings } from "./stores"
|
||||||
|
|
||||||
export const FAVICON_DEFAULT = "favicon.svg"
|
|
||||||
export const FAVICON_GREEN = "favicon-green.svg"
|
|
||||||
export const FAVICON_RED = "favicon-red.svg"
|
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs))
|
return twMerge(clsx(inputs))
|
||||||
}
|
}
|
||||||
@@ -100,9 +95,36 @@ export const formatDay = (timestamp: string) => {
|
|||||||
return dayFormatter.format(new Date(timestamp))
|
return dayFormatter.format(new Date(timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const updateFavicon = (newIcon: string) => {
|
export const updateFavicon = (() => {
|
||||||
;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = prependBasePath(`/static/${newIcon}`)
|
let prevDownCount = 0
|
||||||
|
return (downCount = 0) => {
|
||||||
|
if (downCount === prevDownCount) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
prevDownCount = downCount
|
||||||
|
const svg = `
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="gradient" x1="0%" y1="20%" x2="100%" y2="120%">
|
||||||
|
<stop offset="0%" style="stop-color:#747bff"/>
|
||||||
|
<stop offset="100%" style="stop-color:#24eb5c"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path fill="url(#gradient)" d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/>
|
||||||
|
${
|
||||||
|
downCount > 0 &&
|
||||||
|
`
|
||||||
|
<circle cx="40" cy="50" r="22" fill="#f00"/>
|
||||||
|
<text x="40" y="60" font-size="34" text-anchor="middle" fill="#fff" font-family="Arial" font-weight="bold">${downCount}</text>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
</svg>
|
||||||
|
`
|
||||||
|
const blob = new Blob([svg], { type: "image/svg+xml" })
|
||||||
|
const url = URL.createObjectURL(blob)
|
||||||
|
;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = url
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
export const chartTimeData: ChartTimeData = {
|
export const chartTimeData: ChartTimeData = {
|
||||||
"1m": {
|
"1m": {
|
||||||
|
|||||||
Reference in New Issue
Block a user