mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-05 21:47:48 +01: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:
|
||||
|
||||
- [The troubleshooting guide](https://gethomepage.dev/en/more/troubleshooting/).
|
||||
- [The troubleshooting guide](https://gethomepage.dev/latest/more/troubleshooting/).
|
||||
- [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).
|
||||
- type: textarea
|
||||
@@ -78,7 +78,7 @@ body:
|
||||
id: troubleshooting
|
||||
attributes:
|
||||
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:
|
||||
required: true
|
||||
- type: textarea
|
||||
@@ -93,7 +93,7 @@ body:
|
||||
options:
|
||||
- label: Check [the documentation](https://gethomepage.dev/)
|
||||
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
|
||||
- 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
|
||||
|
||||
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 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.
|
||||
|
||||
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)
|
||||
@@ -20,11 +20,12 @@ What type of change does your PR introduce to Homepage?
|
||||
- [ ] New service widget
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Documentation only
|
||||
- [ ] Other (please explain)
|
||||
|
||||
## Checklist:
|
||||
|
||||
- [ ] If adding a service widget or a change that requires it, I have added corresponding documentation.
|
||||
- [ ] If adding a new widget I have reviewed the [guidelines](https://gethomepage.dev/en/more/development/#service-widget-guidelines).
|
||||
- [ ] 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/latest/more/development/#service-widget-guidelines).
|
||||
- [ ] 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.
|
||||
|
||||
12
.github/workflows/docker-publish.yml
vendored
12
.github/workflows/docker-publish.yml
vendored
@@ -12,8 +12,14 @@ on:
|
||||
branches: [ "main" ]
|
||||
# Publish semver tags as releases.
|
||||
tags: [ 'v*.*.*' ]
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- 'mkdocs.yml'
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- 'mkdocs.yml'
|
||||
|
||||
env:
|
||||
# Use docker.io for Docker Hub if empty
|
||||
@@ -24,7 +30,8 @@ env:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
name: Docker Build & Push
|
||||
if: github.repository == 'benphelps/homepage'
|
||||
runs-on: self-hosted
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -40,7 +47,7 @@ jobs:
|
||||
# Install the cosign tool except on PR
|
||||
# https://github.com/sigstore/cosign-installer
|
||||
- name: Install cosign
|
||||
if: github.event_name != 'pull_request'
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: sigstore/cosign-installer@main
|
||||
with:
|
||||
cosign-release: 'v1.13.1' # optional
|
||||
@@ -98,6 +105,7 @@ jobs:
|
||||
BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
|
||||
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
|
||||
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
|
||||
# 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
|
||||
|
||||
44
.github/workflows/docs-publish.yml
vendored
44
.github/workflows/docs-publish.yml
vendored
@@ -4,13 +4,43 @@ on:
|
||||
push:
|
||||
tags: [ 'v*.*.*' ]
|
||||
branches: ['main']
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'mkdocs.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'mkdocs.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
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:
|
||||
name: Build & Deploy
|
||||
if: github.repository == 'benphelps/homepage' && github.event_name != 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -26,7 +56,7 @@ jobs:
|
||||
path: .cache
|
||||
restore-keys: |
|
||||
mkdocs-material-
|
||||
- run: sudo apt-get install pngquant
|
||||
- run: sudo apt-get install pngquant
|
||||
- run: pip install mike
|
||||
- run: pip install git+https://${GH_TOKEN}@github.com/benphelps/mkdocs-material-insiders.git
|
||||
- name: Set Git config
|
||||
@@ -39,11 +69,11 @@ jobs:
|
||||
git checkout gh-pages
|
||||
git pull origin gh-pages
|
||||
git checkout main
|
||||
- name: Mike Deploy for Main
|
||||
- name: Docs Deploy for Main
|
||||
if: github.ref == 'refs/heads/main'
|
||||
run: mike deploy --update --push ${{github.ref_name}}
|
||||
- name: Mike Deploy for Tags
|
||||
run: MKINSIDERS=true mike deploy --update --push ${{github.ref_name}}
|
||||
- name: Docs Deploy for Tags
|
||||
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:
|
||||
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
|
||||
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.
|
||||
|
||||
## 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
|
||||
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 VERSION
|
||||
ARG REVISION
|
||||
ARG DEPRECATED_REPO
|
||||
|
||||
COPY --link --from=deps /app/node_modules ./node_modules/
|
||||
COPY . .
|
||||
@@ -30,7 +31,7 @@ COPY . .
|
||||
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
|
||||
RUN npm run telemetry \
|
||||
&& 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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
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.
|
||||
|
||||
<!-- TODO: Insert images of the new status styles there -->
|
||||
You can also apply different styles to the ping indicator by using the `statusStyle` property, see [settings](settings.md#status-style).
|
||||
|
||||
## Docker Integration
|
||||
|
||||
|
||||
@@ -380,6 +380,30 @@ or per-service (`services.yaml`) with:
|
||||
|
||||
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 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:
|
||||
|
||||
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.:
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
_(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.
|
||||
|
||||
|
||||
17
mkdocs.yml
17
mkdocs.yml
@@ -63,7 +63,6 @@ nav:
|
||||
- widgets/services/homeassistant.md
|
||||
- widgets/services/homebridge.md
|
||||
- widgets/services/immich.md
|
||||
- widgets/services/index.md
|
||||
- widgets/services/jackett.md
|
||||
- widgets/services/jdownloader.md
|
||||
- widgets/services/jellyfin.md
|
||||
@@ -193,6 +192,13 @@ extra_css:
|
||||
extra:
|
||||
version:
|
||||
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:
|
||||
- pymdownx.highlight:
|
||||
@@ -216,10 +222,13 @@ markdown_extensions:
|
||||
- admonition
|
||||
|
||||
plugins:
|
||||
- group:
|
||||
enabled: !ENV MKINSIDERS
|
||||
plugins:
|
||||
- optimize
|
||||
- typeset
|
||||
- social
|
||||
- tags
|
||||
- typeset
|
||||
# - social
|
||||
- optimize
|
||||
- search:
|
||||
pipeline:
|
||||
- stemmer
|
||||
|
||||
@@ -80,7 +80,9 @@
|
||||
},
|
||||
"ping": {
|
||||
"error": "Error",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"down": "Down",
|
||||
"up": "Up"
|
||||
},
|
||||
"emby": {
|
||||
"playing": "Playing",
|
||||
|
||||
@@ -300,8 +300,8 @@
|
||||
"73-night": "Nevada",
|
||||
"75-day": "Fuertes Nevadas",
|
||||
"75-night": "Fuertes Nevadas",
|
||||
"77-day": "Nevada Leve",
|
||||
"77-night": "Nevada Leve",
|
||||
"77-day": "Granizada",
|
||||
"77-night": "Granizada",
|
||||
"80-day": "Llovizna",
|
||||
"80-night": "Llovizna",
|
||||
"81-day": "Lluvia",
|
||||
@@ -741,8 +741,8 @@
|
||||
"absolutePower": "Encender"
|
||||
},
|
||||
"calendar": {
|
||||
"physicalRelease": "Physical release",
|
||||
"inCinemas": "In cinemas",
|
||||
"digitalRelease": "Digital release"
|
||||
"physicalRelease": "Lanzamiento en físico",
|
||||
"inCinemas": "En cine",
|
||||
"digitalRelease": "Lanzamiento en digital"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,7 +527,7 @@
|
||||
"alertstriggered": "Alertes déclenchées"
|
||||
},
|
||||
"nextcloud": {
|
||||
"freespace": "Espace Libre",
|
||||
"freespace": "Libre",
|
||||
"activeusers": "Utilisateurs Actifs",
|
||||
"cpuload": "Charge Cpu",
|
||||
"memoryusage": "Utilisation Mémoire",
|
||||
@@ -741,8 +741,8 @@
|
||||
"absolutePower": "Puissance"
|
||||
},
|
||||
"calendar": {
|
||||
"physicalRelease": "Physical release",
|
||||
"inCinemas": "In cinemas",
|
||||
"digitalRelease": "Digital release"
|
||||
"physicalRelease": "Release physique",
|
||||
"inCinemas": "En salle",
|
||||
"digitalRelease": "Release digitale"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,14 +735,14 @@
|
||||
"unknown": "Sconosciuto"
|
||||
},
|
||||
"opendtu": {
|
||||
"relativePower": "Power %",
|
||||
"yieldDay": "Today",
|
||||
"limit": "Limit",
|
||||
"absolutePower": "Power"
|
||||
"relativePower": "Potenza %",
|
||||
"yieldDay": "Oggi",
|
||||
"limit": "Limite",
|
||||
"absolutePower": "Potenza"
|
||||
},
|
||||
"calendar": {
|
||||
"physicalRelease": "Physical release",
|
||||
"inCinemas": "In cinemas",
|
||||
"physicalRelease": "Release fisici",
|
||||
"inCinemas": "Al cinema",
|
||||
"digitalRelease": "Digital release"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ export default function Item({ service, group }) {
|
||||
const hasLink = service.href && service.href !== "#";
|
||||
const { settings } = useContext(SettingsContext);
|
||||
const showStats = (service.showStats === false) ? false : settings.showStats;
|
||||
const statusStyle = (service.statusStyle !== undefined) ? service.statusStyle : settings.statusStyle;
|
||||
const [statsOpen, setStatsOpen] = useState(service.showStats);
|
||||
const [statsClosing, setStatsClosing] = useState(false);
|
||||
|
||||
@@ -76,10 +77,10 @@ export default function Item({ service, group }) {
|
||||
</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 && (
|
||||
<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>
|
||||
</div>
|
||||
)}
|
||||
@@ -90,7 +91,7 @@ export default function Item({ service, group }) {
|
||||
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
|
||||
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>
|
||||
</button>
|
||||
)}
|
||||
@@ -100,7 +101,7 @@ export default function Item({ service, group }) {
|
||||
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
|
||||
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>
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -1,35 +1,42 @@
|
||||
import useSWR from "swr";
|
||||
import { t } from "i18next";
|
||||
|
||||
export default function KubernetesStatus({ service }) {
|
||||
export default function KubernetesStatus({ service, style }) {
|
||||
const podSelectorString = service.podSelector !== undefined ? `podSelector=${service.podSelector}` : "";
|
||||
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) {
|
||||
<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")}>
|
||||
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
|
||||
</div>
|
||||
statusTitle = t("docker.error");
|
||||
statusLabel = statusTitle;
|
||||
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.status === "not found" || data.status === "down" || data.status === "partial") {
|
||||
statusTitle = data.status;
|
||||
statusLabel = statusTitle;
|
||||
colorClass = "text-orange-400/50 dark:text-orange-400/80";
|
||||
}
|
||||
}
|
||||
|
||||
if (data && data.status === "running") {
|
||||
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" title={data.health ?? data.status}>
|
||||
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{data.health ?? data.status}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (data && (data.status === "not found" || data.status === "down" || data.status === "partial")) {
|
||||
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-warning" title={data.status}>
|
||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{data.status}</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 (
|
||||
<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="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("docker.unknown")}</div>
|
||||
<div className={`w-auto text-center overflow-hidden ${backgroundClass} rounded-b-[3px] k8s-status`} title={statusTitle}>
|
||||
{style !== 'dot' && <div className={`text-[8px] font-bold ${colorClass} uppercase`}>{statusLabel}</div>}
|
||||
{style === 'dot' && <div className={`rounded-full h-3 w-3 ${colorClass}`}/>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,9 +7,8 @@ export default function Ping({ group, service, style }) {
|
||||
refreshInterval: 30000
|
||||
});
|
||||
|
||||
let textSize = "text-[8px]";
|
||||
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 statusText;
|
||||
|
||||
@@ -26,11 +25,7 @@ export default function Ping({ group, service, style }) {
|
||||
statusTitle += ` ${data.status}`
|
||||
|
||||
if (style === "basic") {
|
||||
statusText = t("docker.offline")
|
||||
} else if (style === "dot") {
|
||||
statusText = "◉"
|
||||
textSize = "text-[14px]"
|
||||
backgroundClass = ""
|
||||
statusText = t("ping.down")
|
||||
} else {
|
||||
statusText = data.status
|
||||
}
|
||||
@@ -40,19 +35,22 @@ export default function Ping({ group, service, style }) {
|
||||
colorClass = "text-emerald-500/80"
|
||||
|
||||
if (style === "basic") {
|
||||
statusText = t("docker.running")
|
||||
} else if (style === "dot") {
|
||||
statusText = "◉"
|
||||
textSize = "text-[14px]"
|
||||
backgroundClass = ""
|
||||
statusText = t("ping.up")
|
||||
} else {
|
||||
statusText = ping
|
||||
colorClass += " lowercase"
|
||||
}
|
||||
}
|
||||
|
||||
if (style === "dot") {
|
||||
backgroundClass = 'p-3';
|
||||
colorClass = colorClass.replace('text-', 'bg-').replace(/\/\d\d$/, '');
|
||||
}
|
||||
|
||||
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={`font-bold uppercase ${textSize} ${colorClass}`}>{statusText}</div>
|
||||
<div className={`w-auto text-center rounded-b-[3px] overflow-hidden ping-status ${backgroundClass}`} title={statusTitle}>
|
||||
{style !== 'dot' && <div className={`font-bold uppercase text-[8px] ${colorClass}`}>{statusText}</div>}
|
||||
{style === 'dot' && <div className={`rounded-full h-3 w-3 ${colorClass}`}/>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,65 +1,58 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import useSWR from "swr";
|
||||
|
||||
export default function Status({ service }) {
|
||||
export default function Status({ service, style }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
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) {
|
||||
<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")}>
|
||||
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
if (data) {
|
||||
let statusLabel = "";
|
||||
|
||||
statusTitle = t("docker.error");
|
||||
colorClass = "text-rose-500/80";
|
||||
} else if (data) {
|
||||
if (data.status?.includes("running")) {
|
||||
if (data.health === "starting") {
|
||||
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-starting" title={t("docker.starting")}>
|
||||
<div className="text-[8px] font-bold text-blue-500/80 uppercase">{t("docker.starting")}</div>
|
||||
</div>
|
||||
);
|
||||
statusTitle = t("docker.starting");
|
||||
colorClass = "text-blue-500/80";
|
||||
}
|
||||
|
||||
if (data.health === "unhealthy") {
|
||||
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-unhealthy" title={t("docker.unhealthy")}>
|
||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{t("docker.unhealthy")}</div>
|
||||
</div>
|
||||
);
|
||||
statusTitle = t("docker.unhealthy");
|
||||
colorClass = "text-orange-400/50 dark:text-orange-400/80";
|
||||
}
|
||||
|
||||
if (!data.health) {
|
||||
statusLabel = data.status.replace("running", t("docker.running"))
|
||||
statusLabel = data.status.replace("running", t("docker.running"));
|
||||
} else {
|
||||
statusLabel = data.health === "healthy" ? t("docker.healthy") : data.health
|
||||
statusLabel = data.health === "healthy" ? t("docker.healthy") : data.health;
|
||||
}
|
||||
|
||||
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" title={statusLabel}>
|
||||
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{statusLabel}</div>
|
||||
</div>
|
||||
);
|
||||
statusTitle = statusLabel;
|
||||
colorClass = "text-emerald-500/80";
|
||||
}
|
||||
|
||||
if (data.status === "not found" || data.status === "exited" || data.status?.startsWith("partial")) {
|
||||
if (data.status === "not found") statusLabel = t("docker.not_found")
|
||||
else if (data.status === "exited") statusLabel = t("docker.exited")
|
||||
else statusLabel = data.status.replace("partial", t("docker.partial"))
|
||||
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-warning" title={statusLabel}>
|
||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{statusLabel}</div>
|
||||
</div>
|
||||
);
|
||||
colorClass = "text-orange-400/50 dark:text-orange-400/80";
|
||||
}
|
||||
}
|
||||
|
||||
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 (
|
||||
<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="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("docker.unknown")}</div>
|
||||
<div className={`w-auto text-center overflow-hidden ${backgroundClass} rounded-b-[3px] docker-status`} title={statusTitle}>
|
||||
{style !== 'dot' && <div className={`text-[8px] font-bold ${colorClass} uppercase`}>{statusLabel}</div>}
|
||||
{style === 'dot' && <div className={`rounded-full h-3 w-3 ${colorClass}`}/>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import ErrorBoundary from "components/errorboundry";
|
||||
import themes from "utils/styles/themes";
|
||||
import QuickLaunch from "components/quicklaunch";
|
||||
import { getStoredProvider, searchProviders } from "components/widgets/search/search";
|
||||
import ResolvedIcon from "components/resolvedicon";
|
||||
|
||||
const ThemeToggle = dynamic(() => import("components/toggles/theme"), {
|
||||
ssr: false,
|
||||
@@ -167,6 +168,17 @@ const headerStyles = {
|
||||
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 }) {
|
||||
const { i18n } = useTranslation();
|
||||
const { theme, setTheme } = useContext(ThemeContext);
|
||||
@@ -175,6 +187,9 @@ function Home({ initialSettings }) {
|
||||
const { activeTab, setActiveTab } = useContext(TabContext);
|
||||
const { asPath } = useRouter();
|
||||
|
||||
const isDeprecatedRepo = process.env.NEXT_PUBLIC_DEPRECATED_REPO;
|
||||
const [notificationDismissed, setNotificationDismissed] = useState(getNotificationDismissed);
|
||||
|
||||
useEffect(() => {
|
||||
setSettings(initialSettings);
|
||||
}, [initialSettings, setSettings]);
|
||||
@@ -420,6 +435,23 @@ function Home({ initialSettings }) {
|
||||
</div>
|
||||
|
||||
<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 />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
# For configuration options and examples, please see:
|
||||
# https://gethomepage.dev/en/configs/bookmarks
|
||||
# https://gethomepage.dev/latest/configs/bookmarks
|
||||
|
||||
- Developer:
|
||||
- Github:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
# For configuration options and examples, please see:
|
||||
# https://gethomepage.dev/en/configs/docker/
|
||||
# https://gethomepage.dev/latest/configs/docker/
|
||||
|
||||
# my-docker:
|
||||
# host: 127.0.0.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
# For configuration options and examples, please see:
|
||||
# https://gethomepage.dev/en/configs/services
|
||||
# https://gethomepage.dev/latest/configs/services
|
||||
|
||||
- My First Group:
|
||||
- My First Service:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
# For configuration options and examples, please see:
|
||||
# https://gethomepage.dev/en/configs/settings
|
||||
# https://gethomepage.dev/latest/configs/settings
|
||||
|
||||
providers:
|
||||
openweathermap: openweathermapapikey
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
# For configuration options and examples, please see:
|
||||
# https://gethomepage.dev/en/configs/widgets
|
||||
# https://gethomepage.dev/latest/configs/widgets
|
||||
|
||||
- resources:
|
||||
cpu: true
|
||||
|
||||
@@ -259,6 +259,9 @@ export async function servicesFromKubernetes() {
|
||||
if (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) => {
|
||||
if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) {
|
||||
shvl.set(
|
||||
|
||||
@@ -126,7 +126,7 @@ export default function MonthlyView({ service }) {
|
||||
return <div className="w-full text-center">
|
||||
<div className="flex-col">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user