Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e90e5b256 | ||
|
|
e6a821ecc3 | ||
|
|
49036a9738 | ||
|
|
0197b449ed | ||
|
|
dc3382447c | ||
|
|
6beaf665fb | ||
|
|
b9622f75b0 | ||
|
|
fe462a71d6 | ||
|
|
1e556e105d | ||
|
|
b5f4daa8ef | ||
|
|
fd50241e2a | ||
|
|
6a0fbba407 | ||
|
|
2ee5fd123b | ||
|
|
86a13817df | ||
|
|
2f7d948a5c | ||
|
|
1b79e51194 | ||
|
|
2d98ac30f2 | ||
|
|
1a85175b15 | ||
|
|
6f429a6a4b | ||
|
|
3020a2d1fd | ||
|
|
a6e85240c6 | ||
|
|
98e816204a | ||
|
|
a0b5ac318a | ||
|
|
101461b7b5 | ||
|
|
ba6f50f21d | ||
|
|
dd3a229559 | ||
|
|
630d5024ac | ||
|
|
d239687e2e | ||
|
|
81a3dfbfe4 | ||
|
|
034720f47a |
No files matched your search
@@ -6,6 +6,7 @@
|
|||||||
==================== STOP ====
|
==================== STOP ====
|
||||||
|
|
||||||
⚠️ Before opening this pull request please review the guidelines in the checklist below.
|
⚠️ Before opening this pull request please review the guidelines in the checklist below.
|
||||||
|
|
||||||
If this PR does not meet those guidelines it will not be accepted, and everyone will be sad.
|
If this PR does not meet those guidelines it will not be accepted, and everyone will be sad.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@@ -14,9 +15,6 @@ If this PR does not meet those guidelines it will not be accepted, and everyone
|
|||||||
<!--
|
<!--
|
||||||
Please include a summary of the change. Screenshots and/or videos can also be helpful if appropriate.
|
Please include a summary of the change. Screenshots and/or videos can also be helpful if appropriate.
|
||||||
|
|
||||||
*** Please see the development guidelines for new widgets: https://gethomepage.dev/more/development/#service-widget-guidelines
|
|
||||||
*** If you do not follow these guidelines your PR will likely be closed without review.
|
|
||||||
|
|
||||||
New service widgets should include example(s) of relevant API output as well as updates to the docs for the new widget.
|
New service widgets should include example(s) of relevant API output as well as updates to the docs for the new widget.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@@ -30,13 +28,13 @@ What type of change does your PR introduce to Homepage?
|
|||||||
|
|
||||||
- [ ] New service widget
|
- [ ] New service widget
|
||||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||||
- [ ] New feature (non-breaking change which adds functionality)
|
- [ ] New feature or enhancement (non-breaking change which adds functionality)
|
||||||
- [ ] Documentation only
|
- [ ] Documentation only
|
||||||
- [ ] Other (please explain)
|
- [ ] Other (please explain)
|
||||||
|
|
||||||
## Checklist:
|
## Checklist:
|
||||||
|
|
||||||
- [ ] If applicable, I have added corresponding documentation changes.
|
- [ ] If applicable, I have added corresponding documentation changes.
|
||||||
- [ ] If applicable, I have reviewed the [feature](https://gethomepage.dev/more/development/#new-feature-guidelines) and / or [service widget guidelines](https://gethomepage.dev/more/development/#service-widget-guidelines).
|
- [ ] If applicable, I have reviewed the [feature / enhancement](https://gethomepage.dev/more/development/#new-feature-guidelines) and / or [service widget guidelines](https://gethomepage.dev/more/development/#service-widget-guidelines).
|
||||||
- [ ] I have checked that all code style checks pass using [pre-commit hooks](https://gethomepage.dev/more/development/#code-formatting-with-pre-commit-hooks) and [linting checks](https://gethomepage.dev/more/development/#code-linting).
|
- [ ] I have checked that all code style checks pass using [pre-commit hooks](https://gethomepage.dev/more/development/#code-formatting-with-pre-commit-hooks) and [linting checks](https://gethomepage.dev/more/development/#code-linting).
|
||||||
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.
|
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.
|
||||||
@@ -46,6 +46,24 @@ jobs:
|
|||||||
-
|
-
|
||||||
name: Check files
|
name: Check files
|
||||||
uses: pre-commit/action@v3.0.1
|
uses: pre-commit/action@v3.0.1
|
||||||
|
-
|
||||||
|
name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
run_install: false
|
||||||
|
-
|
||||||
|
name: Install Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: 'pnpm'
|
||||||
|
-
|
||||||
|
name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
|
-
|
||||||
|
name: Lint frontend
|
||||||
|
run: pnpm run lint
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Docker Build & Push
|
name: Docker Build & Push
|
||||||
@@ -127,7 +145,7 @@ jobs:
|
|||||||
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
|
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
|
||||||
# https://github.com/docker/setup-qemu-action#about
|
# https://github.com/docker/setup-qemu-action#about
|
||||||
# platforms: linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6
|
# platforms: linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
|
platforms: linux/amd64,linux/arm64
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache
|
cache-from: type=local,src=/tmp/.buildx-cache
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
|
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
|
||||||
|
|
||||||
|
|||||||
+6
-5
@@ -1,7 +1,7 @@
|
|||||||
# syntax = docker/dockerfile:latest
|
# syntax = docker/dockerfile:latest
|
||||||
|
|
||||||
# Install dependencies only when needed
|
# Install dependencies only when needed
|
||||||
FROM docker.io/node:18-alpine AS deps
|
FROM docker.io/node:22-alpine AS deps
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm f
|
|||||||
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm install -r --offline
|
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm install -r --offline
|
||||||
|
|
||||||
# Rebuild the source code only when needed
|
# Rebuild the source code only when needed
|
||||||
FROM docker.io/node:18-alpine AS builder
|
FROM docker.io/node:22-alpine AS builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ARG BUILDTIME
|
ARG BUILDTIME
|
||||||
@@ -33,7 +33,7 @@ RUN npm run telemetry \
|
|||||||
&& NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
|
&& NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
|
||||||
|
|
||||||
# Production image, copy all the files and run next
|
# Production image, copy all the files and run next
|
||||||
FROM docker.io/node:18-alpine AS runner
|
FROM docker.io/node:22-alpine AS runner
|
||||||
LABEL org.opencontainers.image.title "Homepage"
|
LABEL org.opencontainers.image.title "Homepage"
|
||||||
LABEL org.opencontainers.image.description "A self-hosted services landing page, with docker and service integrations."
|
LABEL org.opencontainers.image.description "A self-hosted services landing page, with docker and service integrations."
|
||||||
LABEL org.opencontainers.image.url="https://github.com/gethomepage/homepage"
|
LABEL org.opencontainers.image.url="https://github.com/gethomepage/homepage"
|
||||||
@@ -41,7 +41,7 @@ LABEL org.opencontainers.image.documentation='https://github.com/gethomepage/hom
|
|||||||
LABEL org.opencontainers.image.source='https://github.com/gethomepage/homepage'
|
LABEL org.opencontainers.image.source='https://github.com/gethomepage/homepage'
|
||||||
LABEL org.opencontainers.image.licenses='Apache-2.0'
|
LABEL org.opencontainers.image.licenses='Apache-2.0'
|
||||||
|
|
||||||
ENV NODE_ENV production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@@ -56,7 +56,8 @@ COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/
|
|||||||
|
|
||||||
RUN apk add --no-cache su-exec
|
RUN apk add --no-cache su-exec
|
||||||
|
|
||||||
ENV PORT 3000
|
ENV HOSTNAME=::
|
||||||
|
ENV PORT=3000
|
||||||
EXPOSE $PORT
|
EXPOSE $PORT
|
||||||
|
|
||||||
HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \
|
HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ With features like quick search, bookmarks, weather support, a wide range of int
|
|||||||
|
|
||||||
- **Fast** - The site is statically generated at build time for instant load times.
|
- **Fast** - The site is statically generated at build time for instant load times.
|
||||||
- **Secure** - All API requests to backend services are proxied, keeping your API keys hidden. Constantly reviewed for security by the community.
|
- **Secure** - All API requests to backend services are proxied, keeping your API keys hidden. Constantly reviewed for security by the community.
|
||||||
- **For Everyone** - Images built for AMD64, ARM64, ARMv7, and ARMv6.
|
- **For Everyone** - Images built for AMD64, ARM64.
|
||||||
- **Full i18n** - Support for over 40 languages.
|
- **Full i18n** - Support for over 40 languages.
|
||||||
- **Service & Web Bookmarks** - Add custom links to the homepage.
|
- **Service & Web Bookmarks** - Add custom links to the homepage.
|
||||||
- **Docker Integration** - Container status and stats. Automatic service discovery via labels.
|
- **Docker Integration** - Container status and stats. Automatic service discovery via labels.
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ Services may have descriptions,
|
|||||||
|
|
||||||
## Icons
|
## Icons
|
||||||
|
|
||||||
Services may have an icon attached to them, you can use icons from [Dashboard Icons](https://github.com/walkxcode/dashboard-icons) automatically, by passing the name of the icon, with, or without `.png` or with `.svg` to use the svg version.
|
Services may have an icon attached to them, you can use icons from [Dashboard Icons](https://github.com/homarr-labs/dashboard-icons) automatically, by passing the name of the icon, with, or without `.png`, `.webp` or `.svg` to specify the desired version.
|
||||||
|
|
||||||
You can also specify prefixed icons from:
|
You can also specify prefixed icons from:
|
||||||
|
|
||||||
|
|||||||
@@ -23,3 +23,5 @@ Finally, run the server:
|
|||||||
```bash
|
```bash
|
||||||
pnpm start
|
pnpm start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When updating homepage versions you will need to re-build the static files i.e. repeat the process above.
|
||||||
@@ -46,9 +46,9 @@ See the [pre-commit documentation](https://pre-commit.com/#install) to get start
|
|||||||
In general, homepage is meant to be a dashboard for 'self-hosted' services and we believe it is a small way we can help showcase this kind of software. While exceptions are made, mostly when there is no viable
|
In general, homepage is meant to be a dashboard for 'self-hosted' services and we believe it is a small way we can help showcase this kind of software. While exceptions are made, mostly when there is no viable
|
||||||
self-hosted / open-source alternative, we ask that any widgets, etc. are developed primarily for a self-hosted tool.
|
self-hosted / open-source alternative, we ask that any widgets, etc. are developed primarily for a self-hosted tool.
|
||||||
|
|
||||||
## New Feature Guidelines
|
## New Feature or Enhancement Guidelines {#new-feature-guidelines}
|
||||||
|
|
||||||
- New features should be linked to an existing feature request. The purpose of this requirement is to avoid the addition (and maintenance) of features that might only benefit a small number of users.
|
- New features or enhancements, **no matter how small**, must be linked to an existing feature request. The purpose of this requirement is to avoid the addition (and maintenance) of features that might only benefit a small number of users.
|
||||||
- If you have ideas for a larger feature you may want to open a discussion first.
|
- If you have ideas for a larger feature you may want to open a discussion first.
|
||||||
|
|
||||||
## Service Widget Guidelines
|
## Service Widget Guidelines
|
||||||
|
|||||||
@@ -62,10 +62,12 @@ widget:
|
|||||||
format: size
|
format: size
|
||||||
```
|
```
|
||||||
|
|
||||||
Supported formats for the values are `text`, `number`, `float`, `percent`, `bytes`, `bitrate`, `size`, `date` and `relativeDate`.
|
Supported formats for the values are `text`, `number`, `float`, `percent`, `duration`, `bytes`, `bitrate`, `size`, `date` and `relativeDate`.
|
||||||
|
|
||||||
The `dateStyle` and `timeStyle` options of the `date` format are passed directly to [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) and the `style` and `numeric` options of `relativeDate` are passed to [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat).
|
The `dateStyle` and `timeStyle` options of the `date` format are passed directly to [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) and the `style` and `numeric` options of `relativeDate` are passed to [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat).
|
||||||
|
|
||||||
|
The `duration` format expects the duration to be specified in seconds. The `scale` transformation tool can be used if a conversion is required.
|
||||||
|
|
||||||
The `size` format will return the length of the array or string, or the number of keys in an object. This is then formatted as `number`.
|
The `size` format will return the length of the array or string, or the number of keys in an object. This is then formatted as `number`.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Learn more about [Gluetun](https://github.com/qdm12/gluetun).
|
|||||||
|
|
||||||
Allowed fields: `["public_ip", "region", "country"]`.
|
Allowed fields: `["public_ip", "region", "country"]`.
|
||||||
|
|
||||||
To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication).
|
To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication). Note that to use the api key method, you must add the route `GET /v1/publicip/ip` to the `routes` array in your Gluetun config.toml.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Allowed fields: `["uptime", "wan", "lan", "lan_users", "lan_devices", "wlan", "w
|
|||||||
|
|
||||||
!!! hint
|
!!! hint
|
||||||
|
|
||||||
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container to clear the cache.
|
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container or restart the service to clear the cache.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
|
|||||||
Generated
+1940
-1192
File diff suppressed because it is too large.
Load diff
+15
-15
@@ -10,7 +10,7 @@
|
|||||||
"telemetry": "next telemetry disable"
|
"telemetry": "next telemetry disable"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.7.18",
|
"@headlessui/react": "^1.7.19",
|
||||||
"@kubernetes/client-node": "^0.17.1",
|
"@kubernetes/client-node": "^0.17.1",
|
||||||
"cal-parser": "^1.0.2",
|
"cal-parser": "^1.0.2",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
@@ -24,22 +24,22 @@
|
|||||||
"luxon": "^3.5.0",
|
"luxon": "^3.5.0",
|
||||||
"memory-cache": "^0.2.0",
|
"memory-cache": "^0.2.0",
|
||||||
"minecraft-ping-js": "^1.0.2",
|
"minecraft-ping-js": "^1.0.2",
|
||||||
"next": "^12.3.4",
|
"next": "^15.0.3",
|
||||||
"next-i18next": "^12.1.0",
|
"next-i18next": "^12.1.0",
|
||||||
"ping": "^0.4.4",
|
"ping": "^0.4.4",
|
||||||
"pretty-bytes": "^6.1.1",
|
"pretty-bytes": "^6.1.1",
|
||||||
"raw-body": "^3.0.0",
|
"raw-body": "^3.0.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.3.1",
|
||||||
"react-i18next": "^11.18.6",
|
"react-i18next": "^11.18.6",
|
||||||
"react-icons": "^4.12.0",
|
"react-icons": "^5.4.0",
|
||||||
"recharts": "^2.12.6",
|
"recharts": "^2.12.7",
|
||||||
"rrule": "^2.8.1",
|
"rrule": "^2.8.1",
|
||||||
"swr": "^1.3.0",
|
"swr": "^1.3.0",
|
||||||
"systeminformation": "^5.23.8",
|
"systeminformation": "^5.24.3",
|
||||||
"tough-cookie": "^4.1.3",
|
"tough-cookie": "^4.1.4",
|
||||||
"urbackup-server-api": "^0.52.1",
|
"urbackup-server-api": "^0.8.9",
|
||||||
"winston": "^3.11.0",
|
"winston": "^3.13.0",
|
||||||
"xml-js": "^1.6.11"
|
"xml-js": "^1.6.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -47,17 +47,17 @@
|
|||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"eslint": "^8.57.1",
|
"eslint": "^8.57.1",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-config-next": "^14.2.3",
|
"eslint-config-next": "^14.2.4",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-import": "^2.31.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.9.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-react": "^7.37.2",
|
"eslint-plugin-react": "^7.37.3",
|
||||||
"eslint-plugin-react-hooks": "^4.6.2",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.4.48",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.3.2",
|
||||||
"tailwind-scrollbar": "^3.0.5",
|
"tailwind-scrollbar": "^3.0.5",
|
||||||
"tailwindcss": "^3.4.14",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "^5.6.3"
|
"typescript": "^5.6.3"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
|||||||
Generated
+1562
-1239
File diff suppressed because it is too large.
Load diff
@@ -64,7 +64,7 @@
|
|||||||
"up": "Up",
|
"up": "Up",
|
||||||
"down": "INACTIF",
|
"down": "INACTIF",
|
||||||
"wait": "Veuillez patienter",
|
"wait": "Veuillez patienter",
|
||||||
"empty_data": "Statut sous-système inconnu"
|
"empty_data": "Statut du sous-système inconnu"
|
||||||
},
|
},
|
||||||
"docker": {
|
"docker": {
|
||||||
"rx": "Rx",
|
"rx": "Rx",
|
||||||
@@ -84,17 +84,17 @@
|
|||||||
},
|
},
|
||||||
"ping": {
|
"ping": {
|
||||||
"error": "Erreur",
|
"error": "Erreur",
|
||||||
"ping": "Ping",
|
"ping": "Latence",
|
||||||
"down": "Down",
|
"down": "Bas",
|
||||||
"up": "Up",
|
"up": "Haut",
|
||||||
"not_available": "Non disponible"
|
"not_available": "Non disponible"
|
||||||
},
|
},
|
||||||
"siteMonitor": {
|
"siteMonitor": {
|
||||||
"http_status": "Statut HTTP",
|
"http_status": "Statut HTTP",
|
||||||
"error": "Erreur",
|
"error": "Erreur",
|
||||||
"response": "Réponse",
|
"response": "Réponse",
|
||||||
"down": "Down",
|
"down": "Bas",
|
||||||
"up": "Up",
|
"up": "Haut",
|
||||||
"not_available": "Non disponible"
|
"not_available": "Non disponible"
|
||||||
},
|
},
|
||||||
"emby": {
|
"emby": {
|
||||||
@@ -144,8 +144,8 @@
|
|||||||
"uptime": "Démarré depuis",
|
"uptime": "Démarré depuis",
|
||||||
"maxDown": "Max. Bas",
|
"maxDown": "Max. Bas",
|
||||||
"maxUp": "Max. Haut",
|
"maxUp": "Max. Haut",
|
||||||
"down": "Down",
|
"down": "Bas",
|
||||||
"up": "Up",
|
"up": "Haut",
|
||||||
"received": "Reçu",
|
"received": "Reçu",
|
||||||
"sent": "Envoyé",
|
"sent": "Envoyé",
|
||||||
"externalIPAddress": "IP externe"
|
"externalIPAddress": "IP externe"
|
||||||
@@ -173,11 +173,11 @@
|
|||||||
"plex_connection_error": "Vérifier la connexion à Plex"
|
"plex_connection_error": "Vérifier la connexion à Plex"
|
||||||
},
|
},
|
||||||
"omada": {
|
"omada": {
|
||||||
"connectedAp": "AP connectés",
|
"connectedAp": "APs connectées",
|
||||||
"activeUser": "Équipts actifs",
|
"activeUser": "Périphériques actifs",
|
||||||
"alerts": "Alertes",
|
"alerts": "Alertes",
|
||||||
"connectedGateway": "Passerelles connectées",
|
"connectedGateway": "Passerelles connectées",
|
||||||
"connectedSwitches": "Switches connectés"
|
"connectedSwitches": "Switchs connectés"
|
||||||
},
|
},
|
||||||
"nzbget": {
|
"nzbget": {
|
||||||
"rate": "Débit",
|
"rate": "Débit",
|
||||||
@@ -213,11 +213,11 @@
|
|||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"qnap": {
|
"qnap": {
|
||||||
"cpuUsage": "Cpu",
|
"cpuUsage": "Utilisation CPU",
|
||||||
"memUsage": "Mém",
|
"memUsage": "Utilisation MÉM",
|
||||||
"systemTempC": "Temp",
|
"systemTempC": "Temp. système",
|
||||||
"poolUsage": "Pool",
|
"poolUsage": "Utilisation de la pool",
|
||||||
"volumeUsage": "Volume",
|
"volumeUsage": "Utilisation du volume",
|
||||||
"invalid": "Invalide"
|
"invalid": "Invalide"
|
||||||
},
|
},
|
||||||
"deluge": {
|
"deluge": {
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
"speedtest": {
|
"speedtest": {
|
||||||
"upload": "Envoi",
|
"upload": "Envoi",
|
||||||
"download": "Récep.",
|
"download": "Récep.",
|
||||||
"ping": "Ping"
|
"ping": "Latence"
|
||||||
},
|
},
|
||||||
"portainer": {
|
"portainer": {
|
||||||
"running": "Démarré",
|
"running": "Démarré",
|
||||||
@@ -349,8 +349,8 @@
|
|||||||
"tdarr": {
|
"tdarr": {
|
||||||
"queue": "En attente",
|
"queue": "En attente",
|
||||||
"processed": "Traité",
|
"processed": "Traité",
|
||||||
"errored": "En erreur",
|
"errored": "Erroné",
|
||||||
"saved": "Libéré"
|
"saved": "Enregistré"
|
||||||
},
|
},
|
||||||
"traefik": {
|
"traefik": {
|
||||||
"routers": "Routeurs",
|
"routers": "Routeurs",
|
||||||
@@ -376,7 +376,7 @@
|
|||||||
"gotify": {
|
"gotify": {
|
||||||
"apps": "Applis",
|
"apps": "Applis",
|
||||||
"clients": "Clients",
|
"clients": "Clients",
|
||||||
"messages": "Msg"
|
"messages": "Messages"
|
||||||
},
|
},
|
||||||
"prowlarr": {
|
"prowlarr": {
|
||||||
"enableIndexers": "Indexeur",
|
"enableIndexers": "Indexeur",
|
||||||
@@ -387,7 +387,7 @@
|
|||||||
},
|
},
|
||||||
"jackett": {
|
"jackett": {
|
||||||
"configured": "Configuré",
|
"configured": "Configuré",
|
||||||
"errored": "En erreur"
|
"errored": "Erroné"
|
||||||
},
|
},
|
||||||
"strelaysrv": {
|
"strelaysrv": {
|
||||||
"numActiveSessions": "Sessions",
|
"numActiveSessions": "Sessions",
|
||||||
@@ -461,10 +461,10 @@
|
|||||||
"0-night": "Ciel clair",
|
"0-night": "Ciel clair",
|
||||||
"1-day": "Principalement ensoleillé",
|
"1-day": "Principalement ensoleillé",
|
||||||
"1-night": "Principalement clair",
|
"1-night": "Principalement clair",
|
||||||
"2-day": "Partiellement couvert",
|
"2-day": "Partiellement nuageux",
|
||||||
"2-night": "Partiellement couvert",
|
"2-night": "Partiellement nuageux",
|
||||||
"3-day": "Couvert",
|
"3-day": "Nuageux",
|
||||||
"3-night": "Couvert",
|
"3-night": "Nuageux",
|
||||||
"45-day": "Brumeux",
|
"45-day": "Brumeux",
|
||||||
"45-night": "Brumeux",
|
"45-night": "Brumeux",
|
||||||
"48-day": "Brumeux",
|
"48-day": "Brumeux",
|
||||||
@@ -489,8 +489,8 @@
|
|||||||
"66-night": "Pluie verglaçante",
|
"66-night": "Pluie verglaçante",
|
||||||
"67-day": "Pluie verglaçante",
|
"67-day": "Pluie verglaçante",
|
||||||
"67-night": "Pluie verglaçante",
|
"67-night": "Pluie verglaçante",
|
||||||
"71-day": "Neige légère",
|
"71-day": "Légères chutes de neige",
|
||||||
"71-night": "Neige légère",
|
"71-night": "Légères chutes de neige",
|
||||||
"73-day": "Neige",
|
"73-day": "Neige",
|
||||||
"73-night": "Neige",
|
"73-night": "Neige",
|
||||||
"75-day": "Neige abondante",
|
"75-day": "Neige abondante",
|
||||||
@@ -521,15 +521,15 @@
|
|||||||
"up_to_date": "À jour",
|
"up_to_date": "À jour",
|
||||||
"child_bridges": "Child Bridges",
|
"child_bridges": "Child Bridges",
|
||||||
"child_bridges_status": "{{ok}}/{{total}}",
|
"child_bridges_status": "{{ok}}/{{total}}",
|
||||||
"up": "Up",
|
"up": "Haut",
|
||||||
"pending": "En attente",
|
"pending": "En attente",
|
||||||
"down": "Down"
|
"down": "Bas"
|
||||||
},
|
},
|
||||||
"healthchecks": {
|
"healthchecks": {
|
||||||
"new": "Nouveau",
|
"new": "Nouveau",
|
||||||
"up": "Up",
|
"up": "Haut",
|
||||||
"grace": "En Période de Grâce",
|
"grace": "En Période de Grâce",
|
||||||
"down": "Down",
|
"down": "Bas",
|
||||||
"paused": "En Pause",
|
"paused": "En Pause",
|
||||||
"status": "Statut",
|
"status": "Statut",
|
||||||
"last_ping": "Dernier Ping",
|
"last_ping": "Dernier Ping",
|
||||||
@@ -632,8 +632,8 @@
|
|||||||
},
|
},
|
||||||
"octoprint": {
|
"octoprint": {
|
||||||
"printer_state": "Statut",
|
"printer_state": "Statut",
|
||||||
"temp_tool": "Tool T°",
|
"temp_tool": "Temp. de l'outil",
|
||||||
"temp_bed": "Bed T°",
|
"temp_bed": "Temp. du lit",
|
||||||
"job_completion": "Achèvement"
|
"job_completion": "Achèvement"
|
||||||
},
|
},
|
||||||
"cloudflared": {
|
"cloudflared": {
|
||||||
@@ -644,8 +644,8 @@
|
|||||||
"load": "Charge moy.",
|
"load": "Charge moy.",
|
||||||
"memory": "Util. Mém.",
|
"memory": "Util. Mém.",
|
||||||
"wanStatus": "Statut WAN",
|
"wanStatus": "Statut WAN",
|
||||||
"up": "Up",
|
"up": "Haut",
|
||||||
"down": "Down",
|
"down": "Bas",
|
||||||
"temp": "T°",
|
"temp": "T°",
|
||||||
"disk": "Util. Disque",
|
"disk": "Util. Disque",
|
||||||
"wanIP": "IP WAN"
|
"wanIP": "IP WAN"
|
||||||
@@ -754,9 +754,9 @@
|
|||||||
"booksDuration": "Durée"
|
"booksDuration": "Durée"
|
||||||
},
|
},
|
||||||
"homeassistant": {
|
"homeassistant": {
|
||||||
"people_home": "People Home",
|
"people_home": "Personne à la maison",
|
||||||
"lights_on": "Lumières allumées",
|
"lights_on": "Lumières allumées",
|
||||||
"switches_on": "Commutateur On"
|
"switches_on": "Interrupteurs allumés"
|
||||||
},
|
},
|
||||||
"whatsupdocker": {
|
"whatsupdocker": {
|
||||||
"monitoring": "Conteneurs",
|
"monitoring": "Conteneurs",
|
||||||
@@ -800,8 +800,8 @@
|
|||||||
"currentPlayers": "Joueurs actuels",
|
"currentPlayers": "Joueurs actuels",
|
||||||
"players": "Joueurs",
|
"players": "Joueurs",
|
||||||
"maxPlayers": "Joueurs max",
|
"maxPlayers": "Joueurs max",
|
||||||
"bots": "Bots",
|
"bots": "Robots",
|
||||||
"ping": "Ping"
|
"ping": "Latence"
|
||||||
},
|
},
|
||||||
"urbackup": {
|
"urbackup": {
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
@@ -826,8 +826,8 @@
|
|||||||
"openwrt": {
|
"openwrt": {
|
||||||
"uptime": "Démarré depuis",
|
"uptime": "Démarré depuis",
|
||||||
"cpuLoad": "Charge moyenne CPU (5 min)",
|
"cpuLoad": "Charge moyenne CPU (5 min)",
|
||||||
"up": "Up",
|
"up": "Haut",
|
||||||
"down": "Down",
|
"down": "Bas",
|
||||||
"bytesTx": "Transmis",
|
"bytesTx": "Transmis",
|
||||||
"bytesRx": "Reçu"
|
"bytesRx": "Reçu"
|
||||||
},
|
},
|
||||||
@@ -840,9 +840,9 @@
|
|||||||
"sitesDown": "Hors ligne",
|
"sitesDown": "Hors ligne",
|
||||||
"paused": "En Pause",
|
"paused": "En Pause",
|
||||||
"notyetchecked": "Non vérifié",
|
"notyetchecked": "Non vérifié",
|
||||||
"up": "Up",
|
"up": "Haut",
|
||||||
"seemsdown": "Semble hors ligne",
|
"seemsdown": "Semble hors ligne",
|
||||||
"down": "Down",
|
"down": "Bas",
|
||||||
"unknown": "Inconnu"
|
"unknown": "Inconnu"
|
||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
@@ -912,7 +912,7 @@
|
|||||||
},
|
},
|
||||||
"crowdsec": {
|
"crowdsec": {
|
||||||
"alerts": "Alertes",
|
"alerts": "Alertes",
|
||||||
"bans": "Exclusions"
|
"bans": "Bannissements"
|
||||||
},
|
},
|
||||||
"wgeasy": {
|
"wgeasy": {
|
||||||
"connected": "Connecté",
|
"connected": "Connecté",
|
||||||
@@ -927,12 +927,12 @@
|
|||||||
"banned": "Banni"
|
"banned": "Banni"
|
||||||
},
|
},
|
||||||
"myspeed": {
|
"myspeed": {
|
||||||
"ping": "Ping",
|
"ping": "Latence",
|
||||||
"download": "Récep.",
|
"download": "Récep.",
|
||||||
"upload": "Envoi"
|
"upload": "Envoi"
|
||||||
},
|
},
|
||||||
"stocks": {
|
"stocks": {
|
||||||
"stocks": "Actions",
|
"stocks": "Stocks",
|
||||||
"loading": "Chargement",
|
"loading": "Chargement",
|
||||||
"open": "Ouvert - Marché américain",
|
"open": "Ouvert - Marché américain",
|
||||||
"closed": "Fermé - marché américain",
|
"closed": "Fermé - marché américain",
|
||||||
@@ -981,8 +981,8 @@
|
|||||||
"beszel": {
|
"beszel": {
|
||||||
"name": "Nom",
|
"name": "Nom",
|
||||||
"systems": "Systèmes",
|
"systems": "Systèmes",
|
||||||
"up": "Up",
|
"up": "Haut",
|
||||||
"down": "Down",
|
"down": "Bas",
|
||||||
"paused": "En Pause",
|
"paused": "En Pause",
|
||||||
"pending": "En attente",
|
"pending": "En attente",
|
||||||
"status": "Statut",
|
"status": "Statut",
|
||||||
|
|||||||
@@ -311,13 +311,13 @@
|
|||||||
},
|
},
|
||||||
"suwayomi": {
|
"suwayomi": {
|
||||||
"download": "下载",
|
"download": "下载",
|
||||||
"nondownload": "Non-Downloaded",
|
"nondownload": "未下载",
|
||||||
"read": "已读",
|
"read": "已读",
|
||||||
"unread": "未读",
|
"unread": "未读",
|
||||||
"downloadedread": "Downloaded & Read",
|
"downloadedread": "已下载 & 已读",
|
||||||
"downloadedunread": "Downloaded & Unread",
|
"downloadedunread": "已下载 & 未读",
|
||||||
"nondownloadedread": "Non-Downloaded & Read",
|
"nondownloadedread": "未下载 & 已读",
|
||||||
"nondownloadedunread": "Non-Downloaded & Unread"
|
"nondownloadedunread": "未下载 & 未读"
|
||||||
},
|
},
|
||||||
"tailscale": {
|
"tailscale": {
|
||||||
"address": "地址",
|
"address": "地址",
|
||||||
@@ -980,7 +980,7 @@
|
|||||||
},
|
},
|
||||||
"beszel": {
|
"beszel": {
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "系统",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
"down": "Down",
|
"down": "Down",
|
||||||
"paused": "暂停",
|
"paused": "暂停",
|
||||||
@@ -989,26 +989,26 @@
|
|||||||
"updated": "已升级",
|
"updated": "已升级",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
"memory": "内存",
|
"memory": "内存",
|
||||||
"disk": "Disk",
|
"disk": "磁盘",
|
||||||
"network": "NET"
|
"network": "网络"
|
||||||
},
|
},
|
||||||
"argocd": {
|
"argocd": {
|
||||||
"apps": "应用程序",
|
"apps": "应用程序",
|
||||||
"synced": "Synced",
|
"synced": "已同步",
|
||||||
"outOfSync": "Out Of Sync",
|
"outOfSync": "未同步",
|
||||||
"healthy": "健康",
|
"healthy": "健康",
|
||||||
"degraded": "Degraded",
|
"degraded": "已降级",
|
||||||
"progressing": "Progressing",
|
"progressing": "进行中",
|
||||||
"missing": "丢失",
|
"missing": "丢失",
|
||||||
"suspended": "Suspended"
|
"suspended": "已停用"
|
||||||
},
|
},
|
||||||
"spoolman": {
|
"spoolman": {
|
||||||
"loading": "正在加载"
|
"loading": "正在加载"
|
||||||
},
|
},
|
||||||
"gitlab": {
|
"gitlab": {
|
||||||
"groups": "Groups",
|
"groups": "群组",
|
||||||
"issues": "问题",
|
"issues": "问题",
|
||||||
"merges": "Merge Requests",
|
"merges": "合并请求",
|
||||||
"projects": "Projects"
|
"projects": "项目"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,8 +14,10 @@ export default class ErrorBoundary extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// You can also log error messages to an error reporting service here
|
// You can also log error messages to an error reporting service here
|
||||||
// eslint-disable-next-line no-console
|
if (error || errorInfo) {
|
||||||
console.error(error, errorInfo);
|
// eslint-disable-next-line no-console
|
||||||
|
console.error("component error: %s, info: %s", error, errorInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
import Image from "next/future/image";
|
import Image from "next/image";
|
||||||
|
|
||||||
import { SettingsContext } from "utils/contexts/settings";
|
import { SettingsContext } from "utils/contexts/settings";
|
||||||
import { ThemeContext } from "utils/contexts/theme";
|
import { ThemeContext } from "utils/contexts/theme";
|
||||||
@@ -101,7 +101,26 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
|
|||||||
const iconName = icon.replace(".svg", "");
|
const iconName = icon.replace(".svg", "");
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/svg/${iconName}.svg`}
|
src={`https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/${iconName}.svg`}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
style={{
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
objectFit: "contain",
|
||||||
|
maxHeight: "100%",
|
||||||
|
maxWidth: "100%",
|
||||||
|
}}
|
||||||
|
alt={alt}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icon.endsWith(".webp")) {
|
||||||
|
const iconName = icon.replace(".webp", "");
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={`https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/webp/${iconName}.webp`}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
style={{
|
style={{
|
||||||
@@ -119,7 +138,7 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
|
|||||||
const iconName = icon.replace(".png", "");
|
const iconName = icon.replace(".png", "");
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`}
|
src={`https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/${iconName}.png`}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { compareVersions } from "compare-versions";
|
import { compareVersions, validate } from "compare-versions";
|
||||||
import { MdNewReleases } from "react-icons/md";
|
import { MdNewReleases } from "react-icons/md";
|
||||||
|
|
||||||
export default function Version() {
|
export default function Version() {
|
||||||
@@ -44,7 +44,7 @@ export default function Version() {
|
|||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
{version === "main" || version === "dev" || version === "nightly"
|
{!validate(version)
|
||||||
? null
|
? null
|
||||||
: releaseData &&
|
: releaseData &&
|
||||||
latestRelease &&
|
latestRelease &&
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { useState, useEffect, Fragment } from "react";
|
import { useState, useEffect, Fragment } from "react";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { FiSearch } from "react-icons/fi";
|
import { FiSearch } from "react-icons/fi";
|
||||||
import { SiDuckduckgo, SiMicrosoftbing, SiGoogle, SiBaidu, SiBrave } from "react-icons/si";
|
import { SiDuckduckgo, SiGoogle, SiBaidu, SiBrave } from "react-icons/si";
|
||||||
|
import { BiLogoBing } from "react-icons/bi";
|
||||||
import { Listbox, Transition, Combobox } from "@headlessui/react";
|
import { Listbox, Transition, Combobox } from "@headlessui/react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ export const searchProviders = {
|
|||||||
name: "Bing",
|
name: "Bing",
|
||||||
url: "https://www.bing.com/search?q=",
|
url: "https://www.bing.com/search?q=",
|
||||||
suggestionUrl: "https://api.bing.com/osjson.aspx?query=",
|
suggestionUrl: "https://api.bing.com/osjson.aspx?query=",
|
||||||
icon: SiMicrosoftbing,
|
icon: BiLogoBing,
|
||||||
},
|
},
|
||||||
baidu: {
|
baidu: {
|
||||||
name: "Baidu",
|
name: "Baidu",
|
||||||
|
|||||||
+18
-7
@@ -166,6 +166,18 @@ const headerStyles = {
|
|||||||
boxedWidgets: "m-5 mb-0 sm:m-9 sm:mb-0 sm:mt-1",
|
boxedWidgets: "m-5 mb-0 sm:m-9 sm:mb-0 sm:mt-1",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getAllServices(services) {
|
||||||
|
function getServices(group) {
|
||||||
|
let nestedServices = [...group.services];
|
||||||
|
if (group.groups.length > 0) {
|
||||||
|
nestedServices = [...nestedServices, ...group.groups.map(getServices).flat()];
|
||||||
|
}
|
||||||
|
return nestedServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...services.map(getServices).flat()];
|
||||||
|
}
|
||||||
|
|
||||||
function Home({ initialSettings }) {
|
function Home({ initialSettings }) {
|
||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
const { theme, setTheme } = useContext(ThemeContext);
|
const { theme, setTheme } = useContext(ThemeContext);
|
||||||
@@ -182,10 +194,9 @@ function Home({ initialSettings }) {
|
|||||||
const { data: bookmarks } = useSWR("/api/bookmarks");
|
const { data: bookmarks } = useSWR("/api/bookmarks");
|
||||||
const { data: widgets } = useSWR("/api/widgets");
|
const { data: widgets } = useSWR("/api/widgets");
|
||||||
|
|
||||||
const servicesAndBookmarks = [
|
const servicesAndBookmarks = [...bookmarks.map((bg) => bg.bookmarks).flat(), ...getAllServices(services)].filter(
|
||||||
...services.map((sg) => sg.services).flat(),
|
(i) => i?.href,
|
||||||
...bookmarks.map((bg) => bg.bookmarks).flat(),
|
);
|
||||||
].filter((i) => i?.href);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (settings.language) {
|
if (settings.language) {
|
||||||
@@ -459,7 +470,7 @@ function Home({ initialSettings }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Wrapper({ initialSettings, fallback }) {
|
export default function Wrapper({ initialSettings, fallback }) {
|
||||||
const { theme } = useContext(ThemeContext);
|
const { themeContext } = useContext(ThemeContext);
|
||||||
const wrappedStyle = {};
|
const wrappedStyle = {};
|
||||||
let backgroundBlur = false;
|
let backgroundBlur = false;
|
||||||
let backgroundSaturate = false;
|
let backgroundSaturate = false;
|
||||||
@@ -490,9 +501,9 @@ export default function Wrapper({ initialSettings, fallback }) {
|
|||||||
id="page_wrapper"
|
id="page_wrapper"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative",
|
"relative",
|
||||||
theme && theme,
|
initialSettings.theme && initialSettings.theme,
|
||||||
initialSettings.color && `theme-${initialSettings.color}`,
|
initialSettings.color && `theme-${initialSettings.color}`,
|
||||||
theme === "dark" ? "scheme-dark" : "scheme-light",
|
themeContext === "dark" ? "scheme-dark" : "scheme-light",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -67,3 +67,8 @@ dialog ::-webkit-scrollbar {
|
|||||||
.chart + .chart {
|
.chart + .chart {
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.service-container + .chart {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
@@ -79,7 +79,7 @@ export default async function genericProxyHandler(req, res, map) {
|
|||||||
error: {
|
error: {
|
||||||
message: "HTTP Error",
|
message: "HTTP Error",
|
||||||
url: sanitizeErrorURL(url),
|
url: sanitizeErrorURL(url),
|
||||||
resultData: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData,
|
data: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ function formatValue(t, mapping, rawValue) {
|
|||||||
case "percent":
|
case "percent":
|
||||||
value = t("common.percent", { value });
|
value = t("common.percent", { value });
|
||||||
break;
|
break;
|
||||||
|
case "duration":
|
||||||
|
value = t("common.duration", { value });
|
||||||
|
break;
|
||||||
case "bytes":
|
case "bytes":
|
||||||
value = t("common.bytes", { value });
|
value = t("common.bytes", { value });
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -29,10 +29,13 @@ export default function Component({ service }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// broken by evcc v0.133.0 https://github.com/evcc-io/evcc/commit/9dcb1fa0a7c08dd926b79309aa1f676a5fc6c8aa
|
||||||
|
const gridPower = stateData.result.gridPower ?? stateData.result.grid?.power ?? 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="evcc.pv_power" value={`${toKilowatts(t, stateData.result.pvPower)} ${t("evcc.kilowatt")}`} />
|
<Block label="evcc.pv_power" value={`${toKilowatts(t, stateData.result.pvPower)} ${t("evcc.kilowatt")}`} />
|
||||||
<Block label="evcc.grid_power" value={`${toKilowatts(t, stateData.result.gridPower)} ${t("evcc.kilowatt")}`} />
|
<Block label="evcc.grid_power" value={`${toKilowatts(t, gridPower)} ${t("evcc.kilowatt")}`} />
|
||||||
<Block label="evcc.home_power" value={`${toKilowatts(t, stateData.result.homePower)} ${t("evcc.kilowatt")}`} />
|
<Block label="evcc.home_power" value={`${toKilowatts(t, stateData.result.homePower)} ${t("evcc.kilowatt")}`} />
|
||||||
<Block
|
<Block
|
||||||
label="evcc.charge_power"
|
label="evcc.charge_power"
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default function Component({ service }) {
|
|||||||
<div className="absolute -top-2 -left-2 -right-2 -bottom-2">
|
<div className="absolute -top-2 -left-2 -right-2 -bottom-2">
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
height: `${Math.max(20, fsData.size / fsData.free)}%`,
|
height: `${Math.max(20, (140 * (fsData.size - fsData.free)) / fsData.size)}px`,
|
||||||
}}
|
}}
|
||||||
className="absolute bottom-0 border-t border-t-theme-500 bg-gradient-to-b from-theme-500/40 to-theme-500/10 w-full"
|
className="absolute bottom-0 border-t border-t-theme-500 bg-gradient-to-b from-theme-500/40 to-theme-500/10 w-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in new issue
Block a user