mirror of
https://github.com/henrygd/beszel.git
synced 2025-12-17 18:56:17 +01:00
add prettier config and format files site files
This commit is contained in:
@@ -1,57 +1,64 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import i18n from "i18next"
|
||||
import { initReactI18next } from "react-i18next"
|
||||
|
||||
import en from '../locales/en/translation.json';
|
||||
import es from '../locales/es/translation.json';
|
||||
import fr from '../locales/fr/translation.json';
|
||||
import de from '../locales/de/translation.json';
|
||||
import ru from '../locales/ru/translation.json';
|
||||
import zhHans from '../locales/zh-CN/translation.json';
|
||||
import zhHant from '../locales/zh-HK/translation.json';
|
||||
import en from "../locales/en/translation.json"
|
||||
import es from "../locales/es/translation.json"
|
||||
import fr from "../locales/fr/translation.json"
|
||||
import de from "../locales/de/translation.json"
|
||||
import ru from "../locales/ru/translation.json"
|
||||
import zhHans from "../locales/zh-CN/translation.json"
|
||||
import zhHant from "../locales/zh-HK/translation.json"
|
||||
|
||||
// Custom language detector to use localStorage
|
||||
const languageDetector: any = {
|
||||
type: 'languageDetector',
|
||||
async: true,
|
||||
detect: (callback: (lng: string) => void) => {
|
||||
const savedLanguage = localStorage.getItem('i18nextLng');
|
||||
const fallbackLanguage = (()=>{
|
||||
switch (navigator.language) {
|
||||
case 'zh-CN': case 'zh-SG': case 'zh-MY': case 'zh': case 'zh-Hans':
|
||||
return 'zh-CN';
|
||||
case 'zh-HK': case 'zh-TW': case 'zh-MO': case 'zh-Hant':
|
||||
return 'zh-HK';
|
||||
default:
|
||||
return navigator.language;
|
||||
}
|
||||
})();
|
||||
callback(savedLanguage || fallbackLanguage);
|
||||
},
|
||||
init: () => {},
|
||||
cacheUserLanguage: (lng: string) => {
|
||||
localStorage.setItem('i18nextLng', lng);
|
||||
}
|
||||
};
|
||||
type: "languageDetector",
|
||||
async: true,
|
||||
detect: (callback: (lng: string) => void) => {
|
||||
const savedLanguage = localStorage.getItem("i18nextLng")
|
||||
const fallbackLanguage = (() => {
|
||||
switch (navigator.language) {
|
||||
case "zh-CN":
|
||||
case "zh-SG":
|
||||
case "zh-MY":
|
||||
case "zh":
|
||||
case "zh-Hans":
|
||||
return "zh-CN"
|
||||
case "zh-HK":
|
||||
case "zh-TW":
|
||||
case "zh-MO":
|
||||
case "zh-Hant":
|
||||
return "zh-HK"
|
||||
default:
|
||||
return navigator.language
|
||||
}
|
||||
})()
|
||||
callback(savedLanguage || fallbackLanguage)
|
||||
},
|
||||
init: () => {},
|
||||
cacheUserLanguage: (lng: string) => {
|
||||
localStorage.setItem("i18nextLng", lng)
|
||||
},
|
||||
}
|
||||
|
||||
i18n
|
||||
.use(languageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources: {
|
||||
en: { translation: en },
|
||||
es: { translation: es },
|
||||
fr: { translation: fr },
|
||||
de: { translation: de },
|
||||
ru: { translation: ru },
|
||||
// Chinese (Simplified)
|
||||
'zh-CN': { translation: zhHans },
|
||||
// Chinese (Traditional)
|
||||
'zh-HK': { translation: zhHant },
|
||||
},
|
||||
fallbackLng: 'en',
|
||||
interpolation: {
|
||||
escapeValue: false
|
||||
}
|
||||
});
|
||||
.use(languageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources: {
|
||||
en: { translation: en },
|
||||
es: { translation: es },
|
||||
fr: { translation: fr },
|
||||
de: { translation: de },
|
||||
ru: { translation: ru },
|
||||
// Chinese (Simplified)
|
||||
"zh-CN": { translation: zhHans },
|
||||
// Chinese (Traditional)
|
||||
"zh-HK": { translation: zhHant },
|
||||
},
|
||||
fallbackLng: "en",
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
})
|
||||
|
||||
export { i18n };
|
||||
export { i18n }
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
[
|
||||
{
|
||||
"lang": "en",
|
||||
"label": "English"
|
||||
},
|
||||
{
|
||||
"lang": "es",
|
||||
"label": "Español"
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"label": "Français"
|
||||
},
|
||||
{
|
||||
"lang": "de",
|
||||
"label": "Deutsch"
|
||||
},
|
||||
{
|
||||
"lang": "ru",
|
||||
"label": "Русский"
|
||||
},
|
||||
{
|
||||
"lang": "zh-CN",
|
||||
"label": "简体中文"
|
||||
},
|
||||
{
|
||||
"lang": "zh-HK",
|
||||
"label": "繁體中文"
|
||||
}
|
||||
]
|
||||
{
|
||||
"lang": "en",
|
||||
"label": "English"
|
||||
},
|
||||
{
|
||||
"lang": "es",
|
||||
"label": "Español"
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"label": "Français"
|
||||
},
|
||||
{
|
||||
"lang": "de",
|
||||
"label": "Deutsch"
|
||||
},
|
||||
{
|
||||
"lang": "ru",
|
||||
"label": "Русский"
|
||||
},
|
||||
{
|
||||
"lang": "zh-CN",
|
||||
"label": "简体中文"
|
||||
},
|
||||
{
|
||||
"lang": "zh-HK",
|
||||
"label": "繁體中文"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import PocketBase from 'pocketbase'
|
||||
import { atom, map, WritableAtom } from 'nanostores'
|
||||
import { AlertRecord, ChartTimes, SystemRecord, UserSettings } from '@/types'
|
||||
import PocketBase from "pocketbase"
|
||||
import { atom, map, WritableAtom } from "nanostores"
|
||||
import { AlertRecord, ChartTimes, SystemRecord, UserSettings } from "@/types"
|
||||
|
||||
/** PocketBase JS Client */
|
||||
export const pb = new PocketBase('/')
|
||||
export const pb = new PocketBase("/")
|
||||
|
||||
/** Store if user is authenticated */
|
||||
export const $authenticated = atom(pb.authStore.isValid)
|
||||
@@ -15,18 +15,18 @@ export const $systems = atom([] as SystemRecord[])
|
||||
export const $alerts = atom([] as AlertRecord[])
|
||||
|
||||
/** SSH public key */
|
||||
export const $publicKey = atom('')
|
||||
export const $publicKey = atom("")
|
||||
|
||||
/** Beszel hub version */
|
||||
export const $hubVersion = atom('')
|
||||
export const $hubVersion = atom("")
|
||||
|
||||
/** Chart time period */
|
||||
export const $chartTime = atom('1h') as WritableAtom<ChartTimes>
|
||||
export const $chartTime = atom("1h") as WritableAtom<ChartTimes>
|
||||
|
||||
/** User settings */
|
||||
export const $userSettings = map<UserSettings>({
|
||||
chartTime: '1h',
|
||||
emails: [pb.authStore.model?.email || ''],
|
||||
chartTime: "1h",
|
||||
emails: [pb.authStore.model?.email || ""],
|
||||
})
|
||||
// update local storage on change
|
||||
$userSettings.subscribe((value) => {
|
||||
@@ -35,7 +35,7 @@ $userSettings.subscribe((value) => {
|
||||
})
|
||||
|
||||
/** Container chart filter */
|
||||
export const $containerFilter = atom('')
|
||||
export const $containerFilter = atom("")
|
||||
|
||||
/** Fallback copy to clipboard dialog content */
|
||||
export const $copyContent = atom('')
|
||||
export const $copyContent = atom("")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
|
||||
// adapted from usehooks-ts/use-intersection-observer
|
||||
|
||||
@@ -72,7 +72,7 @@ type IntersectionReturn = {
|
||||
export function useIntersectionObserver({
|
||||
threshold = 0,
|
||||
root = null,
|
||||
rootMargin = '0%',
|
||||
rootMargin = "0%",
|
||||
freeze = true,
|
||||
initialIsIntersecting = false,
|
||||
onChange,
|
||||
@@ -84,7 +84,7 @@ export function useIntersectionObserver({
|
||||
entry: undefined,
|
||||
}))
|
||||
|
||||
const callbackRef = useRef<UseIntersectionObserverOptions['onChange']>()
|
||||
const callbackRef = useRef<UseIntersectionObserverOptions["onChange"]>()
|
||||
|
||||
callbackRef.current = onChange
|
||||
|
||||
@@ -95,7 +95,7 @@ export function useIntersectionObserver({
|
||||
if (!ref) return
|
||||
|
||||
// Ensure the browser supports the Intersection Observer API
|
||||
if (!('IntersectionObserver' in window)) return
|
||||
if (!("IntersectionObserver" in window)) return
|
||||
|
||||
// Skip if frozen
|
||||
if (frozen) return
|
||||
@@ -104,14 +104,11 @@ export function useIntersectionObserver({
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries: IntersectionObserverEntry[]): void => {
|
||||
const thresholds = Array.isArray(observer.thresholds)
|
||||
? observer.thresholds
|
||||
: [observer.thresholds]
|
||||
const thresholds = Array.isArray(observer.thresholds) ? observer.thresholds : [observer.thresholds]
|
||||
|
||||
entries.forEach((entry) => {
|
||||
const isIntersecting =
|
||||
entry.isIntersecting &&
|
||||
thresholds.some((threshold) => entry.intersectionRatio >= threshold)
|
||||
entry.isIntersecting && thresholds.some((threshold) => entry.intersectionRatio >= threshold)
|
||||
|
||||
setState({ isIntersecting, entry })
|
||||
|
||||
@@ -149,13 +146,7 @@ export function useIntersectionObserver({
|
||||
const prevRef = useRef<Element | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!ref &&
|
||||
state.entry?.target &&
|
||||
!freeze &&
|
||||
!frozen &&
|
||||
prevRef.current !== state.entry.target
|
||||
) {
|
||||
if (!ref && state.entry?.target && !freeze && !frozen && prevRef.current !== state.entry.target) {
|
||||
prevRef.current = state.entry.target
|
||||
setState({ isIntersecting: initialIsIntersecting, entry: undefined })
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { toast } from '@/components/ui/use-toast'
|
||||
import { type ClassValue, clsx } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { $alerts, $copyContent, $systems, $userSettings, pb } from './stores'
|
||||
import { AlertRecord, ChartTimeData, ChartTimes, SystemRecord } from '@/types'
|
||||
import { RecordModel, RecordSubscription } from 'pocketbase'
|
||||
import { WritableAtom } from 'nanostores'
|
||||
import { timeDay, timeHour } from 'd3-time'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { CpuIcon, HardDriveIcon, MemoryStickIcon, ServerIcon } from 'lucide-react'
|
||||
import { EthernetIcon, ThermometerIcon } from '@/components/ui/icons'
|
||||
import { toast } from "@/components/ui/use-toast"
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { $alerts, $copyContent, $systems, $userSettings, pb } from "./stores"
|
||||
import { AlertRecord, ChartTimeData, ChartTimes, SystemRecord } from "@/types"
|
||||
import { RecordModel, RecordSubscription } from "pocketbase"
|
||||
import { WritableAtom } from "nanostores"
|
||||
import { timeDay, timeHour } from "d3-time"
|
||||
import { useEffect, useState } from "react"
|
||||
import { CpuIcon, HardDriveIcon, MemoryStickIcon, ServerIcon } from "lucide-react"
|
||||
import { EthernetIcon, ThermometerIcon } from "@/components/ui/icons"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
@@ -21,7 +21,7 @@ export async function copyToClipboard(content: string) {
|
||||
await navigator.clipboard.writeText(content)
|
||||
toast({
|
||||
duration,
|
||||
description: 'Copied to clipboard',
|
||||
description: "Copied to clipboard",
|
||||
})
|
||||
} catch (e: any) {
|
||||
$copyContent.set(content)
|
||||
@@ -29,22 +29,22 @@ export async function copyToClipboard(content: string) {
|
||||
}
|
||||
|
||||
const verifyAuth = () => {
|
||||
pb.collection('users')
|
||||
pb.collection("users")
|
||||
.authRefresh()
|
||||
.catch(() => {
|
||||
pb.authStore.clear()
|
||||
toast({
|
||||
title: 'Failed to authenticate',
|
||||
description: 'Please log in again',
|
||||
variant: 'destructive',
|
||||
title: "Failed to authenticate",
|
||||
description: "Please log in again",
|
||||
variant: "destructive",
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const updateSystemList = async () => {
|
||||
const records = await pb
|
||||
.collection<SystemRecord>('systems')
|
||||
.getFullList({ sort: '+name', fields: 'id,name,host,info,status' })
|
||||
.collection<SystemRecord>("systems")
|
||||
.getFullList({ sort: "+name", fields: "id,name,host,info,status" })
|
||||
if (records.length) {
|
||||
$systems.set(records)
|
||||
} else {
|
||||
@@ -53,26 +53,26 @@ export const updateSystemList = async () => {
|
||||
}
|
||||
|
||||
export const updateAlerts = () => {
|
||||
pb.collection('alerts')
|
||||
.getFullList<AlertRecord>({ fields: 'id,name,system,value,min,triggered', sort: 'updated' })
|
||||
pb.collection("alerts")
|
||||
.getFullList<AlertRecord>({ fields: "id,name,system,value,min,triggered", sort: "updated" })
|
||||
.then((records) => {
|
||||
$alerts.set(records)
|
||||
})
|
||||
}
|
||||
|
||||
const hourWithMinutesFormatter = new Intl.DateTimeFormat(undefined, {
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
})
|
||||
export const hourWithMinutes = (timestamp: string) => {
|
||||
return hourWithMinutesFormatter.format(new Date(timestamp))
|
||||
}
|
||||
|
||||
const shortDateFormatter = new Intl.DateTimeFormat(undefined, {
|
||||
day: 'numeric',
|
||||
month: 'short',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
day: "numeric",
|
||||
month: "short",
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
})
|
||||
export const formatShortDate = (timestamp: string) => {
|
||||
// console.log('ts', timestamp)
|
||||
@@ -93,8 +93,8 @@ export const formatShortDate = (timestamp: string) => {
|
||||
// }
|
||||
|
||||
const dayFormatter = new Intl.DateTimeFormat(undefined, {
|
||||
day: 'numeric',
|
||||
month: 'short',
|
||||
day: "numeric",
|
||||
month: "short",
|
||||
// dateStyle: 'medium',
|
||||
})
|
||||
export const formatDay = (timestamp: string) => {
|
||||
@@ -106,19 +106,16 @@ export const updateFavicon = (newIcon: string) => {
|
||||
;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = `/static/${newIcon}`
|
||||
}
|
||||
|
||||
export const isAdmin = () => pb.authStore.model?.role === 'admin'
|
||||
export const isReadOnlyUser = () => pb.authStore.model?.role === 'readonly'
|
||||
export const isAdmin = () => pb.authStore.model?.role === "admin"
|
||||
export const isReadOnlyUser = () => pb.authStore.model?.role === "readonly"
|
||||
// export const isDefaultUser = () => pb.authStore.model?.role === 'user'
|
||||
|
||||
/** Update systems / alerts list when records change */
|
||||
export function updateRecordList<T extends RecordModel>(
|
||||
e: RecordSubscription<T>,
|
||||
$store: WritableAtom<T[]>
|
||||
) {
|
||||
export function updateRecordList<T extends RecordModel>(e: RecordSubscription<T>, $store: WritableAtom<T[]>) {
|
||||
const curRecords = $store.get()
|
||||
const newRecords = []
|
||||
// console.log('e', e)
|
||||
if (e.action === 'delete') {
|
||||
if (e.action === "delete") {
|
||||
for (const server of curRecords) {
|
||||
if (server.id !== e.record.id) {
|
||||
newRecords.push(server)
|
||||
@@ -143,51 +140,51 @@ export function updateRecordList<T extends RecordModel>(
|
||||
export function getPbTimestamp(timeString: ChartTimes, d?: Date) {
|
||||
d ||= chartTimeData[timeString].getOffset(new Date())
|
||||
const year = d.getUTCFullYear()
|
||||
const month = String(d.getUTCMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getUTCDate()).padStart(2, '0')
|
||||
const hours = String(d.getUTCHours()).padStart(2, '0')
|
||||
const minutes = String(d.getUTCMinutes()).padStart(2, '0')
|
||||
const seconds = String(d.getUTCSeconds()).padStart(2, '0')
|
||||
const month = String(d.getUTCMonth() + 1).padStart(2, "0")
|
||||
const day = String(d.getUTCDate()).padStart(2, "0")
|
||||
const hours = String(d.getUTCHours()).padStart(2, "0")
|
||||
const minutes = String(d.getUTCMinutes()).padStart(2, "0")
|
||||
const seconds = String(d.getUTCSeconds()).padStart(2, "0")
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
export const chartTimeData: ChartTimeData = {
|
||||
'1h': {
|
||||
type: '1m',
|
||||
"1h": {
|
||||
type: "1m",
|
||||
expectedInterval: 60_000,
|
||||
label: '1 hour',
|
||||
label: "1 hour",
|
||||
// ticks: 12,
|
||||
format: (timestamp: string) => hourWithMinutes(timestamp),
|
||||
getOffset: (endTime: Date) => timeHour.offset(endTime, -1),
|
||||
},
|
||||
'12h': {
|
||||
type: '10m',
|
||||
"12h": {
|
||||
type: "10m",
|
||||
expectedInterval: 60_000 * 10,
|
||||
label: '12 hours',
|
||||
label: "12 hours",
|
||||
ticks: 12,
|
||||
format: (timestamp: string) => hourWithMinutes(timestamp),
|
||||
getOffset: (endTime: Date) => timeHour.offset(endTime, -12),
|
||||
},
|
||||
'24h': {
|
||||
type: '20m',
|
||||
"24h": {
|
||||
type: "20m",
|
||||
expectedInterval: 60_000 * 20,
|
||||
label: '24 hours',
|
||||
label: "24 hours",
|
||||
format: (timestamp: string) => hourWithMinutes(timestamp),
|
||||
getOffset: (endTime: Date) => timeHour.offset(endTime, -24),
|
||||
},
|
||||
'1w': {
|
||||
type: '120m',
|
||||
"1w": {
|
||||
type: "120m",
|
||||
expectedInterval: 60_000 * 120,
|
||||
label: '1 week',
|
||||
label: "1 week",
|
||||
ticks: 7,
|
||||
format: (timestamp: string) => formatDay(timestamp),
|
||||
getOffset: (endTime: Date) => timeDay.offset(endTime, -7),
|
||||
},
|
||||
'30d': {
|
||||
type: '480m',
|
||||
"30d": {
|
||||
type: "480m",
|
||||
expectedInterval: 60_000 * 480,
|
||||
label: '30 days',
|
||||
label: "30 days",
|
||||
ticks: 30,
|
||||
format: (timestamp: string) => formatDay(timestamp),
|
||||
getOffset: (endTime: Date) => timeDay.offset(endTime, -30),
|
||||
@@ -202,8 +199,8 @@ export function useYAxisWidth() {
|
||||
function updateYAxisWidth(str: string) {
|
||||
if (str.length > maxChars) {
|
||||
maxChars = str.length
|
||||
const div = document.createElement('div')
|
||||
div.className = 'text-xs tabular-nums tracking-tighter table sr-only'
|
||||
const div = document.createElement("div")
|
||||
div.className = "text-xs tabular-nums tracking-tighter table sr-only"
|
||||
div.innerHTML = str
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => {
|
||||
@@ -263,20 +260,18 @@ export const useLocalStorage = (key: string, defaultValue: any) => {
|
||||
|
||||
export async function updateUserSettings() {
|
||||
try {
|
||||
const req = await pb.collection('user_settings').getFirstListItem('', { fields: 'settings' })
|
||||
const req = await pb.collection("user_settings").getFirstListItem("", { fields: "settings" })
|
||||
$userSettings.set(req.settings)
|
||||
return
|
||||
} catch (e) {
|
||||
console.log('get settings', e)
|
||||
console.log("get settings", e)
|
||||
}
|
||||
// create user settings if error fetching existing
|
||||
try {
|
||||
const createdSettings = await pb
|
||||
.collection('user_settings')
|
||||
.create({ user: pb.authStore.model!.id })
|
||||
const createdSettings = await pb.collection("user_settings").create({ user: pb.authStore.model!.id })
|
||||
$userSettings.set(createdSettings.settings)
|
||||
} catch (e) {
|
||||
console.log('create settings', e)
|
||||
console.log("create settings", e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,51 +285,51 @@ export const getSizeAndUnit = (n: number, isGigabytes = true) => {
|
||||
const sizeInGB = isGigabytes ? n : n / 1_000
|
||||
|
||||
if (sizeInGB >= 1_000) {
|
||||
return { v: sizeInGB / 1_000, u: ' TB' }
|
||||
return { v: sizeInGB / 1_000, u: " TB" }
|
||||
} else if (sizeInGB >= 1) {
|
||||
return { v: sizeInGB, u: ' GB' }
|
||||
return { v: sizeInGB, u: " GB" }
|
||||
}
|
||||
return { v: n, u: ' MB' }
|
||||
return { v: n, u: " MB" }
|
||||
}
|
||||
|
||||
export const chartMargin = { top: 12 }
|
||||
|
||||
export const alertInfo = {
|
||||
Status: {
|
||||
name: 'alerts.info.status',
|
||||
unit: '',
|
||||
name: "alerts.info.status",
|
||||
unit: "",
|
||||
icon: ServerIcon,
|
||||
desc: 'alerts.info.status_des',
|
||||
desc: "alerts.info.status_des",
|
||||
single: true,
|
||||
},
|
||||
CPU: {
|
||||
name: 'alerts.info.cpu_usage',
|
||||
unit: '%',
|
||||
name: "alerts.info.cpu_usage",
|
||||
unit: "%",
|
||||
icon: CpuIcon,
|
||||
desc: 'alerts.info.cpu_usage_des',
|
||||
desc: "alerts.info.cpu_usage_des",
|
||||
},
|
||||
Memory: {
|
||||
name: 'alerts.info.memory_usage',
|
||||
unit: '%',
|
||||
name: "alerts.info.memory_usage",
|
||||
unit: "%",
|
||||
icon: MemoryStickIcon,
|
||||
desc: 'alerts.info.memory_usage_des',
|
||||
desc: "alerts.info.memory_usage_des",
|
||||
},
|
||||
Disk: {
|
||||
name: 'alerts.info.disk_usage',
|
||||
unit: '%',
|
||||
name: "alerts.info.disk_usage",
|
||||
unit: "%",
|
||||
icon: HardDriveIcon,
|
||||
desc: 'alerts.info.disk_usage_des',
|
||||
desc: "alerts.info.disk_usage_des",
|
||||
},
|
||||
Bandwidth: {
|
||||
name: 'alerts.info.bandwidth',
|
||||
unit: ' MB/s',
|
||||
name: "alerts.info.bandwidth",
|
||||
unit: " MB/s",
|
||||
icon: EthernetIcon,
|
||||
desc: 'alerts.info.bandwidth_des',
|
||||
desc: "alerts.info.bandwidth_des",
|
||||
},
|
||||
Temperature: {
|
||||
name: 'alerts.info.temperature',
|
||||
unit: '°C',
|
||||
name: "alerts.info.temperature",
|
||||
unit: "°C",
|
||||
icon: ThermometerIcon,
|
||||
desc: 'alerts.info.temperature_des',
|
||||
desc: "alerts.info.temperature_des",
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user