mirror of
https://github.com/gethomepage/homepage.git
synced 2026-09-12 07:05:56 -07:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d9ad0632b | |||
| 6be85c7a47 | |||
| bd4f8094c1 | |||
| 64627f6cb2 | |||
| 9ca3934673 | |||
| 1619123057 | |||
| 1dda594682 | |||
| 31a57c60e2 | |||
| cbb5667512 | |||
| 91f3b9df5c | |||
| 593c18dc4c | |||
| c7aad6e975 | |||
| 408935b091 | |||
| bea9d4efa1 | |||
| f9b60e3cb9 | |||
| 165d4c8588 | |||
| 5485e0356a | |||
| 873bd99651 | |||
| 83a7e590eb | |||
| f8ccbdb87a | |||
| 8710a498c5 | |||
| e4fbdfb414 | |||
| 47583f3489 | |||
| c2552e5025 | |||
| 632e03e68a | |||
| de1d763b80 | |||
| 1104bac6f6 | |||
| 9cef37aed6 | |||
| 9a4dea39b0 | |||
| e7a147899c | |||
| e81aadb071 | |||
| 1e6be5cc17 | |||
| 9b1b14116b | |||
| 02a9d74c95 | |||
| e7a749782a | |||
| f8e2e8d410 | |||
| 6053ddbab6 | |||
| 11e9f28e5e |
+1
-1
@@ -8,7 +8,7 @@ coverage:
|
|||||||
status:
|
status:
|
||||||
project:
|
project:
|
||||||
default:
|
default:
|
||||||
target: 100%
|
target: auto
|
||||||
threshold: 15%
|
threshold: 15%
|
||||||
patch:
|
patch:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Extract Docker metadata
|
- name: Extract Docker metadata
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
${{ env.IMAGE_NAME }}
|
${{ env.IMAGE_NAME }}
|
||||||
@@ -61,7 +61,7 @@ jobs:
|
|||||||
nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
||||||
|
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
uses: pnpm/action-setup@26f6d4f2c533a43e6b5da0b4a5dd983f98f7b49a # v6.0.4
|
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
|
||||||
with:
|
with:
|
||||||
version: 10
|
version: 10
|
||||||
run_install: false
|
run_install: false
|
||||||
@@ -84,7 +84,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Log into registry ${{ env.REGISTRY }}
|
- name: Log into registry ${{ env.REGISTRY }}
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@@ -92,20 +92,20 @@ jobs:
|
|||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Setup QEMU
|
- name: Setup QEMU
|
||||||
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
|
||||||
|
|
||||||
- name: Setup Docker buildx
|
- name: Setup Docker buildx
|
||||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
|
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
id: build-and-push
|
id: build-and-push
|
||||||
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7
|
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
|||||||
@@ -3,14 +3,17 @@ name: Issue Triage
|
|||||||
on:
|
on:
|
||||||
issues:
|
issues:
|
||||||
types: [labeled]
|
types: [labeled]
|
||||||
|
discussion:
|
||||||
|
types: [labeled]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
|
discussions: write
|
||||||
issues: write
|
issues: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
close-needs-discussion:
|
close-needs-discussion:
|
||||||
name: Issues Need Discussion
|
name: Issues Need Discussion
|
||||||
if: github.event.label.name == 'needs-discussion'
|
if: github.event_name == 'issues' && github.event.label.name == 'needs-discussion'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||||
@@ -41,3 +44,47 @@ jobs:
|
|||||||
issue_number: issueNumber,
|
issue_number: issueNumber,
|
||||||
lock_reason: 'off-topic',
|
lock_reason: 'off-topic',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
comment-needs-information:
|
||||||
|
name: Discussions Need Information
|
||||||
|
if: github.event_name == 'discussion' && github.event.label.name == 'needs-information'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const owner = context.repo.owner;
|
||||||
|
const repo = context.repo.repo;
|
||||||
|
const discussionNumber = context.payload.discussion.number;
|
||||||
|
let discussionId = context.payload.discussion.node_id;
|
||||||
|
|
||||||
|
if (!discussionId) {
|
||||||
|
const result = await github.graphql(
|
||||||
|
`query($owner:String!, $repo:String!, $number:Int!) {
|
||||||
|
repository(owner:$owner, name:$repo) {
|
||||||
|
discussion(number:$number) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
{
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
number: discussionNumber,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
discussionId = result.repository.discussion.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
await github.graphql(
|
||||||
|
`mutation($discussion:ID!, $body:String!) {
|
||||||
|
addDiscussionComment(input:{discussionId:$discussion, body:$body}) {
|
||||||
|
clientMutationId
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
{
|
||||||
|
discussion: discussionId,
|
||||||
|
body: 'Dear homepage user, thanks for opening this discussion! Please ensure you add the output from the troubleshooting guide steps, the support template asks for those details because they usually make it possible to understand the problem without guessing. Please update the discussion with the relevant troubleshooting output, configuration, logs, and browser console details where applicable: https://gethomepage.dev/troubleshooting/. Thank you!',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ jobs:
|
|||||||
uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
|
uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
|
||||||
|
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
uses: pnpm/action-setup@26f6d4f2c533a43e6b5da0b4a5dd983f98f7b49a # v6.0.4
|
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
|
||||||
with:
|
with:
|
||||||
version: 10
|
version: 10
|
||||||
run_install: false
|
run_install: false
|
||||||
|
|||||||
@@ -16,3 +16,8 @@ jobs:
|
|||||||
- uses: peakoss/anti-slop@57858eead489d08b255fab2af45a506c2ca6eab2 # v0
|
- uses: peakoss/anti-slop@57858eead489d08b255fab2af45a506c2ca6eab2 # v0
|
||||||
with:
|
with:
|
||||||
max-failures: 4
|
max-failures: 4
|
||||||
|
failure-add-pr-labels: 'ai'
|
||||||
|
failure-pr-message: |
|
||||||
|
This pull request was automatically closed because it matched multiple low-quality or automated-PR signals.
|
||||||
|
require-pr-template: true
|
||||||
|
optional-pr-template-sections: 'Checklist:'
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
name: PR Triage
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [labeled]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
close-needs-requirements:
|
||||||
|
name: PRs Need Requirements
|
||||||
|
if: github.event.label.name == 'needs-requirements'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const pullNumber = context.payload.pull_request.number;
|
||||||
|
const owner = context.repo.owner;
|
||||||
|
const repo = context.repo.repo;
|
||||||
|
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: pullNumber,
|
||||||
|
body: 'Dear contributor, thanks for taking the time to open this pull request! It is being closed because it does not currently meet the pull request guidelines. Please review the checklist in the pull request template and the relevant [contributing guidelines](https://gethomepage.dev/widgets/authoring/getting-started/#new-feature-guidelines) before opening a new pull request.',
|
||||||
|
});
|
||||||
|
|
||||||
|
await github.rest.pulls.update({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
pull_number: pullNumber,
|
||||||
|
state: 'closed',
|
||||||
|
});
|
||||||
@@ -15,4 +15,4 @@ jobs:
|
|||||||
action:
|
action:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/reaction-comments@e86d247c12bd5c043eec379a1a4453f20cadf913 # v4
|
- uses: dessant/reaction-comments@170a79b6e2538a1df7ba669ac527d7457cd3b128 # v5.0.1
|
||||||
|
|||||||
@@ -26,14 +26,14 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- if: github.event_name == 'workflow_dispatch' && github.event.inputs.version != ''
|
- if: github.event_name == 'workflow_dispatch' && github.event.inputs.version != ''
|
||||||
uses: release-drafter/release-drafter@563bf132657a13ded0b01fcb723c5a58cdd824e2 # v7
|
uses: release-drafter/release-drafter@693d20e7c1ce1a81d3a41962f85914253b518449 # v7
|
||||||
with:
|
with:
|
||||||
config-name: release-drafter.yml
|
config-name: release-drafter.yml
|
||||||
version: ${{ github.event.inputs.version }}
|
version: ${{ github.event.inputs.version }}
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- if: github.event_name != 'workflow_dispatch' || github.event.inputs.version == ''
|
- if: github.event_name != 'workflow_dispatch' || github.event.inputs.version == ''
|
||||||
uses: release-drafter/release-drafter@563bf132657a13ded0b01fcb723c5a58cdd824e2 # v7
|
uses: release-drafter/release-drafter@693d20e7c1ce1a81d3a41962f85914253b518449 # v7
|
||||||
with:
|
with:
|
||||||
config-name: release-drafter.yml
|
config-name: release-drafter.yml
|
||||||
env:
|
env:
|
||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: release-drafter/release-drafter/autolabeler@563bf132657a13ded0b01fcb723c5a58cdd824e2
|
- uses: release-drafter/release-drafter/autolabeler@693d20e7c1ce1a81d3a41962f85914253b518449
|
||||||
with:
|
with:
|
||||||
config-name: release-drafter.yml
|
config-name: release-drafter.yml
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
name: 'Stale'
|
name: 'Stale'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10
|
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10
|
||||||
with:
|
with:
|
||||||
days-before-stale: 7
|
days-before-stale: 7
|
||||||
days-before-close: 14
|
days-before-close: 14
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
name: 'Lock Old Threads'
|
name: 'Lock Old Threads'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v6
|
- uses: dessant/lock-threads@89ae32b08ed1a541efecbab17912962a5e38981c # v6.0.2
|
||||||
with:
|
with:
|
||||||
issue-inactive-days: '30'
|
issue-inactive-days: '30'
|
||||||
pr-inactive-days: '30'
|
pr-inactive-days: '30'
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
|
|
||||||
- uses: pnpm/action-setup@26f6d4f2c533a43e6b5da0b4a5dd983f98f7b49a # v6.0.4
|
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
|
||||||
with:
|
with:
|
||||||
version: 9
|
version: 9
|
||||||
|
|
||||||
@@ -28,10 +28,10 @@ jobs:
|
|||||||
# Run Vitest directly so `--shard` is parsed as an option
|
# Run Vitest directly so `--shard` is parsed as an option
|
||||||
- run: pnpm -s exec vitest run --coverage --shard ${{ matrix.shard }}/4 --pool forks
|
- run: pnpm -s exec vitest run --coverage --shard ${{ matrix.shard }}/4 --pool forks
|
||||||
- name: Upload coverage reports to Codecov
|
- name: Upload coverage reports to Codecov
|
||||||
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
files: ./coverage/lcov.info
|
files: ./coverage/lcov.info
|
||||||
flags: vitest,shard-${{ matrix.shard }}
|
flags: vitest-shard-${{ matrix.shard }}
|
||||||
name: vitest-shard-${{ matrix.shard }}
|
name: vitest-shard-${{ matrix.shard }}
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
|
|||||||
+12
-12
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "homepage",
|
"name": "homepage",
|
||||||
"version": "1.13.1",
|
"version": "1.13.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
@@ -18,18 +18,18 @@
|
|||||||
"@kubernetes/client-node": "^1.0.0",
|
"@kubernetes/client-node": "^1.0.0",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"compare-versions": "^6.1.1",
|
"compare-versions": "^6.1.1",
|
||||||
"dockerode": "^4.0.10",
|
"dockerode": "^5.0.0",
|
||||||
"follow-redirects": "^1.16.0",
|
"follow-redirects": "^1.16.0",
|
||||||
"gamedig": "^5.3.2",
|
"gamedig": "^5.3.3",
|
||||||
"i18next": "^25.10.9",
|
"i18next": "^26.3.0",
|
||||||
"ical.js": "^2.2.1",
|
"ical.js": "^2.2.1",
|
||||||
"js-yaml": "^4.1.1",
|
"js-yaml": "^4.1.1",
|
||||||
"json-rpc-2.0": "^1.7.1",
|
"json-rpc-2.0": "^1.7.1",
|
||||||
"luxon": "^3.6.1",
|
"luxon": "^3.7.2",
|
||||||
"memory-cache": "^0.2.0",
|
"memory-cache": "^0.2.0",
|
||||||
"minecraftstatuspinger": "^1.2.2",
|
"minecraftstatuspinger": "^1.2.2",
|
||||||
"next": "^16.2.4",
|
"next": "^16.2.6",
|
||||||
"next-i18next": "^15.4.3",
|
"next-i18next": "^16.0.7",
|
||||||
"ping": "^0.4.4",
|
"ping": "^0.4.4",
|
||||||
"pretty-bytes": "^7.1.0",
|
"pretty-bytes": "^7.1.0",
|
||||||
"raw-body": "^3.0.2",
|
"raw-body": "^3.0.2",
|
||||||
@@ -39,11 +39,11 @@
|
|||||||
"react-icons": "^5.6.0",
|
"react-icons": "^5.6.0",
|
||||||
"recharts": "^3.1.2",
|
"recharts": "^3.1.2",
|
||||||
"swr": "^2.4.1",
|
"swr": "^2.4.1",
|
||||||
"systeminformation": "^5.30.8",
|
"systeminformation": "^5.31.6",
|
||||||
"tough-cookie": "^6.0.0",
|
"tough-cookie": "^6.0.0",
|
||||||
"urbackup-server-api": "^0.92.2",
|
"urbackup-server-api": "^0.92.2",
|
||||||
"winston": "^3.19.0",
|
"winston": "^3.19.0",
|
||||||
"ws": "^8.18.3",
|
"ws": "^8.20.1",
|
||||||
"xml-js": "^1.6.11"
|
"xml-js": "^1.6.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
"@tailwindcss/postcss": "^4.1.18",
|
"@tailwindcss/postcss": "^4.1.18",
|
||||||
"@testing-library/jest-dom": "^6.8.0",
|
"@testing-library/jest-dom": "^6.8.0",
|
||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@vitest/coverage-v8": "^3.2.4",
|
"@vitest/coverage-v8": "^4.1.8",
|
||||||
"eslint": "^9.25.1",
|
"eslint": "^9.25.1",
|
||||||
"eslint-config-next": "^15.5.11",
|
"eslint-config-next": "^15.5.11",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
@@ -68,9 +68,9 @@
|
|||||||
"prettier": "^3.8.1",
|
"prettier": "^3.8.1",
|
||||||
"prettier-plugin-organize-imports": "^4.3.0",
|
"prettier-plugin-organize-imports": "^4.3.0",
|
||||||
"tailwind-scrollbar": "^4.0.2",
|
"tailwind-scrollbar": "^4.0.2",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.3.0",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.7.3",
|
||||||
"vitest": "^3.2.4"
|
"vitest": "^4.1.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"osx-temperature-sensor": "^1.0.8"
|
"osx-temperature-sensor": "^1.0.8"
|
||||||
|
|||||||
Generated
+636
-831
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,15 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
|||||||
|
|
||||||
import createMockRes from "test-utils/create-mock-res";
|
import createMockRes from "test-utils/create-mock-res";
|
||||||
|
|
||||||
const { checkAndCopyConfig } = vi.hoisted(() => ({
|
const { checkAndCopyConfig, getSettings } = vi.hoisted(() => ({
|
||||||
checkAndCopyConfig: vi.fn(),
|
checkAndCopyConfig: vi.fn(),
|
||||||
|
getSettings: vi.fn(() => ({})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("utils/config/config", () => ({
|
vi.mock("utils/config/config", () => ({
|
||||||
default: checkAndCopyConfig,
|
default: checkAndCopyConfig,
|
||||||
|
getSettings,
|
||||||
|
CONF_DIR: "/tmp",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
import handler from "pages/api/validate";
|
import handler from "pages/api/validate";
|
||||||
@@ -18,13 +21,28 @@ describe("pages/api/validate", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("returns errors for any configs that don't validate", async () => {
|
it("returns errors for any configs that don't validate", async () => {
|
||||||
checkAndCopyConfig.mockReturnValueOnce(true).mockReturnValueOnce("settings bad").mockReturnValue(true);
|
checkAndCopyConfig
|
||||||
|
.mockReturnValueOnce(true)
|
||||||
|
.mockReturnValueOnce({
|
||||||
|
name: "YAMLException",
|
||||||
|
config: "settings.yaml",
|
||||||
|
reason: "settings bad",
|
||||||
|
mark: { line: 1 },
|
||||||
|
})
|
||||||
|
.mockReturnValue(true);
|
||||||
|
|
||||||
const req = {};
|
const req = {};
|
||||||
const res = createMockRes();
|
const res = createMockRes();
|
||||||
|
|
||||||
await handler(req, res);
|
await handler(req, res);
|
||||||
|
|
||||||
expect(res.body).toEqual(["settings bad"]);
|
expect(res.body).toEqual([
|
||||||
|
{
|
||||||
|
name: "YAMLException",
|
||||||
|
config: "settings.yaml",
|
||||||
|
reason: "settings bad",
|
||||||
|
mark: { line: 1 },
|
||||||
|
},
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -92,14 +92,14 @@ vi.mock("next/head", () => ({ default: ({ children }) => children }));
|
|||||||
vi.mock("next/script", () => ({ default: () => null }));
|
vi.mock("next/script", () => ({ default: () => null }));
|
||||||
vi.mock("next/router", () => ({ useRouter: () => router }));
|
vi.mock("next/router", () => ({ useRouter: () => router }));
|
||||||
|
|
||||||
vi.mock("next-i18next", () => ({
|
vi.mock("next-i18next/pages", () => ({
|
||||||
useTranslation: () => ({
|
useTranslation: () => ({
|
||||||
i18n,
|
i18n,
|
||||||
t: (k) => k,
|
t: (k) => k,
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("next-i18next/serverSideTranslations", () => ({
|
vi.mock("next-i18next/pages/serverSideTranslations", () => ({
|
||||||
serverSideTranslations,
|
serverSideTranslations,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -324,13 +324,12 @@ describe("pages/index Index routing + SWR branches", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("renders config errors when /api/validate returns a list of errors", async () => {
|
it("renders config errors when /api/validate returns a list of errors", async () => {
|
||||||
state.validateData = [{ config: "services.yaml", reason: "broken", mark: { snippet: "x: y" } }];
|
state.validateData = [{ config: "services.yaml", name: "Service 1", reason: "broken", mark: { line: 4 } }];
|
||||||
|
|
||||||
await renderIndex({ initialSettings: { title: "Homepage", layout: {} }, settings: { layout: {} } });
|
await renderIndex({ initialSettings: { title: "Homepage", layout: {} }, settings: { layout: {} } });
|
||||||
|
|
||||||
expect(screen.getByText("services.yaml")).toBeInTheDocument();
|
expect(screen.getByText(/services.yaml/)).toBeInTheDocument();
|
||||||
expect(screen.getByText("broken")).toBeInTheDocument();
|
expect(screen.getByText(/line 4/)).toBeInTheDocument();
|
||||||
expect(screen.getByText("x: y")).toBeInTheDocument();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("marks the UI stale when the hash changes and triggers a revalidate reload", async () => {
|
it("marks the UI stale when the hash changes and triggers a revalidate reload", async () => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
||||||
import { FiSearch } from "react-icons/fi";
|
import { FiSearch } from "react-icons/fi";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
export default function Ping({ groupName, serviceName, style }) {
|
export default function Ping({ groupName, serviceName, style }) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
export default function ProxmoxStatus({ service, style }) {
|
export default function ProxmoxStatus({ service, style }) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
export default function SiteMonitor({ groupName, serviceName, style }) {
|
export default function SiteMonitor({ groupName, serviceName, style }) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
export default function Status({ service, style }) {
|
export default function Status({ service, style }) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import ErrorBoundary from "components/errorboundry";
|
import ErrorBoundary from "components/errorboundry";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import components from "widgets/components";
|
import components from "widgets/components";
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useContext, useMemo } from "react";
|
import { useContext, useMemo } from "react";
|
||||||
|
|
||||||
import { BlockHighlightContext } from "./highlight-context";
|
import { BlockHighlightContext } from "./highlight-context";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { IoAlertCircle } from "react-icons/io5";
|
import { IoAlertCircle } from "react-icons/io5";
|
||||||
|
|
||||||
function displayError(error) {
|
function displayError(error) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { compareVersions, validate } from "compare-versions";
|
import { compareVersions, validate } from "compare-versions";
|
||||||
import cache from "memory-cache";
|
import cache from "memory-cache";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { MdNewReleases } from "react-icons/md";
|
import { MdNewReleases } from "react-icons/md";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import Container from "../widget/container";
|
import Container from "../widget/container";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
import { FaMemory, FaRegClock, FaThermometerHalf } from "react-icons/fa";
|
import { FaMemory, FaRegClock, FaThermometerHalf } from "react-icons/fa";
|
||||||
import { FiCpu, FiHardDrive } from "react-icons/fi";
|
import { FiCpu, FiHardDrive } from "react-icons/fi";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
import Container from "../widget/container";
|
import Container from "../widget/container";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { FaMemory } from "react-icons/fa";
|
import { FaMemory } from "react-icons/fa";
|
||||||
import { FiAlertTriangle, FiCpu, FiServer } from "react-icons/fi";
|
import { FiAlertTriangle, FiCpu, FiServer } from "react-icons/fi";
|
||||||
import { SiKubernetes } from "react-icons/si";
|
import { SiKubernetes } from "react-icons/si";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { FiHardDrive } from "react-icons/fi";
|
import { FiHardDrive } from "react-icons/fi";
|
||||||
|
|
||||||
import Resource from "../widget/resource";
|
import Resource from "../widget/resource";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { MdLocationDisabled, MdLocationSearching } from "react-icons/md";
|
import { MdLocationDisabled, MdLocationSearching } from "react-icons/md";
|
||||||
import { WiCloudDown } from "react-icons/wi";
|
import { WiCloudDown } from "react-icons/wi";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { MdLocationDisabled, MdLocationSearching } from "react-icons/md";
|
import { MdLocationDisabled, MdLocationSearching } from "react-icons/md";
|
||||||
import { WiCloudDown } from "react-icons/wi";
|
import { WiCloudDown } from "react-icons/wi";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { FiCpu } from "react-icons/fi";
|
import { FiCpu } from "react-icons/fi";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
import { render } from "@testing-library/react";
|
import { render } from "@testing-library/react";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const { useSWR, Resource, Error } = vi.hoisted(() => ({
|
const { useSWR, Resource, ErrorComponent } = vi.hoisted(() => ({
|
||||||
useSWR: vi.fn(),
|
useSWR: vi.fn(),
|
||||||
Resource: vi.fn(() => <div data-testid="resource" />),
|
Resource: vi.fn(() => <div data-testid="resource" />),
|
||||||
Error: vi.fn(() => <div data-testid="error" />),
|
ErrorComponent: vi.fn(() => <div data-testid="error" />),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("swr", () => ({ default: useSWR }));
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
vi.mock("../widget/resource", () => ({ default: Resource }));
|
vi.mock("../widget/resource", () => ({ default: Resource }));
|
||||||
vi.mock("../widget/error", () => ({ default: Error }));
|
vi.mock("../widget/error", () => ({ default: ErrorComponent }));
|
||||||
|
|
||||||
import Cpu from "./cpu";
|
import Cpu from "./cpu";
|
||||||
|
|
||||||
@@ -50,6 +50,6 @@ describe("components/widgets/resources/cpu", () => {
|
|||||||
|
|
||||||
render(<Cpu expanded />);
|
render(<Cpu expanded />);
|
||||||
|
|
||||||
expect(Error).toHaveBeenCalled();
|
expect(ErrorComponent).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { FaThermometerHalf } from "react-icons/fa";
|
import { FaThermometerHalf } from "react-icons/fa";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
import { render } from "@testing-library/react";
|
import { render } from "@testing-library/react";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const { useSWR, Resource, Error } = vi.hoisted(() => ({
|
const { useSWR, Resource, ErrorComponent } = vi.hoisted(() => ({
|
||||||
useSWR: vi.fn(),
|
useSWR: vi.fn(),
|
||||||
Resource: vi.fn(() => <div data-testid="resource" />),
|
Resource: vi.fn(() => <div data-testid="resource" />),
|
||||||
Error: vi.fn(() => <div data-testid="error" />),
|
ErrorComponent: vi.fn(() => <div data-testid="error" />),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("swr", () => ({ default: useSWR }));
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
vi.mock("../widget/resource", () => ({ default: Resource }));
|
vi.mock("../widget/resource", () => ({ default: Resource }));
|
||||||
vi.mock("../widget/error", () => ({ default: Error }));
|
vi.mock("../widget/error", () => ({ default: ErrorComponent }));
|
||||||
|
|
||||||
import CpuTemp from "./cputemp";
|
import CpuTemp from "./cputemp";
|
||||||
|
|
||||||
@@ -48,6 +48,6 @@ describe("components/widgets/resources/cputemp", () => {
|
|||||||
|
|
||||||
render(<CpuTemp expanded units="metric" />);
|
render(<CpuTemp expanded units="metric" />);
|
||||||
|
|
||||||
expect(Error).toHaveBeenCalled();
|
expect(ErrorComponent).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { FiHardDrive } from "react-icons/fi";
|
import { FiHardDrive } from "react-icons/fi";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
import { render } from "@testing-library/react";
|
import { render } from "@testing-library/react";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const { useSWR, Resource, Error } = vi.hoisted(() => ({
|
const { useSWR, Resource, ErrorComponent } = vi.hoisted(() => ({
|
||||||
useSWR: vi.fn(),
|
useSWR: vi.fn(),
|
||||||
Resource: vi.fn(() => <div data-testid="resource" />),
|
Resource: vi.fn(() => <div data-testid="resource" />),
|
||||||
Error: vi.fn(() => <div data-testid="error" />),
|
ErrorComponent: vi.fn(() => <div data-testid="error" />),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("swr", () => ({ default: useSWR }));
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
vi.mock("../widget/resource", () => ({ default: Resource }));
|
vi.mock("../widget/resource", () => ({ default: Resource }));
|
||||||
vi.mock("../widget/error", () => ({ default: Error }));
|
vi.mock("../widget/error", () => ({ default: ErrorComponent }));
|
||||||
|
|
||||||
import Disk from "./disk";
|
import Disk from "./disk";
|
||||||
|
|
||||||
@@ -48,6 +48,6 @@ describe("components/widgets/resources/disk", () => {
|
|||||||
|
|
||||||
render(<Disk options={{ disk: "/" }} expanded />);
|
render(<Disk options={{ disk: "/" }} expanded />);
|
||||||
|
|
||||||
expect(Error).toHaveBeenCalled();
|
expect(ErrorComponent).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { FaMemory } from "react-icons/fa";
|
import { FaMemory } from "react-icons/fa";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
import { render } from "@testing-library/react";
|
import { render } from "@testing-library/react";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const { useSWR, Resource, Error } = vi.hoisted(() => ({
|
const { useSWR, Resource, ErrorComponent } = vi.hoisted(() => ({
|
||||||
useSWR: vi.fn(),
|
useSWR: vi.fn(),
|
||||||
Resource: vi.fn(() => <div data-testid="resource" />),
|
Resource: vi.fn(() => <div data-testid="resource" />),
|
||||||
Error: vi.fn(() => <div data-testid="error" />),
|
ErrorComponent: vi.fn(() => <div data-testid="error" />),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("swr", () => ({ default: useSWR }));
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
vi.mock("../widget/resource", () => ({ default: Resource }));
|
vi.mock("../widget/resource", () => ({ default: Resource }));
|
||||||
vi.mock("../widget/error", () => ({ default: Error }));
|
vi.mock("../widget/error", () => ({ default: ErrorComponent }));
|
||||||
|
|
||||||
import Memory from "./memory";
|
import Memory from "./memory";
|
||||||
|
|
||||||
@@ -48,6 +48,6 @@ describe("components/widgets/resources/memory", () => {
|
|||||||
|
|
||||||
render(<Memory expanded />);
|
render(<Memory expanded />);
|
||||||
|
|
||||||
expect(Error).toHaveBeenCalled();
|
expect(ErrorComponent).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { FaNetworkWired } from "react-icons/fa";
|
import { FaNetworkWired } from "react-icons/fa";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
import { render } from "@testing-library/react";
|
import { render } from "@testing-library/react";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const { useSWR, Resource, Error } = vi.hoisted(() => ({
|
const { useSWR, Resource, ErrorComponent } = vi.hoisted(() => ({
|
||||||
useSWR: vi.fn(),
|
useSWR: vi.fn(),
|
||||||
Resource: vi.fn(() => <div data-testid="resource" />),
|
Resource: vi.fn(() => <div data-testid="resource" />),
|
||||||
Error: vi.fn(() => <div data-testid="error" />),
|
ErrorComponent: vi.fn(() => <div data-testid="error" />),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("swr", () => ({ default: useSWR }));
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
vi.mock("../widget/resource", () => ({ default: Resource }));
|
vi.mock("../widget/resource", () => ({ default: Resource }));
|
||||||
vi.mock("../widget/error", () => ({ default: Error }));
|
vi.mock("../widget/error", () => ({ default: ErrorComponent }));
|
||||||
|
|
||||||
import Network from "./network";
|
import Network from "./network";
|
||||||
|
|
||||||
@@ -52,6 +52,6 @@ describe("components/widgets/resources/network", () => {
|
|||||||
|
|
||||||
render(<Network options={{ network: "en0" }} />);
|
render(<Network options={{ network: "en0" }} />);
|
||||||
|
|
||||||
expect(Error).toHaveBeenCalled();
|
expect(ErrorComponent).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { FaRegClock } from "react-icons/fa";
|
import { FaRegClock } from "react-icons/fa";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
import { render } from "@testing-library/react";
|
import { render } from "@testing-library/react";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const { useSWR, Resource, Error } = vi.hoisted(() => ({
|
const { useSWR, Resource, ErrorComponent } = vi.hoisted(() => ({
|
||||||
useSWR: vi.fn(),
|
useSWR: vi.fn(),
|
||||||
Resource: vi.fn(() => <div data-testid="resource" />),
|
Resource: vi.fn(() => <div data-testid="resource" />),
|
||||||
Error: vi.fn(() => <div data-testid="error" />),
|
ErrorComponent: vi.fn(() => <div data-testid="error" />),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("swr", () => ({ default: useSWR }));
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
vi.mock("../widget/resource", () => ({ default: Resource }));
|
vi.mock("../widget/resource", () => ({ default: Resource }));
|
||||||
vi.mock("../widget/error", () => ({ default: Error }));
|
vi.mock("../widget/error", () => ({ default: ErrorComponent }));
|
||||||
|
|
||||||
import Uptime from "./uptime";
|
import Uptime from "./uptime";
|
||||||
|
|
||||||
@@ -49,6 +49,6 @@ describe("components/widgets/resources/uptime", () => {
|
|||||||
|
|
||||||
render(<Uptime />);
|
render(<Uptime />);
|
||||||
|
|
||||||
expect(Error).toHaveBeenCalled();
|
expect(ErrorComponent).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
Transition,
|
Transition,
|
||||||
} from "@headlessui/react";
|
} from "@headlessui/react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { Fragment, useEffect, useState } from "react";
|
import { Fragment, useEffect, useState } from "react";
|
||||||
import { BiLogoBing } from "react-icons/bi";
|
import { BiLogoBing } from "react-icons/bi";
|
||||||
import { FiSearch } from "react-icons/fi";
|
import { FiSearch } from "react-icons/fi";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FaChartLine } from "react-icons/fa6";
|
import { FaChartLine } from "react-icons/fa6";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { BiCheckCircle, BiError, BiNetworkChart, BiWifi, BiXCircle } from "react-icons/bi";
|
import { BiCheckCircle, BiError, BiNetworkChart, BiWifi, BiXCircle } from "react-icons/bi";
|
||||||
import { MdSettingsEthernet } from "react-icons/md";
|
import { MdSettingsEthernet } from "react-icons/md";
|
||||||
import { SiUbiquiti } from "react-icons/si";
|
import { SiUbiquiti } from "react-icons/si";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { MdLocationDisabled, MdLocationSearching } from "react-icons/md";
|
import { MdLocationDisabled, MdLocationSearching } from "react-icons/md";
|
||||||
import { WiCloudDown } from "react-icons/wi";
|
import { WiCloudDown } from "react-icons/wi";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { BiError } from "react-icons/bi";
|
import { BiError } from "react-icons/bi";
|
||||||
|
|
||||||
import Container from "./container";
|
import Container from "./container";
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable react/jsx-props-no-spreading */
|
/* eslint-disable react/jsx-props-no-spreading */
|
||||||
import { appWithTranslation } from "next-i18next";
|
import { appWithTranslation } from "next-i18next/pages";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import "styles/globals.css";
|
import "styles/globals.css";
|
||||||
import "styles/manrope.css";
|
import "styles/manrope.css";
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
import checkAndCopyConfig from "utils/config/config";
|
import checkAndCopyConfig from "utils/config/config";
|
||||||
|
import createLogger from "utils/logger";
|
||||||
|
|
||||||
const configs = ["docker.yaml", "settings.yaml", "services.yaml", "bookmarks.yaml", "kubernetes.yaml", "proxmox.yaml"];
|
const configs = ["docker.yaml", "settings.yaml", "services.yaml", "bookmarks.yaml", "kubernetes.yaml", "proxmox.yaml"];
|
||||||
|
const logger = createLogger("configValidationHandler");
|
||||||
|
|
||||||
export default async function handler(req, res) {
|
export default async function handler(req, res) {
|
||||||
const errors = configs.map((config) => checkAndCopyConfig(config)).filter((status) => status !== true);
|
let errors = configs.map((config) => checkAndCopyConfig(config)).filter((status) => status !== true);
|
||||||
|
if (errors.length > 0) {
|
||||||
|
logger.error("Configuration validation errors", errors);
|
||||||
|
errors = errors.map((error) => ({
|
||||||
|
name: error.name,
|
||||||
|
config: error.config,
|
||||||
|
reason: error.reason,
|
||||||
|
mark: { line: error.mark?.line },
|
||||||
|
}));
|
||||||
|
}
|
||||||
res.send(errors);
|
res.send(errors);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-5
@@ -7,8 +7,8 @@ import ServicesGroup from "components/services/group";
|
|||||||
import Tab, { slugifyAndEncode } from "components/tab";
|
import Tab, { slugifyAndEncode } from "components/tab";
|
||||||
import Revalidate from "components/toggles/revalidate";
|
import Revalidate from "components/toggles/revalidate";
|
||||||
import Widget from "components/widgets/widget";
|
import Widget from "components/widgets/widget";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
|
import { serverSideTranslations } from "next-i18next/pages/serverSideTranslations";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
@@ -167,11 +167,13 @@ function Index({ initialSettings, fallback }) {
|
|||||||
>
|
>
|
||||||
<div className="bg-amber-200 text-amber-800 dark:text-amber-200 dark:bg-amber-800 p-2 rounded-md font-bold">
|
<div className="bg-amber-200 text-amber-800 dark:text-amber-200 dark:bg-amber-800 p-2 rounded-md font-bold">
|
||||||
<BiError className="float-right w-6 h-6" />
|
<BiError className="float-right w-6 h-6" />
|
||||||
{error.config}
|
{error.name} - {error.config}
|
||||||
</div>
|
</div>
|
||||||
<div className="p-2 text-theme-100 dark:text-theme-200">
|
<div className="p-2 text-theme-100 dark:text-theme-200">
|
||||||
<pre className="opacity-50 font-bold pb-2">{error.reason}</pre>
|
<pre className="opacity-50 font-bold pb-2">
|
||||||
<pre className="text-sm">{error.mark.snippet}</pre>
|
Reason: "{error.reason}" at line {error.mark?.line}
|
||||||
|
</pre>
|
||||||
|
<pre className="font-italic">Check logs for details.</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -40,10 +40,12 @@ const { state, fs, yaml, config, Docker, dockerCfg, kubeCfg, kubeApi } = vi.hois
|
|||||||
default: vi.fn(),
|
default: vi.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const Docker = vi.fn((conn) => ({
|
const Docker = vi.fn(function Docker(conn) {
|
||||||
|
return {
|
||||||
listContainers: vi.fn(async () => state.dockerContainersByServer[conn?.serverName] ?? state.dockerContainers),
|
listContainers: vi.fn(async () => state.dockerContainersByServer[conn?.serverName] ?? state.dockerContainers),
|
||||||
listServices: vi.fn(async () => state.dockerServicesByServer[conn?.serverName] ?? state.dockerContainers),
|
listServices: vi.fn(async () => state.dockerServicesByServer[conn?.serverName] ?? state.dockerContainers),
|
||||||
}));
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const dockerCfg = {
|
const dockerCfg = {
|
||||||
default: vi.fn((serverName) => ({ conn: { serverName } })),
|
default: vi.fn((serverName) => ({ conn: { serverName } })),
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { Cookie, CookieJar } from "tough-cookie";
|
|||||||
|
|
||||||
const cookieJar = new CookieJar();
|
const cookieJar = new CookieJar();
|
||||||
|
|
||||||
export function setCookieHeader(url, params) {
|
export function setCookieHeader(url, params, { overwrite = false } = {}) {
|
||||||
// add cookie header, if we have one in the jar
|
// add cookie header, if we have one in the jar
|
||||||
const existingCookie = cookieJar.getCookieStringSync(url.toString());
|
const existingCookie = cookieJar.getCookieStringSync(url.toString());
|
||||||
if (existingCookie) {
|
if (existingCookie) {
|
||||||
params.headers = params.headers ?? {};
|
params.headers = params.headers ?? {};
|
||||||
const cookieHeader = params.cookieHeader ?? "Cookie";
|
const cookieHeader = params.cookieHeader ?? "Cookie";
|
||||||
if (!params.headers[cookieHeader]) {
|
if (overwrite || !params.headers[cookieHeader]) {
|
||||||
params.headers[cookieHeader] = existingCookie;
|
params.headers[cookieHeader] = existingCookie;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,17 @@ describe("utils/proxy/cookie-jar", () => {
|
|||||||
|
|
||||||
expect(params.headers.Cookie).toBe("manual=1");
|
expect(params.headers.Cookie).toBe("manual=1");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("overwrites an existing cookie header when requested", async () => {
|
||||||
|
const { addCookieToJar, setCookieHeader } = await import("./cookie-jar");
|
||||||
|
|
||||||
|
const url = new URL("http://example5.test/path");
|
||||||
|
addCookieToJar(url, { "set-cookie": ["sid=1; Path=/"] });
|
||||||
|
|
||||||
|
const params = { headers: { Cookie: "stale=1" } };
|
||||||
|
setCookieHeader(url, params, { overwrite: true });
|
||||||
|
|
||||||
|
expect(params.headers.Cookie).toContain("sid=1");
|
||||||
|
expect(params.headers.Cookie).not.toContain("stale=1");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export default function createUnifiProxyHandler({
|
|||||||
}
|
}
|
||||||
|
|
||||||
addCookieToJar(url, responseHeaders);
|
addCookieToJar(url, responseHeaders);
|
||||||
setCookieHeader(url, params);
|
setCookieHeader(url, params, { overwrite: true });
|
||||||
|
|
||||||
[status, contentType, data, responseHeaders] = await httpProxy(url, params);
|
[status, contentType, data, responseHeaders] = await httpProxy(url, params);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function addCookieHandler(url, params) {
|
|||||||
// handle cookies during redirects
|
// handle cookies during redirects
|
||||||
params.beforeRedirect = (options, responseInfo) => {
|
params.beforeRedirect = (options, responseInfo) => {
|
||||||
addCookieToJar(options.href, responseInfo.headers);
|
addCookieToJar(options.href, responseInfo.headers);
|
||||||
setCookieHeader(options.href, options);
|
setCookieHeader(options.href, options, { overwrite: true });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -348,7 +348,9 @@ describe("utils/proxy/http httpProxy", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(cookieJar.addCookieToJar).toHaveBeenCalledWith("http://example.com/redirect", { "set-cookie": ["a=b"] });
|
expect(cookieJar.addCookieToJar).toHaveBeenCalledWith("http://example.com/redirect", { "set-cookie": ["a=b"] });
|
||||||
expect(cookieJar.setCookieHeader).toHaveBeenCalledWith("http://example.com/redirect", expect.any(Object));
|
expect(cookieJar.setCookieHeader).toHaveBeenCalledWith("http://example.com/redirect", expect.any(Object), {
|
||||||
|
overwrite: true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("supports gzip-compressed responses", async () => {
|
it("supports gzip-compressed responses", async () => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import Event, { compareDateTimezone } from "./event";
|
import Event, { compareDateTimezone } from "./event";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { useContext, useEffect, useMemo, useState } from "react";
|
import { useContext, useEffect, useMemo, useState } from "react";
|
||||||
import { SettingsContext } from "utils/contexts/settings";
|
import { SettingsContext } from "utils/contexts/settings";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { IoMdCheckmarkCircleOutline } from "react-icons/io";
|
import { IoMdCheckmarkCircleOutline } from "react-icons/io";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import ICAL from "ical.js";
|
import ICAL from "ical.js";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
import Error from "../../../components/services/widget/error";
|
import Error from "../../../components/services/widget/error";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
import Error from "../../../components/services/widget/error";
|
import Error from "../../../components/services/widget/error";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { DateTime, Info } from "luxon";
|
import { DateTime, Info } from "luxon";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
import Event, { compareDateTimezone } from "./event";
|
import Event, { compareDateTimezone } from "./event";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import classNames from "classnames";
|
|||||||
import Dropdown from "components/services/dropdown";
|
import Dropdown from "components/services/dropdown";
|
||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import * as shvl from "utils/config/shvl";
|
import * as shvl from "utils/config/shvl";
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import QueueEntry from "../../components/widgets/queue/queueEntry";
|
import QueueEntry from "../../components/widgets/queue/queueEntry";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
@@ -50,10 +50,10 @@ export default function Component({ service }) {
|
|||||||
streams?.channels &&
|
streams?.channels &&
|
||||||
streams.channels.map((activeStream) => (
|
streams.channels.map((activeStream) => (
|
||||||
<StreamEntry
|
<StreamEntry
|
||||||
title={activeStream.stream_name}
|
title={activeStream.channel_name ?? activeStream.stream_name}
|
||||||
clients={activeStream.clients.length}
|
clients={activeStream.clients.length}
|
||||||
bitrate={activeStream.avg_bitrate}
|
bitrate={activeStream.avg_bitrate}
|
||||||
key={activeStream.stream_name}
|
key={activeStream.channel_name ?? activeStream.stream_name}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ describe("widgets/dispatcharr/component", () => {
|
|||||||
useWidgetAPI.mockReturnValueOnce({ data: [{}, {}, {}], error: undefined }).mockReturnValueOnce({
|
useWidgetAPI.mockReturnValueOnce({ data: [{}, {}, {}], error: undefined }).mockReturnValueOnce({
|
||||||
data: {
|
data: {
|
||||||
count: 1,
|
count: 1,
|
||||||
channels: [{ stream_name: "Stream1", clients: [{}, {}], avg_bitrate: "1000kbps" }],
|
channels: [{ channel_name: "Stream1", clients: [{}, {}], avg_bitrate: "1000kbps" }],
|
||||||
},
|
},
|
||||||
error: undefined,
|
error: undefined,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
import { calculateCPUPercent, calculateThroughput, calculateUsedMemory } from "./stats-helpers";
|
import { calculateCPUPercent, calculateThroughput, calculateUsedMemory } from "./stats-helpers";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
import { BsCpu, BsFillCpuFill, BsFillPlayFill, BsPauseFill, BsVolumeMuteFill } from "react-icons/bs";
|
import { BsCpu, BsFillCpuFill, BsFillPlayFill, BsPauseFill, BsVolumeMuteFill } from "react-icons/bs";
|
||||||
import { MdOutlineSmartDisplay } from "react-icons/md";
|
import { MdOutlineSmartDisplay } from "react-icons/md";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next/pages";
|
||||||
|
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import getServiceWidget from "utils/config/service-helpers";
|
import getServiceWidget from "utils/config/service-helpers";
|
||||||
import createLogger from "utils/logger";
|
import createLogger from "utils/logger";
|
||||||
import { asJson, formatApiCall, sanitizeErrorURL } from "utils/proxy/api-helpers";
|
import { asJson, formatApiCall, sanitizeErrorURL } from "utils/proxy/api-helpers";
|
||||||
import { addCookieToJar } from "utils/proxy/cookie-jar";
|
import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar";
|
||||||
import { httpProxy } from "utils/proxy/http";
|
import { httpProxy } from "utils/proxy/http";
|
||||||
import widgets from "widgets/widgets";
|
import widgets from "widgets/widgets";
|
||||||
|
|
||||||
@@ -57,6 +57,7 @@ export default async function frigateProxyHandler(req, res, map) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addCookieToJar(url, loginResponseHeaders);
|
addCookieToJar(url, loginResponseHeaders);
|
||||||
|
setCookieHeader(url, params, { overwrite: true });
|
||||||
// Retry original request with cookie set
|
// Retry original request with cookie set
|
||||||
[status, , data] = await httpProxy(url, params);
|
[status, , data] = await httpProxy(url, params);
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user