mirror of
https://github.com/gethomepage/homepage.git
synced 2026-01-06 07:22:07 +08:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cf88d290f | ||
|
|
9f030d1540 | ||
|
|
e8f6d81d13 | ||
|
|
571f627b3b | ||
|
|
861ab32ca3 | ||
|
|
aa5d24b9e4 | ||
|
|
7adfe2ffd9 | ||
|
|
f8d2bb8611 | ||
|
|
892ebb8bd9 | ||
|
|
456fe6afc2 | ||
|
|
ce3fb1abc1 | ||
|
|
a1e023e240 | ||
|
|
56f46ae85c | ||
|
|
67ebe29db7 | ||
|
|
0c2671ea00 | ||
|
|
7a6470381b | ||
|
|
86d3fc4fbb | ||
|
|
ceeb007ca0 | ||
|
|
87113eaac4 | ||
|
|
25cd09a117 |
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -15,7 +15,7 @@ body:
|
|||||||
|
|
||||||
Before opening an issue, please double check:
|
Before opening an issue, please double check:
|
||||||
|
|
||||||
- [The troubleshooting guide](https://gethomepage.dev/en/more/troubleshooting/).
|
- [The troubleshooting guide](https://gethomepage.dev/latest/more/troubleshooting/).
|
||||||
- [The homepage documentation](https://gethomepage.dev/)
|
- [The homepage documentation](https://gethomepage.dev/)
|
||||||
- [Existing issues](https://github.com/benphelps/homepage/search?q=&type=issues) and [discussions](https://github.com/benphelps/homepage/search?q=&type=discussions).
|
- [Existing issues](https://github.com/benphelps/homepage/search?q=&type=issues) and [discussions](https://github.com/benphelps/homepage/search?q=&type=discussions).
|
||||||
- type: textarea
|
- type: textarea
|
||||||
@@ -78,7 +78,7 @@ body:
|
|||||||
id: troubleshooting
|
id: troubleshooting
|
||||||
attributes:
|
attributes:
|
||||||
label: Troubleshooting
|
label: Troubleshooting
|
||||||
description: Please include output from your [troubleshooting tests](https://gethomepage.dev/en/more/troubleshooting/#service-widget-errors). If this is a service widget issue and you do not include any information here your issue will be closed. If it is not, indicate e.g. 'n/a'
|
description: Please include output from your [troubleshooting tests](https://gethomepage.dev/latest/more/troubleshooting/#service-widget-errors). If this is a service widget issue and you do not include any information here your issue will be closed. If it is not, indicate e.g. 'n/a'
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
@@ -93,7 +93,7 @@ body:
|
|||||||
options:
|
options:
|
||||||
- label: Check [the documentation](https://gethomepage.dev/)
|
- label: Check [the documentation](https://gethomepage.dev/)
|
||||||
required: true
|
required: true
|
||||||
- label: Follow [the troubleshooting guide](https://gethomepage.dev/en/more/troubleshooting/) (please include output above if applicable).
|
- label: Follow [the troubleshooting guide](https://gethomepage.dev/latest/more/troubleshooting/) (please include output above if applicable).
|
||||||
required: true
|
required: true
|
||||||
- label: Search [existing issues](https://github.com/benphelps/homepage/search?q=&type=issues) and [discussions](https://github.com/benphelps/homepage/search?q=&type=discussions).
|
- label: Search [existing issues](https://github.com/benphelps/homepage/search?q=&type=issues) and [discussions](https://github.com/benphelps/homepage/search?q=&type=discussions).
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -3,10 +3,10 @@
|
|||||||
<!--
|
<!--
|
||||||
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/en/more/development/#service-widget-guidelines
|
*** Please see the development guidelines for new widgets: https://gethomepage.dev/latest/more/development/#service-widget-guidelines
|
||||||
*** If you do not follow these guidelines your PR will likely be closed without review.
|
*** If you do not follow these guidelines your PR will likely be closed without review.
|
||||||
|
|
||||||
New service widgets should include example(s) of relevant relevant API output as well as a PR to the docs for the new widget.
|
New service widgets should include example(s) of relevant relevant API output as well updates to the docs for the new widget.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
Closes # (issue)
|
Closes # (issue)
|
||||||
@@ -20,11 +20,12 @@ 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 (non-breaking change which adds functionality)
|
||||||
|
- [ ] Documentation only
|
||||||
- [ ] Other (please explain)
|
- [ ] Other (please explain)
|
||||||
|
|
||||||
## Checklist:
|
## Checklist:
|
||||||
|
|
||||||
- [ ] If adding a service widget or a change that requires it, I have added corresponding documentation.
|
- [ ] If adding a service widget or a change that requires it, I have added corresponding documentation changes.
|
||||||
- [ ] If adding a new widget I have reviewed the [guidelines](https://gethomepage.dev/en/more/development/#service-widget-guidelines).
|
- [ ] If adding a new widget I have reviewed the [guidelines](https://gethomepage.dev/latest/more/development/#service-widget-guidelines).
|
||||||
- [ ] If applicable, I have checked that all tests pass with e.g. `pnpm lint`.
|
- [ ] If applicable, I have checked that all tests pass with e.g. `pnpm lint`.
|
||||||
- [ ] 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.
|
||||||
|
|||||||
10
.github/workflows/docker-publish.yml
vendored
10
.github/workflows/docker-publish.yml
vendored
@@ -12,8 +12,14 @@ on:
|
|||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
# Publish semver tags as releases.
|
# Publish semver tags as releases.
|
||||||
tags: [ 'v*.*.*' ]
|
tags: [ 'v*.*.*' ]
|
||||||
|
paths-ignore:
|
||||||
|
- 'docs/**'
|
||||||
|
- 'mkdocs.yml'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
|
paths-ignore:
|
||||||
|
- 'docs/**'
|
||||||
|
- 'mkdocs.yml'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Use docker.io for Docker Hub if empty
|
# Use docker.io for Docker Hub if empty
|
||||||
@@ -24,7 +30,8 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
name: Docker Build & Push
|
||||||
|
if: github.repository == 'benphelps/homepage'
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -98,6 +105,7 @@ jobs:
|
|||||||
BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
|
BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
|
||||||
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
|
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
|
||||||
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
|
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
|
||||||
|
DEPRECATED_REPO=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.source'] == 'https://github.com/benphelps/homepage' }}
|
||||||
# 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,linux/arm/v7,linux/arm/v6
|
||||||
|
|||||||
38
.github/workflows/docs-publish.yml
vendored
38
.github/workflows/docs-publish.yml
vendored
@@ -4,13 +4,43 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags: [ 'v*.*.*' ]
|
tags: [ 'v*.*.*' ]
|
||||||
branches: ['main']
|
branches: ['main']
|
||||||
|
paths:
|
||||||
|
- 'docs/**'
|
||||||
|
- 'mkdocs.yml'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'docs/**'
|
||||||
|
- 'mkdocs.yml'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test Build
|
||||||
|
if: github.repository == 'benphelps/homepage' && github.event_name == 'pull_request'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
key: mkdocs-material-${{ env.cache_id }}
|
||||||
|
path: .cache
|
||||||
|
restore-keys: |
|
||||||
|
mkdocs-material-
|
||||||
|
- run: sudo apt-get install pngquant
|
||||||
|
- run: pip install mike
|
||||||
|
- run: pip install mkdocs-material
|
||||||
|
- name: Test Docs Build
|
||||||
|
run: MKINSIDERS=false mkdocs build
|
||||||
deploy:
|
deploy:
|
||||||
|
name: Build & Deploy
|
||||||
|
if: github.repository == 'benphelps/homepage' && github.event_name != 'pull_request'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -39,11 +69,11 @@ jobs:
|
|||||||
git checkout gh-pages
|
git checkout gh-pages
|
||||||
git pull origin gh-pages
|
git pull origin gh-pages
|
||||||
git checkout main
|
git checkout main
|
||||||
- name: Mike Deploy for Main
|
- name: Docs Deploy for Main
|
||||||
if: github.ref == 'refs/heads/main'
|
if: github.ref == 'refs/heads/main'
|
||||||
run: mike deploy --update --push ${{github.ref_name}}
|
run: MKINSIDERS=true mike deploy --update --push ${{github.ref_name}}
|
||||||
- name: Mike Deploy for Tags
|
- name: Docs Deploy for Tags
|
||||||
if: github.ref != 'refs/heads/main'
|
if: github.ref != 'refs/heads/main'
|
||||||
run: mike deploy --update --push ${{github.ref_name}} latest
|
run: MKINSIDERS=true mike deploy --update --push ${{github.ref_name}} latest
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -48,3 +48,7 @@ next-env.d.ts
|
|||||||
|
|
||||||
# MkDocs documentation
|
# MkDocs documentation
|
||||||
site*/
|
site*/
|
||||||
|
.cache/
|
||||||
|
|
||||||
|
# venv
|
||||||
|
.venv/
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ Homepage includes a lot of configuration options and is often deploying in large
|
|||||||
People *love* thorough bug reports. I'm not even kidding.
|
People *love* thorough bug reports. I'm not even kidding.
|
||||||
|
|
||||||
## Development Guidelines
|
## Development Guidelines
|
||||||
Please see the [documentation regarding development](https://gethomepage.dev/en/more/development/) and specifically the [guidelines for new service widgets](https://gethomepage.dev/en/more/development/#service-widget-guidelines) if you are considering making one.
|
Please see the [documentation regarding development](https://gethomepage.dev/latest/more/development/) and specifically the [guidelines for new service widgets](https://gethomepage.dev/latest/more/development/#service-widget-guidelines) if you are considering making one.
|
||||||
|
|
||||||
## Use a Consistent Coding Style
|
## Use a Consistent Coding Style
|
||||||
This project follows the [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript), please follow it when submitting pull requests.
|
This project follows the [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript), please follow it when submitting pull requests.
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ WORKDIR /app
|
|||||||
ARG BUILDTIME
|
ARG BUILDTIME
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
ARG REVISION
|
ARG REVISION
|
||||||
|
ARG DEPRECATED_REPO
|
||||||
|
|
||||||
COPY --link --from=deps /app/node_modules ./node_modules/
|
COPY --link --from=deps /app/node_modules ./node_modules/
|
||||||
COPY . .
|
COPY . .
|
||||||
@@ -30,7 +31,7 @@ COPY . .
|
|||||||
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
|
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
|
||||||
RUN npm run telemetry \
|
RUN npm run telemetry \
|
||||||
&& mkdir config \
|
&& mkdir config \
|
||||||
&& 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 NEXT_PUBLIC_DEPRECATED_REPO=$DEPRECATED_REPO 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:18-alpine AS runner
|
||||||
|
|||||||
@@ -39,19 +39,19 @@ With features like quick search, bookmarks, weather support, a wide range of int
|
|||||||
|
|
||||||
## Docker Integration
|
## Docker Integration
|
||||||
|
|
||||||
Homepage has built-in support for Docker, and can automatically discover and add services to the homepage based on labels. See the [Docker](https://gethomepage.dev/en/installation/docker/) page for more information.
|
Homepage has built-in support for Docker, and can automatically discover and add services to the homepage based on labels. See the [Docker](https://gethomepage.dev/latest/installation/docker/) page for more information.
|
||||||
|
|
||||||
## Service Widgets
|
## Service Widgets
|
||||||
|
|
||||||
Homepage also has support for over 100 3rd party services, including all popular starr apps, and most popular self-hosted apps. Some examples include: Radarr, Sonarr, Lidarr, Bazarr, Ombi, Tautulli, Plex, Jellyfin, Emby, Transmission, qBittorrent, Deluge, Jackett, NZBGet, SABnzbd, etc. As well as service integrations, Homepage also has a number of information providers, sourcing information from a variety of external 3rd party APIs. See the [Service](https://gethomepage.dev/en/configs/service-widgets/) page for more information.
|
Homepage also has support for over 100 3rd party services, including all popular starr apps, and most popular self-hosted apps. Some examples include: Radarr, Sonarr, Lidarr, Bazarr, Ombi, Tautulli, Plex, Jellyfin, Emby, Transmission, qBittorrent, Deluge, Jackett, NZBGet, SABnzbd, etc. As well as service integrations, Homepage also has a number of information providers, sourcing information from a variety of external 3rd party APIs. See the [Service](https://gethomepage.dev/latest/configs/service-widgets/) page for more information.
|
||||||
|
|
||||||
## Information Widgets
|
## Information Widgets
|
||||||
|
|
||||||
Homepage has built-in support for a number of information providers, including weather, time, date, search, glances and more. System and status information presented at the top of the page. See the [Information Providers](https://gethomepage.dev/en/configs/widgets/) page for more information.
|
Homepage has built-in support for a number of information providers, including weather, time, date, search, glances and more. System and status information presented at the top of the page. See the [Information Providers](https://gethomepage.dev/latest/configs/widgets/) page for more information.
|
||||||
|
|
||||||
## Customization
|
## Customization
|
||||||
|
|
||||||
Homepage is highly customizable, with support for custom themes, custom CSS & JS, custom layouts, formatting, localization and more. See the [Settings](https://gethomepage.dev/en/configs/settings/) page for more information.
|
Homepage is highly customizable, with support for custom themes, custom CSS & JS, custom layouts, formatting, localization and more. See the [Settings](https://gethomepage.dev/latest/configs/settings/) page for more information.
|
||||||
|
|
||||||
# Getting Started
|
# Getting Started
|
||||||
|
|
||||||
|
|||||||
@@ -123,9 +123,7 @@ Services may have an optional `ping` property that allows you to monitor the ava
|
|||||||
|
|
||||||
<img width="1038" alt="Ping" src="https://github.com/benphelps/homepage/assets/88257202/7bc13bd3-0d0b-44e3-888c-a20e069a3233">
|
<img width="1038" alt="Ping" src="https://github.com/benphelps/homepage/assets/88257202/7bc13bd3-0d0b-44e3-888c-a20e069a3233">
|
||||||
|
|
||||||
You can also apply different styles to the ping indicator by using the `statusStyle` property. The default is no value, and displays the response time in ms, but you can also use `dot` or `simple`. `dot` showing a green dot for a successful ping, and `simple` showing either ONLINE or OFFLINE to match the status style of Docker containers.
|
You can also apply different styles to the ping indicator by using the `statusStyle` property, see [settings](settings.md#status-style).
|
||||||
|
|
||||||
<!-- TODO: Insert images of the new status styles there -->
|
|
||||||
|
|
||||||
## Docker Integration
|
## Docker Integration
|
||||||
|
|
||||||
|
|||||||
@@ -380,6 +380,30 @@ or per-service (`services.yaml`) with:
|
|||||||
|
|
||||||
If you have both set the per-service settings take precedence.
|
If you have both set the per-service settings take precedence.
|
||||||
|
|
||||||
|
## Status Style
|
||||||
|
|
||||||
|
You can choose from the following styles for docker or k8s status and ping: `dot` or `basic`
|
||||||
|
|
||||||
|
- The default is no value, and displays the ping response time in ms and the docker / k8s container status
|
||||||
|
- `dot` shows a green dot for a successful ping or healthy status.
|
||||||
|
- `basic` shows either UP or DOWN for ping
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
statusStyle: 'dot'
|
||||||
|
```
|
||||||
|
|
||||||
|
or per-service (`services.yaml`) with:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- Example Service:
|
||||||
|
...
|
||||||
|
statusStyle: 'dot'
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have both set, the per-service settings take precedence.
|
||||||
|
|
||||||
## Hide Widget Error Messages
|
## Hide Widget Error Messages
|
||||||
|
|
||||||
Hide the visible API error messages either globally in `settings.yaml`:
|
Hide the visible API error messages either globally in `settings.yaml`:
|
||||||
|
|||||||
8
docs/more/homepage-move.md
Normal file
8
docs/more/homepage-move.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
title: Homepage Move
|
||||||
|
description: Homepage Container Deprecation
|
||||||
|
---
|
||||||
|
|
||||||
|
As of v0.7.1 homepage migrated from benphelps/homepage to an "orgnization" located at gethomepage/homepage. The reason for this is to setup the project for longevity and allow for community maintenance.
|
||||||
|
|
||||||
|
Migrating your installation should be as simple as changing `image: ghcr.io/benphelps/homepage:latest` to `image: ghcr.io/gethomepage/homepage:latest`.
|
||||||
@@ -17,7 +17,7 @@ hide:
|
|||||||
|
|
||||||
All service widgets work essentially the same, that is, homepage makes a proxied call to an API made available by that service. The majority of the time widgets don't work it is a configuration issue. Of course, sometimes things do break. Some basic steps to try:
|
All service widgets work essentially the same, that is, homepage makes a proxied call to an API made available by that service. The majority of the time widgets don't work it is a configuration issue. Of course, sometimes things do break. Some basic steps to try:
|
||||||
|
|
||||||
1. Ensure that you follow the rule mentioned on https://gethomepage.dev/en/configs/service-widgets/. **Unless otherwise noted, URLs should not end with a / or other API path. Each widget will handle the path on its own.**. This is very important as including a trailing slash can result in an error.
|
1. Ensure that you follow the rule mentioned on https://gethomepage.dev/latest/configs/service-widgets/. **Unless otherwise noted, URLs should not end with a / or other API path. Each widget will handle the path on its own.**. This is very important as including a trailing slash can result in an error.
|
||||||
|
|
||||||
2. Verify the homepage installation can connect to the IP address or host you are using for the widget `url`. This is most simply achieved by pinging the server from the homepage machine, in Docker this means _from inside the container_ itself, e.g.:
|
2. Verify the homepage installation can connect to the IP address or host you are using for the widget `url`. This is most simply achieved by pinging the server from the homepage machine, in Docker this means _from inside the container_ itself, e.g.:
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ description: Glances Widget Configuration
|
|||||||
|
|
||||||
<img width="1614" alt="glances" src="https://github.com/benphelps/homepage-docs/assets/82196/25648c97-2c1b-4db0-b5a5-f1509806079c">
|
<img width="1614" alt="glances" src="https://github.com/benphelps/homepage-docs/assets/82196/25648c97-2c1b-4db0-b5a5-f1509806079c">
|
||||||
|
|
||||||
_(Find the Glances information widget [here](../services/glances.md))_
|
_(Find the Glances information widget [here](../info/glances.md))_
|
||||||
|
|
||||||
The Glances widget allows you to monitor the resources (cpu, memory, diskio, sensors & processes) of host or another machine. You can have multiple instances by adding another service block.
|
The Glances widget allows you to monitor the resources (cpu, memory, diskio, sensors & processes) of host or another machine. You can have multiple instances by adding another service block.
|
||||||
|
|
||||||
|
|||||||
17
mkdocs.yml
17
mkdocs.yml
@@ -63,7 +63,6 @@ nav:
|
|||||||
- widgets/services/homeassistant.md
|
- widgets/services/homeassistant.md
|
||||||
- widgets/services/homebridge.md
|
- widgets/services/homebridge.md
|
||||||
- widgets/services/immich.md
|
- widgets/services/immich.md
|
||||||
- widgets/services/index.md
|
|
||||||
- widgets/services/jackett.md
|
- widgets/services/jackett.md
|
||||||
- widgets/services/jdownloader.md
|
- widgets/services/jdownloader.md
|
||||||
- widgets/services/jellyfin.md
|
- widgets/services/jellyfin.md
|
||||||
@@ -193,6 +192,13 @@ extra_css:
|
|||||||
extra:
|
extra:
|
||||||
version:
|
version:
|
||||||
provider: mike
|
provider: mike
|
||||||
|
social:
|
||||||
|
- icon: fontawesome/brands/discord
|
||||||
|
link: https://discord.gg/k4ruYNrudu
|
||||||
|
- icon: fontawesome/regular/message
|
||||||
|
link: https://github.com/benphelps/homepage/discussions
|
||||||
|
- icon: fontawesome/brands/github
|
||||||
|
link: https://github.com/benphelps/homepage
|
||||||
|
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- pymdownx.highlight:
|
- pymdownx.highlight:
|
||||||
@@ -216,10 +222,13 @@ markdown_extensions:
|
|||||||
- admonition
|
- admonition
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
- tags
|
- group:
|
||||||
- typeset
|
enabled: !ENV MKINSIDERS
|
||||||
# - social
|
plugins:
|
||||||
- optimize
|
- optimize
|
||||||
|
- typeset
|
||||||
|
- social
|
||||||
|
- tags
|
||||||
- search:
|
- search:
|
||||||
pipeline:
|
pipeline:
|
||||||
- stemmer
|
- stemmer
|
||||||
|
|||||||
@@ -80,7 +80,9 @@
|
|||||||
},
|
},
|
||||||
"ping": {
|
"ping": {
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
"ping": "Ping"
|
"ping": "Ping",
|
||||||
|
"down": "Down",
|
||||||
|
"up": "Up"
|
||||||
},
|
},
|
||||||
"emby": {
|
"emby": {
|
||||||
"playing": "Playing",
|
"playing": "Playing",
|
||||||
|
|||||||
@@ -300,8 +300,8 @@
|
|||||||
"73-night": "Nevada",
|
"73-night": "Nevada",
|
||||||
"75-day": "Fuertes Nevadas",
|
"75-day": "Fuertes Nevadas",
|
||||||
"75-night": "Fuertes Nevadas",
|
"75-night": "Fuertes Nevadas",
|
||||||
"77-day": "Nevada Leve",
|
"77-day": "Granizada",
|
||||||
"77-night": "Nevada Leve",
|
"77-night": "Granizada",
|
||||||
"80-day": "Llovizna",
|
"80-day": "Llovizna",
|
||||||
"80-night": "Llovizna",
|
"80-night": "Llovizna",
|
||||||
"81-day": "Lluvia",
|
"81-day": "Lluvia",
|
||||||
@@ -741,8 +741,8 @@
|
|||||||
"absolutePower": "Encender"
|
"absolutePower": "Encender"
|
||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"physicalRelease": "Physical release",
|
"physicalRelease": "Lanzamiento en físico",
|
||||||
"inCinemas": "In cinemas",
|
"inCinemas": "En cine",
|
||||||
"digitalRelease": "Digital release"
|
"digitalRelease": "Lanzamiento en digital"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -527,7 +527,7 @@
|
|||||||
"alertstriggered": "Alertes déclenchées"
|
"alertstriggered": "Alertes déclenchées"
|
||||||
},
|
},
|
||||||
"nextcloud": {
|
"nextcloud": {
|
||||||
"freespace": "Espace Libre",
|
"freespace": "Libre",
|
||||||
"activeusers": "Utilisateurs Actifs",
|
"activeusers": "Utilisateurs Actifs",
|
||||||
"cpuload": "Charge Cpu",
|
"cpuload": "Charge Cpu",
|
||||||
"memoryusage": "Utilisation Mémoire",
|
"memoryusage": "Utilisation Mémoire",
|
||||||
@@ -741,8 +741,8 @@
|
|||||||
"absolutePower": "Puissance"
|
"absolutePower": "Puissance"
|
||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"physicalRelease": "Physical release",
|
"physicalRelease": "Release physique",
|
||||||
"inCinemas": "In cinemas",
|
"inCinemas": "En salle",
|
||||||
"digitalRelease": "Digital release"
|
"digitalRelease": "Release digitale"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -735,14 +735,14 @@
|
|||||||
"unknown": "Sconosciuto"
|
"unknown": "Sconosciuto"
|
||||||
},
|
},
|
||||||
"opendtu": {
|
"opendtu": {
|
||||||
"relativePower": "Power %",
|
"relativePower": "Potenza %",
|
||||||
"yieldDay": "Today",
|
"yieldDay": "Oggi",
|
||||||
"limit": "Limit",
|
"limit": "Limite",
|
||||||
"absolutePower": "Power"
|
"absolutePower": "Potenza"
|
||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"physicalRelease": "Physical release",
|
"physicalRelease": "Release fisici",
|
||||||
"inCinemas": "In cinemas",
|
"inCinemas": "Al cinema",
|
||||||
"digitalRelease": "Digital release"
|
"digitalRelease": "Digital release"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export default function Item({ service, group }) {
|
|||||||
const hasLink = service.href && service.href !== "#";
|
const hasLink = service.href && service.href !== "#";
|
||||||
const { settings } = useContext(SettingsContext);
|
const { settings } = useContext(SettingsContext);
|
||||||
const showStats = (service.showStats === false) ? false : settings.showStats;
|
const showStats = (service.showStats === false) ? false : settings.showStats;
|
||||||
|
const statusStyle = (service.statusStyle !== undefined) ? service.statusStyle : settings.statusStyle;
|
||||||
const [statsOpen, setStatsOpen] = useState(service.showStats);
|
const [statsOpen, setStatsOpen] = useState(service.showStats);
|
||||||
const [statsClosing, setStatsClosing] = useState(false);
|
const [statsClosing, setStatsClosing] = useState(false);
|
||||||
|
|
||||||
@@ -76,10 +77,10 @@ export default function Item({ service, group }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="absolute top-0 right-0 flex flex-row justify-end gap-2 mr-2 z-30 service-tags">
|
<div className={`absolute top-0 right-0 flex flex-row justify-end ${statusStyle === 'dot' ? 'gap-0' : 'gap-2'} mr-2 z-30 service-tags`}>
|
||||||
{service.ping && (
|
{service.ping && (
|
||||||
<div className="flex-shrink-0 flex items-center justify-center service-tag service-ping">
|
<div className="flex-shrink-0 flex items-center justify-center service-tag service-ping">
|
||||||
<Ping group={group} service={service.name} style={service.statusStyle} />
|
<Ping group={group} service={service.name} style={statusStyle} />
|
||||||
<span className="sr-only">Ping status</span>
|
<span className="sr-only">Ping status</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -90,7 +91,7 @@ export default function Item({ service, group }) {
|
|||||||
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
|
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
|
||||||
className="flex-shrink-0 flex items-center justify-center cursor-pointer service-tag service-container-stats"
|
className="flex-shrink-0 flex items-center justify-center cursor-pointer service-tag service-container-stats"
|
||||||
>
|
>
|
||||||
<Status service={service} />
|
<Status service={service} style={statusStyle} />
|
||||||
<span className="sr-only">View container stats</span>
|
<span className="sr-only">View container stats</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
@@ -100,7 +101,7 @@ export default function Item({ service, group }) {
|
|||||||
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
|
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
|
||||||
className="flex-shrink-0 flex items-center justify-center cursor-pointer service-tag service-app"
|
className="flex-shrink-0 flex items-center justify-center cursor-pointer service-tag service-app"
|
||||||
>
|
>
|
||||||
<KubernetesStatus service={service} />
|
<KubernetesStatus service={service} style={statusStyle} />
|
||||||
<span className="sr-only">View container stats</span>
|
<span className="sr-only">View container stats</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,35 +1,42 @@
|
|||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { t } from "i18next";
|
import { t } from "i18next";
|
||||||
|
|
||||||
export default function KubernetesStatus({ service }) {
|
export default function KubernetesStatus({ service, style }) {
|
||||||
const podSelectorString = service.podSelector !== undefined ? `podSelector=${service.podSelector}` : "";
|
const podSelectorString = service.podSelector !== undefined ? `podSelector=${service.podSelector}` : "";
|
||||||
const { data, error } = useSWR(`/api/kubernetes/status/${service.namespace}/${service.app}?${podSelectorString}`);
|
const { data, error } = useSWR(`/api/kubernetes/status/${service.namespace}/${service.app}?${podSelectorString}`);
|
||||||
|
|
||||||
|
let statusLabel = t("docker.unknown");
|
||||||
|
let statusTitle = "";
|
||||||
|
let backgroundClass = "px-1.5 py-0.5 bg-theme-500/10 dark:bg-theme-900/50";
|
||||||
|
let colorClass = "text-black/20 dark:text-white/40 ";
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status-error" title={t("docker.error")}>
|
statusTitle = t("docker.error");
|
||||||
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
|
statusLabel = statusTitle;
|
||||||
</div>
|
colorClass = "text-rose-500/80";
|
||||||
|
} else if (data) {
|
||||||
|
if (data.status === "running") {
|
||||||
|
statusTitle = data.health ?? data.status;
|
||||||
|
statusLabel = statusTitle;
|
||||||
|
colorClass = "text-emerald-500/80";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data && data.status === "running") {
|
if (data.status === "not found" || data.status === "down" || data.status === "partial") {
|
||||||
return (
|
statusTitle = data.status;
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status" title={data.health ?? data.status}>
|
statusLabel = statusTitle;
|
||||||
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{data.health ?? data.status}</div>
|
colorClass = "text-orange-400/50 dark:text-orange-400/80";
|
||||||
</div>
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data && (data.status === "not found" || data.status === "down" || data.status === "partial")) {
|
if (style === 'dot') {
|
||||||
return (
|
colorClass = colorClass.replace('text-', 'bg-').replace(/\/\d\d$/, '');
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status-warning" title={data.status}>
|
backgroundClass = "p-3 hover:bg-theme-500/10 dark:hover:bg-theme-900/20";
|
||||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{data.status}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status-unknown">
|
<div className={`w-auto text-center overflow-hidden ${backgroundClass} rounded-b-[3px] k8s-status`} title={statusTitle}>
|
||||||
<div className="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("docker.unknown")}</div>
|
{style !== 'dot' && <div className={`text-[8px] font-bold ${colorClass} uppercase`}>{statusLabel}</div>}
|
||||||
|
{style === 'dot' && <div className={`rounded-full h-3 w-3 ${colorClass}`}/>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ export default function Ping({ group, service, style }) {
|
|||||||
refreshInterval: 30000
|
refreshInterval: 30000
|
||||||
});
|
});
|
||||||
|
|
||||||
let textSize = "text-[8px]";
|
|
||||||
let colorClass = ""
|
let colorClass = ""
|
||||||
let backgroundClass = "bg-theme-500/10 dark:bg-theme-900/50";
|
let backgroundClass = "bg-theme-500/10 dark:bg-theme-900/50 px-1.5 py-0.5";
|
||||||
let statusTitle = "HTTP status";
|
let statusTitle = "HTTP status";
|
||||||
let statusText;
|
let statusText;
|
||||||
|
|
||||||
@@ -26,11 +25,7 @@ export default function Ping({ group, service, style }) {
|
|||||||
statusTitle += ` ${data.status}`
|
statusTitle += ` ${data.status}`
|
||||||
|
|
||||||
if (style === "basic") {
|
if (style === "basic") {
|
||||||
statusText = t("docker.offline")
|
statusText = t("ping.down")
|
||||||
} else if (style === "dot") {
|
|
||||||
statusText = "◉"
|
|
||||||
textSize = "text-[14px]"
|
|
||||||
backgroundClass = ""
|
|
||||||
} else {
|
} else {
|
||||||
statusText = data.status
|
statusText = data.status
|
||||||
}
|
}
|
||||||
@@ -40,19 +35,22 @@ export default function Ping({ group, service, style }) {
|
|||||||
colorClass = "text-emerald-500/80"
|
colorClass = "text-emerald-500/80"
|
||||||
|
|
||||||
if (style === "basic") {
|
if (style === "basic") {
|
||||||
statusText = t("docker.running")
|
statusText = t("ping.up")
|
||||||
} else if (style === "dot") {
|
|
||||||
statusText = "◉"
|
|
||||||
textSize = "text-[14px]"
|
|
||||||
backgroundClass = ""
|
|
||||||
} else {
|
} else {
|
||||||
statusText = ping
|
statusText = ping
|
||||||
|
colorClass += " lowercase"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (style === "dot") {
|
||||||
|
backgroundClass = 'p-3';
|
||||||
|
colorClass = colorClass.replace('text-', 'bg-').replace(/\/\d\d$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`w-auto px-1.5 py-0.5 text-center rounded-b-[3px] overflow-hidden ping-status-invalid ${backgroundClass}`} title={statusTitle}>
|
<div className={`w-auto text-center rounded-b-[3px] overflow-hidden ping-status ${backgroundClass}`} title={statusTitle}>
|
||||||
<div className={`font-bold uppercase ${textSize} ${colorClass}`}>{statusText}</div>
|
{style !== 'dot' && <div className={`font-bold uppercase text-[8px] ${colorClass}`}>{statusText}</div>}
|
||||||
|
{style === 'dot' && <div className={`rounded-full h-3 w-3 ${colorClass}`}/>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +1,58 @@
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
export default function Status({ service }) {
|
export default function Status({ service, style }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { data, error } = useSWR(`/api/docker/status/${service.container}/${service.server || ""}`);
|
const { data, error } = useSWR(`/api/docker/status/${service.container}/${service.server || ""}`);
|
||||||
|
|
||||||
|
let statusLabel = t("docker.unknown");
|
||||||
|
let statusTitle = "";
|
||||||
|
let backgroundClass = "px-1.5 py-0.5 bg-theme-500/10 dark:bg-theme-900/50";
|
||||||
|
let colorClass = "text-black/20 dark:text-white/40 ";
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-error" title={t("docker.error")}>
|
statusTitle = t("docker.error");
|
||||||
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
|
colorClass = "text-rose-500/80";
|
||||||
</div>
|
} else if (data) {
|
||||||
}
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
let statusLabel = "";
|
|
||||||
|
|
||||||
if (data.status?.includes("running")) {
|
if (data.status?.includes("running")) {
|
||||||
if (data.health === "starting") {
|
if (data.health === "starting") {
|
||||||
return (
|
statusTitle = t("docker.starting");
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-starting" title={t("docker.starting")}>
|
colorClass = "text-blue-500/80";
|
||||||
<div className="text-[8px] font-bold text-blue-500/80 uppercase">{t("docker.starting")}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.health === "unhealthy") {
|
if (data.health === "unhealthy") {
|
||||||
return (
|
statusTitle = t("docker.unhealthy");
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-unhealthy" title={t("docker.unhealthy")}>
|
colorClass = "text-orange-400/50 dark:text-orange-400/80";
|
||||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{t("docker.unhealthy")}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.health) {
|
if (!data.health) {
|
||||||
statusLabel = data.status.replace("running", t("docker.running"))
|
statusLabel = data.status.replace("running", t("docker.running"));
|
||||||
} else {
|
} else {
|
||||||
statusLabel = data.health === "healthy" ? t("docker.healthy") : data.health
|
statusLabel = data.health === "healthy" ? t("docker.healthy") : data.health;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
statusTitle = statusLabel;
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-status" title={statusLabel}>
|
colorClass = "text-emerald-500/80";
|
||||||
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{statusLabel}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.status === "not found" || data.status === "exited" || data.status?.startsWith("partial")) {
|
if (data.status === "not found" || data.status === "exited" || data.status?.startsWith("partial")) {
|
||||||
if (data.status === "not found") statusLabel = t("docker.not_found")
|
if (data.status === "not found") statusLabel = t("docker.not_found")
|
||||||
else if (data.status === "exited") statusLabel = t("docker.exited")
|
else if (data.status === "exited") statusLabel = t("docker.exited")
|
||||||
else statusLabel = data.status.replace("partial", t("docker.partial"))
|
else statusLabel = data.status.replace("partial", t("docker.partial"))
|
||||||
return (
|
colorClass = "text-orange-400/50 dark:text-orange-400/80";
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-status-warning" title={statusLabel}>
|
|
||||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{statusLabel}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (style === 'dot') {
|
||||||
|
colorClass = colorClass.replace('text-', 'bg-').replace(/\/\d\d$/, '');
|
||||||
|
backgroundClass = "p-3 hover:bg-theme-500/10 dark:hover:bg-theme-900/20";
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-status-unknown">
|
<div className={`w-auto text-center overflow-hidden ${backgroundClass} rounded-b-[3px] docker-status`} title={statusTitle}>
|
||||||
<div className="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("docker.unknown")}</div>
|
{style !== 'dot' && <div className={`text-[8px] font-bold ${colorClass} uppercase`}>{statusLabel}</div>}
|
||||||
|
{style === 'dot' && <div className={`rounded-full h-3 w-3 ${colorClass}`}/>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import ErrorBoundary from "components/errorboundry";
|
|||||||
import themes from "utils/styles/themes";
|
import themes from "utils/styles/themes";
|
||||||
import QuickLaunch from "components/quicklaunch";
|
import QuickLaunch from "components/quicklaunch";
|
||||||
import { getStoredProvider, searchProviders } from "components/widgets/search/search";
|
import { getStoredProvider, searchProviders } from "components/widgets/search/search";
|
||||||
|
import ResolvedIcon from "components/resolvedicon";
|
||||||
|
|
||||||
const ThemeToggle = dynamic(() => import("components/toggles/theme"), {
|
const ThemeToggle = dynamic(() => import("components/toggles/theme"), {
|
||||||
ssr: false,
|
ssr: false,
|
||||||
@@ -167,6 +168,17 @@ const headerStyles = {
|
|||||||
boxedWidgets: "m-6 mb-0 sm:m-9 sm:mb-0 sm:mt-1",
|
boxedWidgets: "m-6 mb-0 sm:m-9 sm:mb-0 sm:mt-1",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const deprecatedNotificationDismissedStorageKey = "deprecated-notification-dismissed";
|
||||||
|
|
||||||
|
const getNotificationDismissed = () => {
|
||||||
|
if (typeof window !== "undefined" && window.localStorage) {
|
||||||
|
const dismissed = window.localStorage.getItem(deprecatedNotificationDismissedStorageKey);
|
||||||
|
return dismissed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
function Home({ initialSettings }) {
|
function Home({ initialSettings }) {
|
||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
const { theme, setTheme } = useContext(ThemeContext);
|
const { theme, setTheme } = useContext(ThemeContext);
|
||||||
@@ -175,6 +187,9 @@ function Home({ initialSettings }) {
|
|||||||
const { activeTab, setActiveTab } = useContext(TabContext);
|
const { activeTab, setActiveTab } = useContext(TabContext);
|
||||||
const { asPath } = useRouter();
|
const { asPath } = useRouter();
|
||||||
|
|
||||||
|
const isDeprecatedRepo = process.env.NEXT_PUBLIC_DEPRECATED_REPO;
|
||||||
|
const [notificationDismissed, setNotificationDismissed] = useState(getNotificationDismissed);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSettings(initialSettings);
|
setSettings(initialSettings);
|
||||||
}, [initialSettings, setSettings]);
|
}, [initialSettings, setSettings]);
|
||||||
@@ -420,6 +435,23 @@ function Home({ initialSettings }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="version" className="flex mt-4 w-full justify-end">
|
<div id="version" className="flex mt-4 w-full justify-end">
|
||||||
|
{isDeprecatedRepo && !notificationDismissed && // outside version in case its hidden
|
||||||
|
<div className="flex flex-row items-center py-1 pl-2 mr-3 rounded-md text-xs text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-rose-900/80">
|
||||||
|
<a className="italic flex flex-row items-center" href="https://gethomepage.dev/latest/more/homepage-move/" title="Read more..." target="_blank" rel="noreferrer">
|
||||||
|
<span className="inline-block flex-shrink-0 mr-1 w-3 h-3">
|
||||||
|
<ResolvedIcon icon="mdi-alert" />
|
||||||
|
</span>
|
||||||
|
Homepage has moved!
|
||||||
|
</a>
|
||||||
|
<button type="button" className="ml-2 w-4 h-4 mr-1" title="Hide this notification"
|
||||||
|
onClick={() => {
|
||||||
|
setNotificationDismissed(true);
|
||||||
|
localStorage.setItem(deprecatedNotificationDismissedStorageKey, true);
|
||||||
|
}}>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
{!settings.hideVersion && <Version />}
|
{!settings.hideVersion && <Version />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
# For configuration options and examples, please see:
|
# For configuration options and examples, please see:
|
||||||
# https://gethomepage.dev/en/configs/bookmarks
|
# https://gethomepage.dev/latest/configs/bookmarks
|
||||||
|
|
||||||
- Developer:
|
- Developer:
|
||||||
- Github:
|
- Github:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
# For configuration options and examples, please see:
|
# For configuration options and examples, please see:
|
||||||
# https://gethomepage.dev/en/configs/docker/
|
# https://gethomepage.dev/latest/configs/docker/
|
||||||
|
|
||||||
# my-docker:
|
# my-docker:
|
||||||
# host: 127.0.0.1
|
# host: 127.0.0.1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
# For configuration options and examples, please see:
|
# For configuration options and examples, please see:
|
||||||
# https://gethomepage.dev/en/configs/services
|
# https://gethomepage.dev/latest/configs/services
|
||||||
|
|
||||||
- My First Group:
|
- My First Group:
|
||||||
- My First Service:
|
- My First Service:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
# For configuration options and examples, please see:
|
# For configuration options and examples, please see:
|
||||||
# https://gethomepage.dev/en/configs/settings
|
# https://gethomepage.dev/latest/configs/settings
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
openweathermap: openweathermapapikey
|
openweathermap: openweathermapapikey
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
# For configuration options and examples, please see:
|
# For configuration options and examples, please see:
|
||||||
# https://gethomepage.dev/en/configs/widgets
|
# https://gethomepage.dev/latest/configs/widgets
|
||||||
|
|
||||||
- resources:
|
- resources:
|
||||||
cpu: true
|
cpu: true
|
||||||
|
|||||||
@@ -259,6 +259,9 @@ export async function servicesFromKubernetes() {
|
|||||||
if (ingress.metadata.annotations[`${ANNOTATION_BASE}/ping`]) {
|
if (ingress.metadata.annotations[`${ANNOTATION_BASE}/ping`]) {
|
||||||
constructedService.ping = ingress.metadata.annotations[`${ANNOTATION_BASE}/ping`];
|
constructedService.ping = ingress.metadata.annotations[`${ANNOTATION_BASE}/ping`];
|
||||||
}
|
}
|
||||||
|
if (ingress.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`]) {
|
||||||
|
constructedService.statusStyle = ingress.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`];
|
||||||
|
}
|
||||||
Object.keys(ingress.metadata.annotations).forEach((annotation) => {
|
Object.keys(ingress.metadata.annotations).forEach((annotation) => {
|
||||||
if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) {
|
if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) {
|
||||||
shvl.set(
|
shvl.set(
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ export default function MonthlyView({ service }) {
|
|||||||
return <div className="w-full text-center">
|
return <div className="w-full text-center">
|
||||||
<div className="flex-col">
|
<div className="flex-col">
|
||||||
<span><button type="button" onClick={ () => setShowDate(showDate.minus({ months: 1 }).startOf("day")) } className={classNames(monthButton)}><</button></span>
|
<span><button type="button" onClick={ () => setShowDate(showDate.minus({ months: 1 }).startOf("day")) } className={classNames(monthButton)}><</button></span>
|
||||||
<span>{ showDate.setLocale(i18n.language).toFormat("MMMM y") }</span>
|
<span><button type="button" onClick={ () => setShowDate(currentDate.startOf("day")) }>{ showDate.setLocale(i18n.language).toFormat("MMMM y") }</button></span>
|
||||||
<span><button type="button" onClick={ () => setShowDate(showDate.plus({ months: 1 }).startOf("day")) } className={classNames(monthButton)}>></button></span>
|
<span><button type="button" onClick={ () => setShowDate(showDate.plus({ months: 1 }).startOf("day")) } className={classNames(monthButton)}>></button></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user