Compare commits

...

7 Commits

Author SHA1 Message Date
henrygd
b084814aea auth form: fix border style and add theme toggle 2025-08-28 21:17:44 -04:00
Impact
cce74246ee Use older cuda image for increased compatibility (#1103) 2025-08-28 20:49:52 -04:00
henrygd
a3420b8c67 add max 1 min memory 2025-08-28 20:07:22 -04:00
henrygd
e1bb17ee9e update locale files 2025-08-28 18:23:40 -04:00
henrygd
52983f60b7 refactor: add api module and page preloading 2025-08-28 18:23:24 -04:00
henrygd
1f053fd85d update 2025-08-28 17:31:18 -04:00
Sven van Ginkel
a989d121d3 [Feature] Add Status Filtering to Systems Table (#927) 2025-08-28 17:30:44 -04:00
61 changed files with 836 additions and 374 deletions

View File

@@ -15,7 +15,7 @@ RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-
# --------------------------
# Final image: GPU-enabled agent with nvidia-smi
# --------------------------
FROM nvidia/cuda:12.9.1-base-ubuntu22.04
FROM nvidia/cuda:12.2.2-base-ubuntu22.04
COPY --from=builder /agent /agent
ENTRYPOINT ["/agent"]

View File

@@ -39,6 +39,7 @@ type Stats struct {
// TODO: remove other load fields in future release in favor of load avg array
LoadAvg [3]float64 `json:"la,omitempty" cbor:"28,keyasint"`
Battery [2]uint8 `json:"bat,omitzero" cbor:"29,keyasint,omitzero"` // [percent, charge state, current]
MaxMem float64 `json:"mm,omitempty" cbor:"30,keyasint,omitempty"`
}
type GPUData struct {

View File

@@ -214,6 +214,7 @@ func (rm *RecordManager) AverageSystemStats(db dbx.Builder, records RecordIds) *
sum.Battery[1] = stats.Battery[1]
// Set peak values
sum.MaxCpu = max(sum.MaxCpu, stats.MaxCpu, stats.Cpu)
sum.MaxMem = max(sum.MaxMem, stats.MaxMem, stats.MemUsed)
sum.MaxNetworkSent = max(sum.MaxNetworkSent, stats.MaxNetworkSent, stats.NetworkSent)
sum.MaxNetworkRecv = max(sum.MaxNetworkRecv, stats.MaxNetworkRecv, stats.NetworkRecv)
sum.MaxDiskReadPs = max(sum.MaxDiskReadPs, stats.MaxDiskReadPs, stats.DiskReadPs)

View File

@@ -66,7 +66,7 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dev": true,
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
@@ -80,7 +80,7 @@
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/helper-validator-identifier": "^7.27.1",
@@ -95,7 +95,7 @@
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
"integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -105,7 +105,7 @@
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz",
"integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
@@ -136,7 +136,7 @@
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
"integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.28.3",
@@ -153,7 +153,7 @@
"version": "7.27.2",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
"integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/compat-data": "^7.27.2",
@@ -170,7 +170,7 @@
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -180,7 +180,7 @@
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
"integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/traverse": "^7.27.1",
@@ -194,7 +194,7 @@
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
"integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.27.1",
@@ -212,7 +212,7 @@
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -222,7 +222,7 @@
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -232,7 +232,7 @@
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
"integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -242,7 +242,7 @@
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz",
"integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.27.2",
@@ -256,7 +256,7 @@
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz",
"integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.28.2"
@@ -284,7 +284,7 @@
"version": "7.27.2",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.27.1",
@@ -299,7 +299,7 @@
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz",
"integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.27.1",
@@ -318,7 +318,7 @@
"version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
"integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
@@ -854,7 +854,7 @@
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
"integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@sinclair/typebox": "^0.27.8"
@@ -867,7 +867,7 @@
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
"integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@jest/schemas": "^29.6.3",
@@ -885,7 +885,7 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -907,7 +907,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -917,14 +917,14 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.30",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
"integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@@ -945,7 +945,7 @@
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/@lingui/babel-plugin-lingui-macro/-/babel-plugin-lingui-macro-5.4.1.tgz",
"integrity": "sha512-9IO+PDvdneY8OCI8zvI1oDXpzryTMtyRv7uq9O0U1mFCvIPVd5dWQKQDu/CpgpYAc2+JG/izn5PNl9xzPc6ckw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.20.12",
@@ -1165,7 +1165,7 @@
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-5.4.1.tgz",
"integrity": "sha512-aDkj/bMSr/mCL8Nr1TS52v0GLCuVa4YqtRz+WvUCFZw/ovVInX0hKq1TClx/bSlhu60FzB/CbclxFMBw8aLVUg==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.20.13",
@@ -2584,7 +2584,7 @@
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
"integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/@swc/core": {
@@ -3227,14 +3227,14 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
"integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/@types/istanbul-lib-report": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
"integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@types/istanbul-lib-coverage": "*"
@@ -3244,7 +3244,7 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
"integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@types/istanbul-lib-report": "*"
@@ -3254,7 +3254,7 @@
"version": "24.3.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz",
"integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.10.0"
@@ -3264,7 +3264,7 @@
"version": "19.1.11",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.11.tgz",
"integrity": "sha512-lr3jdBw/BGj49Eps7EvqlUaoeA0xpj3pc0RoJkHpYaCHkVK7i28dKyImLQb3JVlqs3aYSXf7qYuWOW/fgZnTXQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"csstype": "^3.0.2"
@@ -3274,7 +3274,7 @@
"version": "19.1.7",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz",
"integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"peerDependencies": {
"@types/react": "^19.0.0"
@@ -3284,7 +3284,7 @@
"version": "17.0.33",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
"integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@types/yargs-parser": "*"
@@ -3294,7 +3294,7 @@
"version": "21.0.3",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/@vitejs/plugin-react-swc": {
@@ -3331,7 +3331,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -3374,7 +3374,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"devOptional": true,
"license": "Python-2.0"
},
"node_modules/aria-hidden": {
@@ -3469,7 +3469,7 @@
"version": "4.25.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
"integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
"dev": true,
"devOptional": true,
"funding": [
{
"type": "opencollective",
@@ -3540,7 +3540,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -3550,7 +3550,7 @@
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -3563,7 +3563,7 @@
"version": "1.0.30001727",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
"integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
"dev": true,
"devOptional": true,
"funding": [
{
"type": "opencollective",
@@ -3584,7 +3584,7 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
@@ -3696,7 +3696,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -3709,7 +3709,7 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/colors": {
@@ -3726,14 +3726,14 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/cosmiconfig": {
"version": "8.3.6",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
"integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"import-fresh": "^3.3.0",
@@ -3913,7 +3913,7 @@
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -3983,7 +3983,7 @@
"version": "1.5.182",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.182.tgz",
"integrity": "sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA==",
"dev": true,
"devOptional": true,
"license": "ISC"
},
"node_modules/emoji-regex": {
@@ -4011,7 +4011,7 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"is-arrayish": "^0.2.1"
@@ -4080,7 +4080,7 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -4168,7 +4168,7 @@
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -4194,7 +4194,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -4225,7 +4225,7 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
@@ -4258,7 +4258,7 @@
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/is-binary-path": {
@@ -4351,7 +4351,7 @@
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
"integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -4361,7 +4361,7 @@
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
"integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@jest/types": "^29.6.3",
@@ -4379,7 +4379,7 @@
"version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"dev": true,
"devOptional": true,
"license": "MIT",
"bin": {
"jiti": "bin/jiti.js"
@@ -4401,7 +4401,7 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
@@ -4414,7 +4414,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
@@ -4427,14 +4427,14 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"devOptional": true,
"license": "MIT",
"bin": {
"json5": "lib/cli.js"
@@ -4447,7 +4447,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -4696,7 +4696,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/lodash": {
@@ -4745,7 +4745,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dev": true,
"devOptional": true,
"license": "ISC",
"dependencies": {
"yallist": "^3.0.2"
@@ -4856,7 +4856,7 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/nanoid": {
@@ -4897,7 +4897,7 @@
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/normalize-path": {
@@ -4993,7 +4993,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
@@ -5006,7 +5006,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.0.0",
@@ -5035,7 +5035,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -5045,7 +5045,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"devOptional": true,
"license": "ISC"
},
"node_modules/picomatch": {
@@ -5107,7 +5107,7 @@
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
"integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@jest/schemas": "^29.6.3",
@@ -5122,7 +5122,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -5368,7 +5368,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=4"
@@ -5466,7 +5466,7 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"devOptional": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -5649,7 +5649,7 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
@@ -5783,7 +5783,7 @@
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"dev": true,
"devOptional": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
@@ -5797,14 +5797,14 @@
"version": "7.10.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
"integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
"integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
"dev": true,
"devOptional": true,
"funding": [
{
"type": "opencollective",
@@ -6136,7 +6136,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
"dev": true,
"devOptional": true,
"license": "ISC"
}
}

View File

@@ -13,8 +13,9 @@ import {
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { $publicKey, pb } from "@/lib/stores"
import { cn, generateToken, isReadOnlyUser, tokenMap, useLocalStorage } from "@/lib/utils"
import { $publicKey } from "@/lib/stores"
import { cn, generateToken, tokenMap, useLocalStorage } from "@/lib/utils"
import { pb, isReadOnlyUser } from "@/lib/api"
import { useStore } from "@nanostores/react"
import { ChevronDownIcon, ExternalLinkIcon, PlusIcon } from "lucide-react"
import { memo, useEffect, useRef, useState } from "react"

View File

@@ -1,6 +1,6 @@
import { t } from "@lingui/core/macro"
import { Trans, Plural } from "@lingui/react/macro"
import { $alerts, $systems, pb } from "@/lib/stores"
import { $alerts, $systems } from "@/lib/stores"
import { cn, debounce } from "@/lib/utils"
import { alertInfo } from "@/lib/alerts"
import { Switch } from "@/components/ui/switch"
@@ -15,6 +15,7 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"
import { ServerIcon, GlobeIcon } from "lucide-react"
import { $router, Link } from "@/components/router"
import { DialogHeader } from "@/components/ui/dialog"
import { pb } from "@/lib/api"
const Slider = lazy(() => import("@/components/ui/slider"))

View File

@@ -7,7 +7,7 @@ import { useMemo } from "react"
export type DataPoint = {
label: string
dataKey: (data: SystemStatsRecord) => number | undefined
color: string
color: number | string
opacity: number
}

View File

@@ -6,7 +6,7 @@ import { ChartData } from "@/types"
import { useLingui } from "@lingui/react/macro"
import { Unit } from "@/lib/enums"
export default memo(function MemChart({ chartData }: { chartData: ChartData }) {
export default memo(function MemChart({ chartData, showMax }: { chartData: ChartData; showMax: boolean }) {
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()
const { t } = useLingui()
@@ -66,7 +66,7 @@ export default memo(function MemChart({ chartData }: { chartData: ChartData }) {
<Area
name={t`Used`}
order={3}
dataKey="stats.mu"
dataKey={({ stats }) => (showMax ? stats?.mm : stats?.mu)}
type="monotoneX"
fill="var(--chart-2)"
fillOpacity={0.4}
@@ -74,31 +74,31 @@ export default memo(function MemChart({ chartData }: { chartData: ChartData }) {
stackId="1"
isAnimationActive={false}
/>
{chartData.systemStats.at(-1)?.stats.mz && (
<Area
name="ZFS ARC"
order={2}
dataKey="stats.mz"
type="monotoneX"
fill="hsla(175 60% 45% / 0.8)"
fillOpacity={0.5}
stroke="hsla(175 60% 45% / 0.8)"
stackId="1"
isAnimationActive={false}
/>
)}
{/* {chartData.systemStats.at(-1)?.stats.mz && ( */}
<Area
name="ZFS ARC"
order={2}
dataKey={({ stats }) => (showMax ? null : stats?.mz)}
type="monotoneX"
fill="hsla(175 60% 45% / 0.8)"
fillOpacity={0.5}
stroke="hsla(175 60% 45% / 0.8)"
stackId="1"
isAnimationActive={false}
/>
{/* )} */}
<Area
name={t`Cache / Buffers`}
order={1}
dataKey="stats.mb"
dataKey={({ stats }) => (showMax ? null : stats?.mb)}
type="monotoneX"
fill="hsla(160 60% 45% / 0.5)"
fillOpacity={0.4}
// strokeOpacity={1}
stroke="hsla(160 60% 45% / 0.5)"
stackId="1"
isAnimationActive={false}
/>
{/* <ChartLegend content={<ChartLegendContent />} /> */}
</AreaChart>
</ChartContainer>
</div>

View File

@@ -23,11 +23,13 @@ import {
} from "@/components/ui/command"
import { memo, useEffect, useMemo } from "react"
import { $systems } from "@/lib/stores"
import { getHostDisplayValue, isAdmin, listen } from "@/lib/utils"
import { getHostDisplayValue, listen } from "@/lib/utils"
import { $router, basePath, navigate, prependBasePath } from "./router"
import { Trans } from "@lingui/react/macro"
import { t } from "@lingui/core/macro"
import { getPagePath } from "@nanostores/router"
import { DialogDescription } from "@radix-ui/react-dialog"
import { isAdmin } from "@/lib/api"
export default memo(function CommandPalette({ open, setOpen }: { open: boolean; setOpen: (open: boolean) => void }) {
useEffect(() => {
@@ -54,11 +56,9 @@ export default memo(function CommandPalette({ open, setOpen }: { open: boolean;
)
return (
<CommandDialog open={open} onOpenChange={setOpen}>
<DialogDescription className="sr-only">Command palette</DialogDescription>
<CommandInput placeholder={t`Search for systems or settings...`} />
<CommandList>
<CommandEmpty>
<Trans>No results found.</Trans>
</CommandEmpty>
{systems.length > 0 && (
<>
<CommandGroup>
@@ -214,6 +214,9 @@ export default memo(function CommandPalette({ open, setOpen }: { open: boolean;
</CommandGroup>
</>
)}
<CommandEmpty>
<Trans>No results found.</Trans>
</CommandEmpty>
</CommandList>
</CommandDialog>
)

View File

@@ -5,7 +5,7 @@ import { buttonVariants } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { LoaderCircle, LockIcon, LogInIcon, MailIcon } from "lucide-react"
import { $authenticated, pb } from "@/lib/stores"
import { $authenticated } from "@/lib/stores"
import * as v from "valibot"
import { toast } from "../ui/use-toast"
import { Dialog, DialogContent, DialogTrigger, DialogHeader, DialogTitle } from "@/components/ui/dialog"
@@ -13,6 +13,7 @@ import { useCallback, useEffect, useState } from "react"
import { AuthMethodsList, AuthProviderInfo, OAuth2AuthConfig } from "pocketbase"
import { $router, Link, prependBasePath } from "../router"
import { getPagePath } from "@nanostores/router"
import { pb } from "@/lib/api"
const honeypot = v.literal("")
const emailSchema = v.pipe(v.string(), v.email(t`Invalid email address.`))

View File

@@ -1,5 +1,5 @@
import { Trans } from "@lingui/react/macro";
import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro"
import { t } from "@lingui/core/macro"
import { LoaderCircle, MailIcon, SendHorizonalIcon } from "lucide-react"
import { Input } from "../ui/input"
import { Label } from "../ui/label"
@@ -7,9 +7,9 @@ import { useCallback, useState } from "react"
import { toast } from "../ui/use-toast"
import { buttonVariants } from "../ui/button"
import { cn } from "@/lib/utils"
import { pb } from "@/lib/stores"
import { Dialog, DialogHeader } from "../ui/dialog"
import { DialogContent, DialogTrigger, DialogTitle } from "../ui/dialog"
import { pb } from "@/lib/api"
const showLoginFaliedToast = () => {
toast({

View File

@@ -1,13 +1,14 @@
import { t } from "@lingui/core/macro";
import { t } from "@lingui/core/macro"
import { UserAuthForm } from "@/components/login/auth-form"
import { Logo } from "../logo"
import { useEffect, useMemo, useState } from "react"
import { pb } from "@/lib/stores"
import { useStore } from "@nanostores/react"
import ForgotPassword from "./forgot-pass-form"
import { $router } from "../router"
import { AuthMethodsList } from "pocketbase"
import { useTheme } from "../theme-provider"
import { pb } from "@/lib/api"
import { ModeToggle } from "../mode-toggle"
export default function () {
const page = useStore($router)
@@ -50,8 +51,11 @@ export default function () {
<div
className="grid gap-5 w-full px-4 mx-auto"
// @ts-ignore
style={{ maxWidth: "22em", "--border": theme == "light" ? "30 8% 80%" : "220 3% 20%" }}
style={{ maxWidth: "22em", "--border": theme == "light" ? "hsl(30, 8%, 70%)" : "hsl(220, 3%, 25%)" }}
>
<div className="absolute top-3 right-3">
<ModeToggle />
</div>
<div className="text-center">
<h1 className="mb-3">
<Logo className="h-7 fill-foreground mx-auto" />

View File

@@ -15,8 +15,8 @@ import { $router, basePath, Link, prependBasePath } from "./router"
import { LangToggle } from "./lang-toggle"
import { ModeToggle } from "./mode-toggle"
import { Logo } from "./logo"
import { pb } from "@/lib/stores"
import { cn, isReadOnlyUser, isAdmin, logOut } from "@/lib/utils"
import { cn, runOnce } from "@/lib/utils"
import { isReadOnlyUser, isAdmin, logOut, pb } from "@/lib/api"
import {
DropdownMenu,
DropdownMenuTrigger,
@@ -36,12 +36,17 @@ const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0
export default function Navbar() {
return (
<div className="flex items-center h-14 md:h-16 bg-card px-4 pe-3 sm:px-6 border border-border/60 bt-0 rounded-md my-4">
<Link href={basePath} aria-label="Home" className="p-2 ps-0 me-3">
<Link
href={basePath}
aria-label="Home"
className="p-2 ps-0 me-3"
onMouseEnter={runOnce(() => import("@/components/routes/home"))}
>
<Logo className="h-[1.1rem] md:h-5 fill-foreground" />
</Link>
<SearchButton />
<div className="flex items-center ms-auto">
<div className="flex items-center ms-auto" onMouseEnter={() => import("@/components/routes/settings/general")}>
<LangToggle />
<ModeToggle />
<Link

View File

@@ -1,18 +1,20 @@
import { Suspense, lazy, memo, useEffect, useMemo } from "react"
import { Suspense, memo, useEffect, useMemo } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"
import { $alerts, $systems, pb } from "@/lib/stores"
import { $alerts, $systems } from "@/lib/stores"
import { useStore } from "@nanostores/react"
import { GithubIcon } from "lucide-react"
import { Separator } from "../ui/separator"
import { getSystemNameFromId, updateRecordList, updateSystemList } from "@/lib/utils"
import { getSystemNameFromId } from "@/lib/utils"
import { pb, updateRecordList, updateSystemList } from "@/lib/api"
import { AlertRecord, SystemRecord } from "@/types"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { $router, Link } from "../router"
import { Plural, Trans, useLingui } from "@lingui/react/macro"
import { getPagePath } from "@nanostores/router"
import { alertInfo } from "@/lib/alerts"
import SystemsTable from "@/components/systems-table/systems-table"
const SystemsTable = lazy(() => import("../systems-table/systems-table"))
// const SystemsTable = lazy(() => import("../systems-table/systems-table"))
export default memo(function () {
const { t } = useLingui()

View File

@@ -1,4 +1,4 @@
import { pb } from "@/lib/stores"
import { pb } from "@/lib/api"
import { cn, formatDuration, formatShortDate } from "@/lib/utils"
import { alertInfo } from "@/lib/alerts"
import { AlertsHistoryRecord } from "@/types"

View File

@@ -1,17 +1,16 @@
import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro"
import { isAdmin } from "@/lib/utils"
import { Separator } from "@/components/ui/separator"
import { Button } from "@/components/ui/button"
import { redirectPage } from "@nanostores/router"
import { $router } from "@/components/router"
import { AlertCircleIcon, FileSlidersIcon, LoaderCircleIcon } from "lucide-react"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { pb } from "@/lib/stores"
import { useState } from "react"
import { Textarea } from "@/components/ui/textarea"
import { toast } from "@/components/ui/use-toast"
import clsx from "clsx"
import { isAdmin, pb } from "@/lib/api"
export default function ConfigYaml() {
const [configContent, setConfigContent] = useState<string>("")

View File

@@ -1,6 +1,6 @@
import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro"
import { useEffect } from "react"
import { lazy, useEffect } from "react"
import { Separator } from "../../ui/separator"
import { SidebarNav } from "./sidebar-nav.tsx"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card.tsx"
@@ -8,15 +8,23 @@ import { useStore } from "@nanostores/react"
import { $router } from "@/components/router.tsx"
import { getPagePath, redirectPage } from "@nanostores/router"
import { BellIcon, FileSlidersIcon, FingerprintIcon, SettingsIcon, AlertOctagonIcon } from "lucide-react"
import { $userSettings, pb } from "@/lib/stores.ts"
import { $userSettings } from "@/lib/stores.ts"
import { toast } from "@/components/ui/use-toast.ts"
import { UserSettings } from "@/types"
import General from "./general.tsx"
import Notifications from "./notifications.tsx"
import ConfigYaml from "./config-yaml.tsx"
import { useLingui } from "@lingui/react/macro"
import Fingerprints from "./tokens-fingerprints.tsx"
import AlertsHistoryDataTable from "./alerts-history-data-table"
import { pb } from "@/lib/api"
const generalSettingsImport = () => import("./general.tsx")
const notificationsSettingsImport = () => import("./notifications.tsx")
const configYamlSettingsImport = () => import("./config-yaml.tsx")
const fingerprintsSettingsImport = () => import("./tokens-fingerprints.tsx")
const alertsHistoryDataTableSettingsImport = () => import("./alerts-history-data-table.tsx")
const GeneralSettings = lazy(generalSettingsImport)
const NotificationsSettings = lazy(notificationsSettingsImport)
const ConfigYamlSettings = lazy(configYamlSettingsImport)
const FingerprintsSettings = lazy(fingerprintsSettingsImport)
const AlertsHistoryDataTableSettings = lazy(alertsHistoryDataTableSettingsImport)
export async function saveSettings(newSettings: Partial<UserSettings>) {
try {
@@ -59,23 +67,27 @@ export default function SettingsLayout() {
title: t`Notifications`,
href: getPagePath($router, "settings", { name: "notifications" }),
icon: BellIcon,
preload: notificationsSettingsImport,
},
{
title: t`Tokens & Fingerprints`,
href: getPagePath($router, "settings", { name: "tokens" }),
icon: FingerprintIcon,
noReadOnly: true,
preload: fingerprintsSettingsImport,
},
{
title: t`Alert History`,
href: getPagePath($router, "settings", { name: "alert-history" }),
icon: AlertOctagonIcon,
preload: alertsHistoryDataTableSettingsImport,
},
{
title: t`YAML Config`,
href: getPagePath($router, "settings", { name: "config" }),
icon: FileSlidersIcon,
admin: true,
preload: configYamlSettingsImport,
},
]
@@ -120,14 +132,14 @@ function SettingsContent({ name }: { name: string }) {
switch (name) {
case "general":
return <General userSettings={userSettings} />
return <GeneralSettings userSettings={userSettings} />
case "notifications":
return <Notifications userSettings={userSettings} />
return <NotificationsSettings userSettings={userSettings} />
case "config":
return <ConfigYaml />
return <ConfigYamlSettings />
case "tokens":
return <Fingerprints />
return <FingerprintsSettings />
case "alert-history":
return <AlertsHistoryDataTable />
return <AlertsHistoryDataTableSettings />
}
}

View File

@@ -3,7 +3,6 @@ import { Trans } from "@lingui/react/macro"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { pb } from "@/lib/stores"
import { Separator } from "@/components/ui/separator"
import { Card } from "@/components/ui/card"
import { BellIcon, LoaderCircleIcon, PlusIcon, SaveIcon, Trash2Icon } from "lucide-react"
@@ -13,8 +12,8 @@ import { InputTags } from "@/components/ui/input-tags"
import { UserSettings } from "@/types"
import { saveSettings } from "./layout"
import * as v from "valibot"
import { isAdmin } from "@/lib/utils"
import { prependBasePath } from "@/components/router"
import { isAdmin, pb } from "@/lib/api"
interface ShoutrrrUrlCardProps {
url: string

View File

@@ -1,5 +1,6 @@
import React from "react"
import { cn, isAdmin, isReadOnlyUser } from "@/lib/utils"
import { cn } from "@/lib/utils"
import { isAdmin, isReadOnlyUser } from "@/lib/api"
import { buttonVariants } from "../../ui/button"
import { $router, Link, navigate } from "../../router"
import { useStore } from "@nanostores/react"
@@ -13,6 +14,7 @@ interface SidebarNavProps extends React.HTMLAttributes<HTMLElement> {
icon?: React.FC<React.SVGProps<SVGSVGElement>>
admin?: boolean
noReadOnly?: boolean
preload?: () => Promise<{ default: React.ComponentType<any> }>
}[]
}
@@ -52,6 +54,7 @@ export function SidebarNav({ className, items, ...props }: SidebarNavProps) {
}
return (
<Link
onMouseEnter={() => item.preload?.()}
key={item.href}
href={item.href}
className={cn(

View File

@@ -1,6 +1,6 @@
import { Trans, useLingui } from "@lingui/react/macro"
import { t } from "@lingui/core/macro"
import { $publicKey, pb } from "@/lib/stores"
import { $publicKey } from "@/lib/stores"
import { memo, useEffect, useMemo, useState } from "react"
import { Table, TableCell, TableHead, TableBody, TableRow, TableHeader } from "@/components/ui/table"
import { FingerprintRecord } from "@/types"
@@ -14,7 +14,8 @@ import {
Trash2Icon,
} from "lucide-react"
import { toast } from "@/components/ui/use-toast"
import { cn, copyToClipboard, generateToken, getHubURL, isReadOnlyUser, tokenMap } from "@/lib/utils"
import { cn, copyToClipboard, generateToken, getHubURL, tokenMap } from "@/lib/utils"
import { isReadOnlyUser, pb } from "@/lib/api"
import {
DropdownMenu,
DropdownMenuContent,

View File

@@ -2,7 +2,6 @@ import { t } from "@lingui/core/macro"
import { Plural, Trans } from "@lingui/react/macro"
import {
$systems,
pb,
$chartTime,
$containerFilter,
$userSettings,
@@ -12,7 +11,7 @@ import {
} from "@/lib/stores"
import { ChartData, ChartTimes, ContainerStatsRecord, GPUData, SystemRecord, SystemStatsRecord } from "@/types"
import { ChartType, Unit, Os, SystemStatus } from "@/lib/enums"
import React, { lazy, memo, useCallback, useEffect, useMemo, useRef, useState, type JSX } from "react"
import React, { memo, useCallback, useEffect, useMemo, useRef, useState, type JSX } from "react"
import { Card, CardHeader, CardTitle, CardDescription } from "../ui/card"
import { useStore } from "@nanostores/react"
import Spinner from "../spinner"
@@ -24,12 +23,12 @@ import {
decimalString,
formatBytes,
getHostDisplayValue,
getPbTimestamp,
listen,
parseSemVer,
toFixedFloat,
useLocalStorage,
} from "@/lib/utils"
import { getPbTimestamp, pb } from "@/lib/api"
import { Separator } from "../ui/separator"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip"
import { Button } from "../ui/button"
@@ -42,15 +41,14 @@ import { useLingui } from "@lingui/react/macro"
import { $router, navigate } from "../router"
import { getPagePath } from "@nanostores/router"
import { batteryStateTranslations } from "@/lib/i18n"
const AreaChartDefault = lazy(() => import("../charts/area-chart"))
const ContainerChart = lazy(() => import("../charts/container-chart"))
const MemChart = lazy(() => import("../charts/mem-chart"))
const DiskChart = lazy(() => import("../charts/disk-chart"))
const SwapChart = lazy(() => import("../charts/swap-chart"))
const TemperatureChart = lazy(() => import("../charts/temperature-chart"))
const GpuPowerChart = lazy(() => import("../charts/gpu-power-chart"))
const LoadAverageChart = lazy(() => import("../charts/load-average-chart"))
import AreaChartDefault from "@/components/charts/area-chart"
import ContainerChart from "@/components/charts/container-chart"
import MemChart from "@/components/charts/mem-chart"
import DiskChart from "@/components/charts/disk-chart"
import SwapChart from "@/components/charts/swap-chart"
import TemperatureChart from "@/components/charts/temperature-chart"
import GpuPowerChart from "@/components/charts/gpu-power-chart"
import LoadAverageChart from "@/components/charts/load-average-chart"
const cache = new Map<string, any>()
@@ -287,9 +285,11 @@ export default function SystemDetail({ name }: { name: string }) {
value: system.info.k,
},
}
let uptime: React.ReactNode
if (system.info.u < 172800) {
if (system.info.u < 3600) {
const mins = Math.trunc(system.info.u / 60)
uptime = <Plural value={mins} one="# minute" other="# minutes" />
} else if (system.info.u < 172800) {
const hours = Math.trunc(system.info.u / 3600)
uptime = <Plural value={hours} one="# hour" other="# hours" />
} else {
@@ -317,7 +317,7 @@ export default function SystemDetail({ name }: { name: string }) {
Icon: any
hide?: boolean
}[]
}, [system.info])
}, [system.info, t])
/** Space for tooltip if more than 12 containers */
useEffect(() => {
@@ -486,7 +486,7 @@ export default function SystemDetail({ name }: { name: string }) {
{
label: t`CPU Usage`,
dataKey: ({ stats }) => (showMax ? stats?.cpum : stats?.cpu),
color: "1",
color: 1,
opacity: 0.4,
},
]}
@@ -512,8 +512,9 @@ export default function SystemDetail({ name }: { name: string }) {
grid={grid}
title={t`Memory Usage`}
description={t`Precise utilization at the recorded time`}
cornerEl={maxValSelect}
>
<MemChart chartData={chartData} />
<MemChart chartData={chartData} showMax={showMax} />
</ChartCard>
{containerFilterBar && (
@@ -546,13 +547,13 @@ export default function SystemDetail({ name }: { name: string }) {
{
label: t({ message: "Write", comment: "Disk write" }),
dataKey: ({ stats }) => (showMax ? stats?.dwm : stats?.dw),
color: "3",
color: 3,
opacity: 0.3,
},
{
label: t({ message: "Read", comment: "Disk read" }),
dataKey: ({ stats }) => (showMax ? stats?.drm : stats?.dr),
color: "1",
color: 1,
opacity: 0.3,
},
]}
@@ -587,7 +588,7 @@ export default function SystemDetail({ name }: { name: string }) {
}
return data?.stats?.b?.[0] ?? data?.stats?.ns * 1024 * 1024
},
color: "5",
color: 5,
opacity: 0.2,
},
{
@@ -598,7 +599,7 @@ export default function SystemDetail({ name }: { name: string }) {
}
return data?.stats?.b?.[1] ?? data?.stats?.nr * 1024 * 1024
},
color: "2",
color: 2,
opacity: 0.2,
},
]}
@@ -687,7 +688,7 @@ export default function SystemDetail({ name }: { name: string }) {
{
label: t`Charge`,
dataKey: ({ stats }) => stats?.bat?.[0],
color: "1",
color: 1,
opacity: 0.35,
},
]}
@@ -730,7 +731,7 @@ export default function SystemDetail({ name }: { name: string }) {
{
label: t`Usage`,
dataKey: ({ stats }) => stats?.g?.[id]?.u ?? 0,
color: "1",
color: 1,
opacity: 0.35,
},
]}
@@ -750,7 +751,7 @@ export default function SystemDetail({ name }: { name: string }) {
{
label: t`Usage`,
dataKey: ({ stats }) => stats?.g?.[id]?.mu ?? 0,
color: "2",
color: 2,
opacity: 0.25,
},
]}
@@ -802,13 +803,13 @@ export default function SystemDetail({ name }: { name: string }) {
{
label: t`Write`,
dataKey: ({ stats }) => stats?.efs?.[extraFsName]?.[showMax ? "wm" : "w"] ?? 0,
color: "3",
color: 3,
opacity: 0.3,
},
{
label: t`Read`,
dataKey: ({ stats }) => stats?.efs?.[extraFsName]?.[showMax ? "rm" : "r"] ?? 0,
color: "1",
color: 1,
opacity: 0.3,
},
]}

View File

@@ -23,12 +23,11 @@ import {
formatBytes,
formatTemperature,
getMeterState,
isReadOnlyUser,
parseSemVer,
} from "@/lib/utils"
import { EthernetIcon, GpuIcon, HourglassIcon, ThermometerIcon } from "../ui/icons"
import { useStore } from "@nanostores/react"
import { $userSettings, pb } from "@/lib/stores"
import { $userSettings } from "@/lib/stores"
import { Trans, useLingui } from "@lingui/react/macro"
import { useMemo, useRef, useState } from "react"
import { memo } from "react"
@@ -57,6 +56,7 @@ import { t } from "@lingui/core/macro"
import { MeterState, SystemStatus } from "@/lib/enums"
import { $router, Link } from "../router"
import { getPagePath } from "@nanostores/router"
import { isReadOnlyUser, pb } from "@/lib/api"
const STATUS_COLORS = {
[SystemStatus.Up]: "bg-green-500",

View File

@@ -11,11 +11,8 @@ import {
Row,
Table as TableType,
} from "@tanstack/react-table"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuCheckboxItem,
@@ -36,26 +33,31 @@ import {
ArrowUpIcon,
Settings2Icon,
EyeIcon,
FilterIcon,
} from "lucide-react"
import { memo, useEffect, useMemo, useState } from "react"
import { $systems } from "@/lib/stores"
import { useStore } from "@nanostores/react"
import { cn, useLocalStorage } from "@/lib/utils"
import { cn, runOnce, useLocalStorage } from "@/lib/utils"
import { $router, Link } from "../router"
import { useLingui, Trans } from "@lingui/react/macro"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"
import { Input } from "../ui/input"
import { Input } from "@/components/ui/input"
import { getPagePath } from "@nanostores/router"
import SystemsTableColumns, { ActionsButton, IndicatorDot } from "./systems-table-columns"
import AlertButton from "../alerts/alert-button"
import { SystemStatus } from "@/lib/enums"
type ViewMode = "table" | "grid"
type StatusFilter = "all" | "up" | "down" | "paused"
const preloadSystemDetail = runOnce(() => import("@/components/routes/system.tsx"))
export default function SystemsTable() {
const data = useStore($systems)
const { i18n, t } = useLingui()
const [filter, setFilter] = useState<string>()
const [statusFilter, setStatusFilter] = useState<StatusFilter>("all")
const [sorting, setSorting] = useState<SortingState>([{ id: "system", desc: false }])
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
const [columnVisibility, setColumnVisibility] = useLocalStorage<VisibilityState>("cols", {})
@@ -63,6 +65,14 @@ export default function SystemsTable() {
const locale = i18n.locale
// Filter data based on status filter
const filteredData = useMemo(() => {
if (statusFilter === "all") {
return data
}
return data.filter((system) => system.status === statusFilter)
}, [data, statusFilter])
useEffect(() => {
if (filter !== undefined) {
table.getColumn("system")?.setFilterValue(filter)
@@ -72,7 +82,7 @@ export default function SystemsTable() {
const columnDefs = useMemo(() => SystemsTableColumns(viewMode), [viewMode])
const table = useReactTable({
data,
data: filteredData,
columns: columnDefs,
getCoreRowModel: getCoreRowModel(),
onSortingChange: setSorting,
@@ -111,6 +121,7 @@ export default function SystemsTable() {
<Trans>Updated in real time. Click on a system to view information.</Trans>
</CardDescription>
</div>
<div className="flex gap-2 ms-auto w-full md:w-80">
<Input placeholder={t`Filter...`} onChange={(e) => setFilter(e.target.value)} className="px-4" />
<DropdownMenu>
@@ -121,8 +132,8 @@ export default function SystemsTable() {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="h-72 md:h-auto min-w-48 md:min-w-auto overflow-y-auto">
<div className="grid grid-cols-1 md:grid-cols-3 divide-y md:divide-s md:divide-y-0">
<div>
<div className="grid grid-cols-1 md:grid-cols-4 divide-y md:divide-s md:divide-y-0">
<div className="border-r">
<DropdownMenuLabel className="pt-2 px-3.5 flex items-center gap-2">
<LayoutGridIcon className="size-4" />
<Trans>Layout</Trans>
@@ -144,7 +155,33 @@ export default function SystemsTable() {
</DropdownMenuRadioGroup>
</div>
<div>
<div className="border-r">
<DropdownMenuLabel className="pt-2 px-3.5 flex items-center gap-2">
<FilterIcon className="size-4" />
<Trans>Status</Trans>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup
className="px-1 pb-1"
value={statusFilter}
onValueChange={(value) => setStatusFilter(value as StatusFilter)}
>
<DropdownMenuRadioItem value="all" onSelect={(e) => e.preventDefault()}>
<Trans>All Systems</Trans>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="up" onSelect={(e) => e.preventDefault()}>
<Trans>Up</Trans>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="down" onSelect={(e) => e.preventDefault()}>
<Trans>Down</Trans>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="paused" onSelect={(e) => e.preventDefault()}>
<Trans>Paused</Trans>
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</div>
<div className="border-r">
<DropdownMenuLabel className="pt-2 px-3.5 flex items-center gap-2">
<ArrowUpDownIcon className="size-4" />
<Trans>Sort By</Trans>
@@ -210,7 +247,7 @@ export default function SystemsTable() {
</div>
</CardHeader>
)
}, [visibleColumns.length, sorting, viewMode, locale])
}, [visibleColumns.length, sorting, viewMode, locale, statusFilter])
return (
<Card>
@@ -245,7 +282,7 @@ const AllSystemsTable = memo(
return (
<Table>
<SystemsTableHead table={table} colLength={colLength} />
<TableBody>
<TableBody onMouseEnter={preloadSystemDetail}>
{rows.length ? (
rows.map((row) => (
<SystemTableRow key={row.original.id} row={row} length={rows.length} colLength={colLength} />
@@ -321,6 +358,7 @@ const SystemCard = memo(
return useMemo(() => {
return (
<Card
onMouseEnter={preloadSystemDetail}
key={system.id}
className={cn(
"cursor-pointer hover:shadow-md transition-all bg-transparent w-full dark:border-border duration-200 relative",
@@ -331,7 +369,7 @@ const SystemCard = memo(
>
<CardHeader className="py-1 ps-5 pe-3 bg-muted/30 border-b border-border/60">
<div className="flex items-center justify-between gap-2">
<CardTitle className="text-base tracking-normal shrink-1 text-primary/90 flex items-center min-h-10 gap-2.5 min-w-0">
<CardTitle className="text-base tracking-normal shrink-1 text-primary/90 flex items-center min-w-0 gap-2.5">
<div className="flex items-center gap-2.5 min-w-0">
<IndicatorDot system={system} />
<CardTitle className="text-[.95em]/normal tracking-normal truncate text-primary/90">
@@ -356,7 +394,11 @@ const SystemCard = memo(
const { Icon, name } = column.columnDef as ColumnDef<SystemRecord, unknown>
return (
<div key={column.id} className="flex items-center gap-3">
{Icon && <Icon className="size-4 text-muted-foreground" />}
{column.id === "lastSeen" ? (
<EyeIcon className="size-4 text-muted-foreground" />
) : (
Icon && <Icon className="size-4 text-muted-foreground" />
)}
<div className="flex items-center gap-3 flex-1">
<span className="text-muted-foreground min-w-16">{name()}:</span>
<div className="flex-1">{flexRender(cell.column.columnDef.cell, cell.getContext())}</div>

View File

@@ -79,7 +79,7 @@ const DropdownMenuItem = React.forwardRef<
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
"relative flex select-none items-center rounded-sm px-2.5 py-1.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
"cursor-pointer relative flex select-none items-center rounded-sm px-2.5 py-1.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
inset && "ps-8",
className
)}
@@ -95,7 +95,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 ps-8 pe-2.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className
)}
checked={checked}
@@ -118,7 +118,7 @@ const DropdownMenuRadioItem = React.forwardRef<
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 ps-8 pe-2.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className
)}
{...props}

View File

@@ -2,21 +2,19 @@ import * as React from "react"
import { cn } from "@/lib/utils"
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, type, ...props }, ref) => {
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
<input
type={type}
data-slot="input"
className={cn(
"flex h-10 w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className
)}
ref={ref}
{...props}
/>
)
})
Input.displayName = "Input"
}
export { Input }

View File

@@ -1,9 +1,10 @@
import type { AlertInfo, AlertRecord } from "@/types"
import type { RecordSubscription } from "pocketbase"
import { pb, $alerts } from "@/lib/stores"
import { $alerts } from "@/lib/stores"
import { EthernetIcon } from "@/components/ui/icons"
import { ServerIcon, CpuIcon, MemoryStickIcon, HardDriveIcon, ThermometerIcon, HourglassIcon } from "lucide-react"
import { t } from "@lingui/core/macro"
import { pb } from "./api"
/** Alert info for each alert type */
export const alertInfo: Record<string, AlertInfo> = {

116
beszel/site/src/lib/api.ts Normal file
View File

@@ -0,0 +1,116 @@
import { ChartTimes, SystemRecord, UserSettings } from "@/types"
import { $alerts, $systems, $userSettings } from "./stores"
import { toast } from "@/components/ui/use-toast"
import { t } from "@lingui/core/macro"
import { chartTimeData } from "./utils"
import { WritableAtom } from "nanostores"
import { RecordModel, RecordSubscription } from "pocketbase"
import PocketBase from "pocketbase"
import { basePath } from "@/components/router"
/** PocketBase JS Client */
export const pb = new PocketBase(basePath)
export const isAdmin = () => pb.authStore.record?.role === "admin"
export const isReadOnlyUser = () => pb.authStore.record?.role === "readonly"
const verifyAuth = () => {
pb.collection("users")
.authRefresh()
.catch(() => {
logOut()
toast({
title: t`Failed to authenticate`,
description: t`Please log in again`,
variant: "destructive",
})
})
}
/** Logs the user out by clearing the auth store and unsubscribing from realtime updates. */
export async function logOut() {
$systems.set([])
$alerts.set({})
$userSettings.set({} as UserSettings)
sessionStorage.setItem("lo", "t") // prevent auto login on logout
pb.authStore.clear()
pb.realtime.unsubscribe()
}
/** Fetch or create user settings in database */
export async function updateUserSettings() {
try {
const req = await pb.collection("user_settings").getFirstListItem("", { fields: "settings" })
$userSettings.set(req.settings)
return
} catch (e) {
console.error("get settings", e)
}
// create user settings if error fetching existing
try {
const createdSettings = await pb.collection("user_settings").create({ user: pb.authStore.record!.id })
$userSettings.set(createdSettings.settings)
} catch (e) {
console.error("create settings", e)
}
}
/** Update systems / alerts list when records change */
export function updateRecordList<T extends RecordModel>(e: RecordSubscription<T>, $store: WritableAtom<T[]>) {
const curRecords = $store.get()
const newRecords = []
if (e.action === "delete") {
for (const server of curRecords) {
if (server.id !== e.record.id) {
newRecords.push(server)
}
}
} else {
let found = 0
for (const server of curRecords) {
if (server.id === e.record.id) {
found = newRecords.push(e.record)
} else {
newRecords.push(server)
}
}
if (!found) {
newRecords.push(e.record)
}
}
$store.set(newRecords)
}
/** Fetches updated system list from database */
export const updateSystemList = (() => {
let isFetchingSystems = false
return async () => {
if (isFetchingSystems) {
return
}
isFetchingSystems = true
try {
const records = await pb
.collection<SystemRecord>("systems")
.getFullList({ sort: "+name", fields: "id,name,host,port,info,status" })
if (records.length) {
$systems.set(records)
} else {
verifyAuth()
}
} finally {
isFetchingSystems = false
}
}
})()
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")
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}

View File

@@ -1,11 +1,7 @@
import PocketBase from "pocketbase"
import { atom, map } from "nanostores"
import { AlertMap, ChartTimes, SystemRecord, UserSettings } from "@/types"
import { basePath } from "@/components/router"
import { Unit } from "./enums"
/** PocketBase JS Client */
export const pb = new PocketBase(basePath)
import { pb } from "./api"
/** Store if user is authenticated */
export const $authenticated = atom(pb.authStore.isValid)

View File

@@ -2,14 +2,12 @@ import { t } from "@lingui/core/macro"
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 type { ChartTimeData, ChartTimes, FingerprintRecord, SemVer, SystemRecord, UserSettings } from "@/types"
import { RecordModel, RecordSubscription } from "pocketbase"
import { WritableAtom } from "nanostores"
import { $copyContent, $systems, $userSettings } from "./stores"
import type { ChartTimeData, FingerprintRecord, SemVer, SystemRecord } from "@/types"
import { timeDay, timeHour } from "d3-time"
import { useEffect, useState } from "react"
import { prependBasePath } from "@/components/router"
import { MeterState, Unit } from "./enums"
import { prependBasePath } from "@/components/router"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
@@ -34,52 +32,6 @@ export async function copyToClipboard(content: string) {
}
}
const verifyAuth = () => {
pb.collection("users")
.authRefresh()
.catch(() => {
logOut()
toast({
title: t`Failed to authenticate`,
description: t`Please log in again`,
variant: "destructive",
})
})
}
export const updateSystemList = (() => {
let isFetchingSystems = false
return async () => {
if (isFetchingSystems) {
return
}
isFetchingSystems = true
try {
const records = await pb
.collection<SystemRecord>("systems")
.getFullList({ sort: "+name", fields: "id,name,host,port,info,status" })
if (records.length) {
$systems.set(records)
} else {
verifyAuth()
}
} finally {
isFetchingSystems = false
}
}
})()
/** Logs the user out by clearing the auth store and unsubscribing from realtime updates. */
export async function logOut() {
$systems.set([])
$alerts.set({})
$userSettings.set({} as UserSettings)
sessionStorage.setItem("lo", "t") // prevent auto login on logout
pb.authStore.clear()
pb.realtime.unsubscribe()
}
const hourWithMinutesFormatter = new Intl.DateTimeFormat(undefined, {
hour: "numeric",
minute: "numeric",
@@ -110,47 +62,6 @@ export const updateFavicon = (newIcon: string) => {
;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = prependBasePath(`/static/${newIcon}`)
}
export const isAdmin = () => pb.authStore.record?.role === "admin"
export const isReadOnlyUser = () => pb.authStore.record?.role === "readonly"
/** Update systems / alerts list when records change */
export function updateRecordList<T extends RecordModel>(e: RecordSubscription<T>, $store: WritableAtom<T[]>) {
const curRecords = $store.get()
const newRecords = []
if (e.action === "delete") {
for (const server of curRecords) {
if (server.id !== e.record.id) {
newRecords.push(server)
}
}
} else {
let found = 0
for (const server of curRecords) {
if (server.id === e.record.id) {
found = newRecords.push(e.record)
} else {
newRecords.push(server)
}
}
if (!found) {
newRecords.push(e.record)
}
}
$store.set(newRecords)
}
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")
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
export const chartTimeData: ChartTimeData = {
"1h": {
type: "1m",
@@ -329,24 +240,6 @@ export function formatBytes(
}
}
/** Fetch or create user settings in database */
export async function updateUserSettings() {
try {
const req = await pb.collection("user_settings").getFirstListItem("", { fields: "settings" })
$userSettings.set(req.settings)
return
} catch (e) {
console.error("get settings", e)
}
// create user settings if error fetching existing
try {
const createdSettings = await pb.collection("user_settings").create({ user: pb.authStore.record!.id })
$userSettings.set(createdSettings.settings)
} catch (e) {
console.error("create settings", e)
}
}
export const chartMargin = { top: 12 }
/**
@@ -357,6 +250,21 @@ export const chartMargin = { top: 12 }
*/
export const getHostDisplayValue = (system: SystemRecord): string => system.host.slice(system.host.lastIndexOf("/") + 1)
// export function formatUptimeString(uptimeSeconds: number): string {
// if (!uptimeSeconds || isNaN(uptimeSeconds)) return ""
// if (uptimeSeconds < 3600) {
// const minutes = Math.trunc(uptimeSeconds / 60)
// return plural({ minutes }, { one: "# minute", other: "# minutes" })
// } else if (uptimeSeconds < 172800) {
// const hours = Math.trunc(uptimeSeconds / 3600)
// console.log(hours)
// return plural({ hours }, { one: "# hour", other: "# hours" })
// } else {
// const days = Math.trunc(uptimeSeconds / 86400)
// return plural({ days }, { one: "# day", other: "# days" })
// }
// }
/** Generate a random token for the agent */
export const generateToken = () => {
try {
@@ -448,3 +356,16 @@ export const getSystemNameFromId = (() => {
return sysName
}
})()
/** Run a function only once */
export function runOnce<T extends (...args: any[]) => any>(fn: T): (...args: Parameters<T>) => ReturnType<T> {
let done = false
let result: any
return (...args: any) => {
if (!done) {
result = fn(...args)
done = true
}
return result
}
}

View File

@@ -33,6 +33,10 @@ msgstr "تم تحديد {0} من {1} صف"
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# ساعة} other {# ساعات}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 ساعة"
@@ -125,6 +129,7 @@ msgstr "التنبيهات"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "جميع الأنظمة"
@@ -422,6 +427,7 @@ msgstr "التوثيق"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "معطل"
@@ -492,7 +498,7 @@ msgstr "تصدير تكوين الأنظمة الحالية الخاصة بك."
msgid "Fahrenheit (°F)"
msgstr "فهرنهايت (°ف)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "فشل في المصادقة"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "إيقاف مؤقت"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "متوقف مؤقتا"
@@ -774,7 +781,7 @@ msgstr "يرجى إنشاء حساب مسؤول"
msgid "Please enable pop-ups for this site"
msgstr "يرجى تمكين النوافذ المنبثقة لهذا الموقع"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "يرجى تسجيل الدخول مرة أخرى"
@@ -901,6 +908,7 @@ msgstr "الترتيب حسب"
msgid "State"
msgstr "الحالة"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "الحالة"
@@ -1067,6 +1075,7 @@ msgstr "غير معروفة"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "قيد التشغيل"

View File

@@ -33,6 +33,10 @@ msgstr "{0} от {1} селектирани."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# час} other {# часа}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 час"
@@ -125,6 +129,7 @@ msgstr "Тревоги"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Всички системи"
@@ -422,6 +427,7 @@ msgstr "Документация"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Офлайн"
@@ -492,7 +498,7 @@ msgstr "Експортирай конфигурацията на системи
msgid "Fahrenheit (°F)"
msgstr "Фаренхайт (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Неуспешно удостоверяване"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Пауза"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "На пауза"
@@ -774,7 +781,7 @@ msgstr "Моля създай администраторски акаунт"
msgid "Please enable pop-ups for this site"
msgstr "Моля активирай изскачащите прозорци за този сайт"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Моля влез отново"
@@ -901,6 +908,7 @@ msgstr "Сортиране по"
msgid "State"
msgstr "Състояние"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Статус"
@@ -1067,6 +1075,7 @@ msgstr "Неизвестна"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Нагоре"

View File

@@ -33,6 +33,10 @@ msgstr "{0} z {1} vybraných řádků."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# Hodina} few {# Hodiny} many {# Hodin} other {# Hodin}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 hodina"
@@ -125,6 +129,7 @@ msgstr "Výstrahy"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Všechny systémy"
@@ -422,6 +427,7 @@ msgstr "Dokumentace"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Nefunkční"
@@ -492,7 +498,7 @@ msgstr "Exportovat aktuální konfiguraci systémů."
msgid "Fahrenheit (°F)"
msgstr "Fahrenheita (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Ověření se nezdařilo"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pozastavit"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Pozastaveno"
@@ -774,7 +781,7 @@ msgstr "Vytvořte si prosím účet administrátora"
msgid "Please enable pop-ups for this site"
msgstr "Prosím povolte vyskakovací okna pro tento web"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Přihlaste se prosím znovu"
@@ -901,6 +908,7 @@ msgstr "Seřadit podle"
msgid "State"
msgstr "Stav"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Stav"
@@ -1067,6 +1075,7 @@ msgstr "Neznámá"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Funkční"

View File

@@ -33,6 +33,10 @@ msgstr ""
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# hour} other {# hours}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 time"
@@ -125,6 +129,7 @@ msgstr "Alarmer"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Alle systemer"
@@ -422,6 +427,7 @@ msgstr "Dokumentation"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Nede"
@@ -492,7 +498,7 @@ msgstr "Eksporter din nuværende systemkonfiguration."
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Kunne ikke godkende"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pause"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Sat på pause"
@@ -774,7 +781,7 @@ msgstr "Opret venligst en administratorkonto"
msgid "Please enable pop-ups for this site"
msgstr "Aktiver pop-ups for dette websted"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Log venligst ind igen"
@@ -901,6 +908,7 @@ msgstr "Sorter efter"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1067,6 +1075,7 @@ msgstr "Ukendt"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Oppe"

View File

@@ -33,6 +33,10 @@ msgstr "{0} von {1} Zeile(n) ausgewählt."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# Stunde} other {# Stunden}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 Stunde"
@@ -125,6 +129,7 @@ msgstr "Warnungen"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Alle Systeme"
@@ -422,6 +427,7 @@ msgstr "Dokumentation"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Offline"
@@ -492,7 +498,7 @@ msgstr "Exportiere die aktuelle Systemkonfiguration."
msgid "Fahrenheit (°F)"
msgstr "Fahrenheit (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Authentifizierung fehlgeschlagen"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pause"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Pausiert"
@@ -774,7 +781,7 @@ msgstr "Bitte erstelle ein Administratorkonto"
msgid "Please enable pop-ups for this site"
msgstr "Bitte aktiviere Pop-ups für diese Seite"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Bitte melde dich erneut an"
@@ -901,6 +908,7 @@ msgstr "Sortieren nach"
msgid "State"
msgstr "Status"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1067,6 +1075,7 @@ msgstr "Unbekannt"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "aktiv"

View File

@@ -28,6 +28,10 @@ msgstr "{0} of {1} row(s) selected."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# hour} other {# hours}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr "{mins, plural, one {# minute} other {# minutes}}"
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 hour"
@@ -120,6 +124,7 @@ msgstr "Alerts"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "All Systems"
@@ -417,6 +422,7 @@ msgstr "Documentation"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Down"
@@ -487,7 +493,7 @@ msgstr "Export your current systems configuration."
msgid "Fahrenheit (°F)"
msgstr "Fahrenheit (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Failed to authenticate"
@@ -745,6 +751,7 @@ msgid "Pause"
msgstr "Pause"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Paused"
@@ -769,7 +776,7 @@ msgstr "Please create an admin account"
msgid "Please enable pop-ups for this site"
msgstr "Please enable pop-ups for this site"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Please log in again"
@@ -896,6 +903,7 @@ msgstr "Sort By"
msgid "State"
msgstr "State"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1062,6 +1070,7 @@ msgstr "Unknown"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Up"

View File

@@ -33,6 +33,10 @@ msgstr "{0} de {1} fila(s) seleccionada(s)."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# hora} other {# horas}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 hora"
@@ -125,6 +129,7 @@ msgstr "Alertas"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Todos los Sistemas"
@@ -422,6 +427,7 @@ msgstr "Documentación"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Abajo"
@@ -492,7 +498,7 @@ msgstr "Exporte la configuración actual de sus sistemas."
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Error al autenticar"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pausar"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Pausado"
@@ -774,7 +781,7 @@ msgstr "Por favor, cree una cuenta de administrador"
msgid "Please enable pop-ups for this site"
msgstr "Por favor, habilite las ventanas emergentes para este sitio"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Por favor, inicie sesión de nuevo"
@@ -901,6 +908,7 @@ msgstr "Ordenar por"
msgid "State"
msgstr "Estado"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Estado"
@@ -1067,6 +1075,7 @@ msgstr "Desconocida"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Activo"

View File

@@ -33,6 +33,10 @@ msgstr "{0} از {1} ردیف انتخاب شده است."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# ساعت} other {# ساعت}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "۱ ساعت"
@@ -125,6 +129,7 @@ msgstr "هشدارها"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "همه سیستم‌ها"
@@ -422,6 +427,7 @@ msgstr "مستندات"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "قطع"
@@ -492,7 +498,7 @@ msgstr "پیکربندی سیستم‌های فعلی خود را خارج کن
msgid "Fahrenheit (°F)"
msgstr "فارنهایت (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "احراز هویت ناموفق بود"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "توقف"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "مکث شده"
@@ -774,7 +781,7 @@ msgstr "لطفاً یک حساب مدیر ایجاد کنید"
msgid "Please enable pop-ups for this site"
msgstr "لطفاً پنجره‌های بازشو را برای این سایت فعال کنید"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "لطفاً دوباره وارد شوید"
@@ -901,6 +908,7 @@ msgstr "مرتب‌سازی بر اساس"
msgid "State"
msgstr "وضعیت"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "وضعیت"
@@ -1067,6 +1075,7 @@ msgstr "ناشناخته"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "فعال"

View File

@@ -33,6 +33,10 @@ msgstr ""
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# heure} other {# heures}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 heure"
@@ -125,6 +129,7 @@ msgstr "Alertes"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Tous les systèmes"
@@ -422,6 +427,7 @@ msgstr "Documentation"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Injoignable"
@@ -492,7 +498,7 @@ msgstr "Exportez la configuration actuelle de vos systèmes."
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Échec de l'authentification"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pause"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "En pause"
@@ -774,7 +781,7 @@ msgstr "Veuillez créer un compte administrateur"
msgid "Please enable pop-ups for this site"
msgstr "Veuillez activer les pop-ups pour ce site"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Veuillez vous reconnecter"
@@ -901,6 +908,7 @@ msgstr "Trier par"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Statut"
@@ -1067,6 +1075,7 @@ msgstr "Inconnue"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Joignable"

View File

@@ -33,6 +33,10 @@ msgstr ""
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# sat} other {# sati}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 sat"
@@ -125,6 +129,7 @@ msgstr "Upozorenja"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Svi Sistemi"
@@ -422,6 +427,7 @@ msgstr "Dokumentacija"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr ""
@@ -492,7 +498,7 @@ msgstr "Izvoz trenutne sistemske konfiguracije."
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Provjera autentičnosti nije uspjela"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pauza"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Pauzirano"
@@ -774,7 +781,7 @@ msgstr "Molimo kreirajte administratorski račun"
msgid "Please enable pop-ups for this site"
msgstr "Omogućite skočne prozore za ovu stranicu"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Molimo prijavite se ponovno"
@@ -901,6 +908,7 @@ msgstr "Sortiraj po"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1067,6 +1075,7 @@ msgstr "Nepoznata"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr ""

View File

@@ -33,6 +33,10 @@ msgstr ""
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# óra} other {# óra}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 óra"
@@ -125,6 +129,7 @@ msgstr "Riasztások"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Minden rendszer"
@@ -422,6 +427,7 @@ msgstr "Dokumentáció"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr ""
@@ -492,7 +498,7 @@ msgstr "Exportálja a jelenlegi rendszerkonfigurációt."
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Hitelesítés sikertelen"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Szüneteltetés"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Szüneteltetve"
@@ -774,7 +781,7 @@ msgstr "Kérjük, hozzon létre egy admin fiókot"
msgid "Please enable pop-ups for this site"
msgstr "Kérjük, engedélyezze a felugró ablakokat ezen az oldalon"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Kérjük jelentkezz be újra"
@@ -901,6 +908,7 @@ msgstr "Rendezés"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Állapot"
@@ -1067,6 +1075,7 @@ msgstr "Ismeretlen"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr ""

View File

@@ -33,6 +33,10 @@ msgstr ""
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# klukkustund} other {# klukkustundir}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 klukkustund"
@@ -125,6 +129,7 @@ msgstr "Tilkynningar"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Öll kerfi"
@@ -422,6 +427,7 @@ msgstr "Skjal"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr ""
@@ -492,7 +498,7 @@ msgstr ""
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Villa í auðkenningu"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pása"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Í bið"
@@ -774,7 +781,7 @@ msgstr "Vinsamlegast búðu til admin aðgang"
msgid "Please enable pop-ups for this site"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Vinsamlegast skráðu þið inn aftur"
@@ -901,6 +908,7 @@ msgstr "Raða eftir"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Staða"
@@ -1067,6 +1075,7 @@ msgstr "Óþekkt"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr ""

View File

@@ -33,6 +33,10 @@ msgstr "{0} di {1} righe selezionate."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# ora} other {# ore}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 ora"
@@ -125,6 +129,7 @@ msgstr "Avvisi"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Tutti i Sistemi"
@@ -422,6 +427,7 @@ msgstr "Documentazione"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Offline"
@@ -492,7 +498,7 @@ msgstr "Esporta la configurazione attuale dei tuoi sistemi."
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Autenticazione fallita"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pausa"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "In pausa"
@@ -774,7 +781,7 @@ msgstr "Si prega di creare un account amministratore"
msgid "Please enable pop-ups for this site"
msgstr "Si prega di abilitare i pop-up per questo sito"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Si prega di accedere nuovamente"
@@ -901,6 +908,7 @@ msgstr "Ordina per"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Stato"
@@ -1067,6 +1075,7 @@ msgstr "Sconosciuta"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Attivo"

View File

@@ -33,6 +33,10 @@ msgstr "{1}行のうち{0}行が選択されました。"
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# 時間} other {# 時間}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1時間"
@@ -125,6 +129,7 @@ msgstr "アラート"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "すべてのシステム"
@@ -422,6 +427,7 @@ msgstr "ドキュメント"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "停止"
@@ -492,7 +498,7 @@ msgstr "現在のシステム設定をエクスポートします。"
msgid "Fahrenheit (°F)"
msgstr "華氏 (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "認証に失敗しました"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "一時停止"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "一時停止中"
@@ -774,7 +781,7 @@ msgstr "管理者アカウントを作成してください"
msgid "Please enable pop-ups for this site"
msgstr "このサイトのポップアップを有効にしてください"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "再度ログインしてください"
@@ -901,6 +908,7 @@ msgstr "並び替え基準"
msgid "State"
msgstr "状態"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "ステータス"
@@ -1067,6 +1075,7 @@ msgstr "不明"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "正常"

View File

@@ -33,6 +33,10 @@ msgstr "{1}개의 행 중 {0}개가 선택되었습니다."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# 시간} other {# 시간}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1시간"
@@ -125,6 +129,7 @@ msgstr "알림"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "모든 시스템"
@@ -422,6 +427,7 @@ msgstr "문서"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "오프라인"
@@ -492,7 +498,7 @@ msgstr "현재 시스템 구성 내보내기"
msgid "Fahrenheit (°F)"
msgstr "화씨 (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "인증 실패"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "일시 중지"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "일시 정지됨"
@@ -774,7 +781,7 @@ msgstr "관리자 계정을 생성하세요."
msgid "Please enable pop-ups for this site"
msgstr "이 사이트에 대해 팝업을 활성화하세요."
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "다시 로그인하세요."
@@ -901,6 +908,7 @@ msgstr "정렬 기준"
msgid "State"
msgstr "상태"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "상태"
@@ -1067,6 +1075,7 @@ msgstr "알 수 없음"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "온라인"

View File

@@ -33,6 +33,10 @@ msgstr "{0} van de {1} rij(en) geselecteerd."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# uur} other {# uren}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 uur"
@@ -125,6 +129,7 @@ msgstr "Waarschuwingen"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Alle systemen"
@@ -422,6 +427,7 @@ msgstr "Documentatie"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Offline"
@@ -492,7 +498,7 @@ msgstr "Exporteer je huidige systeemconfiguratie."
msgid "Fahrenheit (°F)"
msgstr "Fahrenheit (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Authenticatie mislukt"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pauze"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Gepauzeerd"
@@ -774,7 +781,7 @@ msgstr "Maak een beheerdersaccount aan"
msgid "Please enable pop-ups for this site"
msgstr "Activeer pop-ups voor deze website"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Meld je opnieuw aan"
@@ -901,6 +908,7 @@ msgstr "Sorteren op"
msgid "State"
msgstr "Status"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1067,6 +1075,7 @@ msgstr "Onbekend"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Online"

View File

@@ -33,6 +33,10 @@ msgstr ""
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# time} other {# timer}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 time"
@@ -125,6 +129,7 @@ msgstr "Alarmer"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Alle Systemer"
@@ -422,6 +427,7 @@ msgstr "Dokumentasjon"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Nede"
@@ -492,7 +498,7 @@ msgstr "Eksporter din nåværende systemkonfigurasjon"
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Autentisering mislyktes"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pause"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Satt på Pause"
@@ -774,7 +781,7 @@ msgstr "Vennligst opprett en admin-konto"
msgid "Please enable pop-ups for this site"
msgstr "Vennligst aktiver pop-ups for nettsiden"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Vennligst logg inn på nytt"
@@ -901,6 +908,7 @@ msgstr "Sorter Etter"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1067,6 +1075,7 @@ msgstr "Ukjent"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Oppe"

View File

@@ -33,6 +33,10 @@ msgstr "{0} z {1} wybranych wierszy."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {godzinę} few {# godziny} many {# godzin} other {# godziny}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 godzina"
@@ -125,6 +129,7 @@ msgstr "Alerty"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Wszystkie systemy"
@@ -422,6 +427,7 @@ msgstr "Dokumentacja"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Nie działa"
@@ -492,7 +498,7 @@ msgstr "Eksportuj aktualną konfigurację systemów."
msgid "Fahrenheit (°F)"
msgstr "Fahrenheit (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Błąd autoryzacji"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pauza"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Wstrzymane"
@@ -774,7 +781,7 @@ msgstr "Utwórz konto administratora"
msgid "Please enable pop-ups for this site"
msgstr "Włącz wyskakujące okna dla tej strony"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Zaloguj się ponownie"
@@ -901,6 +908,7 @@ msgstr "Sortuj według"
msgid "State"
msgstr "Stan"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1067,6 +1075,7 @@ msgstr "Nieznana"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Działa"

View File

@@ -33,6 +33,10 @@ msgstr ""
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# hora} other {# horas}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 hora"
@@ -125,6 +129,7 @@ msgstr "Alertas"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Todos os Sistemas"
@@ -422,6 +427,7 @@ msgstr "Documentação"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "“Desligado”"
@@ -492,7 +498,7 @@ msgstr "Exporte a configuração atual dos seus sistemas."
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Falha na autenticação"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Pausar"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Pausado"
@@ -774,7 +781,7 @@ msgstr "Por favor, crie uma conta de administrador"
msgid "Please enable pop-ups for this site"
msgstr "Por favor, habilite pop-ups para este site"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Por favor, faça login novamente"
@@ -901,6 +908,7 @@ msgstr "Ordenar Por"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1067,6 +1075,7 @@ msgstr "Desconhecida"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "“Ligado”"

View File

@@ -33,6 +33,10 @@ msgstr "Выбрано {0} из {1} строк."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# час} other {# часов}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 час"
@@ -125,6 +129,7 @@ msgstr "Оповещения"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Все системы"
@@ -422,6 +427,7 @@ msgstr "Документация"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Не в сети"
@@ -492,7 +498,7 @@ msgstr "Экспортируйте текущую конфигурацию си
msgid "Fahrenheit (°F)"
msgstr "Фаренгейт (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Не удалось аутентифицировать"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Пауза"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Пауза"
@@ -774,7 +781,7 @@ msgstr "Пожалуйста, создайте учетную запись ад
msgid "Please enable pop-ups for this site"
msgstr "Пожалуйста, включите всплывающие окна для этого сайта"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Пожалуйста, войдите снова"
@@ -901,6 +908,7 @@ msgstr "Сортировать по"
msgid "State"
msgstr "Состояние"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Статус"
@@ -1067,6 +1075,7 @@ msgstr "Неизвестная"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "В сети"

View File

@@ -33,6 +33,10 @@ msgstr ""
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# ura} two {# uri} few {# ur} other {# ur}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 ura"
@@ -125,6 +129,7 @@ msgstr "Opozorila"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Vsi sistemi"
@@ -422,6 +427,7 @@ msgstr "Dokumentacija"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr ""
@@ -492,7 +498,7 @@ msgstr "Izvozi trenutne nastavitve sistema."
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Preverjanje pristnosti ni uspelo"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Premor"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Zaustavljeno"
@@ -774,7 +781,7 @@ msgstr "Ustvarite skrbniški račun"
msgid "Please enable pop-ups for this site"
msgstr "Omogočite pojavna okna za to spletno mesto"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Prosimo, prijavite se znova"
@@ -901,6 +908,7 @@ msgstr "Razvrsti po"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1067,6 +1075,7 @@ msgstr "Neznana"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr ""

View File

@@ -33,6 +33,10 @@ msgstr "{0} av {1} rad(er) valda."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# timme} other {# timmar}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 timme"
@@ -125,6 +129,7 @@ msgstr "Larm"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Alla system"
@@ -422,6 +427,7 @@ msgstr "Dokumentation"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr ""
@@ -492,7 +498,7 @@ msgstr "Exportera din nuvarande systemkonfiguration."
msgid "Fahrenheit (°F)"
msgstr ""
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Autentisering misslyckades"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Paus"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Pausad"
@@ -774,7 +781,7 @@ msgstr "Vänligen skapa ett administratörskonto"
msgid "Please enable pop-ups for this site"
msgstr "Vänligen aktivera popup-fönster för den här webbplatsen"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Vänligen logga in igen"
@@ -901,6 +908,7 @@ msgstr "Sortera efter"
msgid "State"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Status"
@@ -1067,6 +1075,7 @@ msgstr "Okänd"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr ""

View File

@@ -33,6 +33,10 @@ msgstr "{1} satırdan {0} tanesi seçildi."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# saat} other {# saat}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 saat"
@@ -125,6 +129,7 @@ msgstr "Uyarılar"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Tüm Sistemler"
@@ -422,6 +427,7 @@ msgstr "Dokümantasyon"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Kapalı"
@@ -492,7 +498,7 @@ msgstr "Mevcut sistem yapılandırmanızı dışa aktarın."
msgid "Fahrenheit (°F)"
msgstr "Fahrenhayt (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Kimlik doğrulama başarısız"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Duraklat"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Duraklatıldı"
@@ -774,7 +781,7 @@ msgstr "Lütfen bir yönetici hesabı oluşturun"
msgid "Please enable pop-ups for this site"
msgstr "Lütfen bu site için açılır pencereleri etkinleştirin"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Lütfen tekrar giriş yapın"
@@ -901,6 +908,7 @@ msgstr "Sıralama Ölçütü"
msgid "State"
msgstr "Durum"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Durum"
@@ -1067,6 +1075,7 @@ msgstr ""
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Açık"

View File

@@ -33,6 +33,10 @@ msgstr "Вибрано {0} з {1} рядків."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# година} few {# години} many {# годин} other {# години}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 година"
@@ -125,6 +129,7 @@ msgstr "Сповіщення"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Всі системи"
@@ -422,6 +427,7 @@ msgstr "Документація"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Не працює"
@@ -492,7 +498,7 @@ msgstr "Експортуйте поточну конфігурацію сист
msgid "Fahrenheit (°F)"
msgstr "Фаренгейт (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Не вдалося автентифікувати"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Призупинити"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Призупинено"
@@ -774,7 +781,7 @@ msgstr "Будь ласка, створіть адміністративний
msgid "Please enable pop-ups for this site"
msgstr "Будь ласка, увімкніть спливаючі вікна для цього сайту"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Будь ласка, увійдіть знову"
@@ -901,6 +908,7 @@ msgstr "Сортувати за"
msgid "State"
msgstr "Стан"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Статус"
@@ -1067,6 +1075,7 @@ msgstr "Невідома"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Працює"

View File

@@ -33,6 +33,10 @@ msgstr "Đã chọn {0} trên {1} hàng."
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# giờ} other {# giờ}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1 giờ"
@@ -125,6 +129,7 @@ msgstr "Cảnh báo"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "Tất cả Hệ thống"
@@ -422,6 +427,7 @@ msgstr "Tài liệu"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Mất kết nối"
@@ -492,7 +498,7 @@ msgstr "Xuất cấu hình hệ thống hiện tại của bạn."
msgid "Fahrenheit (°F)"
msgstr "Độ F (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "Xác thực thất bại"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "Tạm dừng"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "Đã tạm dừng"
@@ -774,7 +781,7 @@ msgstr "Vui lòng tạo một tài khoản quản trị viên"
msgid "Please enable pop-ups for this site"
msgstr "Vui lòng bật cửa sổ bật lên cho trang web này"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "Vui lòng đăng nhập lại"
@@ -901,6 +908,7 @@ msgstr "Sắp xếp theo"
msgid "State"
msgstr "Trạng thái"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "Trạng thái"
@@ -1067,6 +1075,7 @@ msgstr "Không xác định"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "Hoạt động"

View File

@@ -33,6 +33,10 @@ msgstr "已选择 {0} / {1} 行"
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# 小时} other {# 小时}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1小时"
@@ -125,6 +129,7 @@ msgstr "警报"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "所有客户端"
@@ -422,6 +427,7 @@ msgstr "文档"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "离线"
@@ -492,7 +498,7 @@ msgstr "导出您当前的系统配置。"
msgid "Fahrenheit (°F)"
msgstr "华氏度 (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "认证失败"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "暂停"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "已暂停"
@@ -774,7 +781,7 @@ msgstr "请创建一个管理员账户"
msgid "Please enable pop-ups for this site"
msgstr "请为此网站启用弹出窗口"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "请重新登录"
@@ -901,6 +908,7 @@ msgstr "排序依据"
msgid "State"
msgstr "状态"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "状态"
@@ -1067,6 +1075,7 @@ msgstr "未知"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "在线"

View File

@@ -33,6 +33,10 @@ msgstr "已選擇 {1} 個項目中的 {0} 個"
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# 小時} other {# 小時}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1小時"
@@ -125,6 +129,7 @@ msgstr "警報"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "所有系統"
@@ -422,6 +427,7 @@ msgstr "文件"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "中斷"
@@ -492,7 +498,7 @@ msgstr "匯出您現在的系統設定。"
msgid "Fahrenheit (°F)"
msgstr "華氏 (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "認證失敗"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "暫停"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "已暫停"
@@ -774,7 +781,7 @@ msgstr "請建立一個管理員帳號"
msgid "Please enable pop-ups for this site"
msgstr "請為此網站啟用彈出窗口"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "請重新登入"
@@ -901,6 +908,7 @@ msgstr "排序依據"
msgid "State"
msgstr "狀態"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "狀態"
@@ -1067,6 +1075,7 @@ msgstr "未知"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "上線"

View File

@@ -33,6 +33,10 @@ msgstr "已選取 {1} 個項目中的 {0} 個"
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# 小時} other {# 小時}}"
#: src/components/routes/system.tsx
msgid "{mins, plural, one {# minute} other {# minutes}}"
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
msgstr "1小時"
@@ -125,6 +129,7 @@ msgstr "警報"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
msgid "All Systems"
msgstr "所有系統"
@@ -422,6 +427,7 @@ msgstr "文件"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "離線"
@@ -492,7 +498,7 @@ msgstr "匯出您現在的系統設定。"
msgid "Fahrenheit (°F)"
msgstr "華氏 (°F)"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Failed to authenticate"
msgstr "認證失敗"
@@ -750,6 +756,7 @@ msgid "Pause"
msgstr "暫停"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Paused"
msgstr "已暫停"
@@ -774,7 +781,7 @@ msgstr "請建立一個管理員帳號"
msgid "Please enable pop-ups for this site"
msgstr "請為此網站啟用彈出視窗"
#: src/lib/utils.ts
#: src/lib/api.ts
msgid "Please log in again"
msgstr "請重新登入"
@@ -901,6 +908,7 @@ msgstr "排序"
msgid "State"
msgstr "狀態"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr "狀態"
@@ -1067,6 +1075,7 @@ msgstr "未知"
#. Context: System is up
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Up"
msgstr "上線"

View File

@@ -2,26 +2,26 @@ import "./index.css"
// import { Suspense, lazy, useEffect, StrictMode } from "react"
import { Suspense, lazy, memo, useEffect } from "react"
import ReactDOM from "react-dom/client"
import Home from "./components/routes/home.tsx"
import { ThemeProvider } from "./components/theme-provider.tsx"
import { DirectionProvider } from "@radix-ui/react-direction"
import { $authenticated, $systems, pb, $publicKey, $copyContent, $direction } from "./lib/stores.ts"
import { updateUserSettings, updateFavicon, updateSystemList } from "./lib/utils.ts"
import { $authenticated, $systems, $publicKey, $copyContent, $direction } from "./lib/stores.ts"
import { pb, updateSystemList, updateUserSettings } from "./lib/api.ts"
import { useStore } from "@nanostores/react"
import { Toaster } from "./components/ui/toaster.tsx"
import { $router } from "./components/router.tsx"
import SystemDetail from "./components/routes/system.tsx"
import { updateFavicon } from "@/lib/utils"
import Navbar from "./components/navbar.tsx"
import { I18nProvider } from "@lingui/react"
import { i18n } from "@lingui/core"
import { getLocale, dynamicActivate } from "./lib/i18n"
import { SystemStatus } from "./lib/enums"
import { alertManager } from "./lib/alerts"
import Settings from "./components/routes/settings/layout.tsx"
// const ServerDetail = lazy(() => import('./components/routes/system.tsx'))
const LoginPage = lazy(() => import("./components/login/login.tsx"))
const CopyToClipboardDialog = lazy(() => import("./components/copy-to-clipboard.tsx"))
const Settings = lazy(() => import("./components/routes/settings/layout.tsx"))
const LoginPage = lazy(() => import("@/components/login/login.tsx"))
const Home = lazy(() => import("@/components/routes/home.tsx"))
const SystemDetail = lazy(() => import("@/components/routes/system.tsx"))
const CopyToClipboardDialog = lazy(() => import("@/components/copy-to-clipboard.tsx"))
const App = memo(() => {
const page = useStore($router)
@@ -78,11 +78,7 @@ const App = memo(() => {
} else if (page.route === "system") {
return <SystemDetail name={page.params.name} />
} else if (page.route === "settings") {
return (
<Suspense>
<Settings />
</Suspense>
)
return <Settings />
}
})

View File

@@ -29,6 +29,7 @@ export interface SystemRecord extends RecordModel {
port: string
info: SystemInfo
v: string
updated: string
}
export interface SystemInfo {
@@ -98,6 +99,8 @@ export interface SystemStats {
mp: number
/** memory buffer + cache (gb) */
mb: number
/** max used memory (gb) */
mm?: number
/** zfs arc memory (gb) */
mz?: number
/** swap space (gb) */

View File

@@ -0,0 +1,93 @@
import { memo, useMemo } from "react"
import { Row, TableType } from "@tanstack/react-table"
import { useLingui } from "@lingui/react"
import { cn } from "@/lib/utils"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Link } from "@/components/ui/link"
import { getPagePath } from "@/lib/page-path"
import { useRouter } from "next/router"
import { flexRender } from "@tanstack/react-table"
import { ColumnDef } from "@tanstack/table-core"
import { SystemRecord } from "@/lib/types"
import { IndicatorDot } from "@/components/indicator-dot"
import { AlertsButton } from "@/components/alerts-button"
import { ActionsButton } from "@/components/actions-button"
import { EyeIcon } from "@/components/icons"
const SystemCard = memo(
({ row, table, colLength }: { row: Row<SystemRecord>; table: TableType<SystemRecord>; colLength: number }) => {
const system = row.original
const { t } = useLingui()
return useMemo(() => {
return (
<Card
key={system.id}
className={cn(
"cursor-pointer hover:shadow-md transition-all bg-transparent w-full dark:border-border duration-200 relative",
{
"opacity-50": system.status === "paused",
}
)}
>
<CardHeader className="py-1 ps-5 pe-3 bg-muted/30 border-b border-border/60">
<div className="flex items-center justify-between gap-2">
<CardTitle className="text-base tracking-normal shrink-1 text-primary/90 flex items-center min-w-0 gap-2.5">
<div className="flex items-center gap-2.5 min-w-0">
<IndicatorDot system={system} />
<CardTitle className="text-[.95em]/normal tracking-normal truncate text-primary/90">
{system.name}
</CardTitle>
</div>
</CardTitle>
{table.getColumn("actions")?.getIsVisible() && (
<div className="flex gap-1 flex-shrink-0 relative z-10">
<AlertsButton system={system} />
<ActionsButton system={system} />
</div>
)}
</div>
</CardHeader>
<CardContent className="space-y-2.5 text-sm px-5 pt-3.5 pb-4">
{table.getAllColumns().map((column) => {
if (!column.getIsVisible() || column.id === "system" || column.id === "actions") return null
const cell = row.getAllCells().find((cell) => cell.column.id === column.id)
if (!cell) return null
// @ts-ignore
const { Icon, name } = column.columnDef as ColumnDef<SystemRecord, unknown>
// Special case for 'lastSeen' column: add EyeIcon before value
if (column.id === "lastSeen") {
return (
<div key={column.id} className="flex items-center gap-3">
<EyeIcon className="size-4 text-muted-foreground" />
<div className="flex items-center gap-3 flex-1">
<span className="text-muted-foreground min-w-16">{name()}:</span>
<div className="flex-1">{flexRender(cell.column.columnDef.cell, cell.getContext())}</div>
</div>
</div>
)
}
return (
<div key={column.id} className="flex items-center gap-3">
{Icon && <Icon className="size-4 text-muted-foreground" />}
<div className="flex items-center gap-3 flex-1">
<span className="text-muted-foreground min-w-16">{name()}:</span>
<div className="flex-1">{flexRender(cell.column.columnDef.cell, cell.getContext())}</div>
</div>
</div>
)
})}
</CardContent>
<Link
href={getPagePath($router, "system", { name: row.original.name })}
className="inset-0 absolute w-full h-full"
>
<span className="sr-only">{row.original.name}</span>
</Link>
</Card>
)
}, [system, colLength, t])
}
)

View File

@@ -1,3 +1,13 @@
## 0.12.6
- Add maximum 1 minute memory usage.
- Add status filters to All Systems table.
- Fix Safari system link CSS bug.
- Use older cuda image for increased compatibility (#1103)
## 0.12.5
- Downgrade `gopsutil` to `v4.25.6` to fix panic on FreeBSD (#1083)