Compare commits

..
Author SHA1 Message Date
shamoon 8caed1e797 Fix units 2025-01-26 23:37:16 -08:00
shamoon 2fdd8df9f9 Correct units 2025-01-26 23:35:40 -08:00
shamoon d2cb64c7a3 Use top-level dataset info 2025-01-26 23:26:22 -08:00
shamoon b5eae499ec Update version.jsx 2025-01-26 16:34:23 -08:00
shamoon 546d699799 Feature: use datasets for truenas pools 2025-01-26 00:16:00 -08:00
14 changed files with 2458 additions and 2772 deletions

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
{
"presets": ["next/babel"]
}
+1 -1
View File
@@ -145,7 +145,7 @@ jobs:
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
# https://github.com/docker/setup-qemu-action#about # https://github.com/docker/setup-qemu-action#about
# platforms: linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6 # platforms: linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
cache-from: type=local,src=/tmp/.buildx-cache cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
+5 -6
View File
@@ -1,7 +1,7 @@
# syntax = docker/dockerfile:latest # syntax = docker/dockerfile:latest
# Install dependencies only when needed # Install dependencies only when needed
FROM docker.io/node:22-alpine AS deps FROM docker.io/node:18-alpine AS deps
WORKDIR /app WORKDIR /app
@@ -17,7 +17,7 @@ RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm f
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm install -r --offline RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm install -r --offline
# Rebuild the source code only when needed # Rebuild the source code only when needed
FROM docker.io/node:22-alpine AS builder FROM docker.io/node:18-alpine AS builder
WORKDIR /app WORKDIR /app
ARG BUILDTIME ARG BUILDTIME
@@ -33,7 +33,7 @@ RUN npm run telemetry \
&& NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build && NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
# Production image, copy all the files and run next # Production image, copy all the files and run next
FROM docker.io/node:22-alpine AS runner FROM docker.io/node:18-alpine AS runner
LABEL org.opencontainers.image.title "Homepage" LABEL org.opencontainers.image.title "Homepage"
LABEL org.opencontainers.image.description "A self-hosted services landing page, with docker and service integrations." LABEL org.opencontainers.image.description "A self-hosted services landing page, with docker and service integrations."
LABEL org.opencontainers.image.url="https://github.com/gethomepage/homepage" LABEL org.opencontainers.image.url="https://github.com/gethomepage/homepage"
@@ -41,7 +41,7 @@ LABEL org.opencontainers.image.documentation='https://github.com/gethomepage/hom
LABEL org.opencontainers.image.source='https://github.com/gethomepage/homepage' LABEL org.opencontainers.image.source='https://github.com/gethomepage/homepage'
LABEL org.opencontainers.image.licenses='Apache-2.0' LABEL org.opencontainers.image.licenses='Apache-2.0'
ENV NODE_ENV=production ENV NODE_ENV production
WORKDIR /app WORKDIR /app
@@ -56,8 +56,7 @@ COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/
RUN apk add --no-cache su-exec RUN apk add --no-cache su-exec
ENV HOSTNAME=:: ENV PORT 3000
ENV PORT=3000
EXPOSE $PORT EXPOSE $PORT
HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \ HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \
+1 -1
View File
@@ -38,7 +38,7 @@ With features like quick search, bookmarks, weather support, a wide range of int
- **Fast** - The site is statically generated at build time for instant load times. - **Fast** - The site is statically generated at build time for instant load times.
- **Secure** - All API requests to backend services are proxied, keeping your API keys hidden. Constantly reviewed for security by the community. - **Secure** - All API requests to backend services are proxied, keeping your API keys hidden. Constantly reviewed for security by the community.
- **For Everyone** - Images built for AMD64, ARM64. - **For Everyone** - Images built for AMD64, ARM64, ARMv7, and ARMv6.
- **Full i18n** - Support for over 40 languages. - **Full i18n** - Support for over 40 languages.
- **Service & Web Bookmarks** - Add custom links to the homepage. - **Service & Web Bookmarks** - Add custom links to the homepage.
- **Docker Integration** - Container status and stats. Automatic service discovery via labels. - **Docker Integration** - Container status and stats. Automatic service discovery via labels.
+842 -1482
View File
File diff suppressed because it is too large. Load diff
+11 -11
View File
@@ -10,7 +10,7 @@
"telemetry": "next telemetry disable" "telemetry": "next telemetry disable"
}, },
"dependencies": { "dependencies": {
"@headlessui/react": "^1.7.19", "@headlessui/react": "^1.7.18",
"@kubernetes/client-node": "^0.17.1", "@kubernetes/client-node": "^0.17.1",
"cal-parser": "^1.0.2", "cal-parser": "^1.0.2",
"classnames": "^2.5.1", "classnames": "^2.5.1",
@@ -24,22 +24,22 @@
"luxon": "^3.5.0", "luxon": "^3.5.0",
"memory-cache": "^0.2.0", "memory-cache": "^0.2.0",
"minecraft-ping-js": "^1.0.2", "minecraft-ping-js": "^1.0.2",
"next": "^15.0.3", "next": "^12.3.4",
"next-i18next": "^12.1.0", "next-i18next": "^12.1.0",
"ping": "^0.4.4", "ping": "^0.4.4",
"pretty-bytes": "^6.1.1", "pretty-bytes": "^6.1.1",
"raw-body": "^3.0.0", "raw-body": "^3.0.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.2.0",
"react-i18next": "^11.18.6", "react-i18next": "^11.18.6",
"react-icons": "^5.4.0", "react-icons": "^5.4.0",
"recharts": "^2.12.7", "recharts": "^2.12.6",
"rrule": "^2.8.1", "rrule": "^2.8.1",
"swr": "^1.3.0", "swr": "^1.3.0",
"systeminformation": "^5.24.3", "systeminformation": "^5.24.3",
"tough-cookie": "^4.1.4", "tough-cookie": "^4.1.3",
"urbackup-server-api": "^0.8.9", "urbackup-server-api": "^0.52.1",
"winston": "^3.13.0", "winston": "^3.11.0",
"xml-js": "^1.6.11" "xml-js": "^1.6.11"
}, },
"devDependencies": { "devDependencies": {
@@ -47,15 +47,15 @@
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"eslint": "^8.57.1", "eslint": "^8.57.1",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-next": "^14.2.4", "eslint-config-next": "^14.2.3",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.3", "eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.48", "postcss": "^8.4.47",
"prettier": "^3.3.2", "prettier": "^3.2.5",
"tailwind-scrollbar": "^3.0.5", "tailwind-scrollbar": "^3.0.5",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"typescript": "^5.6.3" "typescript": "^5.6.3"
+1490 -1172
View File
File diff suppressed because it is too large. Load diff
+48 -48
View File
@@ -64,7 +64,7 @@
"up": "Up", "up": "Up",
"down": "INACTIF", "down": "INACTIF",
"wait": "Veuillez patienter", "wait": "Veuillez patienter",
"empty_data": "Statut du sous-système inconnu" "empty_data": "Statut sous-système inconnu"
}, },
"docker": { "docker": {
"rx": "Rx", "rx": "Rx",
@@ -84,17 +84,17 @@
}, },
"ping": { "ping": {
"error": "Erreur", "error": "Erreur",
"ping": "Latence", "ping": "Ping",
"down": "Bas", "down": "Down",
"up": "Haut", "up": "Up",
"not_available": "Non disponible" "not_available": "Non disponible"
}, },
"siteMonitor": { "siteMonitor": {
"http_status": "Statut HTTP", "http_status": "Statut HTTP",
"error": "Erreur", "error": "Erreur",
"response": "Réponse", "response": "Réponse",
"down": "Bas", "down": "Down",
"up": "Haut", "up": "Up",
"not_available": "Non disponible" "not_available": "Non disponible"
}, },
"emby": { "emby": {
@@ -144,8 +144,8 @@
"uptime": "Démarré depuis", "uptime": "Démarré depuis",
"maxDown": "Max. Bas", "maxDown": "Max. Bas",
"maxUp": "Max. Haut", "maxUp": "Max. Haut",
"down": "Bas", "down": "Down",
"up": "Haut", "up": "Up",
"received": "Reçu", "received": "Reçu",
"sent": "Envoyé", "sent": "Envoyé",
"externalIPAddress": "IP externe" "externalIPAddress": "IP externe"
@@ -173,11 +173,11 @@
"plex_connection_error": "Vérifier la connexion à Plex" "plex_connection_error": "Vérifier la connexion à Plex"
}, },
"omada": { "omada": {
"connectedAp": "APs connectées", "connectedAp": "AP connectés",
"activeUser": "Périphériques actifs", "activeUser": "Équipts actifs",
"alerts": "Alertes", "alerts": "Alertes",
"connectedGateway": "Passerelles connectées", "connectedGateway": "Passerelles connectées",
"connectedSwitches": "Switchs connectés" "connectedSwitches": "Switches connectés"
}, },
"nzbget": { "nzbget": {
"rate": "Débit", "rate": "Débit",
@@ -213,11 +213,11 @@
"seed": "Seed" "seed": "Seed"
}, },
"qnap": { "qnap": {
"cpuUsage": "Utilisation CPU", "cpuUsage": "Cpu",
"memUsage": "Utilisation MÉM", "memUsage": "Mém",
"systemTempC": "Temp. système", "systemTempC": "Temp",
"poolUsage": "Utilisation de la pool", "poolUsage": "Pool",
"volumeUsage": "Utilisation du volume", "volumeUsage": "Volume",
"invalid": "Invalide" "invalid": "Invalide"
}, },
"deluge": { "deluge": {
@@ -302,7 +302,7 @@
"speedtest": { "speedtest": {
"upload": "Envoi", "upload": "Envoi",
"download": "Récep.", "download": "Récep.",
"ping": "Latence" "ping": "Ping"
}, },
"portainer": { "portainer": {
"running": "Démarré", "running": "Démarré",
@@ -349,8 +349,8 @@
"tdarr": { "tdarr": {
"queue": "En attente", "queue": "En attente",
"processed": "Traité", "processed": "Traité",
"errored": "Erroné", "errored": "En erreur",
"saved": "Enregistré" "saved": "Libéré"
}, },
"traefik": { "traefik": {
"routers": "Routeurs", "routers": "Routeurs",
@@ -376,7 +376,7 @@
"gotify": { "gotify": {
"apps": "Applis", "apps": "Applis",
"clients": "Clients", "clients": "Clients",
"messages": "Messages" "messages": "Msg"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexeur", "enableIndexers": "Indexeur",
@@ -387,7 +387,7 @@
}, },
"jackett": { "jackett": {
"configured": "Configuré", "configured": "Configuré",
"errored": "Erroné" "errored": "En erreur"
}, },
"strelaysrv": { "strelaysrv": {
"numActiveSessions": "Sessions", "numActiveSessions": "Sessions",
@@ -461,10 +461,10 @@
"0-night": "Ciel clair", "0-night": "Ciel clair",
"1-day": "Principalement ensoleillé", "1-day": "Principalement ensoleillé",
"1-night": "Principalement clair", "1-night": "Principalement clair",
"2-day": "Partiellement nuageux", "2-day": "Partiellement couvert",
"2-night": "Partiellement nuageux", "2-night": "Partiellement couvert",
"3-day": "Nuageux", "3-day": "Couvert",
"3-night": "Nuageux", "3-night": "Couvert",
"45-day": "Brumeux", "45-day": "Brumeux",
"45-night": "Brumeux", "45-night": "Brumeux",
"48-day": "Brumeux", "48-day": "Brumeux",
@@ -489,8 +489,8 @@
"66-night": "Pluie verglaçante", "66-night": "Pluie verglaçante",
"67-day": "Pluie verglaçante", "67-day": "Pluie verglaçante",
"67-night": "Pluie verglaçante", "67-night": "Pluie verglaçante",
"71-day": "Légères chutes de neige", "71-day": "Neige légère",
"71-night": "Légères chutes de neige", "71-night": "Neige légère",
"73-day": "Neige", "73-day": "Neige",
"73-night": "Neige", "73-night": "Neige",
"75-day": "Neige abondante", "75-day": "Neige abondante",
@@ -521,15 +521,15 @@
"up_to_date": "À jour", "up_to_date": "À jour",
"child_bridges": "Child Bridges", "child_bridges": "Child Bridges",
"child_bridges_status": "{{ok}}/{{total}}", "child_bridges_status": "{{ok}}/{{total}}",
"up": "Haut", "up": "Up",
"pending": "En attente", "pending": "En attente",
"down": "Bas" "down": "Down"
}, },
"healthchecks": { "healthchecks": {
"new": "Nouveau", "new": "Nouveau",
"up": "Haut", "up": "Up",
"grace": "En Période de Grâce", "grace": "En Période de Grâce",
"down": "Bas", "down": "Down",
"paused": "En Pause", "paused": "En Pause",
"status": "Statut", "status": "Statut",
"last_ping": "Dernier Ping", "last_ping": "Dernier Ping",
@@ -632,8 +632,8 @@
}, },
"octoprint": { "octoprint": {
"printer_state": "Statut", "printer_state": "Statut",
"temp_tool": "Temp. de l'outil", "temp_tool": "Tool T°",
"temp_bed": "Temp. du lit", "temp_bed": "Bed T°",
"job_completion": "Achèvement" "job_completion": "Achèvement"
}, },
"cloudflared": { "cloudflared": {
@@ -644,8 +644,8 @@
"load": "Charge moy.", "load": "Charge moy.",
"memory": "Util. Mém.", "memory": "Util. Mém.",
"wanStatus": "Statut WAN", "wanStatus": "Statut WAN",
"up": "Haut", "up": "Up",
"down": "Bas", "down": "Down",
"temp": "T°", "temp": "T°",
"disk": "Util. Disque", "disk": "Util. Disque",
"wanIP": "IP WAN" "wanIP": "IP WAN"
@@ -754,9 +754,9 @@
"booksDuration": "Durée" "booksDuration": "Durée"
}, },
"homeassistant": { "homeassistant": {
"people_home": "Personne à la maison", "people_home": "People Home",
"lights_on": "Lumières allumées", "lights_on": "Lumières allumées",
"switches_on": "Interrupteurs allumés" "switches_on": "Commutateur On"
}, },
"whatsupdocker": { "whatsupdocker": {
"monitoring": "Conteneurs", "monitoring": "Conteneurs",
@@ -800,8 +800,8 @@
"currentPlayers": "Joueurs actuels", "currentPlayers": "Joueurs actuels",
"players": "Joueurs", "players": "Joueurs",
"maxPlayers": "Joueurs max", "maxPlayers": "Joueurs max",
"bots": "Robots", "bots": "Bots",
"ping": "Latence" "ping": "Ping"
}, },
"urbackup": { "urbackup": {
"ok": "Ok", "ok": "Ok",
@@ -826,8 +826,8 @@
"openwrt": { "openwrt": {
"uptime": "Démarré depuis", "uptime": "Démarré depuis",
"cpuLoad": "Charge moyenne CPU (5 min)", "cpuLoad": "Charge moyenne CPU (5 min)",
"up": "Haut", "up": "Up",
"down": "Bas", "down": "Down",
"bytesTx": "Transmis", "bytesTx": "Transmis",
"bytesRx": "Reçu" "bytesRx": "Reçu"
}, },
@@ -840,9 +840,9 @@
"sitesDown": "Hors ligne", "sitesDown": "Hors ligne",
"paused": "En Pause", "paused": "En Pause",
"notyetchecked": "Non vérifié", "notyetchecked": "Non vérifié",
"up": "Haut", "up": "Up",
"seemsdown": "Semble hors ligne", "seemsdown": "Semble hors ligne",
"down": "Bas", "down": "Down",
"unknown": "Inconnu" "unknown": "Inconnu"
}, },
"calendar": { "calendar": {
@@ -912,7 +912,7 @@
}, },
"crowdsec": { "crowdsec": {
"alerts": "Alertes", "alerts": "Alertes",
"bans": "Bannissements" "bans": "Exclusions"
}, },
"wgeasy": { "wgeasy": {
"connected": "Connecté", "connected": "Connecté",
@@ -927,12 +927,12 @@
"banned": "Banni" "banned": "Banni"
}, },
"myspeed": { "myspeed": {
"ping": "Latence", "ping": "Ping",
"download": "Récep.", "download": "Récep.",
"upload": "Envoi" "upload": "Envoi"
}, },
"stocks": { "stocks": {
"stocks": "Stocks", "stocks": "Actions",
"loading": "Chargement", "loading": "Chargement",
"open": "Ouvert - Marché américain", "open": "Ouvert - Marché américain",
"closed": "Fermé - marché américain", "closed": "Fermé - marché américain",
@@ -981,8 +981,8 @@
"beszel": { "beszel": {
"name": "Nom", "name": "Nom",
"systems": "Systèmes", "systems": "Systèmes",
"up": "Haut", "up": "Up",
"down": "Bas", "down": "Down",
"paused": "En Pause", "paused": "En Pause",
"pending": "En attente", "pending": "En attente",
"status": "Statut", "status": "Statut",
+16 -16
View File
@@ -311,13 +311,13 @@
}, },
"suwayomi": { "suwayomi": {
"download": "下载", "download": "下载",
"nondownload": "未下载", "nondownload": "Non-Downloaded",
"read": "已读", "read": "已读",
"unread": "未读", "unread": "未读",
"downloadedread": "已下载 & 已读", "downloadedread": "Downloaded & Read",
"downloadedunread": "已下载 & 未读", "downloadedunread": "Downloaded & Unread",
"nondownloadedread": "未下载 & 已读", "nondownloadedread": "Non-Downloaded & Read",
"nondownloadedunread": "未下载 & 未读" "nondownloadedunread": "Non-Downloaded & Unread"
}, },
"tailscale": { "tailscale": {
"address": "地址", "address": "地址",
@@ -980,7 +980,7 @@
}, },
"beszel": { "beszel": {
"name": "Name", "name": "Name",
"systems": "系统", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down", "down": "Down",
"paused": "暂停", "paused": "暂停",
@@ -989,26 +989,26 @@
"updated": "已升级", "updated": "已升级",
"cpu": "CPU", "cpu": "CPU",
"memory": "内存", "memory": "内存",
"disk": "磁盘", "disk": "Disk",
"network": "网络" "network": "NET"
}, },
"argocd": { "argocd": {
"apps": "应用程序", "apps": "应用程序",
"synced": "已同步", "synced": "Synced",
"outOfSync": "未同步", "outOfSync": "Out Of Sync",
"healthy": "健康", "healthy": "健康",
"degraded": "已降级", "degraded": "Degraded",
"progressing": "进行中", "progressing": "Progressing",
"missing": "丢失", "missing": "丢失",
"suspended": "已停用" "suspended": "Suspended"
}, },
"spoolman": { "spoolman": {
"loading": "正在加载" "loading": "正在加载"
}, },
"gitlab": { "gitlab": {
"groups": "群组", "groups": "Groups",
"issues": "问题", "issues": "问题",
"merges": "合并请求", "merges": "Merge Requests",
"projects": "项目" "projects": "Projects"
} }
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import { useContext } from "react"; import { useContext } from "react";
import Image from "next/image"; import Image from "next/future/image";
import { SettingsContext } from "utils/contexts/settings"; import { SettingsContext } from "utils/contexts/settings";
import { ThemeContext } from "utils/contexts/theme"; import { ThemeContext } from "utils/contexts/theme";
+1 -1
View File
@@ -44,7 +44,7 @@ export default function Version() {
</a> </a>
)} )}
</span> </span>
{!validate(version) {version === "main" || version === "dev" || version === "nightly" || !validate(version)
? null ? null
: releaseData && : releaseData &&
latestRelease && latestRelease &&
+23 -15
View File
@@ -12,14 +12,15 @@ export default function Component({ service }) {
const { data: alertData, error: alertError } = useWidgetAPI(widget, "alerts"); const { data: alertData, error: alertError } = useWidgetAPI(widget, "alerts");
const { data: statusData, error: statusError } = useWidgetAPI(widget, "status"); const { data: statusData, error: statusError } = useWidgetAPI(widget, "status");
const { data: poolsData, error: poolsError } = useWidgetAPI(widget, "pools"); const { data: poolsData, error: poolsError } = useWidgetAPI(widget, widget?.enablePools ? "pools" : null);
const { data: datasetData, error: datasetError } = useWidgetAPI(widget, widget?.enablePools ? "dataset" : null);
if (alertError || statusError || poolsError) { if (alertError || statusError || poolsError) {
const finalError = alertError ?? statusError ?? poolsError; const finalError = alertError ?? statusError ?? poolsError ?? datasetError;
return <Container service={service} error={finalError} />; return <Container service={service} error={finalError} />;
} }
if (!alertData || !statusData) { if (!alertData || !statusData || (widget?.enablePools && (!poolsData || !datasetData))) {
return ( return (
<Container service={service}> <Container service={service}>
<Block label="truenas.load" /> <Block label="truenas.load" />
@@ -29,7 +30,22 @@ export default function Component({ service }) {
); );
} }
const enablePools = widget?.enablePools && Array.isArray(poolsData) && poolsData.length > 0; let pools = [];
const showPools =
Array.isArray(poolsData) && poolsData.length > 0 && Array.isArray(datasetData) && datasetData.length > 0;
if (showPools) {
pools = poolsData.map((pool) => {
const dataset = datasetData.find((d) => d.pool === pool.name && d.name === pool.name);
return {
id: pool.id,
name: pool.name,
healthy: pool.healthy,
allocated: dataset?.used.parsed ?? 0,
free: dataset?.available.parsed ?? 0,
};
});
}
return ( return (
<> <>
@@ -38,19 +54,11 @@ export default function Component({ service }) {
<Block label="truenas.uptime" value={t("common.duration", { value: statusData.uptime_seconds })} /> <Block label="truenas.uptime" value={t("common.duration", { value: statusData.uptime_seconds })} />
<Block label="truenas.alerts" value={t("common.number", { value: alertData.pending })} /> <Block label="truenas.alerts" value={t("common.number", { value: alertData.pending })} />
</Container> </Container>
{enablePools && {showPools &&
poolsData pools
.sort((a, b) => a.name.localeCompare(b.name)) .sort((a, b) => a.name.localeCompare(b.name))
.map((pool) => ( .map((pool) => (
<Pool <Pool key={pool.id} name={pool.name} healthy={pool.healthy} allocated={pool.allocated} free={pool.free} />
key={pool.id}
name={pool.name}
healthy={pool.healthy}
allocated={pool.allocated}
free={pool.free}
data={pool.data}
nasType={widget?.nasType ?? "scale"}
/>
))} ))}
</> </>
); );
+13 -15
View File
@@ -1,19 +1,9 @@
import classNames from "classnames"; import classNames from "classnames";
import prettyBytes from "pretty-bytes"; import { useTranslation } from "next-i18next";
export default function Pool({ name, free, allocated, healthy, data, nasType }) { export default function Pool({ name, free, allocated, healthy }) {
let total = 0; const { t } = useTranslation();
if (nasType === "scale") { const usedPercent = Math.round((allocated / (free + allocated)) * 100);
total = free + allocated;
} else {
allocated = 0; // eslint-disable-line no-param-reassign
for (let i = 0; i < data.length; i += 1) {
total += data[i].stats.size;
allocated += data[i].stats.allocated; // eslint-disable-line no-param-reassign
}
}
const usedPercent = Math.round((allocated / total) * 100);
const statusColor = healthy ? "bg-green-500" : "bg-yellow-500"; const statusColor = healthy ? "bg-green-500" : "bg-yellow-500";
return ( return (
@@ -32,7 +22,15 @@ export default function Pool({ name, free, allocated, healthy, data, nasType })
</div> </div>
<div className="self-center text-xs flex justify-end mr-1.5 pl-1 z-10 text-ellipsis overflow-hidden whitespace-nowrap"> <div className="self-center text-xs flex justify-end mr-1.5 pl-1 z-10 text-ellipsis overflow-hidden whitespace-nowrap">
<span> <span>
{prettyBytes(allocated)} / {prettyBytes(total)} {`${t("common.bytes", {
value: allocated,
maximumFractionDigits: 1,
binary: true,
})} / ${t("common.bytes", {
value: free + allocated,
maximumFractionDigits: 1,
binary: true,
})}`}
</span> </span>
<span className="pl-2">({usedPercent}%)</span> <span className="pl-2">({usedPercent}%)</span>
</div> </div>
+3 -3
View File
@@ -23,11 +23,11 @@ const widget = {
id: entry.name, id: entry.name,
name: entry.name, name: entry.name,
healthy: entry.healthy, healthy: entry.healthy,
allocated: entry.allocated,
free: entry.free,
data: entry.topology?.data ?? [],
})), })),
}, },
dataset: {
endpoint: "pool/dataset",
},
}, },
}; };