Compare commits

...

11 Commits

Author SHA1 Message Date
shamoon
4d8a587d8b Update docker-entrypoint.sh 2025-07-16 09:44:23 -07:00
shamoon
d0165326a6 Tweak: Improve ownership check and chown handling for .next dir (#5513) 2025-07-15 06:56:46 -07:00
Oriano de Stefani
dba3a1f893 Enhancement: support for new grafana alerting api (#5476)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-07-12 08:36:13 -07:00
shamoon
f5ecd6d787 Fix: fix glances info when cpu = 0 (#5506) 2025-07-11 19:47:31 -07:00
Đức
1d990ef7c7 Fix: increase color popover z-index (#5489) 2025-07-07 09:29:48 -07:00
dependabot[bot]
767e7c58b4 Chore(deps): Bump react-i18next from 11.18.6 to 15.5.3 (#5470)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 11:58:43 -07:00
dependabot[bot]
c393982e84 Chore(deps-dev): Bump eslint-plugin-prettier from 5.2.6 to 5.5.1 (#5471)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 17:26:59 +00:00
dependabot[bot]
927b943fa4 Chore(deps-dev): Bump prettier from 3.5.3 to 3.6.2 (#5468)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 16:59:47 +00:00
dependabot[bot]
50f6d5f0e7 Chore(deps): Bump systeminformation from 5.25.11 to 5.27.7 (#5469)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 16:36:48 +00:00
dependabot[bot]
0482bf7b17 Chore(deps-dev): Bump eslint-plugin-react-hooks from 5.1.0 to 5.2.0 (#5467)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 09:25:23 -07:00
AdamWHY2K
e215e7d70e Enhancement: sort qBittorrent leechProgress (#5456) 2025-06-28 14:23:02 -07:00
10 changed files with 167 additions and 72 deletions

View File

@@ -17,13 +17,15 @@ if [ -e /app/config ]; then
CURRENT_UID=$(stat -c %u /app/config)
CURRENT_GID=$(stat -c %g /app/config)
if [ "$CURRENT_UID" -ne "$PUID" ] || [ "$CURRENT_GID" -ne "$PGID" ]; then
echo "Fixing ownership of /app/config"
if ! chown -R "$PUID:$PGID" /app/config 2>/dev/null; then
echo "Warning: Could not chown /app/config; continuing anyway"
if [ "$CURRENT_UID" -eq "$PUID" ] && [ "$CURRENT_GID" -eq "$PGID" ]; then
echo "/app/config already owned by correct UID/GID, skipping chown"
if ! [ -w /app/config ]; then
echo "Warning: /app/config is not writable by UID $PUID — this can happen with bind mounts"
echo "Hint: Run 'chmod -R u+rwX /path/to/config' on the host"
fi
else
echo "/app/config already owned by correct UID/GID, skipping chown"
echo "Fixing ownership of /app/config"
chown -R "$PUID:$PGID" /app/config 2>/dev/null || echo "Warning: Could not chown /app/config"
fi
else
echo "/app/config does not exist; skipping ownership check"
@@ -44,9 +46,15 @@ fi
if [ -d /app/.next ]; then
CURRENT_UID=$(stat -c %u /app/.next)
if [ "$CURRENT_UID" -ne "$PUID" ]; then
CURRENT_GID=$(stat -c %g /app/.next)
if [ "$PUID" -ne 0 ] && ([ "$CURRENT_UID" -ne "$PUID" ] || [ "$CURRENT_GID" -ne "$PGID" ]); then
echo "Fixing ownership of /app/.next"
chown -R "$PUID:$PGID" /app/.next || echo "Warning: Could not chown /app/.next"
if ! chown -R "$PUID:$PGID" /app/.next 2>/dev/null; then
echo "Warning: Could not chown /app/.next; continuing anyway"
fi
else
echo "/app/.next already owned by correct UID/GID or running as root, skipping chown"
fi
fi

View File

@@ -5,11 +5,18 @@ description: Grafana Widget Configuration
Learn more about [Grafana](https://github.com/grafana/grafana).
| Grafana Version | Homepage Widget Version |
| --------------- | ----------------------- |
| <= v10.4 | 1 (default) |
| > v10.4 | 2 |
Allowed fields: `["dashboards", "datasources", "totalalerts", "alertstriggered"]`.
```yaml
widget:
type: grafana
version: 2 # optional, default is 1
alerts: alertmanager # optional, default is grafana
url: http://grafana.host.or.ip:port
username: username
password: password

View File

@@ -32,11 +32,11 @@
"raw-body": "^3.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-i18next": "^11.18.6",
"react-i18next": "^15.5.3",
"react-icons": "^5.4.0",
"recharts": "^2.15.3",
"swr": "^2.3.3",
"systeminformation": "^5.25.11",
"systeminformation": "^5.27.7",
"tough-cookie": "^5.1.2",
"urbackup-server-api": "^0.8.9",
"winston": "^3.17.0",
@@ -50,11 +50,11 @@
"eslint-config-prettier": "^10.1.1",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.2.6",
"eslint-plugin-prettier": "^5.5.1",
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-hooks": "^5.2.0",
"postcss": "^8.5.3",
"prettier": "^3.5.3",
"prettier": "^3.6.2",
"prettier-plugin-organize-imports": "^4.1.0",
"tailwind-scrollbar": "^4.0.2",
"tailwindcss": "^4.0.9",

104
pnpm-lock.yaml generated
View File

@@ -72,8 +72,8 @@ importers:
specifier: ^18.3.1
version: 18.3.1(react@18.3.1)
react-i18next:
specifier: ^11.18.6
version: 11.18.6(i18next@24.2.3(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
specifier: ^15.5.3
version: 15.5.3(i18next@24.2.3(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3)
react-icons:
specifier: ^5.4.0
version: 5.4.0(react@18.3.1)
@@ -84,8 +84,8 @@ importers:
specifier: ^2.3.3
version: 2.3.3(react@18.3.1)
systeminformation:
specifier: ^5.25.11
version: 5.25.11
specifier: ^5.27.7
version: 5.27.7
tough-cookie:
specifier: ^5.1.2
version: 5.1.2
@@ -121,23 +121,23 @@ importers:
specifier: ^6.10.2
version: 6.10.2(eslint@9.25.1(jiti@2.4.2))
eslint-plugin-prettier:
specifier: ^5.2.6
version: 5.2.6(eslint-config-prettier@10.1.1(eslint@9.25.1(jiti@2.4.2)))(eslint@9.25.1(jiti@2.4.2))(prettier@3.5.3)
specifier: ^5.5.1
version: 5.5.1(eslint-config-prettier@10.1.1(eslint@9.25.1(jiti@2.4.2)))(eslint@9.25.1(jiti@2.4.2))(prettier@3.6.2)
eslint-plugin-react:
specifier: ^7.37.4
version: 7.37.4(eslint@9.25.1(jiti@2.4.2))
eslint-plugin-react-hooks:
specifier: ^5.1.0
version: 5.1.0(eslint@9.25.1(jiti@2.4.2))
specifier: ^5.2.0
version: 5.2.0(eslint@9.25.1(jiti@2.4.2))
postcss:
specifier: ^8.5.3
version: 8.5.3
prettier:
specifier: ^3.5.3
version: 3.5.3
specifier: ^3.6.2
version: 3.6.2
prettier-plugin-organize-imports:
specifier: ^4.1.0
version: 4.1.0(prettier@3.5.3)(typescript@5.7.3)
version: 4.1.0(prettier@3.6.2)(typescript@5.7.3)
tailwind-scrollbar:
specifier: ^4.0.2
version: 4.0.2(react@18.3.1)(tailwindcss@4.0.9)
@@ -166,8 +166,8 @@ packages:
resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==}
engines: {node: '>=6.9.0'}
'@babel/runtime@7.27.1':
resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==}
'@babel/runtime@7.27.6':
resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==}
engines: {node: '>=6.9.0'}
'@balena/dockerignore@1.0.2':
@@ -476,8 +476,8 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
'@pkgr/core@0.2.4':
resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==}
'@pkgr/core@0.2.7':
resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
'@protobufjs/aspromise@1.1.2':
@@ -1364,8 +1364,8 @@ packages:
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
eslint-plugin-prettier@5.2.6:
resolution: {integrity: sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==}
eslint-plugin-prettier@5.5.1:
resolution: {integrity: sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
'@types/eslint': '>=8.0.0'
@@ -1378,8 +1378,8 @@ packages:
eslint-config-prettier:
optional: true
eslint-plugin-react-hooks@5.1.0:
resolution: {integrity: sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==}
eslint-plugin-react-hooks@5.2.0:
resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==}
engines: {node: '>=10'}
peerDependencies:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
@@ -2262,8 +2262,8 @@ packages:
vue-tsc:
optional: true
prettier@3.5.3:
resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==}
prettier@3.6.2:
resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
engines: {node: '>=14'}
hasBin: true
@@ -2322,6 +2322,22 @@ packages:
react-native:
optional: true
react-i18next@15.5.3:
resolution: {integrity: sha512-ypYmOKOnjqPEJZO4m1BI0kS8kWqkBNsKYyhVUfij0gvjy9xJNoG/VcGkxq5dRlVwzmrmY1BQMAmpbbUBLwC4Kw==}
peerDependencies:
i18next: '>= 23.2.3'
react: '>= 16.8.0'
react-dom: '*'
react-native: '*'
typescript: ^5
peerDependenciesMeta:
react-dom:
optional: true
react-native:
optional: true
typescript:
optional: true
react-icons@5.4.0:
resolution: {integrity: sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==}
peerDependencies:
@@ -2632,12 +2648,12 @@ packages:
peerDependencies:
react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
synckit@0.11.4:
resolution: {integrity: sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==}
synckit@0.11.8:
resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==}
engines: {node: ^14.18.0 || >=16.0.0}
systeminformation@5.25.11:
resolution: {integrity: sha512-jI01fn/t47rrLTQB0FTlMCC+5dYx8o0RRF+R4BPiUNsvg5OdY0s9DKMFmJGrx5SwMZQ4cag0Gl6v8oycso9b/g==}
systeminformation@5.27.7:
resolution: {integrity: sha512-saaqOoVEEFaux4v0K8Q7caiauRwjXC4XbD2eH60dxHXbpKxQ8kH9Rf7Jh+nryKpOUSEFxtCdBlSUx0/lO6rwRg==}
engines: {node: '>=8.0.0'}
os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android]
hasBin: true
@@ -2897,7 +2913,7 @@ snapshots:
dependencies:
regenerator-runtime: 0.14.1
'@babel/runtime@7.27.1': {}
'@babel/runtime@7.27.6': {}
'@balena/dockerignore@1.0.2': {}
@@ -3181,7 +3197,7 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
'@pkgr/core@0.2.4': {}
'@pkgr/core@0.2.7': {}
'@protobufjs/aspromise@1.1.2': {}
@@ -3929,7 +3945,7 @@ snapshots:
dom-helpers@5.2.1:
dependencies:
'@babel/runtime': 7.27.1
'@babel/runtime': 7.27.6
csstype: 3.1.3
dom-serializer@2.0.0:
@@ -4089,7 +4105,7 @@ snapshots:
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.29.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.25.1(jiti@2.4.2))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.25.1(jiti@2.4.2))
eslint-plugin-react: 7.37.4(eslint@9.25.1(jiti@2.4.2))
eslint-plugin-react-hooks: 5.1.0(eslint@9.25.1(jiti@2.4.2))
eslint-plugin-react-hooks: 5.2.0(eslint@9.25.1(jiti@2.4.2))
optionalDependencies:
typescript: 5.7.3
transitivePeerDependencies:
@@ -4183,16 +4199,16 @@ snapshots:
safe-regex-test: 1.1.0
string.prototype.includes: 2.0.1
eslint-plugin-prettier@5.2.6(eslint-config-prettier@10.1.1(eslint@9.25.1(jiti@2.4.2)))(eslint@9.25.1(jiti@2.4.2))(prettier@3.5.3):
eslint-plugin-prettier@5.5.1(eslint-config-prettier@10.1.1(eslint@9.25.1(jiti@2.4.2)))(eslint@9.25.1(jiti@2.4.2))(prettier@3.6.2):
dependencies:
eslint: 9.25.1(jiti@2.4.2)
prettier: 3.5.3
prettier: 3.6.2
prettier-linter-helpers: 1.0.0
synckit: 0.11.4
synckit: 0.11.8
optionalDependencies:
eslint-config-prettier: 10.1.1(eslint@9.25.1(jiti@2.4.2))
eslint-plugin-react-hooks@5.1.0(eslint@9.25.1(jiti@2.4.2)):
eslint-plugin-react-hooks@5.2.0(eslint@9.25.1(jiti@2.4.2)):
dependencies:
eslint: 9.25.1(jiti@2.4.2)
@@ -4535,7 +4551,7 @@ snapshots:
i18next@21.10.0:
dependencies:
'@babel/runtime': 7.27.0
'@babel/runtime': 7.26.9
i18next@24.2.3(typescript@5.7.3):
dependencies:
@@ -5089,12 +5105,12 @@ snapshots:
dependencies:
fast-diff: 1.3.0
prettier-plugin-organize-imports@4.1.0(prettier@3.5.3)(typescript@5.7.3):
prettier-plugin-organize-imports@4.1.0(prettier@3.6.2)(typescript@5.7.3):
dependencies:
prettier: 3.5.3
prettier: 3.6.2
typescript: 5.7.3
prettier@3.5.3: {}
prettier@3.6.2: {}
pretty-bytes@6.1.1: {}
@@ -5160,14 +5176,15 @@ snapshots:
optionalDependencies:
react-dom: 18.3.1(react@18.3.1)
react-i18next@11.18.6(i18next@24.2.3(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
react-i18next@15.5.3(i18next@24.2.3(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.3):
dependencies:
'@babel/runtime': 7.26.9
'@babel/runtime': 7.27.6
html-parse-stringify: 3.0.1
i18next: 24.2.3(typescript@5.7.3)
react: 18.3.1
optionalDependencies:
react-dom: 18.3.1(react@18.3.1)
typescript: 5.7.3
react-icons@5.4.0(react@18.3.1):
dependencies:
@@ -5187,7 +5204,7 @@ snapshots:
react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@babel/runtime': 7.27.1
'@babel/runtime': 7.27.6
dom-helpers: 5.2.1
loose-envify: 1.4.0
prop-types: 15.8.1
@@ -5559,12 +5576,11 @@ snapshots:
react: 18.3.1
use-sync-external-store: 1.5.0(react@18.3.1)
synckit@0.11.4:
synckit@0.11.8:
dependencies:
'@pkgr/core': 0.2.4
tslib: 2.8.1
'@pkgr/core': 0.2.7
systeminformation@5.25.11: {}
systeminformation@5.27.7: {}
tailwind-scrollbar@4.0.2(react@18.3.1)(tailwindcss@4.0.9):
dependencies:

View File

@@ -55,7 +55,7 @@ export default function ColorToggle() {
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute -top-[75px] left-0">
<Popover.Panel className="absolute -top-[75px] left-0 z-10">
<div className="rounded-md shadow-lg ring-1 ring-black ring-opacity-5 w-[85vw] sm:w-full">
<div className="relative grid gap-2 p-2 grid-cols-11 bg-white/50 dark:bg-white/10 shadow-black/10 dark:shadow-black/20 rounded-md shadow-md">
{colors.map((color) => (

View File

@@ -407,6 +407,9 @@ export function cleanServiceGroups(groups) {
// spoolman
spoolIds,
// grafana
alerts,
} = widgetData;
let fieldsList = fields;
@@ -514,7 +517,18 @@ export function cleanServiceGroups(groups) {
if (snapshotPath) widget.snapshotPath = snapshotPath;
}
if (
["beszel", "glances", "immich", "komga", "mealie", "pfsense", "pihole", "speedtest", "wgeasy"].includes(type)
[
"beszel",
"glances",
"immich",
"komga",
"mealie",
"pfsense",
"pihole",
"speedtest",
"wgeasy",
"grafana",
].includes(type)
) {
if (version) widget.version = parseInt(version, 10);
}
@@ -593,6 +607,9 @@ export function cleanServiceGroups(groups) {
if (type === "jellystat") {
if (days !== undefined) widget.days = parseInt(days, 10);
}
if (type === "grafana") {
if (alerts) widget.alerts = alerts;
}
return widget;
});
return cleanedService;

View File

@@ -31,7 +31,8 @@ function CPU({ quicklookData, className = "" }) {
return (
quicklookData &&
quicklookData.cpu && (
quicklookData.cpu !== undefined &&
quicklookData.cpu !== null && (
<div className="text-xs flex place-content-between">
<div className={className}>{t("glances.cpu")}</div>
<div className={className}>

View File

@@ -6,27 +6,51 @@ import useWidgetAPI from "utils/proxy/use-widget-api";
export default function Component({ service }) {
const { t } = useTranslation();
const { widget } = service;
const { version = 1, alerts = "grafana" } = widget;
const { data: statsData, error: statsError } = useWidgetAPI(widget, "stats");
const { data: alertsData, error: alertsError } = useWidgetAPI(widget, "alerts");
const { data: alertmanagerData, error: alertmanagerError } = useWidgetAPI(widget, "alertmanager");
let alertsInt = 0;
if (alertsError || !alertsData || alertsData.length === 0) {
if (alertmanagerData) {
alertsInt = alertmanagerData.length;
}
} else {
alertsInt = alertsData.filter((a) => a.state === "alerting").length;
let primaryAlertsEndpoint = "alerts";
let secondaryAlertsEndpoint = "grafana";
if (version === 2) {
primaryAlertsEndpoint = alerts;
secondaryAlertsEndpoint = "";
}
if (statsError || (alertsError && alertmanagerError)) {
const { data: primaryAlertsData, error: primaryAlertsError } = useWidgetAPI(widget, primaryAlertsEndpoint);
const { data: secondaryAlertsData, error: secondaryAlertsError } = useWidgetAPI(widget, secondaryAlertsEndpoint);
let alertsInt = 0;
let alertsError = null;
if (version === 1) {
if (primaryAlertsError || !primaryAlertsData || primaryAlertsData.length === 0) {
if (secondaryAlertsData) {
alertsInt = secondaryAlertsData.length;
}
} else {
alertsInt = primaryAlertsData.filter((a) => a.state === "alerting").length;
}
if (primaryAlertsError && secondaryAlertsError) {
alertsError = primaryAlertsError ?? secondaryAlertsError;
}
} else if (version === 2) {
if (primaryAlertsData) {
alertsInt = primaryAlertsData.length;
}
if (primaryAlertsError) {
alertsError = primaryAlertsError;
}
}
if (statsError || alertsError) {
return <Container service={service} error={statsError ?? alertsError} />;
}
if (!statsData || (!alertsData && !alertmanagerData)) {
if (!statsData) {
return (
<Container service={service}>
<Block label="grafana.dashboards" />

View File

@@ -9,6 +9,9 @@ const widget = {
endpoint: "alerts",
},
alertmanager: {
endpoint: "alertmanager/alertmanager/api/v2/alerts",
},
grafana: {
endpoint: "alertmanager/grafana/api/v2/alerts",
},
stats: {

View File

@@ -45,6 +45,25 @@ export default function Component({ service }) {
}
const leech = torrentData.length - completed;
const statePriority = [
"downloading",
"forcedDL",
"metaDL",
"forcedMetaDL",
"checkingDL",
"stalledDL",
"queuedDL",
"pausedDL",
];
leechTorrents.sort((firstTorrent, secondTorrent) => {
const firstStateIndex = statePriority.indexOf(firstTorrent.state);
const secondStateIndex = statePriority.indexOf(secondTorrent.state);
if (firstStateIndex !== secondStateIndex) {
return firstStateIndex - secondStateIndex;
}
return secondTorrent.progress - firstTorrent.progress;
});
return (
<>