mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-16 20:59:26 +00:00
Compare commits
2 Commits
20210302.2
...
multiple-a
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e87accdfb4 | ||
![]() |
4dcfe3031d |
@@ -4,7 +4,7 @@
|
|||||||
"dockerfile": "Dockerfile",
|
"dockerfile": "Dockerfile",
|
||||||
"context": ".."
|
"context": ".."
|
||||||
},
|
},
|
||||||
"appPort": "8124:8123",
|
"appPort": 8123,
|
||||||
"context": "..",
|
"context": "..",
|
||||||
"postCreateCommand": "script/bootstrap",
|
"postCreateCommand": "script/bootstrap",
|
||||||
"extensions": [
|
"extensions": [
|
||||||
@@ -26,9 +26,6 @@
|
|||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[javascript]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
||||||
},
|
|
||||||
"files.trimTrailingWhitespace": true
|
"files.trimTrailingWhitespace": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
138
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
138
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,138 +0,0 @@
|
|||||||
name: Report a bug with the UI, Frontend or Lovelace
|
|
||||||
about: Report an issue related to the Home Assistant frontend.
|
|
||||||
labels: bug
|
|
||||||
title: ""
|
|
||||||
issue_body: true
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Make sure you are running the [latest version of Home Assistant][releases] before reporting an issue.
|
|
||||||
|
|
||||||
If you have a feature or enhancement request for the frontend, please [start an discussion][fr] instead of creating an issue.
|
|
||||||
|
|
||||||
**Please not not report issues for custom Lovelace cards.**
|
|
||||||
|
|
||||||
[fr]: https://github.com/home-assistant/frontend/discussions
|
|
||||||
[releases]: https://github.com/home-assistant/home-assistant/releases
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Checklist
|
|
||||||
description: Please verify that you've followed these steps
|
|
||||||
options:
|
|
||||||
- label: I have updated to the latest available Home Assistant version.
|
|
||||||
required: true
|
|
||||||
- label: I have cleared the cache of my browser.
|
|
||||||
required: true
|
|
||||||
- label: I have tried a different browser to see if it is related to my browser.
|
|
||||||
required: true
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
## The problem
|
|
||||||
- type: textarea
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
attributes:
|
|
||||||
label: Describe the issue you are experiencing
|
|
||||||
description: Provide a clear and concise description of what the bug is.
|
|
||||||
- type: textarea
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
attributes:
|
|
||||||
label: Describe the behavior you expected
|
|
||||||
description: Describe what you expected to happen or it should look/behave.
|
|
||||||
- type: textarea
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
attributes:
|
|
||||||
label: Steps to reproduce the issue
|
|
||||||
description: |
|
|
||||||
Please tell us exactly how to reproduce your issue.
|
|
||||||
Provide clear and concise step by step instructions and add code snippets if needed.
|
|
||||||
value: |
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
...
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
## Environment
|
|
||||||
- type: input
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
attributes:
|
|
||||||
label: What version of Home Assistant Core has the issue?
|
|
||||||
placeholder: core-
|
|
||||||
description: >
|
|
||||||
Can be found in the Configuration panel -> Info.
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: What was the last working version of Home Assistant Core?
|
|
||||||
placeholder: core-
|
|
||||||
description: >
|
|
||||||
If known, otherwise leave blank.
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: In which browser are you experiencing the issue with?
|
|
||||||
placeholder: Google Chrome 88.0.4324.150
|
|
||||||
description: >
|
|
||||||
Provide the full name and don't forget to add the version!
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Which operating system are you using to run this browser?
|
|
||||||
placeholder: macOS Big Sur (1.11)
|
|
||||||
description: >
|
|
||||||
Don't forget to add the version!
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
# Details
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: State of relevant entities
|
|
||||||
description: >
|
|
||||||
If your issue is about how an entity is shown in the UI, please add the
|
|
||||||
state and attributes for all situations. You can find this information
|
|
||||||
at Developer Tools -> States.
|
|
||||||
value: |
|
|
||||||
```yaml
|
|
||||||
# Paste your state here.
|
|
||||||
|
|
||||||
```
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Problem-relevant frontend configuration
|
|
||||||
description: >
|
|
||||||
An example configuration that caused the problem for you, e.g., the YAML
|
|
||||||
configuration of the used cards. Fill this out even if it seems
|
|
||||||
unimportant to you. Please be sure to remove personal information like
|
|
||||||
passwords, private URLs and other credentials.
|
|
||||||
value: |
|
|
||||||
```yaml
|
|
||||||
# Paste your YAML here.
|
|
||||||
|
|
||||||
```
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Javascript errors shown in your browser console/inspector
|
|
||||||
description: >
|
|
||||||
If you come across any Javascript or other error logs, e.g., in your
|
|
||||||
browser console/inspector please provide them.
|
|
||||||
value: |
|
|
||||||
```txt
|
|
||||||
# Paste your logs here.
|
|
||||||
|
|
||||||
```
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
## Additional information
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
If you have any additional information for us, use the field below.
|
|
||||||
Please note, you can attach screenshots or screen recordings here,
|
|
||||||
by dragging and dropping files in the field below.
|
|
19
.github/workflows/netflify.yml
vendored
19
.github/workflows/netflify.yml
vendored
@@ -1,19 +0,0 @@
|
|||||||
name: Netlify
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * *"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
trigger_builds:
|
|
||||||
name: Trigger netlify build preview
|
|
||||||
runs-on: "ubuntu-latest"
|
|
||||||
steps:
|
|
||||||
- name: Trigger Cast build
|
|
||||||
run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_CAST_DEV_BUILD_HOOK }}
|
|
||||||
|
|
||||||
- name: Trigger Demo build
|
|
||||||
run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_DEMO_DEV_BUILD_HOOK }}
|
|
||||||
|
|
||||||
- name: Trigger Gallery build
|
|
||||||
run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_GALLERY_DEV_BUILD_HOOK }}
|
|
81
.github/workflows/release.yaml
vendored
81
.github/workflows/release.yaml
vendored
@@ -1,81 +0,0 @@
|
|||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types:
|
|
||||||
- published
|
|
||||||
|
|
||||||
env:
|
|
||||||
WHEELS_TAG: 3.7-alpine3.11
|
|
||||||
PYTHON_VERSION: 3.7
|
|
||||||
NODE_VERSION: 12.1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: Release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout the repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Verify version
|
|
||||||
uses: home-assistant/actions/helpers/verify-version@master
|
|
||||||
|
|
||||||
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
|
||||||
uses: actions/setup-python@v2
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.PYTHON_VERSION }}
|
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
|
||||||
|
|
||||||
- name: Build and release package
|
|
||||||
run: |
|
|
||||||
python3 -m pip install twine
|
|
||||||
export TWINE_USERNAME="__token__"
|
|
||||||
export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}"
|
|
||||||
|
|
||||||
script/release
|
|
||||||
|
|
||||||
wheels-init:
|
|
||||||
name: Init wheels build
|
|
||||||
needs: release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Generate requirements.txt
|
|
||||||
run: |
|
|
||||||
# Sleep to give pypi time to populate the new version across mirrors
|
|
||||||
sleep 240
|
|
||||||
version=$(echo "${{ github.ref }}" | awk -F"/" '{print $NF}' )
|
|
||||||
echo "home-assistant-frontend==$version" > ./requirements.txt
|
|
||||||
|
|
||||||
- name: Upload requirements.txt
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: requirements
|
|
||||||
path: ./requirements.txt
|
|
||||||
|
|
||||||
build-wheels:
|
|
||||||
name: Build wheels for ${{ matrix.arch }}
|
|
||||||
needs: wheels-init
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
arch: ["aarch64", "armhf", "armv7", "amd64", "i386"]
|
|
||||||
steps:
|
|
||||||
- name: Download requirements.txt
|
|
||||||
uses: actions/download-artifact@v2
|
|
||||||
with:
|
|
||||||
name: requirements
|
|
||||||
|
|
||||||
- name: Build wheels
|
|
||||||
uses: home-assistant/wheels@master
|
|
||||||
with:
|
|
||||||
tag: ${{ env.WHEELS_TAG }}
|
|
||||||
arch: ${{ matrix.arch }}
|
|
||||||
wheels-host: ${{ secrets.WHEELS_HOST }}
|
|
||||||
wheels-key: ${{ secrets.WHEELS_KEY }}
|
|
||||||
wheels-user: wheels
|
|
||||||
requirements: "requirements.txt"
|
|
65
.github/workflows/translations.yaml
vendored
65
.github/workflows/translations.yaml
vendored
@@ -1,65 +0,0 @@
|
|||||||
name: Translations
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "30 0 * * *"
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
paths:
|
|
||||||
- src/translations/en.json
|
|
||||||
|
|
||||||
env:
|
|
||||||
NODE_VERSION: 12
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
upload:
|
|
||||||
name: Upload
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout the repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
|
||||||
|
|
||||||
- name: Upload Translations
|
|
||||||
run: |
|
|
||||||
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
|
|
||||||
|
|
||||||
./script/translations_upload_base
|
|
||||||
|
|
||||||
download:
|
|
||||||
name: Download
|
|
||||||
needs: upload
|
|
||||||
if: github.event_name == 'schedule'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout the repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
|
||||||
|
|
||||||
- name: Download Translations
|
|
||||||
run: |
|
|
||||||
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
|
|
||||||
|
|
||||||
npm install
|
|
||||||
./script/translations_download
|
|
||||||
|
|
||||||
- name: Initialize git
|
|
||||||
uses: home-assistant/actions/helpers/git-init@master
|
|
||||||
with:
|
|
||||||
name: GitHub Action
|
|
||||||
email: github-action@users.noreply.github.com
|
|
||||||
|
|
||||||
- name: Update translation
|
|
||||||
run: |
|
|
||||||
git add translations
|
|
||||||
git commit -am "Translation update"
|
|
||||||
git push
|
|
30
azure-pipelines-netlify.yml
Normal file
30
azure-pipelines-netlify.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# https://dev.azure.com/home-assistant
|
||||||
|
|
||||||
|
trigger: none
|
||||||
|
pr: none
|
||||||
|
schedules:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
displayName: "build preview"
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- dev
|
||||||
|
always: true
|
||||||
|
variables:
|
||||||
|
- group: netlify
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
- job: 'Netlify_preview'
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- script: |
|
||||||
|
# Cast
|
||||||
|
curl -X POST -d {} https://api.netlify.com/build_hooks/${NETLIFY_CAST}
|
||||||
|
|
||||||
|
# Demo
|
||||||
|
curl -X POST -d {} https://api.netlify.com/build_hooks/${NETLIFY_DEMO}
|
||||||
|
|
||||||
|
# Gallery
|
||||||
|
curl -X POST -d {} https://api.netlify.com/build_hooks/${NETLIFY_GALLERY}
|
||||||
|
displayName: 'Trigger netlify build preview'
|
59
azure-pipelines-release.yml
Normal file
59
azure-pipelines-release.yml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# https://dev.azure.com/home-assistant
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
batch: true
|
||||||
|
tags:
|
||||||
|
include:
|
||||||
|
- "*"
|
||||||
|
pr: none
|
||||||
|
variables:
|
||||||
|
- name: versionWheels
|
||||||
|
value: '1.10.1-3.7-alpine3.11'
|
||||||
|
- name: versionNode
|
||||||
|
value: '12.1'
|
||||||
|
- group: twine
|
||||||
|
resources:
|
||||||
|
repositories:
|
||||||
|
- repository: azure
|
||||||
|
type: github
|
||||||
|
name: 'home-assistant/ci-azure'
|
||||||
|
endpoint: 'home-assistant'
|
||||||
|
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- stage: "Validate"
|
||||||
|
jobs:
|
||||||
|
- template: templates/azp-job-version.yaml@azure
|
||||||
|
|
||||||
|
- stage: "Build"
|
||||||
|
jobs:
|
||||||
|
- job: "ReleasePython"
|
||||||
|
pool:
|
||||||
|
vmImage: "ubuntu-latest"
|
||||||
|
steps:
|
||||||
|
- task: UsePythonVersion@0
|
||||||
|
displayName: "Use Python 3.7"
|
||||||
|
inputs:
|
||||||
|
versionSpec: "3.7"
|
||||||
|
- task: NodeTool@0
|
||||||
|
displayName: "Use Node $(versionNode)"
|
||||||
|
inputs:
|
||||||
|
versionSpec: "$(versionNode)"
|
||||||
|
- script: pip install twine wheel
|
||||||
|
displayName: "Install tools"
|
||||||
|
- script: |
|
||||||
|
export TWINE_USERNAME="$(twineUser)"
|
||||||
|
export TWINE_PASSWORD="$(twinePassword)"
|
||||||
|
|
||||||
|
script/release
|
||||||
|
displayName: "Build and release package"
|
||||||
|
- stage: "Wheels"
|
||||||
|
jobs:
|
||||||
|
- template: templates/azp-job-wheels.yaml@azure
|
||||||
|
parameters:
|
||||||
|
builderVersion: '$(versionWheels)'
|
||||||
|
wheelsRequirement: 'requirement.txt'
|
||||||
|
preBuild:
|
||||||
|
- script: |
|
||||||
|
sleep 240
|
||||||
|
echo "home-assistant-frontend==$(Build.SourceBranchName)" > requirement.txt
|
70
azure-pipelines-translation.yml
Normal file
70
azure-pipelines-translation.yml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# https://dev.azure.com/home-assistant
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
batch: true
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- dev
|
||||||
|
paths:
|
||||||
|
include:
|
||||||
|
- translations/en.json
|
||||||
|
pr: none
|
||||||
|
schedules:
|
||||||
|
- cron: "30 0 * * *"
|
||||||
|
displayName: "frontend translation update"
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- dev
|
||||||
|
always: true
|
||||||
|
variables:
|
||||||
|
- group: translation
|
||||||
|
resources:
|
||||||
|
repositories:
|
||||||
|
- repository: azure
|
||||||
|
type: github
|
||||||
|
name: 'home-assistant/ci-azure'
|
||||||
|
endpoint: 'home-assistant'
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
- job: 'Upload'
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- task: NodeTool@0
|
||||||
|
displayName: 'Use Node 12.x'
|
||||||
|
inputs:
|
||||||
|
versionSpec: '12.x'
|
||||||
|
- script: |
|
||||||
|
export LOKALISE_TOKEN="$(lokaliseToken)"
|
||||||
|
export AZURE_BRANCH="$(Build.SourceBranchName)"
|
||||||
|
|
||||||
|
./script/translations_upload_base
|
||||||
|
displayName: 'Upload Translation'
|
||||||
|
|
||||||
|
- job: 'Download'
|
||||||
|
dependsOn:
|
||||||
|
- 'Upload'
|
||||||
|
condition: or(eq(variables['Build.Reason'], 'Schedule'), eq(variables['Build.Reason'], 'Manual'))
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- task: NodeTool@0
|
||||||
|
displayName: 'Use Node 12.x'
|
||||||
|
inputs:
|
||||||
|
versionSpec: '12.x'
|
||||||
|
- template: templates/azp-step-git-init.yaml@azure
|
||||||
|
- script: |
|
||||||
|
export LOKALISE_TOKEN="$(lokaliseToken)"
|
||||||
|
export AZURE_BRANCH="$(Build.SourceBranchName)"
|
||||||
|
|
||||||
|
npm install
|
||||||
|
./script/translations_download
|
||||||
|
displayName: 'Download Translation'
|
||||||
|
- script: |
|
||||||
|
git checkout dev
|
||||||
|
git add translation
|
||||||
|
git commit -am "[ci skip] Translation update"
|
||||||
|
git push
|
||||||
|
displayName: 'Update translation'
|
@@ -85,11 +85,6 @@ gulp.task("copy-translations-app", async () => {
|
|||||||
copyTranslations(staticDir);
|
copyTranslations(staticDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("copy-translations-supervisor", async () => {
|
|
||||||
const staticDir = paths.hassio_output_static;
|
|
||||||
copyTranslations(staticDir);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task("copy-static-app", async () => {
|
gulp.task("copy-static-app", async () => {
|
||||||
const staticDir = paths.app_output_static;
|
const staticDir = paths.app_output_static;
|
||||||
// Basic static files
|
// Basic static files
|
||||||
|
@@ -10,8 +10,6 @@ require("./gen-icons-json.js");
|
|||||||
require("./webpack.js");
|
require("./webpack.js");
|
||||||
require("./compress.js");
|
require("./compress.js");
|
||||||
require("./rollup.js");
|
require("./rollup.js");
|
||||||
require("./gather-static.js");
|
|
||||||
require("./translations.js");
|
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-hassio",
|
"develop-hassio",
|
||||||
@@ -22,8 +20,6 @@ gulp.task(
|
|||||||
"clean-hassio",
|
"clean-hassio",
|
||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"gen-index-hassio-dev",
|
"gen-index-hassio-dev",
|
||||||
"build-supervisor-translations",
|
|
||||||
"copy-translations-supervisor",
|
|
||||||
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -36,8 +32,6 @@ gulp.task(
|
|||||||
},
|
},
|
||||||
"clean-hassio",
|
"clean-hassio",
|
||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"build-supervisor-translations",
|
|
||||||
"copy-translations-supervisor",
|
|
||||||
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
||||||
"gen-index-hassio-prod",
|
"gen-index-hassio-prod",
|
||||||
...// Don't compress running tests
|
...// Don't compress running tests
|
||||||
|
@@ -266,7 +266,6 @@ gulp.task(taskName, function () {
|
|||||||
TRANSLATION_FRAGMENTS.forEach((fragment) => {
|
TRANSLATION_FRAGMENTS.forEach((fragment) => {
|
||||||
delete data.ui.panel[fragment];
|
delete data.ui.panel[fragment];
|
||||||
});
|
});
|
||||||
delete data.supervisor;
|
|
||||||
return data;
|
return data;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -343,26 +342,18 @@ gulp.task(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("build-translation-fragment-supervisor", function () {
|
gulp.task(
|
||||||
return gulp
|
"build-translations",
|
||||||
.src(fullDir + "/*.json")
|
gulp.series(
|
||||||
.pipe(transform((data) => data.supervisor))
|
"clean-translations",
|
||||||
.pipe(gulp.dest(workDir + "/supervisor"));
|
"ensure-translations-build-dir",
|
||||||
});
|
env.isProdBuild() ? (done) => done() : "create-test-translation",
|
||||||
|
"build-master-translation",
|
||||||
gulp.task("build-translation-flatten-supervisor", function () {
|
"build-merged-translations",
|
||||||
return gulp
|
gulp.parallel(...splitTasks),
|
||||||
.src(workDir + "/supervisor/*.json")
|
"build-flattened-translations",
|
||||||
.pipe(
|
"build-translation-fingerprints",
|
||||||
transform(function (data) {
|
function writeMetadata() {
|
||||||
// Polymer.AppLocalizeBehavior requires flattened json
|
|
||||||
return flatten(data);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.pipe(gulp.dest(outDir));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task("build-translation-write-metadata", function writeMetadata() {
|
|
||||||
return gulp
|
return gulp
|
||||||
.src(
|
.src(
|
||||||
[
|
[
|
||||||
@@ -378,13 +369,14 @@ gulp.task("build-translation-write-metadata", function writeMetadata() {
|
|||||||
const newData = {};
|
const newData = {};
|
||||||
Object.entries(data).forEach(([key, value]) => {
|
Object.entries(data).forEach(([key, value]) => {
|
||||||
// Filter out translations without native name.
|
// Filter out translations without native name.
|
||||||
if (value.nativeName) {
|
if (data[key].nativeName) {
|
||||||
newData[key] = value;
|
newData[key] = data[key];
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Skipping language ${key}. Native name was not translated.`
|
`Skipping language ${key}. Native name was not translated.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (data[key]) newData[key] = value;
|
||||||
});
|
});
|
||||||
return newData;
|
return newData;
|
||||||
})
|
})
|
||||||
@@ -397,33 +389,6 @@ gulp.task("build-translation-write-metadata", function writeMetadata() {
|
|||||||
)
|
)
|
||||||
.pipe(rename("translationMetadata.json"))
|
.pipe(rename("translationMetadata.json"))
|
||||||
.pipe(gulp.dest(workDir));
|
.pipe(gulp.dest(workDir));
|
||||||
});
|
}
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"build-translations",
|
|
||||||
gulp.series(
|
|
||||||
"clean-translations",
|
|
||||||
"ensure-translations-build-dir",
|
|
||||||
env.isProdBuild() ? (done) => done() : "create-test-translation",
|
|
||||||
"build-master-translation",
|
|
||||||
"build-merged-translations",
|
|
||||||
gulp.parallel(...splitTasks),
|
|
||||||
"build-flattened-translations",
|
|
||||||
"build-translation-fingerprints",
|
|
||||||
"build-translation-write-metadata"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"build-supervisor-translations",
|
|
||||||
gulp.series(
|
|
||||||
"clean-translations",
|
|
||||||
"ensure-translations-build-dir",
|
|
||||||
"build-master-translation",
|
|
||||||
"build-merged-translations",
|
|
||||||
"build-translation-fragment-supervisor",
|
|
||||||
"build-translation-flatten-supervisor",
|
|
||||||
"build-translation-fingerprints",
|
|
||||||
"build-translation-write-metadata"
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@@ -137,12 +137,7 @@ gulp.task("webpack-watch-hassio", () => {
|
|||||||
isProdBuild: false,
|
isProdBuild: false,
|
||||||
latestBuild: true,
|
latestBuild: true,
|
||||||
})
|
})
|
||||||
).watch({ ignored: /build-translations/ }, doneHandler());
|
).watch({}, doneHandler());
|
||||||
|
|
||||||
gulp.watch(
|
|
||||||
path.join(paths.translations_src, "en.json"),
|
|
||||||
gulp.series("build-supervisor-translations", "copy-translations-supervisor")
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("webpack-prod-hassio", () =>
|
gulp.task("webpack-prod-hassio", () =>
|
||||||
|
@@ -34,7 +34,6 @@ module.exports = {
|
|||||||
|
|
||||||
hassio_dir: path.resolve(__dirname, "../hassio"),
|
hassio_dir: path.resolve(__dirname, "../hassio"),
|
||||||
hassio_output_root: path.resolve(__dirname, "../hassio/build"),
|
hassio_output_root: path.resolve(__dirname, "../hassio/build"),
|
||||||
hassio_output_static: path.resolve(__dirname, "../hassio/build/static"),
|
|
||||||
hassio_output_latest: path.resolve(
|
hassio_output_latest: path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
"../hassio/build/frontend_latest"
|
"../hassio/build/frontend_latest"
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
const webpack = require("webpack");
|
const webpack = require("webpack");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
|
const ManifestPlugin = require("webpack-manifest-plugin");
|
||||||
const paths = require("./paths.js");
|
const paths = require("./paths.js");
|
||||||
const bundle = require("./bundle");
|
const bundle = require("./bundle");
|
||||||
const log = require("fancy-log");
|
const log = require("fancy-log");
|
||||||
@@ -68,7 +68,7 @@ const createWebpackConfig = ({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new WebpackManifestPlugin({
|
new ManifestPlugin({
|
||||||
// Only include the JS of entrypoints
|
// Only include the JS of entrypoints
|
||||||
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
||||||
}),
|
}),
|
||||||
|
@@ -48,7 +48,7 @@ class HcCast extends LitElement {
|
|||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (this.lovelaceConfig === undefined) {
|
if (this.lovelaceConfig === undefined) {
|
||||||
return html`<hass-loading-screen no-toolbar></hass-loading-screen>`;
|
return html` <hass-loading-screen no-toolbar></hass-loading-screen>> `;
|
||||||
}
|
}
|
||||||
|
|
||||||
const error =
|
const error =
|
||||||
|
@@ -98,12 +98,8 @@ class HcLayout extends LitElement {
|
|||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
padding: 24px 16px 16px;
|
padding: 24px 16px 16px;
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero {
|
|
||||||
border-radius: 4px 4px 0 0;
|
|
||||||
}
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
|
||||||
property,
|
property,
|
||||||
|
internalProperty,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { mockHistory } from "../../../../demo/src/stubs/history";
|
import { mockHistory } from "../../../../demo/src/stubs/history";
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import "web-animations-js/web-animations-next-lite.min";
|
import "web-animations-js/web-animations-next-lite.min";
|
||||||
import "../../../src/resources/ha-style";
|
|
||||||
import "../../../src/resources/roboto";
|
import "../../../src/resources/roboto";
|
||||||
|
import "../../../src/resources/ha-style";
|
||||||
import "./layout/hc-lovelace";
|
import "./layout/hc-lovelace";
|
||||||
|
@@ -54,8 +54,6 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
|
|||||||
state: "21",
|
state: "21",
|
||||||
attributes: {
|
attributes: {
|
||||||
friendly_name: "Living room temperature",
|
friendly_name: "Living room temperature",
|
||||||
device_class: "temperature",
|
|
||||||
unit_of_measurement: "°C",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"sensor.study_temp_rounded": {
|
"sensor.study_temp_rounded": {
|
||||||
@@ -63,8 +61,6 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
|
|||||||
state: "23",
|
state: "23",
|
||||||
attributes: {
|
attributes: {
|
||||||
friendly_name: "Study temperature",
|
friendly_name: "Study temperature",
|
||||||
device_class: "temperature",
|
|
||||||
unit_of_measurement: "°C",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"sensor.living_room": {
|
"sensor.living_room": {
|
||||||
@@ -265,7 +261,7 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
|
|||||||
entity_id: "light.kitchen_lights",
|
entity_id: "light.kitchen_lights",
|
||||||
state: "off",
|
state: "off",
|
||||||
attributes: {
|
attributes: {
|
||||||
friendly_name: "Kitchen Lights",
|
friendly_name: "Kitchen lights",
|
||||||
supported_features: 1,
|
supported_features: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -488,7 +484,7 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
|
|||||||
attributes: {
|
attributes: {
|
||||||
min_mireds: 111,
|
min_mireds: 111,
|
||||||
max_mireds: 400,
|
max_mireds: 400,
|
||||||
friendly_name: "Garage Lights",
|
friendly_name: "Garage lights",
|
||||||
supported_features: 55,
|
supported_features: 55,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -12,7 +12,6 @@ export const demoLovelaceArsaboo: DemoConfig["lovelace"] = (localize) => ({
|
|||||||
{
|
{
|
||||||
type: "entities",
|
type: "entities",
|
||||||
title: localize("ui.panel.page-demo.config.arsaboo.labels.lights"),
|
title: localize("ui.panel.page-demo.config.arsaboo.labels.lights"),
|
||||||
state_color: true,
|
|
||||||
entities: [
|
entities: [
|
||||||
{
|
{
|
||||||
entity: "light.kitchen_lights",
|
entity: "light.kitchen_lights",
|
||||||
|
@@ -653,7 +653,7 @@ export const demoEntitiesJimpower: DemoConfig["entities"] = () =>
|
|||||||
entity_id: "binary_sensor.smoke_sensor_158d0001b8ddc7",
|
entity_id: "binary_sensor.smoke_sensor_158d0001b8ddc7",
|
||||||
state: "off",
|
state: "off",
|
||||||
attributes: {
|
attributes: {
|
||||||
density: 0,
|
Density: 0,
|
||||||
battery_level: 59,
|
battery_level: 59,
|
||||||
friendly_name: "Downstairs Smoke Detector",
|
friendly_name: "Downstairs Smoke Detector",
|
||||||
device_class: "smoke",
|
device_class: "smoke",
|
||||||
@@ -663,7 +663,7 @@ export const demoEntitiesJimpower: DemoConfig["entities"] = () =>
|
|||||||
entity_id: "binary_sensor.smoke_sensor_158d0001b8deba",
|
entity_id: "binary_sensor.smoke_sensor_158d0001b8deba",
|
||||||
state: "off",
|
state: "off",
|
||||||
attributes: {
|
attributes: {
|
||||||
density: 0,
|
Density: 0,
|
||||||
battery_level: 65,
|
battery_level: 65,
|
||||||
friendly_name: "Upstairs Smoke Detector",
|
friendly_name: "Upstairs Smoke Detector",
|
||||||
device_class: "smoke",
|
device_class: "smoke",
|
||||||
|
@@ -3,7 +3,49 @@ import { DemoConfig } from "../types";
|
|||||||
|
|
||||||
export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
||||||
name: "Kingia Castle",
|
name: "Kingia Castle",
|
||||||
resources: [],
|
resources: [
|
||||||
|
// {
|
||||||
|
// url: "/local/custom_ui/dark-sky-weather-card.js?v=4",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom_ui/mini-media-player-bundle.js?v=0.9.8",
|
||||||
|
// type: "module",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom_ui/tracker-card.js?v=0.1.5",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom_ui/surveillance-card.js?v=0.0.1",
|
||||||
|
// type: "module",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom_ui/mini-graph-card-bundle.js?v=0.1.0",
|
||||||
|
// type: "module",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom_ui/slider-entity-row.js?v=d6da75",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url:
|
||||||
|
// "/local/custom_ui/compact-custom-header/compact-custom-header.js?v=0.2.7",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom_ui/waze-card.js?v=1.1.1",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom_ui/circle-sensor-card.js?v=1.2.0",
|
||||||
|
// type: "module",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom_ui/monster-card.js?v=0.2.3",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
],
|
||||||
views: [
|
views: [
|
||||||
{
|
{
|
||||||
cards: [
|
cards: [
|
||||||
@@ -561,6 +603,89 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
cards: [
|
cards: [
|
||||||
|
// {
|
||||||
|
// style: {
|
||||||
|
// "background-image": 'url("/assets/jimpower/cardbackK.png")',
|
||||||
|
// "background-size": "100% 400px",
|
||||||
|
// "box-shadow": "3px 3px rgba(0,0,0,0.4)",
|
||||||
|
// "background-repeat": "no-repeat",
|
||||||
|
// color: "#999999",
|
||||||
|
// "border-radius": "20px",
|
||||||
|
// border: "solid 1px rgba(100,100,100,0.3)",
|
||||||
|
// "background-color": "rgba(50,50,50,0.3)",
|
||||||
|
// },
|
||||||
|
// type: "custom:card-modder",
|
||||||
|
// card: {
|
||||||
|
// entity_visibility: "sensor.dark_sky_visibility",
|
||||||
|
// entity_sun: "sun.sun",
|
||||||
|
// entity_daily_summary:
|
||||||
|
// "sensor.bom_gc_forecast_detailed_summary_0",
|
||||||
|
// entity_temperature: "sensor.bom_temp",
|
||||||
|
// entity_forecast_high_temp_3:
|
||||||
|
// "sensor.bom_gc_forecast_max_temp_c_3",
|
||||||
|
// entity_forecast_high_temp_2:
|
||||||
|
// "sensor.bom_gc_forecast_max_temp_c_2",
|
||||||
|
// entity_forecast_high_temp_5:
|
||||||
|
// "sensor.bom_gc_forecast_max_temp_c_5",
|
||||||
|
// entity_forecast_high_temp_4:
|
||||||
|
// "sensor.bom_gc_forecast_max_temp_c_4",
|
||||||
|
// entity_wind_speed: "sensor.bom_wind_sp",
|
||||||
|
// entity_forecast_icon_4: "sensor.dark_sky_icon_4",
|
||||||
|
// entity_forecast_icon_5: "sensor.dark_sky_icon_5",
|
||||||
|
// entity_forecast_icon_2: "sensor.dark_sky_icon_2",
|
||||||
|
// entity_forecast_icon_3: "sensor.dark_sky_icon_3",
|
||||||
|
// entity_forecast_icon_1: "sensor.dark_sky_icon_1",
|
||||||
|
// entity_forecast_high_temp_1:
|
||||||
|
// "sensor.bom_gc_forecast_max_temp_c_1",
|
||||||
|
// entity_wind_bearing: "sensor.bom_wind_bear",
|
||||||
|
// entity_forecast_low_temp_2:
|
||||||
|
// "sensor.bom_gc_forecast_min_temp_c_2",
|
||||||
|
// entity_forecast_low_temp_3:
|
||||||
|
// "sensor.bom_gc_forecast_min_temp_c_3",
|
||||||
|
// entity_pressure: "sensor.bom_pres",
|
||||||
|
// entity_forecast_low_temp_1:
|
||||||
|
// "sensor.bom_gc_forecast_min_temp_c_1",
|
||||||
|
// entity_forecast_low_temp_4:
|
||||||
|
// "sensor.bom_gc_forecast_min_temp_c_4",
|
||||||
|
// entity_forecast_low_temp_5:
|
||||||
|
// "sensor.bom_gc_forecast_min_temp_c_5",
|
||||||
|
// entity_humidity: "sensor.bom_humd",
|
||||||
|
// type: "custom:dark-sky-weather-card",
|
||||||
|
// entity_current_conditions: "sensor.dark_sky_icon",
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// style: {
|
||||||
|
// "background-image": 'url("/assets/jimpower/home/waze_5.png")',
|
||||||
|
// "background-size": "100% 400px",
|
||||||
|
// "box-shadow": "3px 3px rgba(0,0,0,0.4)",
|
||||||
|
// "background-repeat": "no-repeat",
|
||||||
|
// "border-radius": "20px",
|
||||||
|
// border: "solid 1px rgba(100,100,100,0.3)",
|
||||||
|
// "background-color": "rgba(50,50,50,0.3)",
|
||||||
|
// },
|
||||||
|
// type: "custom:card-modder",
|
||||||
|
// card: {
|
||||||
|
// entities: [
|
||||||
|
// {
|
||||||
|
// name: "James",
|
||||||
|
// zone: "zone.home",
|
||||||
|
// entity: "sensor.james_to_home",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Tina",
|
||||||
|
// zone: "zone.home",
|
||||||
|
// entity: "sensor.tina_to_home",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Work",
|
||||||
|
// zone: "zone.powertec",
|
||||||
|
// entity: "sensor.commute_to_work",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// type: "custom:waze-card",
|
||||||
|
// },
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
style: {
|
style: {
|
||||||
"border-radius": "20px",
|
"border-radius": "20px",
|
||||||
@@ -597,8 +722,46 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
|||||||
],
|
],
|
||||||
type: "vertical-stack",
|
type: "vertical-stack",
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// cards: [
|
||||||
|
// {
|
||||||
|
// style: {
|
||||||
|
// "border-radius": "20px",
|
||||||
|
// color: "#999999",
|
||||||
|
// "box-shadow": "3px 3px rgba(0,0,0,0.4)",
|
||||||
|
// border: "solid 1px rgba(100,100,100,0.3)",
|
||||||
|
// },
|
||||||
|
// type: "custom:card-modder",
|
||||||
|
// card: {
|
||||||
|
// type: "picture-entity",
|
||||||
|
// entity: "camera.bom_radar",
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // style: {
|
||||||
|
// // "background-image": 'url("/assets/jimpower/cardbackK.png")',
|
||||||
|
// // "background-size": "100% 525px",
|
||||||
|
// // "box-shadow": "3px 3px rgba(0,0,0,0.4)",
|
||||||
|
// // "background-repeat": "no-repeat",
|
||||||
|
// // color: "#999999",
|
||||||
|
// // "border-radius": "20px",
|
||||||
|
// // border: "solid 1px rgba(100,100,100,0.3)",
|
||||||
|
// // "background-color": "rgba(50,50,50,0.3)",
|
||||||
|
// // },
|
||||||
|
// // type: "custom:card-modder",
|
||||||
|
// // card: {
|
||||||
|
// // title: null,
|
||||||
|
// // type: "custom:tracker-card",
|
||||||
|
// // trackers: [
|
||||||
|
// // "sensor.custom_card_tracker",
|
||||||
|
// // "sensor.custom_component_tracker",
|
||||||
|
// // ],
|
||||||
|
// // },
|
||||||
|
// // },
|
||||||
|
// ],
|
||||||
|
// type: "vertical-stack",
|
||||||
|
// },
|
||||||
],
|
],
|
||||||
path: "home",
|
|
||||||
icon: "mdi:castle",
|
icon: "mdi:castle",
|
||||||
name: "Home",
|
name: "Home",
|
||||||
background:
|
background:
|
||||||
@@ -718,13 +881,26 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
|||||||
card: {
|
card: {
|
||||||
image: "/assets/jimpower/security/air_8.jpg",
|
image: "/assets/jimpower/security/air_8.jpg",
|
||||||
elements: [
|
elements: [
|
||||||
|
{
|
||||||
|
image:
|
||||||
|
"https://www.airvisual.com/assets/aqi/ic-face-1-green.svg",
|
||||||
|
type: "image",
|
||||||
|
style: {
|
||||||
|
width: "80px",
|
||||||
|
top: "30%",
|
||||||
|
left: "12%",
|
||||||
|
transform: "none",
|
||||||
|
height: "80px",
|
||||||
|
},
|
||||||
|
entity: "sensor.us_air_pollution_level_2",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
style: {
|
style: {
|
||||||
color: "hsl(120, 41%, 39%)",
|
color: "hsl(120, 41%, 39%)",
|
||||||
top: "50%",
|
top: "50%",
|
||||||
"font-weight": 600,
|
"font-weight": 600,
|
||||||
"font-size": "50px",
|
"font-size": "20px",
|
||||||
left: "30%",
|
left: "44%",
|
||||||
},
|
},
|
||||||
type: "state-label",
|
type: "state-label",
|
||||||
entity: "sensor.us_air_pollution_level_2",
|
entity: "sensor.us_air_pollution_level_2",
|
||||||
@@ -744,7 +920,7 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
|||||||
style: {
|
style: {
|
||||||
color: "white",
|
color: "white",
|
||||||
top: "80%",
|
top: "80%",
|
||||||
left: "48%",
|
left: "52%",
|
||||||
},
|
},
|
||||||
type: "state-icon",
|
type: "state-icon",
|
||||||
entity: "sensor.us_main_pollutant_2",
|
entity: "sensor.us_main_pollutant_2",
|
||||||
@@ -1235,7 +1411,6 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
|||||||
type: "vertical-stack",
|
type: "vertical-stack",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
path: "security",
|
|
||||||
icon: "hass:shield-home",
|
icon: "hass:shield-home",
|
||||||
name: "Security",
|
name: "Security",
|
||||||
background:
|
background:
|
||||||
|
@@ -101,12 +101,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
|
|||||||
"sensor.zwave_battery_front_door": {
|
"sensor.zwave_battery_front_door": {
|
||||||
entity_id: "sensor.zwave_battery_front_door",
|
entity_id: "sensor.zwave_battery_front_door",
|
||||||
state: "63",
|
state: "63",
|
||||||
attributes: {
|
attributes: { friendly_name: "Battery", icon: "mdi:battery-60" },
|
||||||
friendly_name: "Battery",
|
|
||||||
icon: "mdi:battery-60",
|
|
||||||
unit_of_measurement: "%",
|
|
||||||
device_class: "battery",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"sensor.oskar_devices": {
|
"sensor.oskar_devices": {
|
||||||
entity_id: "sensor.oskar_devices",
|
entity_id: "sensor.oskar_devices",
|
||||||
@@ -169,7 +164,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
|
|||||||
},
|
},
|
||||||
"input_select.christmas_pattern": {
|
"input_select.christmas_pattern": {
|
||||||
entity_id: "input_select.christmas_pattern",
|
entity_id: "input_select.christmas_pattern",
|
||||||
state: "Rainbow",
|
state: "None",
|
||||||
attributes: {
|
attributes: {
|
||||||
options: [
|
options: [
|
||||||
"None",
|
"None",
|
||||||
@@ -191,7 +186,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
|
|||||||
},
|
},
|
||||||
"input_select.christmas_palette": {
|
"input_select.christmas_palette": {
|
||||||
entity_id: "input_select.christmas_palette",
|
entity_id: "input_select.christmas_palette",
|
||||||
state: "Party",
|
state: "None",
|
||||||
attributes: {
|
attributes: {
|
||||||
options: [
|
options: [
|
||||||
"None",
|
"None",
|
||||||
@@ -462,7 +457,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
|
|||||||
state: "0.0",
|
state: "0.0",
|
||||||
attributes: {
|
attributes: {
|
||||||
unit_of_measurement: "kB/s",
|
unit_of_measurement: "kB/s",
|
||||||
friendly_name: "Downloading",
|
friendly_name: "Nedladdning",
|
||||||
icon: "mdi:file-download",
|
icon: "mdi:file-download",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -476,7 +471,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
|
|||||||
state: "0.0",
|
state: "0.0",
|
||||||
attributes: {
|
attributes: {
|
||||||
unit_of_measurement: "kB/s",
|
unit_of_measurement: "kB/s",
|
||||||
friendly_name: "Uploading",
|
friendly_name: "Uppladdning",
|
||||||
icon: "mdi:file-upload",
|
icon: "mdi:file-upload",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -2,7 +2,44 @@ import { DemoConfig } from "../types";
|
|||||||
|
|
||||||
export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
||||||
name: "Hem",
|
name: "Hem",
|
||||||
resources: [],
|
resources: [
|
||||||
|
// {
|
||||||
|
// url: "/local/custom-lovelace/monster-card.js",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom-lovelace/mini-media-player-bundle.js?v=0.9.8",
|
||||||
|
// type: "module",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom-lovelace/slideshow-card.js?=1.1.0",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom-lovelace/fold-entity-row.js?v=3ae2c4",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom-lovelace/swipe-card/swipe-card.js?v=2.0.0",
|
||||||
|
// type: "module",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom-lovelace/upcoming-media-card/upcoming-media-card.js",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom-lovelace/tracker-card.js?v=0.1.5",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom-lovelace/card-tools.js?v=6ce5d0",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// url: "/local/custom-lovelace/krisinfo.js?=0.0.1",
|
||||||
|
// type: "js",
|
||||||
|
// },
|
||||||
|
],
|
||||||
views: [
|
views: [
|
||||||
{
|
{
|
||||||
cards: [
|
cards: [
|
||||||
@@ -27,7 +64,7 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
style: {
|
style: {
|
||||||
color: "white",
|
color: "white",
|
||||||
top: "93%",
|
top: "93%",
|
||||||
left: "85%",
|
left: "90%",
|
||||||
},
|
},
|
||||||
type: "state-label",
|
type: "state-label",
|
||||||
entity: "sensor.battery_oskar",
|
entity: "sensor.battery_oskar",
|
||||||
@@ -50,7 +87,7 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
{
|
{
|
||||||
style: {
|
style: {
|
||||||
color: "white",
|
color: "white",
|
||||||
top: "93%",
|
top: "92%",
|
||||||
left: "20%",
|
left: "20%",
|
||||||
},
|
},
|
||||||
type: "state-label",
|
type: "state-label",
|
||||||
@@ -59,8 +96,8 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
{
|
{
|
||||||
style: {
|
style: {
|
||||||
color: "white",
|
color: "white",
|
||||||
top: "93%",
|
top: "92%",
|
||||||
left: "85%",
|
left: "90%",
|
||||||
},
|
},
|
||||||
type: "state-label",
|
type: "state-label",
|
||||||
entity: "sensor.battery_bella",
|
entity: "sensor.battery_bella",
|
||||||
@@ -68,7 +105,7 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
{
|
{
|
||||||
style: {
|
style: {
|
||||||
color: "white",
|
color: "white",
|
||||||
top: "93%",
|
top: "92%",
|
||||||
left: "55%",
|
left: "55%",
|
||||||
},
|
},
|
||||||
type: "state-label",
|
type: "state-label",
|
||||||
@@ -94,6 +131,78 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
type: "entities",
|
type: "entities",
|
||||||
title: "Lock",
|
title: "Lock",
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// filter: {
|
||||||
|
// exclude: [
|
||||||
|
// {
|
||||||
|
// state: "not_home",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// include: [
|
||||||
|
// {
|
||||||
|
// entity_id: "device_tracker.annasiphone",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id: "device_tracker.iphone_2",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// type: "custom:monster-card",
|
||||||
|
// card: {
|
||||||
|
// show_header_toggle: false,
|
||||||
|
// type: "entities",
|
||||||
|
// title: "G\u00e4ster",
|
||||||
|
// },
|
||||||
|
// show_empty: false,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// filter: {
|
||||||
|
// exclude: [
|
||||||
|
// {
|
||||||
|
// state: "Inget",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// state: "i.u.",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// include: [
|
||||||
|
// {
|
||||||
|
// entity_id: "sensor.pollen_al",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id: "sensor.pollen_alm",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id: "sensor.pollen_salg_vide",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id: "sensor.pollen_bjork",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id: "sensor.pollen_bok",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id: "sensor.pollen_ek",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id: "sensor.pollen_grabo",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id: "sensor.pollen_gras",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id: "sensor.pollen_hassel",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// type: "custom:monster-card",
|
||||||
|
// card: {
|
||||||
|
// show_header_toggle: false,
|
||||||
|
// type: "entities",
|
||||||
|
// title: "Pollenniv\u00e5er",
|
||||||
|
// },
|
||||||
|
// show_empty: false,
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
cards: [
|
cards: [
|
||||||
{
|
{
|
||||||
@@ -117,6 +226,10 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
],
|
],
|
||||||
type: "vertical-stack",
|
type: "vertical-stack",
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// url: "https://embed.windy.com/embed2.html",
|
||||||
|
// type: "iframe",
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
entities: [
|
entities: [
|
||||||
{
|
{
|
||||||
@@ -150,7 +263,6 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
],
|
],
|
||||||
type: "glance",
|
type: "glance",
|
||||||
show_state: false,
|
show_state: false,
|
||||||
columns: 4,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
entities: ["sensor.oskar_bluetooth"],
|
entities: ["sensor.oskar_bluetooth"],
|
||||||
@@ -158,6 +270,32 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
type: "entities",
|
type: "entities",
|
||||||
title: "Occupancy",
|
title: "Occupancy",
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// filter: {
|
||||||
|
// exclude: [
|
||||||
|
// {
|
||||||
|
// state: false,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// include: [
|
||||||
|
// {
|
||||||
|
// entity_id:
|
||||||
|
// "binary_sensor.fibaro_system_unknown_type0c02_id1003_sensor_2",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// entity_id:
|
||||||
|
// "binary_sensor.fibaro_system_unknown_type0c02_id1003_sensor_3",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// type: "custom:monster-card",
|
||||||
|
// card: {
|
||||||
|
// show_header_toggle: false,
|
||||||
|
// type: "entities",
|
||||||
|
// title: "Brandvarnare",
|
||||||
|
// },
|
||||||
|
// show_empty: false,
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
type: "weather-forecast",
|
type: "weather-forecast",
|
||||||
entity: "weather.smhi_vader",
|
entity: "weather.smhi_vader",
|
||||||
@@ -240,9 +378,41 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
"binary_sensor.windows_server",
|
"binary_sensor.windows_server",
|
||||||
"binary_sensor.teamspeak",
|
"binary_sensor.teamspeak",
|
||||||
"binary_sensor.harmony_hub",
|
"binary_sensor.harmony_hub",
|
||||||
|
// {
|
||||||
|
// style: {
|
||||||
|
// height: "1px",
|
||||||
|
// width: "85%",
|
||||||
|
// "margin-left": "auto",
|
||||||
|
// background: "#62717b",
|
||||||
|
// "margin-right": "auto",
|
||||||
|
// },
|
||||||
|
// type: "divider",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// items: ["sensor.uptime_router", "sensor.installerad_routeros"],
|
||||||
|
// head: {
|
||||||
|
// entity: "binary_sensor.router",
|
||||||
|
// },
|
||||||
|
// type: "custom:fold-entity-row",
|
||||||
|
// group_config: {
|
||||||
|
// icon: "mdi:router",
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// items: [
|
||||||
|
// "sensor.uptime_router_server",
|
||||||
|
// "sensor.installerad_routeros_server",
|
||||||
|
// ],
|
||||||
|
// head: {
|
||||||
|
// entity: "binary_sensor.router_server",
|
||||||
|
// },
|
||||||
|
// type: "custom:fold-entity-row",
|
||||||
|
// group_config: {
|
||||||
|
// icon: "mdi:router",
|
||||||
|
// },
|
||||||
|
// },
|
||||||
],
|
],
|
||||||
show_header_toggle: false,
|
show_header_toggle: false,
|
||||||
state_color: true,
|
|
||||||
type: "entities",
|
type: "entities",
|
||||||
title: "Network",
|
title: "Network",
|
||||||
},
|
},
|
||||||
@@ -252,10 +422,29 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
|
|||||||
"binary_sensor.ubiquiti_switch",
|
"binary_sensor.ubiquiti_switch",
|
||||||
"binary_sensor.ubiquiti_nvr",
|
"binary_sensor.ubiquiti_nvr",
|
||||||
"binary_sensor.entre_kamera",
|
"binary_sensor.entre_kamera",
|
||||||
|
// {
|
||||||
|
// items: ["sensor.uptime_ap_1"],
|
||||||
|
// head: {
|
||||||
|
// entity: "binary_sensor.accesspunkt_1",
|
||||||
|
// },
|
||||||
|
// type: "custom:fold-entity-row",
|
||||||
|
// group_config: {
|
||||||
|
// icon: "router-wireless",
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// items: ["sensor.uptime_ap_2"],
|
||||||
|
// head: {
|
||||||
|
// entity: "binary_sensor.accesspunkt_2",
|
||||||
|
// },
|
||||||
|
// type: "custom:fold-entity-row",
|
||||||
|
// group_config: {
|
||||||
|
// icon: "router-wireless",
|
||||||
|
// },
|
||||||
|
// },
|
||||||
"sensor.total_clients_wireless",
|
"sensor.total_clients_wireless",
|
||||||
],
|
],
|
||||||
show_header_toggle: false,
|
show_header_toggle: false,
|
||||||
state_color: true,
|
|
||||||
type: "entities",
|
type: "entities",
|
||||||
title: "Ubiquiti",
|
title: "Ubiquiti",
|
||||||
},
|
},
|
||||||
|
@@ -215,7 +215,6 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
card: {
|
card: {
|
||||||
type: "glance",
|
type: "glance",
|
||||||
show_state: false,
|
show_state: false,
|
||||||
columns: 4,
|
|
||||||
},
|
},
|
||||||
state_filter: ["on"],
|
state_filter: ["on"],
|
||||||
},
|
},
|
||||||
@@ -809,6 +808,67 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
],
|
],
|
||||||
type: "vertical-stack",
|
type: "vertical-stack",
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// cards: [
|
||||||
|
// {
|
||||||
|
// entities: [
|
||||||
|
// {
|
||||||
|
// hide_when_off: true,
|
||||||
|
// toggle: true,
|
||||||
|
// type: "custom:slider-entity-row",
|
||||||
|
// name: "Bedside",
|
||||||
|
// entity: "light.bedside_lamp",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// hide_when_off: true,
|
||||||
|
// toggle: true,
|
||||||
|
// type: "custom:slider-entity-row",
|
||||||
|
// name: "Bedroom",
|
||||||
|
// entity: "light.bedroom_ceiling_light",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// hide_when_off: true,
|
||||||
|
// toggle: true,
|
||||||
|
// type: "custom:slider-entity-row",
|
||||||
|
// name: "Isa",
|
||||||
|
// entity: "light.isa_ceiling_light",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// hide_when_off: true,
|
||||||
|
// toggle: true,
|
||||||
|
// type: "custom:slider-entity-row",
|
||||||
|
// name: "Upstairs hallway",
|
||||||
|
// entity: "light.upstairs_hallway_ceiling_light_level",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// hide_when_off: true,
|
||||||
|
// toggle: true,
|
||||||
|
// type: "custom:slider-entity-row",
|
||||||
|
// name: "Nightlight",
|
||||||
|
// entity: "light.gateway_light_34ce008bfc4b",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// hide_when_off: true,
|
||||||
|
// toggle: true,
|
||||||
|
// type: "custom:slider-entity-row",
|
||||||
|
// name: "Walk in closet",
|
||||||
|
// entity: "light.walk_in_closet_lights",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// hide_when_off: true,
|
||||||
|
// toggle: false,
|
||||||
|
// type: "custom:slider-entity-row",
|
||||||
|
// name: "Stefan",
|
||||||
|
// entity: "light.stefan_lightstrip",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// show_header_toggle: false,
|
||||||
|
// type: "entities",
|
||||||
|
// title: "Upstairs",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// type: "vertical-stack",
|
||||||
|
// },
|
||||||
],
|
],
|
||||||
path: "lights",
|
path: "lights",
|
||||||
title: "Lights",
|
title: "Lights",
|
||||||
@@ -858,6 +918,10 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
name: "Dafang",
|
name: "Dafang",
|
||||||
icon: "mdi:webcam",
|
icon: "mdi:webcam",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "IR Hallway",
|
||||||
|
entity: "sensor.system_ir_blaster",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "IR Bedroom",
|
name: "IR Bedroom",
|
||||||
entity: "sensor.system_ir_blaster_bedroom",
|
entity: "sensor.system_ir_blaster_bedroom",
|
||||||
@@ -876,7 +940,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
"sensor.system_ring_chime",
|
"sensor.system_ring_chime",
|
||||||
],
|
],
|
||||||
type: "glance",
|
type: "glance",
|
||||||
columns: 4,
|
columns: 5,
|
||||||
show_state: false,
|
show_state: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -3,8 +3,8 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
|
internalProperty,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { CastManager } from "../../../src/cast/cast_manager";
|
import { CastManager } from "../../../src/cast/cast_manager";
|
||||||
|
@@ -3,9 +3,9 @@ import {
|
|||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
|
internalProperty,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { until } from "lit-html/directives/until";
|
import { until } from "lit-html/directives/until";
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
|
import "../../src/resources/safari-14-attachshadow-patch";
|
||||||
import "@polymer/polymer/lib/elements/dom-if";
|
import "@polymer/polymer/lib/elements/dom-if";
|
||||||
import "@polymer/polymer/lib/elements/dom-repeat";
|
import "@polymer/polymer/lib/elements/dom-repeat";
|
||||||
import "../../src/resources/ha-style";
|
import "../../src/resources/ha-style";
|
||||||
import "../../src/resources/roboto";
|
import "../../src/resources/roboto";
|
||||||
import "../../src/resources/safari-14-attachshadow-patch";
|
|
||||||
import "./ha-demo";
|
import "./ha-demo";
|
||||||
|
|
||||||
/* polyfill for paper-dropdown */
|
/* polyfill for paper-dropdown */
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
// Compat needs to be first import
|
|
||||||
import "../../src/resources/compatibility";
|
import "../../src/resources/compatibility";
|
||||||
import { isNavigationClick } from "../../src/common/dom/is-navigation-click";
|
import { isNavigationClick } from "../../src/common/dom/is-navigation-click";
|
||||||
import { navigate } from "../../src/common/navigate";
|
import { navigate } from "../../src/common/navigate";
|
||||||
|
@@ -2,10 +2,10 @@ import "@polymer/app-layout/app-toolbar/app-toolbar";
|
|||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
/* eslint-plugin-disable lit */
|
/* eslint-plugin-disable lit */
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
|
||||||
import "../../../src/components/ha-formfield";
|
|
||||||
import "../../../src/components/ha-switch";
|
import "../../../src/components/ha-switch";
|
||||||
|
import "../../../src/components/ha-formfield";
|
||||||
import "./demo-card";
|
import "./demo-card";
|
||||||
|
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
||||||
|
|
||||||
class DemoCards extends PolymerElement {
|
class DemoCards extends PolymerElement {
|
||||||
static get template() {
|
static get template() {
|
||||||
|
@@ -2,8 +2,8 @@ import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|||||||
/* eslint-plugin-disable lit */
|
/* eslint-plugin-disable lit */
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../src/dialogs/more-info/more-info-content";
|
|
||||||
import "../../../src/state-summary/state-card-content";
|
import "../../../src/state-summary/state-card-content";
|
||||||
|
import "../../../src/dialogs/more-info/more-info-content";
|
||||||
|
|
||||||
class DemoMoreInfo extends PolymerElement {
|
class DemoMoreInfo extends PolymerElement {
|
||||||
static get template() {
|
static get template() {
|
||||||
|
@@ -2,10 +2,10 @@ import "@polymer/app-layout/app-toolbar/app-toolbar";
|
|||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
/* eslint-plugin-disable lit */
|
/* eslint-plugin-disable lit */
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
|
||||||
import "../../../src/components/ha-formfield";
|
|
||||||
import "../../../src/components/ha-switch";
|
import "../../../src/components/ha-switch";
|
||||||
|
import "../../../src/components/ha-formfield";
|
||||||
import "./demo-more-info";
|
import "./demo-more-info";
|
||||||
|
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
||||||
|
|
||||||
class DemoMoreInfos extends PolymerElement {
|
class DemoMoreInfos extends PolymerElement {
|
||||||
static get template() {
|
static get template() {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
@@ -48,7 +48,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
const CONFIGS = [
|
const CONFIGS = [
|
||||||
{
|
{
|
||||||
heading: "Unfiltered controller",
|
heading: "Controller",
|
||||||
config: `
|
config: `
|
||||||
- type: entities
|
- type: entities
|
||||||
entities:
|
entities:
|
||||||
@@ -58,7 +58,7 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Filtered entities card",
|
heading: "Basic",
|
||||||
config: `
|
config: `
|
||||||
- type: entity-filter
|
- type: entity-filter
|
||||||
entities:
|
entities:
|
||||||
@@ -74,27 +74,7 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: 'With "entities" card config',
|
heading: "With card config",
|
||||||
config: `
|
|
||||||
- type: entity-filter
|
|
||||||
entities:
|
|
||||||
- device_tracker.demo_anne_therese
|
|
||||||
- device_tracker.demo_home_boy
|
|
||||||
- device_tracker.demo_paulus
|
|
||||||
- light.bed_light
|
|
||||||
- light.ceiling_lights
|
|
||||||
- light.kitchen_lights
|
|
||||||
state_filter:
|
|
||||||
- "on"
|
|
||||||
- not_home
|
|
||||||
card:
|
|
||||||
type: entities
|
|
||||||
title: Custom Title
|
|
||||||
show_header_toggle: false
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
heading: 'With "glance" card config',
|
|
||||||
config: `
|
config: `
|
||||||
- type: entity-filter
|
- type: entity-filter
|
||||||
entities:
|
entities:
|
||||||
@@ -109,8 +89,7 @@ const CONFIGS = [
|
|||||||
- not_home
|
- not_home
|
||||||
card:
|
card:
|
||||||
type: glance
|
type: glance
|
||||||
show_state: true
|
show_state: false
|
||||||
title: Custom Title
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
@@ -82,8 +82,7 @@ const CONFIGS = [
|
|||||||
heading: "With title",
|
heading: "With title",
|
||||||
config: `
|
config: `
|
||||||
- type: glance
|
- type: glance
|
||||||
title: Custom title
|
title: This is glance
|
||||||
columns: 4
|
|
||||||
entities:
|
entities:
|
||||||
- device_tracker.demo_paulus
|
- device_tracker.demo_paulus
|
||||||
- media_player.living_room
|
- media_player.living_room
|
||||||
@@ -110,10 +109,9 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "No entity names",
|
heading: "No name",
|
||||||
config: `
|
config: `
|
||||||
- type: glance
|
- type: glance
|
||||||
columns: 4
|
|
||||||
show_name: false
|
show_name: false
|
||||||
entities:
|
entities:
|
||||||
- device_tracker.demo_paulus
|
- device_tracker.demo_paulus
|
||||||
@@ -126,10 +124,9 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "No state labels",
|
heading: "No state",
|
||||||
config: `
|
config: `
|
||||||
- type: glance
|
- type: glance
|
||||||
columns: 4
|
|
||||||
show_state: false
|
show_state: false
|
||||||
entities:
|
entities:
|
||||||
- device_tracker.demo_paulus
|
- device_tracker.demo_paulus
|
||||||
@@ -142,10 +139,9 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "No names and no state labels",
|
heading: "No name and no state",
|
||||||
config: `
|
config: `
|
||||||
- type: glance
|
- type: glance
|
||||||
columns: 4
|
|
||||||
show_name: false
|
show_name: false
|
||||||
show_state: false
|
show_state: false
|
||||||
entities:
|
entities:
|
||||||
@@ -159,24 +155,47 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Custom name + custom icon",
|
heading: "Custom name, custom icon",
|
||||||
config: `
|
config: `
|
||||||
- type: glance
|
- type: glance
|
||||||
columns: 4
|
|
||||||
entities:
|
entities:
|
||||||
- entity: device_tracker.demo_paulus
|
- entity: device_tracker.demo_paulus
|
||||||
name: ¯\\_(ツ)_/¯
|
name: ¯\\_(ツ)_/¯
|
||||||
icon: mdi:home-assistant
|
icon: mdi:home-assistant
|
||||||
- entity: media_player.living_room
|
- media_player.living_room
|
||||||
name: ¯\\_(ツ)_/¯
|
- sun.sun
|
||||||
icon: mdi:home-assistant
|
- cover.kitchen_window
|
||||||
|
- entity: light.kitchen_lights
|
||||||
|
icon: mdi:alarm-light
|
||||||
|
- lock.kitchen_door
|
||||||
|
- light.ceiling_lights
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: "Custom tap action",
|
||||||
|
config: `
|
||||||
|
- type: glance
|
||||||
|
entities:
|
||||||
|
- entity: lock.kitchen_door
|
||||||
|
tap_action:
|
||||||
|
type: toggle
|
||||||
|
- entity: light.ceiling_lights
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: light.turn_on
|
||||||
|
service_data:
|
||||||
|
entity_id: light.ceiling_lights
|
||||||
|
- device_tracker.demo_paulus
|
||||||
|
- media_player.living_room
|
||||||
|
- sun.sun
|
||||||
|
- cover.kitchen_window
|
||||||
|
- light.kitchen_lights
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Selectively hidden name",
|
heading: "Selectively hidden name",
|
||||||
config: `
|
config: `
|
||||||
- type: glance
|
- type: glance
|
||||||
columns: 4
|
|
||||||
entities:
|
entities:
|
||||||
- device_tracker.demo_paulus
|
- device_tracker.demo_paulus
|
||||||
- entity: media_player.living_room
|
- entity: media_player.living_room
|
||||||
@@ -185,32 +204,21 @@ const CONFIGS = [
|
|||||||
- entity: cover.kitchen_window
|
- entity: cover.kitchen_window
|
||||||
name:
|
name:
|
||||||
- light.kitchen_lights
|
- light.kitchen_lights
|
||||||
- entity: lock.kitchen_door
|
|
||||||
name:
|
|
||||||
- light.ceiling_lights
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Custom tap action",
|
heading: "Primary theme",
|
||||||
config: `
|
config: `
|
||||||
- type: glance
|
- type: glance
|
||||||
columns: 4
|
theming: primary
|
||||||
entities:
|
entities:
|
||||||
- entity: lock.kitchen_door
|
- device_tracker.demo_paulus
|
||||||
name: Custom
|
- media_player.living_room
|
||||||
tap_action:
|
- sun.sun
|
||||||
type: toggle
|
- cover.kitchen_window
|
||||||
- entity: light.ceiling_lights
|
- light.kitchen_lights
|
||||||
name: Custom
|
- lock.kitchen_door
|
||||||
tap_action:
|
- light.ceiling_lights
|
||||||
action: call-service
|
|
||||||
service: light.turn_on
|
|
||||||
service_data:
|
|
||||||
entity_id: light.ceiling_lights
|
|
||||||
- entity: sun.sun
|
|
||||||
name: Regular
|
|
||||||
- entity: light.kitchen_lights
|
|
||||||
name: Regular
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { customElement, html, LitElement, TemplateResult } from "lit-element";
|
import { html, LitElement, customElement, TemplateResult } from "lit-element";
|
||||||
import "../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const CONFIGS = [
|
const CONFIGS = [
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
customElement,
|
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
customElement,
|
||||||
property,
|
property,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
@@ -10,20 +10,20 @@ import {
|
|||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import {
|
import {
|
||||||
SUPPORT_BRIGHTNESS,
|
SUPPORT_BRIGHTNESS,
|
||||||
SUPPORT_COLOR,
|
|
||||||
SUPPORT_COLOR_TEMP,
|
SUPPORT_COLOR_TEMP,
|
||||||
SUPPORT_EFFECT,
|
SUPPORT_EFFECT,
|
||||||
SUPPORT_FLASH,
|
SUPPORT_FLASH,
|
||||||
|
SUPPORT_COLOR,
|
||||||
SUPPORT_TRANSITION,
|
SUPPORT_TRANSITION,
|
||||||
SUPPORT_WHITE_VALUE,
|
SUPPORT_WHITE_VALUE,
|
||||||
} from "../../../src/data/light";
|
} from "../../../src/data/light";
|
||||||
import "../../../src/dialogs/more-info/more-info-content";
|
|
||||||
import { getEntity } from "../../../src/fake_data/entity";
|
import { getEntity } from "../../../src/fake_data/entity";
|
||||||
import {
|
import {
|
||||||
MockHomeAssistant,
|
|
||||||
provideHass,
|
provideHass,
|
||||||
|
MockHomeAssistant,
|
||||||
} from "../../../src/fake_data/provide_hass";
|
} from "../../../src/fake_data/provide_hass";
|
||||||
import "../components/demo-more-infos";
|
import "../components/demo-more-infos";
|
||||||
|
import "../../../src/dialogs/more-info/more-info-content";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("light", "bed_light", "on", {
|
getEntity("light", "bed_light", "on", {
|
||||||
|
@@ -15,7 +15,6 @@ import {
|
|||||||
HassioAddonInfo,
|
HassioAddonInfo,
|
||||||
HassioAddonRepository,
|
HassioAddonRepository,
|
||||||
} from "../../../src/data/hassio/addon";
|
} from "../../../src/data/hassio/addon";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
import "../components/hassio-card-content";
|
import "../components/hassio-card-content";
|
||||||
import { filterAndSort } from "../components/hassio-filter-addons";
|
import { filterAndSort } from "../components/hassio-filter-addons";
|
||||||
@@ -24,8 +23,6 @@ import { hassioStyle } from "../resources/hassio-style";
|
|||||||
class HassioAddonRepositoryEl extends LitElement {
|
class HassioAddonRepositoryEl extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public repo!: HassioAddonRepository;
|
@property({ attribute: false }) public repo!: HassioAddonRepository;
|
||||||
|
|
||||||
@property({ attribute: false }) public addons!: HassioAddonInfo[];
|
@property({ attribute: false }) public addons!: HassioAddonInfo[];
|
||||||
@@ -57,11 +54,7 @@ class HassioAddonRepositoryEl extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<p class="description">
|
<p class="description">
|
||||||
${this.supervisor.localize(
|
No results found in "${repo.name}."
|
||||||
"store.no_results_found",
|
|
||||||
"repository",
|
|
||||||
repo.name
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -90,13 +83,11 @@ class HassioAddonRepositoryEl extends LitElement {
|
|||||||
: mdiPuzzle}
|
: mdiPuzzle}
|
||||||
.iconTitle=${addon.installed
|
.iconTitle=${addon.installed
|
||||||
? addon.update_available
|
? addon.update_available
|
||||||
? this.supervisor.localize(
|
? "New version available"
|
||||||
"common.new_version_available"
|
: "Add-on is installed"
|
||||||
)
|
|
||||||
: this.supervisor.localize("addon.installed")
|
|
||||||
: addon.available
|
: addon.available
|
||||||
? this.supervisor.localize("addon.not_installed")
|
? "Add-on is not installed"
|
||||||
: this.supervisor.localize("addon.not_available")}
|
: "Add-on is not available on your system"}
|
||||||
.iconClass=${addon.installed
|
.iconClass=${addon.installed
|
||||||
? addon.update_available
|
? addon.update_available
|
||||||
? "update"
|
? "update"
|
||||||
|
@@ -11,18 +11,17 @@ import {
|
|||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { html, TemplateResult } from "lit-html";
|
import { html, TemplateResult } from "lit-html";
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
|
||||||
import "../../../src/common/search/search-input";
|
import "../../../src/common/search/search-input";
|
||||||
import "../../../src/components/ha-button-menu";
|
import "../../../src/components/ha-button-menu";
|
||||||
import "../../../src/components/ha-svg-icon";
|
import "../../../src/components/ha-svg-icon";
|
||||||
import {
|
import {
|
||||||
|
fetchHassioAddonsInfo,
|
||||||
HassioAddonInfo,
|
HassioAddonInfo,
|
||||||
HassioAddonRepository,
|
HassioAddonRepository,
|
||||||
reloadHassioAddons,
|
reloadHassioAddons,
|
||||||
} from "../../../src/data/hassio/addon";
|
} from "../../../src/data/hassio/addon";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
||||||
import "../../../src/layouts/hass-loading-screen";
|
import "../../../src/layouts/hass-loading-screen";
|
||||||
import "../../../src/layouts/hass-tabs-subpage";
|
import "../../../src/layouts/hass-tabs-subpage";
|
||||||
import { HomeAssistant, Route } from "../../../src/types";
|
import { HomeAssistant, Route } from "../../../src/types";
|
||||||
@@ -50,43 +49,58 @@ const sortRepos = (a: HassioAddonRepository, b: HassioAddonRepository) => {
|
|||||||
class HassioAddonStore extends LitElement {
|
class HassioAddonStore extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
|
@property({ attribute: false }) private _addons?: HassioAddonInfo[];
|
||||||
|
|
||||||
|
@property({ attribute: false }) private _repos?: HassioAddonRepository[];
|
||||||
|
|
||||||
@internalProperty() private _filter?: string;
|
@internalProperty() private _filter?: string;
|
||||||
|
|
||||||
public async refreshData() {
|
public async refreshData() {
|
||||||
|
this._repos = undefined;
|
||||||
|
this._addons = undefined;
|
||||||
|
this._filter = undefined;
|
||||||
await reloadHassioAddons(this.hass);
|
await reloadHassioAddons(this.hass);
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
let repos: TemplateResult[] = [];
|
const repos: TemplateResult[] = [];
|
||||||
|
|
||||||
if (this.supervisor.addon.repositories) {
|
if (this._repos) {
|
||||||
repos = this.addonRepositories(
|
for (const repo of this._repos) {
|
||||||
this.supervisor.addon.repositories,
|
const addons = this._addons!.filter(
|
||||||
this.supervisor.addon.addons,
|
(addon) => addon.repository === repo.slug
|
||||||
this._filter
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (addons.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
repos.push(html`
|
||||||
|
<hassio-addon-repository
|
||||||
|
.hass=${this.hass}
|
||||||
|
.repo=${repo}
|
||||||
|
.addons=${addons}
|
||||||
|
.filter=${this._filter!}
|
||||||
|
></hassio-addon-repository>
|
||||||
|
`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<hass-tabs-subpage
|
<hass-tabs-subpage
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.localizeFunc=${this.supervisor.localize}
|
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
.tabs=${supervisorTabs}
|
hassio
|
||||||
main-page
|
main-page
|
||||||
supervisor
|
.tabs=${supervisorTabs}
|
||||||
>
|
>
|
||||||
<span slot="header">
|
<span slot="header">Add-on Store</span>
|
||||||
${this.supervisor.localize("panel.store")}
|
|
||||||
</span>
|
|
||||||
<ha-button-menu
|
<ha-button-menu
|
||||||
corner="BOTTOM_START"
|
corner="BOTTOM_START"
|
||||||
slot="toolbar-icon"
|
slot="toolbar-icon"
|
||||||
@@ -96,15 +110,15 @@ class HassioAddonStore extends LitElement {
|
|||||||
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
||||||
</mwc-icon-button>
|
</mwc-icon-button>
|
||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("store.repositories")}
|
Repositories
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("common.reload")}
|
Reload
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
${this.hass.userData?.showAdvanced &&
|
${this.hass.userData?.showAdvanced &&
|
||||||
atLeastVersion(this.hass.config.version, 0, 117)
|
atLeastVersion(this.hass.config.version, 0, 117)
|
||||||
? html`<mwc-list-item>
|
? html`<mwc-list-item>
|
||||||
${this.supervisor.localize("store.registries")}
|
Registries
|
||||||
</mwc-list-item>`
|
</mwc-list-item>`
|
||||||
: ""}
|
: ""}
|
||||||
</ha-button-menu>
|
</ha-button-menu>
|
||||||
@@ -125,9 +139,11 @@ class HassioAddonStore extends LitElement {
|
|||||||
${!this.hass.userData?.showAdvanced
|
${!this.hass.userData?.showAdvanced
|
||||||
? html`
|
? html`
|
||||||
<div class="advanced">
|
<div class="advanced">
|
||||||
|
Missing add-ons? Enable advanced mode on
|
||||||
<a href="/profile" target="_top">
|
<a href="/profile" target="_top">
|
||||||
${this.supervisor.localize("store.missing_addons")}
|
your profile page
|
||||||
</a>
|
</a>
|
||||||
|
.
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -141,32 +157,6 @@ class HassioAddonStore extends LitElement {
|
|||||||
this._loadData();
|
this._loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private addonRepositories = memoizeOne(
|
|
||||||
(
|
|
||||||
repositories: HassioAddonRepository[],
|
|
||||||
addons: HassioAddonInfo[],
|
|
||||||
filter?: string
|
|
||||||
) => {
|
|
||||||
return repositories.sort(sortRepos).map((repo) => {
|
|
||||||
const filteredAddons = addons.filter(
|
|
||||||
(addon) => addon.repository === repo.slug
|
|
||||||
);
|
|
||||||
|
|
||||||
return filteredAddons.length !== 0
|
|
||||||
? html`
|
|
||||||
<hassio-addon-repository
|
|
||||||
.hass=${this.hass}
|
|
||||||
.repo=${repo}
|
|
||||||
.addons=${filteredAddons}
|
|
||||||
.filter=${filter!}
|
|
||||||
.supervisor=${this.supervisor}
|
|
||||||
></hassio-addon-repository>
|
|
||||||
`
|
|
||||||
: html``;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
private _handleAction(ev: CustomEvent<ActionDetail>) {
|
private _handleAction(ev: CustomEvent<ActionDetail>) {
|
||||||
switch (ev.detail.index) {
|
switch (ev.detail.index) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -189,20 +179,24 @@ class HassioAddonStore extends LitElement {
|
|||||||
|
|
||||||
private async _manageRepositories() {
|
private async _manageRepositories() {
|
||||||
showRepositoriesDialog(this, {
|
showRepositoriesDialog(this, {
|
||||||
supervisor: this.supervisor,
|
repos: this._repos!,
|
||||||
loadData: () => this._loadData(),
|
loadData: () => this._loadData(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _manageRegistries() {
|
private async _manageRegistries() {
|
||||||
showRegistriesDialog(this, { supervisor: this.supervisor });
|
showRegistriesDialog(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _loadData() {
|
private async _loadData() {
|
||||||
fireEvent(this, "supervisor-colllection-refresh", { colllection: "addon" });
|
try {
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
|
||||||
colllection: "supervisor",
|
this._repos = addonsInfo.repositories;
|
||||||
});
|
this._repos.sort(sortRepos);
|
||||||
|
this._addons = addonsInfo.addons;
|
||||||
|
} catch (err) {
|
||||||
|
alert(extractApiErrorMessage(err));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _filterChanged(e) {
|
private async _filterChanged(e) {
|
||||||
|
@@ -7,14 +7,13 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
|
internalProperty,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "web-animations-js/web-animations-next-lite.min";
|
import "web-animations-js/web-animations-next-lite.min";
|
||||||
import "../../../../src/components/buttons/ha-progress-button";
|
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
import {
|
import {
|
||||||
HassioAddonDetails,
|
HassioAddonDetails,
|
||||||
@@ -25,18 +24,16 @@ import {
|
|||||||
fetchHassioHardwareAudio,
|
fetchHassioHardwareAudio,
|
||||||
HassioHardwareAudioDevice,
|
HassioHardwareAudioDevice,
|
||||||
} from "../../../../src/data/hassio/hardware";
|
} from "../../../../src/data/hassio/hardware";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import { haStyle } from "../../../../src/resources/styles";
|
import { haStyle } from "../../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
||||||
import { hassioStyle } from "../../resources/hassio-style";
|
import { hassioStyle } from "../../resources/hassio-style";
|
||||||
|
import "../../../../src/components/buttons/ha-progress-button";
|
||||||
|
|
||||||
@customElement("hassio-addon-audio")
|
@customElement("hassio-addon-audio")
|
||||||
class HassioAddonAudio extends LitElement {
|
class HassioAddonAudio extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@internalProperty() private _error?: string;
|
||||||
@@ -51,16 +48,12 @@ class HassioAddonAudio extends LitElement {
|
|||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<ha-card
|
<ha-card header="Audio">
|
||||||
.header=${this.supervisor.localize("addon.configuration.audio.header")}
|
|
||||||
>
|
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
||||||
|
|
||||||
<paper-dropdown-menu
|
<paper-dropdown-menu
|
||||||
.label=${this.supervisor.localize(
|
label="Input"
|
||||||
"addon.configuration.audio.input"
|
|
||||||
)}
|
|
||||||
@iron-select=${this._setInputDevice}
|
@iron-select=${this._setInputDevice}
|
||||||
>
|
>
|
||||||
<paper-listbox
|
<paper-listbox
|
||||||
@@ -71,17 +64,15 @@ class HassioAddonAudio extends LitElement {
|
|||||||
${this._inputDevices &&
|
${this._inputDevices &&
|
||||||
this._inputDevices.map((item) => {
|
this._inputDevices.map((item) => {
|
||||||
return html`
|
return html`
|
||||||
<paper-item device=${item.device || ""}>
|
<paper-item device=${item.device || ""}
|
||||||
${item.name}
|
>${item.name}</paper-item
|
||||||
</paper-item>
|
>
|
||||||
`;
|
`;
|
||||||
})}
|
})}
|
||||||
</paper-listbox>
|
</paper-listbox>
|
||||||
</paper-dropdown-menu>
|
</paper-dropdown-menu>
|
||||||
<paper-dropdown-menu
|
<paper-dropdown-menu
|
||||||
.label=${this.supervisor.localize(
|
label="Output"
|
||||||
"addon.configuration.audio.output"
|
|
||||||
)}
|
|
||||||
@iron-select=${this._setOutputDevice}
|
@iron-select=${this._setOutputDevice}
|
||||||
>
|
>
|
||||||
<paper-listbox
|
<paper-listbox
|
||||||
@@ -102,7 +93,7 @@ class HassioAddonAudio extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<ha-progress-button @click=${this._saveSettings}>
|
<ha-progress-button @click=${this._saveSettings}>
|
||||||
${this.supervisor.localize("common.save")}
|
Save
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
@@ -161,7 +152,7 @@ class HassioAddonAudio extends LitElement {
|
|||||||
|
|
||||||
const noDevice: HassioHardwareAudioDevice = {
|
const noDevice: HassioHardwareAudioDevice = {
|
||||||
device: "default",
|
device: "default",
|
||||||
name: this.supervisor.localize("addon.configuration.audio.default"),
|
name: "Default",
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -198,7 +189,7 @@ class HassioAddonAudio extends LitElement {
|
|||||||
try {
|
try {
|
||||||
await setHassioAddonOption(this.hass, this.addon.slug, data);
|
await setHassioAddonOption(this.hass, this.addon.slug, data);
|
||||||
if (this.addon?.state === "started") {
|
if (this.addon?.state === "started") {
|
||||||
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
await suggestAddonRestart(this, this.hass, this.addon);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
this._error = "Failed to set addon audio device";
|
this._error = "Failed to set addon audio device";
|
||||||
|
@@ -7,12 +7,11 @@ import {
|
|||||||
property,
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "../../../../src/components/ha-circular-progress";
|
|
||||||
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import { haStyle } from "../../../../src/resources/styles";
|
import { haStyle } from "../../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import { hassioStyle } from "../../resources/hassio-style";
|
import { hassioStyle } from "../../resources/hassio-style";
|
||||||
|
import "../../../../src/components/ha-circular-progress";
|
||||||
import "./hassio-addon-audio";
|
import "./hassio-addon-audio";
|
||||||
import "./hassio-addon-config";
|
import "./hassio-addon-config";
|
||||||
import "./hassio-addon-network";
|
import "./hassio-addon-network";
|
||||||
@@ -21,37 +20,23 @@ import "./hassio-addon-network";
|
|||||||
class HassioAddonConfigDashboard extends LitElement {
|
class HassioAddonConfigDashboard extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (!this.addon) {
|
if (!this.addon) {
|
||||||
return html`<ha-circular-progress active></ha-circular-progress>`;
|
return html`<ha-circular-progress active></ha-circular-progress>`;
|
||||||
}
|
}
|
||||||
const hasConfiguration =
|
|
||||||
(this.addon.options && Object.keys(this.addon.options).length) ||
|
|
||||||
(this.addon.schema && Object.keys(this.addon.schema).length);
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${hasConfiguration || this.addon.network || this.addon.audio
|
|
||||||
? html`
|
|
||||||
${hasConfiguration
|
|
||||||
? html`
|
|
||||||
<hassio-addon-config
|
<hassio-addon-config
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.addon=${this.addon}
|
.addon=${this.addon}
|
||||||
.supervisor=${this.supervisor}
|
|
||||||
></hassio-addon-config>
|
></hassio-addon-config>
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
${this.addon.network
|
${this.addon.network
|
||||||
? html`
|
? html`
|
||||||
<hassio-addon-network
|
<hassio-addon-network
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.addon=${this.addon}
|
.addon=${this.addon}
|
||||||
.supervisor=${this.supervisor}
|
|
||||||
></hassio-addon-network>
|
></hassio-addon-network>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -60,12 +45,9 @@ class HassioAddonConfigDashboard extends LitElement {
|
|||||||
<hassio-addon-audio
|
<hassio-addon-audio
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.addon=${this.addon}
|
.addon=${this.addon}
|
||||||
.supervisor=${this.supervisor}
|
|
||||||
></hassio-addon-audio>
|
></hassio-addon-audio>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
`
|
|
||||||
: this.supervisor.localize("addon.configuration.no_configuration")}
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,4 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import { ActionDetail } from "@material/mwc-list";
|
|
||||||
import "@material/mwc-list/mwc-list-item";
|
|
||||||
import { mdiDotsVertical } from "@mdi/js";
|
|
||||||
import "@polymer/iron-autogrow-textarea/iron-autogrow-textarea";
|
import "@polymer/iron-autogrow-textarea/iron-autogrow-textarea";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
@@ -15,15 +12,9 @@ import {
|
|||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import "../../../../src/components/buttons/ha-progress-button";
|
import "../../../../src/components/buttons/ha-progress-button";
|
||||||
import "../../../../src/components/ha-button-menu";
|
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
import "../../../../src/components/ha-form/ha-form";
|
|
||||||
import type { HaFormSchema } from "../../../../src/components/ha-form/ha-form";
|
|
||||||
import "../../../../src/components/ha-formfield";
|
|
||||||
import "../../../../src/components/ha-switch";
|
|
||||||
import "../../../../src/components/ha-yaml-editor";
|
import "../../../../src/components/ha-yaml-editor";
|
||||||
import type { HaYamlEditor } from "../../../../src/components/ha-yaml-editor";
|
import type { HaYamlEditor } from "../../../../src/components/ha-yaml-editor";
|
||||||
import {
|
import {
|
||||||
@@ -32,208 +23,73 @@ import {
|
|||||||
setHassioAddonOption,
|
setHassioAddonOption,
|
||||||
} from "../../../../src/data/hassio/addon";
|
} from "../../../../src/data/hassio/addon";
|
||||||
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box";
|
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box";
|
||||||
import { haStyle } from "../../../../src/resources/styles";
|
import { haStyle } from "../../../../src/resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
||||||
import { hassioStyle } from "../../resources/hassio-style";
|
import { hassioStyle } from "../../resources/hassio-style";
|
||||||
|
|
||||||
const SUPPORTED_UI_TYPES = ["string", "select", "boolean", "integer", "float"];
|
|
||||||
|
|
||||||
@customElement("hassio-addon-config")
|
@customElement("hassio-addon-config")
|
||||||
class HassioAddonConfig extends LitElement {
|
class HassioAddonConfig extends LitElement {
|
||||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||||
|
|
||||||
|
@internalProperty() private _error?: string;
|
||||||
|
|
||||||
@property({ type: Boolean }) private _configHasChanged = false;
|
@property({ type: Boolean }) private _configHasChanged = false;
|
||||||
|
|
||||||
@property({ type: Boolean }) private _valid = true;
|
@property({ type: Boolean }) private _valid = true;
|
||||||
|
|
||||||
@internalProperty() private _canShowSchema = false;
|
@query("ha-yaml-editor", true) private _editor!: HaYamlEditor;
|
||||||
|
|
||||||
@internalProperty() private _showOptional = false;
|
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
|
||||||
|
|
||||||
@internalProperty() private _options?: Record<string, unknown>;
|
|
||||||
|
|
||||||
@internalProperty() private _yamlMode = false;
|
|
||||||
|
|
||||||
@query("ha-yaml-editor") private _editor?: HaYamlEditor;
|
|
||||||
|
|
||||||
public computeLabel = (entry: HaFormSchema): string => {
|
|
||||||
return (
|
|
||||||
this.addon.translations[this.hass.language]?.configuration?.[entry.name]
|
|
||||||
?.name ||
|
|
||||||
this.addon.translations.en?.configuration?.[entry.name].name ||
|
|
||||||
entry.name
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
private _filteredShchema = memoizeOne(
|
|
||||||
(options: Record<string, unknown>, schema: HaFormSchema[]) => {
|
|
||||||
return schema.filter((entry) => entry.name in options || entry.required);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const showForm =
|
|
||||||
!this._yamlMode && this._canShowSchema && this.addon.schema;
|
|
||||||
const hasHiddenOptions =
|
|
||||||
showForm &&
|
|
||||||
JSON.stringify(this.addon.schema) !==
|
|
||||||
JSON.stringify(
|
|
||||||
this._filteredShchema(this.addon.options, this.addon.schema!)
|
|
||||||
);
|
|
||||||
return html`
|
return html`
|
||||||
<h1>${this.addon.name}</h1>
|
<h1>${this.addon.name}</h1>
|
||||||
<ha-card>
|
<ha-card header="Configuration">
|
||||||
<div class="header">
|
|
||||||
<h2>
|
|
||||||
${this.supervisor.localize("addon.configuration.options.header")}
|
|
||||||
</h2>
|
|
||||||
<div class="card-menu">
|
|
||||||
<ha-button-menu corner="BOTTOM_START" @action=${this._handleAction}>
|
|
||||||
<mwc-icon-button slot="trigger">
|
|
||||||
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
|
||||||
</mwc-icon-button>
|
|
||||||
<mwc-list-item .disabled=${!this._canShowSchema}>
|
|
||||||
${this._yamlMode
|
|
||||||
? this.supervisor.localize(
|
|
||||||
"addon.configuration.options.edit_in_ui"
|
|
||||||
)
|
|
||||||
: this.supervisor.localize(
|
|
||||||
"addon.configuration.options.edit_in_yaml"
|
|
||||||
)}
|
|
||||||
</mwc-list-item>
|
|
||||||
<mwc-list-item class="warning">
|
|
||||||
${this.supervisor.localize("common.reset_defaults")}
|
|
||||||
</mwc-list-item>
|
|
||||||
</ha-button-menu>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
${showForm
|
<ha-yaml-editor
|
||||||
? html`<ha-form
|
|
||||||
.data=${this._options!}
|
|
||||||
@value-changed=${this._configChanged}
|
@value-changed=${this._configChanged}
|
||||||
.computeLabel=${this.computeLabel}
|
></ha-yaml-editor>
|
||||||
.schema=${this._showOptional
|
|
||||||
? this.addon.schema!
|
|
||||||
: this._filteredShchema(
|
|
||||||
this.addon.options,
|
|
||||||
this.addon.schema!
|
|
||||||
)}
|
|
||||||
></ha-form>`
|
|
||||||
: html` <ha-yaml-editor
|
|
||||||
@value-changed=${this._configChanged}
|
|
||||||
></ha-yaml-editor>`}
|
|
||||||
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
||||||
${!this._yamlMode ||
|
${this._valid ? "" : html` <div class="errors">Invalid YAML</div> `}
|
||||||
(this._canShowSchema && this.addon.schema) ||
|
|
||||||
this._valid
|
|
||||||
? ""
|
|
||||||
: html`
|
|
||||||
<div class="errors">
|
|
||||||
${this.supervisor.localize(
|
|
||||||
"addon.configuration.options.invalid_yaml"
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
`}
|
<div class="card-actions">
|
||||||
</div>
|
<ha-progress-button class="warning" @click=${this._resetTapped}>
|
||||||
${hasHiddenOptions
|
Reset to defaults
|
||||||
? html`<ha-formfield
|
</ha-progress-button>
|
||||||
class="show-additional"
|
|
||||||
.label=${this.supervisor.localize(
|
|
||||||
"addon.configuration.options.show_unused_optional"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ha-switch
|
|
||||||
@change=${this._toggleOptional}
|
|
||||||
.checked=${this._showOptional}
|
|
||||||
>
|
|
||||||
</ha-switch>
|
|
||||||
</ha-formfield>`
|
|
||||||
: ""}
|
|
||||||
<div class="card-actions right">
|
|
||||||
<ha-progress-button
|
<ha-progress-button
|
||||||
@click=${this._saveTapped}
|
@click=${this._saveTapped}
|
||||||
.disabled=${!this._configHasChanged || !this._valid}
|
.disabled=${!this._configHasChanged || !this._valid}
|
||||||
>
|
>
|
||||||
Save ${this.supervisor.localize("common.save")}
|
Save
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(changedProps) {
|
|
||||||
super.firstUpdated(changedProps);
|
|
||||||
this._canShowSchema = !this.addon.schema!.find(
|
|
||||||
// @ts-ignore
|
|
||||||
(entry) => !SUPPORTED_UI_TYPES.includes(entry.type) || entry.multiple
|
|
||||||
);
|
|
||||||
this._yamlMode = !this._canShowSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected updated(changedProperties: PropertyValues): void {
|
protected updated(changedProperties: PropertyValues): void {
|
||||||
if (changedProperties.has("addon")) {
|
|
||||||
this._options = { ...this.addon.options };
|
|
||||||
}
|
|
||||||
super.updated(changedProperties);
|
super.updated(changedProperties);
|
||||||
if (
|
if (changedProperties.has("addon")) {
|
||||||
changedProperties.has("_yamlMode") ||
|
this._editor.setValue(this.addon.options);
|
||||||
changedProperties.has("_options")
|
|
||||||
) {
|
|
||||||
if (this._yamlMode) {
|
|
||||||
const editor = this._editor;
|
|
||||||
if (editor) {
|
|
||||||
editor.setValue(this._options!);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _handleAction(ev: CustomEvent<ActionDetail>) {
|
|
||||||
switch (ev.detail.index) {
|
|
||||||
case 0:
|
|
||||||
this._yamlMode = !this._yamlMode;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
this._resetTapped(ev);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _toggleOptional() {
|
|
||||||
this._showOptional = !this._showOptional;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _configChanged(ev): void {
|
private _configChanged(ev): void {
|
||||||
if (this.addon.schema && this._canShowSchema && !this._yamlMode) {
|
|
||||||
this._valid = true;
|
|
||||||
this._configHasChanged = true;
|
|
||||||
this._options! = ev.detail.value;
|
|
||||||
} else {
|
|
||||||
this._configHasChanged = true;
|
this._configHasChanged = true;
|
||||||
this._valid = ev.detail.isValid;
|
this._valid = ev.detail.isValid;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async _resetTapped(ev: CustomEvent): Promise<void> {
|
private async _resetTapped(ev: CustomEvent): Promise<void> {
|
||||||
const button = ev.currentTarget as any;
|
const button = ev.currentTarget as any;
|
||||||
button.progress = true;
|
button.progress = true;
|
||||||
|
|
||||||
const confirmed = await showConfirmationDialog(this, {
|
const confirmed = await showConfirmationDialog(this, {
|
||||||
title: this.supervisor.localize("confirm.reset_options.title"),
|
title: this.addon.name,
|
||||||
text: this.supervisor.localize("confirm.reset_options.text"),
|
text: "Are you sure you want to reset all your options?",
|
||||||
confirmText: this.supervisor.localize("common.reset_options"),
|
confirmText: "reset options",
|
||||||
dismissText: this.supervisor.localize("common.cancel"),
|
dismissText: "no",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
@@ -255,11 +111,9 @@ class HassioAddonConfig extends LitElement {
|
|||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to reset addon configuration, ${extractApiErrorMessage(
|
||||||
"addon.common.update_available",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
button.progress = false;
|
button.progress = false;
|
||||||
}
|
}
|
||||||
@@ -268,13 +122,18 @@ class HassioAddonConfig extends LitElement {
|
|||||||
const button = ev.currentTarget as any;
|
const button = ev.currentTarget as any;
|
||||||
button.progress = true;
|
button.progress = true;
|
||||||
|
|
||||||
|
let data: HassioAddonSetOptionParams;
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await setHassioAddonOption(this.hass, this.addon.slug, {
|
data = {
|
||||||
options: this._yamlMode ? this._editor?.value : this._options,
|
options: this._editor.value,
|
||||||
});
|
};
|
||||||
|
} catch (err) {
|
||||||
|
this._error = err;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await setHassioAddonOption(this.hass, this.addon.slug, data);
|
||||||
this._configHasChanged = false;
|
this._configHasChanged = false;
|
||||||
const eventdata = {
|
const eventdata = {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -283,14 +142,12 @@ class HassioAddonConfig extends LitElement {
|
|||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
if (this.addon?.state === "started") {
|
if (this.addon?.state === "started") {
|
||||||
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
await suggestAddonRestart(this, this.hass, this.addon);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to save addon configuration, ${extractApiErrorMessage(
|
||||||
"addon.configuration.options.failed_to_save",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
button.progress = false;
|
button.progress = false;
|
||||||
}
|
}
|
||||||
@@ -321,36 +178,6 @@ class HassioAddonConfig extends LitElement {
|
|||||||
.syntaxerror {
|
.syntaxerror {
|
||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
}
|
}
|
||||||
.card-menu {
|
|
||||||
float: right;
|
|
||||||
z-index: 3;
|
|
||||||
--mdc-theme-text-primary-on-background: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
mwc-list-item[disabled] {
|
|
||||||
--mdc-theme-text-primary-on-background: var(--disabled-text-color);
|
|
||||||
}
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.header h2 {
|
|
||||||
color: var(--ha-card-header-color, --primary-text-color);
|
|
||||||
font-family: var(--ha-card-header-font-family, inherit);
|
|
||||||
font-size: var(--ha-card-header-font-size, 24px);
|
|
||||||
letter-spacing: -0.012em;
|
|
||||||
line-height: 48px;
|
|
||||||
padding: 12px 16px 16px;
|
|
||||||
display: block;
|
|
||||||
margin-block: 0px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
.card-actions.right {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-additional {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@ import {
|
|||||||
setHassioAddonOption,
|
setHassioAddonOption,
|
||||||
} from "../../../../src/data/hassio/addon";
|
} from "../../../../src/data/hassio/addon";
|
||||||
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import { haStyle } from "../../../../src/resources/styles";
|
import { haStyle } from "../../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
||||||
@@ -39,8 +38,6 @@ interface NetworkItemInput extends PaperInputElement {
|
|||||||
class HassioAddonNetwork extends LitElement {
|
class HassioAddonNetwork extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@internalProperty() private _error?: string;
|
||||||
@@ -58,30 +55,16 @@ class HassioAddonNetwork extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-card
|
<ha-card header="Network">
|
||||||
.header=${this.supervisor.localize(
|
|
||||||
"addon.configuration.network.header"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>Container</th>
|
||||||
${this.supervisor.localize(
|
<th>Host</th>
|
||||||
"addon.configuration.network.container"
|
<th>Description</th>
|
||||||
)}
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
${this.supervisor.localize(
|
|
||||||
"addon.configuration.network.host"
|
|
||||||
)}
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
${this.supervisor.localize("common.description")}
|
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
${this._config!.map((item) => {
|
${this._config!.map((item) => {
|
||||||
return html`
|
return html`
|
||||||
@@ -90,15 +73,13 @@ class HassioAddonNetwork extends LitElement {
|
|||||||
<td>
|
<td>
|
||||||
<paper-input
|
<paper-input
|
||||||
@value-changed=${this._configChanged}
|
@value-changed=${this._configChanged}
|
||||||
placeholder="${this.supervisor.localize(
|
placeholder="disabled"
|
||||||
"addon.configuration.network.disabled"
|
|
||||||
)}"
|
|
||||||
.value=${item.host ? String(item.host) : ""}
|
.value=${item.host ? String(item.host) : ""}
|
||||||
.container=${item.container}
|
.container=${item.container}
|
||||||
no-label-float
|
no-label-float
|
||||||
></paper-input>
|
></paper-input>
|
||||||
</td>
|
</td>
|
||||||
<td>${this._computeDescription(item)}</td>
|
<td>${item.description}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
})}
|
})}
|
||||||
@@ -107,10 +88,10 @@ class HassioAddonNetwork extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<ha-progress-button class="warning" @click=${this._resetTapped}>
|
<ha-progress-button class="warning" @click=${this._resetTapped}>
|
||||||
${this.supervisor.localize("common.reset_defaults")}
|
Reset to defaults
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
<ha-progress-button @click=${this._saveTapped}>
|
<ha-progress-button @click=${this._saveTapped}>
|
||||||
${this.supervisor.localize("common.save")}
|
Save
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
@@ -124,15 +105,6 @@ class HassioAddonNetwork extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeDescription = (item: NetworkItem): string => {
|
|
||||||
return (
|
|
||||||
this.addon.translations[this.hass.language]?.network?.[item.container]
|
|
||||||
?.description ||
|
|
||||||
this.addon.translations.en?.network?.[item.container]?.description ||
|
|
||||||
item.description
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
private _setNetworkConfig(): void {
|
private _setNetworkConfig(): void {
|
||||||
const network = this.addon.network || {};
|
const network = this.addon.network || {};
|
||||||
const description = this.addon.network_description || {};
|
const description = this.addon.network_description || {};
|
||||||
@@ -175,14 +147,12 @@ class HassioAddonNetwork extends LitElement {
|
|||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
if (this.addon?.state === "started") {
|
if (this.addon?.state === "started") {
|
||||||
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
await suggestAddonRestart(this, this.hass, this.addon);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to set addon network configuration, ${extractApiErrorMessage(
|
||||||
"addon.failed_to_reset",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button.progress = false;
|
button.progress = false;
|
||||||
@@ -211,14 +181,12 @@ class HassioAddonNetwork extends LitElement {
|
|||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
if (this.addon?.state === "started") {
|
if (this.addon?.state === "started") {
|
||||||
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
await suggestAddonRestart(this, this.hass, this.addon);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to set addon network configuration, ${extractApiErrorMessage(
|
||||||
"addon.failed_to_save",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
button.progress = false;
|
button.progress = false;
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import "../../../../src/components/ha-card";
|
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
@@ -20,14 +19,11 @@ import "../../../../src/layouts/hass-loading-screen";
|
|||||||
import { haStyle } from "../../../../src/resources/styles";
|
import { haStyle } from "../../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import { hassioStyle } from "../../resources/hassio-style";
|
import { hassioStyle } from "../../resources/hassio-style";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
|
|
||||||
@customElement("hassio-addon-documentation-tab")
|
@customElement("hassio-addon-documentation-tab")
|
||||||
class HassioAddonDocumentationDashboard extends LitElement {
|
class HassioAddonDocumentationDashboard extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@internalProperty() private _error?: string;
|
||||||
@@ -85,11 +81,9 @@ class HassioAddonDocumentationDashboard extends LitElement {
|
|||||||
this.addon!.slug
|
this.addon!.slug
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to get addon documentation, ${extractApiErrorMessage(
|
||||||
"addon.documentation.get_logs",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,25 +9,17 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
|
||||||
import { navigate } from "../../../src/common/navigate";
|
|
||||||
import { extractSearchParam } from "../../../src/common/url/search-params";
|
|
||||||
import "../../../src/components/ha-circular-progress";
|
|
||||||
import {
|
import {
|
||||||
fetchHassioAddonInfo,
|
fetchHassioAddonInfo,
|
||||||
HassioAddonDetails,
|
HassioAddonDetails,
|
||||||
} from "../../../src/data/hassio/addon";
|
} from "../../../src/data/hassio/addon";
|
||||||
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
|
||||||
import "../../../src/layouts/hass-error-screen";
|
|
||||||
import "../../../src/layouts/hass-loading-screen";
|
|
||||||
import "../../../src/layouts/hass-tabs-subpage";
|
import "../../../src/layouts/hass-tabs-subpage";
|
||||||
|
import "../../../src/components/ha-circular-progress";
|
||||||
import type { PageNavigation } from "../../../src/layouts/hass-tabs-subpage";
|
import type { PageNavigation } from "../../../src/layouts/hass-tabs-subpage";
|
||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
import { HomeAssistant, Route } from "../../../src/types";
|
import { HomeAssistant, Route } from "../../../src/types";
|
||||||
@@ -43,16 +35,12 @@ import "./log/hassio-addon-logs";
|
|||||||
class HassioAddonDashboard extends LitElement {
|
class HassioAddonDashboard extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
|
|
||||||
@internalProperty() _error?: string;
|
|
||||||
|
|
||||||
private _computeTail = memoizeOne((route: Route) => {
|
private _computeTail = memoizeOne((route: Route) => {
|
||||||
const dividerPos = route.path.indexOf("/", 1);
|
const dividerPos = route.path.indexOf("/", 1);
|
||||||
return dividerPos === -1
|
return dividerPos === -1
|
||||||
@@ -67,19 +55,13 @@ class HassioAddonDashboard extends LitElement {
|
|||||||
});
|
});
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (this._error) {
|
|
||||||
return html`<hass-error-screen
|
|
||||||
.error=${this._error}
|
|
||||||
></hass-error-screen>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.addon) {
|
if (!this.addon) {
|
||||||
return html`<hass-loading-screen></hass-loading-screen>`;
|
return html`<ha-circular-progress active></ha-circular-progress>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const addonTabs: PageNavigation[] = [
|
const addonTabs: PageNavigation[] = [
|
||||||
{
|
{
|
||||||
translationKey: "addon.panel.info",
|
name: "Info",
|
||||||
path: `/hassio/addon/${this.addon.slug}/info`,
|
path: `/hassio/addon/${this.addon.slug}/info`,
|
||||||
iconPath: mdiInformationVariant,
|
iconPath: mdiInformationVariant,
|
||||||
},
|
},
|
||||||
@@ -87,7 +69,7 @@ class HassioAddonDashboard extends LitElement {
|
|||||||
|
|
||||||
if (this.addon.documentation) {
|
if (this.addon.documentation) {
|
||||||
addonTabs.push({
|
addonTabs.push({
|
||||||
translationKey: "addon.panel.documentation",
|
name: "Documentation",
|
||||||
path: `/hassio/addon/${this.addon.slug}/documentation`,
|
path: `/hassio/addon/${this.addon.slug}/documentation`,
|
||||||
iconPath: mdiFileDocument,
|
iconPath: mdiFileDocument,
|
||||||
});
|
});
|
||||||
@@ -96,12 +78,12 @@ class HassioAddonDashboard extends LitElement {
|
|||||||
if (this.addon.version) {
|
if (this.addon.version) {
|
||||||
addonTabs.push(
|
addonTabs.push(
|
||||||
{
|
{
|
||||||
translationKey: "addon.panel.configuration",
|
name: "Configuration",
|
||||||
path: `/hassio/addon/${this.addon.slug}/config`,
|
path: `/hassio/addon/${this.addon.slug}/config`,
|
||||||
iconPath: mdiCogs,
|
iconPath: mdiCogs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
translationKey: "addon.panel.log",
|
name: "Log",
|
||||||
path: `/hassio/addon/${this.addon.slug}/logs`,
|
path: `/hassio/addon/${this.addon.slug}/logs`,
|
||||||
iconPath: mdiMathLog,
|
iconPath: mdiMathLog,
|
||||||
}
|
}
|
||||||
@@ -113,19 +95,17 @@ class HassioAddonDashboard extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<hass-tabs-subpage
|
<hass-tabs-subpage
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.localizeFunc=${this.supervisor.localize}
|
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
.backPath=${this.addon.version ? "/hassio/dashboard" : "/hassio/store"}
|
.backPath=${this.addon.version ? "/hassio/dashboard" : "/hassio/store"}
|
||||||
.route=${route}
|
.route=${route}
|
||||||
|
hassio
|
||||||
.tabs=${addonTabs}
|
.tabs=${addonTabs}
|
||||||
supervisor
|
|
||||||
>
|
>
|
||||||
<span slot="header">${this.addon.name}</span>
|
<span slot="header">${this.addon.name}</span>
|
||||||
<hassio-addon-router
|
<hassio-addon-router
|
||||||
.route=${route}
|
.route=${route}
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.supervisor=${this.supervisor}
|
|
||||||
.addon=${this.addon}
|
.addon=${this.addon}
|
||||||
></hassio-addon-router>
|
></hassio-addon-router>
|
||||||
</hass-tabs-subpage>
|
</hass-tabs-subpage>
|
||||||
@@ -172,53 +152,30 @@ class HassioAddonDashboard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async firstUpdated(): Promise<void> {
|
protected async firstUpdated(): Promise<void> {
|
||||||
if (this.route.path === "") {
|
await this._routeDataChanged(this.route);
|
||||||
const addon = extractSearchParam("addon");
|
|
||||||
if (addon) {
|
|
||||||
navigate(this, `/hassio/addon/${addon}`, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.addEventListener("hass-api-called", (ev) => this._apiCalled(ev));
|
this.addEventListener("hass-api-called", (ev) => this._apiCalled(ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _apiCalled(ev): Promise<void> {
|
private async _apiCalled(ev): Promise<void> {
|
||||||
const pathSplit: string[] = ev.detail.path?.split("/");
|
const path: string = ev.detail.path;
|
||||||
|
|
||||||
if (!pathSplit || pathSplit.length === 0) {
|
if (!path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const path: string = pathSplit[pathSplit.length - 1];
|
|
||||||
|
|
||||||
if (["uninstall", "install", "update", "start", "stop"].includes(path)) {
|
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
|
||||||
colllection: "supervisor",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path === "uninstall") {
|
if (path === "uninstall") {
|
||||||
window.history.back();
|
history.back();
|
||||||
} else {
|
} else {
|
||||||
await this._routeDataChanged();
|
await this._routeDataChanged(this.route);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProperties) {
|
private async _routeDataChanged(routeData: Route): Promise<void> {
|
||||||
if (changedProperties.has("route") && !this.addon) {
|
const addon = routeData.path.split("/")[1];
|
||||||
this._routeDataChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _routeDataChanged(): Promise<void> {
|
|
||||||
const addon = this.route.path.split("/")[1];
|
|
||||||
if (!addon) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const addoninfo = await fetchHassioAddonInfo(this.hass, addon);
|
const addoninfo = await fetchHassioAddonInfo(this.hass, addon);
|
||||||
this.addon = addoninfo;
|
this.addon = addoninfo;
|
||||||
} catch (err) {
|
} catch {
|
||||||
this._error = `Error fetching addon info: ${extractApiErrorMessage(err)}`;
|
|
||||||
this.addon = undefined;
|
this.addon = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { customElement, property } from "lit-element";
|
import { customElement, property } from "lit-element";
|
||||||
import { HassioAddonDetails } from "../../../src/data/hassio/addon";
|
import { HassioAddonDetails } from "../../../src/data/hassio/addon";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
|
||||||
import {
|
import {
|
||||||
HassRouterPage,
|
HassRouterPage,
|
||||||
RouterOptions,
|
RouterOptions,
|
||||||
@@ -18,8 +17,6 @@ class HassioAddonRouter extends HassRouterPage {
|
|||||||
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||||
|
|
||||||
protected routerOptions: RouterOptions = {
|
protected routerOptions: RouterOptions = {
|
||||||
@@ -44,7 +41,6 @@ class HassioAddonRouter extends HassRouterPage {
|
|||||||
protected updatePageEl(el) {
|
protected updatePageEl(el) {
|
||||||
el.route = this.routeTail;
|
el.route = this.routeTail;
|
||||||
el.hass = this.hass;
|
el.hass = this.hass;
|
||||||
el.supervisor = this.supervisor;
|
|
||||||
el.addon = this.addon;
|
el.addon = this.addon;
|
||||||
el.narrow = this.narrow;
|
el.narrow = this.narrow;
|
||||||
}
|
}
|
||||||
|
@@ -7,9 +7,8 @@ import {
|
|||||||
property,
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "../../../../src/components/ha-circular-progress";
|
|
||||||
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
import "../../../../src/components/ha-circular-progress";
|
||||||
import { haStyle } from "../../../../src/resources/styles";
|
import { haStyle } from "../../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import { hassioStyle } from "../../resources/hassio-style";
|
import { hassioStyle } from "../../resources/hassio-style";
|
||||||
@@ -21,8 +20,6 @@ class HassioAddonInfoDashboard extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
@@ -35,7 +32,6 @@ class HassioAddonInfoDashboard extends LitElement {
|
|||||||
<hassio-addon-info
|
<hassio-addon-info
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.supervisor=${this.supervisor}
|
|
||||||
.addon=${this.addon}
|
.addon=${this.addon}
|
||||||
></hassio-addon-info>
|
></hassio-addon-info>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -25,7 +25,6 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { atLeastVersion } from "../../../../src/common/config/version";
|
import { atLeastVersion } from "../../../../src/common/config/version";
|
||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import { navigate } from "../../../../src/common/navigate";
|
import { navigate } from "../../../../src/common/navigate";
|
||||||
@@ -44,35 +43,22 @@ import {
|
|||||||
HassioAddonSetOptionParams,
|
HassioAddonSetOptionParams,
|
||||||
HassioAddonSetSecurityParams,
|
HassioAddonSetSecurityParams,
|
||||||
installHassioAddon,
|
installHassioAddon,
|
||||||
restartHassioAddon,
|
|
||||||
setHassioAddonOption,
|
setHassioAddonOption,
|
||||||
setHassioAddonSecurity,
|
setHassioAddonSecurity,
|
||||||
startHassioAddon,
|
startHassioAddon,
|
||||||
stopHassioAddon,
|
|
||||||
uninstallHassioAddon,
|
uninstallHassioAddon,
|
||||||
updateHassioAddon,
|
|
||||||
validateHassioAddonOption,
|
validateHassioAddonOption,
|
||||||
} from "../../../../src/data/hassio/addon";
|
} from "../../../../src/data/hassio/addon";
|
||||||
import {
|
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
||||||
extractApiErrorMessage,
|
|
||||||
fetchHassioStats,
|
|
||||||
HassioStats,
|
|
||||||
} from "../../../../src/data/hassio/common";
|
|
||||||
import { StoreAddon } from "../../../../src/data/supervisor/store";
|
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import {
|
import {
|
||||||
showAlertDialog,
|
showAlertDialog,
|
||||||
showConfirmationDialog,
|
showConfirmationDialog,
|
||||||
} from "../../../../src/dialogs/generic/show-dialog-box";
|
} from "../../../../src/dialogs/generic/show-dialog-box";
|
||||||
import { haStyle } from "../../../../src/resources/styles";
|
import { haStyle } from "../../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import { bytesToString } from "../../../../src/util/bytes-to-string";
|
|
||||||
import "../../components/hassio-card-content";
|
import "../../components/hassio-card-content";
|
||||||
import "../../components/supervisor-metric";
|
|
||||||
import { showHassioMarkdownDialog } from "../../dialogs/markdown/show-dialog-hassio-markdown";
|
import { showHassioMarkdownDialog } from "../../dialogs/markdown/show-dialog-hassio-markdown";
|
||||||
import { showDialogSupervisorUpdate } from "../../dialogs/update/show-dialog-update";
|
|
||||||
import { hassioStyle } from "../../resources/hassio-style";
|
import { hassioStyle } from "../../resources/hassio-style";
|
||||||
import { addonArchIsSupported } from "../../util/addon";
|
|
||||||
|
|
||||||
const STAGE_ICON = {
|
const STAGE_ICON = {
|
||||||
stable: mdiCheckCircle,
|
stable: mdiCheckCircle,
|
||||||
@@ -80,6 +66,63 @@ const STAGE_ICON = {
|
|||||||
deprecated: mdiExclamationThick,
|
deprecated: mdiExclamationThick,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const PERMIS_DESC = {
|
||||||
|
stage: {
|
||||||
|
title: "Add-on Stage",
|
||||||
|
description: `Add-ons can have one of three stages:\n\n<ha-svg-icon path="${STAGE_ICON.stable}"></ha-svg-icon> **Stable**: These are add-ons ready to be used in production.\n\n<ha-svg-icon path="${STAGE_ICON.experimental}"></ha-svg-icon> **Experimental**: These may contain bugs, and may be unfinished.\n\n<ha-svg-icon path="${STAGE_ICON.deprecated}"></ha-svg-icon> **Deprecated**: These add-ons will no longer receive any updates.`,
|
||||||
|
},
|
||||||
|
rating: {
|
||||||
|
title: "Add-on Security Rating",
|
||||||
|
description:
|
||||||
|
"Home Assistant provides a security rating to each of the add-ons, which indicates the risks involved when using this add-on. The more access an add-on requires on your system, the lower the score, thus raising the possible security risks.\n\nA score is on a scale from 1 to 6. Where 1 is the lowest score (considered the most insecure and highest risk) and a score of 6 is the highest score (considered the most secure and lowest risk).",
|
||||||
|
},
|
||||||
|
host_network: {
|
||||||
|
title: "Host Network",
|
||||||
|
description:
|
||||||
|
"Add-ons usually run in their own isolated network layer, which prevents them from accessing the network of the host operating system. In some cases, this network isolation can limit add-ons in providing their services and therefore, the isolation can be lifted by the add-on author, giving the add-on full access to the network capabilities of the host machine. This gives the add-on more networking capabilities but lowers the security, hence, the security rating of the add-on will be lowered when this option is used by the add-on.",
|
||||||
|
},
|
||||||
|
homeassistant_api: {
|
||||||
|
title: "Home Assistant API Access",
|
||||||
|
description:
|
||||||
|
"This add-on is allowed to access your running Home Assistant instance directly via the Home Assistant API. This mode handles authentication for the add-on as well, which enables an add-on to interact with Home Assistant without the need for additional authentication tokens.",
|
||||||
|
},
|
||||||
|
full_access: {
|
||||||
|
title: "Full Hardware Access",
|
||||||
|
description:
|
||||||
|
"This add-on is given full access to the hardware of your system, by request of the add-on author. Access is comparable to the privileged mode in Docker. Since this opens up possible security risks, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on.",
|
||||||
|
},
|
||||||
|
hassio_api: {
|
||||||
|
title: "Supervisor API Access",
|
||||||
|
description:
|
||||||
|
"The add-on was given access to the Supervisor API, by request of the add-on author. By default, the add-on can access general version information of your system. When the add-on requests 'manager' or 'admin' level access to the API, it will gain access to control multiple parts of your Home Assistant system. This permission is indicated by this badge and will impact the security score of the addon negatively.",
|
||||||
|
},
|
||||||
|
docker_api: {
|
||||||
|
title: "Full Docker Access",
|
||||||
|
description:
|
||||||
|
"The add-on author has requested the add-on to have management access to the Docker instance running on your system. This mode gives the add-on full access and control to your entire Home Assistant system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on.",
|
||||||
|
},
|
||||||
|
host_pid: {
|
||||||
|
title: "Host Processes Namespace",
|
||||||
|
description:
|
||||||
|
"Usually, the processes the add-on runs, are isolated from all other system processes. The add-on author has requested the add-on to have access to the system processes running on the host system instance, and allow the add-on to spawn processes on the host system as well. This mode gives the add-on full access and control to your entire Home Assistant system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on.",
|
||||||
|
},
|
||||||
|
apparmor: {
|
||||||
|
title: "AppArmor",
|
||||||
|
description:
|
||||||
|
"AppArmor ('Application Armor') is a Linux kernel security module that restricts add-ons capabilities like network access, raw socket access, and permission to read, write, or execute specific files.\n\nAdd-on authors can provide their security profiles, optimized for the add-on, or request it to be disabled. If AppArmor is disabled, it will raise security risks and therefore, has a negative impact on the security score of the add-on.",
|
||||||
|
},
|
||||||
|
auth_api: {
|
||||||
|
title: "Home Assistant Authentication",
|
||||||
|
description:
|
||||||
|
"An add-on can authenticate users against Home Assistant, allowing add-ons to give users the possibility to log into applications running inside add-ons, using their Home Assistant username/password. This badge indicates if the add-on author requests this capability.",
|
||||||
|
},
|
||||||
|
ingress: {
|
||||||
|
title: "Ingress",
|
||||||
|
description:
|
||||||
|
"This add-on is using Ingress to embed its interface securely into Home Assistant.",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
@customElement("hassio-addon-info")
|
@customElement("hassio-addon-info")
|
||||||
class HassioAddonInfo extends LitElement {
|
class HassioAddonInfo extends LitElement {
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
@@ -88,96 +131,43 @@ class HassioAddonInfo extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@internalProperty() private _metrics?: HassioStats;
|
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@internalProperty() private _error?: string;
|
||||||
|
|
||||||
private _addonStoreInfo = memoizeOne(
|
|
||||||
(slug: string, storeAddons: StoreAddon[]) =>
|
|
||||||
storeAddons.find((addon) => addon.slug === slug)
|
|
||||||
);
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const addonStoreInfo =
|
|
||||||
!this.addon.detached && !this.addon.available
|
|
||||||
? this._addonStoreInfo(this.addon.slug, this.supervisor.store.addons)
|
|
||||||
: undefined;
|
|
||||||
const metrics = [
|
|
||||||
{
|
|
||||||
description: this.supervisor.localize("addon.dashboard.cpu_usage"),
|
|
||||||
value: this._metrics?.cpu_percent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: this.supervisor.localize("addon.dashboard.ram_usage"),
|
|
||||||
value: this._metrics?.memory_percent,
|
|
||||||
tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString(
|
|
||||||
this._metrics?.memory_limit
|
|
||||||
)}`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return html`
|
return html`
|
||||||
${this.addon.update_available
|
${this.addon.update_available
|
||||||
? html`
|
? html`
|
||||||
<ha-card
|
<ha-card header="Update available! 🎉">
|
||||||
.header="${this.supervisor.localize(
|
|
||||||
"common.update_available",
|
|
||||||
"count",
|
|
||||||
1
|
|
||||||
)}🎉"
|
|
||||||
>
|
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<hassio-card-content
|
<hassio-card-content
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.title="${this.supervisor.localize(
|
.title="${this.addon.name} ${this.addon
|
||||||
"addon.dashboard.new_update_available",
|
.version_latest} is available"
|
||||||
"name",
|
.description="You are currently running version ${this.addon
|
||||||
this.addon.name,
|
.version}"
|
||||||
"version",
|
|
||||||
this.addon.version_latest
|
|
||||||
)}"
|
|
||||||
.description="${this.supervisor.localize(
|
|
||||||
"common.running_version",
|
|
||||||
"version",
|
|
||||||
this.addon.version
|
|
||||||
)}"
|
|
||||||
icon=${mdiArrowUpBoldCircle}
|
icon=${mdiArrowUpBoldCircle}
|
||||||
iconClass="update"
|
iconClass="update"
|
||||||
></hassio-card-content>
|
></hassio-card-content>
|
||||||
${!this.addon.available && addonStoreInfo
|
${!this.addon.available
|
||||||
? !addonArchIsSupported(
|
|
||||||
this.supervisor.info.supported_arch,
|
|
||||||
this.addon.arch
|
|
||||||
)
|
|
||||||
? html`
|
? html`
|
||||||
<p class="warning">
|
<p>
|
||||||
${this.supervisor.localize(
|
This update is no longer compatible with your system.
|
||||||
"addon.dashboard.not_available_arch"
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
`
|
|
||||||
: html`
|
|
||||||
<p class="warning">
|
|
||||||
${this.supervisor.localize(
|
|
||||||
"addon.dashboard.not_available_arch",
|
|
||||||
"core_version_installed",
|
|
||||||
this.supervisor.core.version,
|
|
||||||
"core_version_needed",
|
|
||||||
addonStoreInfo.homeassistant
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<mwc-button @click=${this._updateClicked}>
|
<ha-call-api-button
|
||||||
${this.supervisor.localize("common.update")}
|
.hass=${this.hass}
|
||||||
</mwc-button>
|
.disabled=${!this.addon.available}
|
||||||
|
path="hassio/addons/${this.addon.slug}/update"
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ha-call-api-button>
|
||||||
${this.addon.changelog
|
${this.addon.changelog
|
||||||
? html`
|
? html`
|
||||||
<mwc-button @click=${this._openChangelog}>
|
<mwc-button @click=${this._openChangelog}>
|
||||||
${this.supervisor.localize("addon.dashboard.changelog")}
|
Changelog
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -188,19 +178,12 @@ class HassioAddonInfo extends LitElement {
|
|||||||
${!this.addon.protected
|
${!this.addon.protected
|
||||||
? html`
|
? html`
|
||||||
<ha-card class="warning">
|
<ha-card class="warning">
|
||||||
<h1 class="card-header">${this.supervisor.localize(
|
<h1 class="card-header">Warning: Protection mode is disabled!</h1>
|
||||||
"addon.dashboard.protection_mode.title"
|
|
||||||
)}
|
|
||||||
</h1>
|
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
${this.supervisor.localize("addon.dashboard.protection_mode.content")}
|
Protection mode on this add-on is disabled! This gives the add-on full access to the entire system, which adds security risks, and could damage your system when used incorrectly. Only disable the protection mode if you know, need AND trust the source of this add-on.
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions protection-enable">
|
<div class="card-actions protection-enable">
|
||||||
<mwc-button @click=${this._protectionToggled}>
|
<mwc-button @click=${this._protectionToggled}>Enable Protection mode</mwc-button>
|
||||||
${this.supervisor.localize(
|
|
||||||
"addon.dashboard.protection_mode.enable"
|
|
||||||
)}
|
|
||||||
</mwc-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
@@ -217,18 +200,14 @@ class HassioAddonInfo extends LitElement {
|
|||||||
${this._computeIsRunning
|
${this._computeIsRunning
|
||||||
? html`
|
? html`
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
.title=${this.supervisor.localize(
|
title="Add-on is running"
|
||||||
"dashboard.addon_running"
|
|
||||||
)}
|
|
||||||
class="running"
|
class="running"
|
||||||
.path=${mdiCircle}
|
.path=${mdiCircle}
|
||||||
></ha-svg-icon>
|
></ha-svg-icon>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
.title=${this.supervisor.localize(
|
title="Add-on is stopped"
|
||||||
"dashboard.addon_stopped"
|
|
||||||
)}
|
|
||||||
class="stopped"
|
class="stopped"
|
||||||
.path=${mdiCircle}
|
.path=${mdiCircle}
|
||||||
></ha-svg-icon>
|
></ha-svg-icon>
|
||||||
@@ -242,32 +221,22 @@ class HassioAddonInfo extends LitElement {
|
|||||||
? html`
|
? html`
|
||||||
Current version: ${this.addon.version}
|
Current version: ${this.addon.version}
|
||||||
<div class="changelog" @click=${this._openChangelog}>
|
<div class="changelog" @click=${this._openChangelog}>
|
||||||
(<span class="changelog-link">
|
(<span class="changelog-link">changelog</span>)
|
||||||
${this.supervisor.localize("addon.dashboard.changelog")} </span
|
|
||||||
>)
|
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: html`<span class="changelog-link" @click=${this._openChangelog}>
|
: html`<span class="changelog-link" @click=${this._openChangelog}
|
||||||
${this.supervisor.localize("addon.dashboard.changelog")}
|
>Changelog</span
|
||||||
</span>`}
|
>`}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="description light-color">
|
<div class="description light-color">
|
||||||
${this.addon.description}.<br />
|
${this.addon.description}.<br />
|
||||||
${this.supervisor.localize(
|
Visit
|
||||||
"addon.dashboard.visit_addon_page",
|
<a href="${this.addon.url!}" target="_blank" rel="noreferrer">
|
||||||
"name",
|
${this.addon.name} page</a
|
||||||
html`<a
|
|
||||||
href="${this.addon.url!}"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
>
|
||||||
${this.addon.name}
|
for details.
|
||||||
</a>`
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="addon-container">
|
|
||||||
<div>
|
|
||||||
${this.addon.logo
|
${this.addon.logo
|
||||||
? html`
|
? html`
|
||||||
<img
|
<img
|
||||||
@@ -285,9 +254,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
})}
|
})}
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="stage"
|
id="stage"
|
||||||
.label=${this.supervisor.localize(
|
label="stage"
|
||||||
"addon.dashboard.capability.label.stage"
|
|
||||||
)}
|
|
||||||
description=""
|
description=""
|
||||||
>
|
>
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
@@ -313,9 +280,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="host_network"
|
id="host_network"
|
||||||
.label=${this.supervisor.localize(
|
label="host"
|
||||||
"addon.dashboard.capability.label.host"
|
|
||||||
)}
|
|
||||||
description=""
|
description=""
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${mdiNetwork}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiNetwork}></ha-svg-icon>
|
||||||
@@ -327,9 +292,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="full_access"
|
id="full_access"
|
||||||
.label=${this.supervisor.localize(
|
label="hardware"
|
||||||
"addon.dashboard.capability.label.hardware"
|
|
||||||
)}
|
|
||||||
description=""
|
description=""
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${mdiChip}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiChip}></ha-svg-icon>
|
||||||
@@ -341,9 +304,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="homeassistant_api"
|
id="homeassistant_api"
|
||||||
.label=${this.supervisor.localize(
|
label="hass"
|
||||||
"addon.dashboard.capability.label.hass"
|
|
||||||
)}
|
|
||||||
description=""
|
description=""
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${mdiHomeAssistant}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiHomeAssistant}></ha-svg-icon>
|
||||||
@@ -355,12 +316,8 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="hassio_api"
|
id="hassio_api"
|
||||||
.label=${this.supervisor.localize(
|
label="hassio"
|
||||||
"addon.dashboard.capability.label.hassio"
|
.description=${this.addon.hassio_role}
|
||||||
)}
|
|
||||||
.description=${this.supervisor.localize(
|
|
||||||
`addon.dashboard.capability.role.${this.addon.hassio_role}`
|
|
||||||
) || this.addon.hassio_role}
|
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${mdiHomeAssistant}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiHomeAssistant}></ha-svg-icon>
|
||||||
</ha-label-badge>
|
</ha-label-badge>
|
||||||
@@ -371,9 +328,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="docker_api"
|
id="docker_api"
|
||||||
.label=".${this.supervisor.localize(
|
label="docker"
|
||||||
"addon.dashboard.capability.label.docker"
|
|
||||||
)}"
|
|
||||||
description=""
|
description=""
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${mdiDocker}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiDocker}></ha-svg-icon>
|
||||||
@@ -385,9 +340,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="host_pid"
|
id="host_pid"
|
||||||
.label=${this.supervisor.localize(
|
label="host pid"
|
||||||
"addon.dashboard.capability.label.host_pid"
|
|
||||||
)}
|
|
||||||
description=""
|
description=""
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${mdiPound}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiPound}></ha-svg-icon>
|
||||||
@@ -400,9 +353,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
class=${this._computeApparmorClassName}
|
class=${this._computeApparmorClassName}
|
||||||
id="apparmor"
|
id="apparmor"
|
||||||
.label=${this.supervisor.localize(
|
label="apparmor"
|
||||||
"addon.dashboard.capability.label.apparmor"
|
|
||||||
)}
|
|
||||||
description=""
|
description=""
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${mdiShield}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiShield}></ha-svg-icon>
|
||||||
@@ -414,9 +365,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="auth_api"
|
id="auth_api"
|
||||||
.label=${this.supervisor.localize(
|
label="auth"
|
||||||
"addon.dashboard.capability.label.auth"
|
|
||||||
)}
|
|
||||||
description=""
|
description=""
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${mdiKey}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiKey}></ha-svg-icon>
|
||||||
@@ -428,9 +377,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="ingress"
|
id="ingress"
|
||||||
.label=${this.supervisor.localize(
|
label="ingress"
|
||||||
"addon.dashboard.capability.label.ingress"
|
|
||||||
)}
|
|
||||||
description=""
|
description=""
|
||||||
>
|
>
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
@@ -443,22 +390,13 @@ class HassioAddonInfo extends LitElement {
|
|||||||
|
|
||||||
${this.addon.version
|
${this.addon.version
|
||||||
? html`
|
? html`
|
||||||
<div
|
<div class="addon-options">
|
||||||
class="${classMap({
|
|
||||||
"addon-options": true,
|
|
||||||
started: this.addon.state === "started",
|
|
||||||
})}"
|
|
||||||
>
|
|
||||||
<ha-settings-row ?three-line=${this.narrow}>
|
<ha-settings-row ?three-line=${this.narrow}>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize(
|
Start on boot
|
||||||
"addon.dashboard.option.boot.title"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.localize(
|
Make the add-on start during a system boot
|
||||||
"addon.dashboard.option.boot.description"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<ha-switch
|
<ha-switch
|
||||||
@change=${this._startOnBootToggled}
|
@change=${this._startOnBootToggled}
|
||||||
@@ -471,14 +409,10 @@ class HassioAddonInfo extends LitElement {
|
|||||||
? html`
|
? html`
|
||||||
<ha-settings-row ?three-line=${this.narrow}>
|
<ha-settings-row ?three-line=${this.narrow}>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize(
|
Watchdog
|
||||||
"addon.dashboard.option.watchdog.title"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.localize(
|
This will start the add-on if it crashes
|
||||||
"addon.dashboard.option.boot.description"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<ha-switch
|
<ha-switch
|
||||||
@change=${this._watchdogToggled}
|
@change=${this._watchdogToggled}
|
||||||
@@ -488,19 +422,15 @@ class HassioAddonInfo extends LitElement {
|
|||||||
</ha-settings-row>
|
</ha-settings-row>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
${this.addon.auto_update ||
|
${this.addon.auto_update || this.hass.userData?.showAdvanced
|
||||||
this.hass.userData?.showAdvanced
|
|
||||||
? html`
|
? html`
|
||||||
<ha-settings-row ?three-line=${this.narrow}>
|
<ha-settings-row ?three-line=${this.narrow}>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize(
|
Auto update
|
||||||
"addon.dashboard.option.auto_update.title"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.localize(
|
Auto update the add-on when there is a new version
|
||||||
"addon.dashboard.option.boot.description"
|
available
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<ha-switch
|
<ha-switch
|
||||||
@change=${this._autoUpdateToggled}
|
@change=${this._autoUpdateToggled}
|
||||||
@@ -510,22 +440,21 @@ class HassioAddonInfo extends LitElement {
|
|||||||
</ha-settings-row>
|
</ha-settings-row>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
${!this._computeCannotIngressSidebar && this.addon.ingress
|
${this.addon.ingress
|
||||||
? html`
|
? html`
|
||||||
<ha-settings-row ?three-line=${this.narrow}>
|
<ha-settings-row ?three-line=${this.narrow}>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize(
|
Show in sidebar
|
||||||
"addon.dashboard.option.ingress_panel.title"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.localize(
|
${this._computeCannotIngressSidebar
|
||||||
"addon.dashboard.option.ingress_panel.description"
|
? "This option requires Home Assistant 0.92 or later."
|
||||||
)}
|
: "Add this add-on to your sidebar"}
|
||||||
</span>
|
</span>
|
||||||
<ha-switch
|
<ha-switch
|
||||||
@change=${this._panelToggled}
|
@change=${this._panelToggled}
|
||||||
.checked=${this.addon.ingress_panel}
|
.checked=${this.addon.ingress_panel}
|
||||||
|
.disabled=${this._computeCannotIngressSidebar}
|
||||||
haptic
|
haptic
|
||||||
></ha-switch>
|
></ha-switch>
|
||||||
</ha-settings-row>
|
</ha-settings-row>
|
||||||
@@ -535,14 +464,10 @@ class HassioAddonInfo extends LitElement {
|
|||||||
? html`
|
? html`
|
||||||
<ha-settings-row ?three-line=${this.narrow}>
|
<ha-settings-row ?three-line=${this.narrow}>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize(
|
Protection mode
|
||||||
"addon.dashboard.option.protected.title"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.localize(
|
Blocks elevated system access from the add-on
|
||||||
"addon.dashboard.option.protected.description"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<ha-switch
|
<ha-switch
|
||||||
@change=${this._protectionToggled}
|
@change=${this._protectionToggled}
|
||||||
@@ -555,134 +480,88 @@ class HassioAddonInfo extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
${this.addon.state === "started"
|
|
||||||
? html`<ha-settings-row ?three-line=${this.narrow}>
|
|
||||||
<span slot="heading">
|
|
||||||
${this.supervisor.localize("addon.dashboard.hostname")}
|
|
||||||
</span>
|
|
||||||
<code slot="description">
|
|
||||||
${this.addon.hostname}
|
|
||||||
</code>
|
|
||||||
</ha-settings-row>
|
|
||||||
${metrics.map(
|
|
||||||
(metric) =>
|
|
||||||
html`
|
|
||||||
<supervisor-metric
|
|
||||||
.description=${metric.description}
|
|
||||||
.value=${metric.value ?? 0}
|
|
||||||
.tooltip=${metric.tooltip}
|
|
||||||
></supervisor-metric>
|
|
||||||
`
|
|
||||||
)}`
|
|
||||||
: ""}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
||||||
${!this.addon.version && addonStoreInfo && !this.addon.available
|
|
||||||
? !addonArchIsSupported(
|
|
||||||
this.supervisor.info.supported_arch,
|
|
||||||
this.addon.arch
|
|
||||||
)
|
|
||||||
? html`
|
|
||||||
<p class="warning">
|
|
||||||
${this.supervisor.localize(
|
|
||||||
"addon.dashboard.not_available_arch"
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
`
|
|
||||||
: html`
|
|
||||||
<p class="warning">
|
|
||||||
${this.supervisor.localize(
|
|
||||||
"addon.dashboard.not_available_version",
|
|
||||||
"core_version_installed",
|
|
||||||
this.supervisor.core.version,
|
|
||||||
"core_version_needed",
|
|
||||||
addonStoreInfo!.homeassistant
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<div>
|
|
||||||
${this.addon.version
|
${this.addon.version
|
||||||
? this._computeIsRunning
|
|
||||||
? html`
|
? html`
|
||||||
<ha-progress-button
|
${this._computeIsRunning
|
||||||
|
? html`
|
||||||
|
<ha-call-api-button
|
||||||
class="warning"
|
class="warning"
|
||||||
@click=${this._stopClicked}
|
.hass=${this.hass}
|
||||||
|
.path="hassio/addons/${this.addon.slug}/stop"
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("addon.dashboard.stop")}
|
Stop
|
||||||
</ha-progress-button>
|
</ha-call-api-button>
|
||||||
<ha-progress-button
|
<ha-call-api-button
|
||||||
class="warning"
|
class="warning"
|
||||||
@click=${this._restartClicked}
|
.hass=${this.hass}
|
||||||
|
.path="hassio/addons/${this.addon.slug}/restart"
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("addon.dashboard.restart")}
|
Restart
|
||||||
</ha-progress-button>
|
</ha-call-api-button>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<ha-progress-button @click=${this._startClicked}>
|
<ha-progress-button @click=${this._startClicked}>
|
||||||
${this.supervisor.localize("addon.dashboard.start")}
|
Start
|
||||||
</ha-progress-button>
|
|
||||||
`
|
|
||||||
: html`
|
|
||||||
<ha-progress-button
|
|
||||||
.disabled=${!this.addon.available}
|
|
||||||
@click=${this._installClicked}
|
|
||||||
>
|
|
||||||
${this.supervisor.localize("addon.dashboard.install")}
|
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
`}
|
`}
|
||||||
</div>
|
${this._computeShowWebUI
|
||||||
<div>
|
|
||||||
${this.addon.version
|
|
||||||
? html` ${this._computeShowWebUI
|
|
||||||
? html`
|
? html`
|
||||||
<a
|
<a
|
||||||
href=${this._pathWebui!}
|
href=${this._pathWebui!}
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
class="right"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
>
|
>
|
||||||
<mwc-button>
|
<mwc-button>
|
||||||
${this.supervisor.localize(
|
Open web UI
|
||||||
"addon.dashboard.open_web_ui"
|
|
||||||
)}
|
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
</a>
|
</a>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
${this._computeShowIngressUI
|
${this._computeShowIngressUI
|
||||||
? html`
|
? html`
|
||||||
<mwc-button @click=${this._openIngress}>
|
<mwc-button class="right" @click=${this._openIngress}>
|
||||||
${this.supervisor.localize(
|
Open web UI
|
||||||
"addon.dashboard.open_web_ui"
|
|
||||||
)}
|
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
<ha-progress-button
|
<ha-progress-button
|
||||||
class="warning"
|
class=" right warning"
|
||||||
@click=${this._uninstallClicked}
|
@click=${this._uninstallClicked}
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("addon.dashboard.uninstall")}
|
Uninstall
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
${this.addon.build
|
${this.addon.build
|
||||||
? html`
|
? html`
|
||||||
<ha-call-api-button
|
<ha-call-api-button
|
||||||
class="warning"
|
class="warning right"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.path="hassio/addons/${this.addon.slug}/rebuild"
|
.path="hassio/addons/${this.addon.slug}/rebuild"
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("addon.dashboard.rebuild")}
|
Rebuild
|
||||||
</ha-call-api-button>
|
</ha-call-api-button>
|
||||||
`
|
`
|
||||||
: ""}`
|
|
||||||
: ""}
|
: ""}
|
||||||
</div>
|
`
|
||||||
|
: html`
|
||||||
|
${!this.addon.available
|
||||||
|
? html`
|
||||||
|
<p class="warning">
|
||||||
|
This add-on is not available on your system.
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
<ha-progress-button
|
||||||
|
.disabled=${!this.addon.available}
|
||||||
|
@click=${this._installClicked}
|
||||||
|
>
|
||||||
|
Install
|
||||||
|
</ha-progress-button>
|
||||||
|
`}
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
|
|
||||||
@@ -700,22 +579,6 @@ class HassioAddonInfo extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps) {
|
|
||||||
super.updated(changedProps);
|
|
||||||
if (changedProps.has("addon")) {
|
|
||||||
this._loadData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _loadData(): Promise<void> {
|
|
||||||
if (this.addon.state === "started") {
|
|
||||||
this._metrics = await fetchHassioStats(
|
|
||||||
this.hass,
|
|
||||||
`addons/${this.addon.slug}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _computeHassioApi(): boolean {
|
private get _computeHassioApi(): boolean {
|
||||||
return (
|
return (
|
||||||
this.addon.hassio_api &&
|
this.addon.hassio_api &&
|
||||||
@@ -737,21 +600,8 @@ class HassioAddonInfo extends LitElement {
|
|||||||
private _showMoreInfo(ev): void {
|
private _showMoreInfo(ev): void {
|
||||||
const id = ev.currentTarget.id;
|
const id = ev.currentTarget.id;
|
||||||
showHassioMarkdownDialog(this, {
|
showHassioMarkdownDialog(this, {
|
||||||
title: this.supervisor.localize(`addon.dashboard.capability.${id}.title`),
|
title: PERMIS_DESC[id].title,
|
||||||
content:
|
content: PERMIS_DESC[id].description,
|
||||||
id === "stage"
|
|
||||||
? this.supervisor.localize(
|
|
||||||
`addon.dashboard.capability.${id}.description`,
|
|
||||||
"icon_stable",
|
|
||||||
`<ha-svg-icon path="${STAGE_ICON.stable}"></ha-svg-icon>`,
|
|
||||||
"icon_experimental",
|
|
||||||
`<ha-svg-icon path="${STAGE_ICON.experimental}"></ha-svg-icon>`,
|
|
||||||
"icon_deprecated",
|
|
||||||
`<ha-svg-icon path="${STAGE_ICON.deprecated}"></ha-svg-icon>`
|
|
||||||
)
|
|
||||||
: this.supervisor.localize(
|
|
||||||
`addon.dashboard.capability.${id}.description`
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -804,11 +654,9 @@ class HassioAddonInfo extends LitElement {
|
|||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to set addon option, ${extractApiErrorMessage(
|
||||||
"addon.failed_to_save",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,11 +674,9 @@ class HassioAddonInfo extends LitElement {
|
|||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to set addon option, ${extractApiErrorMessage(
|
||||||
"addon.failed_to_save",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -848,11 +694,9 @@ class HassioAddonInfo extends LitElement {
|
|||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to set addon option, ${extractApiErrorMessage(
|
||||||
"addon.failed_to_save",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -870,11 +714,9 @@ class HassioAddonInfo extends LitElement {
|
|||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to set addon security option, ${extractApiErrorMessage(
|
||||||
"addon.failed_to_save",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -892,11 +734,9 @@ class HassioAddonInfo extends LitElement {
|
|||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to set addon option, ${extractApiErrorMessage(
|
||||||
"addon.failed_to_save",
|
err
|
||||||
"error",
|
)}`;
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -907,14 +747,12 @@ class HassioAddonInfo extends LitElement {
|
|||||||
this.addon.slug
|
this.addon.slug
|
||||||
);
|
);
|
||||||
showHassioMarkdownDialog(this, {
|
showHassioMarkdownDialog(this, {
|
||||||
title: this.supervisor.localize("addon.dashboard.changelog"),
|
title: "Changelog",
|
||||||
content,
|
content,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to get addon changelog",
|
||||||
"addon.dashboard.action_error.get_changelog"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -934,82 +772,13 @@ class HassioAddonInfo extends LitElement {
|
|||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("addon.dashboard.action_error.install"),
|
title: "Failed to install addon",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
button.progress = false;
|
button.progress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _stopClicked(ev: CustomEvent): Promise<void> {
|
|
||||||
const button = ev.currentTarget as any;
|
|
||||||
button.progress = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await stopHassioAddon(this.hass, this.addon.slug);
|
|
||||||
const eventdata = {
|
|
||||||
success: true,
|
|
||||||
response: undefined,
|
|
||||||
path: "stop",
|
|
||||||
};
|
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
|
||||||
} catch (err) {
|
|
||||||
showAlertDialog(this, {
|
|
||||||
title: this.supervisor.localize("addon.dashboard.action_error.stop"),
|
|
||||||
text: extractApiErrorMessage(err),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
button.progress = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _restartClicked(ev: CustomEvent): Promise<void> {
|
|
||||||
const button = ev.currentTarget as any;
|
|
||||||
button.progress = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await restartHassioAddon(this.hass, this.addon.slug);
|
|
||||||
const eventdata = {
|
|
||||||
success: true,
|
|
||||||
response: undefined,
|
|
||||||
path: "stop",
|
|
||||||
};
|
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
|
||||||
} catch (err) {
|
|
||||||
showAlertDialog(this, {
|
|
||||||
title: this.supervisor.localize("addon.dashboard.action_error.restart"),
|
|
||||||
text: extractApiErrorMessage(err),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
button.progress = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _updateClicked(): Promise<void> {
|
|
||||||
showDialogSupervisorUpdate(this, {
|
|
||||||
supervisor: this.supervisor,
|
|
||||||
name: this.addon.name,
|
|
||||||
version: this.addon.version_latest,
|
|
||||||
snapshotParams: {
|
|
||||||
name: `addon_${this.addon.slug}_${this.addon.version}`,
|
|
||||||
addons: [this.addon.slug],
|
|
||||||
homeassistant: false,
|
|
||||||
},
|
|
||||||
updateHandler: async () => await this._updateAddon(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _updateAddon(): Promise<void> {
|
|
||||||
await updateHassioAddon(this.hass, this.addon.slug);
|
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
|
||||||
colllection: "addon",
|
|
||||||
});
|
|
||||||
const eventdata = {
|
|
||||||
success: true,
|
|
||||||
response: undefined,
|
|
||||||
path: "update",
|
|
||||||
};
|
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _startClicked(ev: CustomEvent): Promise<void> {
|
private async _startClicked(ev: CustomEvent): Promise<void> {
|
||||||
const button = ev.currentTarget as any;
|
const button = ev.currentTarget as any;
|
||||||
button.progress = true;
|
button.progress = true;
|
||||||
@@ -1018,17 +787,13 @@ class HassioAddonInfo extends LitElement {
|
|||||||
this.hass,
|
this.hass,
|
||||||
this.addon.slug
|
this.addon.slug
|
||||||
);
|
);
|
||||||
if (!validate.valid) {
|
if (!validate.data.valid) {
|
||||||
await showConfirmationDialog(this, {
|
await showConfirmationDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to start addon - configuration validation failed!",
|
||||||
"addon.dashboard.action_error.start_invalid_config"
|
text: validate.data.message.split(" Got ")[0],
|
||||||
),
|
|
||||||
text: validate.message.split(" Got ")[0],
|
|
||||||
confirm: () => this._openConfiguration(),
|
confirm: () => this._openConfiguration(),
|
||||||
confirmText: this.supervisor.localize(
|
confirmText: "Go to configuration",
|
||||||
"addon.dashboard.action_error.go_to_config"
|
dismissText: "Cancel",
|
||||||
),
|
|
||||||
dismissText: this.supervisor.localize("common.cancel"),
|
|
||||||
});
|
});
|
||||||
button.progress = false;
|
button.progress = false;
|
||||||
return;
|
return;
|
||||||
@@ -1045,15 +810,9 @@ class HassioAddonInfo extends LitElement {
|
|||||||
try {
|
try {
|
||||||
await startHassioAddon(this.hass, this.addon.slug);
|
await startHassioAddon(this.hass, this.addon.slug);
|
||||||
this.addon = await fetchHassioAddonInfo(this.hass, this.addon.slug);
|
this.addon = await fetchHassioAddonInfo(this.hass, this.addon.slug);
|
||||||
const eventdata = {
|
|
||||||
success: true,
|
|
||||||
response: undefined,
|
|
||||||
path: "start",
|
|
||||||
};
|
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("addon.dashboard.action_error.start"),
|
title: "Failed to start addon",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1091,9 +850,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to uninstall addon",
|
||||||
"addon.dashboard.action_error.uninstall"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1168,6 +925,9 @@ class HassioAddonInfo extends LitElement {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
.right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
protection-enable mwc-button {
|
protection-enable mwc-button {
|
||||||
--mdc-theme-primary: white;
|
--mdc-theme-primary: white;
|
||||||
}
|
}
|
||||||
@@ -1190,8 +950,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
.card-actions {
|
.card-actions {
|
||||||
justify-content: space-between;
|
display: flow-root;
|
||||||
display: flex;
|
|
||||||
}
|
}
|
||||||
.security h3 {
|
.security h3 {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
@@ -1227,26 +986,12 @@ class HassioAddonInfo extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.addon-options {
|
.addon-options {
|
||||||
max-width: 90%;
|
max-width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addon-container {
|
|
||||||
display: grid;
|
|
||||||
grid-auto-flow: column;
|
|
||||||
grid-template-columns: 60% 40%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.addon-container > div:last-of-type {
|
|
||||||
align-self: end;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
.addon-options {
|
.addon-options {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
.addon-container {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
@@ -7,9 +7,8 @@ import {
|
|||||||
property,
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "../../../../src/components/ha-circular-progress";
|
|
||||||
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
import "../../../../src/components/ha-circular-progress";
|
||||||
import { haStyle } from "../../../../src/resources/styles";
|
import { haStyle } from "../../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import { hassioStyle } from "../../resources/hassio-style";
|
import { hassioStyle } from "../../resources/hassio-style";
|
||||||
@@ -19,8 +18,6 @@ import "./hassio-addon-logs";
|
|||||||
class HassioAddonLogDashboard extends LitElement {
|
class HassioAddonLogDashboard extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
@@ -31,7 +28,6 @@ class HassioAddonLogDashboard extends LitElement {
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<hassio-addon-logs
|
<hassio-addon-logs
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.supervisor=${this.supervisor}
|
|
||||||
.addon=${this.addon}
|
.addon=${this.addon}
|
||||||
></hassio-addon-logs>
|
></hassio-addon-logs>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -15,7 +15,6 @@ import {
|
|||||||
HassioAddonDetails,
|
HassioAddonDetails,
|
||||||
} from "../../../../src/data/hassio/addon";
|
} from "../../../../src/data/hassio/addon";
|
||||||
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import { haStyle } from "../../../../src/resources/styles";
|
import { haStyle } from "../../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import "../../components/hassio-ansi-to-html";
|
import "../../components/hassio-ansi-to-html";
|
||||||
@@ -25,8 +24,6 @@ import { hassioStyle } from "../../resources/hassio-style";
|
|||||||
class HassioAddonLogs extends LitElement {
|
class HassioAddonLogs extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@internalProperty() private _error?: string;
|
||||||
@@ -51,9 +48,7 @@ class HassioAddonLogs extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<mwc-button @click=${this._refresh}>
|
<mwc-button @click=${this._refresh}>Refresh</mwc-button>
|
||||||
${this.supervisor.localize("common.refresh")}
|
|
||||||
</mwc-button>
|
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
@@ -81,11 +76,7 @@ class HassioAddonLogs extends LitElement {
|
|||||||
try {
|
try {
|
||||||
this._content = await fetchHassioAddonLogs(this.hass, this.addon.slug);
|
this._content = await fetchHassioAddonLogs(this.hass, this.addon.slug);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to get addon logs, ${extractApiErrorMessage(err)}`;
|
||||||
"addon.logs.get_logs",
|
|
||||||
"error",
|
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,7 +44,7 @@ class HassioCardContent extends LitElement {
|
|||||||
${this.iconImage
|
${this.iconImage
|
||||||
? html`
|
? html`
|
||||||
<div class="icon_image ${this.iconClass}">
|
<div class="icon_image ${this.iconClass}">
|
||||||
<img src="${this.iconImage}" .title=${this.iconTitle} />
|
<img src="${this.iconImage}" title="${this.iconTitle}" />
|
||||||
<div></div>
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
@@ -1,87 +0,0 @@
|
|||||||
import {
|
|
||||||
css,
|
|
||||||
CSSResult,
|
|
||||||
customElement,
|
|
||||||
html,
|
|
||||||
LitElement,
|
|
||||||
property,
|
|
||||||
TemplateResult,
|
|
||||||
} from "lit-element";
|
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
|
||||||
import "../../../src/components/ha-bar";
|
|
||||||
import "../../../src/components/ha-settings-row";
|
|
||||||
import { roundWithOneDecimal } from "../../../src/util/calculate";
|
|
||||||
|
|
||||||
@customElement("supervisor-metric")
|
|
||||||
class SupervisorMetric extends LitElement {
|
|
||||||
@property({ type: Number }) public value!: number;
|
|
||||||
|
|
||||||
@property({ type: String }) public description!: string;
|
|
||||||
|
|
||||||
@property({ type: String }) public tooltip?: string;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
const roundedValue = roundWithOneDecimal(this.value);
|
|
||||||
return html`<ha-settings-row>
|
|
||||||
<span slot="heading">
|
|
||||||
${this.description}
|
|
||||||
</span>
|
|
||||||
<div slot="description" .title=${this.tooltip ?? ""}>
|
|
||||||
<span class="value">
|
|
||||||
${roundedValue}%
|
|
||||||
</span>
|
|
||||||
<ha-bar
|
|
||||||
class="${classMap({
|
|
||||||
"target-warning": roundedValue > 50,
|
|
||||||
"target-critical": roundedValue > 85,
|
|
||||||
})}"
|
|
||||||
.value=${this.value}
|
|
||||||
></ha-bar>
|
|
||||||
</div>
|
|
||||||
</ha-settings-row>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
|
||||||
return css`
|
|
||||||
ha-settings-row {
|
|
||||||
padding: 0;
|
|
||||||
height: 54px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
ha-settings-row > div[slot="description"] {
|
|
||||||
white-space: normal;
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
ha-bar {
|
|
||||||
--ha-bar-primary-color: var(
|
|
||||||
--hassio-bar-ok-color,
|
|
||||||
var(--success-color)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.target-warning {
|
|
||||||
--ha-bar-primary-color: var(
|
|
||||||
--hassio-bar-warning-color,
|
|
||||||
var(--warning-color)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.target-critical {
|
|
||||||
--ha-bar-primary-color: var(
|
|
||||||
--hassio-bar-critical-color,
|
|
||||||
var(--error-color)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.value {
|
|
||||||
width: 42px;
|
|
||||||
padding-right: 4px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"supervisor-metric": SupervisorMetric;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -27,15 +27,17 @@ class HassioAddons extends LitElement {
|
|||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h1>${this.supervisor.localize("dashboard.addons")}</h1>
|
<h1>Add-ons</h1>
|
||||||
<div class="card-group">
|
<div class="card-group">
|
||||||
${!this.supervisor.supervisor.addons?.length
|
${!this.supervisor.supervisor.addons?.length
|
||||||
? html`
|
? html`
|
||||||
<ha-card>
|
<ha-card>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
|
You don't have any add-ons installed yet. Head over to
|
||||||
<button class="link" @click=${this._openStore}>
|
<button class="link" @click=${this._openStore}>
|
||||||
${this.supervisor.localize("dashboard.no_addons")}
|
the add-on store
|
||||||
</button>
|
</button>
|
||||||
|
to get started!
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`
|
`
|
||||||
@@ -56,16 +58,10 @@ class HassioAddons extends LitElement {
|
|||||||
? mdiArrowUpBoldCircle
|
? mdiArrowUpBoldCircle
|
||||||
: mdiPuzzle}
|
: mdiPuzzle}
|
||||||
.iconTitle=${addon.state !== "started"
|
.iconTitle=${addon.state !== "started"
|
||||||
? this.supervisor.localize(
|
? "Add-on is stopped"
|
||||||
"dashboard.addon_stopped"
|
|
||||||
)
|
|
||||||
: addon.update_available!
|
: addon.update_available!
|
||||||
? this.supervisor.localize(
|
? "New version available"
|
||||||
"dashboard.addon_new_version"
|
: "Add-on is running"}
|
||||||
)
|
|
||||||
: this.supervisor.localize(
|
|
||||||
"dashboard.addon_running"
|
|
||||||
)}
|
|
||||||
.iconClass=${addon.update_available
|
.iconClass=${addon.update_available
|
||||||
? addon.state === "started"
|
? addon.state === "started"
|
||||||
? "update"
|
? "update"
|
||||||
|
@@ -29,16 +29,13 @@ class HassioDashboard extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<hass-tabs-subpage
|
<hass-tabs-subpage
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.localizeFunc=${this.supervisor.localize}
|
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
|
hassio
|
||||||
|
main-page
|
||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
.tabs=${supervisorTabs}
|
.tabs=${supervisorTabs}
|
||||||
main-page
|
|
||||||
supervisor
|
|
||||||
>
|
>
|
||||||
<span slot="header">
|
<span slot="header">Dashboard</span>
|
||||||
${this.supervisor.localize("panel.dashboard")}
|
|
||||||
</span>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<hassio-update
|
<hassio-update
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
|
@@ -10,11 +10,8 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
|
||||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
|
||||||
import "../../../src/components/buttons/ha-progress-button";
|
import "../../../src/components/buttons/ha-progress-button";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../src/components/ha-settings-row";
|
|
||||||
import "../../../src/components/ha-svg-icon";
|
import "../../../src/components/ha-svg-icon";
|
||||||
import {
|
import {
|
||||||
extractApiErrorMessage,
|
extractApiErrorMessage,
|
||||||
@@ -26,24 +23,15 @@ import {
|
|||||||
HassioHomeAssistantInfo,
|
HassioHomeAssistantInfo,
|
||||||
HassioSupervisorInfo,
|
HassioSupervisorInfo,
|
||||||
} from "../../../src/data/hassio/supervisor";
|
} from "../../../src/data/hassio/supervisor";
|
||||||
import { updateCore } from "../../../src/data/supervisor/core";
|
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||||
import {
|
|
||||||
Supervisor,
|
|
||||||
supervisorApiWsRequest,
|
|
||||||
} from "../../../src/data/supervisor/supervisor";
|
|
||||||
import {
|
import {
|
||||||
showAlertDialog,
|
showAlertDialog,
|
||||||
showConfirmationDialog,
|
showConfirmationDialog,
|
||||||
} from "../../../src/dialogs/generic/show-dialog-box";
|
} from "../../../src/dialogs/generic/show-dialog-box";
|
||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
import { showDialogSupervisorUpdate } from "../dialogs/update/show-dialog-update";
|
|
||||||
import { hassioStyle } from "../resources/hassio-style";
|
import { hassioStyle } from "../resources/hassio-style";
|
||||||
|
|
||||||
const computeVersion = (key: string, version: string): string => {
|
|
||||||
return key === "os" ? version : `${key}-${version}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
@customElement("hassio-update")
|
@customElement("hassio-update")
|
||||||
export class HassioUpdate extends LitElement {
|
export class HassioUpdate extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
@@ -69,17 +57,13 @@ export class HassioUpdate extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h1>
|
<h1>
|
||||||
${this.supervisor.localize(
|
${updatesAvailable > 1
|
||||||
"common.update_available",
|
? "Updates Available 🎉"
|
||||||
"count",
|
: "Update Available 🎉"}
|
||||||
updatesAvailable
|
|
||||||
)}
|
|
||||||
🎉
|
|
||||||
</h1>
|
</h1>
|
||||||
<div class="card-group">
|
<div class="card-group">
|
||||||
${this._renderUpdateCard(
|
${this._renderUpdateCard(
|
||||||
"Home Assistant Core",
|
"Home Assistant Core",
|
||||||
"core",
|
|
||||||
this.supervisor.core,
|
this.supervisor.core,
|
||||||
"hassio/homeassistant/update",
|
"hassio/homeassistant/update",
|
||||||
`https://${
|
`https://${
|
||||||
@@ -88,7 +72,6 @@ export class HassioUpdate extends LitElement {
|
|||||||
)}
|
)}
|
||||||
${this._renderUpdateCard(
|
${this._renderUpdateCard(
|
||||||
"Supervisor",
|
"Supervisor",
|
||||||
"supervisor",
|
|
||||||
this.supervisor.supervisor,
|
this.supervisor.supervisor,
|
||||||
"hassio/supervisor/update",
|
"hassio/supervisor/update",
|
||||||
`https://github.com//home-assistant/hassio/releases/tag/${this.supervisor.supervisor.version_latest}`
|
`https://github.com//home-assistant/hassio/releases/tag/${this.supervisor.supervisor.version_latest}`
|
||||||
@@ -96,7 +79,6 @@ export class HassioUpdate extends LitElement {
|
|||||||
${this.supervisor.host.features.includes("hassos")
|
${this.supervisor.host.features.includes("hassos")
|
||||||
? this._renderUpdateCard(
|
? this._renderUpdateCard(
|
||||||
"Operating System",
|
"Operating System",
|
||||||
"os",
|
|
||||||
this.supervisor.os,
|
this.supervisor.os,
|
||||||
"hassio/os/update",
|
"hassio/os/update",
|
||||||
`https://github.com//home-assistant/hassos/releases/tag/${this.supervisor.os.version_latest}`
|
`https://github.com//home-assistant/hassos/releases/tag/${this.supervisor.os.version_latest}`
|
||||||
@@ -109,7 +91,6 @@ export class HassioUpdate extends LitElement {
|
|||||||
|
|
||||||
private _renderUpdateCard(
|
private _renderUpdateCard(
|
||||||
name: string,
|
name: string,
|
||||||
key: string,
|
|
||||||
object: HassioHomeAssistantInfo | HassioSupervisorInfo | HassioHassOSInfo,
|
object: HassioHomeAssistantInfo | HassioSupervisorInfo | HassioHassOSInfo,
|
||||||
apiPath: string,
|
apiPath: string,
|
||||||
releaseNotesUrl: string
|
releaseNotesUrl: string
|
||||||
@@ -123,39 +104,22 @@ export class HassioUpdate extends LitElement {
|
|||||||
<div class="icon">
|
<div class="icon">
|
||||||
<ha-svg-icon .path=${mdiHomeAssistant}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiHomeAssistant}></ha-svg-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="update-heading">${name}</div>
|
<div class="update-heading">${name} ${object.version_latest}</div>
|
||||||
<ha-settings-row two-line>
|
<div class="warning">
|
||||||
<span slot="heading">
|
You are currently running version ${object.version}
|
||||||
${this.supervisor.localize("common.version")}
|
</div>
|
||||||
</span>
|
|
||||||
<span slot="description">
|
|
||||||
${computeVersion(key, object.version!)}
|
|
||||||
</span>
|
|
||||||
</ha-settings-row>
|
|
||||||
|
|
||||||
<ha-settings-row two-line>
|
|
||||||
<span slot="heading">
|
|
||||||
${this.supervisor.localize("common.newest_version")}
|
|
||||||
</span>
|
|
||||||
<span slot="description">
|
|
||||||
${computeVersion(key, object.version_latest!)}
|
|
||||||
</span>
|
|
||||||
</ha-settings-row>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<a href="${releaseNotesUrl}" target="_blank" rel="noreferrer">
|
<a href="${releaseNotesUrl}" target="_blank" rel="noreferrer">
|
||||||
<mwc-button>
|
<mwc-button>Release notes</mwc-button>
|
||||||
${this.supervisor.localize("common.release_notes")}
|
|
||||||
</mwc-button>
|
|
||||||
</a>
|
</a>
|
||||||
<ha-progress-button
|
<ha-progress-button
|
||||||
.apiPath=${apiPath}
|
.apiPath=${apiPath}
|
||||||
.name=${name}
|
.name=${name}
|
||||||
.key=${key}
|
|
||||||
.version=${object.version_latest}
|
.version=${object.version_latest}
|
||||||
@click=${this._confirmUpdate}
|
@click=${this._confirmUpdate}
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("common.update")}
|
Update
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
@@ -164,36 +128,12 @@ export class HassioUpdate extends LitElement {
|
|||||||
|
|
||||||
private async _confirmUpdate(ev): Promise<void> {
|
private async _confirmUpdate(ev): Promise<void> {
|
||||||
const item = ev.currentTarget;
|
const item = ev.currentTarget;
|
||||||
if (item.key === "core") {
|
|
||||||
showDialogSupervisorUpdate(this, {
|
|
||||||
supervisor: this.supervisor,
|
|
||||||
name: "Home Assistant Core",
|
|
||||||
version: this.supervisor.core.version,
|
|
||||||
snapshotParams: {
|
|
||||||
name: `core_${this.supervisor.core.version}`,
|
|
||||||
folders: ["homeassistant"],
|
|
||||||
homeassistant: true,
|
|
||||||
},
|
|
||||||
updateHandler: async () => this._updateCore(),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
item.progress = true;
|
item.progress = true;
|
||||||
const confirmed = await showConfirmationDialog(this, {
|
const confirmed = await showConfirmationDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: `Update ${item.name}`,
|
||||||
"confirm.update.title",
|
text: `Are you sure you want to update ${item.name} to version ${item.version}?`,
|
||||||
"name",
|
confirmText: "update",
|
||||||
item.name
|
dismissText: "cancel",
|
||||||
),
|
|
||||||
text: this.supervisor.localize(
|
|
||||||
"confirm.update.text",
|
|
||||||
"name",
|
|
||||||
item.name,
|
|
||||||
"version",
|
|
||||||
computeVersion(item.key, item.version)
|
|
||||||
),
|
|
||||||
confirmText: this.supervisor.localize("common.update"),
|
|
||||||
dismissText: this.supervisor.localize("common.cancel"),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
@@ -201,28 +141,13 @@ export class HassioUpdate extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
|
||||||
await supervisorApiWsRequest(this.hass.connection, {
|
|
||||||
method: "post",
|
|
||||||
endpoint: item.apiPath.replace("hassio", ""),
|
|
||||||
timeout: null,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await this.hass.callApi<HassioResponse<void>>("POST", item.apiPath);
|
await this.hass.callApi<HassioResponse<void>>("POST", item.apiPath);
|
||||||
}
|
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
|
||||||
colllection: item.key,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Only show an error if the status code was not expected (user behind proxy)
|
// Only show an error if the status code was not expected (user behind proxy)
|
||||||
// or no status at all(connection terminated)
|
// or no status at all(connection terminated)
|
||||||
if (
|
if (err.status_code && !ignoredStatusCodes.has(err.status_code)) {
|
||||||
this.hass.connection.connected &&
|
|
||||||
err.status_code &&
|
|
||||||
!ignoredStatusCodes.has(err.status_code)
|
|
||||||
) {
|
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("common.error.update_failed"),
|
title: "Update failed",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -230,13 +155,6 @@ export class HassioUpdate extends LitElement {
|
|||||||
item.progress = false;
|
item.progress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _updateCore(): Promise<void> {
|
|
||||||
await updateCore(this.hass);
|
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
|
||||||
colllection: "core",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
@@ -254,6 +172,9 @@ export class HassioUpdate extends LitElement {
|
|||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
}
|
}
|
||||||
|
.warning {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
.card-content {
|
.card-content {
|
||||||
height: calc(100% - 47px);
|
height: calc(100% - 47px);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -261,13 +182,13 @@ export class HassioUpdate extends LitElement {
|
|||||||
.card-actions {
|
.card-actions {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
.errors {
|
||||||
|
color: var(--error-color);
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
ha-settings-row {
|
|
||||||
padding: 0;
|
|
||||||
--paper-item-body-two-line-min-height: 32px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -3,9 +3,9 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
|
internalProperty,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { createCloseHeading } from "../../../../src/components/ha-dialog";
|
import { createCloseHeading } from "../../../../src/components/ha-dialog";
|
||||||
|
@@ -35,7 +35,6 @@ import {
|
|||||||
updateNetworkInterface,
|
updateNetworkInterface,
|
||||||
WifiConfiguration,
|
WifiConfiguration,
|
||||||
} from "../../../../src/data/hassio/network";
|
} from "../../../../src/data/hassio/network";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import {
|
import {
|
||||||
showAlertDialog,
|
showAlertDialog,
|
||||||
showConfirmationDialog,
|
showConfirmationDialog,
|
||||||
@@ -52,8 +51,6 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
implements HassDialog<HassioNetworkDialogParams> {
|
implements HassDialog<HassioNetworkDialogParams> {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@internalProperty() private _accessPoints?: AccessPoints;
|
@internalProperty() private _accessPoints?: AccessPoints;
|
||||||
|
|
||||||
@internalProperty() private _curTabIndex = 0;
|
@internalProperty() private _curTabIndex = 0;
|
||||||
@@ -76,8 +73,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
this._params = params;
|
this._params = params;
|
||||||
this._dirty = false;
|
this._dirty = false;
|
||||||
this._curTabIndex = 0;
|
this._curTabIndex = 0;
|
||||||
this.supervisor = params.supervisor;
|
this._interfaces = params.network.interfaces.sort((a, b) => {
|
||||||
this._interfaces = params.supervisor.network.interfaces.sort((a, b) => {
|
|
||||||
return a.primary > b.primary ? -1 : 1;
|
return a.primary > b.primary ? -1 : 1;
|
||||||
});
|
});
|
||||||
this._interface = { ...this._interfaces[this._curTabIndex] };
|
this._interface = { ...this._interfaces[this._curTabIndex] };
|
||||||
@@ -108,7 +104,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
<div slot="heading">
|
<div slot="heading">
|
||||||
<ha-header-bar>
|
<ha-header-bar>
|
||||||
<span slot="title">
|
<span slot="title">
|
||||||
${this.supervisor.localize("dialog.network.title")}
|
Network settings
|
||||||
</span>
|
</span>
|
||||||
<mwc-icon-button slot="actionItems" dialogAction="cancel">
|
<mwc-icon-button slot="actionItems" dialogAction="cancel">
|
||||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||||
@@ -143,13 +139,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
? html`
|
? html`
|
||||||
<ha-expansion-panel header="Wi-Fi" outlined>
|
<ha-expansion-panel header="Wi-Fi" outlined>
|
||||||
${this._interface?.wifi?.ssid
|
${this._interface?.wifi?.ssid
|
||||||
? html`<p>
|
? html`<p>Connected to: ${this._interface?.wifi?.ssid}</p>`
|
||||||
${this.supervisor.localize(
|
|
||||||
"dialog.network.connected_to",
|
|
||||||
"ssid",
|
|
||||||
this._interface?.wifi?.ssid
|
|
||||||
)}
|
|
||||||
</p>`
|
|
||||||
: ""}
|
: ""}
|
||||||
<mwc-button
|
<mwc-button
|
||||||
class="scan"
|
class="scan"
|
||||||
@@ -159,7 +149,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
${this._scanning
|
${this._scanning
|
||||||
? html`<ha-circular-progress active size="small">
|
? html`<ha-circular-progress active size="small">
|
||||||
</ha-circular-progress>`
|
</ha-circular-progress>`
|
||||||
: this.supervisor.localize("dialog.network.scan_ap")}
|
: "Scan for accesspoints"}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
${this._accessPoints &&
|
${this._accessPoints &&
|
||||||
this._accessPoints.accesspoints &&
|
this._accessPoints.accesspoints &&
|
||||||
@@ -191,11 +181,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
${this._wifiConfiguration
|
${this._wifiConfiguration
|
||||||
? html`
|
? html`
|
||||||
<div class="radio-row">
|
<div class="radio-row">
|
||||||
<ha-formfield
|
<ha-formfield label="open">
|
||||||
.label=${this.supervisor.localize(
|
|
||||||
"dialog.network.open"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@change=${this._handleRadioValueChangedAp}
|
@change=${this._handleRadioValueChangedAp}
|
||||||
.ap=${this._wifiConfiguration}
|
.ap=${this._wifiConfiguration}
|
||||||
@@ -207,11 +193,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
>
|
>
|
||||||
</ha-radio>
|
</ha-radio>
|
||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
<ha-formfield
|
<ha-formfield label="wep">
|
||||||
.label=${this.supervisor.localize(
|
|
||||||
"dialog.network.wep"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@change=${this._handleRadioValueChangedAp}
|
@change=${this._handleRadioValueChangedAp}
|
||||||
.ap=${this._wifiConfiguration}
|
.ap=${this._wifiConfiguration}
|
||||||
@@ -221,11 +203,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
>
|
>
|
||||||
</ha-radio>
|
</ha-radio>
|
||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
<ha-formfield
|
<ha-formfield label="wpa-psk">
|
||||||
.label=${this.supervisor.localize(
|
|
||||||
"dialog.network.wpa"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@change=${this._handleRadioValueChangedAp}
|
@change=${this._handleRadioValueChangedAp}
|
||||||
.ap=${this._wifiConfiguration}
|
.ap=${this._wifiConfiguration}
|
||||||
@@ -259,21 +237,18 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
: ""}
|
: ""}
|
||||||
${this._dirty
|
${this._dirty
|
||||||
? html`<div class="warning">
|
? html`<div class="warning">
|
||||||
${this.supervisor.localize("dialog.network.warning")}
|
If you are changing the Wi-Fi, IP or gateway addresses, you might
|
||||||
|
lose the connection!
|
||||||
</div>`
|
</div>`
|
||||||
: ""}
|
: ""}
|
||||||
</div>
|
</div>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<mwc-button
|
<mwc-button label="close" @click=${this.closeDialog}> </mwc-button>
|
||||||
.label=${this.supervisor.localize("common.cancel")}
|
|
||||||
@click=${this.closeDialog}
|
|
||||||
>
|
|
||||||
</mwc-button>
|
|
||||||
<mwc-button @click=${this._updateNetwork} .disabled=${!this._dirty}>
|
<mwc-button @click=${this._updateNetwork} .disabled=${!this._dirty}>
|
||||||
${this._processing
|
${this._processing
|
||||||
? html`<ha-circular-progress active size="small">
|
? html`<ha-circular-progress active size="small">
|
||||||
</ha-circular-progress>`
|
</ha-circular-progress>`
|
||||||
: this.supervisor.localize("common.save")}
|
: "Save"}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
@@ -310,9 +285,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
outlined
|
outlined
|
||||||
>
|
>
|
||||||
<div class="radio-row">
|
<div class="radio-row">
|
||||||
<ha-formfield
|
<ha-formfield label="DHCP">
|
||||||
.label=${this.supervisor.localize("dialog.network.dhcp")}
|
|
||||||
>
|
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@change=${this._handleRadioValueChanged}
|
@change=${this._handleRadioValueChanged}
|
||||||
.version=${version}
|
.version=${version}
|
||||||
@@ -322,9 +295,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
>
|
>
|
||||||
</ha-radio>
|
</ha-radio>
|
||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
<ha-formfield
|
<ha-formfield label="Static">
|
||||||
.label=${this.supervisor.localize("dialog.network.static")}
|
|
||||||
>
|
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@change=${this._handleRadioValueChanged}
|
@change=${this._handleRadioValueChanged}
|
||||||
.version=${version}
|
.version=${version}
|
||||||
@@ -334,10 +305,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
>
|
>
|
||||||
</ha-radio>
|
</ha-radio>
|
||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
<ha-formfield
|
<ha-formfield label="Disabled" class="warning">
|
||||||
.label=${this.supervisor.localize("dialog.network.disabled")}
|
|
||||||
class="warning"
|
|
||||||
>
|
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@change=${this._handleRadioValueChanged}
|
@change=${this._handleRadioValueChanged}
|
||||||
.version=${version}
|
.version=${version}
|
||||||
@@ -353,7 +321,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
<paper-input
|
<paper-input
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="address"
|
id="address"
|
||||||
.label=${this.supervisor.localize("dialog.network.ip_netmask")}
|
label="IP address/Netmask"
|
||||||
.version=${version}
|
.version=${version}
|
||||||
.value=${this._toString(this._interface![version].address)}
|
.value=${this._toString(this._interface![version].address)}
|
||||||
@value-changed=${this._handleInputValueChanged}
|
@value-changed=${this._handleInputValueChanged}
|
||||||
@@ -362,7 +330,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
<paper-input
|
<paper-input
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="gateway"
|
id="gateway"
|
||||||
.label=${this.supervisor.localize("dialog.network.gateway")}
|
label="Gateway address"
|
||||||
.version=${version}
|
.version=${version}
|
||||||
.value=${this._interface![version].gateway}
|
.value=${this._interface![version].gateway}
|
||||||
@value-changed=${this._handleInputValueChanged}
|
@value-changed=${this._handleInputValueChanged}
|
||||||
@@ -371,7 +339,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
<paper-input
|
<paper-input
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="nameservers"
|
id="nameservers"
|
||||||
.label=${this.supervisor.localize("dialog.network.dns_servers")}
|
label="DNS servers"
|
||||||
.version=${version}
|
.version=${version}
|
||||||
.value=${this._toString(this._interface![version].nameservers)}
|
.value=${this._toString(this._interface![version].nameservers)}
|
||||||
@value-changed=${this._handleInputValueChanged}
|
@value-changed=${this._handleInputValueChanged}
|
||||||
@@ -456,7 +424,7 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("dialog.network.failed_to_change"),
|
title: "Failed to change network settings",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
this._processing = false;
|
this._processing = false;
|
||||||
@@ -469,9 +437,10 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
private async _handleTabActivated(ev: CustomEvent): Promise<void> {
|
private async _handleTabActivated(ev: CustomEvent): Promise<void> {
|
||||||
if (this._dirty) {
|
if (this._dirty) {
|
||||||
const confirm = await showConfirmationDialog(this, {
|
const confirm = await showConfirmationDialog(this, {
|
||||||
text: this.supervisor.localize("dialog.network.unsaved"),
|
text:
|
||||||
confirmText: this.supervisor.localize("common.yes"),
|
"You have unsaved changes, these will get lost if you change tabs, do you want to continue?",
|
||||||
dismissText: this.supervisor.localize("common.no"),
|
confirmText: "yes",
|
||||||
|
dismissText: "no",
|
||||||
});
|
});
|
||||||
if (!confirm) {
|
if (!confirm) {
|
||||||
this.requestUpdate("_interface");
|
this.requestUpdate("_interface");
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
import { NetworkInfo } from "../../../../src/data/hassio/network";
|
||||||
import "./dialog-hassio-network";
|
import "./dialog-hassio-network";
|
||||||
|
|
||||||
export interface HassioNetworkDialogParams {
|
export interface HassioNetworkDialogParams {
|
||||||
supervisor: Supervisor;
|
network: NetworkInfo;
|
||||||
loadData: () => Promise<void>;
|
loadData: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,18 +22,14 @@ import {
|
|||||||
fetchHassioDockerRegistries,
|
fetchHassioDockerRegistries,
|
||||||
removeHassioDockerRegistry,
|
removeHassioDockerRegistry,
|
||||||
} from "../../../../src/data/hassio/docker";
|
} from "../../../../src/data/hassio/docker";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import { showAlertDialog } from "../../../../src/dialogs/generic/show-dialog-box";
|
import { showAlertDialog } from "../../../../src/dialogs/generic/show-dialog-box";
|
||||||
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import { RegistriesDialogParams } from "./show-dialog-registries";
|
|
||||||
|
|
||||||
@customElement("dialog-hassio-registries")
|
@customElement("dialog-hassio-registries")
|
||||||
class HassioRegistriesDialog extends LitElement {
|
class HassioRegistriesDialog extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) private _registries?: {
|
@property({ attribute: false }) private _registries?: {
|
||||||
registry: string;
|
registry: string;
|
||||||
username: string;
|
username: string;
|
||||||
@@ -59,8 +55,8 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
.heading=${createCloseHeading(
|
.heading=${createCloseHeading(
|
||||||
this.hass,
|
this.hass,
|
||||||
this._addingRegistry
|
this._addingRegistry
|
||||||
? this.supervisor.localize("dialog.registries.title_add")
|
? "Add New Docker Registry"
|
||||||
: this.supervisor.localize("dialog.registries.title_manage")
|
: "Manage Docker Registries"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div class="form">
|
<div class="form">
|
||||||
@@ -70,9 +66,7 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
@value-changed=${this._inputChanged}
|
@value-changed=${this._inputChanged}
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
name="registry"
|
name="registry"
|
||||||
.label=${this.supervisor.localize(
|
label="Registry"
|
||||||
"dialog.registries.registry"
|
|
||||||
)}
|
|
||||||
required
|
required
|
||||||
auto-validate
|
auto-validate
|
||||||
></paper-input>
|
></paper-input>
|
||||||
@@ -80,9 +74,7 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
@value-changed=${this._inputChanged}
|
@value-changed=${this._inputChanged}
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
name="username"
|
name="username"
|
||||||
.label=${this.supervisor.localize(
|
label="Username"
|
||||||
"dialog.registries.username"
|
|
||||||
)}
|
|
||||||
required
|
required
|
||||||
auto-validate
|
auto-validate
|
||||||
></paper-input>
|
></paper-input>
|
||||||
@@ -90,9 +82,7 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
@value-changed=${this._inputChanged}
|
@value-changed=${this._inputChanged}
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
name="password"
|
name="password"
|
||||||
.label=${this.supervisor.localize(
|
label="Password"
|
||||||
"dialog.registries.password"
|
|
||||||
)}
|
|
||||||
type="password"
|
type="password"
|
||||||
required
|
required
|
||||||
auto-validate
|
auto-validate
|
||||||
@@ -104,7 +94,7 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
)}
|
)}
|
||||||
@click=${this._addNewRegistry}
|
@click=${this._addNewRegistry}
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("dialog.registries.add_registry")}
|
Add registry
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
`
|
`
|
||||||
: html`${this._registries?.length
|
: html`${this._registries?.length
|
||||||
@@ -113,16 +103,11 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
<mwc-list-item class="option" hasMeta twoline>
|
<mwc-list-item class="option" hasMeta twoline>
|
||||||
<span>${entry.registry}</span>
|
<span>${entry.registry}</span>
|
||||||
<span slot="secondary"
|
<span slot="secondary"
|
||||||
>${this.supervisor.localize(
|
>Username: ${entry.username}</span
|
||||||
"dialog.registries.username"
|
|
||||||
)}:
|
|
||||||
${entry.username}</span
|
|
||||||
>
|
>
|
||||||
<mwc-icon-button
|
<mwc-icon-button
|
||||||
.entry=${entry}
|
.entry=${entry}
|
||||||
.title=${this.supervisor.localize(
|
title="Remove"
|
||||||
"dialog.registries.remove"
|
|
||||||
)}
|
|
||||||
slot="meta"
|
slot="meta"
|
||||||
@click=${this._removeRegistry}
|
@click=${this._removeRegistry}
|
||||||
>
|
>
|
||||||
@@ -133,17 +118,11 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
})
|
})
|
||||||
: html`
|
: html`
|
||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
<span
|
<span>No registries configured</span>
|
||||||
>${this.supervisor.localize(
|
|
||||||
"dialog.registries.no_registries"
|
|
||||||
)}</span
|
|
||||||
>
|
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
`}
|
`}
|
||||||
<mwc-button @click=${this._addRegistry}>
|
<mwc-button @click=${this._addRegistry}>
|
||||||
${this.supervisor.localize(
|
Add new registry
|
||||||
"dialog.registries.add_new_registry"
|
|
||||||
)}
|
|
||||||
</mwc-button> `}
|
</mwc-button> `}
|
||||||
</div>
|
</div>
|
||||||
</ha-dialog>
|
</ha-dialog>
|
||||||
@@ -155,9 +134,8 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
this[`_${target.name}`] = target.value;
|
this[`_${target.name}`] = target.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async showDialog(dialogParams: RegistriesDialogParams): Promise<void> {
|
public async showDialog(_dialogParams: any): Promise<void> {
|
||||||
this._opened = true;
|
this._opened = true;
|
||||||
this.supervisor = dialogParams.supervisor;
|
|
||||||
await this._loadRegistries();
|
await this._loadRegistries();
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
}
|
}
|
||||||
@@ -200,7 +178,7 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
this._addingRegistry = false;
|
this._addingRegistry = false;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("dialog.registries.failed_to_add"),
|
title: "Failed to add registry",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -214,7 +192,7 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
await this._loadRegistries();
|
await this._loadRegistries();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("dialog.registries.failed_to_remove"),
|
title: "Failed to remove registry",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +1,10 @@
|
|||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import "./dialog-hassio-registries";
|
import "./dialog-hassio-registries";
|
||||||
|
|
||||||
export interface RegistriesDialogParams {
|
export const showRegistriesDialog = (element: HTMLElement): void => {
|
||||||
supervisor: Supervisor;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const showRegistriesDialog = (
|
|
||||||
element: HTMLElement,
|
|
||||||
dialogParams: RegistriesDialogParams
|
|
||||||
): void => {
|
|
||||||
fireEvent(element, "show-dialog", {
|
fireEvent(element, "show-dialog", {
|
||||||
dialogTag: "dialog-hassio-registries",
|
dialogTag: "dialog-hassio-registries",
|
||||||
dialogImport: () => import("./dialog-hassio-registries"),
|
dialogImport: () => import("./dialog-hassio-registries"),
|
||||||
dialogParams,
|
dialogParams: {},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@@ -18,7 +18,7 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import "../../../../src/components/ha-circular-progress";
|
import "../../../../src/components/ha-circular-progress";
|
||||||
import { createCloseHeading } from "../../../../src/components/ha-dialog";
|
import "../../../../src/components/ha-dialog";
|
||||||
import "../../../../src/components/ha-svg-icon";
|
import "../../../../src/components/ha-svg-icon";
|
||||||
import {
|
import {
|
||||||
fetchHassioAddonsInfo,
|
fetchHassioAddonsInfo,
|
||||||
@@ -26,7 +26,6 @@ import {
|
|||||||
} from "../../../../src/data/hassio/addon";
|
} from "../../../../src/data/hassio/addon";
|
||||||
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
||||||
import { setSupervisorOption } from "../../../../src/data/hassio/supervisor";
|
import { setSupervisorOption } from "../../../../src/data/hassio/supervisor";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import { HassioRepositoryDialogParams } from "./show-dialog-repositories";
|
import { HassioRepositoryDialogParams } from "./show-dialog-repositories";
|
||||||
@@ -35,8 +34,6 @@ import { HassioRepositoryDialogParams } from "./show-dialog-repositories";
|
|||||||
class HassioRepositoriesDialog extends LitElement {
|
class HassioRepositoriesDialog extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) private _repos: HassioAddonRepository[] = [];
|
@property({ attribute: false }) private _repos: HassioAddonRepository[] = [];
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
@@ -50,11 +47,9 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@internalProperty() private _error?: string;
|
||||||
|
|
||||||
public async showDialog(
|
public async showDialog(_dialogParams: any): Promise<void> {
|
||||||
dialogParams: HassioRepositoryDialogParams
|
this._dialogParams = _dialogParams;
|
||||||
): Promise<void> {
|
this._repos = _dialogParams.repos;
|
||||||
this._dialogParams = dialogParams;
|
|
||||||
this.supervisor = dialogParams.supervisor;
|
|
||||||
this._opened = true;
|
this._opened = true;
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
}
|
}
|
||||||
@@ -71,19 +66,14 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
);
|
);
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const repositories = this._filteredRepositories(
|
const repositories = this._filteredRepositories(this._repos);
|
||||||
this.supervisor.addon.repositories
|
|
||||||
);
|
|
||||||
return html`
|
return html`
|
||||||
<ha-dialog
|
<ha-dialog
|
||||||
.open=${this._opened}
|
.open=${this._opened}
|
||||||
@closing=${this.closeDialog}
|
@closing=${this.closeDialog}
|
||||||
scrimClickAction
|
scrimClickAction
|
||||||
escapeKeyAction
|
escapeKeyAction
|
||||||
.heading=${createCloseHeading(
|
heading="Manage add-on repositories"
|
||||||
this.hass,
|
|
||||||
this.supervisor.localize("dialog.repositories.title")
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
${this._error ? html`<div class="error">${this._error}</div>` : ""}
|
${this._error ? html`<div class="error">${this._error}</div>` : ""}
|
||||||
<div class="form">
|
<div class="form">
|
||||||
@@ -98,9 +88,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
</paper-item-body>
|
</paper-item-body>
|
||||||
<mwc-icon-button
|
<mwc-icon-button
|
||||||
.slug=${repo.slug}
|
.slug=${repo.slug}
|
||||||
.title=${this.supervisor.localize(
|
title="Remove"
|
||||||
"dialog.repositories.remove"
|
|
||||||
)}
|
|
||||||
@click=${this._removeRepository}
|
@click=${this._removeRepository}
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${mdiDelete}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiDelete}></ha-svg-icon>
|
||||||
@@ -117,13 +105,13 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
<paper-input
|
<paper-input
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="repository_input"
|
id="repository_input"
|
||||||
.label=${this.supervisor.localize("dialog.repositories.add")}
|
label="Add repository"
|
||||||
@keydown=${this._handleKeyAdd}
|
@keydown=${this._handleKeyAdd}
|
||||||
></paper-input>
|
></paper-input>
|
||||||
<mwc-button @click=${this._addRepository}>
|
<mwc-button @click=${this._addRepository}>
|
||||||
${this._prosessing
|
${this._prosessing
|
||||||
? html`<ha-circular-progress active></ha-circular-progress>`
|
? html`<ha-circular-progress active></ha-circular-progress>`
|
||||||
: this.supervisor.localize("dialog.repositories.add")}
|
: "Add"}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
import { HassioAddonRepository } from "../../../../src/data/hassio/addon";
|
||||||
import "./dialog-hassio-repositories";
|
import "./dialog-hassio-repositories";
|
||||||
|
|
||||||
export interface HassioRepositoryDialogParams {
|
export interface HassioRepositoryDialogParams {
|
||||||
supervisor: Supervisor;
|
repos: HassioAddonRepository[];
|
||||||
loadData: () => Promise<void>;
|
loadData: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,11 +22,7 @@ import {
|
|||||||
fetchHassioSnapshotInfo,
|
fetchHassioSnapshotInfo,
|
||||||
HassioSnapshotDetail,
|
HassioSnapshotDetail,
|
||||||
} from "../../../../src/data/hassio/snapshot";
|
} from "../../../../src/data/hassio/snapshot";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box";
|
||||||
import {
|
|
||||||
showAlertDialog,
|
|
||||||
showConfirmationDialog,
|
|
||||||
} from "../../../../src/dialogs/generic/show-dialog-box";
|
|
||||||
import { PolymerChangedEvent } from "../../../../src/polymer-types";
|
import { PolymerChangedEvent } from "../../../../src/polymer-types";
|
||||||
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
@@ -79,8 +75,6 @@ interface FolderItem {
|
|||||||
class HassioSnapshotDialog extends LitElement {
|
class HassioSnapshotDialog extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor?: Supervisor;
|
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@internalProperty() private _error?: string;
|
||||||
|
|
||||||
@internalProperty() private _onboarding = false;
|
@internalProperty() private _onboarding = false;
|
||||||
@@ -95,7 +89,7 @@ class HassioSnapshotDialog extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _snapshotPassword!: string;
|
@internalProperty() private _snapshotPassword!: string;
|
||||||
|
|
||||||
@internalProperty() private _restoreHass = true;
|
@internalProperty() private _restoreHass: boolean | null | undefined = true;
|
||||||
|
|
||||||
public async showDialog(params: HassioSnapshotDialogParams) {
|
public async showDialog(params: HassioSnapshotDialogParams) {
|
||||||
this._snapshot = await fetchHassioSnapshotInfo(this.hass, params.slug);
|
this._snapshot = await fetchHassioSnapshotInfo(this.hass, params.slug);
|
||||||
@@ -108,10 +102,6 @@ class HassioSnapshotDialog extends LitElement {
|
|||||||
|
|
||||||
this._dialogParams = params;
|
this._dialogParams = params;
|
||||||
this._onboarding = params.onboarding ?? false;
|
this._onboarding = params.onboarding ?? false;
|
||||||
this.supervisor = params.supervisor;
|
|
||||||
if (!this._snapshot.homeassistant) {
|
|
||||||
this._restoreHass = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
@@ -137,17 +127,15 @@ class HassioSnapshotDialog extends LitElement {
|
|||||||
(${this._computeSize})<br />
|
(${this._computeSize})<br />
|
||||||
${this._formatDatetime(this._snapshot.date)}
|
${this._formatDatetime(this._snapshot.date)}
|
||||||
</div>
|
</div>
|
||||||
${this._snapshot.homeassistant
|
<div>Home Assistant:</div>
|
||||||
? html`<div>Home Assistant:</div>
|
|
||||||
<paper-checkbox
|
<paper-checkbox
|
||||||
.checked=${this._restoreHass}
|
.checked=${this._restoreHass}
|
||||||
@change="${(ev: Event) => {
|
@change="${(ev: Event) => {
|
||||||
this._restoreHass = (ev.target as PaperCheckboxElement).checked!;
|
this._restoreHass = (ev.target as PaperCheckboxElement).checked;
|
||||||
}}"
|
}}"
|
||||||
>
|
>
|
||||||
Home Assistant ${this._snapshot.homeassistant}
|
Home Assistant ${this._snapshot.homeassistant}
|
||||||
</paper-checkbox>`
|
</paper-checkbox>
|
||||||
: ""}
|
|
||||||
${this._folders.length
|
${this._folders.length
|
||||||
? html`
|
? html`
|
||||||
<div>Folders:</div>
|
<div>Folders:</div>
|
||||||
@@ -310,16 +298,6 @@ class HassioSnapshotDialog extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _partialRestoreClicked() {
|
private async _partialRestoreClicked() {
|
||||||
if (
|
|
||||||
this.supervisor !== undefined &&
|
|
||||||
this.supervisor.info.state !== "running"
|
|
||||||
) {
|
|
||||||
await showAlertDialog(this, {
|
|
||||||
title: "Could not restore snapshot",
|
|
||||||
text: `Restoring a snapshot is not possible right now because the system is in ${this.supervisor.info.state} state.`,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (
|
if (
|
||||||
!(await showConfirmationDialog(this, {
|
!(await showConfirmationDialog(this, {
|
||||||
title: "Are you sure you want partially to restore this snapshot?",
|
title: "Are you sure you want partially to restore this snapshot?",
|
||||||
@@ -339,7 +317,7 @@ class HassioSnapshotDialog extends LitElement {
|
|||||||
.map((folder) => folder.slug);
|
.map((folder) => folder.slug);
|
||||||
|
|
||||||
const data: {
|
const data: {
|
||||||
homeassistant: boolean;
|
homeassistant: boolean | null | undefined;
|
||||||
addons: any;
|
addons: any;
|
||||||
folders: any;
|
folders: any;
|
||||||
password?: string;
|
password?: string;
|
||||||
@@ -381,16 +359,6 @@ class HassioSnapshotDialog extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _fullRestoreClicked() {
|
private async _fullRestoreClicked() {
|
||||||
if (
|
|
||||||
this.supervisor !== undefined &&
|
|
||||||
this.supervisor.info.state !== "running"
|
|
||||||
) {
|
|
||||||
await showAlertDialog(this, {
|
|
||||||
title: "Could not restore snapshot",
|
|
||||||
text: `Restoring a snapshot is not possible right now because the system is in ${this.supervisor.info.state} state.`,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (
|
if (
|
||||||
!(await showConfirmationDialog(this, {
|
!(await showConfirmationDialog(this, {
|
||||||
title:
|
title:
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
|
|
||||||
export interface HassioSnapshotDialogParams {
|
export interface HassioSnapshotDialogParams {
|
||||||
slug: string;
|
slug: string;
|
||||||
onDelete?: () => void;
|
onDelete?: () => void;
|
||||||
onboarding?: boolean;
|
onboarding?: boolean;
|
||||||
supervisor?: Supervisor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const showHassioSnapshotDialog = (
|
export const showHassioSnapshotDialog = (
|
||||||
|
@@ -4,7 +4,6 @@ import {
|
|||||||
restartHassioAddon,
|
restartHassioAddon,
|
||||||
} from "../../../src/data/hassio/addon";
|
} from "../../../src/data/hassio/addon";
|
||||||
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
|
||||||
import {
|
import {
|
||||||
showAlertDialog,
|
showAlertDialog,
|
||||||
showConfirmationDialog,
|
showConfirmationDialog,
|
||||||
@@ -14,25 +13,20 @@ import { HomeAssistant } from "../../../src/types";
|
|||||||
export const suggestAddonRestart = async (
|
export const suggestAddonRestart = async (
|
||||||
element: LitElement,
|
element: LitElement,
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
supervisor: Supervisor,
|
|
||||||
addon: HassioAddonDetails
|
addon: HassioAddonDetails
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const confirmed = await showConfirmationDialog(element, {
|
const confirmed = await showConfirmationDialog(element, {
|
||||||
title: supervisor.localize("common.restart_name", "name", addon.name),
|
title: addon.name,
|
||||||
text: supervisor.localize("dialog.restart_addon.text"),
|
text: "Do you want to restart the add-on with your changes?",
|
||||||
confirmText: supervisor.localize("dialog.restart_addon.confirm_text"),
|
confirmText: "restart add-on",
|
||||||
dismissText: supervisor.localize("common.cancel"),
|
dismissText: "no",
|
||||||
});
|
});
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
try {
|
try {
|
||||||
await restartHassioAddon(hass, addon.slug);
|
await restartHassioAddon(hass, addon.slug);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(element, {
|
showAlertDialog(element, {
|
||||||
title: supervisor.localize(
|
title: "Failed to restart",
|
||||||
"common.failed_to_restart_name",
|
|
||||||
"name",
|
|
||||||
addon.name
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,203 +0,0 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
|
||||||
import {
|
|
||||||
css,
|
|
||||||
CSSResult,
|
|
||||||
customElement,
|
|
||||||
html,
|
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
|
||||||
TemplateResult,
|
|
||||||
} from "lit-element";
|
|
||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
|
||||||
import "../../../../src/components/ha-circular-progress";
|
|
||||||
import "../../../../src/components/ha-dialog";
|
|
||||||
import "../../../../src/components/ha-settings-row";
|
|
||||||
import "../../../../src/components/ha-svg-icon";
|
|
||||||
import "../../../../src/components/ha-switch";
|
|
||||||
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
|
||||||
import { createHassioPartialSnapshot } from "../../../../src/data/hassio/snapshot";
|
|
||||||
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
|
||||||
import { SupervisorDialogSupervisorUpdateParams } from "./show-dialog-update";
|
|
||||||
|
|
||||||
@customElement("dialog-supervisor-update")
|
|
||||||
class DialogSupervisorUpdate extends LitElement {
|
|
||||||
public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@internalProperty() private _opened = false;
|
|
||||||
|
|
||||||
@internalProperty() private _createSnapshot = true;
|
|
||||||
|
|
||||||
@internalProperty() private _action: "snapshot" | "update" | null = null;
|
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
|
||||||
|
|
||||||
@internalProperty()
|
|
||||||
private _dialogParams?: SupervisorDialogSupervisorUpdateParams;
|
|
||||||
|
|
||||||
public async showDialog(
|
|
||||||
params: SupervisorDialogSupervisorUpdateParams
|
|
||||||
): Promise<void> {
|
|
||||||
this._opened = true;
|
|
||||||
this._dialogParams = params;
|
|
||||||
await this.updateComplete;
|
|
||||||
}
|
|
||||||
|
|
||||||
public closeDialog(): void {
|
|
||||||
this._action = null;
|
|
||||||
this._createSnapshot = true;
|
|
||||||
this._error = undefined;
|
|
||||||
this._dialogParams = undefined;
|
|
||||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
|
||||||
}
|
|
||||||
|
|
||||||
public focus(): void {
|
|
||||||
this.updateComplete.then(() =>
|
|
||||||
(this.shadowRoot?.querySelector(
|
|
||||||
"[dialogInitialFocus]"
|
|
||||||
) as HTMLElement)?.focus()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
if (!this._dialogParams) {
|
|
||||||
return html``;
|
|
||||||
}
|
|
||||||
return html`
|
|
||||||
<ha-dialog .open=${this._opened} scrimClickAction escapeKeyAction>
|
|
||||||
${this._action === null
|
|
||||||
? html`<slot name="heading">
|
|
||||||
<h2 id="title" class="header_title">
|
|
||||||
${this._dialogParams.supervisor.localize(
|
|
||||||
"confirm.update.title",
|
|
||||||
"name",
|
|
||||||
this._dialogParams.name
|
|
||||||
)}
|
|
||||||
</h2>
|
|
||||||
</slot>
|
|
||||||
<div>
|
|
||||||
${this._dialogParams.supervisor.localize(
|
|
||||||
"confirm.update.text",
|
|
||||||
"name",
|
|
||||||
this._dialogParams.name,
|
|
||||||
"version",
|
|
||||||
this._dialogParams.version
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ha-settings-row>
|
|
||||||
<span slot="heading">
|
|
||||||
${this._dialogParams.supervisor.localize(
|
|
||||||
"dialog.update.snapshot"
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
<span slot="description">
|
|
||||||
${this._dialogParams.supervisor.localize(
|
|
||||||
"dialog.update.create_snapshot",
|
|
||||||
"name",
|
|
||||||
this._dialogParams.name
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
<ha-switch
|
|
||||||
.checked=${this._createSnapshot}
|
|
||||||
haptic
|
|
||||||
@click=${this._toggleSnapshot}
|
|
||||||
>
|
|
||||||
</ha-switch>
|
|
||||||
</ha-settings-row>
|
|
||||||
<mwc-button @click=${this.closeDialog} slot="secondaryAction">
|
|
||||||
${this._dialogParams.supervisor.localize("common.cancel")}
|
|
||||||
</mwc-button>
|
|
||||||
<mwc-button
|
|
||||||
.disabled=${this._error !== undefined}
|
|
||||||
@click=${this._update}
|
|
||||||
slot="primaryAction"
|
|
||||||
>
|
|
||||||
${this._dialogParams.supervisor.localize("common.update")}
|
|
||||||
</mwc-button>`
|
|
||||||
: html`<ha-circular-progress alt="Updating" size="large" active>
|
|
||||||
</ha-circular-progress>
|
|
||||||
<p class="progress-text">
|
|
||||||
${this._action === "update"
|
|
||||||
? this._dialogParams.supervisor.localize(
|
|
||||||
"dialog.update.updating",
|
|
||||||
"name",
|
|
||||||
this._dialogParams.name,
|
|
||||||
"version",
|
|
||||||
this._dialogParams.version
|
|
||||||
)
|
|
||||||
: this._dialogParams.supervisor.localize(
|
|
||||||
"dialog.update.snapshotting",
|
|
||||||
"name",
|
|
||||||
this._dialogParams.name
|
|
||||||
)}
|
|
||||||
</p>`}
|
|
||||||
${this._error ? html`<p class="error">${this._error}</p>` : ""}
|
|
||||||
</ha-dialog>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _toggleSnapshot() {
|
|
||||||
this._createSnapshot = !this._createSnapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _update() {
|
|
||||||
if (this._createSnapshot) {
|
|
||||||
this._action = "snapshot";
|
|
||||||
try {
|
|
||||||
await createHassioPartialSnapshot(
|
|
||||||
this.hass,
|
|
||||||
this._dialogParams!.snapshotParams
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
this._error = extractApiErrorMessage(err);
|
|
||||||
this._action = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._action = "update";
|
|
||||||
try {
|
|
||||||
await this._dialogParams!.updateHandler!();
|
|
||||||
} catch (err) {
|
|
||||||
this._error = extractApiErrorMessage(err);
|
|
||||||
this._action = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.closeDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
|
||||||
return [
|
|
||||||
haStyle,
|
|
||||||
haStyleDialog,
|
|
||||||
css`
|
|
||||||
.form {
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
ha-settings-row {
|
|
||||||
margin-top: 32px;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ha-circular-progress {
|
|
||||||
display: block;
|
|
||||||
margin: 32px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-text {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"dialog-supervisor-update": DialogSupervisorUpdate;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,21 +0,0 @@
|
|||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
|
|
||||||
export interface SupervisorDialogSupervisorUpdateParams {
|
|
||||||
supervisor: Supervisor;
|
|
||||||
name: string;
|
|
||||||
version: string;
|
|
||||||
snapshotParams: any;
|
|
||||||
updateHandler: () => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const showDialogSupervisorUpdate = (
|
|
||||||
element: HTMLElement,
|
|
||||||
dialogParams: SupervisorDialogSupervisorUpdateParams
|
|
||||||
): void => {
|
|
||||||
fireEvent(element, "show-dialog", {
|
|
||||||
dialogTag: "dialog-supervisor-update",
|
|
||||||
dialogImport: () => import("./dialog-supervisor-update"),
|
|
||||||
dialogParams,
|
|
||||||
});
|
|
||||||
};
|
|
@@ -1,7 +1,6 @@
|
|||||||
// Compat needs to be first import
|
|
||||||
import "../../src/resources/compatibility";
|
import "../../src/resources/compatibility";
|
||||||
import "../../src/resources/roboto";
|
|
||||||
import "../../src/resources/safari-14-attachshadow-patch";
|
import "../../src/resources/safari-14-attachshadow-patch";
|
||||||
|
import "../../src/resources/roboto";
|
||||||
import "./hassio-main";
|
import "./hassio-main";
|
||||||
|
|
||||||
const styleEl = document.createElement("style");
|
const styleEl = document.createElement("style");
|
||||||
|
@@ -1,21 +1,17 @@
|
|||||||
import { customElement, html, property, PropertyValues } from "lit-element";
|
import { html, PropertyValues, customElement, property } from "lit-element";
|
||||||
import { atLeastVersion } from "../../src/common/config/version";
|
import "./hassio-router";
|
||||||
|
import { HomeAssistant, Route } from "../../src/types";
|
||||||
|
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
|
||||||
import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element";
|
||||||
import { fireEvent } from "../../src/common/dom/fire_event";
|
import { fireEvent } from "../../src/common/dom/fire_event";
|
||||||
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
|
|
||||||
import { Supervisor } from "../../src/data/supervisor/supervisor";
|
|
||||||
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
|
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
|
||||||
import "../../src/layouts/hass-loading-screen";
|
import { atLeastVersion } from "../../src/common/config/version";
|
||||||
import { HomeAssistant, Route } from "../../src/types";
|
|
||||||
import "./hassio-router";
|
|
||||||
import { SupervisorBaseElement } from "./supervisor-base-element";
|
import { SupervisorBaseElement } from "./supervisor-base-element";
|
||||||
|
|
||||||
@customElement("hassio-main")
|
@customElement("hassio-main")
|
||||||
export class HassioMain extends SupervisorBaseElement {
|
export class HassioMain extends SupervisorBaseElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public panel!: HassioPanelInfo;
|
@property({ attribute: false }) public panel!: HassioPanelInfo;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
@@ -74,6 +70,9 @@ export class HassioMain extends SupervisorBaseElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
|
if (!this.supervisor || !this.hass) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
return html`
|
return html`
|
||||||
<hassio-router
|
<hassio-router
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
|
@@ -1,133 +0,0 @@
|
|||||||
import {
|
|
||||||
customElement,
|
|
||||||
html,
|
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
|
||||||
property,
|
|
||||||
TemplateResult,
|
|
||||||
} from "lit-element";
|
|
||||||
import { sanitizeUrl } from "@braintree/sanitize-url";
|
|
||||||
import {
|
|
||||||
createSearchParam,
|
|
||||||
extractSearchParamsObject,
|
|
||||||
} from "../../src/common/url/search-params";
|
|
||||||
import "../../src/layouts/hass-error-screen";
|
|
||||||
import {
|
|
||||||
ParamType,
|
|
||||||
Redirect,
|
|
||||||
Redirects,
|
|
||||||
} from "../../src/panels/my/ha-panel-my";
|
|
||||||
import { navigate } from "../../src/common/navigate";
|
|
||||||
import { HomeAssistant, Route } from "../../src/types";
|
|
||||||
import { Supervisor } from "../../src/data/supervisor/supervisor";
|
|
||||||
|
|
||||||
const REDIRECTS: Redirects = {
|
|
||||||
supervisor_logs: {
|
|
||||||
redirect: "/hassio/system",
|
|
||||||
},
|
|
||||||
supervisor_info: {
|
|
||||||
redirect: "/hassio/system",
|
|
||||||
},
|
|
||||||
supervisor_snapshots: {
|
|
||||||
redirect: "/hassio/snapshots",
|
|
||||||
},
|
|
||||||
supervisor_store: {
|
|
||||||
redirect: "/hassio/store",
|
|
||||||
},
|
|
||||||
supervisor: {
|
|
||||||
redirect: "/hassio/dashboard",
|
|
||||||
},
|
|
||||||
supervisor_addon: {
|
|
||||||
redirect: "/hassio/addon",
|
|
||||||
params: {
|
|
||||||
addon: "string",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
@customElement("hassio-my-redirect")
|
|
||||||
class HassioMyRedirect extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
|
||||||
|
|
||||||
@internalProperty() public _error?: TemplateResult | string;
|
|
||||||
|
|
||||||
connectedCallback() {
|
|
||||||
super.connectedCallback();
|
|
||||||
const path = this.route.path.substr(1);
|
|
||||||
const redirect = REDIRECTS[path];
|
|
||||||
|
|
||||||
if (!redirect) {
|
|
||||||
this._error = this.supervisor.localize(
|
|
||||||
"my.not_supported",
|
|
||||||
"link",
|
|
||||||
html`<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
href="https://my.home-assistant.io/faq.html#supported-pages"
|
|
||||||
>
|
|
||||||
${this.supervisor.localize("my.faq_link")}
|
|
||||||
</a>`
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url: string;
|
|
||||||
try {
|
|
||||||
url = this._createRedirectUrl(redirect);
|
|
||||||
} catch (err) {
|
|
||||||
this._error = this.supervisor.localize("my.error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
navigate(this, url, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
if (this._error) {
|
|
||||||
return html`<hass-error-screen
|
|
||||||
.error=${this._error}
|
|
||||||
></hass-error-screen>`;
|
|
||||||
}
|
|
||||||
return html``;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createRedirectUrl(redirect: Redirect): string {
|
|
||||||
const params = this._createRedirectParams(redirect);
|
|
||||||
return `${redirect.redirect}${params}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createRedirectParams(redirect: Redirect): string {
|
|
||||||
const params = extractSearchParamsObject();
|
|
||||||
if (!redirect.params && !Object.keys(params).length) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
const resultParams = {};
|
|
||||||
Object.entries(redirect.params || {}).forEach(([key, type]) => {
|
|
||||||
if (!params[key] || !this._checkParamType(type, params[key])) {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
resultParams[key] = params[key];
|
|
||||||
});
|
|
||||||
return `?${createSearchParam(resultParams)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _checkParamType(type: ParamType, value: string) {
|
|
||||||
if (type === "string") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (type === "url") {
|
|
||||||
return value && value === sanitizeUrl(value);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"hassio-my-redirect": HassioMyRedirect;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -7,10 +7,7 @@ import {
|
|||||||
property,
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import {
|
import { Supervisor } from "../../src/data/supervisor/supervisor";
|
||||||
Supervisor,
|
|
||||||
supervisorCollection,
|
|
||||||
} from "../../src/data/supervisor/supervisor";
|
|
||||||
import { HomeAssistant, Route } from "../../src/types";
|
import { HomeAssistant, Route } from "../../src/types";
|
||||||
import "./hassio-panel-router";
|
import "./hassio-panel-router";
|
||||||
|
|
||||||
@@ -25,17 +22,6 @@ class HassioPanel extends LitElement {
|
|||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (!this.hass) {
|
|
||||||
return html`<hass-loading-screen></hass-loading-screen>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
Object.keys(supervisorCollection).some(
|
|
||||||
(colllection) => !this.supervisor[colllection]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return html`<hass-loading-screen></hass-loading-screen>`;
|
|
||||||
}
|
|
||||||
return html`
|
return html`
|
||||||
<hassio-panel-router
|
<hassio-panel-router
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
|
@@ -23,7 +23,7 @@ class HassioRouter extends HassRouterPage {
|
|||||||
protected routerOptions: RouterOptions = {
|
protected routerOptions: RouterOptions = {
|
||||||
// Hass.io has a page with tabs, so we route all non-matching routes to it.
|
// Hass.io has a page with tabs, so we route all non-matching routes to it.
|
||||||
defaultPage: "dashboard",
|
defaultPage: "dashboard",
|
||||||
initialLoad: () => this._redirectIngress(),
|
initialLoad: () => this._fetchData(),
|
||||||
showLoading: true,
|
showLoading: true,
|
||||||
routes: {
|
routes: {
|
||||||
dashboard: {
|
dashboard: {
|
||||||
@@ -41,42 +41,32 @@ class HassioRouter extends HassRouterPage {
|
|||||||
tag: "hassio-ingress-view",
|
tag: "hassio-ingress-view",
|
||||||
load: () => import("./ingress-view/hassio-ingress-view"),
|
load: () => import("./ingress-view/hassio-ingress-view"),
|
||||||
},
|
},
|
||||||
_my_redirect: {
|
|
||||||
tag: "hassio-my-redirect",
|
|
||||||
load: () => import("./hassio-my-redirect"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
protected updatePageEl(el) {
|
protected updatePageEl(el) {
|
||||||
// the tabs page does its own routing so needs full route.
|
// the tabs page does its own routing so needs full route.
|
||||||
const hassioPanel = el.nodeName === "HASSIO-PANEL";
|
const route = el.nodeName === "HASSIO-PANEL" ? this.route : this.routeTail;
|
||||||
const route = hassioPanel ? this.route : this.routeTail;
|
|
||||||
|
|
||||||
if (hassioPanel && this.panel.config?.ingress) {
|
|
||||||
this._redirectIngress();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
el.hass = this.hass;
|
el.hass = this.hass;
|
||||||
|
el.supervisor = this.supervisor;
|
||||||
el.narrow = this.narrow;
|
el.narrow = this.narrow;
|
||||||
el.route = route;
|
el.route = route;
|
||||||
|
|
||||||
if (el.localName === "hassio-ingress-view") {
|
if (el.localName === "hassio-ingress-view") {
|
||||||
el.ingressPanel = this.panel.config && this.panel.config.ingress;
|
el.ingressPanel = this.panel.config && this.panel.config.ingress;
|
||||||
} else {
|
|
||||||
el.supervisor = this.supervisor;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _redirectIngress() {
|
private async _fetchData() {
|
||||||
if (this.panel.config && this.panel.config.ingress) {
|
if (this.panel.config && this.panel.config.ingress) {
|
||||||
this.route = {
|
this._redirectIngress(this.panel.config.ingress);
|
||||||
prefix: "/hassio",
|
|
||||||
path: `/ingress/${this.panel.config.ingress}`,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _redirectIngress(addonSlug: string) {
|
||||||
|
this.route = { prefix: "/hassio", path: `/ingress/${addonSlug}` };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@@ -3,22 +3,22 @@ import type { PageNavigation } from "../../src/layouts/hass-tabs-subpage";
|
|||||||
|
|
||||||
export const supervisorTabs: PageNavigation[] = [
|
export const supervisorTabs: PageNavigation[] = [
|
||||||
{
|
{
|
||||||
translationKey: "panel.dashboard",
|
name: "Dashboard",
|
||||||
path: `/hassio/dashboard`,
|
path: `/hassio/dashboard`,
|
||||||
iconPath: mdiViewDashboard,
|
iconPath: mdiViewDashboard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
translationKey: "panel.store",
|
name: "Add-on Store",
|
||||||
path: `/hassio/store`,
|
path: `/hassio/store`,
|
||||||
iconPath: mdiStore,
|
iconPath: mdiStore,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
translationKey: "panel.snapshots",
|
name: "Snapshots",
|
||||||
path: `/hassio/snapshots`,
|
path: `/hassio/snapshots`,
|
||||||
iconPath: mdiBackupRestore,
|
iconPath: mdiBackupRestore,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
translationKey: "panel.system",
|
name: "System",
|
||||||
path: `/hassio/system`,
|
path: `/hassio/system`,
|
||||||
iconPath: mdiCogs,
|
iconPath: mdiCogs,
|
||||||
},
|
},
|
||||||
|
@@ -1,17 +1,14 @@
|
|||||||
import { mdiMenu } from "@mdi/js";
|
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
|
internalProperty,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
|
||||||
import { navigate } from "../../../src/common/navigate";
|
|
||||||
import {
|
import {
|
||||||
fetchHassioAddonInfo,
|
fetchHassioAddonInfo,
|
||||||
HassioAddonDetails,
|
HassioAddonDetails,
|
||||||
@@ -20,10 +17,13 @@ import {
|
|||||||
createHassioSession,
|
createHassioSession,
|
||||||
validateHassioSession,
|
validateHassioSession,
|
||||||
} from "../../../src/data/hassio/ingress";
|
} from "../../../src/data/hassio/ingress";
|
||||||
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
|
|
||||||
import "../../../src/layouts/hass-loading-screen";
|
import "../../../src/layouts/hass-loading-screen";
|
||||||
import "../../../src/layouts/hass-subpage";
|
import "../../../src/layouts/hass-subpage";
|
||||||
import { HomeAssistant, Route } from "../../../src/types";
|
import { HomeAssistant, Route } from "../../../src/types";
|
||||||
|
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
|
||||||
|
import { navigate } from "../../../src/common/navigate";
|
||||||
|
import { mdiMenu } from "@mdi/js";
|
||||||
|
import { fireEvent } from "../../../src/common/dom/fire_event";
|
||||||
|
|
||||||
@customElement("hassio-ingress-view")
|
@customElement("hassio-ingress-view")
|
||||||
class HassioIngressView extends LitElement {
|
class HassioIngressView extends LitElement {
|
||||||
|
@@ -41,7 +41,6 @@ import {
|
|||||||
reloadHassioSnapshots,
|
reloadHassioSnapshots,
|
||||||
} from "../../../src/data/hassio/snapshot";
|
} from "../../../src/data/hassio/snapshot";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||||
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
|
|
||||||
import "../../../src/layouts/hass-tabs-subpage";
|
import "../../../src/layouts/hass-tabs-subpage";
|
||||||
import { PolymerChangedEvent } from "../../../src/polymer-types";
|
import { PolymerChangedEvent } from "../../../src/polymer-types";
|
||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
@@ -55,8 +54,8 @@ import { hassioStyle } from "../resources/hassio-style";
|
|||||||
|
|
||||||
interface CheckboxItem {
|
interface CheckboxItem {
|
||||||
slug: string;
|
slug: string;
|
||||||
|
name: string;
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
name?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@customElement("hassio-snapshots")
|
@customElement("hassio-snapshots")
|
||||||
@@ -84,12 +83,13 @@ class HassioSnapshots extends LitElement {
|
|||||||
@internalProperty() private _folderList: CheckboxItem[] = [
|
@internalProperty() private _folderList: CheckboxItem[] = [
|
||||||
{
|
{
|
||||||
slug: "homeassistant",
|
slug: "homeassistant",
|
||||||
|
name: "Home Assistant configuration",
|
||||||
checked: true,
|
checked: true,
|
||||||
},
|
},
|
||||||
{ slug: "ssl", checked: true },
|
{ slug: "ssl", name: "SSL", checked: true },
|
||||||
{ slug: "share", checked: true },
|
{ slug: "share", name: "Share", checked: true },
|
||||||
{ slug: "media", checked: true },
|
{ slug: "media", name: "Media", checked: true },
|
||||||
{ slug: "addons/local", checked: true },
|
{ slug: "addons/local", name: "Local add-ons", checked: true },
|
||||||
];
|
];
|
||||||
|
|
||||||
@internalProperty() private _error = "";
|
@internalProperty() private _error = "";
|
||||||
@@ -103,16 +103,13 @@ class HassioSnapshots extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<hass-tabs-subpage
|
<hass-tabs-subpage
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.localizeFunc=${this.supervisor.localize}
|
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
|
hassio
|
||||||
|
main-page
|
||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
.tabs=${supervisorTabs}
|
.tabs=${supervisorTabs}
|
||||||
main-page
|
|
||||||
supervisor
|
|
||||||
>
|
>
|
||||||
<span slot="header">
|
<span slot="header">Snapshots</span>
|
||||||
${this.supervisor.localize("panel.snapshots")}
|
|
||||||
</span>
|
|
||||||
<ha-button-menu
|
<ha-button-menu
|
||||||
corner="BOTTOM_START"
|
corner="BOTTOM_START"
|
||||||
slot="toolbar-icon"
|
slot="toolbar-icon"
|
||||||
@@ -122,50 +119,50 @@ class HassioSnapshots extends LitElement {
|
|||||||
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
||||||
</mwc-icon-button>
|
</mwc-icon-button>
|
||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("common.reload")}
|
Reload
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
${atLeastVersion(this.hass.config.version, 0, 116)
|
${atLeastVersion(this.hass.config.version, 0, 116)
|
||||||
? html`<mwc-list-item>
|
? html`<mwc-list-item>
|
||||||
${this.supervisor.localize("snapshot.upload_snapshot")}
|
Upload snapshot
|
||||||
</mwc-list-item>`
|
</mwc-list-item>`
|
||||||
: ""}
|
: ""}
|
||||||
</ha-button-menu>
|
</ha-button-menu>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h1>
|
<h1>
|
||||||
${this.supervisor.localize("snapshot.create_snapshot")}
|
Create Snapshot
|
||||||
</h1>
|
</h1>
|
||||||
<p class="description">
|
<p class="description">
|
||||||
${this.supervisor.localize("snapshot.description")}
|
Snapshots allow you to easily backup and restore all data of your
|
||||||
|
Home Assistant instance.
|
||||||
</p>
|
</p>
|
||||||
<div class="card-group">
|
<div class="card-group">
|
||||||
<ha-card>
|
<ha-card>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<paper-input
|
<paper-input
|
||||||
autofocus
|
autofocus
|
||||||
.label=${this.supervisor.localize("snapshot.name")}
|
label="Name"
|
||||||
name="snapshotName"
|
name="snapshotName"
|
||||||
.value=${this._snapshotName}
|
.value=${this._snapshotName}
|
||||||
@value-changed=${this._handleTextValueChanged}
|
@value-changed=${this._handleTextValueChanged}
|
||||||
></paper-input>
|
></paper-input>
|
||||||
${this.supervisor.localize("snapshot.type")}:
|
Type:
|
||||||
<paper-radio-group
|
<paper-radio-group
|
||||||
name="snapshotType"
|
name="snapshotType"
|
||||||
type="${this.supervisor.localize("snapshot.type")}"
|
|
||||||
.selected=${this._snapshotType}
|
.selected=${this._snapshotType}
|
||||||
@selected-changed=${this._handleRadioValueChanged}
|
@selected-changed=${this._handleRadioValueChanged}
|
||||||
>
|
>
|
||||||
<paper-radio-button name="full">
|
<paper-radio-button name="full">
|
||||||
${this.supervisor.localize("snapshot.full_snapshot")}
|
Full snapshot
|
||||||
</paper-radio-button>
|
</paper-radio-button>
|
||||||
<paper-radio-button name="partial">
|
<paper-radio-button name="partial">
|
||||||
${this.supervisor.localize("snapshot.partial_snapshot")}
|
Partial snapshot
|
||||||
</paper-radio-button>
|
</paper-radio-button>
|
||||||
</paper-radio-group>
|
</paper-radio-group>
|
||||||
${this._snapshotType === "full"
|
${this._snapshotType === "full"
|
||||||
? undefined
|
? undefined
|
||||||
: html`
|
: html`
|
||||||
${this.supervisor.localize("snapshot.folders")}:
|
Folders:
|
||||||
${this._folderList.map(
|
${this._folderList.map(
|
||||||
(folder, idx) => html`
|
(folder, idx) => html`
|
||||||
<paper-checkbox
|
<paper-checkbox
|
||||||
@@ -173,13 +170,11 @@ class HassioSnapshots extends LitElement {
|
|||||||
.checked=${folder.checked}
|
.checked=${folder.checked}
|
||||||
@checked-changed=${this._folderChecked}
|
@checked-changed=${this._folderChecked}
|
||||||
>
|
>
|
||||||
${this.supervisor.localize(
|
${folder.name}
|
||||||
`snapshot.folder.${folder.slug}`
|
|
||||||
)}
|
|
||||||
</paper-checkbox>
|
</paper-checkbox>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
${this.supervisor.localize("snapshot.addons")}:
|
Add-ons:
|
||||||
${this._addonList.map(
|
${this._addonList.map(
|
||||||
(addon, idx) => html`
|
(addon, idx) => html`
|
||||||
<paper-checkbox
|
<paper-checkbox
|
||||||
@@ -192,18 +187,18 @@ class HassioSnapshots extends LitElement {
|
|||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
`}
|
`}
|
||||||
${this.supervisor.localize("snapshot.security")}:
|
Security:
|
||||||
<paper-checkbox
|
<paper-checkbox
|
||||||
name="snapshotHasPassword"
|
name="snapshotHasPassword"
|
||||||
.checked=${this._snapshotHasPassword}
|
.checked=${this._snapshotHasPassword}
|
||||||
@checked-changed=${this._handleCheckboxValueChanged}
|
@checked-changed=${this._handleCheckboxValueChanged}
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("snapshot.password_protection")}
|
Password protection
|
||||||
</paper-checkbox>
|
</paper-checkbox>
|
||||||
${this._snapshotHasPassword
|
${this._snapshotHasPassword
|
||||||
? html`
|
? html`
|
||||||
<paper-input
|
<paper-input
|
||||||
.label=${this.supervisor.localize("snapshot.password")}
|
label="Password"
|
||||||
type="password"
|
type="password"
|
||||||
name="snapshotPassword"
|
name="snapshotPassword"
|
||||||
.value=${this._snapshotPassword}
|
.value=${this._snapshotPassword}
|
||||||
@@ -216,24 +211,14 @@ class HassioSnapshots extends LitElement {
|
|||||||
: undefined}
|
: undefined}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<ha-progress-button
|
<ha-progress-button @click=${this._createSnapshot}>
|
||||||
@click=${this._createSnapshot}
|
Create
|
||||||
.title=${this.supervisor.info.state !== "running"
|
|
||||||
? this.supervisor.localize(
|
|
||||||
"snapshot.create_blocked_not_running",
|
|
||||||
"state",
|
|
||||||
this.supervisor.info.state
|
|
||||||
)
|
|
||||||
: ""}
|
|
||||||
.disabled=${this.supervisor.info.state !== "running"}
|
|
||||||
>
|
|
||||||
${this.supervisor.localize("snapshot.create")}
|
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1>${this.supervisor.localize("snapshot.available_snapshots")}</h1>
|
<h1>Available Snapshots</h1>
|
||||||
<div class="card-group">
|
<div class="card-group">
|
||||||
${this._snapshots === undefined
|
${this._snapshots === undefined
|
||||||
? undefined
|
? undefined
|
||||||
@@ -241,7 +226,7 @@ class HassioSnapshots extends LitElement {
|
|||||||
? html`
|
? html`
|
||||||
<ha-card>
|
<ha-card>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
${this.supervisor.localize("snapshot.no_snapshots")}
|
You don't have any snapshots yet.
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`
|
`
|
||||||
@@ -279,7 +264,7 @@ class HassioSnapshots extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues) {
|
protected updated(changedProps: PropertyValues) {
|
||||||
if (changedProps.has("supervisor")) {
|
if (changedProps.has("supervisorInfo")) {
|
||||||
this._addonList = this.supervisor.supervisor.addons
|
this._addonList = this.supervisor.supervisor.addons
|
||||||
.map((addon) => ({
|
.map((addon) => ({
|
||||||
slug: addon.slug,
|
slug: addon.slug,
|
||||||
@@ -340,22 +325,12 @@ class HassioSnapshots extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _createSnapshot(ev: CustomEvent): Promise<void> {
|
private async _createSnapshot(ev: CustomEvent): Promise<void> {
|
||||||
if (this.supervisor.info.state !== "running") {
|
|
||||||
await showAlertDialog(this, {
|
|
||||||
title: this.supervisor.localize("snapshot.could_not_create"),
|
|
||||||
text: this.supervisor.localize(
|
|
||||||
"snapshot.create_blocked_not_running",
|
|
||||||
"state",
|
|
||||||
this.supervisor.info.state
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const button = ev.currentTarget as any;
|
const button = ev.currentTarget as any;
|
||||||
button.progress = true;
|
button.progress = true;
|
||||||
|
|
||||||
this._error = "";
|
this._error = "";
|
||||||
if (this._snapshotHasPassword && !this._snapshotPassword.length) {
|
if (this._snapshotHasPassword && !this._snapshotPassword.length) {
|
||||||
this._error = this.supervisor.localize("snapshot.enter_password");
|
this._error = "Please enter a password.";
|
||||||
button.progress = false;
|
button.progress = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -404,16 +379,13 @@ class HassioSnapshots extends LitElement {
|
|||||||
|
|
||||||
private _computeDetails(snapshot: HassioSnapshot) {
|
private _computeDetails(snapshot: HassioSnapshot) {
|
||||||
const type =
|
const type =
|
||||||
snapshot.type === "full"
|
snapshot.type === "full" ? "Full snapshot" : "Partial snapshot";
|
||||||
? this.supervisor.localize("snapshot.full_snapshot")
|
|
||||||
: this.supervisor.localize("snapshot.partial_snapshot");
|
|
||||||
return snapshot.protected ? `${type}, password protected` : type;
|
return snapshot.protected ? `${type}, password protected` : type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _snapshotClicked(ev) {
|
private _snapshotClicked(ev) {
|
||||||
showHassioSnapshotDialog(this, {
|
showHassioSnapshotDialog(this, {
|
||||||
slug: ev.currentTarget!.snapshot.slug,
|
slug: ev.currentTarget!.snapshot.slug,
|
||||||
supervisor: this.supervisor,
|
|
||||||
onDelete: () => this._updateSnapshots(),
|
onDelete: () => this._updateSnapshots(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -423,7 +395,6 @@ class HassioSnapshots extends LitElement {
|
|||||||
showSnapshot: (slug: string) =>
|
showSnapshot: (slug: string) =>
|
||||||
showHassioSnapshotDialog(this, {
|
showHassioSnapshotDialog(this, {
|
||||||
slug,
|
slug,
|
||||||
supervisor: this.supervisor,
|
|
||||||
onDelete: () => this._updateSnapshots(),
|
onDelete: () => this._updateSnapshots(),
|
||||||
}),
|
}),
|
||||||
reloadSnapshot: () => this.refreshData(),
|
reloadSnapshot: () => this.refreshData(),
|
||||||
|
@@ -1,14 +1,4 @@
|
|||||||
import { Collection, UnsubscribeFunc } from "home-assistant-js-websocket";
|
import { LitElement, property, PropertyValues } from "lit-element";
|
||||||
import {
|
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
|
||||||
property,
|
|
||||||
PropertyValues,
|
|
||||||
} from "lit-element";
|
|
||||||
import { atLeastVersion } from "../../src/common/config/version";
|
|
||||||
import { computeLocalize } from "../../src/common/translations/localize";
|
|
||||||
import { fetchHassioAddonsInfo } from "../../src/data/hassio/addon";
|
|
||||||
import { HassioResponse } from "../../src/data/hassio/common";
|
|
||||||
import {
|
import {
|
||||||
fetchHassioHassOsInfo,
|
fetchHassioHassOsInfo,
|
||||||
fetchHassioHostInfo,
|
fetchHassioHostInfo,
|
||||||
@@ -20,151 +10,35 @@ import {
|
|||||||
fetchHassioInfo,
|
fetchHassioInfo,
|
||||||
fetchHassioSupervisorInfo,
|
fetchHassioSupervisorInfo,
|
||||||
} from "../../src/data/hassio/supervisor";
|
} from "../../src/data/hassio/supervisor";
|
||||||
import { fetchSupervisorStore } from "../../src/data/supervisor/store";
|
import { Supervisor } from "../../src/data/supervisor/supervisor";
|
||||||
import {
|
|
||||||
getSupervisorEventCollection,
|
|
||||||
subscribeSupervisorEvents,
|
|
||||||
Supervisor,
|
|
||||||
SupervisorObject,
|
|
||||||
supervisorCollection,
|
|
||||||
} from "../../src/data/supervisor/supervisor";
|
|
||||||
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
|
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
|
||||||
import { urlSyncMixin } from "../../src/state/url-sync-mixin";
|
import { urlSyncMixin } from "../../src/state/url-sync-mixin";
|
||||||
import { getTranslation } from "../../src/util/common-translation";
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"supervisor-update": Partial<Supervisor>;
|
"supervisor-update": Partial<Supervisor>;
|
||||||
"supervisor-colllection-refresh": { colllection: SupervisorObject };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SupervisorBaseElement extends urlSyncMixin(
|
export class SupervisorBaseElement extends urlSyncMixin(
|
||||||
ProvideHassLitMixin(LitElement)
|
ProvideHassLitMixin(LitElement)
|
||||||
) {
|
) {
|
||||||
@property({ attribute: false }) public supervisor: Partial<Supervisor> = {
|
@property({ attribute: false }) public supervisor?: Supervisor;
|
||||||
localize: () => "",
|
|
||||||
};
|
|
||||||
|
|
||||||
@internalProperty() private _unsubs: Record<string, UnsubscribeFunc> = {};
|
|
||||||
|
|
||||||
@internalProperty() private _collections: Record<
|
|
||||||
string,
|
|
||||||
Collection<unknown>
|
|
||||||
> = {};
|
|
||||||
|
|
||||||
@internalProperty() private _resources?: Record<string, any>;
|
|
||||||
|
|
||||||
@internalProperty() private _language = "en";
|
|
||||||
|
|
||||||
public connectedCallback(): void {
|
|
||||||
super.connectedCallback();
|
|
||||||
this._initializeLocalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public disconnectedCallback() {
|
|
||||||
super.disconnectedCallback();
|
|
||||||
Object.keys(this._unsubs).forEach((unsub) => {
|
|
||||||
this._unsubs[unsub]();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected updated(changedProperties: PropertyValues) {
|
|
||||||
super.updated(changedProperties);
|
|
||||||
|
|
||||||
if (changedProperties.has("_language")) {
|
|
||||||
if (changedProperties.get("_language") !== this._language) {
|
|
||||||
this._initializeLocalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _updateSupervisor(obj: Partial<Supervisor>): void {
|
protected _updateSupervisor(obj: Partial<Supervisor>): void {
|
||||||
this.supervisor = { ...this.supervisor, ...obj };
|
this.supervisor = { ...this.supervisor!, ...obj };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(changedProps: PropertyValues): void {
|
protected firstUpdated(changedProps: PropertyValues): void {
|
||||||
super.firstUpdated(changedProps);
|
super.firstUpdated(changedProps);
|
||||||
if (this._language !== this.hass.language) {
|
|
||||||
this._language = this.hass.language;
|
|
||||||
}
|
|
||||||
this._initializeLocalize();
|
|
||||||
this._initSupervisor();
|
this._initSupervisor();
|
||||||
}
|
this.addEventListener("supervisor-update", (ev) =>
|
||||||
|
this._updateSupervisor(ev.detail)
|
||||||
private async _initializeLocalize() {
|
|
||||||
const { language, data } = await getTranslation(
|
|
||||||
null,
|
|
||||||
this._language,
|
|
||||||
"/api/hassio/app/static/translations"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this._resources = {
|
|
||||||
[language]: data,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.supervisor = {
|
|
||||||
...this.supervisor,
|
|
||||||
localize: await computeLocalize(
|
|
||||||
this.constructor.prototype,
|
|
||||||
this._language,
|
|
||||||
this._resources
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _handleSupervisorStoreRefreshEvent(ev) {
|
|
||||||
const colllection = ev.detail.colllection;
|
|
||||||
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
|
||||||
this._collections[colllection].refresh();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.hass.callApi<HassioResponse<any>>(
|
|
||||||
"GET",
|
|
||||||
`hassio${supervisorCollection[colllection]}`
|
|
||||||
);
|
|
||||||
this._updateSupervisor({ [colllection]: response.data });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _initSupervisor(): Promise<void> {
|
private async _initSupervisor(): Promise<void> {
|
||||||
this.addEventListener(
|
|
||||||
"supervisor-colllection-refresh",
|
|
||||||
this._handleSupervisorStoreRefreshEvent
|
|
||||||
);
|
|
||||||
|
|
||||||
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
|
||||||
Object.keys(supervisorCollection).forEach((colllection) => {
|
|
||||||
this._unsubs[colllection] = subscribeSupervisorEvents(
|
|
||||||
this.hass,
|
|
||||||
(data) => this._updateSupervisor({ [colllection]: data }),
|
|
||||||
colllection,
|
|
||||||
supervisorCollection[colllection]
|
|
||||||
);
|
|
||||||
if (this._collections[colllection]) {
|
|
||||||
this._collections[colllection].refresh();
|
|
||||||
} else {
|
|
||||||
this._collections[colllection] = getSupervisorEventCollection(
|
|
||||||
this.hass.connection,
|
|
||||||
colllection,
|
|
||||||
supervisorCollection[colllection]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(this._collections).forEach((collection) => {
|
|
||||||
if (
|
|
||||||
this.supervisor === undefined ||
|
|
||||||
this.supervisor[collection] === undefined
|
|
||||||
) {
|
|
||||||
this._updateSupervisor({
|
|
||||||
[collection]: this._collections[collection].state,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const [
|
const [
|
||||||
addon,
|
|
||||||
supervisor,
|
supervisor,
|
||||||
host,
|
host,
|
||||||
core,
|
core,
|
||||||
@@ -172,9 +46,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
os,
|
os,
|
||||||
network,
|
network,
|
||||||
resolution,
|
resolution,
|
||||||
store,
|
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
fetchHassioAddonsInfo(this.hass),
|
|
||||||
fetchHassioSupervisorInfo(this.hass),
|
fetchHassioSupervisorInfo(this.hass),
|
||||||
fetchHassioHostInfo(this.hass),
|
fetchHassioHostInfo(this.hass),
|
||||||
fetchHassioHomeAssistantInfo(this.hass),
|
fetchHassioHomeAssistantInfo(this.hass),
|
||||||
@@ -182,11 +54,9 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
fetchHassioHassOsInfo(this.hass),
|
fetchHassioHassOsInfo(this.hass),
|
||||||
fetchNetworkInfo(this.hass),
|
fetchNetworkInfo(this.hass),
|
||||||
fetchHassioResolution(this.hass),
|
fetchHassioResolution(this.hass),
|
||||||
fetchSupervisorStore(this.hass),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this._updateSupervisor({
|
this.supervisor = {
|
||||||
addon,
|
|
||||||
supervisor,
|
supervisor,
|
||||||
host,
|
host,
|
||||||
core,
|
core,
|
||||||
@@ -194,12 +64,6 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
os,
|
os,
|
||||||
network,
|
network,
|
||||||
resolution,
|
resolution,
|
||||||
store,
|
};
|
||||||
});
|
|
||||||
|
|
||||||
this.addEventListener("supervisor-update", (ev) =>
|
|
||||||
this._updateSupervisor(ev.detail)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,259 +0,0 @@
|
|||||||
import "@material/mwc-button";
|
|
||||||
import "@material/mwc-list/mwc-list-item";
|
|
||||||
import {
|
|
||||||
css,
|
|
||||||
CSSResult,
|
|
||||||
customElement,
|
|
||||||
html,
|
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
|
||||||
property,
|
|
||||||
TemplateResult,
|
|
||||||
} from "lit-element";
|
|
||||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
|
||||||
import "../../../src/components/buttons/ha-progress-button";
|
|
||||||
import "../../../src/components/ha-button-menu";
|
|
||||||
import "../../../src/components/ha-card";
|
|
||||||
import "../../../src/components/ha-settings-row";
|
|
||||||
import {
|
|
||||||
extractApiErrorMessage,
|
|
||||||
fetchHassioStats,
|
|
||||||
HassioStats,
|
|
||||||
} from "../../../src/data/hassio/common";
|
|
||||||
import { restartCore, updateCore } from "../../../src/data/supervisor/core";
|
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
|
||||||
import {
|
|
||||||
showAlertDialog,
|
|
||||||
showConfirmationDialog,
|
|
||||||
} from "../../../src/dialogs/generic/show-dialog-box";
|
|
||||||
import { haStyle } from "../../../src/resources/styles";
|
|
||||||
import { HomeAssistant } from "../../../src/types";
|
|
||||||
import { bytesToString } from "../../../src/util/bytes-to-string";
|
|
||||||
import "../components/supervisor-metric";
|
|
||||||
import { showDialogSupervisorUpdate } from "../dialogs/update/show-dialog-update";
|
|
||||||
import { hassioStyle } from "../resources/hassio-style";
|
|
||||||
|
|
||||||
@customElement("hassio-core-info")
|
|
||||||
class HassioCoreInfo extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@internalProperty() private _metrics?: HassioStats;
|
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
|
||||||
const metrics = [
|
|
||||||
{
|
|
||||||
description: this.supervisor.localize("system.core.cpu_usage"),
|
|
||||||
value: this._metrics?.cpu_percent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: this.supervisor.localize("system.core.ram_usage"),
|
|
||||||
value: this._metrics?.memory_percent,
|
|
||||||
tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString(
|
|
||||||
this._metrics?.memory_limit
|
|
||||||
)}`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<ha-card header="Core">
|
|
||||||
<div class="card-content">
|
|
||||||
<div>
|
|
||||||
<ha-settings-row>
|
|
||||||
<span slot="heading">
|
|
||||||
${this.supervisor.localize("common.version")}
|
|
||||||
</span>
|
|
||||||
<span slot="description">
|
|
||||||
core-${this.supervisor.core.version}
|
|
||||||
</span>
|
|
||||||
</ha-settings-row>
|
|
||||||
<ha-settings-row>
|
|
||||||
<span slot="heading">
|
|
||||||
${this.supervisor.localize("common.newest_version")}
|
|
||||||
</span>
|
|
||||||
<span slot="description">
|
|
||||||
core-${this.supervisor.core.version_latest}
|
|
||||||
</span>
|
|
||||||
${this.supervisor.core.update_available
|
|
||||||
? html`
|
|
||||||
<ha-progress-button
|
|
||||||
.title=${this.supervisor.localize("common.update")}
|
|
||||||
@click=${this._coreUpdate}
|
|
||||||
>
|
|
||||||
${this.supervisor.localize("common.update")}
|
|
||||||
</ha-progress-button>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
</ha-settings-row>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
${metrics.map(
|
|
||||||
(metric) =>
|
|
||||||
html`
|
|
||||||
<supervisor-metric
|
|
||||||
.description=${metric.description}
|
|
||||||
.value=${metric.value ?? 0}
|
|
||||||
.tooltip=${metric.tooltip}
|
|
||||||
></supervisor-metric>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-actions">
|
|
||||||
<ha-progress-button
|
|
||||||
slot="primaryAction"
|
|
||||||
class="warning"
|
|
||||||
@click=${this._coreRestart}
|
|
||||||
.title=${this.supervisor.localize(
|
|
||||||
"common.restart_name",
|
|
||||||
"name",
|
|
||||||
"Core"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
${this.supervisor.localize("common.restart_name", "name", "Core")}
|
|
||||||
</ha-progress-button>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected firstUpdated(): void {
|
|
||||||
this._loadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _loadData(): Promise<void> {
|
|
||||||
this._metrics = await fetchHassioStats(this.hass, "core");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _coreRestart(ev: CustomEvent): Promise<void> {
|
|
||||||
const button = ev.currentTarget as any;
|
|
||||||
button.progress = true;
|
|
||||||
|
|
||||||
const confirmed = await showConfirmationDialog(this, {
|
|
||||||
title: this.supervisor.localize(
|
|
||||||
"confirm.restart.title",
|
|
||||||
"name",
|
|
||||||
"Home Assistant Core"
|
|
||||||
),
|
|
||||||
text: this.supervisor.localize(
|
|
||||||
"confirm.restart.text",
|
|
||||||
"name",
|
|
||||||
"Home Assistant Core"
|
|
||||||
),
|
|
||||||
confirmText: this.supervisor.localize("common.restart"),
|
|
||||||
dismissText: this.supervisor.localize("common.cancel"),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!confirmed) {
|
|
||||||
button.progress = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await restartCore(this.hass);
|
|
||||||
} catch (err) {
|
|
||||||
if (this.hass.connection.connected) {
|
|
||||||
showAlertDialog(this, {
|
|
||||||
title: this.supervisor.localize(
|
|
||||||
"common.failed_to_restart_name",
|
|
||||||
"name",
|
|
||||||
"Home AssistantCore"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
button.progress = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _coreUpdate(): Promise<void> {
|
|
||||||
showDialogSupervisorUpdate(this, {
|
|
||||||
supervisor: this.supervisor,
|
|
||||||
name: "Home Assistant Core",
|
|
||||||
version: this.supervisor.core.version,
|
|
||||||
snapshotParams: {
|
|
||||||
name: `core_${this.supervisor.core.version}`,
|
|
||||||
folders: ["homeassistant"],
|
|
||||||
homeassistant: true,
|
|
||||||
},
|
|
||||||
updateHandler: async () => await this._updateCore(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _updateCore(): Promise<void> {
|
|
||||||
await updateCore(this.hass);
|
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
|
||||||
colllection: "core",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
|
||||||
return [
|
|
||||||
haStyle,
|
|
||||||
hassioStyle,
|
|
||||||
css`
|
|
||||||
ha-card {
|
|
||||||
height: 100%;
|
|
||||||
justify-content: space-between;
|
|
||||||
flex-direction: column;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.card-actions {
|
|
||||||
height: 48px;
|
|
||||||
border-top: none;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.card-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: calc(100% - 124px);
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
ha-settings-row {
|
|
||||||
padding: 0;
|
|
||||||
height: 54px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
ha-settings-row[three-line] {
|
|
||||||
height: 74px;
|
|
||||||
}
|
|
||||||
ha-settings-row > span[slot="description"] {
|
|
||||||
white-space: normal;
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning {
|
|
||||||
--mdc-theme-primary: var(--error-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
ha-button-menu {
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
--mdc-menu-min-width: 200px;
|
|
||||||
}
|
|
||||||
@media (min-width: 563px) {
|
|
||||||
paper-listbox {
|
|
||||||
max-height: 150px;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
paper-item {
|
|
||||||
cursor: pointer;
|
|
||||||
min-height: 35px;
|
|
||||||
}
|
|
||||||
mwc-list-item ha-svg-icon {
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"hassio-core-info": HassioCoreInfo;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -13,7 +13,6 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
|
||||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../src/common/dom/fire_event";
|
||||||
import "../../../src/components/buttons/ha-progress-button";
|
import "../../../src/components/buttons/ha-progress-button";
|
||||||
import "../../../src/components/ha-button-menu";
|
import "../../../src/components/ha-button-menu";
|
||||||
@@ -27,6 +26,7 @@ import { fetchHassioHardwareInfo } from "../../../src/data/hassio/hardware";
|
|||||||
import {
|
import {
|
||||||
changeHostOptions,
|
changeHostOptions,
|
||||||
configSyncOS,
|
configSyncOS,
|
||||||
|
fetchHassioHostInfo,
|
||||||
rebootHost,
|
rebootHost,
|
||||||
shutdownHost,
|
shutdownHost,
|
||||||
updateOS,
|
updateOS,
|
||||||
@@ -43,11 +43,6 @@ import {
|
|||||||
} from "../../../src/dialogs/generic/show-dialog-box";
|
} from "../../../src/dialogs/generic/show-dialog-box";
|
||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
import {
|
|
||||||
getValueInPercentage,
|
|
||||||
roundWithOneDecimal,
|
|
||||||
} from "../../../src/util/calculate";
|
|
||||||
import "../components/supervisor-metric";
|
|
||||||
import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown";
|
import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown";
|
||||||
import { showNetworkDialog } from "../dialogs/network/show-dialog-network";
|
import { showNetworkDialog } from "../dialogs/network/show-dialog-network";
|
||||||
import { hassioStyle } from "../resources/hassio-style";
|
import { hassioStyle } from "../resources/hassio-style";
|
||||||
@@ -62,31 +57,20 @@ class HassioHostInfo extends LitElement {
|
|||||||
const primaryIpAddress = this.supervisor.host.features.includes("network")
|
const primaryIpAddress = this.supervisor.host.features.includes("network")
|
||||||
? this._primaryIpAddress(this.supervisor.network!)
|
? this._primaryIpAddress(this.supervisor.network!)
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
const metrics = [
|
|
||||||
{
|
|
||||||
description: this.supervisor.localize("system.host.used_space"),
|
|
||||||
value: this._getUsedSpace(
|
|
||||||
this.supervisor.host.disk_used,
|
|
||||||
this.supervisor.host.disk_total
|
|
||||||
),
|
|
||||||
tooltip: `${this.supervisor.host.disk_used} GB/${this.supervisor.host.disk_total} GB`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return html`
|
return html`
|
||||||
<ha-card header="Host">
|
<ha-card header="Host System">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div>
|
|
||||||
${this.supervisor.host.features.includes("hostname")
|
${this.supervisor.host.features.includes("hostname")
|
||||||
? html`<ha-settings-row>
|
? html`<ha-settings-row>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize("system.host.hostname")}
|
Hostname
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.host.hostname}
|
${this.supervisor.host.hostname}
|
||||||
</span>
|
</span>
|
||||||
<mwc-button
|
<mwc-button
|
||||||
.label=${this.supervisor.localize("system.host.change")}
|
title="Change the hostname"
|
||||||
|
label="Change"
|
||||||
@click=${this._changeHostnameClicked}
|
@click=${this._changeHostnameClicked}
|
||||||
>
|
>
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
@@ -95,13 +79,14 @@ class HassioHostInfo extends LitElement {
|
|||||||
${this.supervisor.host.features.includes("network")
|
${this.supervisor.host.features.includes("network")
|
||||||
? html` <ha-settings-row>
|
? html` <ha-settings-row>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize("system.host.ip_address")}
|
IP Address
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${primaryIpAddress}
|
${primaryIpAddress}
|
||||||
</span>
|
</span>
|
||||||
<mwc-button
|
<mwc-button
|
||||||
.label=${this.supervisor.localize("system.host.change")}
|
title="Change the network"
|
||||||
|
label="Change"
|
||||||
@click=${this._changeNetworkClicked}
|
@click=${this._changeNetworkClicked}
|
||||||
>
|
>
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
@@ -110,15 +95,18 @@ class HassioHostInfo extends LitElement {
|
|||||||
|
|
||||||
<ha-settings-row>
|
<ha-settings-row>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize("system.host.operating_system")}
|
Operating System
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.host.operating_system}
|
${this.supervisor.host.operating_system}
|
||||||
</span>
|
</span>
|
||||||
${this.supervisor.os.update_available
|
${this.supervisor.os.update_available
|
||||||
? html`
|
? html`
|
||||||
<ha-progress-button @click=${this._osUpdate}>
|
<ha-progress-button
|
||||||
${this.supervisor.localize("commmon.update")}
|
title="Update the host OS"
|
||||||
|
@click=${this._osUpdate}
|
||||||
|
>
|
||||||
|
Update
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -126,7 +114,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
${!this.supervisor.host.features.includes("hassos")
|
${!this.supervisor.host.features.includes("hassos")
|
||||||
? html`<ha-settings-row>
|
? html`<ha-settings-row>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize("system.host.docker_version")}
|
Docker version
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.info.docker}
|
${this.supervisor.info.docker}
|
||||||
@@ -136,7 +124,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
${this.supervisor.host.deployment
|
${this.supervisor.host.deployment
|
||||||
? html`<ha-settings-row>
|
? html`<ha-settings-row>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize("system.host.deployment")}
|
Deployment
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.host.deployment}
|
${this.supervisor.host.deployment}
|
||||||
@@ -144,48 +132,26 @@ class HassioHostInfo extends LitElement {
|
|||||||
</ha-settings-row>`
|
</ha-settings-row>`
|
||||||
: ""}
|
: ""}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
${this.supervisor.host.disk_life_time !== "" &&
|
|
||||||
this.supervisor.host.disk_life_time >= 10
|
|
||||||
? html` <ha-settings-row>
|
|
||||||
<span slot="heading">
|
|
||||||
${this.supervisor.localize(
|
|
||||||
"system.host.emmc_lifetime_used"
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
<span slot="description">
|
|
||||||
${this.supervisor.host.disk_life_time - 10}% -
|
|
||||||
${this.supervisor.host.disk_life_time}%
|
|
||||||
</span>
|
|
||||||
</ha-settings-row>`
|
|
||||||
: ""}
|
|
||||||
${metrics.map(
|
|
||||||
(metric) =>
|
|
||||||
html`
|
|
||||||
<supervisor-metric
|
|
||||||
.description=${metric.description}
|
|
||||||
.value=${metric.value ?? 0}
|
|
||||||
.tooltip=${metric.tooltip}
|
|
||||||
></supervisor-metric>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
${this.supervisor.host.features.includes("reboot")
|
${this.supervisor.host.features.includes("reboot")
|
||||||
? html`
|
? html`
|
||||||
<ha-progress-button class="warning" @click=${this._hostReboot}>
|
<ha-progress-button
|
||||||
${this.supervisor.localize("system.host.reboot_host")}
|
title="Reboot the host OS"
|
||||||
|
class="warning"
|
||||||
|
@click=${this._hostReboot}
|
||||||
|
>
|
||||||
|
Reboot
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
${this.supervisor.host.features.includes("shutdown")
|
${this.supervisor.host.features.includes("shutdown")
|
||||||
? html`
|
? html`
|
||||||
<ha-progress-button
|
<ha-progress-button
|
||||||
|
title="Shutdown the host OS"
|
||||||
class="warning"
|
class="warning"
|
||||||
@click=${this._hostShutdown}
|
@click=${this._hostShutdown}
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("system.host.shutdown_host")}
|
Shutdown
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -197,12 +163,14 @@ class HassioHostInfo extends LitElement {
|
|||||||
<mwc-icon-button slot="trigger">
|
<mwc-icon-button slot="trigger">
|
||||||
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
||||||
</mwc-icon-button>
|
</mwc-icon-button>
|
||||||
<mwc-list-item>
|
<mwc-list-item title="Show a list of hardware">
|
||||||
${this.supervisor.localize("system.host.hardware")}
|
Hardware
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
${this.supervisor.host.features.includes("hassos")
|
${this.supervisor.host.features.includes("hassos")
|
||||||
? html`<mwc-list-item>
|
? html`<mwc-list-item
|
||||||
${this.supervisor.localize("system.host.import_from_usb")}
|
title="Load HassOS configs or updates from USB"
|
||||||
|
>
|
||||||
|
Import from USB
|
||||||
</mwc-list-item>`
|
</mwc-list-item>`
|
||||||
: ""}
|
: ""}
|
||||||
</ha-button-menu>
|
</ha-button-menu>
|
||||||
@@ -215,10 +183,6 @@ class HassioHostInfo extends LitElement {
|
|||||||
this._loadData();
|
this._loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getUsedSpace = memoizeOne((used: number, total: number) =>
|
|
||||||
roundWithOneDecimal(getValueInPercentage(used, 0, total))
|
|
||||||
);
|
|
||||||
|
|
||||||
private _primaryIpAddress = memoizeOne((network_info: NetworkInfo) => {
|
private _primaryIpAddress = memoizeOne((network_info: NetworkInfo) => {
|
||||||
if (!network_info || !network_info.interfaces) {
|
if (!network_info || !network_info.interfaces) {
|
||||||
return "";
|
return "";
|
||||||
@@ -241,14 +205,12 @@ class HassioHostInfo extends LitElement {
|
|||||||
try {
|
try {
|
||||||
const content = await fetchHassioHardwareInfo(this.hass);
|
const content = await fetchHassioHardwareInfo(this.hass);
|
||||||
showHassioMarkdownDialog(this, {
|
showHassioMarkdownDialog(this, {
|
||||||
title: this.supervisor.localize("system.host.hardware"),
|
title: "Hardware",
|
||||||
content: `<pre>${safeDump(content, { indent: 2 })}</pre>`,
|
content: `<pre>${safeDump(content, { indent: 2 })}</pre>`,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to get hardware list",
|
||||||
"system.host.failed_to_get_hardware_list"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -259,10 +221,10 @@ class HassioHostInfo extends LitElement {
|
|||||||
button.progress = true;
|
button.progress = true;
|
||||||
|
|
||||||
const confirmed = await showConfirmationDialog(this, {
|
const confirmed = await showConfirmationDialog(this, {
|
||||||
title: this.supervisor.localize("system.host.reboot_host"),
|
title: "Reboot",
|
||||||
text: this.supervisor.localize("system.host.confirm_reboot"),
|
text: "Are you sure you want to reboot the host?",
|
||||||
confirmText: this.supervisor.localize("system.host.reboot_host"),
|
confirmText: "reboot host",
|
||||||
dismissText: this.supervisor.localize("common.cancel"),
|
dismissText: "no",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
@@ -276,7 +238,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
// Ignore connection errors, these are all expected
|
// Ignore connection errors, these are all expected
|
||||||
if (err.status_code && !ignoredStatusCodes.has(err.status_code)) {
|
if (err.status_code && !ignoredStatusCodes.has(err.status_code)) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("system.host.failed_to_reboot"),
|
title: "Failed to reboot",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -289,10 +251,10 @@ class HassioHostInfo extends LitElement {
|
|||||||
button.progress = true;
|
button.progress = true;
|
||||||
|
|
||||||
const confirmed = await showConfirmationDialog(this, {
|
const confirmed = await showConfirmationDialog(this, {
|
||||||
title: this.supervisor.localize("system.host.shutdown_host"),
|
title: "Shutdown",
|
||||||
text: this.supervisor.localize("system.host.confirm_shutdown"),
|
text: "Are you sure you want to shutdown the host?",
|
||||||
confirmText: this.supervisor.localize("system.host.shutdown_host"),
|
confirmText: "shutdown host",
|
||||||
dismissText: this.supervisor.localize("common.cancel"),
|
dismissText: "no",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
@@ -306,7 +268,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
// Ignore connection errors, these are all expected
|
// Ignore connection errors, these are all expected
|
||||||
if (err.status_code && !ignoredStatusCodes.has(err.status_code)) {
|
if (err.status_code && !ignoredStatusCodes.has(err.status_code)) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("system.host.failed_to_shutdown"),
|
title: "Failed to shutdown",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -319,19 +281,9 @@ class HassioHostInfo extends LitElement {
|
|||||||
button.progress = true;
|
button.progress = true;
|
||||||
|
|
||||||
const confirmed = await showConfirmationDialog(this, {
|
const confirmed = await showConfirmationDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Update",
|
||||||
"confirm.update.title",
|
text: "Are you sure you want to update the OS?",
|
||||||
"name",
|
confirmText: "update os",
|
||||||
"Home Assistant Operating System"
|
|
||||||
),
|
|
||||||
text: this.supervisor.localize(
|
|
||||||
"confirm.update.text",
|
|
||||||
"name",
|
|
||||||
"Home Assistant Operating System",
|
|
||||||
"version",
|
|
||||||
this.supervisor.os.version_latest
|
|
||||||
),
|
|
||||||
confirmText: this.supervisor.localize("common.update"),
|
|
||||||
dismissText: "no",
|
dismissText: "no",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -342,25 +294,18 @@ class HassioHostInfo extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await updateOS(this.hass);
|
await updateOS(this.hass);
|
||||||
fireEvent(this, "supervisor-colllection-refresh", { colllection: "os" });
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (this.hass.connection.connected) {
|
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to update",
|
||||||
"common.failed_to_update_name",
|
|
||||||
"name",
|
|
||||||
"Home Assistant Operating System"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
button.progress = false;
|
button.progress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _changeNetworkClicked(): Promise<void> {
|
private async _changeNetworkClicked(): Promise<void> {
|
||||||
showNetworkDialog(this, {
|
showNetworkDialog(this, {
|
||||||
supervisor: this.supervisor,
|
network: this.supervisor.network!,
|
||||||
loadData: () => this._loadData(),
|
loadData: () => this._loadData(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -368,22 +313,20 @@ class HassioHostInfo extends LitElement {
|
|||||||
private async _changeHostnameClicked(): Promise<void> {
|
private async _changeHostnameClicked(): Promise<void> {
|
||||||
const curHostname: string = this.supervisor.host.hostname;
|
const curHostname: string = this.supervisor.host.hostname;
|
||||||
const hostname = await showPromptDialog(this, {
|
const hostname = await showPromptDialog(this, {
|
||||||
title: this.supervisor.localize("system.host.change_hostname"),
|
title: "Change Hostname",
|
||||||
inputLabel: this.supervisor.localize("system.host.new_hostname"),
|
inputLabel: "Please enter a new hostname:",
|
||||||
inputType: "string",
|
inputType: "string",
|
||||||
defaultValue: curHostname,
|
defaultValue: curHostname,
|
||||||
confirmText: this.supervisor.localize("common.update"),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (hostname && hostname !== curHostname) {
|
if (hostname && hostname !== curHostname) {
|
||||||
try {
|
try {
|
||||||
await changeHostOptions(this.hass, { hostname });
|
await changeHostOptions(this.hass, { hostname });
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
const host = await fetchHassioHostInfo(this.hass);
|
||||||
colllection: "host",
|
fireEvent(this, "supervisor-update", { host });
|
||||||
});
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("system.host.failed_to_set_hostname"),
|
title: "Setting hostname failed",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -393,29 +336,20 @@ class HassioHostInfo extends LitElement {
|
|||||||
private async _importFromUSB(): Promise<void> {
|
private async _importFromUSB(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await configSyncOS(this.hass);
|
await configSyncOS(this.hass);
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
const host = await fetchHassioHostInfo(this.hass);
|
||||||
colllection: "host",
|
fireEvent(this, "supervisor-update", { host });
|
||||||
});
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to import from USB",
|
||||||
"system.host.failed_to_import_from_usb"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _loadData(): Promise<void> {
|
private async _loadData(): Promise<void> {
|
||||||
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
|
||||||
colllection: "network",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const network = await fetchNetworkInfo(this.hass);
|
const network = await fetchNetworkInfo(this.hass);
|
||||||
fireEvent(this, "supervisor-update", { network });
|
fireEvent(this, "supervisor-update", { network });
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
@@ -435,12 +369,6 @@ class HassioHostInfo extends LitElement {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.card-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: calc(100% - 124px);
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
ha-settings-row {
|
ha-settings-row {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 54px;
|
height: 54px;
|
||||||
|
@@ -3,7 +3,6 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
@@ -13,12 +12,9 @@ import "../../../src/components/buttons/ha-progress-button";
|
|||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../src/components/ha-settings-row";
|
import "../../../src/components/ha-settings-row";
|
||||||
import "../../../src/components/ha-switch";
|
import "../../../src/components/ha-switch";
|
||||||
|
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
||||||
import {
|
import {
|
||||||
extractApiErrorMessage,
|
fetchHassioSupervisorInfo,
|
||||||
fetchHassioStats,
|
|
||||||
HassioStats,
|
|
||||||
} from "../../../src/data/hassio/common";
|
|
||||||
import {
|
|
||||||
reloadSupervisor,
|
reloadSupervisor,
|
||||||
restartSupervisor,
|
restartSupervisor,
|
||||||
setSupervisorOption,
|
setSupervisorOption,
|
||||||
@@ -32,29 +28,57 @@ import {
|
|||||||
} from "../../../src/dialogs/generic/show-dialog-box";
|
} from "../../../src/dialogs/generic/show-dialog-box";
|
||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
import { bytesToString } from "../../../src/util/bytes-to-string";
|
|
||||||
import { documentationUrl } from "../../../src/util/documentation-url";
|
import { documentationUrl } from "../../../src/util/documentation-url";
|
||||||
import "../components/supervisor-metric";
|
|
||||||
import { hassioStyle } from "../resources/hassio-style";
|
import { hassioStyle } from "../resources/hassio-style";
|
||||||
|
|
||||||
const UNSUPPORTED_REASON_URL = {
|
const UNSUPPORTED_REASON = {
|
||||||
container: "/more-info/unsupported/container",
|
container: {
|
||||||
dbus: "/more-info/unsupported/dbus",
|
title: "Containers known to cause issues",
|
||||||
docker_configuration: "/more-info/unsupported/docker_configuration",
|
url: "/more-info/unsupported/container",
|
||||||
docker_version: "/more-info/unsupported/docker_version",
|
},
|
||||||
job_conditions: "/more-info/unsupported/job_conditions",
|
dbus: { title: "DBUS", url: "/more-info/unsupported/dbus" },
|
||||||
lxc: "/more-info/unsupported/lxc",
|
docker_configuration: {
|
||||||
network_manager: "/more-info/unsupported/network_manager",
|
title: "Docker Configuration",
|
||||||
os: "/more-info/unsupported/os",
|
url: "/more-info/unsupported/docker_configuration",
|
||||||
privileged: "/more-info/unsupported/privileged",
|
},
|
||||||
systemd: "/more-info/unsupported/systemd",
|
docker_version: {
|
||||||
|
title: "Docker Version",
|
||||||
|
url: "/more-info/unsupported/docker_version",
|
||||||
|
},
|
||||||
|
job_conditions: {
|
||||||
|
title: "Ignored job conditions",
|
||||||
|
url: "/more-info/unsupported/job_conditions",
|
||||||
|
},
|
||||||
|
lxc: { title: "LXC", url: "/more-info/unsupported/lxc" },
|
||||||
|
network_manager: {
|
||||||
|
title: "Network Manager",
|
||||||
|
url: "/more-info/unsupported/network_manager",
|
||||||
|
},
|
||||||
|
os: { title: "Operating System", url: "/more-info/unsupported/os" },
|
||||||
|
privileged: {
|
||||||
|
title: "Supervisor is not privileged",
|
||||||
|
url: "/more-info/unsupported/privileged",
|
||||||
|
},
|
||||||
|
systemd: { title: "Systemd", url: "/more-info/unsupported/systemd" },
|
||||||
};
|
};
|
||||||
|
|
||||||
const UNHEALTHY_REASON_URL = {
|
const UNHEALTHY_REASON = {
|
||||||
privileged: "/more-info/unsupported/privileged",
|
privileged: {
|
||||||
supervisor: "/more-info/unhealthy/supervisor",
|
title: "Supervisor is not privileged",
|
||||||
setup: "/more-info/unhealthy/setup",
|
url: "/more-info/unsupported/privileged",
|
||||||
docker: "/more-info/unhealthy/docker",
|
},
|
||||||
|
supervisor: {
|
||||||
|
title: "Supervisor was not able to update",
|
||||||
|
url: "/more-info/unhealthy/supervisor",
|
||||||
|
},
|
||||||
|
setup: {
|
||||||
|
title: "Setup of the Supervisor failed",
|
||||||
|
url: "/more-info/unhealthy/setup",
|
||||||
|
},
|
||||||
|
docker: {
|
||||||
|
title: "The Docker environment is not working properly",
|
||||||
|
url: "/more-info/unhealthy/docker",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@customElement("hassio-supervisor-info")
|
@customElement("hassio-supervisor-info")
|
||||||
@@ -63,57 +87,39 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@internalProperty() private _metrics?: HassioStats;
|
|
||||||
|
|
||||||
protected render(): TemplateResult | void {
|
protected render(): TemplateResult | void {
|
||||||
const metrics = [
|
|
||||||
{
|
|
||||||
description: this.supervisor.localize("system.supervisor.cpu_usage"),
|
|
||||||
value: this._metrics?.cpu_percent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: this.supervisor.localize("system.supervisor.ram_usage"),
|
|
||||||
value: this._metrics?.memory_percent,
|
|
||||||
tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString(
|
|
||||||
this._metrics?.memory_limit
|
|
||||||
)}`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return html`
|
return html`
|
||||||
<ha-card header="Supervisor">
|
<ha-card header="Supervisor">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div>
|
|
||||||
<ha-settings-row>
|
<ha-settings-row>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize("common.version")}
|
Version
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
supervisor-${this.supervisor.supervisor.version}
|
${this.supervisor.supervisor.version}
|
||||||
</span>
|
</span>
|
||||||
</ha-settings-row>
|
</ha-settings-row>
|
||||||
<ha-settings-row>
|
<ha-settings-row>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize("common.newest_version")}
|
Newest Version
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
supervisor-${this.supervisor.supervisor.version_latest}
|
${this.supervisor.supervisor.version_latest}
|
||||||
</span>
|
</span>
|
||||||
${this.supervisor.supervisor.update_available
|
${this.supervisor.supervisor.update_available
|
||||||
? html`
|
? html`
|
||||||
<ha-progress-button
|
<ha-progress-button
|
||||||
.title=${this.supervisor.localize(
|
title="Update the supervisor"
|
||||||
"system.supervisor.update_supervisor"
|
|
||||||
)}
|
|
||||||
@click=${this._supervisorUpdate}
|
@click=${this._supervisorUpdate}
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("common.update")}
|
Update
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
</ha-settings-row>
|
</ha-settings-row>
|
||||||
<ha-settings-row>
|
<ha-settings-row>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize("system.supervisor.channel")}
|
Channel
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${this.supervisor.supervisor.channel}
|
${this.supervisor.supervisor.channel}
|
||||||
@@ -122,26 +128,18 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
? html`
|
? html`
|
||||||
<ha-progress-button
|
<ha-progress-button
|
||||||
@click=${this._toggleBeta}
|
@click=${this._toggleBeta}
|
||||||
.title=${this.supervisor.localize(
|
title="Get stable updates for Home Assistant, supervisor and host"
|
||||||
"system.supervisor.leave_beta_description"
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
${this.supervisor.localize(
|
Leave beta channel
|
||||||
"system.supervisor.leave_beta_action"
|
|
||||||
)}
|
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
`
|
`
|
||||||
: this.supervisor.supervisor.channel === "stable"
|
: this.supervisor.supervisor.channel === "stable"
|
||||||
? html`
|
? html`
|
||||||
<ha-progress-button
|
<ha-progress-button
|
||||||
@click=${this._toggleBeta}
|
@click=${this._toggleBeta}
|
||||||
.title=${this.supervisor.localize(
|
title="Get beta updates for Home Assistant (RCs), supervisor and host"
|
||||||
"system.supervisor.join_beta_description"
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
${this.supervisor.localize(
|
Join beta channel
|
||||||
"system.supervisor.join_beta_action"
|
|
||||||
)}
|
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -150,20 +148,16 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
${this.supervisor.supervisor.supported
|
${this.supervisor.supervisor.supported
|
||||||
? html` <ha-settings-row three-line>
|
? html` <ha-settings-row three-line>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
${this.supervisor.localize(
|
Share Diagnostics
|
||||||
"system.supervisor.share_diagnostics"
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<div slot="description" class="diagnostics-description">
|
<div slot="description" class="diagnostics-description">
|
||||||
${this.supervisor.localize(
|
Share crash reports and diagnostic information.
|
||||||
"system.supervisor.share_diagnostics_description"
|
|
||||||
)}
|
|
||||||
<button
|
<button
|
||||||
class="link"
|
class="link"
|
||||||
.title=${this.supervisor.localize("common.show_more")}
|
title="Show more information about this"
|
||||||
@click=${this._diagnosticsInformationDialog}
|
@click=${this._diagnosticsInformationDialog}
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("common.learn_more")}
|
Learn more
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ha-switch
|
<ha-switch
|
||||||
@@ -173,12 +167,10 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
></ha-switch>
|
></ha-switch>
|
||||||
</ha-settings-row>`
|
</ha-settings-row>`
|
||||||
: html`<div class="error">
|
: html`<div class="error">
|
||||||
${this.supervisor.localize(
|
You are running an unsupported installation.
|
||||||
"system.supervisor.unsupported_title"
|
|
||||||
)}
|
|
||||||
<button
|
<button
|
||||||
class="link"
|
class="link"
|
||||||
.title=${this.supervisor.localize("common.learn_more")}
|
title="Learn more about how you can make your system compliant"
|
||||||
@click=${this._unsupportedDialog}
|
@click=${this._unsupportedDialog}
|
||||||
>
|
>
|
||||||
Learn more
|
Learn more
|
||||||
@@ -186,12 +178,10 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
</div>`}
|
</div>`}
|
||||||
${!this.supervisor.supervisor.healthy
|
${!this.supervisor.supervisor.healthy
|
||||||
? html`<div class="error">
|
? html`<div class="error">
|
||||||
${this.supervisor.localize(
|
Your installation is running in an unhealthy state.
|
||||||
"system.supervisor.unhealthy_title"
|
|
||||||
)}
|
|
||||||
<button
|
<button
|
||||||
class="link"
|
class="link"
|
||||||
.title=${this.supervisor.localize("common.learn_more")}
|
title="Learn more about why your system is marked as unhealthy"
|
||||||
@click=${this._unhealthyDialog}
|
@click=${this._unhealthyDialog}
|
||||||
>
|
>
|
||||||
Learn more
|
Learn more
|
||||||
@@ -199,79 +189,48 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
</div>`
|
</div>`
|
||||||
: ""}
|
: ""}
|
||||||
</div>
|
</div>
|
||||||
<div class="metrics-block">
|
|
||||||
${metrics.map(
|
|
||||||
(metric) =>
|
|
||||||
html`
|
|
||||||
<supervisor-metric
|
|
||||||
.description=${metric.description}
|
|
||||||
.value=${metric.value ?? 0}
|
|
||||||
.tooltip=${metric.tooltip}
|
|
||||||
></supervisor-metric>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<ha-progress-button
|
<ha-progress-button
|
||||||
@click=${this._supervisorReload}
|
@click=${this._supervisorReload}
|
||||||
.title=${this.supervisor.localize(
|
title="Reload parts of the Supervisor"
|
||||||
"system.supervisor.reload_supervisor"
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("system.supervisor.reload_supervisor")}
|
Reload
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
<ha-progress-button
|
<ha-progress-button
|
||||||
class="warning"
|
class="warning"
|
||||||
@click=${this._supervisorRestart}
|
@click=${this._supervisorRestart}
|
||||||
.title=${this.supervisor.localize(
|
title="Restart the Supervisor"
|
||||||
"common.restart_name",
|
|
||||||
"name",
|
|
||||||
"Supervisor"
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
${this.supervisor.localize(
|
Restart
|
||||||
"common.restart_name",
|
|
||||||
"name",
|
|
||||||
"Supervisor"
|
|
||||||
)}
|
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(): void {
|
|
||||||
this._loadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _loadData(): Promise<void> {
|
|
||||||
this._metrics = await fetchHassioStats(this.hass, "supervisor");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _toggleBeta(ev: CustomEvent): Promise<void> {
|
private async _toggleBeta(ev: CustomEvent): Promise<void> {
|
||||||
const button = ev.currentTarget as any;
|
const button = ev.currentTarget as any;
|
||||||
button.progress = true;
|
button.progress = true;
|
||||||
|
|
||||||
if (this.supervisor.supervisor.channel === "stable") {
|
if (this.supervisor.supervisor.channel === "stable") {
|
||||||
const confirmed = await showConfirmationDialog(this, {
|
const confirmed = await showConfirmationDialog(this, {
|
||||||
title: this.supervisor.localize("system.supervisor.warning"),
|
title: "WARNING",
|
||||||
text: html`${this.supervisor.localize("system.supervisor.beta_warning")}
|
text: html` Beta releases are for testers and early adopters and can
|
||||||
|
contain unstable code changes.
|
||||||
<br />
|
<br />
|
||||||
<b>
|
<b>
|
||||||
${this.supervisor.localize("system.supervisor.beta_backup")}
|
Make sure you have backups of your data before you activate this
|
||||||
|
feature.
|
||||||
</b>
|
</b>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
${this.supervisor.localize("system.supervisor.beta_release_items")}
|
This includes beta releases for:
|
||||||
<li>Home Assistant Core</li>
|
<li>Home Assistant Core</li>
|
||||||
<li>Home Assistant Supervisor</li>
|
<li>Home Assistant Supervisor</li>
|
||||||
<li>Home Assistant Operating System</li>
|
<li>Home Assistant Operating System</li>
|
||||||
<br />
|
<br />
|
||||||
${this.supervisor.localize("system.supervisor.join_beta_action")}`,
|
Do you want to join the beta channel?`,
|
||||||
confirmText: this.supervisor.localize(
|
confirmText: "join beta",
|
||||||
"system.supervisor.beta_join_confirm"
|
dismissText: "no",
|
||||||
),
|
|
||||||
dismissText: this.supervisor.localize("common.cancel"),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
@@ -289,9 +248,7 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
await this._reloadSupervisor();
|
await this._reloadSupervisor();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to set supervisor option",
|
||||||
"system.supervisor.failed_to_set_option"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
@@ -307,7 +264,7 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
await this._reloadSupervisor();
|
await this._reloadSupervisor();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("system.supervisor.failed_to_reload"),
|
title: "Failed to reload the supervisor",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
@@ -317,44 +274,19 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
|
|
||||||
private async _reloadSupervisor(): Promise<void> {
|
private async _reloadSupervisor(): Promise<void> {
|
||||||
await reloadSupervisor(this.hass);
|
await reloadSupervisor(this.hass);
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
const supervisor = await fetchHassioSupervisorInfo(this.hass);
|
||||||
colllection: "supervisor",
|
fireEvent(this, "supervisor-update", { supervisor });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _supervisorRestart(ev: CustomEvent): Promise<void> {
|
private async _supervisorRestart(ev: CustomEvent): Promise<void> {
|
||||||
const button = ev.currentTarget as any;
|
const button = ev.currentTarget as any;
|
||||||
button.progress = true;
|
button.progress = true;
|
||||||
|
|
||||||
const confirmed = await showConfirmationDialog(this, {
|
|
||||||
title: this.supervisor.localize(
|
|
||||||
"confirm.restart.title",
|
|
||||||
"name",
|
|
||||||
"Supervisor"
|
|
||||||
),
|
|
||||||
text: this.supervisor.localize(
|
|
||||||
"confirm.restart.text",
|
|
||||||
"name",
|
|
||||||
"Supervisor"
|
|
||||||
),
|
|
||||||
confirmText: this.supervisor.localize("common.restart"),
|
|
||||||
dismissText: this.supervisor.localize("common.cancel"),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!confirmed) {
|
|
||||||
button.progress = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await restartSupervisor(this.hass);
|
await restartSupervisor(this.hass);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to restart the supervisor",
|
||||||
"common.failed_to_restart_name",
|
|
||||||
"name",
|
|
||||||
"Supervisor"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
@@ -367,16 +299,10 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
button.progress = true;
|
button.progress = true;
|
||||||
|
|
||||||
const confirmed = await showConfirmationDialog(this, {
|
const confirmed = await showConfirmationDialog(this, {
|
||||||
title: this.supervisor.localize("confirm.update", "name", "Supervisor"),
|
title: "Update Supervisor",
|
||||||
text: this.supervisor.localize(
|
text: `Are you sure you want to update supervisor to version ${this.supervisor.supervisor.version_latest}?`,
|
||||||
"confirm.text",
|
confirmText: "update",
|
||||||
"name",
|
dismissText: "cancel",
|
||||||
"Supervisor",
|
|
||||||
"version",
|
|
||||||
this.supervisor.supervisor.version_latest
|
|
||||||
),
|
|
||||||
confirmText: this.supervisor.localize("common.update"),
|
|
||||||
dismissText: this.supervisor.localize("common.cancel"),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
@@ -386,16 +312,9 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await updateSupervisor(this.hass);
|
await updateSupervisor(this.hass);
|
||||||
fireEvent(this, "supervisor-colllection-refresh", {
|
|
||||||
colllection: "supervisor",
|
|
||||||
});
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to update the supervisor",
|
||||||
"common.failed_to_update_name",
|
|
||||||
"name",
|
|
||||||
"Supervisor"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
@@ -405,41 +324,40 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
|
|
||||||
private async _diagnosticsInformationDialog(): Promise<void> {
|
private async _diagnosticsInformationDialog(): Promise<void> {
|
||||||
await showAlertDialog(this, {
|
await showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Help Improve Home Assistant",
|
||||||
"system.supervisor.share_diagonstics_title"
|
text: html`Would you want to automatically share crash reports and
|
||||||
),
|
diagnostic information when the supervisor encounters unexpected errors?
|
||||||
text: this.supervisor.localize(
|
<br /><br />
|
||||||
"system.supervisor.share_diagonstics_description",
|
This will allow us to fix the problems, the information is only
|
||||||
"line_break",
|
accessible to the Home Assistant Core team and will not be shared with
|
||||||
html`<br /><br />`
|
others.
|
||||||
),
|
<br /><br />
|
||||||
|
The data does not include any private/sensitive information and you can
|
||||||
|
disable this in settings at any time you want.`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _unsupportedDialog(): Promise<void> {
|
private async _unsupportedDialog(): Promise<void> {
|
||||||
await showAlertDialog(this, {
|
await showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("system.supervisor.unsupported_title"),
|
title: "You are running an unsupported installation",
|
||||||
text: html`${this.supervisor.localize(
|
text: html`Below is a list of issues found with your installation, click
|
||||||
"system.supervisor.unsupported_description"
|
on the links to learn how you can resolve the issues. <br /><br />
|
||||||
)} <br /><br />
|
|
||||||
<ul>
|
<ul>
|
||||||
${this.supervisor.resolution.unsupported.map(
|
${this.supervisor.resolution.unsupported.map(
|
||||||
(reason) => html`
|
(issue) => html`
|
||||||
<li>
|
<li>
|
||||||
${UNSUPPORTED_REASON_URL[reason]
|
${UNSUPPORTED_REASON[issue]
|
||||||
? html`<a
|
? html`<a
|
||||||
href="${documentationUrl(
|
href="${documentationUrl(
|
||||||
this.hass,
|
this.hass,
|
||||||
UNSUPPORTED_REASON_URL[reason]
|
UNSUPPORTED_REASON[issue].url
|
||||||
)}"
|
)}"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
${this.supervisor.localize(
|
${UNSUPPORTED_REASON[issue].title}
|
||||||
`system.supervisor.unsupported_reason.${reason}`
|
|
||||||
) || reason}
|
|
||||||
</a>`
|
</a>`
|
||||||
: reason}
|
: issue}
|
||||||
</li>
|
</li>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
@@ -449,28 +367,26 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
|
|
||||||
private async _unhealthyDialog(): Promise<void> {
|
private async _unhealthyDialog(): Promise<void> {
|
||||||
await showAlertDialog(this, {
|
await showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("system.supervisor.unhealthy_title"),
|
title: "Your installation is unhealthy",
|
||||||
text: html`${this.supervisor.localize(
|
text: html`Running an unhealthy installation will cause issues. Below is a
|
||||||
"system.supervisor.unhealthy_description"
|
list of issues found with your installation, click on the links to learn
|
||||||
)} <br /><br />
|
how you can resolve the issues. <br /><br />
|
||||||
<ul>
|
<ul>
|
||||||
${this.supervisor.resolution.unhealthy.map(
|
${this.supervisor.resolution.unhealthy.map(
|
||||||
(reason) => html`
|
(issue) => html`
|
||||||
<li>
|
<li>
|
||||||
${UNHEALTHY_REASON_URL[reason]
|
${UNHEALTHY_REASON[issue]
|
||||||
? html`<a
|
? html`<a
|
||||||
href="${documentationUrl(
|
href="${documentationUrl(
|
||||||
this.hass,
|
this.hass,
|
||||||
UNHEALTHY_REASON_URL[reason]
|
UNHEALTHY_REASON[issue].url
|
||||||
)}"
|
)}"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
${this.supervisor.localize(
|
${UNHEALTHY_REASON[issue].title}
|
||||||
`system.supervisor.unhealthy_reason.${reason}`
|
|
||||||
) || reason}
|
|
||||||
</a>`
|
</a>`
|
||||||
: reason}
|
: issue}
|
||||||
</li>
|
</li>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
@@ -486,9 +402,7 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
await setSupervisorOption(this.hass, data);
|
await setSupervisorOption(this.hass, data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: "Failed to set supervisor option",
|
||||||
"system.supervisor.failed_to_set_option"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -512,15 +426,6 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.card-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: calc(100% - 124px);
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.metrics-block {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
button.link {
|
button.link {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,6 @@ import "../../../src/components/buttons/ha-progress-button";
|
|||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
||||||
import { fetchHassioLogs } from "../../../src/data/hassio/supervisor";
|
import { fetchHassioLogs } from "../../../src/data/hassio/supervisor";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
|
||||||
import "../../../src/layouts/hass-loading-screen";
|
import "../../../src/layouts/hass-loading-screen";
|
||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
@@ -59,8 +58,6 @@ const logProviders: LogProvider[] = [
|
|||||||
class HassioSupervisorLog extends LitElement {
|
class HassioSupervisorLog extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@internalProperty() private _error?: string;
|
||||||
|
|
||||||
@internalProperty() private _selectedLogProvider = "supervisor";
|
@internalProperty() private _selectedLogProvider = "supervisor";
|
||||||
@@ -79,7 +76,7 @@ class HassioSupervisorLog extends LitElement {
|
|||||||
${this.hass.userData?.showAdvanced
|
${this.hass.userData?.showAdvanced
|
||||||
? html`
|
? html`
|
||||||
<paper-dropdown-menu
|
<paper-dropdown-menu
|
||||||
.label=${this.supervisor.localize("system.log.log_provider")}
|
label="Log Provider"
|
||||||
@iron-select=${this._setLogProvider}
|
@iron-select=${this._setLogProvider}
|
||||||
>
|
>
|
||||||
<paper-listbox
|
<paper-listbox
|
||||||
@@ -89,9 +86,9 @@ class HassioSupervisorLog extends LitElement {
|
|||||||
>
|
>
|
||||||
${logProviders.map((provider) => {
|
${logProviders.map((provider) => {
|
||||||
return html`
|
return html`
|
||||||
<paper-item provider=${provider.key}>
|
<paper-item provider=${provider.key}
|
||||||
${provider.name}
|
>${provider.name}</paper-item
|
||||||
</paper-item>
|
>
|
||||||
`;
|
`;
|
||||||
})}
|
})}
|
||||||
</paper-listbox>
|
</paper-listbox>
|
||||||
@@ -101,13 +98,14 @@ class HassioSupervisorLog extends LitElement {
|
|||||||
|
|
||||||
<div class="card-content" id="content">
|
<div class="card-content" id="content">
|
||||||
${this._content
|
${this._content
|
||||||
? html`<hassio-ansi-to-html .content=${this._content}>
|
? html`<hassio-ansi-to-html
|
||||||
</hassio-ansi-to-html>`
|
.content=${this._content}
|
||||||
|
></hassio-ansi-to-html>`
|
||||||
: html`<hass-loading-screen no-toolbar></hass-loading-screen>`}
|
: html`<hass-loading-screen no-toolbar></hass-loading-screen>`}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<ha-progress-button @click=${this._refresh}>
|
<ha-progress-button @click=${this._refresh}>
|
||||||
${this.supervisor.localize("common.refresh")}
|
Refresh
|
||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
@@ -136,13 +134,9 @@ class HassioSupervisorLog extends LitElement {
|
|||||||
this._selectedLogProvider
|
this._selectedLogProvider
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = `Failed to get supervisor logs, ${extractApiErrorMessage(
|
||||||
"system.log.get_logs",
|
err
|
||||||
"provider",
|
)}`;
|
||||||
this._selectedLogProvider,
|
|
||||||
"error",
|
|
||||||
extractApiErrorMessage(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
185
hassio/src/system/hassio-system-metrics.ts
Normal file
185
hassio/src/system/hassio-system-metrics.ts
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
import "@material/mwc-button";
|
||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
internalProperty,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import "../../../src/components/buttons/ha-progress-button";
|
||||||
|
import "../../../src/components/ha-bar";
|
||||||
|
import "../../../src/components/ha-button-menu";
|
||||||
|
import "../../../src/components/ha-card";
|
||||||
|
import "../../../src/components/ha-settings-row";
|
||||||
|
import { fetchHassioStats, HassioStats } from "../../../src/data/hassio/common";
|
||||||
|
import { HassioHostInfo } from "../../../src/data/hassio/host";
|
||||||
|
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||||
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
|
import { HomeAssistant } from "../../../src/types";
|
||||||
|
import { bytesToString } from "../../../src/util/bytes-to-string";
|
||||||
|
import {
|
||||||
|
getValueInPercentage,
|
||||||
|
roundWithOneDecimal,
|
||||||
|
} from "../../../src/util/calculate";
|
||||||
|
import { hassioStyle } from "../resources/hassio-style";
|
||||||
|
|
||||||
|
@customElement("hassio-system-metrics")
|
||||||
|
class HassioSystemMetrics extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
|
@internalProperty() private _supervisorMetrics?: HassioStats;
|
||||||
|
|
||||||
|
@internalProperty() private _coreMetrics?: HassioStats;
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
const metrics = [
|
||||||
|
{
|
||||||
|
description: "Core CPU Usage",
|
||||||
|
value: this._coreMetrics?.cpu_percent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Core RAM Usage",
|
||||||
|
value: this._coreMetrics?.memory_percent,
|
||||||
|
tooltip: `${bytesToString(
|
||||||
|
this._coreMetrics?.memory_usage
|
||||||
|
)}/${bytesToString(this._coreMetrics?.memory_limit)}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Supervisor CPU Usage",
|
||||||
|
value: this._supervisorMetrics?.cpu_percent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Supervisor RAM Usage",
|
||||||
|
value: this._supervisorMetrics?.memory_percent,
|
||||||
|
tooltip: `${bytesToString(
|
||||||
|
this._supervisorMetrics?.memory_usage
|
||||||
|
)}/${bytesToString(this._supervisorMetrics?.memory_limit)}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Used Space",
|
||||||
|
value: this._getUsedSpace(this.supervisor.host),
|
||||||
|
tooltip: `${this.supervisor.host.disk_used} GB/${this.supervisor.host.disk_total} GB`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-card header="System Metrics">
|
||||||
|
<div class="card-content">
|
||||||
|
${metrics.map((metric) =>
|
||||||
|
this._renderMetric(
|
||||||
|
metric.description,
|
||||||
|
metric.value ?? 0,
|
||||||
|
metric.tooltip
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected firstUpdated(): void {
|
||||||
|
this._loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderMetric(
|
||||||
|
description: string,
|
||||||
|
value: number,
|
||||||
|
tooltip?: string
|
||||||
|
): TemplateResult {
|
||||||
|
const roundedValue = roundWithOneDecimal(value);
|
||||||
|
return html`<ha-settings-row>
|
||||||
|
<span slot="heading">
|
||||||
|
${description}
|
||||||
|
</span>
|
||||||
|
<div slot="description" title="${tooltip ?? ""}">
|
||||||
|
<span class="value">
|
||||||
|
${roundedValue}%
|
||||||
|
</span>
|
||||||
|
<ha-bar
|
||||||
|
class="${classMap({
|
||||||
|
"target-warning": roundedValue > 50,
|
||||||
|
"target-critical": roundedValue > 85,
|
||||||
|
})}"
|
||||||
|
.value=${value}
|
||||||
|
></ha-bar>
|
||||||
|
</div>
|
||||||
|
</ha-settings-row>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getUsedSpace = memoizeOne((hostInfo: HassioHostInfo) =>
|
||||||
|
roundWithOneDecimal(
|
||||||
|
getValueInPercentage(hostInfo.disk_used, 0, hostInfo.disk_total)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
private async _loadData(): Promise<void> {
|
||||||
|
const [supervisor, core] = await Promise.all([
|
||||||
|
fetchHassioStats(this.hass, "supervisor"),
|
||||||
|
fetchHassioStats(this.hass, "core"),
|
||||||
|
]);
|
||||||
|
this._supervisorMetrics = supervisor;
|
||||||
|
this._coreMetrics = core;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return [
|
||||||
|
haStyle,
|
||||||
|
hassioStyle,
|
||||||
|
css`
|
||||||
|
ha-card {
|
||||||
|
height: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: column;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
ha-settings-row {
|
||||||
|
padding: 0;
|
||||||
|
height: 54px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
ha-settings-row > div[slot="description"] {
|
||||||
|
white-space: normal;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
ha-bar {
|
||||||
|
--ha-bar-primary-color: var(
|
||||||
|
--hassio-bar-ok-color,
|
||||||
|
var(--success-color)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
.target-warning {
|
||||||
|
--ha-bar-primary-color: var(
|
||||||
|
--hassio-bar-warning-color,
|
||||||
|
var(--warning-color)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
.target-critical {
|
||||||
|
--ha-bar-primary-color: var(
|
||||||
|
--hassio-bar-critical-color,
|
||||||
|
var(--error-color)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
.value {
|
||||||
|
width: 42px;
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hassio-system-metrics": HassioSystemMetrics;
|
||||||
|
}
|
||||||
|
}
|
@@ -13,10 +13,10 @@ import { haStyle } from "../../../src/resources/styles";
|
|||||||
import { HomeAssistant, Route } from "../../../src/types";
|
import { HomeAssistant, Route } from "../../../src/types";
|
||||||
import { supervisorTabs } from "../hassio-tabs";
|
import { supervisorTabs } from "../hassio-tabs";
|
||||||
import { hassioStyle } from "../resources/hassio-style";
|
import { hassioStyle } from "../resources/hassio-style";
|
||||||
import "./hassio-core-info";
|
|
||||||
import "./hassio-host-info";
|
import "./hassio-host-info";
|
||||||
import "./hassio-supervisor-info";
|
import "./hassio-supervisor-info";
|
||||||
import "./hassio-supervisor-log";
|
import "./hassio-supervisor-log";
|
||||||
|
import "./hassio-system-metrics";
|
||||||
|
|
||||||
@customElement("hassio-system")
|
@customElement("hassio-system")
|
||||||
class HassioSystem extends LitElement {
|
class HassioSystem extends LitElement {
|
||||||
@@ -32,22 +32,15 @@ class HassioSystem extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<hass-tabs-subpage
|
<hass-tabs-subpage
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.localizeFunc=${this.supervisor.localize}
|
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
|
hassio
|
||||||
|
main-page
|
||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
.tabs=${supervisorTabs}
|
.tabs=${supervisorTabs}
|
||||||
main-page
|
|
||||||
supervisor
|
|
||||||
>
|
>
|
||||||
<span slot="header">
|
<span slot="header">System</span>
|
||||||
${this.supervisor.localize("panel.system")}
|
|
||||||
</span>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="card-group">
|
<div class="card-group">
|
||||||
<hassio-core-info
|
|
||||||
.hass=${this.hass}
|
|
||||||
.supervisor=${this.supervisor}
|
|
||||||
></hassio-core-info>
|
|
||||||
<hassio-supervisor-info
|
<hassio-supervisor-info
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.supervisor=${this.supervisor}
|
.supervisor=${this.supervisor}
|
||||||
@@ -56,11 +49,12 @@ class HassioSystem extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.supervisor=${this.supervisor}
|
.supervisor=${this.supervisor}
|
||||||
></hassio-host-info>
|
></hassio-host-info>
|
||||||
</div>
|
<hassio-system-metrics
|
||||||
<hassio-supervisor-log
|
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.supervisor=${this.supervisor}
|
.supervisor=${this.supervisor}
|
||||||
></hassio-supervisor-log>
|
></hassio-system-metrics>
|
||||||
|
</div>
|
||||||
|
<hassio-supervisor-log .hass=${this.hass}></hassio-supervisor-log>
|
||||||
</div>
|
</div>
|
||||||
</hass-tabs-subpage>
|
</hass-tabs-subpage>
|
||||||
`;
|
`;
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { SupervisorArch } from "../../../src/data/supervisor/supervisor";
|
|
||||||
|
|
||||||
export const addonArchIsSupported = memoizeOne(
|
|
||||||
(supported_archs: SupervisorArch[], addon_archs: SupervisorArch[]) =>
|
|
||||||
addon_archs.some((arch) => supported_archs.includes(arch))
|
|
||||||
);
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user