mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-23 16:19:25 +00:00
Compare commits
1 Commits
20230601.1
...
allow-part
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a548d13931 |
@@ -1,33 +0,0 @@
|
|||||||
[modern]
|
|
||||||
# Support for dynamic import is the main litmus test for serving modern builds.
|
|
||||||
# Although officially a ES2020 feature, browsers implemented it early, so this
|
|
||||||
# enables all of ES2017 and some features in ES2018.
|
|
||||||
supports es6-module-dynamic-import
|
|
||||||
|
|
||||||
# Exclude Safari 11-12 because of a bug in tagged template literals
|
|
||||||
# https://bugs.webkit.org/show_bug.cgi?id=190756
|
|
||||||
# Note: Dropping version 11 also enables several more ES2018 features
|
|
||||||
not Safari < 13
|
|
||||||
not iOS < 13
|
|
||||||
|
|
||||||
# Exclude unsupported browsers
|
|
||||||
not dead
|
|
||||||
|
|
||||||
[legacy]
|
|
||||||
# Legacy builds are served when modern requirements are not met and support browsers:
|
|
||||||
# - released in the last 7 years + current alpha/beta versionss
|
|
||||||
# - with global utilization above 0.05%
|
|
||||||
# The lattermost query ensures that support for popular old browsers is not dropped too early
|
|
||||||
# (e.g. IE 11, Android 4.4, or Samsung 4).
|
|
||||||
#
|
|
||||||
# In addition, legacy browsers must support some minimum features that cannot be polyfilled:
|
|
||||||
# - ES5 (strict mode)
|
|
||||||
# - web sockets to communicate with backend
|
|
||||||
# - inline SVG used widely in buttons, widgets, etc.
|
|
||||||
# - custom events used for most user interactions
|
|
||||||
# - CSS flexbox used in the majority of the layout
|
|
||||||
# Nearly all of these are redundant with the above rules.
|
|
||||||
# As of May 2023, only web sockets must be added to the query.
|
|
||||||
unreleased versions
|
|
||||||
last 7 years
|
|
||||||
> 0.05% and supports websockets
|
|
@@ -5,3 +5,9 @@ ENV \
|
|||||||
DEBIAN_FRONTEND=noninteractive \
|
DEBIAN_FRONTEND=noninteractive \
|
||||||
DEVCONTAINER=true \
|
DEVCONTAINER=true \
|
||||||
PATH=$PATH:./node_modules/.bin
|
PATH=$PATH:./node_modules/.bin
|
||||||
|
|
||||||
|
# Install nvm
|
||||||
|
COPY .nvmrc /tmp/.nvmrc
|
||||||
|
RUN \
|
||||||
|
su vscode -c \
|
||||||
|
"source /usr/local/share/nvm/nvm.sh && nvm install $(cat /tmp/.nvmrc) 2>&1"
|
@@ -5,7 +5,7 @@
|
|||||||
"context": ".."
|
"context": ".."
|
||||||
},
|
},
|
||||||
"appPort": "8124:8123",
|
"appPort": "8124:8123",
|
||||||
"postStartCommand": "script/bootstrap",
|
"postCreateCommand": "script/bootstrap",
|
||||||
"containerEnv": {
|
"containerEnv": {
|
||||||
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
|
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
|
||||||
},
|
},
|
||||||
|
13
.github/workflows/cast_deployment.yaml
vendored
13
.github/workflows/cast_deployment.yaml
vendored
@@ -9,6 +9,7 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -21,14 +22,14 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
with:
|
with:
|
||||||
ref: dev
|
ref: dev
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -57,14 +58,14 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
with:
|
with:
|
||||||
ref: master
|
ref: master
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
25
.github/workflows/ci.yaml
vendored
25
.github/workflows/ci.yaml
vendored
@@ -11,6 +11,7 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
@@ -24,11 +25,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --immutable
|
run: yarn install --immutable
|
||||||
@@ -47,11 +48,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --immutable
|
run: yarn install --immutable
|
||||||
@@ -65,11 +66,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --immutable
|
run: yarn install --immutable
|
||||||
@@ -83,11 +84,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --immutable
|
run: yarn install --immutable
|
||||||
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
with:
|
with:
|
||||||
# We must fetch at least the immediate parents so that if this is
|
# We must fetch at least the immediate parents so that if this is
|
||||||
# a pull request then we can checkout the head.
|
# a pull request then we can checkout the head.
|
||||||
|
17
.github/workflows/demo_deployment.yaml
vendored
17
.github/workflows/demo_deployment.yaml
vendored
@@ -10,26 +10,27 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy_dev:
|
deploy_dev:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Demo Development
|
name: Demo Development
|
||||||
if: github.event_name != 'push' || github.ref_name != 'master'
|
if: github.event_name != 'push' || github.ref != 'master'
|
||||||
environment:
|
environment:
|
||||||
name: Demo Development
|
name: Demo Development
|
||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
with:
|
with:
|
||||||
ref: dev
|
ref: dev
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -52,20 +53,20 @@ jobs:
|
|||||||
deploy_master:
|
deploy_master:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Demo Production
|
name: Demo Production
|
||||||
if: github.event_name == 'push' && github.ref_name == 'master'
|
if: github.event_name == 'push' && github.ref == 'master'
|
||||||
environment:
|
environment:
|
||||||
name: Demo Production
|
name: Demo Production
|
||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
with:
|
with:
|
||||||
ref: master
|
ref: master
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
7
.github/workflows/design_deployment.yaml
vendored
7
.github/workflows/design_deployment.yaml
vendored
@@ -6,6 +6,7 @@ on:
|
|||||||
- cron: "0 0 * * *"
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -16,12 +17,12 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
7
.github/workflows/design_preview.yaml
vendored
7
.github/workflows/design_preview.yaml
vendored
@@ -11,6 +11,7 @@ on:
|
|||||||
- dev
|
- dev
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -21,12 +22,12 @@ jobs:
|
|||||||
if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview')
|
if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview')
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
7
.github/workflows/nightly.yaml
vendored
7
.github/workflows/nightly.yaml
vendored
@@ -7,6 +7,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
PYTHON_VERSION: "3.10"
|
PYTHON_VERSION: "3.10"
|
||||||
|
NODE_VERSION: 16
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -20,17 +21,17 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
|
|
||||||
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.PYTHON_VERSION }}
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
9
.github/workflows/release.yaml
vendored
9
.github/workflows/release.yaml
vendored
@@ -7,6 +7,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
PYTHON_VERSION: "3.10"
|
PYTHON_VERSION: "3.10"
|
||||||
|
NODE_VERSION: 16
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
# Set default workflow permissions
|
# Set default workflow permissions
|
||||||
@@ -23,7 +24,7 @@ jobs:
|
|||||||
contents: write # Required to upload release assets
|
contents: write # Required to upload release assets
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
|
|
||||||
- name: Verify version
|
- name: Verify version
|
||||||
uses: home-assistant/actions/helpers/verify-version@master
|
uses: home-assistant/actions/helpers/verify-version@master
|
||||||
@@ -33,10 +34,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: ${{ env.PYTHON_VERSION }}
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -74,7 +75,7 @@ jobs:
|
|||||||
echo "home-assistant-frontend==$version" > ./requirements.txt
|
echo "home-assistant-frontend==$version" > ./requirements.txt
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: home-assistant/wheels@2023.04.0
|
uses: home-assistant/wheels@2022.10.1
|
||||||
with:
|
with:
|
||||||
abi: cp310
|
abi: cp310
|
||||||
tag: musllinux_1_2
|
tag: musllinux_1_2
|
||||||
|
6
.github/workflows/translations.yaml
vendored
6
.github/workflows/translations.yaml
vendored
@@ -7,15 +7,19 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- src/translations/en.json
|
- src/translations/en.json
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
upload:
|
upload:
|
||||||
name: Upload
|
name: Upload
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.0
|
||||||
|
|
||||||
- name: Upload Translations
|
- name: Upload Translations
|
||||||
run: |
|
run: |
|
||||||
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
|
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
|
||||||
|
|
||||||
./script/translations_upload_base
|
./script/translations_upload_base
|
||||||
|
@@ -1,39 +0,0 @@
|
|||||||
diff --git a/modular/sortable.complete.esm.js b/modular/sortable.complete.esm.js
|
|
||||||
index 02e9f2d6bebeb430fe6e7c1cc3f9c3c9df051f14..bb8268b0844a1faa4108cc92c0be2a3dbaf23f83 100644
|
|
||||||
--- a/modular/sortable.complete.esm.js
|
|
||||||
+++ b/modular/sortable.complete.esm.js
|
|
||||||
@@ -1657,7 +1657,7 @@ Sortable.prototype =
|
|
||||||
target = parent; // store last element
|
|
||||||
}
|
|
||||||
/* jshint boss:true */
|
|
||||||
- while (parent = parent.parentNode);
|
|
||||||
+ while (parent = parent.parentNode || parent.getRootNode().host);
|
|
||||||
}
|
|
||||||
|
|
||||||
_unhideGhostForTarget();
|
|
||||||
diff --git a/modular/sortable.core.esm.js b/modular/sortable.core.esm.js
|
|
||||||
index b04c8b4634f7c6b4ef1aadbb48afe6564306dea9..39a107163c8c336ebd669b5ea8a936af87e1c1e7 100644
|
|
||||||
--- a/modular/sortable.core.esm.js
|
|
||||||
+++ b/modular/sortable.core.esm.js
|
|
||||||
@@ -1657,7 +1657,7 @@ Sortable.prototype =
|
|
||||||
target = parent; // store last element
|
|
||||||
}
|
|
||||||
/* jshint boss:true */
|
|
||||||
- while (parent = parent.parentNode);
|
|
||||||
+ while (parent = parent.parentNode || parent.getRootNode().host);
|
|
||||||
}
|
|
||||||
|
|
||||||
_unhideGhostForTarget();
|
|
||||||
diff --git a/modular/sortable.esm.js b/modular/sortable.esm.js
|
|
||||||
index 6ec7ed1bb557e21c2578200161e989c65d23150b..0a05475a22904472fac6c13f524c674da76584b0 100644
|
|
||||||
--- a/modular/sortable.esm.js
|
|
||||||
+++ b/modular/sortable.esm.js
|
|
||||||
@@ -1657,7 +1657,7 @@ Sortable.prototype =
|
|
||||||
target = parent; // store last element
|
|
||||||
}
|
|
||||||
/* jshint boss:true */
|
|
||||||
- while (parent = parent.parentNode);
|
|
||||||
+ while (parent = parent.parentNode || parent.getRootNode().host);
|
|
||||||
}
|
|
||||||
|
|
||||||
_unhideGhostForTarget();
|
|
File diff suppressed because one or more lines are too long
@@ -8,4 +8,4 @@ plugins:
|
|||||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||||
spec: "@yarnpkg/plugin-interactive-tools"
|
spec: "@yarnpkg/plugin-interactive-tools"
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-3.5.1.cjs
|
yarnPath: .yarn/releases/yarn-3.5.0.cjs
|
||||||
|
@@ -76,7 +76,7 @@ module.exports.htmlMinifierOptions = {
|
|||||||
|
|
||||||
module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
|
module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
|
||||||
safari10: !latestBuild,
|
safari10: !latestBuild,
|
||||||
ecma: latestBuild ? 2015 : 5,
|
ecma: latestBuild ? undefined : 5,
|
||||||
format: { comments: false },
|
format: { comments: false },
|
||||||
sourceMap: !isTestBuild,
|
sourceMap: !isTestBuild,
|
||||||
});
|
});
|
||||||
@@ -84,25 +84,17 @@ module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
|
|||||||
module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
||||||
babelrc: false,
|
babelrc: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
assumptions: {
|
|
||||||
privateFieldsAsProperties: true,
|
|
||||||
setPublicClassFields: true,
|
|
||||||
setSpreadProperties: true,
|
|
||||||
},
|
|
||||||
browserslistEnv: latestBuild ? "modern" : "legacy",
|
|
||||||
// Must be unambiguous because some dependencies are CommonJS only
|
|
||||||
sourceType: "unambiguous",
|
|
||||||
presets: [
|
presets: [
|
||||||
[
|
!latestBuild && [
|
||||||
"@babel/preset-env",
|
"@babel/preset-env",
|
||||||
{
|
{
|
||||||
useBuiltIns: latestBuild ? false : "entry",
|
useBuiltIns: "entry",
|
||||||
corejs: latestBuild ? false : { version: "3.30", proposals: true },
|
corejs: { version: "3.29", proposals: true },
|
||||||
bugfixes: true,
|
bugfixes: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"@babel/preset-typescript",
|
"@babel/preset-typescript",
|
||||||
],
|
].filter(Boolean),
|
||||||
plugins: [
|
plugins: [
|
||||||
[
|
[
|
||||||
path.resolve(
|
path.resolve(
|
||||||
@@ -114,6 +106,22 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
|||||||
ignoreModuleNotFound: true,
|
ignoreModuleNotFound: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
// Part of ES2018. Converts {...a, b: 2} to Object.assign({}, a, {b: 2})
|
||||||
|
!latestBuild && [
|
||||||
|
"@babel/plugin-proposal-object-rest-spread",
|
||||||
|
{ loose: true, useBuiltIns: true },
|
||||||
|
],
|
||||||
|
// Only support the syntax, Webpack will handle it.
|
||||||
|
"@babel/plugin-syntax-import-meta",
|
||||||
|
"@babel/plugin-syntax-dynamic-import",
|
||||||
|
"@babel/plugin-syntax-top-level-await",
|
||||||
|
// Support various proposals
|
||||||
|
"@babel/plugin-proposal-optional-chaining",
|
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||||
|
["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
|
||||||
|
["@babel/plugin-proposal-private-methods", { loose: true }],
|
||||||
|
["@babel/plugin-proposal-private-property-in-object", { loose: true }],
|
||||||
|
["@babel/plugin-proposal-class-properties", { loose: true }],
|
||||||
// Minify template literals for production
|
// Minify template literals for production
|
||||||
isProdBuild && [
|
isProdBuild && [
|
||||||
"template-html-minifier",
|
"template-html-minifier",
|
||||||
@@ -131,13 +139,6 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
|||||||
failOnError: true, // we can turn this off in case of false positives
|
failOnError: true, // we can turn this off in case of false positives
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
// Import helpers and regenerator from runtime package
|
|
||||||
[
|
|
||||||
"@babel/plugin-transform-runtime",
|
|
||||||
{ version: require("../package.json").dependencies["@babel/runtime"] },
|
|
||||||
],
|
|
||||||
// Support some proposals still in TC39 process
|
|
||||||
["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
|
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
exclude: [
|
exclude: [
|
||||||
// \\ for Windows, / for Mac OS and Linux
|
// \\ for Windows, / for Mac OS and Linux
|
||||||
@@ -156,7 +157,7 @@ const publicPath = (latestBuild, root = "") =>
|
|||||||
latestBuild ? `${root}/frontend_latest/` : `${root}/frontend_es5/`;
|
latestBuild ? `${root}/frontend_latest/` : `${root}/frontend_es5/`;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
BundleConfig {
|
BundleConfig {
|
||||||
// Object with entrypoints that need to be bundled
|
// Object with entrypoints that need to be bundled
|
||||||
entry: { [name: string]: pathToFile },
|
entry: { [name: string]: pathToFile },
|
||||||
// Folder where bundled files need to be written
|
// Folder where bundled files need to be written
|
||||||
@@ -175,8 +176,8 @@ const publicPath = (latestBuild, root = "") =>
|
|||||||
isTestBuild: boolean,
|
isTestBuild: boolean,
|
||||||
// Names of entrypoints that should not be hashed
|
// Names of entrypoints that should not be hashed
|
||||||
dontHash: Set<string>
|
dontHash: Set<string>
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports.config = {
|
module.exports.config = {
|
||||||
app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild, isWDS }) {
|
app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild, isWDS }) {
|
||||||
@@ -259,7 +260,6 @@ module.exports.config = {
|
|||||||
isHassioBuild: true,
|
isHassioBuild: true,
|
||||||
defineOverlay: {
|
defineOverlay: {
|
||||||
__SUPERVISOR__: true,
|
__SUPERVISOR__: true,
|
||||||
__STATIC_PATH__: `"${paths.hassio_publicPath}/static/"`,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@@ -1,16 +1,18 @@
|
|||||||
import gulp from "gulp";
|
// Run HA develop mode
|
||||||
import env from "../env.cjs";
|
|
||||||
import "./clean.js";
|
const gulp = require("gulp");
|
||||||
import "./compress.js";
|
const env = require("../env.cjs");
|
||||||
import "./entry-html.js";
|
require("./clean.cjs");
|
||||||
import "./gather-static.js";
|
require("./translations.cjs");
|
||||||
import "./gen-icons-json.js";
|
require("./locale-data.cjs");
|
||||||
import "./locale-data.js";
|
require("./gen-icons-json.cjs");
|
||||||
import "./rollup.js";
|
require("./gather-static.cjs");
|
||||||
import "./service-worker.js";
|
require("./compress.cjs");
|
||||||
import "./translations.js";
|
require("./webpack.cjs");
|
||||||
import "./wds.js";
|
require("./service-worker.cjs");
|
||||||
import "./webpack.js";
|
require("./entry-html.cjs");
|
||||||
|
require("./rollup.cjs");
|
||||||
|
require("./wds.cjs");
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-app",
|
"develop-app",
|
||||||
@@ -22,7 +24,8 @@ gulp.task(
|
|||||||
gulp.parallel(
|
gulp.parallel(
|
||||||
"gen-service-worker-app-dev",
|
"gen-service-worker-app-dev",
|
||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"gen-pages-app-dev",
|
"gen-pages-dev",
|
||||||
|
"gen-index-app-dev",
|
||||||
"build-translations",
|
"build-translations",
|
||||||
"build-locale-data"
|
"build-locale-data"
|
||||||
),
|
),
|
||||||
@@ -47,6 +50,10 @@ gulp.task(
|
|||||||
env.useRollup() ? "rollup-prod-app" : "webpack-prod-app",
|
env.useRollup() ? "rollup-prod-app" : "webpack-prod-app",
|
||||||
// Don't compress running tests
|
// Don't compress running tests
|
||||||
...(env.isTestBuild() ? [] : ["compress-app"]),
|
...(env.isTestBuild() ? [] : ["compress-app"]),
|
||||||
gulp.parallel("gen-pages-app-prod", "gen-service-worker-app-prod")
|
gulp.parallel(
|
||||||
|
"gen-pages-prod",
|
||||||
|
"gen-index-app-prod",
|
||||||
|
"gen-service-worker-app-prod"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
@@ -1,12 +1,13 @@
|
|||||||
import gulp from "gulp";
|
const gulp = require("gulp");
|
||||||
import env from "../env.cjs";
|
const env = require("../env.cjs");
|
||||||
import "./clean.js";
|
|
||||||
import "./entry-html.js";
|
require("./clean.cjs");
|
||||||
import "./gather-static.js";
|
require("./translations.cjs");
|
||||||
import "./rollup.js";
|
require("./gather-static.cjs");
|
||||||
import "./service-worker.js";
|
require("./webpack.cjs");
|
||||||
import "./translations.js";
|
require("./service-worker.cjs");
|
||||||
import "./webpack.js";
|
require("./entry-html.cjs");
|
||||||
|
require("./rollup.cjs");
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-cast",
|
"develop-cast",
|
||||||
@@ -18,7 +19,7 @@ gulp.task(
|
|||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||||
"copy-static-cast",
|
"copy-static-cast",
|
||||||
"gen-pages-cast-dev",
|
"gen-index-cast-dev",
|
||||||
env.useRollup() ? "rollup-dev-server-cast" : "webpack-dev-server-cast"
|
env.useRollup() ? "rollup-dev-server-cast" : "webpack-dev-server-cast"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -34,6 +35,6 @@ gulp.task(
|
|||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||||
"copy-static-cast",
|
"copy-static-cast",
|
||||||
env.useRollup() ? "rollup-prod-cast" : "webpack-prod-cast",
|
env.useRollup() ? "rollup-prod-cast" : "webpack-prod-cast",
|
||||||
"gen-pages-cast-prod"
|
"gen-index-cast-prod"
|
||||||
)
|
)
|
||||||
);
|
);
|
@@ -1,37 +1,37 @@
|
|||||||
import { deleteSync } from "del";
|
const del = import("del");
|
||||||
import gulp from "gulp";
|
const gulp = require("gulp");
|
||||||
import paths from "../paths.cjs";
|
const paths = require("../paths.cjs");
|
||||||
import "./translations.js";
|
require("./translations.cjs");
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean",
|
"clean",
|
||||||
gulp.parallel("clean-translations", async () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
deleteSync([paths.app_output_root, paths.build_dir])
|
(await del).deleteSync([paths.app_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-demo",
|
"clean-demo",
|
||||||
gulp.parallel("clean-translations", async () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
deleteSync([paths.demo_output_root, paths.build_dir])
|
(await del).deleteSync([paths.demo_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-cast",
|
"clean-cast",
|
||||||
gulp.parallel("clean-translations", async () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
deleteSync([paths.cast_output_root, paths.build_dir])
|
(await del).deleteSync([paths.cast_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("clean-hassio", async () =>
|
gulp.task("clean-hassio", async () =>
|
||||||
deleteSync([paths.hassio_output_root, paths.build_dir])
|
(await del).deleteSync([paths.hassio_output_root, paths.build_dir])
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-gallery",
|
"clean-gallery",
|
||||||
gulp.parallel("clean-translations", async () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
deleteSync([
|
(await del).deleteSync([
|
||||||
paths.gallery_output_root,
|
paths.gallery_output_root,
|
||||||
paths.gallery_build,
|
paths.gallery_build,
|
||||||
paths.build_dir,
|
paths.build_dir,
|
@@ -1,10 +1,10 @@
|
|||||||
// Tasks to compress
|
// Tasks to compress
|
||||||
|
|
||||||
import gulp from "gulp";
|
const gulp = require("gulp");
|
||||||
import zopfli from "gulp-zopfli-green";
|
const zopfli = require("gulp-zopfli-green");
|
||||||
import merge from "merge-stream";
|
const merge = require("merge-stream");
|
||||||
import path from "path";
|
const path = require("path");
|
||||||
import paths from "../paths.cjs";
|
const paths = require("../paths.cjs");
|
||||||
|
|
||||||
const zopfliOptions = { threshold: 150 };
|
const zopfliOptions = { threshold: 150 };
|
||||||
|
|
@@ -1,13 +1,15 @@
|
|||||||
import gulp from "gulp";
|
// Run demo develop mode
|
||||||
import env from "../env.cjs";
|
const gulp = require("gulp");
|
||||||
import "./clean.js";
|
const env = require("../env.cjs");
|
||||||
import "./entry-html.js";
|
|
||||||
import "./gather-static.js";
|
require("./clean.cjs");
|
||||||
import "./gen-icons-json.js";
|
require("./translations.cjs");
|
||||||
import "./rollup.js";
|
require("./gen-icons-json.cjs");
|
||||||
import "./service-worker.js";
|
require("./gather-static.cjs");
|
||||||
import "./translations.js";
|
require("./webpack.cjs");
|
||||||
import "./webpack.js";
|
require("./service-worker.cjs");
|
||||||
|
require("./entry-html.cjs");
|
||||||
|
require("./rollup.cjs");
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-demo",
|
"develop-demo",
|
||||||
@@ -19,7 +21,7 @@ gulp.task(
|
|||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel(
|
gulp.parallel(
|
||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"gen-pages-demo-dev",
|
"gen-index-demo-dev",
|
||||||
"build-translations",
|
"build-translations",
|
||||||
"build-locale-data"
|
"build-locale-data"
|
||||||
),
|
),
|
||||||
@@ -40,6 +42,6 @@ gulp.task(
|
|||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||||
"copy-static-demo",
|
"copy-static-demo",
|
||||||
env.useRollup() ? "rollup-prod-demo" : "webpack-prod-demo",
|
env.useRollup() ? "rollup-prod-demo" : "webpack-prod-demo",
|
||||||
"gen-pages-demo-prod"
|
"gen-index-demo-prod"
|
||||||
)
|
)
|
||||||
);
|
);
|
@@ -1,6 +1,6 @@
|
|||||||
import fs from "fs/promises";
|
const gulp = require("gulp");
|
||||||
import gulp from "gulp";
|
const fs = require("fs/promises");
|
||||||
import mapStream from "map-stream";
|
const mapStream = require("map-stream");
|
||||||
|
|
||||||
const inDirFrontend = "translations/frontend";
|
const inDirFrontend = "translations/frontend";
|
||||||
const inDirBackend = "translations/backend";
|
const inDirBackend = "translations/backend";
|
351
build-scripts/gulp/entry-html.cjs
Normal file
351
build-scripts/gulp/entry-html.cjs
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
// Tasks to generate entry HTML
|
||||||
|
const gulp = require("gulp");
|
||||||
|
const fs = require("fs-extra");
|
||||||
|
const path = require("path");
|
||||||
|
const template = require("lodash.template");
|
||||||
|
const { minify } = require("html-minifier-terser");
|
||||||
|
const paths = require("../paths.cjs");
|
||||||
|
const env = require("../env.cjs");
|
||||||
|
const { htmlMinifierOptions, terserOptions } = require("../bundle.cjs");
|
||||||
|
|
||||||
|
const templatePath = (tpl) =>
|
||||||
|
path.resolve(paths.polymer_dir, "src/html/", `${tpl}.html.template`);
|
||||||
|
|
||||||
|
const readFile = (pth) => fs.readFileSync(pth).toString();
|
||||||
|
|
||||||
|
const renderTemplate = (pth, data = {}, pathFunc = templatePath) => {
|
||||||
|
const compiled = template(readFile(pathFunc(pth)));
|
||||||
|
return compiled({
|
||||||
|
...data,
|
||||||
|
useRollup: env.useRollup(),
|
||||||
|
useWDS: env.useWDS(),
|
||||||
|
renderTemplate,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderDemoTemplate = (pth, data = {}) =>
|
||||||
|
renderTemplate(pth, data, (tpl) =>
|
||||||
|
path.resolve(paths.demo_dir, "src/html/", `${tpl}.html.template`)
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderCastTemplate = (pth, data = {}) =>
|
||||||
|
renderTemplate(pth, data, (tpl) =>
|
||||||
|
path.resolve(paths.cast_dir, "src/html/", `${tpl}.html.template`)
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderGalleryTemplate = (pth, data = {}) =>
|
||||||
|
renderTemplate(pth, data, (tpl) =>
|
||||||
|
path.resolve(paths.gallery_dir, "src/html/", `${tpl}.html.template`)
|
||||||
|
);
|
||||||
|
|
||||||
|
const minifyHtml = (content) =>
|
||||||
|
minify(content, {
|
||||||
|
...htmlMinifierOptions,
|
||||||
|
conservativeCollapse: false,
|
||||||
|
minifyJS: terserOptions({
|
||||||
|
latestBuild: false, // Shared scripts should be ES5
|
||||||
|
isTestBuild: true, // Don't need source maps
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const PAGES = ["onboarding", "authorize"];
|
||||||
|
|
||||||
|
gulp.task("gen-pages-dev", (done) => {
|
||||||
|
for (const page of PAGES) {
|
||||||
|
const content = renderTemplate(page, {
|
||||||
|
latestPageJS: `/frontend_latest/${page}.js`,
|
||||||
|
|
||||||
|
es5PageJS: `/frontend_es5/${page}.js`,
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.app_output_root, `${page}.html`),
|
||||||
|
content
|
||||||
|
);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-pages-prod", async () => {
|
||||||
|
const latestManifest = require(path.resolve(
|
||||||
|
paths.app_output_latest,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
const es5Manifest = require(path.resolve(
|
||||||
|
paths.app_output_es5,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
|
||||||
|
const minifiedHTML = [];
|
||||||
|
for (const page of PAGES) {
|
||||||
|
const content = renderTemplate(page, {
|
||||||
|
latestPageJS: latestManifest[`${page}.js`],
|
||||||
|
es5PageJS: es5Manifest[`${page}.js`],
|
||||||
|
});
|
||||||
|
|
||||||
|
minifiedHTML.push(
|
||||||
|
minifyHtml(content).then((minified) =>
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.app_output_root, `${page}.html`),
|
||||||
|
minified
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await Promise.all(minifiedHTML);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-app-dev", (done) => {
|
||||||
|
let latestAppJS;
|
||||||
|
let latestCoreJS;
|
||||||
|
let latestCustomPanelJS;
|
||||||
|
|
||||||
|
if (env.useWDS()) {
|
||||||
|
latestAppJS = "http://localhost:8000/src/entrypoints/app.ts";
|
||||||
|
latestCoreJS = "http://localhost:8000/src/entrypoints/core.ts";
|
||||||
|
latestCustomPanelJS =
|
||||||
|
"http://localhost:8000/src/entrypoints/custom-panel.ts";
|
||||||
|
} else {
|
||||||
|
latestAppJS = "/frontend_latest/app.js";
|
||||||
|
latestCoreJS = "/frontend_latest/core.js";
|
||||||
|
latestCustomPanelJS = "/frontend_latest/custom-panel.js";
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = renderTemplate("index", {
|
||||||
|
latestAppJS,
|
||||||
|
latestCoreJS,
|
||||||
|
latestCustomPanelJS,
|
||||||
|
|
||||||
|
es5AppJS: "/frontend_es5/app.js",
|
||||||
|
es5CoreJS: "/frontend_es5/core.js",
|
||||||
|
es5CustomPanelJS: "/frontend_es5/custom-panel.js",
|
||||||
|
}).replace(/#THEMEC/g, "{{ theme_color }}");
|
||||||
|
|
||||||
|
fs.outputFileSync(path.resolve(paths.app_output_root, "index.html"), content);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-app-prod", async () => {
|
||||||
|
const latestManifest = require(path.resolve(
|
||||||
|
paths.app_output_latest,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
const es5Manifest = require(path.resolve(
|
||||||
|
paths.app_output_es5,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
const content = renderTemplate("index", {
|
||||||
|
latestAppJS: latestManifest["app.js"],
|
||||||
|
latestCoreJS: latestManifest["core.js"],
|
||||||
|
latestCustomPanelJS: latestManifest["custom-panel.js"],
|
||||||
|
|
||||||
|
es5AppJS: es5Manifest["app.js"],
|
||||||
|
es5CoreJS: es5Manifest["core.js"],
|
||||||
|
es5CustomPanelJS: es5Manifest["custom-panel.js"],
|
||||||
|
});
|
||||||
|
const minified = (await minifyHtml(content)).replace(
|
||||||
|
/#THEMEC/g,
|
||||||
|
"{{ theme_color }}"
|
||||||
|
);
|
||||||
|
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.app_output_root, "index.html"),
|
||||||
|
minified
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-cast-dev", (done) => {
|
||||||
|
const contentReceiver = renderCastTemplate("receiver", {
|
||||||
|
latestReceiverJS: "/frontend_latest/receiver.js",
|
||||||
|
});
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.cast_output_root, "receiver.html"),
|
||||||
|
contentReceiver
|
||||||
|
);
|
||||||
|
|
||||||
|
const contentMedia = renderCastTemplate("media", {
|
||||||
|
latestMediaJS: "/frontend_latest/media.js",
|
||||||
|
es5MediaJS: "/frontend_es5/media.js",
|
||||||
|
});
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.cast_output_root, "media.html"),
|
||||||
|
contentMedia
|
||||||
|
);
|
||||||
|
|
||||||
|
const contentFAQ = renderCastTemplate("launcher-faq", {
|
||||||
|
latestLauncherJS: "/frontend_latest/launcher.js",
|
||||||
|
es5LauncherJS: "/frontend_es5/launcher.js",
|
||||||
|
});
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.cast_output_root, "faq.html"),
|
||||||
|
contentFAQ
|
||||||
|
);
|
||||||
|
|
||||||
|
const contentLauncher = renderCastTemplate("launcher", {
|
||||||
|
latestLauncherJS: "/frontend_latest/launcher.js",
|
||||||
|
es5LauncherJS: "/frontend_es5/launcher.js",
|
||||||
|
});
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.cast_output_root, "index.html"),
|
||||||
|
contentLauncher
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-cast-prod", (done) => {
|
||||||
|
const latestManifest = require(path.resolve(
|
||||||
|
paths.cast_output_latest,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
const es5Manifest = require(path.resolve(
|
||||||
|
paths.cast_output_es5,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
|
||||||
|
const contentReceiver = renderCastTemplate("receiver", {
|
||||||
|
latestReceiverJS: latestManifest["receiver.js"],
|
||||||
|
});
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.cast_output_root, "receiver.html"),
|
||||||
|
contentReceiver
|
||||||
|
);
|
||||||
|
|
||||||
|
const contentMedia = renderCastTemplate("media", {
|
||||||
|
latestMediaJS: latestManifest["media.js"],
|
||||||
|
es5MediaJS: es5Manifest["media.js"],
|
||||||
|
});
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.cast_output_root, "media.html"),
|
||||||
|
contentMedia
|
||||||
|
);
|
||||||
|
|
||||||
|
const contentFAQ = renderCastTemplate("launcher-faq", {
|
||||||
|
latestLauncherJS: latestManifest["launcher.js"],
|
||||||
|
es5LauncherJS: es5Manifest["launcher.js"],
|
||||||
|
});
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.cast_output_root, "faq.html"),
|
||||||
|
contentFAQ
|
||||||
|
);
|
||||||
|
|
||||||
|
const contentLauncher = renderCastTemplate("launcher", {
|
||||||
|
latestLauncherJS: latestManifest["launcher.js"],
|
||||||
|
es5LauncherJS: es5Manifest["launcher.js"],
|
||||||
|
});
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.cast_output_root, "index.html"),
|
||||||
|
contentLauncher
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-demo-dev", (done) => {
|
||||||
|
const content = renderDemoTemplate("index", {
|
||||||
|
latestDemoJS: "/frontend_latest/main.js",
|
||||||
|
|
||||||
|
es5DemoJS: "/frontend_es5/main.js",
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.demo_output_root, "index.html"),
|
||||||
|
content
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-demo-prod", async () => {
|
||||||
|
const latestManifest = require(path.resolve(
|
||||||
|
paths.demo_output_latest,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
const es5Manifest = require(path.resolve(
|
||||||
|
paths.demo_output_es5,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
const content = renderDemoTemplate("index", {
|
||||||
|
latestDemoJS: latestManifest["main.js"],
|
||||||
|
|
||||||
|
es5DemoJS: es5Manifest["main.js"],
|
||||||
|
});
|
||||||
|
const minified = await minifyHtml(content);
|
||||||
|
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.demo_output_root, "index.html"),
|
||||||
|
minified
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-gallery-dev", (done) => {
|
||||||
|
const content = renderGalleryTemplate("index", {
|
||||||
|
latestGalleryJS: "./frontend_latest/entrypoint.js",
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.gallery_output_root, "index.html"),
|
||||||
|
content
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-gallery-prod", async () => {
|
||||||
|
const latestManifest = require(path.resolve(
|
||||||
|
paths.gallery_output_latest,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
const content = renderGalleryTemplate("index", {
|
||||||
|
latestGalleryJS: latestManifest["entrypoint.js"],
|
||||||
|
});
|
||||||
|
const minified = await minifyHtml(content);
|
||||||
|
|
||||||
|
fs.outputFileSync(
|
||||||
|
path.resolve(paths.gallery_output_root, "index.html"),
|
||||||
|
minified
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-hassio-dev", async () => {
|
||||||
|
writeHassioEntrypoint(
|
||||||
|
`${paths.hassio_publicPath}/frontend_latest/entrypoint.js`,
|
||||||
|
`${paths.hassio_publicPath}/frontend_es5/entrypoint.js`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("gen-index-hassio-prod", async () => {
|
||||||
|
const latestManifest = require(path.resolve(
|
||||||
|
paths.hassio_output_latest,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
const es5Manifest = require(path.resolve(
|
||||||
|
paths.hassio_output_es5,
|
||||||
|
"manifest.json"
|
||||||
|
));
|
||||||
|
writeHassioEntrypoint(
|
||||||
|
latestManifest["entrypoint.js"],
|
||||||
|
es5Manifest["entrypoint.js"]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
function writeHassioEntrypoint(latestEntrypoint, es5Entrypoint) {
|
||||||
|
fs.mkdirSync(paths.hassio_output_root, { recursive: true });
|
||||||
|
// Safari 12 and below does not have a compliant ES2015 implementation of template literals, so we ship ES5
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.resolve(paths.hassio_output_root, "entrypoint.js"),
|
||||||
|
`
|
||||||
|
function loadES5() {
|
||||||
|
var el = document.createElement('script');
|
||||||
|
el.src = '${es5Entrypoint}';
|
||||||
|
document.body.appendChild(el);
|
||||||
|
}
|
||||||
|
if (/.*Version\\/(?:11|12)(?:\\.\\d+)*.*Safari\\//.test(navigator.userAgent)) {
|
||||||
|
loadES5();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
new Function("import('${latestEntrypoint}')")();
|
||||||
|
} catch (err) {
|
||||||
|
loadES5();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
{ encoding: "utf-8" }
|
||||||
|
);
|
||||||
|
}
|
@@ -1,233 +0,0 @@
|
|||||||
// Tasks to generate entry HTML
|
|
||||||
|
|
||||||
import fs from "fs-extra";
|
|
||||||
import gulp from "gulp";
|
|
||||||
import { minify } from "html-minifier-terser";
|
|
||||||
import template from "lodash.template";
|
|
||||||
import path from "path";
|
|
||||||
import { htmlMinifierOptions, terserOptions } from "../bundle.cjs";
|
|
||||||
import env from "../env.cjs";
|
|
||||||
import paths from "../paths.cjs";
|
|
||||||
|
|
||||||
const renderTemplate = (templateFile, data = {}) => {
|
|
||||||
const compiled = template(
|
|
||||||
fs.readFileSync(templateFile, { encoding: "utf-8" })
|
|
||||||
);
|
|
||||||
return compiled({
|
|
||||||
...data,
|
|
||||||
useRollup: env.useRollup(),
|
|
||||||
useWDS: env.useWDS(),
|
|
||||||
// Resolve any child/nested templates relative to the parent and pass the same data
|
|
||||||
renderTemplate: (childTemplate) =>
|
|
||||||
renderTemplate(
|
|
||||||
path.resolve(path.dirname(templateFile), childTemplate),
|
|
||||||
data
|
|
||||||
),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const WRAP_TAGS = { ".js": "script", ".css": "style" };
|
|
||||||
|
|
||||||
const minifyHtml = (content, ext) => {
|
|
||||||
const wrapTag = WRAP_TAGS[ext] || "";
|
|
||||||
const begTag = wrapTag && `<${wrapTag}>`;
|
|
||||||
const endTag = wrapTag && `</${wrapTag}>`;
|
|
||||||
return minify(begTag + content + endTag, {
|
|
||||||
...htmlMinifierOptions,
|
|
||||||
conservativeCollapse: false,
|
|
||||||
minifyJS: terserOptions({
|
|
||||||
latestBuild: false, // Shared scripts should be ES5
|
|
||||||
isTestBuild: true, // Don't need source maps
|
|
||||||
}),
|
|
||||||
}).then((wrapped) =>
|
|
||||||
wrapTag ? wrapped.slice(begTag.length, -endTag.length) : wrapped
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function to generate a dev task for each project's configuration
|
|
||||||
// Note Currently WDS paths are hard-coded to only work for app
|
|
||||||
const genPagesDevTask =
|
|
||||||
(
|
|
||||||
pageEntries,
|
|
||||||
inputRoot,
|
|
||||||
outputRoot,
|
|
||||||
useWDS = false,
|
|
||||||
inputSub = "src/html",
|
|
||||||
publicRoot = ""
|
|
||||||
) =>
|
|
||||||
async () => {
|
|
||||||
for (const [page, entries] of Object.entries(pageEntries)) {
|
|
||||||
const content = renderTemplate(
|
|
||||||
path.resolve(inputRoot, inputSub, `${page}.template`),
|
|
||||||
{
|
|
||||||
latestEntryJS: entries.map((entry) =>
|
|
||||||
useWDS
|
|
||||||
? `http://localhost:8000/src/entrypoints/${entry}.ts`
|
|
||||||
: `${publicRoot}/frontend_latest/${entry}.js`
|
|
||||||
),
|
|
||||||
es5EntryJS: entries.map(
|
|
||||||
(entry) => `${publicRoot}/frontend_es5/${entry}.js`
|
|
||||||
),
|
|
||||||
latestCustomPanelJS: useWDS
|
|
||||||
? "http://localhost:8000/src/entrypoints/custom-panel.ts"
|
|
||||||
: `${publicRoot}/frontend_latest/custom-panel.js`,
|
|
||||||
es5CustomPanelJS: `${publicRoot}/frontend_es5/custom-panel.js`,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
fs.outputFileSync(path.resolve(outputRoot, page), content);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Same as previous but for production builds
|
|
||||||
// (includes minification and hashed file names from manifest)
|
|
||||||
const genPagesProdTask =
|
|
||||||
(
|
|
||||||
pageEntries,
|
|
||||||
inputRoot,
|
|
||||||
outputRoot,
|
|
||||||
outputLatest,
|
|
||||||
outputES5,
|
|
||||||
inputSub = "src/html"
|
|
||||||
) =>
|
|
||||||
async () => {
|
|
||||||
const latestManifest = fs.readJsonSync(
|
|
||||||
path.resolve(outputLatest, "manifest.json")
|
|
||||||
);
|
|
||||||
const es5Manifest = outputES5
|
|
||||||
? fs.readJsonSync(path.resolve(outputES5, "manifest.json"))
|
|
||||||
: {};
|
|
||||||
const minifiedHTML = [];
|
|
||||||
for (const [page, entries] of Object.entries(pageEntries)) {
|
|
||||||
const content = renderTemplate(
|
|
||||||
path.resolve(inputRoot, inputSub, `${page}.template`),
|
|
||||||
{
|
|
||||||
latestEntryJS: entries.map((entry) => latestManifest[`${entry}.js`]),
|
|
||||||
es5EntryJS: entries.map((entry) => es5Manifest[`${entry}.js`]),
|
|
||||||
latestCustomPanelJS: latestManifest["custom-panel.js"],
|
|
||||||
es5CustomPanelJS: es5Manifest["custom-panel.js"],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
minifiedHTML.push(
|
|
||||||
minifyHtml(content, path.extname(page)).then((minified) =>
|
|
||||||
fs.outputFileSync(path.resolve(outputRoot, page), minified)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await Promise.all(minifiedHTML);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Map HTML pages to their required entrypoints
|
|
||||||
const APP_PAGE_ENTRIES = {
|
|
||||||
"authorize.html": ["authorize"],
|
|
||||||
"onboarding.html": ["onboarding"],
|
|
||||||
"index.html": ["core", "app"],
|
|
||||||
};
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-app-dev",
|
|
||||||
genPagesDevTask(
|
|
||||||
APP_PAGE_ENTRIES,
|
|
||||||
paths.polymer_dir,
|
|
||||||
paths.app_output_root,
|
|
||||||
env.useWDS()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-app-prod",
|
|
||||||
genPagesProdTask(
|
|
||||||
APP_PAGE_ENTRIES,
|
|
||||||
paths.polymer_dir,
|
|
||||||
paths.app_output_root,
|
|
||||||
paths.app_output_latest,
|
|
||||||
paths.app_output_es5
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const CAST_PAGE_ENTRIES = {
|
|
||||||
"faq.html": ["launcher"],
|
|
||||||
"index.html": ["launcher"],
|
|
||||||
"media.html": ["media"],
|
|
||||||
"receiver.html": ["receiver"],
|
|
||||||
};
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-cast-dev",
|
|
||||||
genPagesDevTask(CAST_PAGE_ENTRIES, paths.cast_dir, paths.cast_output_root)
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-cast-prod",
|
|
||||||
genPagesProdTask(
|
|
||||||
CAST_PAGE_ENTRIES,
|
|
||||||
paths.cast_dir,
|
|
||||||
paths.cast_output_root,
|
|
||||||
paths.cast_output_latest,
|
|
||||||
paths.cast_output_es5
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const DEMO_PAGE_ENTRIES = { "index.html": ["main"] };
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-demo-dev",
|
|
||||||
genPagesDevTask(DEMO_PAGE_ENTRIES, paths.demo_dir, paths.demo_output_root)
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-demo-prod",
|
|
||||||
genPagesProdTask(
|
|
||||||
DEMO_PAGE_ENTRIES,
|
|
||||||
paths.demo_dir,
|
|
||||||
paths.demo_output_root,
|
|
||||||
paths.demo_output_latest,
|
|
||||||
paths.demo_output_es5
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const GALLERY_PAGE_ENTRIES = { "index.html": ["entrypoint"] };
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-gallery-dev",
|
|
||||||
genPagesDevTask(
|
|
||||||
GALLERY_PAGE_ENTRIES,
|
|
||||||
paths.gallery_dir,
|
|
||||||
paths.gallery_output_root
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-gallery-prod",
|
|
||||||
genPagesProdTask(
|
|
||||||
GALLERY_PAGE_ENTRIES,
|
|
||||||
paths.gallery_dir,
|
|
||||||
paths.gallery_output_root,
|
|
||||||
paths.gallery_output_latest
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const HASSIO_PAGE_ENTRIES = { "entrypoint.js": ["entrypoint"] };
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-hassio-dev",
|
|
||||||
genPagesDevTask(
|
|
||||||
HASSIO_PAGE_ENTRIES,
|
|
||||||
paths.hassio_dir,
|
|
||||||
paths.hassio_output_root,
|
|
||||||
undefined,
|
|
||||||
"src",
|
|
||||||
paths.hassio_publicPath
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"gen-pages-hassio-prod",
|
|
||||||
genPagesProdTask(
|
|
||||||
HASSIO_PAGE_ENTRIES,
|
|
||||||
paths.hassio_dir,
|
|
||||||
paths.hassio_output_root,
|
|
||||||
paths.hassio_output_latest,
|
|
||||||
paths.hassio_output_es5,
|
|
||||||
"src"
|
|
||||||
)
|
|
||||||
);
|
|
@@ -1,15 +1,14 @@
|
|||||||
// Task to download the latest Lokalise translations from the nightly workflow artifacts
|
// Task to download the latest Lokalise translations from the nightly workflow artifacts
|
||||||
|
|
||||||
import { createOAuthDeviceAuth } from "@octokit/auth-oauth-device";
|
const del = import("del");
|
||||||
import { retry } from "@octokit/plugin-retry";
|
const fs = require("fs/promises");
|
||||||
import { Octokit } from "@octokit/rest";
|
const path = require("path");
|
||||||
import { deleteAsync } from "del";
|
const process = require("process");
|
||||||
import { mkdir, readFile, writeFile } from "fs/promises";
|
const gulp = require("gulp");
|
||||||
import gulp from "gulp";
|
const jszip = require("jszip");
|
||||||
import jszip from "jszip";
|
const tar = require("tar");
|
||||||
import path from "path";
|
const { Octokit } = require("@octokit/rest");
|
||||||
import process from "process";
|
const { createOAuthDeviceAuth } = require("@octokit/auth-oauth-device");
|
||||||
import tar from "tar";
|
|
||||||
|
|
||||||
const MAX_AGE = 24; // hours
|
const MAX_AGE = 24; // hours
|
||||||
const OWNER = "home-assistant";
|
const OWNER = "home-assistant";
|
||||||
@@ -38,7 +37,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
// and stop if they are not old enough
|
// and stop if they are not old enough
|
||||||
let currentArtifact;
|
let currentArtifact;
|
||||||
try {
|
try {
|
||||||
currentArtifact = JSON.parse(await readFile(ARTIFACT_FILE, "utf-8"));
|
currentArtifact = JSON.parse(await fs.readFile(ARTIFACT_FILE, "utf-8"));
|
||||||
const currentAge =
|
const currentAge =
|
||||||
(Date.now() - Date.parse(currentArtifact.created_at)) / 3600000;
|
(Date.now() - Date.parse(currentArtifact.created_at)) / 3600000;
|
||||||
if (currentAge < MAX_AGE) {
|
if (currentAge < MAX_AGE) {
|
||||||
@@ -53,7 +52,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// To store file writing promises
|
// To store file writing promises
|
||||||
const createExtractDir = mkdir(EXTRACT_DIR, { recursive: true });
|
const createExtractDir = fs.mkdir(EXTRACT_DIR, { recursive: true });
|
||||||
const writings = [];
|
const writings = [];
|
||||||
|
|
||||||
// Authenticate to GitHub using GitHub action token if it exists,
|
// Authenticate to GitHub using GitHub action token if it exists,
|
||||||
@@ -63,7 +62,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
tokenAuth = { token: process.env.GITHUB_TOKEN };
|
tokenAuth = { token: process.env.GITHUB_TOKEN };
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
tokenAuth = JSON.parse(await readFile(TOKEN_FILE, "utf-8"));
|
tokenAuth = JSON.parse(await fs.readFile(TOKEN_FILE, "utf-8"));
|
||||||
} catch {
|
} catch {
|
||||||
if (!allowTokenSetup) {
|
if (!allowTokenSetup) {
|
||||||
console.log("No token found so build wil continue with English only");
|
console.log("No token found so build wil continue with English only");
|
||||||
@@ -88,7 +87,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
tokenAuth = await auth({ type: "oauth" });
|
tokenAuth = await auth({ type: "oauth" });
|
||||||
writings.push(
|
writings.push(
|
||||||
createExtractDir.then(
|
createExtractDir.then(
|
||||||
writeFile(TOKEN_FILE, JSON.stringify(tokenAuth, null, 2))
|
fs.writeFile(TOKEN_FILE, JSON.stringify(tokenAuth, null, 2))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -96,7 +95,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
|
|
||||||
// Authenticate with token and request workflow runs from GitHub
|
// Authenticate with token and request workflow runs from GitHub
|
||||||
console.log("Fetching new translations...");
|
console.log("Fetching new translations...");
|
||||||
const octokit = new (Octokit.plugin(retry))({
|
const octokit = new Octokit({
|
||||||
userAgent: "Fetch Nightly Translations",
|
userAgent: "Fetch Nightly Translations",
|
||||||
auth: tokenAuth.token,
|
auth: tokenAuth.token,
|
||||||
});
|
});
|
||||||
@@ -132,13 +131,17 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
}
|
}
|
||||||
writings.push(
|
writings.push(
|
||||||
createExtractDir.then(
|
createExtractDir.then(
|
||||||
writeFile(ARTIFACT_FILE, JSON.stringify(latestArtifact, null, 2))
|
fs.writeFile(ARTIFACT_FILE, JSON.stringify(latestArtifact, null, 2))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Remove the current translations
|
// Remove the current translations
|
||||||
const deleteCurrent = Promise.all(writings).then(
|
const deleteCurrent = Promise.all(writings).then(
|
||||||
deleteAsync([`${EXTRACT_DIR}/*`, `!${ARTIFACT_FILE}`, `!${TOKEN_FILE}`])
|
(await del).deleteAsync([
|
||||||
|
`${EXTRACT_DIR}/*`,
|
||||||
|
`!${ARTIFACT_FILE}`,
|
||||||
|
`!${TOKEN_FILE}`,
|
||||||
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get the download URL and follow the redirect to download (stored as ArrayBuffer)
|
// Get the download URL and follow the redirect to download (stored as ArrayBuffer)
|
@@ -1,19 +1,22 @@
|
|||||||
import fs from "fs";
|
// Run demo develop mode
|
||||||
import { glob } from "glob";
|
const gulp = require("gulp");
|
||||||
import gulp from "gulp";
|
const fs = require("fs");
|
||||||
import yaml from "js-yaml";
|
const path = require("path");
|
||||||
import { marked } from "marked";
|
const { marked } = require("marked");
|
||||||
import path from "path";
|
const glob = require("glob");
|
||||||
import env from "../env.cjs";
|
const yaml = require("js-yaml");
|
||||||
import paths from "../paths.cjs";
|
|
||||||
import "./clean.js";
|
const env = require("../env.cjs");
|
||||||
import "./entry-html.js";
|
const paths = require("../paths.cjs");
|
||||||
import "./gather-static.js";
|
|
||||||
import "./gen-icons-json.js";
|
require("./clean.cjs");
|
||||||
import "./rollup.js";
|
require("./translations.cjs");
|
||||||
import "./service-worker.js";
|
require("./gen-icons-json.cjs");
|
||||||
import "./translations.js";
|
require("./gather-static.cjs");
|
||||||
import "./webpack.js";
|
require("./webpack.cjs");
|
||||||
|
require("./service-worker.cjs");
|
||||||
|
require("./entry-html.cjs");
|
||||||
|
require("./rollup.cjs");
|
||||||
|
|
||||||
gulp.task("gather-gallery-pages", async function gatherPages() {
|
gulp.task("gather-gallery-pages", async function gatherPages() {
|
||||||
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
|
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
|
||||||
@@ -156,7 +159,7 @@ gulp.task(
|
|||||||
"gather-gallery-pages"
|
"gather-gallery-pages"
|
||||||
),
|
),
|
||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
"gen-pages-gallery-dev",
|
"gen-index-gallery-dev",
|
||||||
gulp.parallel(
|
gulp.parallel(
|
||||||
env.useRollup()
|
env.useRollup()
|
||||||
? "rollup-dev-server-gallery"
|
? "rollup-dev-server-gallery"
|
||||||
@@ -190,6 +193,6 @@ gulp.task(
|
|||||||
),
|
),
|
||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
env.useRollup() ? "rollup-prod-gallery" : "webpack-prod-gallery",
|
env.useRollup() ? "rollup-prod-gallery" : "webpack-prod-gallery",
|
||||||
"gen-pages-gallery-prod"
|
"gen-index-gallery-prod"
|
||||||
)
|
)
|
||||||
);
|
);
|
@@ -1,9 +1,9 @@
|
|||||||
// Gulp task to gather all static files.
|
// Gulp task to gather all static files.
|
||||||
|
|
||||||
import fs from "fs-extra";
|
const gulp = require("gulp");
|
||||||
import gulp from "gulp";
|
const path = require("path");
|
||||||
import path from "path";
|
const fs = require("fs-extra");
|
||||||
import paths from "../paths.cjs";
|
const paths = require("../paths.cjs");
|
||||||
|
|
||||||
const npmPath = (...parts) =>
|
const npmPath = (...parts) =>
|
||||||
path.resolve(paths.polymer_dir, "node_modules", ...parts);
|
path.resolve(paths.polymer_dir, "node_modules", ...parts);
|
||||||
@@ -111,10 +111,9 @@ gulp.task("copy-translations-supervisor", async () => {
|
|||||||
copyTranslations(staticDir);
|
copyTranslations(staticDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("copy-static-supervisor", async () => {
|
gulp.task("copy-locale-data-supervisor", async () => {
|
||||||
const staticDir = paths.hassio_output_static;
|
const staticDir = paths.hassio_output_static;
|
||||||
copyLocaleData(staticDir);
|
copyLocaleData(staticDir);
|
||||||
copyFonts(staticDir);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("copy-static-app", async () => {
|
gulp.task("copy-static-app", async () => {
|
@@ -1,15 +1,17 @@
|
|||||||
import fs from "fs";
|
const gulp = require("gulp");
|
||||||
import gulp from "gulp";
|
const path = require("path");
|
||||||
import hash from "object-hash";
|
const fs = require("fs");
|
||||||
import path from "path";
|
const hash = require("object-hash");
|
||||||
import paths from "../paths.cjs";
|
|
||||||
|
|
||||||
const ICON_PACKAGE_PATH = path.resolve("node_modules/@mdi/svg/");
|
const ICON_PACKAGE_PATH = path.resolve(
|
||||||
|
__dirname,
|
||||||
|
"../../node_modules/@mdi/svg/"
|
||||||
|
);
|
||||||
const META_PATH = path.resolve(ICON_PACKAGE_PATH, "meta.json");
|
const META_PATH = path.resolve(ICON_PACKAGE_PATH, "meta.json");
|
||||||
const PACKAGE_PATH = path.resolve(ICON_PACKAGE_PATH, "package.json");
|
const PACKAGE_PATH = path.resolve(ICON_PACKAGE_PATH, "package.json");
|
||||||
const ICON_PATH = path.resolve(ICON_PACKAGE_PATH, "svg");
|
const ICON_PATH = path.resolve(ICON_PACKAGE_PATH, "svg");
|
||||||
const OUTPUT_DIR = path.resolve(paths.build_dir, "mdi");
|
const OUTPUT_DIR = path.resolve(__dirname, "../../build/mdi");
|
||||||
const REMOVED_ICONS_PATH = new URL("../removedIcons.json", import.meta.url);
|
const REMOVED_ICONS_PATH = path.resolve(__dirname, "../removedIcons.json");
|
||||||
|
|
||||||
const encoding = "utf8";
|
const encoding = "utf8";
|
||||||
|
|
@@ -1,13 +1,13 @@
|
|||||||
import gulp from "gulp";
|
const gulp = require("gulp");
|
||||||
import env from "../env.cjs";
|
const env = require("../env.cjs");
|
||||||
import "./clean.js";
|
require("./clean.cjs");
|
||||||
import "./compress.js";
|
require("./compress.cjs");
|
||||||
import "./entry-html.js";
|
require("./entry-html.cjs");
|
||||||
import "./gather-static.js";
|
require("./gather-static.cjs");
|
||||||
import "./gen-icons-json.js";
|
require("./gen-icons-json.cjs");
|
||||||
import "./rollup.js";
|
require("./rollup.cjs");
|
||||||
import "./translations.js";
|
require("./translations.cjs");
|
||||||
import "./webpack.js";
|
require("./webpack.cjs");
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-hassio",
|
"develop-hassio",
|
||||||
@@ -17,11 +17,11 @@ gulp.task(
|
|||||||
},
|
},
|
||||||
"clean-hassio",
|
"clean-hassio",
|
||||||
"gen-dummy-icons-json",
|
"gen-dummy-icons-json",
|
||||||
"gen-pages-hassio-dev",
|
"gen-index-hassio-dev",
|
||||||
"build-supervisor-translations",
|
"build-supervisor-translations",
|
||||||
"copy-translations-supervisor",
|
"copy-translations-supervisor",
|
||||||
"build-locale-data",
|
"build-locale-data",
|
||||||
"copy-static-supervisor",
|
"copy-locale-data-supervisor",
|
||||||
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -37,9 +37,9 @@ gulp.task(
|
|||||||
"build-supervisor-translations",
|
"build-supervisor-translations",
|
||||||
"copy-translations-supervisor",
|
"copy-translations-supervisor",
|
||||||
"build-locale-data",
|
"build-locale-data",
|
||||||
"copy-static-supervisor",
|
"copy-locale-data-supervisor",
|
||||||
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
||||||
"gen-pages-hassio-prod",
|
"gen-index-hassio-prod",
|
||||||
...// Don't compress running tests
|
...// Don't compress running tests
|
||||||
(env.isTestBuild() ? [] : ["compress-hassio"])
|
(env.isTestBuild() ? [] : ["compress-hassio"])
|
||||||
)
|
)
|
@@ -1,22 +1,24 @@
|
|||||||
import { deleteSync } from "del";
|
const del = import("del");
|
||||||
import fs from "fs";
|
const path = require("path");
|
||||||
import gulp from "gulp";
|
const gulp = require("gulp");
|
||||||
import path from "path";
|
const fs = require("fs");
|
||||||
import paths from "../paths.cjs";
|
const paths = require("../paths.cjs");
|
||||||
|
|
||||||
const outDir = "build/locale-data";
|
const outDir = "build/locale-data";
|
||||||
|
|
||||||
gulp.task("clean-locale-data", async () => deleteSync([outDir]));
|
gulp.task("clean-locale-data", async () => (await del).deleteSync([outDir]));
|
||||||
|
|
||||||
gulp.task("ensure-locale-data-build-dir", async () => {
|
gulp.task("ensure-locale-data-build-dir", (done) => {
|
||||||
|
if (!fs.existsSync(outDir)) {
|
||||||
fs.mkdirSync(outDir, { recursive: true });
|
fs.mkdirSync(outDir, { recursive: true });
|
||||||
|
}
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
const modules = {
|
const modules = {
|
||||||
"intl-relativetimeformat": "RelativeTimeFormat",
|
"intl-relativetimeformat": "RelativeTimeFormat",
|
||||||
"intl-datetimeformat": "DateTimeFormat",
|
"intl-datetimeformat": "DateTimeFormat",
|
||||||
"intl-numberformat": "NumberFormat",
|
"intl-numberformat": "NumberFormat",
|
||||||
"intl-displaynames": "DisplayNames",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
gulp.task("create-locale-data", (done) => {
|
gulp.task("create-locale-data", (done) => {
|
||||||
@@ -28,13 +30,10 @@ gulp.task("create-locale-data", (done) => {
|
|||||||
Object.entries(modules).forEach(([module, className]) => {
|
Object.entries(modules).forEach(([module, className]) => {
|
||||||
Object.keys(translationMeta).forEach((lang) => {
|
Object.keys(translationMeta).forEach((lang) => {
|
||||||
try {
|
try {
|
||||||
const localeData = fs
|
const localeData = String(
|
||||||
.readFileSync(
|
fs.readFileSync(
|
||||||
path.resolve(
|
require.resolve(`@formatjs/${module}/locale-data/${lang}.js`)
|
||||||
paths.polymer_dir,
|
)
|
||||||
`node_modules/@formatjs/${module}/locale-data/${lang}.js`
|
|
||||||
),
|
|
||||||
"utf-8"
|
|
||||||
)
|
)
|
||||||
.replace(
|
.replace(
|
||||||
new RegExp(
|
new RegExp(
|
||||||
@@ -46,13 +45,15 @@ gulp.task("create-locale-data", (done) => {
|
|||||||
.replace(/\)\s*}/im, "");
|
.replace(/\)\s*}/im, "");
|
||||||
// make sure we have valid JSON
|
// make sure we have valid JSON
|
||||||
JSON.parse(localeData);
|
JSON.parse(localeData);
|
||||||
|
if (!fs.existsSync(path.join(outDir, module))) {
|
||||||
fs.mkdirSync(path.join(outDir, module), { recursive: true });
|
fs.mkdirSync(path.join(outDir, module), { recursive: true });
|
||||||
|
}
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(outDir, `${module}/${lang}.json`),
|
path.join(outDir, `${module}/${lang}.json`),
|
||||||
localeData
|
localeData
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code !== "ENOENT") {
|
if (e.code !== "MODULE_NOT_FOUND") {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,14 +1,13 @@
|
|||||||
// Tasks to run Rollup
|
// Tasks to run Rollup
|
||||||
|
const path = require("path");
|
||||||
import log from "fancy-log";
|
const gulp = require("gulp");
|
||||||
import gulp from "gulp";
|
const rollup = require("rollup");
|
||||||
import http from "http";
|
const handler = require("serve-handler");
|
||||||
import open from "open";
|
const http = require("http");
|
||||||
import path from "path";
|
const log = require("fancy-log");
|
||||||
import { rollup } from "rollup";
|
const open = require("open");
|
||||||
import handler from "serve-handler";
|
const rollupConfig = require("../rollup.cjs");
|
||||||
import paths from "../paths.cjs";
|
const paths = require("../paths.cjs");
|
||||||
import rollupConfig from "../rollup.cjs";
|
|
||||||
|
|
||||||
const bothBuilds = (createConfigFunc, params) =>
|
const bothBuilds = (createConfigFunc, params) =>
|
||||||
gulp.series(
|
gulp.series(
|
@@ -1,12 +1,11 @@
|
|||||||
// Generate service worker.
|
// Generate service worker.
|
||||||
// Based on manifest, create a file with the content as service_worker.js
|
// Based on manifest, create a file with the content as service_worker.js
|
||||||
|
const gulp = require("gulp");
|
||||||
import fs from "fs-extra";
|
const path = require("path");
|
||||||
import gulp from "gulp";
|
const fs = require("fs-extra");
|
||||||
import path from "path";
|
const workboxBuild = require("workbox-build");
|
||||||
import sourceMapUrl from "source-map-url";
|
const sourceMapUrl = require("source-map-url");
|
||||||
import workboxBuild from "workbox-build";
|
const paths = require("../paths.cjs");
|
||||||
import paths from "../paths.cjs";
|
|
||||||
|
|
||||||
const swDest = path.resolve(paths.app_output_root, "service_worker.js");
|
const swDest = path.resolve(paths.app_output_root, "service_worker.js");
|
||||||
|
|
||||||
@@ -29,9 +28,10 @@ self.addEventListener('install', (event) => {
|
|||||||
|
|
||||||
gulp.task("gen-service-worker-app-prod", async () => {
|
gulp.task("gen-service-worker-app-prod", async () => {
|
||||||
// Read bundled source file
|
// Read bundled source file
|
||||||
const bundleManifestLatest = fs.readJsonSync(
|
const bundleManifestLatest = require(path.resolve(
|
||||||
path.resolve(paths.app_output_latest, "manifest.json")
|
paths.app_output_latest,
|
||||||
);
|
"manifest.json"
|
||||||
|
));
|
||||||
let serviceWorkerContent = fs.readFileSync(
|
let serviceWorkerContent = fs.readFileSync(
|
||||||
paths.app_output_root + bundleManifestLatest["service_worker.js"],
|
paths.app_output_root + bundleManifestLatest["service_worker.js"],
|
||||||
"utf-8"
|
"utf-8"
|
||||||
@@ -46,9 +46,10 @@ gulp.task("gen-service-worker-app-prod", async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Remove ES5
|
// Remove ES5
|
||||||
const bundleManifestES5 = fs.readJsonSync(
|
const bundleManifestES5 = require(path.resolve(
|
||||||
path.resolve(paths.app_output_es5, "manifest.json")
|
paths.app_output_es5,
|
||||||
);
|
"manifest.json"
|
||||||
|
));
|
||||||
fs.removeSync(paths.app_output_root + bundleManifestES5["service_worker.js"]);
|
fs.removeSync(paths.app_output_root + bundleManifestES5["service_worker.js"]);
|
||||||
fs.removeSync(
|
fs.removeSync(
|
||||||
paths.app_output_root + bundleManifestES5["service_worker.js.map"]
|
paths.app_output_root + bundleManifestES5["service_worker.js.map"]
|
@@ -1,24 +1,19 @@
|
|||||||
import { createHash } from "crypto";
|
const del = import("del");
|
||||||
import { deleteSync } from "del";
|
const crypto = require("crypto");
|
||||||
import {
|
const path = require("path");
|
||||||
mkdirSync,
|
const source = require("vinyl-source-stream");
|
||||||
readdirSync,
|
const vinylBuffer = require("vinyl-buffer");
|
||||||
readFileSync,
|
const gulp = require("gulp");
|
||||||
renameSync,
|
const fs = require("fs");
|
||||||
writeFile,
|
const flatmap = require("gulp-flatmap");
|
||||||
} from "fs";
|
const merge = require("gulp-merge-json");
|
||||||
import gulp from "gulp";
|
const rename = require("gulp-rename");
|
||||||
import flatmap from "gulp-flatmap";
|
const transform = require("gulp-json-transform");
|
||||||
import transform from "gulp-json-transform";
|
const { mapFiles } = require("../util.cjs");
|
||||||
import merge from "gulp-merge-json";
|
const env = require("../env.cjs");
|
||||||
import rename from "gulp-rename";
|
const paths = require("../paths.cjs");
|
||||||
import path from "path";
|
|
||||||
import vinylBuffer from "vinyl-buffer";
|
require("./fetch-nightly-translations.cjs");
|
||||||
import source from "vinyl-source-stream";
|
|
||||||
import env from "../env.cjs";
|
|
||||||
import paths from "../paths.cjs";
|
|
||||||
import { mapFiles } from "../util.cjs";
|
|
||||||
import "./fetch-nightly-translations.js";
|
|
||||||
|
|
||||||
const inFrontendDir = "translations/frontend";
|
const inFrontendDir = "translations/frontend";
|
||||||
const inBackendDir = "translations/backend";
|
const inBackendDir = "translations/backend";
|
||||||
@@ -38,12 +33,7 @@ gulp.task(
|
|||||||
|
|
||||||
// Panel translations which should be split from the core translations.
|
// Panel translations which should be split from the core translations.
|
||||||
const TRANSLATION_FRAGMENTS = Object.keys(
|
const TRANSLATION_FRAGMENTS = Object.keys(
|
||||||
JSON.parse(
|
require("../../src/translations/en.json").ui.panel
|
||||||
readFileSync(
|
|
||||||
path.resolve(paths.polymer_dir, "src/translations/en.json"),
|
|
||||||
"utf-8"
|
|
||||||
)
|
|
||||||
).ui.panel
|
|
||||||
);
|
);
|
||||||
|
|
||||||
function recursiveFlatten(prefix, data) {
|
function recursiveFlatten(prefix, data) {
|
||||||
@@ -130,14 +120,17 @@ function lokaliseTransform(data, original, file) {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task("clean-translations", async () => deleteSync([workDir]));
|
gulp.task("clean-translations", async () => (await del).deleteSync([workDir]));
|
||||||
|
|
||||||
gulp.task("ensure-translations-build-dir", async () => {
|
gulp.task("ensure-translations-build-dir", (done) => {
|
||||||
mkdirSync(workDir, { recursive: true });
|
if (!fs.existsSync(workDir)) {
|
||||||
|
fs.mkdirSync(workDir, { recursive: true });
|
||||||
|
}
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("create-test-metadata", (cb) => {
|
gulp.task("create-test-metadata", (cb) => {
|
||||||
writeFile(
|
fs.writeFile(
|
||||||
workDir + "/testMetadata.json",
|
workDir + "/testMetadata.json",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
test: {
|
test: {
|
||||||
@@ -310,14 +303,15 @@ const fingerprints = {};
|
|||||||
|
|
||||||
gulp.task("build-translation-fingerprints", () => {
|
gulp.task("build-translation-fingerprints", () => {
|
||||||
// Fingerprint full file of each language
|
// Fingerprint full file of each language
|
||||||
const files = readdirSync(fullDir);
|
const files = fs.readdirSync(fullDir);
|
||||||
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
fingerprints[files[i].split(".")[0]] = {
|
fingerprints[files[i].split(".")[0]] = {
|
||||||
// In dev we create fake hashes
|
// In dev we create fake hashes
|
||||||
hash: env.isProdBuild()
|
hash: env.isProdBuild()
|
||||||
? createHash("md5")
|
? crypto
|
||||||
.update(readFileSync(path.join(fullDir, files[i]), "utf-8"))
|
.createHash("md5")
|
||||||
|
.update(fs.readFileSync(path.join(fullDir, files[i]), "utf-8"))
|
||||||
.digest("hex")
|
.digest("hex")
|
||||||
: "dev",
|
: "dev",
|
||||||
};
|
};
|
||||||
@@ -333,7 +327,7 @@ gulp.task("build-translation-fingerprints", () => {
|
|||||||
throw new Error(`Unable to find hash for ${filename}`);
|
throw new Error(`Unable to find hash for ${filename}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
renameSync(
|
fs.renameSync(
|
||||||
filename,
|
filename,
|
||||||
`${parsed.dir}/${parsed.name}-${fingerprints[parsed.name].hash}${
|
`${parsed.dir}/${parsed.name}-${fingerprints[parsed.name].hash}${
|
||||||
parsed.ext
|
parsed.ext
|
11
build-scripts/gulp/wds.cjs
Normal file
11
build-scripts/gulp/wds.cjs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Tasks to run Rollup
|
||||||
|
const gulp = require("gulp");
|
||||||
|
const { startDevServer } = require("@web/dev-server");
|
||||||
|
|
||||||
|
gulp.task("wds-watch-app", () => {
|
||||||
|
startDevServer({
|
||||||
|
config: {
|
||||||
|
watch: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
@@ -1,10 +0,0 @@
|
|||||||
import gulp from "gulp";
|
|
||||||
import { startDevServer } from "@web/dev-server";
|
|
||||||
|
|
||||||
gulp.task("wds-watch-app", async () => {
|
|
||||||
startDevServer({
|
|
||||||
config: {
|
|
||||||
watch: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,20 +1,19 @@
|
|||||||
// Tasks to run webpack.
|
// Tasks to run webpack.
|
||||||
|
const fs = require("fs");
|
||||||
import log from "fancy-log";
|
const gulp = require("gulp");
|
||||||
import fs from "fs";
|
const webpack = require("webpack");
|
||||||
import gulp from "gulp";
|
const WebpackDevServer = require("webpack-dev-server");
|
||||||
import path from "path";
|
const log = require("fancy-log");
|
||||||
import webpack from "webpack";
|
const path = require("path");
|
||||||
import WebpackDevServer from "webpack-dev-server";
|
const env = require("../env.cjs");
|
||||||
import env from "../env.cjs";
|
const paths = require("../paths.cjs");
|
||||||
import paths from "../paths.cjs";
|
const {
|
||||||
import {
|
|
||||||
createAppConfig,
|
createAppConfig,
|
||||||
createCastConfig,
|
|
||||||
createDemoConfig,
|
createDemoConfig,
|
||||||
createGalleryConfig,
|
createCastConfig,
|
||||||
createHassioConfig,
|
createHassioConfig,
|
||||||
} from "../webpack.cjs";
|
createGalleryConfig,
|
||||||
|
} = require("../webpack.cjs");
|
||||||
|
|
||||||
const bothBuilds = (createConfigFunc, params) => [
|
const bothBuilds = (createConfigFunc, params) => [
|
||||||
createConfigFunc({ ...params, latestBuild: true }),
|
createConfigFunc({ ...params, latestBuild: true }),
|
@@ -1,59 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
// Script to print Babel plugins and Core JS polyfills that will be used by browserslist environments
|
|
||||||
|
|
||||||
import { version as babelVersion } from "@babel/core";
|
|
||||||
import presetEnv from "@babel/preset-env";
|
|
||||||
import compilationTargets from "@babel/helper-compilation-targets";
|
|
||||||
import coreJSCompat from "core-js-compat";
|
|
||||||
import { logPlugin } from "@babel/preset-env/lib/debug.js";
|
|
||||||
import { babelOptions } from "./bundle.cjs";
|
|
||||||
|
|
||||||
const detailsOpen = (heading) =>
|
|
||||||
`<details>\n<summary><h4>${heading}</h4></summary>\n`;
|
|
||||||
const detailsClose = "</details>\n";
|
|
||||||
|
|
||||||
const dummyAPI = {
|
|
||||||
version: babelVersion,
|
|
||||||
assertVersion: () => {},
|
|
||||||
caller: (callback) =>
|
|
||||||
callback({
|
|
||||||
name: "Dummy Bundler",
|
|
||||||
supportsStaticESM: true,
|
|
||||||
supportsDynamicImport: true,
|
|
||||||
supportsTopLevelAwait: true,
|
|
||||||
supportsExportNamespaceFrom: true,
|
|
||||||
}),
|
|
||||||
targets: () => ({}),
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const buildType of ["Modern", "Legacy"]) {
|
|
||||||
const browserslistEnv = buildType.toLowerCase();
|
|
||||||
const babelOpts = babelOptions({ latestBuild: browserslistEnv === "modern" });
|
|
||||||
const presetEnvOpts = babelOpts.presets[0][1];
|
|
||||||
|
|
||||||
// Invoking preset-env in debug mode will log the included plugins
|
|
||||||
console.log(detailsOpen(`${buildType} Build Babel Plugins`));
|
|
||||||
presetEnv.default(dummyAPI, {
|
|
||||||
...presetEnvOpts,
|
|
||||||
browserslistEnv,
|
|
||||||
debug: true,
|
|
||||||
});
|
|
||||||
console.log(detailsClose);
|
|
||||||
|
|
||||||
// Manually log the Core-JS polyfills using the same technique
|
|
||||||
if (presetEnvOpts.useBuiltIns) {
|
|
||||||
console.log(detailsOpen(`${buildType} Build Core-JS Polyfills`));
|
|
||||||
const targets = compilationTargets.default(babelOpts?.targets, {
|
|
||||||
browserslistEnv,
|
|
||||||
});
|
|
||||||
const polyfillList = coreJSCompat({ targets }).list;
|
|
||||||
console.log(
|
|
||||||
"The following %i polyfills may be injected by Babel:\n",
|
|
||||||
polyfillList.length
|
|
||||||
);
|
|
||||||
for (const polyfill of polyfillList) {
|
|
||||||
logPlugin(polyfill, targets, coreJSCompat.data);
|
|
||||||
}
|
|
||||||
console.log(detailsClose);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -132,17 +132,6 @@ const createWebpackConfig = ({
|
|||||||
),
|
),
|
||||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
||||||
),
|
),
|
||||||
// See `src/resources/intl-polyfill-legacy.ts` for explanation
|
|
||||||
!latestBuild &&
|
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
|
||||||
new RegExp(
|
|
||||||
path.resolve(paths.polymer_dir, "src/resources/intl-polyfill.ts")
|
|
||||||
),
|
|
||||||
path.resolve(
|
|
||||||
paths.polymer_dir,
|
|
||||||
"src/resources/intl-polyfill-legacy.ts"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
!isProdBuild && new LogStartCompilePlugin(),
|
!isProdBuild && new LogStartCompilePlugin(),
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
resolve: {
|
resolve: {
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
<meta property="fb:app_id" content="338291289691179" />
|
|
||||||
<meta property="og:title" content="Home Assistant Cast" />
|
|
||||||
<meta property="og:site_name" content="Home Assistant Cast" />
|
|
||||||
<meta property="og:url" content="https://cast.home-assistant.io/" />
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta
|
|
||||||
property="og:description"
|
|
||||||
content="Show Home Assistant on your Chromecast or Google Assistant devices with a screen."
|
|
||||||
/>
|
|
||||||
<meta
|
|
||||||
property="og:image"
|
|
||||||
content="https://cast.home-assistant.io/images/google-nest-hub.png"
|
|
||||||
/>
|
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
|
||||||
<meta name="twitter:site" content="@home_assistant" />
|
|
||||||
<meta name="twitter:title" content="Home Assistant Cast" />
|
|
||||||
<meta
|
|
||||||
name="twitter:description"
|
|
||||||
content="Show Home Assistant on your Chromecast or Google Assistant devices with a screen."
|
|
||||||
/>
|
|
||||||
<meta
|
|
||||||
name="twitter:image"
|
|
||||||
content="https://cast.home-assistant.io/images/google-nest-hub.png"
|
|
||||||
/>
|
|
@@ -1,35 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Home Assistant Cast</title>
|
|
||||||
<link rel="manifest" href="/manifest.json" />
|
|
||||||
<link rel="icon" href="/images/ha-cast-icon.png" type="image/png" />
|
|
||||||
<%= renderTemplate("../../../src/html/_style_base.html.template") %>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background-color: #e5e5e5;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<%= renderTemplate("_social_meta.html.template") %>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
|
||||||
<hc-connect></hc-connect>
|
|
||||||
<script>
|
|
||||||
<% for (const entry of latestEntryJS) { %>
|
|
||||||
import("<%= entry %>");
|
|
||||||
<% } %>
|
|
||||||
window.latestJS = true;
|
|
||||||
</script>
|
|
||||||
<%= renderTemplate("../../../src/html/_script_load_es5.html.template") %>
|
|
||||||
<script>
|
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
||||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
|
||||||
|
|
||||||
ga('create', 'UA-57927901-9', 'auto');
|
|
||||||
ga('send', 'pageview', location.pathname.includes("auth_callback") === -1 ? location.pathname : "/");
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Home Assistant Cast - FAQ</title>
|
<title>Home Assistant Cast - FAQ</title>
|
||||||
<link rel="icon" href="/images/ha-cast-icon.png" type="image/png" />
|
<link rel="icon" href="/images/ha-cast-icon.png" type="image/png" />
|
||||||
<%= renderTemplate("../../../src/html/_style_base.html.template") %>
|
<%= renderTemplate('_style_base') %>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #e5e5e5;
|
background-color: #e5e5e5;
|
||||||
@@ -35,14 +35,25 @@
|
|||||||
/>
|
/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
<%= renderTemplate('_js_base') %>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
<% for (const entry of latestEntryJS) { %>
|
import("<%= latestLauncherJS %>");
|
||||||
import("<%= entry %>");
|
|
||||||
<% } %>
|
|
||||||
window.latestJS = true;
|
window.latestJS = true;
|
||||||
</script>
|
</script>
|
||||||
<%= renderTemplate("../../../src/html/_script_load_es5.html.template") %>
|
|
||||||
|
<script>
|
||||||
|
if (!window.latestJS) {
|
||||||
|
<% if (useRollup) { %>
|
||||||
|
_ls("/static/js/s.min.js").onload = function() {
|
||||||
|
System.import("<%= es5LauncherJS %>");
|
||||||
|
};
|
||||||
|
<% } else { %>
|
||||||
|
_ls("<%= es5LauncherJS %>");
|
||||||
|
<% } %>
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<hc-layout subtitle="FAQ">
|
<hc-layout subtitle="FAQ">
|
||||||
<style>
|
<style>
|
||||||
a {
|
a {
|
57
cast/src/html/launcher.html.template
Normal file
57
cast/src/html/launcher.html.template
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Home Assistant Cast</title>
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
<link rel="icon" href="/images/ha-cast-icon.png" type="image/png" />
|
||||||
|
<%= renderTemplate('_style_base') %>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<meta property="fb:app_id" content="338291289691179">
|
||||||
|
<meta property="og:title" content="Home Assistant Cast">
|
||||||
|
<meta property="og:site_name" content="Home Assistant Cast">
|
||||||
|
<meta property="og:url" content="https://cast.home-assistant.io/">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:description" content="Show Home Assistant on your Chromecast or Google Assistant devices with a screen.">
|
||||||
|
<meta property="og:image" content="https://cast.home-assistant.io/images/google-nest-hub.png">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="twitter:site" content="@home_assistant">
|
||||||
|
<meta name="twitter:title" content="Home Assistant Cast">
|
||||||
|
<meta name="twitter:description" content="Show Home Assistant on your Chromecast or Google Assistant devices with a screen.">
|
||||||
|
<meta name="twitter:image" content="https://cast.home-assistant.io/images/google-nest-hub.png">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%= renderTemplate('_js_base') %>
|
||||||
|
|
||||||
|
<hc-connect></hc-connect>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import("<%= latestLauncherJS %>");
|
||||||
|
window.latestJS = true;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
if (!window.latestJS) {
|
||||||
|
<% if (useRollup) { %>
|
||||||
|
_ls("/static/js/s.min.js").onload = function() {
|
||||||
|
System.import("<%= es5LauncherJS %>");
|
||||||
|
};
|
||||||
|
<% } else { %>
|
||||||
|
_ls("<%= es5LauncherJS %>");
|
||||||
|
<% } %>
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||||
|
|
||||||
|
ga('create', 'UA-57927901-9', 'auto');
|
||||||
|
ga('send', 'pageview', location.pathname.includes("auth_callback") === -1 ? location.pathname : "/");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@@ -22,14 +22,25 @@
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
<%= renderTemplate('_js_base') %>
|
||||||
|
|
||||||
<cast-media-player></cast-media-player>
|
<cast-media-player></cast-media-player>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
<% for (const entry of latestEntryJS) { %>
|
import("<%= latestMediaJS %>");
|
||||||
import("<%= entry %>");
|
|
||||||
<% } %>
|
|
||||||
window.latestJS = true;
|
window.latestJS = true;
|
||||||
</script>
|
</script>
|
||||||
<%= renderTemplate("../../../src/html/_script_load_es5.html.template") %>
|
|
||||||
|
<script>
|
||||||
|
if (!window.latestJS) {
|
||||||
|
<% if (useRollup) { %>
|
||||||
|
_ls("/static/js/s.min.js").onload = function() {
|
||||||
|
System.import("<%= es5MediaJS %>");
|
||||||
|
};
|
||||||
|
<% } else { %>
|
||||||
|
_ls("<%= es5MediaJS %>");
|
||||||
|
<% } %>
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
|
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
|
||||||
<% for (const entry of latestEntryJS) { %>
|
<script type="module" src="<%= latestReceiverJS %>"></script>
|
||||||
<script type="module" src="<%= entry %>"></script>
|
<%= renderTemplate('_style_base') %>
|
||||||
<% } %>
|
|
||||||
<%= renderTemplate("../../../src/html/_style_base.html.template") %>
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
@@ -190,7 +190,7 @@ export class HcConnect extends LitElement {
|
|||||||
|
|
||||||
private _handleInputKeyDown(ev: KeyboardEvent) {
|
private _handleInputKeyDown(ev: KeyboardEvent) {
|
||||||
// Handle pressing enter.
|
// Handle pressing enter.
|
||||||
if (ev.key === "Enter") {
|
if (ev.keyCode === 13) {
|
||||||
this._handleConnect();
|
this._handleConnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
import { cast } from "chromecast-caf-receiver";
|
|
||||||
|
|
||||||
const castContext = cast.framework.CastReceiverContext.getInstance();
|
const castContext = cast.framework.CastReceiverContext.getInstance();
|
||||||
|
|
||||||
const playerManager = castContext.getPlayerManager();
|
const playerManager = castContext.getPlayerManager();
|
||||||
|
@@ -1,3 +1,2 @@
|
|||||||
import { cast } from "chromecast-caf-receiver";
|
/* eslint-disable no-undef */
|
||||||
|
|
||||||
export const castContext = cast.framework.CastReceiverContext.getInstance();
|
export const castContext = cast.framework.CastReceiverContext.getInstance();
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { cast } from "chromecast-caf-receiver";
|
/* eslint-disable no-undef */
|
||||||
import { CAST_NS } from "../../../src/cast/const";
|
import { CAST_NS } from "../../../src/cast/const";
|
||||||
import { HassMessage } from "../../../src/cast/receiver_messages";
|
import { HassMessage } from "../../../src/cast/receiver_messages";
|
||||||
import "../../../src/resources/custom-card-support";
|
import "../../../src/resources/custom-card-support";
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
<meta property="fb:app_id" content="338291289691179" />
|
|
||||||
<meta property="og:title" content="Home Assistant Demo" />
|
|
||||||
<meta property="og:site_name" content="Home Assistant" />
|
|
||||||
<meta property="og:url" content="https://demo.home-assistant.io/" />
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta
|
|
||||||
property="og:description"
|
|
||||||
content="Open source home automation that puts local control and privacy first."
|
|
||||||
/>
|
|
||||||
<meta
|
|
||||||
property="og:image"
|
|
||||||
content="https://www.home-assistant.io/images/default-social.png"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
|
||||||
<meta name="twitter:site" content="@home_assistant" />
|
|
||||||
|
|
||||||
<meta name="twitter:title" content="Home Assistant" />
|
|
||||||
<meta
|
|
||||||
name="twitter:description"
|
|
||||||
content="Open source home automation that puts local control and privacy first."
|
|
||||||
/>
|
|
||||||
<meta
|
|
||||||
name="twitter:image"
|
|
||||||
content="https://www.home-assistant.io/images/default-social.png"
|
|
||||||
/>
|
|
@@ -1,8 +1,9 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Home Assistant Demo</title>
|
<meta charset="utf-8" />
|
||||||
<%= renderTemplate("../../../src/html/_header.html.template") %>
|
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||||
|
<link rel="icon" href="/static/icons/favicon.ico" />
|
||||||
<link rel="mask-icon" href="/static/icons/mask-icon.svg" color="#03a9f4" />
|
<link rel="mask-icon" href="/static/icons/mask-icon.svg" color="#03a9f4" />
|
||||||
<link
|
<link
|
||||||
rel="apple-touch-icon"
|
rel="apple-touch-icon"
|
||||||
@@ -34,7 +35,33 @@
|
|||||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||||
/>
|
/>
|
||||||
<meta name="theme-color" content="#03a9f4" />
|
<meta name="theme-color" content="#03a9f4" />
|
||||||
<%= renderTemplate("_social_meta.html.template") %>
|
<meta property="fb:app_id" content="338291289691179" />
|
||||||
|
<meta property="og:title" content="Home Assistant Demo" />
|
||||||
|
<meta property="og:site_name" content="Home Assistant" />
|
||||||
|
<meta property="og:url" content="https://demo.home-assistant.io/" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta
|
||||||
|
property="og:description"
|
||||||
|
content="Open source home automation that puts local control and privacy first."
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
property="og:image"
|
||||||
|
content="https://www.home-assistant.io/images/default-social.png"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:site" content="@home_assistant" />
|
||||||
|
|
||||||
|
<meta name="twitter:title" content="Home Assistant" />
|
||||||
|
<meta
|
||||||
|
name="twitter:description"
|
||||||
|
content="Open source home automation that puts local control and privacy first."
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="twitter:image"
|
||||||
|
content="https://www.home-assistant.io/images/default-social.png"
|
||||||
|
/>
|
||||||
|
<title>Home Assistant Demo</title>
|
||||||
<style>
|
<style>
|
||||||
html {
|
html {
|
||||||
background-color: var(--primary-background-color, #fafafa);
|
background-color: var(--primary-background-color, #fafafa);
|
||||||
@@ -80,19 +107,29 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<div id="ha-launch-screen-info-box" class="ha-launch-screen-spacer"></div>
|
<div id="ha-launch-screen-info-box" class="ha-launch-screen-spacer"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ha-demo></ha-demo>
|
<ha-demo></ha-demo>
|
||||||
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
|
||||||
<%= renderTemplate("../../../src/html/_preload_roboto.html.template") %>
|
<%= renderTemplate('_js_base') %>
|
||||||
|
<%= renderTemplate('_preload_roboto') %>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Safari 12 and below does not have a compliant ES2015 implementation of template literals, so we ship ES5
|
import("<%= latestDemoJS %>");
|
||||||
if (!isS11_12) {
|
|
||||||
<% for (const entry of latestEntryJS) { %>
|
|
||||||
import("<%= entry %>");
|
|
||||||
<% } %>
|
|
||||||
window.latestJS = true;
|
window.latestJS = true;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
if (!window.latestJS) {
|
||||||
|
<% if (useRollup) { %>
|
||||||
|
_ls("/static/js/s.min.js").onload = function() {
|
||||||
|
System.import("<%= es5DemoJS %>");
|
||||||
|
};
|
||||||
|
<% } else { %>
|
||||||
|
_ls("<%= es5DemoJS %>");
|
||||||
|
<% } %>
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<%= renderTemplate("../../../src/html/_script_load_es5.html.template") %>
|
|
||||||
<script>
|
<script>
|
||||||
var _gaq = [["_setAccount", "UA-57927901-5"], ["_trackPageview"]];
|
var _gaq = [["_setAccount", "UA-57927901-5"], ["_trackPageview"]];
|
||||||
(function (d, t) {
|
(function (d, t) {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
|
|
||||||
export const mockConfigEntries = (hass: MockHomeAssistant) => {
|
export const mockConfigEntries = (hass: MockHomeAssistant) => {
|
||||||
hass.mockWS("config_entries/get_matching", () => [
|
hass.mockWS("config_entries/get", () => [
|
||||||
{
|
{
|
||||||
entry_id: "co2signal",
|
entry_id: "co2signal",
|
||||||
domain: "co2signal",
|
domain: "co2signal",
|
||||||
|
@@ -45,10 +45,6 @@ export default [
|
|||||||
header: "Users",
|
header: "Users",
|
||||||
pages: ["user-types", "configuration-menu"],
|
pages: ["user-types", "configuration-menu"],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
category: "date-time",
|
|
||||||
header: "Date and Time",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
category: "design.home-assistant.io",
|
category: "design.home-assistant.io",
|
||||||
header: "About",
|
header: "About",
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import "@polymer/polymer/lib/elements/dom-if";
|
||||||
|
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 "./ha-gallery";
|
import "./ha-gallery";
|
||||||
|
@@ -8,9 +8,8 @@
|
|||||||
/>
|
/>
|
||||||
<meta name="theme-color" content="#2157BC" />
|
<meta name="theme-color" content="#2157BC" />
|
||||||
<title>Home Assistant Design</title>
|
<title>Home Assistant Design</title>
|
||||||
<% for (const entry of latestEntryJS) { %>
|
|
||||||
<script type="module" src="<%= entry %>"></script>
|
<script type="module" src="<%= latestGalleryJS %>"></script>
|
||||||
<% } %>
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Roboto, Noto, sans-serif;
|
font-family: Roboto, Noto, sans-serif;
|
||||||
|
@@ -63,7 +63,7 @@ export class DemoAutomationDescribeCondition extends LitElement {
|
|||||||
<div class="condition">
|
<div class="condition">
|
||||||
<span>
|
<span>
|
||||||
${this._condition
|
${this._condition
|
||||||
? describeCondition(this._condition, this.hass, [])
|
? describeCondition(this._condition, this.hass)
|
||||||
: "<invalid YAML>"}
|
: "<invalid YAML>"}
|
||||||
</span>
|
</span>
|
||||||
<ha-yaml-editor
|
<ha-yaml-editor
|
||||||
@@ -76,7 +76,7 @@ export class DemoAutomationDescribeCondition extends LitElement {
|
|||||||
${conditions.map(
|
${conditions.map(
|
||||||
(conf) => html`
|
(conf) => html`
|
||||||
<div class="condition">
|
<div class="condition">
|
||||||
<span>${describeCondition(conf as any, this.hass, [])}</span>
|
<span>${describeCondition(conf as any, this.hass)}</span>
|
||||||
<pre>${dump(conf)}</pre>
|
<pre>${dump(conf)}</pre>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
@@ -74,7 +74,7 @@ export class DemoAutomationDescribeTrigger extends LitElement {
|
|||||||
<div class="trigger">
|
<div class="trigger">
|
||||||
<span>
|
<span>
|
||||||
${this._trigger
|
${this._trigger
|
||||||
? describeTrigger(this._trigger, this.hass, [])
|
? describeTrigger(this._trigger, this.hass)
|
||||||
: "<invalid YAML>"}
|
: "<invalid YAML>"}
|
||||||
</span>
|
</span>
|
||||||
<ha-yaml-editor
|
<ha-yaml-editor
|
||||||
@@ -86,7 +86,7 @@ export class DemoAutomationDescribeTrigger extends LitElement {
|
|||||||
${triggers.map(
|
${triggers.map(
|
||||||
(conf) => html`
|
(conf) => html`
|
||||||
<div class="trigger">
|
<div class="trigger">
|
||||||
<span>${describeTrigger(conf as any, this.hass, [])}</span>
|
<span>${describeTrigger(conf as any, this.hass)}</span>
|
||||||
<pre>${dump(conf)}</pre>
|
<pre>${dump(conf)}</pre>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
@@ -336,7 +336,7 @@ const SCHEMAS: {
|
|||||||
["and", "another_one"],
|
["and", "another_one"],
|
||||||
["option", "1000"],
|
["option", "1000"],
|
||||||
],
|
],
|
||||||
name: "select many options",
|
name: "select many otions",
|
||||||
default: "default",
|
default: "default",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -364,7 +364,7 @@ const SCHEMAS: {
|
|||||||
and: "another_one",
|
and: "another_one",
|
||||||
option: "1000",
|
option: "1000",
|
||||||
},
|
},
|
||||||
name: "multi many options",
|
name: "multi many otions",
|
||||||
default: ["default"],
|
default: ["default"],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
title: HS Color Picker
|
|
||||||
---
|
|
@@ -1,120 +0,0 @@
|
|||||||
import "../../../../src/components/ha-hs-color-picker";
|
|
||||||
|
|
||||||
import { css, html, LitElement, TemplateResult } from "lit";
|
|
||||||
import { customElement, state } from "lit/decorators";
|
|
||||||
|
|
||||||
import "../../../../src/components/ha-card";
|
|
||||||
import "../../../../src/components/ha-slider";
|
|
||||||
import { hsv2rgb } from "../../../../src/common/color/convert-color";
|
|
||||||
|
|
||||||
@customElement("demo-components-ha-hs-color-picker")
|
|
||||||
export class DemoHaHsColorPicker extends LitElement {
|
|
||||||
@state()
|
|
||||||
brightness = 255;
|
|
||||||
|
|
||||||
@state()
|
|
||||||
value: [number, number] = [0, 0];
|
|
||||||
|
|
||||||
@state()
|
|
||||||
liveValue?: [number, number];
|
|
||||||
|
|
||||||
private _brightnessChanged(ev) {
|
|
||||||
this.brightness = Number(ev.target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _hsColorCursor(ev) {
|
|
||||||
this.liveValue = ev.detail.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _hsColorChanged(ev) {
|
|
||||||
this.value = ev.detail.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _hueChanged(ev) {
|
|
||||||
this.value = [ev.target.value, this.value[1]];
|
|
||||||
}
|
|
||||||
|
|
||||||
private _saturationChanged(ev) {
|
|
||||||
this.value = [this.value[0], ev.target.value];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
const h = (this.liveValue ?? this.value)[0];
|
|
||||||
const s = (this.liveValue ?? this.value)[1];
|
|
||||||
|
|
||||||
const rgb = hsv2rgb([h, s, this.brightness]);
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<ha-card>
|
|
||||||
<div class="card-content">
|
|
||||||
<p class="value">${h}° - ${Math.round(s * 100)}%</p>
|
|
||||||
<p class="value">${rgb.map((v) => Math.round(v)).join(", ")}</p>
|
|
||||||
<ha-hs-color-picker
|
|
||||||
colorBrightness=${this.brightness}
|
|
||||||
.value=${this.value}
|
|
||||||
@value-changed=${this._hsColorChanged}
|
|
||||||
@cursor-moved=${this._hsColorCursor}
|
|
||||||
></ha-hs-color-picker>
|
|
||||||
<p>Hue : ${this.value[0]}</p>
|
|
||||||
<ha-slider
|
|
||||||
step="1"
|
|
||||||
pin
|
|
||||||
min="0"
|
|
||||||
max="360"
|
|
||||||
.value=${this.value[0]}
|
|
||||||
@change=${this._hueChanged}
|
|
||||||
>
|
|
||||||
</ha-slider>
|
|
||||||
<p>Saturation : ${this.value[1]}</p>
|
|
||||||
<ha-slider
|
|
||||||
step="0.01"
|
|
||||||
pin
|
|
||||||
min="0"
|
|
||||||
max="1"
|
|
||||||
.value=${this.value[1]}
|
|
||||||
@change=${this._saturationChanged}
|
|
||||||
>
|
|
||||||
</ha-slider>
|
|
||||||
<p>Color Brighness : ${this.brightness}</p>
|
|
||||||
<ha-slider
|
|
||||||
step="1"
|
|
||||||
pin
|
|
||||||
min="0"
|
|
||||||
max="255"
|
|
||||||
.value=${this.brightness}
|
|
||||||
@change=${this._brightnessChanged}
|
|
||||||
>
|
|
||||||
</ha-slider>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles() {
|
|
||||||
return css`
|
|
||||||
ha-card {
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 24px auto;
|
|
||||||
}
|
|
||||||
.card-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
ha-hs-color-picker {
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
.value {
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 12px 0;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"demo-components-ha-hs-color-picker": DemoHaHsColorPicker;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
title: Temp Color Picker
|
|
||||||
---
|
|
@@ -1,117 +0,0 @@
|
|||||||
import "../../../../src/components/ha-temp-color-picker";
|
|
||||||
|
|
||||||
import { css, html, LitElement, TemplateResult } from "lit";
|
|
||||||
import { customElement, state } from "lit/decorators";
|
|
||||||
|
|
||||||
import "../../../../src/components/ha-card";
|
|
||||||
import "../../../../src/components/ha-slider";
|
|
||||||
|
|
||||||
@customElement("demo-components-ha-temp-color-picker")
|
|
||||||
export class DemoHaTempColorPicker extends LitElement {
|
|
||||||
@state()
|
|
||||||
min = 3000;
|
|
||||||
|
|
||||||
@state()
|
|
||||||
max = 7000;
|
|
||||||
|
|
||||||
@state()
|
|
||||||
value = 4000;
|
|
||||||
|
|
||||||
@state()
|
|
||||||
liveValue?: number;
|
|
||||||
|
|
||||||
private _minChanged(ev) {
|
|
||||||
this.min = Number(ev.target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _maxChanged(ev) {
|
|
||||||
this.max = Number(ev.target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _valueChanged(ev) {
|
|
||||||
this.value = Number(ev.target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _tempColorCursor(ev) {
|
|
||||||
this.liveValue = ev.detail.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _tempColorChanged(ev) {
|
|
||||||
this.value = ev.detail.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
return html`
|
|
||||||
<ha-card>
|
|
||||||
<div class="card-content">
|
|
||||||
<p class="value">${this.liveValue ?? this.value} K</p>
|
|
||||||
<ha-temp-color-picker
|
|
||||||
.min=${this.min}
|
|
||||||
.max=${this.max}
|
|
||||||
.value=${this.value}
|
|
||||||
@value-changed=${this._tempColorChanged}
|
|
||||||
@cursor-moved=${this._tempColorCursor}
|
|
||||||
></ha-temp-color-picker>
|
|
||||||
<p>Min temp : ${this.min} K</p>
|
|
||||||
<ha-slider
|
|
||||||
step="1"
|
|
||||||
pin
|
|
||||||
min="2000"
|
|
||||||
max="10000"
|
|
||||||
.value=${this.min}
|
|
||||||
@change=${this._minChanged}
|
|
||||||
>
|
|
||||||
</ha-slider>
|
|
||||||
<p>Max temp : ${this.max} K</p>
|
|
||||||
<ha-slider
|
|
||||||
step="1"
|
|
||||||
pin
|
|
||||||
min="2000"
|
|
||||||
max="10000"
|
|
||||||
.value=${this.max}
|
|
||||||
@change=${this._maxChanged}
|
|
||||||
>
|
|
||||||
</ha-slider>
|
|
||||||
<p>Value : ${this.value} K</p>
|
|
||||||
<ha-slider
|
|
||||||
step="1"
|
|
||||||
pin
|
|
||||||
min=${this.min}
|
|
||||||
max=${this.max}
|
|
||||||
.value=${this.value}
|
|
||||||
@change=${this._valueChanged}
|
|
||||||
>
|
|
||||||
</ha-slider>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles() {
|
|
||||||
return css`
|
|
||||||
ha-card {
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 24px auto;
|
|
||||||
}
|
|
||||||
.card-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
ha-temp-color-picker {
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
.value {
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 12px 0;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"demo-components-ha-temp-color-picker": DemoHaTempColorPicker;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
title: (Numeric) Date Formatting
|
|
||||||
---
|
|
||||||
|
|
||||||
This pages lists all supported languages with their available (numeric) date formats.
|
|
||||||
|
|
||||||
Formatting function: `const formatDateNumeric: (dateObj: Date, locale: FrontendLocaleData) => string`
|
|
@@ -1,106 +0,0 @@
|
|||||||
import { html, css, LitElement } from "lit";
|
|
||||||
import { customElement, property } from "lit/decorators";
|
|
||||||
import "../../../../src/components/ha-card";
|
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
|
||||||
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
|
||||||
import { formatDateNumeric } from "../../../../src/common/datetime/format_date";
|
|
||||||
import {
|
|
||||||
FrontendLocaleData,
|
|
||||||
NumberFormat,
|
|
||||||
TimeFormat,
|
|
||||||
DateFormat,
|
|
||||||
FirstWeekday,
|
|
||||||
} from "../../../../src/data/translation";
|
|
||||||
|
|
||||||
@customElement("demo-date-time-date")
|
|
||||||
export class DemoDateTimeDate extends LitElement {
|
|
||||||
@property({ attribute: false }) hass!: HomeAssistant;
|
|
||||||
|
|
||||||
protected render() {
|
|
||||||
const defaultLocale: FrontendLocaleData = {
|
|
||||||
language: "en",
|
|
||||||
number_format: NumberFormat.language,
|
|
||||||
time_format: TimeFormat.language,
|
|
||||||
date_format: DateFormat.language,
|
|
||||||
first_weekday: FirstWeekday.language,
|
|
||||||
};
|
|
||||||
const date = new Date();
|
|
||||||
return html`
|
|
||||||
<mwc-list>
|
|
||||||
<div class="container header">
|
|
||||||
<div>Language</div>
|
|
||||||
<div class="center">Default (lang)</div>
|
|
||||||
<div class="center">Day-Month-Year</div>
|
|
||||||
<div class="center">Month-Day-Year</div>
|
|
||||||
<div class="center">Year-Month-Day</div>
|
|
||||||
</div>
|
|
||||||
${Object.entries(translationMetadata.translations)
|
|
||||||
.filter(([key, _]) => key !== "test")
|
|
||||||
.map(
|
|
||||||
([key, value]) => html`
|
|
||||||
<div class="container">
|
|
||||||
<div>${value.nativeName}</div>
|
|
||||||
<div class="center">
|
|
||||||
${formatDateNumeric(date, {
|
|
||||||
...defaultLocale,
|
|
||||||
language: key,
|
|
||||||
date_format: DateFormat.language,
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div class="center">
|
|
||||||
${formatDateNumeric(date, {
|
|
||||||
...defaultLocale,
|
|
||||||
language: key,
|
|
||||||
date_format: DateFormat.DMY,
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div class="center">
|
|
||||||
${formatDateNumeric(date, {
|
|
||||||
...defaultLocale,
|
|
||||||
language: key,
|
|
||||||
date_format: DateFormat.MDY,
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div class="center">
|
|
||||||
${formatDateNumeric(date, {
|
|
||||||
...defaultLocale,
|
|
||||||
language: key,
|
|
||||||
date_format: DateFormat.YMD,
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</mwc-list>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles() {
|
|
||||||
return css`
|
|
||||||
.header {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.container {
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 12px auto;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container > div {
|
|
||||||
flex-grow: 1;
|
|
||||||
width: 20%;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"demo-date-time-date": DemoDateTimeDate;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -50,7 +50,6 @@ const SENSOR_DEVICE_CLASSES = [
|
|||||||
"temperature",
|
"temperature",
|
||||||
"timestamp",
|
"timestamp",
|
||||||
"volatile_organic_compounds",
|
"volatile_organic_compounds",
|
||||||
"volatile_organic_compounds_parts",
|
|
||||||
"voltage",
|
"voltage",
|
||||||
"volume",
|
"volume",
|
||||||
"water",
|
"water",
|
||||||
|
@@ -130,7 +130,6 @@ export class HassioAddonRepositoryEl extends LitElement {
|
|||||||
css`
|
css`
|
||||||
ha-card {
|
ha-card {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
.not_available {
|
.not_available {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
|
@@ -70,7 +70,7 @@ export class HassioAddonStore extends LitElement {
|
|||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
this._loadData();
|
await this._loadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,17 +92,21 @@ export class HassioAddonStore extends LitElement {
|
|||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
.header=${this.supervisor.localize("panel.store")}
|
.header=${this.supervisor.localize("panel.store")}
|
||||||
>
|
>
|
||||||
<ha-button-menu slot="toolbar-icon" @action=${this._handleAction}>
|
<ha-button-menu
|
||||||
|
corner="BOTTOM_START"
|
||||||
|
slot="toolbar-icon"
|
||||||
|
@action=${this._handleAction}
|
||||||
|
>
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
.label=${this.supervisor.localize("common.menu")}
|
.label=${this.supervisor.localize("common.menu")}
|
||||||
.path=${mdiDotsVertical}
|
.path=${mdiDotsVertical}
|
||||||
slot="trigger"
|
slot="trigger"
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("store.check_updates")}
|
${this.supervisor.localize("store.repositories")}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("store.repositories")}
|
${this.supervisor.localize("store.check_updates")}
|
||||||
</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)
|
||||||
@@ -177,10 +181,10 @@ export class HassioAddonStore extends LitElement {
|
|||||||
private _handleAction(ev: CustomEvent<ActionDetail>) {
|
private _handleAction(ev: CustomEvent<ActionDetail>) {
|
||||||
switch (ev.detail.index) {
|
switch (ev.detail.index) {
|
||||||
case 0:
|
case 0:
|
||||||
this.refreshData();
|
this._manageRepositoriesClicked();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
this._manageRepositoriesClicked();
|
this.refreshData();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
this._manageRegistries();
|
this._manageRegistries();
|
||||||
@@ -198,25 +202,25 @@ export class HassioAddonStore extends LitElement {
|
|||||||
this._manageRepositories();
|
this._manageRepositories();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _manageRepositories(url?: string) {
|
private async _manageRepositories(url?: string) {
|
||||||
showRepositoriesDialog(this, {
|
showRepositoriesDialog(this, {
|
||||||
supervisor: this.supervisor,
|
supervisor: this.supervisor,
|
||||||
url,
|
url,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _manageRegistries() {
|
private async _manageRegistries() {
|
||||||
showRegistriesDialog(this, { supervisor: this.supervisor });
|
showRegistriesDialog(this, { supervisor: this.supervisor });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _loadData() {
|
private async _loadData() {
|
||||||
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
||||||
fireEvent(this, "supervisor-collection-refresh", {
|
fireEvent(this, "supervisor-collection-refresh", {
|
||||||
collection: "supervisor",
|
collection: "supervisor",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _filterChanged(e) {
|
private async _filterChanged(e) {
|
||||||
this._filter = e.detail.value;
|
this._filter = e.detail.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -140,12 +140,7 @@ class HassioAddonConfig extends LitElement {
|
|||||||
? {
|
? {
|
||||||
name: entry.name,
|
name: entry.name,
|
||||||
required: entry.required,
|
required: entry.required,
|
||||||
selector: {
|
selector: { number: { mode: "box" } },
|
||||||
number: {
|
|
||||||
mode: "box",
|
|
||||||
step: entry.type === "float" ? "any" : undefined,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
: entry
|
: entry
|
||||||
)
|
)
|
||||||
@@ -173,7 +168,7 @@ class HassioAddonConfig extends LitElement {
|
|||||||
${this.supervisor.localize("addon.configuration.options.header")}
|
${this.supervisor.localize("addon.configuration.options.header")}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="card-menu">
|
<div class="card-menu">
|
||||||
<ha-button-menu @action=${this._handleAction}>
|
<ha-button-menu corner="BOTTOM_START" @action=${this._handleAction}>
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
.label=${this.supervisor.localize("common.menu")}
|
.label=${this.supervisor.localize("common.menu")}
|
||||||
.path=${mdiDotsVertical}
|
.path=${mdiDotsVertical}
|
||||||
|
@@ -29,6 +29,7 @@ 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";
|
||||||
|
import "../../../../src/components/buttons/ha-call-api-button";
|
||||||
import "../../../../src/components/buttons/ha-progress-button";
|
import "../../../../src/components/buttons/ha-progress-button";
|
||||||
import "../../../../src/components/ha-alert";
|
import "../../../../src/components/ha-alert";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
@@ -46,7 +47,6 @@ import {
|
|||||||
HassioAddonSetOptionParams,
|
HassioAddonSetOptionParams,
|
||||||
HassioAddonSetSecurityParams,
|
HassioAddonSetSecurityParams,
|
||||||
installHassioAddon,
|
installHassioAddon,
|
||||||
rebuildLocalAddon,
|
|
||||||
restartHassioAddon,
|
restartHassioAddon,
|
||||||
setHassioAddonOption,
|
setHassioAddonOption,
|
||||||
setHassioAddonSecurity,
|
setHassioAddonSecurity,
|
||||||
@@ -640,12 +640,13 @@ class HassioAddonInfo extends LitElement {
|
|||||||
</ha-progress-button>
|
</ha-progress-button>
|
||||||
${this.addon.build
|
${this.addon.build
|
||||||
? html`
|
? html`
|
||||||
<ha-progress-button
|
<ha-call-api-button
|
||||||
class="warning"
|
class="warning"
|
||||||
@click=${this._rebuildClicked}
|
.hass=${this.hass}
|
||||||
|
.path="hassio/addons/${this.addon.slug}/rebuild"
|
||||||
>
|
>
|
||||||
${this.supervisor.localize("addon.dashboard.rebuild")}
|
${this.supervisor.localize("addon.dashboard.rebuild")}
|
||||||
</ha-progress-button>
|
</ha-call-api-button>
|
||||||
`
|
`
|
||||||
: ""}`
|
: ""}`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -965,21 +966,6 @@ class HassioAddonInfo extends LitElement {
|
|||||||
button.progress = false;
|
button.progress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _rebuildClicked(ev: CustomEvent): Promise<void> {
|
|
||||||
const button = ev.currentTarget as any;
|
|
||||||
button.progress = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await rebuildLocalAddon(this.hass, this.addon.slug);
|
|
||||||
} catch (err: any) {
|
|
||||||
showAlertDialog(this, {
|
|
||||||
title: this.supervisor.localize("addon.dashboard.action_error.rebuild"),
|
|
||||||
text: extractApiErrorMessage(err),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
button.progress = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
@@ -1138,6 +1124,10 @@ class HassioAddonInfo extends LitElement {
|
|||||||
ha-svg-icon.stopped {
|
ha-svg-icon.stopped {
|
||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
}
|
}
|
||||||
|
ha-call-api-button {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
protection-enable mwc-button {
|
protection-enable mwc-button {
|
||||||
--mdc-theme-primary: white;
|
--mdc-theme-primary: white;
|
||||||
}
|
}
|
||||||
|
@@ -3,11 +3,11 @@ import { ActionDetail } from "@material/mwc-list";
|
|||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import { mdiBackupRestore, mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
|
import { mdiBackupRestore, mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
|
css,
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
css,
|
|
||||||
html,
|
|
||||||
nothing,
|
nothing,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
@@ -26,9 +26,9 @@ import "../../../src/components/ha-fab";
|
|||||||
import "../../../src/components/ha-icon-button";
|
import "../../../src/components/ha-icon-button";
|
||||||
import "../../../src/components/ha-svg-icon";
|
import "../../../src/components/ha-svg-icon";
|
||||||
import {
|
import {
|
||||||
HassioBackup,
|
|
||||||
fetchHassioBackups,
|
fetchHassioBackups,
|
||||||
friendlyFolderName,
|
friendlyFolderName,
|
||||||
|
HassioBackup,
|
||||||
reloadHassioBackups,
|
reloadHassioBackups,
|
||||||
removeBackup,
|
removeBackup,
|
||||||
} from "../../../src/data/hassio/backup";
|
} from "../../../src/data/hassio/backup";
|
||||||
@@ -43,7 +43,6 @@ import type { HaTabsSubpageDataTable } from "../../../src/layouts/hass-tabs-subp
|
|||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
import { HomeAssistant, Route } from "../../../src/types";
|
import { HomeAssistant, Route } from "../../../src/types";
|
||||||
import { showBackupUploadDialog } from "../dialogs/backup/show-dialog-backup-upload";
|
import { showBackupUploadDialog } from "../dialogs/backup/show-dialog-backup-upload";
|
||||||
import { showHassioBackupLocationDialog } from "../dialogs/backup/show-dialog-hassio-backu-location";
|
|
||||||
import { showHassioBackupDialog } from "../dialogs/backup/show-dialog-hassio-backup";
|
import { showHassioBackupDialog } from "../dialogs/backup/show-dialog-hassio-backup";
|
||||||
import { showHassioCreateBackupDialog } from "../dialogs/backup/show-dialog-hassio-create-backup";
|
import { showHassioCreateBackupDialog } from "../dialogs/backup/show-dialog-hassio-create-backup";
|
||||||
import { supervisorTabs } from "../hassio-tabs";
|
import { supervisorTabs } from "../hassio-tabs";
|
||||||
@@ -196,7 +195,11 @@ export class HassioBackups extends LitElement {
|
|||||||
: "/config"}
|
: "/config"}
|
||||||
supervisor
|
supervisor
|
||||||
>
|
>
|
||||||
<ha-button-menu slot="toolbar-icon" @action=${this._handleAction}>
|
<ha-button-menu
|
||||||
|
corner="BOTTOM_START"
|
||||||
|
slot="toolbar-icon"
|
||||||
|
@action=${this._handleAction}
|
||||||
|
>
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
.label=${this.supervisor?.localize("common.menu")}
|
.label=${this.supervisor?.localize("common.menu")}
|
||||||
.path=${mdiDotsVertical}
|
.path=${mdiDotsVertical}
|
||||||
@@ -205,9 +208,6 @@ export class HassioBackups extends LitElement {
|
|||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("common.reload")}
|
${this.supervisor.localize("common.reload")}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
<mwc-list-item>
|
|
||||||
${this.supervisor.localize("dialog.backup_location.title")}
|
|
||||||
</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("backup.upload_backup")}
|
${this.supervisor.localize("backup.upload_backup")}
|
||||||
@@ -274,9 +274,6 @@ export class HassioBackups extends LitElement {
|
|||||||
this.refreshData();
|
this.refreshData();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
showHassioBackupLocationDialog(this, { supervisor: this.supervisor });
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
this._showUploadBackupDialog();
|
this._showUploadBackupDialog();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
import { mdiFolder, mdiHomeAssistant, mdiPuzzle } from "@mdi/js";
|
import { mdiFolder, mdiHomeAssistant, mdiPuzzle } from "@mdi/js";
|
||||||
import "@polymer/paper-input/paper-input";
|
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
nothing,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
nothing,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, query } from "lit/decorators";
|
import { customElement, property, query } from "lit/decorators";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
@@ -24,11 +23,8 @@ import {
|
|||||||
HassioPartialBackupCreateParams,
|
HassioPartialBackupCreateParams,
|
||||||
} from "../../../src/data/hassio/backup";
|
} from "../../../src/data/hassio/backup";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||||
import {
|
import { PolymerChangedEvent } from "../../../src/polymer-types";
|
||||||
HomeAssistant,
|
import { HomeAssistant, TranslationDict } from "../../../src/types";
|
||||||
TranslationDict,
|
|
||||||
ValueChangedEvent,
|
|
||||||
} from "../../../src/types";
|
|
||||||
import "./supervisor-formfield-label";
|
import "./supervisor-formfield-label";
|
||||||
|
|
||||||
type BackupOrRestoreKey = keyof TranslationDict["supervisor"]["backup"] &
|
type BackupOrRestoreKey = keyof TranslationDict["supervisor"]["backup"] &
|
||||||
@@ -420,7 +416,7 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
this[input.name] = input.value;
|
this[input.name] = input.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleTextValueChanged(ev: ValueChangedEvent<string>) {
|
private _handleTextValueChanged(ev: PolymerChangedEvent<string>) {
|
||||||
const input = ev.currentTarget as PaperInputElement;
|
const input = ev.currentTarget as PaperInputElement;
|
||||||
this[input.name!] = ev.detail.value;
|
this[input.name!] = ev.detail.value;
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,10 @@
|
|||||||
import { mdiArrowUpBoldCircle, mdiPuzzle } from "@mdi/js";
|
import { mdiArrowUpBoldCircle, mdiPuzzle } from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
import { navigate } from "../../../src/common/navigate";
|
import { navigate } from "../../../src/common/navigate";
|
||||||
import { caseInsensitiveStringCompare } from "../../../src/common/string/compare";
|
import { caseInsensitiveStringCompare } from "../../../src/common/string/compare";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../src/components/search-input";
|
|
||||||
import { HassioAddonInfo } from "../../../src/data/hassio/addon";
|
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
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";
|
||||||
@@ -20,25 +17,11 @@ class HassioAddons extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
|
||||||
|
|
||||||
@state() private _filter?: string;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<div class="search">
|
|
||||||
<search-input
|
|
||||||
.hass=${this.hass}
|
|
||||||
suffix
|
|
||||||
.filter=${this._filter}
|
|
||||||
@value-changed=${this._handleSearchChange}
|
|
||||||
.label=${this.supervisor.localize("dashboard.search_addons")}
|
|
||||||
>
|
|
||||||
</search-input>
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${!atLeastVersion(this.hass.config.version, 2021, 12)
|
${!atLeastVersion(this.hass.config.version, 2021, 12)
|
||||||
? html`<h1>${this.supervisor.localize("dashboard.addons")}</h1>`
|
? html` <h1>${this.supervisor.localize("dashboard.addons")}</h1> `
|
||||||
: ""}
|
: ""}
|
||||||
<div class="card-group">
|
<div class="card-group">
|
||||||
${!this.supervisor.addon.addons.length
|
${!this.supervisor.addon.addons.length
|
||||||
@@ -51,9 +34,21 @@ class HassioAddons extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`
|
`
|
||||||
: this._getAddons(this.supervisor.addon.addons, this._filter).map(
|
: this.supervisor.addon.addons
|
||||||
|
.sort((a, b) =>
|
||||||
|
caseInsensitiveStringCompare(
|
||||||
|
a.name,
|
||||||
|
b.name,
|
||||||
|
this.hass.locale.language
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.map(
|
||||||
(addon) => html`
|
(addon) => html`
|
||||||
<ha-card outlined .addon=${addon} @click=${this._addonTapped}>
|
<ha-card
|
||||||
|
outlined
|
||||||
|
.addon=${addon}
|
||||||
|
@click=${this._addonTapped}
|
||||||
|
>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<hassio-card-content
|
<hassio-card-content
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
@@ -66,12 +61,16 @@ class HassioAddons extends LitElement {
|
|||||||
? mdiArrowUpBoldCircle
|
? mdiArrowUpBoldCircle
|
||||||
: mdiPuzzle}
|
: mdiPuzzle}
|
||||||
.iconTitle=${addon.state !== "started"
|
.iconTitle=${addon.state !== "started"
|
||||||
? this.supervisor.localize("dashboard.addon_stopped")
|
? this.supervisor.localize(
|
||||||
|
"dashboard.addon_stopped"
|
||||||
|
)
|
||||||
: addon.update_available!
|
: addon.update_available!
|
||||||
? this.supervisor.localize(
|
? this.supervisor.localize(
|
||||||
"dashboard.addon_new_version"
|
"dashboard.addon_new_version"
|
||||||
)
|
)
|
||||||
: this.supervisor.localize("dashboard.addon_running")}
|
: this.supervisor.localize(
|
||||||
|
"dashboard.addon_running"
|
||||||
|
)}
|
||||||
.iconClass=${addon.update_available
|
.iconClass=${addon.update_available
|
||||||
? addon.state === "started"
|
? addon.state === "started"
|
||||||
? "update"
|
? "update"
|
||||||
@@ -96,28 +95,6 @@ class HassioAddons extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getAddons = memoizeOne(
|
|
||||||
(addons: HassioAddonInfo[], filter?: string) => {
|
|
||||||
if (filter) {
|
|
||||||
addons = addons.filter((addon) => {
|
|
||||||
const lowerCaseFilter = filter.toLowerCase();
|
|
||||||
return (
|
|
||||||
addon.name.toLowerCase().includes(lowerCaseFilter) ||
|
|
||||||
addon.description.toLowerCase().includes(lowerCaseFilter) ||
|
|
||||||
addon.slug.toLowerCase().includes(lowerCaseFilter)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return addons.sort((a, b) =>
|
|
||||||
caseInsensitiveStringCompare(a.name, b.name, this.hass.locale.language)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
private _handleSearchChange(ev: CustomEvent) {
|
|
||||||
this._filter = ev.detail.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
@@ -125,17 +102,6 @@ class HassioAddons extends LitElement {
|
|||||||
css`
|
css`
|
||||||
ha-card {
|
ha-card {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.search {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
search-input {
|
|
||||||
display: block;
|
|
||||||
--mdc-text-field-fill-color: var(--sidebar-background-color);
|
|
||||||
--mdc-text-field-idle-line-color: var(--divider-color);
|
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { mdiStorePlus, mdiUpdate } from "@mdi/js";
|
import { mdiStorePlus } from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
@@ -9,11 +9,8 @@ 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 "./hassio-addons";
|
import "./hassio-addons";
|
||||||
|
import "./hassio-update";
|
||||||
import "../../../src/layouts/hass-subpage";
|
import "../../../src/layouts/hass-subpage";
|
||||||
import { reloadHassioAddons } from "../../../src/data/hassio/addon";
|
|
||||||
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
|
||||||
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
|
|
||||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
|
||||||
|
|
||||||
@customElement("hassio-dashboard")
|
@customElement("hassio-dashboard")
|
||||||
class HassioDashboard extends LitElement {
|
class HassioDashboard extends LitElement {
|
||||||
@@ -25,12 +22,6 @@ class HassioDashboard extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
firstUpdated() {
|
|
||||||
if (!atLeastVersion(this.hass.config.version, 2022, 5)) {
|
|
||||||
import("./hassio-update");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (atLeastVersion(this.hass.config.version, 2022, 5)) {
|
if (atLeastVersion(this.hass.config.version, 2022, 5)) {
|
||||||
return html`<hass-subpage
|
return html`<hass-subpage
|
||||||
@@ -40,16 +31,9 @@ class HassioDashboard extends LitElement {
|
|||||||
back-path="/config"
|
back-path="/config"
|
||||||
.header=${this.supervisor.localize("panel.addons")}
|
.header=${this.supervisor.localize("panel.addons")}
|
||||||
>
|
>
|
||||||
<ha-icon-button
|
|
||||||
slot="toolbar-icon"
|
|
||||||
@click=${this._handleCheckUpdates}
|
|
||||||
.path=${mdiUpdate}
|
|
||||||
.label=${this.supervisor.localize("store.check_updates")}
|
|
||||||
></ha-icon-button>
|
|
||||||
<hassio-addons
|
<hassio-addons
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.supervisor=${this.supervisor}
|
.supervisor=${this.supervisor}
|
||||||
.narrow=${this.narrow}
|
|
||||||
></hassio-addons>
|
></hassio-addons>
|
||||||
<a href="/hassio/store">
|
<a href="/hassio/store">
|
||||||
<ha-fab
|
<ha-fab
|
||||||
@@ -60,7 +44,7 @@ class HassioDashboard extends LitElement {
|
|||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
slot="icon"
|
slot="icon"
|
||||||
.path=${mdiStorePlus}
|
.path=${mdiStorePlus}
|
||||||
></ha-svg-icon></ha-fab
|
></ha-svg-icon> </ha-fab
|
||||||
></a>
|
></a>
|
||||||
</hass-subpage>`;
|
</hass-subpage>`;
|
||||||
}
|
}
|
||||||
@@ -110,18 +94,6 @@ class HassioDashboard extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _handleCheckUpdates() {
|
|
||||||
try {
|
|
||||||
await reloadHassioAddons(this.hass);
|
|
||||||
} catch (err) {
|
|
||||||
showAlertDialog(this, {
|
|
||||||
text: extractApiErrorMessage(err),
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
|
@@ -1,154 +0,0 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators";
|
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
|
||||||
import "../../../../src/components/ha-dialog";
|
|
||||||
import "../../../../src/components/ha-form/ha-form";
|
|
||||||
import type { SchemaUnion } from "../../../../src/components/ha-form/types";
|
|
||||||
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
|
||||||
import { changeMountOptions } from "../../../../src/data/supervisor/mounts";
|
|
||||||
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
|
||||||
import { HassioBackupLocationDialogParams } from "./show-dialog-hassio-backu-location";
|
|
||||||
|
|
||||||
const SCHEMA = memoizeOne(
|
|
||||||
() =>
|
|
||||||
[
|
|
||||||
{
|
|
||||||
name: "default_backup_mount",
|
|
||||||
required: true,
|
|
||||||
selector: { backup_location: {} },
|
|
||||||
},
|
|
||||||
] as const
|
|
||||||
);
|
|
||||||
|
|
||||||
@customElement("dialog-hassio-backup-location")
|
|
||||||
class HassioBackupLocationDialog extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property({ attribute: false })
|
|
||||||
public _dialogParams?: HassioBackupLocationDialogParams;
|
|
||||||
|
|
||||||
@state() private _data?: { default_backup_mount: string | null };
|
|
||||||
|
|
||||||
@state() private _waiting?: boolean;
|
|
||||||
|
|
||||||
@state() private _error?: string;
|
|
||||||
|
|
||||||
public async showDialog(
|
|
||||||
dialogParams: HassioBackupLocationDialogParams
|
|
||||||
): Promise<void> {
|
|
||||||
this._dialogParams = dialogParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
public closeDialog(): void {
|
|
||||||
this._data = undefined;
|
|
||||||
this._error = undefined;
|
|
||||||
this._waiting = undefined;
|
|
||||||
this._dialogParams = undefined;
|
|
||||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render() {
|
|
||||||
if (!this._dialogParams) {
|
|
||||||
return nothing;
|
|
||||||
}
|
|
||||||
return html`
|
|
||||||
<ha-dialog
|
|
||||||
open
|
|
||||||
scrimClickAction
|
|
||||||
escapeKeyAction
|
|
||||||
.heading=${this._dialogParams.supervisor.localize(
|
|
||||||
"dialog.backup_location.title"
|
|
||||||
)}
|
|
||||||
@closed=${this.closeDialog}
|
|
||||||
>
|
|
||||||
${this._error
|
|
||||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
|
||||||
: nothing}
|
|
||||||
|
|
||||||
<ha-form
|
|
||||||
.hass=${this.hass}
|
|
||||||
.data=${this._data}
|
|
||||||
.schema=${SCHEMA()}
|
|
||||||
.computeLabel=${this._computeLabelCallback}
|
|
||||||
.computeHelper=${this._computeHelperCallback}
|
|
||||||
@value-changed=${this._valueChanged}
|
|
||||||
dialogInitialFocus
|
|
||||||
></ha-form>
|
|
||||||
<mwc-button
|
|
||||||
slot="secondaryAction"
|
|
||||||
@click=${this.closeDialog}
|
|
||||||
dialogInitialFocus
|
|
||||||
>
|
|
||||||
${this._dialogParams.supervisor.localize("common.cancel")}
|
|
||||||
</mwc-button>
|
|
||||||
<mwc-button
|
|
||||||
.disabled=${this._waiting || !this._data}
|
|
||||||
slot="primaryAction"
|
|
||||||
@click=${this._changeMount}
|
|
||||||
>
|
|
||||||
${this._dialogParams.supervisor.localize("common.save")}
|
|
||||||
</mwc-button>
|
|
||||||
</ha-dialog>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _computeLabelCallback = (
|
|
||||||
// @ts-ignore
|
|
||||||
schema: SchemaUnion<ReturnType<typeof SCHEMA>>
|
|
||||||
): string =>
|
|
||||||
this._dialogParams!.supervisor.localize(
|
|
||||||
`dialog.backup_location.options.${schema.name}.name`
|
|
||||||
) || schema.name;
|
|
||||||
|
|
||||||
private _computeHelperCallback = (
|
|
||||||
// @ts-ignore
|
|
||||||
schema: SchemaUnion<ReturnType<typeof SCHEMA>>
|
|
||||||
): string =>
|
|
||||||
this._dialogParams!.supervisor.localize(
|
|
||||||
`dialog.backup_location.options.${schema.name}.description`
|
|
||||||
);
|
|
||||||
|
|
||||||
private _valueChanged(ev: CustomEvent) {
|
|
||||||
const newLocation = ev.detail.value.default_backup_mount;
|
|
||||||
this._data = {
|
|
||||||
default_backup_mount: newLocation === "/backup" ? null : newLocation,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _changeMount() {
|
|
||||||
if (!this._data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._error = undefined;
|
|
||||||
this._waiting = true;
|
|
||||||
try {
|
|
||||||
await changeMountOptions(this.hass, this._data);
|
|
||||||
} catch (err: any) {
|
|
||||||
this._error = extractApiErrorMessage(err);
|
|
||||||
this._waiting = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.closeDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
|
||||||
return [
|
|
||||||
haStyle,
|
|
||||||
haStyleDialog,
|
|
||||||
css`
|
|
||||||
.delete-btn {
|
|
||||||
--mdc-theme-primary: var(--error-color);
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"dialog-hassio-backup-location": HassioBackupLocationDialog;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -7,7 +7,6 @@ import { atLeastVersion } from "../../../../src/common/config/version";
|
|||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import { stopPropagation } from "../../../../src/common/dom/stop_propagation";
|
import { stopPropagation } from "../../../../src/common/dom/stop_propagation";
|
||||||
import { slugify } from "../../../../src/common/string/slugify";
|
import { slugify } from "../../../../src/common/string/slugify";
|
||||||
import "../../../../src/components/ha-dialog";
|
|
||||||
import "../../../../src/components/buttons/ha-progress-button";
|
import "../../../../src/components/buttons/ha-progress-button";
|
||||||
import "../../../../src/components/ha-alert";
|
import "../../../../src/components/ha-alert";
|
||||||
import "../../../../src/components/ha-button-menu";
|
import "../../../../src/components/ha-button-menu";
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
|
|
||||||
export interface HassioBackupLocationDialogParams {
|
|
||||||
supervisor: Supervisor;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const showHassioBackupLocationDialog = (
|
|
||||||
element: HTMLElement,
|
|
||||||
dialogParams: HassioBackupLocationDialogParams
|
|
||||||
): void => {
|
|
||||||
fireEvent(element, "show-dialog", {
|
|
||||||
dialogTag: "dialog-hassio-backup-location",
|
|
||||||
dialogImport: () => import("./dialog-hassio-backup-location"),
|
|
||||||
dialogParams,
|
|
||||||
});
|
|
||||||
};
|
|
@@ -316,7 +316,7 @@ export class DialogHassioNetwork
|
|||||||
>
|
>
|
||||||
<div class="radio-row">
|
<div class="radio-row">
|
||||||
<ha-formfield
|
<ha-formfield
|
||||||
.label=${this.supervisor.localize("dialog.network.auto")}
|
.label=${this.supervisor.localize("dialog.network.dhcp")}
|
||||||
>
|
>
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@change=${this._handleRadioValueChanged}
|
@change=${this._handleRadioValueChanged}
|
||||||
|
@@ -218,7 +218,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
|
|
||||||
private _handleKeyAdd(ev: KeyboardEvent) {
|
private _handleKeyAdd(ev: KeyboardEvent) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
if (ev.key !== "Enter") {
|
if (ev.keyCode !== 13) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._addRepository();
|
this._addRepository();
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
(function () {
|
|
||||||
function loadES5(src) {
|
|
||||||
var el = document.createElement("script");
|
|
||||||
el.src = src;
|
|
||||||
document.body.appendChild(el);
|
|
||||||
}
|
|
||||||
if (/.*Version\/(?:11|12)(?:\.\d+)*.*Safari\//.test(navigator.userAgent)) {
|
|
||||||
<% for (const entry of es5EntryJS) { %>
|
|
||||||
loadES5("<%= entry %>");
|
|
||||||
<% } %>
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
<% for (const entry of latestEntryJS) { %>
|
|
||||||
new Function("import('<%= entry %>')")();
|
|
||||||
<% } %>
|
|
||||||
} catch (err) {
|
|
||||||
<% for (const entry of es5EntryJS) { %>
|
|
||||||
loadES5("<%= entry %>");
|
|
||||||
<% } %>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
@@ -2,7 +2,6 @@
|
|||||||
import "../../src/resources/compatibility";
|
import "../../src/resources/compatibility";
|
||||||
import { setCancelSyntheticClickEvents } from "@polymer/polymer/lib/utils/settings";
|
import { setCancelSyntheticClickEvents } from "@polymer/polymer/lib/utils/settings";
|
||||||
import "../../src/resources/roboto";
|
import "../../src/resources/roboto";
|
||||||
import "../../src/resources/ha-style";
|
|
||||||
import "../../src/resources/safari-14-attachshadow-patch";
|
import "../../src/resources/safari-14-attachshadow-patch";
|
||||||
import "./hassio-main";
|
import "./hassio-main";
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@ import { navigate } from "../../src/common/navigate";
|
|||||||
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
|
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
|
||||||
import { Supervisor } from "../../src/data/supervisor/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 { HomeAssistant } from "../../src/types";
|
import { HomeAssistant } from "../../src/types";
|
||||||
import "./hassio-router";
|
import "./hassio-router";
|
||||||
import { SupervisorBaseElement } from "./supervisor-base-element";
|
import { SupervisorBaseElement } from "./supervisor-base-element";
|
||||||
|
@@ -5,8 +5,12 @@ import {
|
|||||||
RouterOptions,
|
RouterOptions,
|
||||||
} from "../../src/layouts/hass-router-page";
|
} from "../../src/layouts/hass-router-page";
|
||||||
import { HomeAssistant, Route } from "../../src/types";
|
import { HomeAssistant, Route } from "../../src/types";
|
||||||
|
import "./addon-store/hassio-addon-store";
|
||||||
// Don't codesplit it, that way the dashboard always loads fast.
|
// Don't codesplit it, that way the dashboard always loads fast.
|
||||||
import "./dashboard/hassio-dashboard";
|
import "./dashboard/hassio-dashboard";
|
||||||
|
// Don't codesplit the others, because it breaks the UI when pushed to a Pi
|
||||||
|
import "./backups/hassio-backups";
|
||||||
|
import "./system/hassio-system";
|
||||||
|
|
||||||
@customElement("hassio-panel-router")
|
@customElement("hassio-panel-router")
|
||||||
class HassioPanelRouter extends HassRouterPage {
|
class HassioPanelRouter extends HassRouterPage {
|
||||||
@@ -27,15 +31,12 @@ class HassioPanelRouter extends HassRouterPage {
|
|||||||
},
|
},
|
||||||
store: {
|
store: {
|
||||||
tag: "hassio-addon-store",
|
tag: "hassio-addon-store",
|
||||||
load: () => import("./addon-store/hassio-addon-store"),
|
|
||||||
},
|
},
|
||||||
backups: {
|
backups: {
|
||||||
tag: "hassio-backups",
|
tag: "hassio-backups",
|
||||||
load: () => import("./backups/hassio-backups"),
|
|
||||||
},
|
},
|
||||||
system: {
|
system: {
|
||||||
tag: "hassio-system",
|
tag: "hassio-system",
|
||||||
load: () => import("./system/hassio-system"),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -4,7 +4,6 @@ import {
|
|||||||
Supervisor,
|
Supervisor,
|
||||||
supervisorCollection,
|
supervisorCollection,
|
||||||
} from "../../src/data/supervisor/supervisor";
|
} from "../../src/data/supervisor/supervisor";
|
||||||
import "../../src/layouts/hass-loading-screen";
|
|
||||||
import { HomeAssistant, Route } from "../../src/types";
|
import { HomeAssistant, Route } from "../../src/types";
|
||||||
import "./hassio-panel-router";
|
import "./hassio-panel-router";
|
||||||
|
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
|
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
|
||||||
import { Supervisor } from "../../src/data/supervisor/supervisor";
|
import { Supervisor } from "../../src/data/supervisor/supervisor";
|
||||||
import {
|
import {
|
||||||
HassRouterPage,
|
HassRouterPage,
|
||||||
RouterOptions,
|
RouterOptions,
|
||||||
} from "../../src/layouts/hass-router-page";
|
} from "../../src/layouts/hass-router-page";
|
||||||
|
import "../../src/resources/ha-style";
|
||||||
import { HomeAssistant } from "../../src/types";
|
import { HomeAssistant } from "../../src/types";
|
||||||
// Don't codesplit it, that way the dashboard always loads fast.
|
// Don't codesplit it, that way the dashboard always loads fast.
|
||||||
import "./hassio-panel";
|
import "./hassio-panel";
|
||||||
@@ -23,15 +23,9 @@ 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",
|
||||||
beforeRender: (page: string) => {
|
beforeRender: (page: string) =>
|
||||||
if (page === "snapshots") {
|
page === "snapshots" ? "backups" : undefined,
|
||||||
return "backups";
|
initialLoad: () => this._redirectIngress(),
|
||||||
}
|
|
||||||
if (page === "dashboard" && this.panel.config?.ingress) {
|
|
||||||
return "ingress";
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
showLoading: true,
|
showLoading: true,
|
||||||
routes: {
|
routes: {
|
||||||
dashboard: {
|
dashboard: {
|
||||||
@@ -62,28 +56,32 @@ class HassioRouter extends HassRouterPage {
|
|||||||
|
|
||||||
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.localName === "hassio-panel";
|
const hassioPanel = el.nodeName === "HASSIO-PANEL";
|
||||||
const ingressPanel = el.localName === "hassio-ingress-view";
|
const route = hassioPanel ? this.route : this.routeTail;
|
||||||
const route = hassioPanel
|
|
||||||
? this.route
|
if (hassioPanel && this.panel.config?.ingress) {
|
||||||
: ingressPanel && this.panel.config?.ingress
|
this._redirectIngress();
|
||||||
? this._ingressRoute(this.panel.config?.ingress)
|
return;
|
||||||
: this.routeTail;
|
}
|
||||||
|
|
||||||
el.hass = this.hass;
|
el.hass = this.hass;
|
||||||
el.narrow = this.narrow;
|
el.narrow = this.narrow;
|
||||||
el.route = route;
|
el.route = route;
|
||||||
el.supervisor = this.supervisor;
|
el.supervisor = this.supervisor;
|
||||||
|
|
||||||
if (ingressPanel) {
|
if (el.localName === "hassio-ingress-view") {
|
||||||
el.ingressPanel = Boolean(this.panel.config?.ingress);
|
el.ingressPanel = this.panel.config && this.panel.config.ingress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _ingressRoute = memoizeOne((ingress: string) => ({
|
private async _redirectIngress() {
|
||||||
prefix: "/hassio/ingress",
|
if (this.panel.config && this.panel.config.ingress) {
|
||||||
path: `/${ingress}`,
|
this.route = {
|
||||||
}));
|
prefix: "/hassio",
|
||||||
|
path: `/ingress/${this.panel.config.ingress}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@@ -44,6 +44,10 @@ export const hassioStyle = css`
|
|||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 0.25fr));
|
grid-template-columns: repeat(auto-fit, minmax(300px, 0.25fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ha-call-api-button {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
.error {
|
.error {
|
||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
|
@@ -53,54 +53,78 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
|
|
||||||
public connectedCallback(): void {
|
public connectedCallback(): void {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
if (!this.hasUpdated) {
|
this._initializeLocalize();
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.route?.prefix === "/hassio") {
|
|
||||||
this._initSupervisor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public disconnectedCallback() {
|
public disconnectedCallback() {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
Object.keys(this._unsubs).forEach((unsub) => {
|
Object.keys(this._unsubs).forEach((unsub) => {
|
||||||
this._unsubs[unsub]();
|
this._unsubs[unsub]();
|
||||||
delete this._unsubs[unsub];
|
|
||||||
});
|
});
|
||||||
this.removeEventListener(
|
|
||||||
"supervisor-collection-refresh",
|
|
||||||
this._handleSupervisorStoreRefreshEvent
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected willUpdate(changedProperties: PropertyValues) {
|
protected updated(changedProperties: PropertyValues) {
|
||||||
if (!this.hasUpdated) {
|
super.updated(changedProperties);
|
||||||
if (this.route?.prefix === "/hassio") {
|
|
||||||
this._initSupervisor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (changedProperties.has("hass")) {
|
if (changedProperties.has("hass")) {
|
||||||
const oldHass = changedProperties.get("hass") as
|
const oldHass = changedProperties.get("hass") as
|
||||||
| HomeAssistant
|
| HomeAssistant
|
||||||
| undefined;
|
| undefined;
|
||||||
if (oldHass?.language !== this.hass.language) {
|
if (
|
||||||
|
oldHass !== undefined &&
|
||||||
|
oldHass.language !== undefined &&
|
||||||
|
oldHass.language !== this.hass.language
|
||||||
|
) {
|
||||||
this._language = this.hass.language;
|
this._language = this.hass.language;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedProperties.has("_language") || !this.hasUpdated) {
|
if (changedProperties.has("_language")) {
|
||||||
|
if (changedProperties.get("_language") !== this._language) {
|
||||||
this._initializeLocalize();
|
this._initializeLocalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _updateSupervisor(update: Partial<Supervisor>): void {
|
if (changedProperties.has("_collections")) {
|
||||||
this.supervisor = { ...this.supervisor, ...update };
|
if (this._collections) {
|
||||||
|
const unsubs = Object.keys(this._unsubs);
|
||||||
|
for (const collection of Object.keys(this._collections)) {
|
||||||
|
if (!unsubs.includes(collection)) {
|
||||||
|
this._unsubs[collection] = this._collections[collection].subscribe(
|
||||||
|
(data) => this._updateSupervisor({ [collection]: data })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _updateSupervisor(obj: Partial<Supervisor>): void {
|
||||||
|
this.supervisor = { ...this.supervisor, ...obj };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected firstUpdated(changedProps: PropertyValues): void {
|
||||||
|
super.firstUpdated(changedProps);
|
||||||
|
if (
|
||||||
|
this._language !== this.hass.language &&
|
||||||
|
this.hass.language !== undefined
|
||||||
|
) {
|
||||||
|
this._language = this.hass.language;
|
||||||
|
}
|
||||||
|
this._initializeLocalize();
|
||||||
|
if (this.route?.prefix === "/hassio") {
|
||||||
|
this._initSupervisor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _initializeLocalize() {
|
private async _initializeLocalize() {
|
||||||
const { language, data } = await getTranslation(null, this._language);
|
const { language, data } = await getTranslation(
|
||||||
|
null,
|
||||||
|
this._language,
|
||||||
|
"/api/hassio/app/static/translations"
|
||||||
|
);
|
||||||
|
|
||||||
this._updateSupervisor({
|
this.supervisor = {
|
||||||
|
...this.supervisor,
|
||||||
localize: await computeLocalize<SupervisorKeys>(
|
localize: await computeLocalize<SupervisorKeys>(
|
||||||
this.constructor.prototype,
|
this.constructor.prototype,
|
||||||
language,
|
language,
|
||||||
@@ -108,7 +132,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
[language]: data,
|
[language]: data,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _handleSupervisorStoreRefreshEvent(ev) {
|
private async _handleSupervisorStoreRefreshEvent(ev) {
|
||||||
@@ -125,17 +149,6 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
this._updateSupervisor({ [collection]: response.data });
|
this._updateSupervisor({ [collection]: response.data });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _subscribeCollection(collection: string) {
|
|
||||||
if (this._unsubs[collection]) {
|
|
||||||
this._unsubs[collection]();
|
|
||||||
}
|
|
||||||
this._unsubs[collection] = this._collections[collection].subscribe((data) =>
|
|
||||||
this._updateSupervisor({
|
|
||||||
[collection]: data,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _initSupervisor(): Promise<void> {
|
private async _initSupervisor(): Promise<void> {
|
||||||
this.addEventListener(
|
this.addEventListener(
|
||||||
"supervisor-collection-refresh",
|
"supervisor-collection-refresh",
|
||||||
@@ -145,7 +158,6 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
||||||
Object.keys(supervisorCollection).forEach((collection) => {
|
Object.keys(supervisorCollection).forEach((collection) => {
|
||||||
if (collection in this._collections) {
|
if (collection in this._collections) {
|
||||||
this._subscribeCollection(collection);
|
|
||||||
this._collections[collection].refresh();
|
this._collections[collection].refresh();
|
||||||
} else {
|
} else {
|
||||||
this._collections[collection] = getSupervisorEventCollection(
|
this._collections[collection] = getSupervisorEventCollection(
|
||||||
@@ -153,14 +165,18 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
collection,
|
collection,
|
||||||
supervisorCollection[collection]
|
supervisorCollection[collection]
|
||||||
);
|
);
|
||||||
if (this._collections[collection].state) {
|
}
|
||||||
// happens when the grace period of the collection unsubscribe has not passed yet
|
});
|
||||||
|
|
||||||
|
Object.keys(this._collections).forEach((collection) => {
|
||||||
|
if (
|
||||||
|
this.supervisor === undefined ||
|
||||||
|
this.supervisor[collection] === undefined
|
||||||
|
) {
|
||||||
this._updateSupervisor({
|
this._updateSupervisor({
|
||||||
[collection]: this._collections[collection].state,
|
[collection]: this._collections[collection].state,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this._subscribeCollection(collection);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const [
|
const [
|
||||||
|
@@ -184,7 +184,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
|
|
||||||
<ha-button-menu>
|
<ha-button-menu corner="BOTTOM_START">
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
.label=${this.supervisor.localize("common.menu")}
|
.label=${this.supervisor.localize("common.menu")}
|
||||||
.path=${mdiDotsVertical}
|
.path=${mdiDotsVertical}
|
||||||
|
@@ -42,6 +42,9 @@ import { updateCore } from "../../../src/data/supervisor/core";
|
|||||||
import { StoreAddon } from "../../../src/data/supervisor/store";
|
import { StoreAddon } from "../../../src/data/supervisor/store";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
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 "../../../src/layouts/hass-loading-screen";
|
||||||
|
import "../../../src/layouts/hass-subpage";
|
||||||
|
import "../../../src/layouts/hass-tabs-subpage";
|
||||||
import { HomeAssistant, Route } from "../../../src/types";
|
import { HomeAssistant, Route } from "../../../src/types";
|
||||||
import { addonArchIsSupported, extractChangelog } from "../util/addon";
|
import { addonArchIsSupported, extractChangelog } from "../util/addon";
|
||||||
|
|
||||||
|
163
package.json
163
package.json
@@ -25,33 +25,31 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "7.22.3",
|
|
||||||
"@braintree/sanitize-url": "6.0.2",
|
"@braintree/sanitize-url": "6.0.2",
|
||||||
"@codemirror/autocomplete": "6.7.1",
|
"@codemirror/autocomplete": "6.4.2",
|
||||||
"@codemirror/commands": "6.2.4",
|
"@codemirror/commands": "6.2.2",
|
||||||
"@codemirror/language": "6.7.0",
|
"@codemirror/language": "6.6.0",
|
||||||
"@codemirror/legacy-modes": "6.3.2",
|
"@codemirror/legacy-modes": "6.3.2",
|
||||||
"@codemirror/search": "6.4.0",
|
"@codemirror/search": "6.3.0",
|
||||||
"@codemirror/state": "6.2.1",
|
"@codemirror/state": "6.2.0",
|
||||||
"@codemirror/view": "6.12.0",
|
"@codemirror/view": "6.9.3",
|
||||||
"@egjs/hammerjs": "2.0.17",
|
"@egjs/hammerjs": "2.0.17",
|
||||||
"@formatjs/intl-datetimeformat": "6.8.0",
|
"@formatjs/intl-datetimeformat": "6.5.1",
|
||||||
"@formatjs/intl-displaynames": "6.3.2",
|
"@formatjs/intl-getcanonicallocales": "2.1.0",
|
||||||
"@formatjs/intl-getcanonicallocales": "2.2.0",
|
"@formatjs/intl-locale": "3.1.1",
|
||||||
"@formatjs/intl-locale": "3.3.0",
|
"@formatjs/intl-numberformat": "8.3.5",
|
||||||
"@formatjs/intl-numberformat": "8.5.0",
|
"@formatjs/intl-pluralrules": "5.1.10",
|
||||||
"@formatjs/intl-pluralrules": "5.2.2",
|
"@formatjs/intl-relativetimeformat": "11.1.10",
|
||||||
"@formatjs/intl-relativetimeformat": "11.2.2",
|
"@fullcalendar/core": "6.1.5",
|
||||||
"@fullcalendar/core": "6.1.8",
|
"@fullcalendar/daygrid": "6.1.5",
|
||||||
"@fullcalendar/daygrid": "6.1.8",
|
"@fullcalendar/interaction": "6.1.5",
|
||||||
"@fullcalendar/interaction": "6.1.8",
|
"@fullcalendar/list": "6.1.5",
|
||||||
"@fullcalendar/list": "6.1.8",
|
"@fullcalendar/timegrid": "6.1.5",
|
||||||
"@fullcalendar/timegrid": "6.1.8",
|
"@lezer/highlight": "1.1.4",
|
||||||
"@lezer/highlight": "1.1.6",
|
"@lit-labs/context": "0.3.0",
|
||||||
"@lit-labs/context": "0.3.1",
|
|
||||||
"@lit-labs/motion": "1.0.3",
|
"@lit-labs/motion": "1.0.3",
|
||||||
"@lit-labs/virtualizer": "2.0.2",
|
"@lit-labs/virtualizer": "1.0.1",
|
||||||
"@lrnwebcomponents/simple-tooltip": "7.0.0",
|
"@lrnwebcomponents/simple-tooltip": "4.1.0",
|
||||||
"@material/chips": "=14.0.0-canary.53b3cad2f.0",
|
"@material/chips": "=14.0.0-canary.53b3cad2f.0",
|
||||||
"@material/data-table": "=14.0.0-canary.53b3cad2f.0",
|
"@material/data-table": "=14.0.0-canary.53b3cad2f.0",
|
||||||
"@material/mwc-button": "0.27.0",
|
"@material/mwc-button": "0.27.0",
|
||||||
@@ -77,7 +75,7 @@
|
|||||||
"@material/mwc-top-app-bar": "0.27.0",
|
"@material/mwc-top-app-bar": "0.27.0",
|
||||||
"@material/mwc-top-app-bar-fixed": "0.27.0",
|
"@material/mwc-top-app-bar-fixed": "0.27.0",
|
||||||
"@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0",
|
"@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0",
|
||||||
"@material/web": "=1.0.0-pre.9",
|
"@material/web": "=1.0.0-pre.4",
|
||||||
"@mdi/js": "7.2.96",
|
"@mdi/js": "7.2.96",
|
||||||
"@mdi/svg": "7.2.96",
|
"@mdi/svg": "7.2.96",
|
||||||
"@polymer/app-layout": "3.1.0",
|
"@polymer/app-layout": "3.1.0",
|
||||||
@@ -92,40 +90,41 @@
|
|||||||
"@polymer/paper-toast": "3.0.1",
|
"@polymer/paper-toast": "3.0.1",
|
||||||
"@polymer/polymer": "3.5.1",
|
"@polymer/polymer": "3.5.1",
|
||||||
"@thomasloven/round-slider": "0.6.0",
|
"@thomasloven/round-slider": "0.6.0",
|
||||||
"@vaadin/combo-box": "24.0.7",
|
"@vaadin/combo-box": "23.3.9",
|
||||||
"@vaadin/vaadin-themable-mixin": "24.0.7",
|
"@vaadin/vaadin-themable-mixin": "23.3.9",
|
||||||
"@vibrant/color": "3.2.1-alpha.1",
|
"@vibrant/color": "3.2.1-alpha.1",
|
||||||
"@vibrant/core": "3.2.1-alpha.1",
|
"@vibrant/core": "3.2.1-alpha.1",
|
||||||
"@vibrant/quantizer-mmcq": "3.2.1-alpha.1",
|
"@vibrant/quantizer-mmcq": "3.2.1-alpha.1",
|
||||||
"@vue/web-component-wrapper": "1.3.0",
|
"@vue/web-component-wrapper": "1.3.0",
|
||||||
"@webcomponents/scoped-custom-element-registry": "0.0.9",
|
"@webcomponents/scoped-custom-element-registry": "0.0.8",
|
||||||
"@webcomponents/webcomponentsjs": "2.8.0",
|
"@webcomponents/webcomponentsjs": "2.7.0",
|
||||||
"app-datepicker": "5.1.1",
|
"app-datepicker": "5.1.1",
|
||||||
"chart.js": "3.3.2",
|
"chart.js": "3.3.2",
|
||||||
"comlink": "4.4.1",
|
"comlink": "4.4.1",
|
||||||
"core-js": "3.30.2",
|
"core-js": "3.29.1",
|
||||||
"cropperjs": "1.5.13",
|
"cropperjs": "1.5.13",
|
||||||
"date-fns": "2.30.0",
|
"date-fns": "2.29.3",
|
||||||
"date-fns-tz": "2.0.0",
|
"date-fns-tz": "2.0.0",
|
||||||
"deep-clone-simple": "1.1.1",
|
"deep-clone-simple": "1.1.1",
|
||||||
"deep-freeze": "0.0.1",
|
"deep-freeze": "0.0.1",
|
||||||
"fuse.js": "6.6.2",
|
"fuse.js": "6.6.2",
|
||||||
"google-timezones-json": "1.1.0",
|
"google-timezones-json": "1.0.2",
|
||||||
"hls.js": "1.4.4",
|
"hls.js": "1.3.5",
|
||||||
"home-assistant-js-websocket": "8.0.1",
|
"home-assistant-js-websocket": "8.0.1",
|
||||||
"idb-keyval": "6.2.1",
|
"idb-keyval": "6.2.0",
|
||||||
"intl-messageformat": "10.3.5",
|
"intl-messageformat": "10.3.3",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"leaflet": "1.9.4",
|
"leaflet": "1.9.3",
|
||||||
"leaflet-draw": "1.0.4",
|
"leaflet-draw": "1.0.4",
|
||||||
"lit": "2.7.4",
|
"lit": "2.7.0",
|
||||||
"marked": "4.3.0",
|
"marked": "4.3.0",
|
||||||
"memoize-one": "6.0.0",
|
"memoize-one": "6.0.0",
|
||||||
"node-vibrant": "3.2.1-alpha.1",
|
"node-vibrant": "3.2.1-alpha.1",
|
||||||
"proxy-polyfill": "0.3.2",
|
"proxy-polyfill": "0.3.2",
|
||||||
"punycode": "2.3.0",
|
"punycode": "2.3.0",
|
||||||
"qr-scanner": "1.4.2",
|
"qr-scanner": "1.4.2",
|
||||||
"qrcode": "1.5.3",
|
"qrcode": "1.5.1",
|
||||||
|
"regenerator-runtime": "0.13.11",
|
||||||
"resize-observer-polyfill": "1.5.1",
|
"resize-observer-polyfill": "1.5.1",
|
||||||
"roboto-fontface": "0.10.0",
|
"roboto-fontface": "0.10.0",
|
||||||
"rrule": "2.7.2",
|
"rrule": "2.7.2",
|
||||||
@@ -140,32 +139,37 @@
|
|||||||
"vue": "2.7.14",
|
"vue": "2.7.14",
|
||||||
"vue2-daterange-picker": "0.6.8",
|
"vue2-daterange-picker": "0.6.8",
|
||||||
"weekstart": "2.0.0",
|
"weekstart": "2.0.0",
|
||||||
"workbox-cacheable-response": "6.6.0",
|
"workbox-cacheable-response": "6.5.4",
|
||||||
"workbox-core": "6.6.0",
|
"workbox-core": "6.5.4",
|
||||||
"workbox-expiration": "6.6.0",
|
"workbox-expiration": "6.5.4",
|
||||||
"workbox-precaching": "6.6.0",
|
"workbox-precaching": "6.5.4",
|
||||||
"workbox-routing": "6.6.0",
|
"workbox-routing": "6.5.4",
|
||||||
"workbox-strategies": "6.6.0",
|
"workbox-strategies": "6.5.4",
|
||||||
"xss": "1.0.14"
|
"xss": "1.0.14"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.22.1",
|
"@babel/core": "7.21.3",
|
||||||
"@babel/plugin-proposal-decorators": "7.22.3",
|
"@babel/plugin-external-helpers": "7.18.6",
|
||||||
"@babel/plugin-transform-runtime": "7.22.4",
|
"@babel/plugin-proposal-class-properties": "7.18.6",
|
||||||
"@babel/preset-env": "7.22.4",
|
"@babel/plugin-proposal-decorators": "7.21.0",
|
||||||
"@babel/preset-typescript": "7.21.5",
|
"@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
|
||||||
|
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
|
||||||
|
"@babel/plugin-proposal-optional-chaining": "7.21.0",
|
||||||
|
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||||
|
"@babel/plugin-syntax-import-meta": "7.10.4",
|
||||||
|
"@babel/plugin-syntax-top-level-await": "7.14.5",
|
||||||
|
"@babel/preset-env": "7.20.2",
|
||||||
|
"@babel/preset-typescript": "7.21.0",
|
||||||
"@koa/cors": "4.0.0",
|
"@koa/cors": "4.0.0",
|
||||||
"@octokit/auth-oauth-device": "4.0.4",
|
"@octokit/auth-oauth-device": "4.0.4",
|
||||||
"@octokit/plugin-retry": "4.1.3",
|
"@octokit/rest": "19.0.7",
|
||||||
"@octokit/rest": "19.0.11",
|
|
||||||
"@open-wc/dev-server-hmr": "0.1.4",
|
"@open-wc/dev-server-hmr": "0.1.4",
|
||||||
"@rollup/plugin-babel": "6.0.3",
|
"@rollup/plugin-babel": "6.0.3",
|
||||||
"@rollup/plugin-commonjs": "25.0.0",
|
"@rollup/plugin-commonjs": "24.0.1",
|
||||||
"@rollup/plugin-json": "6.0.0",
|
"@rollup/plugin-json": "6.0.0",
|
||||||
"@rollup/plugin-node-resolve": "15.0.2",
|
"@rollup/plugin-node-resolve": "15.0.1",
|
||||||
"@rollup/plugin-replace": "5.0.2",
|
"@rollup/plugin-replace": "5.0.2",
|
||||||
"@types/babel__plugin-transform-runtime": "7.9.2",
|
"@types/chromecast-caf-receiver": "5.0.12",
|
||||||
"@types/chromecast-caf-receiver": "6.0.9",
|
|
||||||
"@types/chromecast-caf-sender": "1.0.5",
|
"@types/chromecast-caf-sender": "1.0.5",
|
||||||
"@types/esprima": "4.0.3",
|
"@types/esprima": "4.0.3",
|
||||||
"@types/glob": "8.1.0",
|
"@types/glob": "8.1.0",
|
||||||
@@ -173,47 +177,47 @@
|
|||||||
"@types/js-yaml": "4.0.5",
|
"@types/js-yaml": "4.0.5",
|
||||||
"@types/leaflet": "1.9.3",
|
"@types/leaflet": "1.9.3",
|
||||||
"@types/leaflet-draw": "1.0.6",
|
"@types/leaflet-draw": "1.0.6",
|
||||||
"@types/marked": "4.3.1",
|
"@types/marked": "4.0.8",
|
||||||
"@types/mocha": "10.0.1",
|
"@types/mocha": "10.0.1",
|
||||||
"@types/qrcode": "1.5.0",
|
"@types/qrcode": "1.5.0",
|
||||||
"@types/serve-handler": "6.1.1",
|
"@types/serve-handler": "6.1.1",
|
||||||
"@types/sortablejs": "1.15.1",
|
"@types/sortablejs": "1.15.1",
|
||||||
"@types/tar": "6.1.5",
|
"@types/tar": "6.1.4",
|
||||||
"@types/webspeechapi": "0.0.29",
|
"@types/webspeechapi": "0.0.29",
|
||||||
"@typescript-eslint/eslint-plugin": "5.59.7",
|
"@typescript-eslint/eslint-plugin": "5.57.0",
|
||||||
"@typescript-eslint/parser": "5.59.7",
|
"@typescript-eslint/parser": "5.57.0",
|
||||||
"@web/dev-server": "0.1.38",
|
"@web/dev-server": "0.1.37",
|
||||||
"@web/dev-server-rollup": "0.4.1",
|
"@web/dev-server-rollup": "0.4.0",
|
||||||
"babel-loader": "9.1.2",
|
"babel-loader": "9.1.2",
|
||||||
"babel-plugin-template-html-minifier": "4.1.0",
|
"babel-plugin-template-html-minifier": "4.1.0",
|
||||||
"chai": "4.3.7",
|
"chai": "4.3.7",
|
||||||
"del": "7.0.0",
|
"del": "7.0.0",
|
||||||
"eslint": "8.41.0",
|
"eslint": "8.37.0",
|
||||||
"eslint-config-airbnb-base": "15.0.0",
|
"eslint-config-airbnb-base": "15.0.0",
|
||||||
"eslint-config-airbnb-typescript": "17.0.0",
|
"eslint-config-airbnb-typescript": "17.0.0",
|
||||||
"eslint-config-prettier": "8.8.0",
|
"eslint-config-prettier": "8.8.0",
|
||||||
"eslint-import-resolver-webpack": "0.13.2",
|
"eslint-import-resolver-webpack": "0.13.2",
|
||||||
"eslint-plugin-disable": "2.0.3",
|
"eslint-plugin-disable": "2.0.3",
|
||||||
"eslint-plugin-import": "2.27.5",
|
"eslint-plugin-import": "2.27.5",
|
||||||
"eslint-plugin-lit": "1.8.3",
|
"eslint-plugin-lit": "1.8.2",
|
||||||
"eslint-plugin-lit-a11y": "2.4.1",
|
"eslint-plugin-lit-a11y": "2.4.0",
|
||||||
"eslint-plugin-unused-imports": "2.0.0",
|
"eslint-plugin-unused-imports": "2.0.0",
|
||||||
"eslint-plugin-wc": "1.5.0",
|
"eslint-plugin-wc": "1.4.0",
|
||||||
"esprima": "4.0.1",
|
"esprima": "4.0.1",
|
||||||
"fancy-log": "2.0.0",
|
"fancy-log": "2.0.0",
|
||||||
"fs-extra": "11.1.1",
|
"fs-extra": "11.1.1",
|
||||||
"glob": "10.2.6",
|
"glob": "9.3.2",
|
||||||
"gulp": "4.0.2",
|
"gulp": "4.0.2",
|
||||||
"gulp-flatmap": "1.0.2",
|
"gulp-flatmap": "1.0.2",
|
||||||
"gulp-json-transform": "0.4.8",
|
"gulp-json-transform": "0.4.8",
|
||||||
"gulp-merge-json": "2.1.2",
|
"gulp-merge-json": "2.1.2",
|
||||||
"gulp-rename": "2.0.0",
|
"gulp-rename": "2.0.0",
|
||||||
"gulp-zopfli-green": "6.0.1",
|
"gulp-zopfli-green": "6.0.1",
|
||||||
"html-minifier-terser": "7.2.0",
|
"html-minifier-terser": "7.1.0",
|
||||||
"husky": "8.0.3",
|
"husky": "8.0.3",
|
||||||
"instant-mocha": "1.5.1",
|
"instant-mocha": "1.5.0",
|
||||||
"jszip": "3.10.1",
|
"jszip": "3.10.1",
|
||||||
"lint-staged": "13.2.2",
|
"lint-staged": "13.2.0",
|
||||||
"lit-analyzer": "1.2.1",
|
"lit-analyzer": "1.2.1",
|
||||||
"lodash.template": "4.5.0",
|
"lodash.template": "4.5.0",
|
||||||
"magic-string": "0.30.0",
|
"magic-string": "0.30.0",
|
||||||
@@ -221,39 +225,38 @@
|
|||||||
"merge-stream": "2.0.0",
|
"merge-stream": "2.0.0",
|
||||||
"mocha": "10.2.0",
|
"mocha": "10.2.0",
|
||||||
"object-hash": "3.0.0",
|
"object-hash": "3.0.0",
|
||||||
"open": "9.1.0",
|
"open": "8.4.2",
|
||||||
"pinst": "3.0.0",
|
"pinst": "3.0.0",
|
||||||
"prettier": "2.8.8",
|
"prettier": "2.8.7",
|
||||||
"rollup": "2.79.1",
|
"rollup": "2.79.1",
|
||||||
"rollup-plugin-string": "3.0.0",
|
"rollup-plugin-string": "3.0.0",
|
||||||
"rollup-plugin-terser": "7.0.2",
|
"rollup-plugin-terser": "7.0.2",
|
||||||
"rollup-plugin-visualizer": "5.9.0",
|
"rollup-plugin-visualizer": "5.9.0",
|
||||||
"serve-handler": "6.1.5",
|
"serve-handler": "6.1.5",
|
||||||
"sinon": "15.1.0",
|
"sinon": "15.0.3",
|
||||||
"source-map-url": "0.4.1",
|
"source-map-url": "0.4.1",
|
||||||
"systemjs": "6.14.1",
|
"systemjs": "6.14.1",
|
||||||
"tar": "6.1.15",
|
"tar": "6.1.13",
|
||||||
"terser-webpack-plugin": "5.3.9",
|
"terser-webpack-plugin": "5.3.7",
|
||||||
"ts-lit-plugin": "1.2.1",
|
"ts-lit-plugin": "1.2.1",
|
||||||
"typescript": "4.9.5",
|
"typescript": "4.9.5",
|
||||||
"vinyl-buffer": "1.0.1",
|
"vinyl-buffer": "1.0.1",
|
||||||
"vinyl-source-stream": "2.0.0",
|
"vinyl-source-stream": "2.0.0",
|
||||||
"webpack": "5.84.1",
|
"webpack": "=5.72.1",
|
||||||
"webpack-cli": "5.1.1",
|
"webpack-cli": "5.0.1",
|
||||||
"webpack-dev-server": "4.15.0",
|
"webpack-dev-server": "4.13.1",
|
||||||
"webpack-manifest-plugin": "5.0.0",
|
"webpack-manifest-plugin": "5.0.0",
|
||||||
"webpackbar": "5.0.2",
|
"webpackbar": "5.0.2",
|
||||||
"workbox-build": "6.6.0"
|
"workbox-build": "6.5.4"
|
||||||
},
|
},
|
||||||
"_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
|
"_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@polymer/polymer": "patch:@polymer/polymer@3.5.1#./.yarn/patches/@polymer/polymer/pr-5569.patch",
|
"@polymer/polymer": "patch:@polymer/polymer@3.5.1#./.yarn/patches/@polymer/polymer/pr-5569.patch",
|
||||||
"@material/mwc-button@^0.25.3": "^0.27.0",
|
"@material/mwc-button@^0.25.3": "^0.27.0"
|
||||||
"sortablejs@1.15.0": "patch:sortablejs@npm%3A1.15.0#./.yarn/patches/sortablejs-npm-1.15.0-f3a393abcc.patch"
|
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"arrowParens": "always"
|
"arrowParens": "always"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@3.5.1"
|
"packageManager": "yarn@3.5.0"
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 8.8 KiB |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "home-assistant-frontend"
|
name = "home-assistant-frontend"
|
||||||
version = "20230601.1"
|
version = "20230401.0"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
description = "The Home Assistant frontend"
|
description = "The Home Assistant frontend"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash -i
|
#!/bin/sh
|
||||||
# Resolve all frontend dependencies that the application requires to develop.
|
# Resolve all frontend dependencies that the application requires to develop.
|
||||||
|
|
||||||
# Stop on errors
|
# Stop on errors
|
||||||
@@ -6,17 +6,5 @@ set -e
|
|||||||
|
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
# Install/upgrade node when inside devcontainer
|
|
||||||
if [[ -n "$DEVCONTAINER" ]]; then
|
|
||||||
nodeCurrent=$(nvm version default || echo "")
|
|
||||||
nodeLatest=$(nvm version-remote "$(cat .nvmrc)")
|
|
||||||
if [[ -z "$nodeCurrent" ]]; then
|
|
||||||
nvm install
|
|
||||||
elif [[ "$nodeCurrent" != "$nodeLatest" ]]; then
|
|
||||||
nvm install --reinstall-packages-from="$nodeCurrent" --default
|
|
||||||
nvm uninstall "$nodeCurrent"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install node modules
|
# Install node modules
|
||||||
yarn install
|
yarn install
|
@@ -9,7 +9,6 @@ import {
|
|||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { LocalizeFunc } from "../common/translations/localize";
|
|
||||||
import "../components/ha-alert";
|
import "../components/ha-alert";
|
||||||
import "../components/ha-checkbox";
|
import "../components/ha-checkbox";
|
||||||
import { computeInitialHaFormData } from "../components/ha-form/compute-initial-ha-form-data";
|
import { computeInitialHaFormData } from "../components/ha-form/compute-initial-ha-form-data";
|
||||||
@@ -21,12 +20,13 @@ import {
|
|||||||
DataEntryFlowStep,
|
DataEntryFlowStep,
|
||||||
DataEntryFlowStepForm,
|
DataEntryFlowStepForm,
|
||||||
} from "../data/data_entry_flow";
|
} from "../data/data_entry_flow";
|
||||||
|
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
||||||
import "./ha-password-manager-polyfill";
|
import "./ha-password-manager-polyfill";
|
||||||
|
|
||||||
type State = "loading" | "error" | "step";
|
type State = "loading" | "error" | "step";
|
||||||
|
|
||||||
@customElement("ha-auth-flow")
|
@customElement("ha-auth-flow")
|
||||||
export class HaAuthFlow extends LitElement {
|
export class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
||||||
@property({ attribute: false }) public authProvider?: AuthProvider;
|
@property({ attribute: false }) public authProvider?: AuthProvider;
|
||||||
|
|
||||||
@property() public clientId?: string;
|
@property() public clientId?: string;
|
||||||
@@ -35,8 +35,6 @@ export class HaAuthFlow extends LitElement {
|
|||||||
|
|
||||||
@property() public oauth2State?: string;
|
@property() public oauth2State?: string;
|
||||||
|
|
||||||
@property() public localize!: LocalizeFunc;
|
|
||||||
|
|
||||||
@state() private _state: State = "loading";
|
@state() private _state: State = "loading";
|
||||||
|
|
||||||
@state() private _stepData?: Record<string, any>;
|
@state() private _stepData?: Record<string, any>;
|
||||||
@@ -105,7 +103,7 @@ export class HaAuthFlow extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.addEventListener("keypress", (ev) => {
|
this.addEventListener("keypress", (ev) => {
|
||||||
if (ev.key === "Enter") {
|
if (ev.keyCode === 13) {
|
||||||
this._handleSubmit(ev);
|
this._handleSubmit(ev);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -82,13 +82,12 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
.redirectUri=${this.redirectUri}
|
.redirectUri=${this.redirectUri}
|
||||||
.oauth2State=${this.oauth2State}
|
.oauth2State=${this.oauth2State}
|
||||||
.authProvider=${this._authProvider}
|
.authProvider=${this._authProvider}
|
||||||
.localize=${this.localize}
|
|
||||||
></ha-auth-flow>
|
></ha-auth-flow>
|
||||||
|
|
||||||
${inactiveProviders.length > 0
|
${inactiveProviders.length > 0
|
||||||
? html`
|
? html`
|
||||||
<ha-pick-auth-provider
|
<ha-pick-auth-provider
|
||||||
.localize=${this.localize}
|
.resources=${this.resources}
|
||||||
.clientId=${this.clientId}
|
.clientId=${this.clientId}
|
||||||
.authProviders=${inactiveProviders}
|
.authProviders=${inactiveProviders}
|
||||||
@pick-auth-provider=${this._handleAuthProviderPick}
|
@pick-auth-provider=${this._handleAuthProviderPick}
|
||||||
|
@@ -2,10 +2,10 @@ import "@material/mwc-list";
|
|||||||
import { css, html, LitElement } from "lit";
|
import { css, html, LitElement } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { LocalizeFunc } from "../common/translations/localize";
|
|
||||||
import "../components/ha-icon-next";
|
import "../components/ha-icon-next";
|
||||||
import "../components/ha-list-item";
|
import "../components/ha-list-item";
|
||||||
import { AuthProvider } from "../data/auth";
|
import { AuthProvider } from "../data/auth";
|
||||||
|
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
@@ -14,11 +14,9 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@customElement("ha-pick-auth-provider")
|
@customElement("ha-pick-auth-provider")
|
||||||
export class HaPickAuthProvider extends LitElement {
|
export class HaPickAuthProvider extends litLocalizeLiteMixin(LitElement) {
|
||||||
@property() public authProviders: AuthProvider[] = [];
|
@property() public authProviders: AuthProvider[] = [];
|
||||||
|
|
||||||
@property() public localize!: LocalizeFunc;
|
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`
|
return html`
|
||||||
<p>${this.localize("ui.panel.page-authorize.pick_auth_provider")}:</p>
|
<p>${this.localize("ui.panel.page-authorize.pick_auth_provider")}:</p>
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-undef, no-console */
|
||||||
|
import {
|
||||||
|
CastStateEventData,
|
||||||
|
SessionStateEventData,
|
||||||
|
} from "chromecast-caf-receiver/cast.framework";
|
||||||
import { Auth } from "home-assistant-js-websocket";
|
import { Auth } from "home-assistant-js-websocket";
|
||||||
import { castApiAvailable } from "./cast_framework";
|
import { castApiAvailable } from "./cast_framework";
|
||||||
import { CAST_APP_ID, CAST_DEV, CAST_NS } from "./const";
|
import { CAST_APP_ID, CAST_DEV, CAST_NS } from "./const";
|
||||||
@@ -45,11 +48,11 @@ export class CastManager {
|
|||||||
});
|
});
|
||||||
context.addEventListener(
|
context.addEventListener(
|
||||||
cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
|
cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
|
||||||
this._sessionStateChanged
|
(ev) => this._sessionStateChanged(ev)
|
||||||
);
|
);
|
||||||
context.addEventListener(
|
context.addEventListener(
|
||||||
cast.framework.CastContextEventType.CAST_STATE_CHANGED,
|
cast.framework.CastContextEventType.CAST_STATE_CHANGED,
|
||||||
this._castStateChanged
|
(ev) => this._castStateChanged(ev)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +119,7 @@ export class CastManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _sessionStateChanged = (ev: cast.framework.SessionStateEventData) => {
|
private _sessionStateChanged(ev: SessionStateEventData) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.log("Cast session state changed", ev.sessionState);
|
console.log("Cast session state changed", ev.sessionState);
|
||||||
}
|
}
|
||||||
@@ -137,14 +140,14 @@ export class CastManager {
|
|||||||
this.status = undefined;
|
this.status = undefined;
|
||||||
this._fireEvent("connection-changed");
|
this._fireEvent("connection-changed");
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
private _castStateChanged = (ev: cast.framework.CastStateEventData) => {
|
private _castStateChanged(ev: CastStateEventData) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.log("Cast state changed", ev.castState);
|
console.log("Cast state changed", ev.castState);
|
||||||
}
|
}
|
||||||
this._fireEvent("state-changed");
|
this._fireEvent("state-changed");
|
||||||
};
|
}
|
||||||
|
|
||||||
private _attachMessageListener() {
|
private _attachMessageListener() {
|
||||||
const session = this.castSession;
|
const session = this.castSession;
|
||||||
|
@@ -1,106 +0,0 @@
|
|||||||
import { clamp } from "../number/clamp";
|
|
||||||
|
|
||||||
const DEFAULT_MIN_KELVIN = 2700;
|
|
||||||
const DEFAULT_MAX_KELVIN = 6500;
|
|
||||||
|
|
||||||
export const temperature2rgb = (
|
|
||||||
temperature: number
|
|
||||||
): [number, number, number] => {
|
|
||||||
const value = temperature / 100;
|
|
||||||
return [
|
|
||||||
temperatureRed(value),
|
|
||||||
temperatureGreen(value),
|
|
||||||
temperatureBlue(value),
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
const temperatureRed = (temperature: number): number => {
|
|
||||||
if (temperature <= 66) {
|
|
||||||
return 255;
|
|
||||||
}
|
|
||||||
const red = 329.698727446 * (temperature - 60) ** -0.1332047592;
|
|
||||||
return clamp(red, 0, 255);
|
|
||||||
};
|
|
||||||
|
|
||||||
const temperatureGreen = (temperature: number): number => {
|
|
||||||
let green: number;
|
|
||||||
if (temperature <= 66) {
|
|
||||||
green = 99.4708025861 * Math.log(temperature) - 161.1195681661;
|
|
||||||
} else {
|
|
||||||
green = 288.1221695283 * (temperature - 60) ** -0.0755148492;
|
|
||||||
}
|
|
||||||
return clamp(green, 0, 255);
|
|
||||||
};
|
|
||||||
|
|
||||||
const temperatureBlue = (temperature: number): number => {
|
|
||||||
if (temperature >= 66) {
|
|
||||||
return 255;
|
|
||||||
}
|
|
||||||
if (temperature <= 19) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const blue = 138.5177312231 * Math.log(temperature - 10) - 305.0447927307;
|
|
||||||
return clamp(blue, 0, 255);
|
|
||||||
};
|
|
||||||
|
|
||||||
const matchMaxScale = (
|
|
||||||
inputColors: number[],
|
|
||||||
outputColors: number[]
|
|
||||||
): number[] => {
|
|
||||||
const maxIn: number = Math.max(...inputColors);
|
|
||||||
const maxOut: number = Math.max(...outputColors);
|
|
||||||
let factor: number;
|
|
||||||
if (maxOut === 0) {
|
|
||||||
factor = 0.0;
|
|
||||||
} else {
|
|
||||||
factor = maxIn / maxOut;
|
|
||||||
}
|
|
||||||
return outputColors.map((value) => Math.round(value * factor));
|
|
||||||
};
|
|
||||||
|
|
||||||
const mired2kelvin = (miredTemperature: number) =>
|
|
||||||
Math.floor(1000000 / miredTemperature);
|
|
||||||
|
|
||||||
const kelvin2mired = (kelvintTemperature: number) =>
|
|
||||||
Math.floor(1000000 / kelvintTemperature);
|
|
||||||
|
|
||||||
export const rgbww2rgb = (
|
|
||||||
rgbww: [number, number, number, number, number],
|
|
||||||
minKelvin?: number,
|
|
||||||
maxKelvin?: number
|
|
||||||
): [number, number, number] => {
|
|
||||||
const [r, g, b, cw, ww] = rgbww;
|
|
||||||
// Calculate color temperature of the white channels
|
|
||||||
const maxMireds: number = kelvin2mired(minKelvin ?? DEFAULT_MIN_KELVIN);
|
|
||||||
const minMireds: number = kelvin2mired(maxKelvin ?? DEFAULT_MAX_KELVIN);
|
|
||||||
const miredRange: number = maxMireds - minMireds;
|
|
||||||
let ctRatio: number;
|
|
||||||
try {
|
|
||||||
ctRatio = ww / (cw + ww);
|
|
||||||
} catch (_error) {
|
|
||||||
ctRatio = 0.5;
|
|
||||||
}
|
|
||||||
const colorTempMired = minMireds + ctRatio * miredRange;
|
|
||||||
const colorTempKelvin = colorTempMired ? mired2kelvin(colorTempMired) : 0;
|
|
||||||
const [wR, wG, wB] = temperature2rgb(colorTempKelvin);
|
|
||||||
const whiteLevel = Math.max(cw, ww) / 255;
|
|
||||||
|
|
||||||
// Add the white channels to the rgb channels.
|
|
||||||
const rgb = [
|
|
||||||
r + wR * whiteLevel,
|
|
||||||
g + wG * whiteLevel,
|
|
||||||
b + wB * whiteLevel,
|
|
||||||
] as [number, number, number];
|
|
||||||
|
|
||||||
// Match the output maximum value to the input. This ensures the
|
|
||||||
// output doesn't overflow.
|
|
||||||
return matchMaxScale([r, g, b, cw, ww], rgb) as [number, number, number];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const rgbw2rgb = (
|
|
||||||
rgbw: [number, number, number, number]
|
|
||||||
): [number, number, number] => {
|
|
||||||
const [r, g, b, w] = rgbw;
|
|
||||||
const rgb = [r + w, g + w, b + w] as [number, number, number];
|
|
||||||
return matchMaxScale([r, g, b, w], rgb) as [number, number, number];
|
|
||||||
};
|
|
@@ -50,7 +50,6 @@ import {
|
|||||||
mdiRobotVacuum,
|
mdiRobotVacuum,
|
||||||
mdiScriptText,
|
mdiScriptText,
|
||||||
mdiSineWave,
|
mdiSineWave,
|
||||||
mdiSpeakerMessage,
|
|
||||||
mdiSpeedometer,
|
mdiSpeedometer,
|
||||||
mdiSunWireless,
|
mdiSunWireless,
|
||||||
mdiThermometer,
|
mdiThermometer,
|
||||||
@@ -76,15 +75,13 @@ export const DEFAULT_DOMAIN_ICON = mdiBookmark;
|
|||||||
|
|
||||||
/** Icons for each domain */
|
/** Icons for each domain */
|
||||||
export const FIXED_DOMAIN_ICONS = {
|
export const FIXED_DOMAIN_ICONS = {
|
||||||
air_quality: mdiAirFilter,
|
|
||||||
alert: mdiAlert,
|
alert: mdiAlert,
|
||||||
|
air_quality: mdiAirFilter,
|
||||||
calendar: mdiCalendar,
|
calendar: mdiCalendar,
|
||||||
climate: mdiThermostat,
|
climate: mdiThermostat,
|
||||||
configurator: mdiCog,
|
configurator: mdiCog,
|
||||||
conversation: mdiMicrophoneMessage,
|
conversation: mdiMicrophoneMessage,
|
||||||
counter: mdiCounter,
|
counter: mdiCounter,
|
||||||
datetime: mdiCalendarClock,
|
|
||||||
date: mdiCalendar,
|
|
||||||
demo: mdiHomeAssistant,
|
demo: mdiHomeAssistant,
|
||||||
google_assistant: mdiGoogleAssistant,
|
google_assistant: mdiGoogleAssistant,
|
||||||
group: mdiGoogleCirclesCommunities,
|
group: mdiGoogleCirclesCommunities,
|
||||||
@@ -109,13 +106,10 @@ export const FIXED_DOMAIN_ICONS = {
|
|||||||
script: mdiScriptText,
|
script: mdiScriptText,
|
||||||
select: mdiFormatListBulleted,
|
select: mdiFormatListBulleted,
|
||||||
sensor: mdiEye,
|
sensor: mdiEye,
|
||||||
simple_alarm: mdiBell,
|
|
||||||
siren: mdiBullhorn,
|
siren: mdiBullhorn,
|
||||||
stt: mdiMicrophoneMessage,
|
simple_alarm: mdiBell,
|
||||||
text: mdiFormTextbox,
|
text: mdiFormTextbox,
|
||||||
time: mdiClock,
|
|
||||||
timer: mdiTimerOutline,
|
timer: mdiTimerOutline,
|
||||||
tts: mdiSpeakerMessage,
|
|
||||||
updater: mdiCloudUpload,
|
updater: mdiCloudUpload,
|
||||||
vacuum: mdiRobotVacuum,
|
vacuum: mdiRobotVacuum,
|
||||||
zone: mdiMapMarkerRadius,
|
zone: mdiMapMarkerRadius,
|
||||||
@@ -162,7 +156,6 @@ export const FIXED_DEVICE_CLASS_ICONS = {
|
|||||||
temperature: mdiThermometer,
|
temperature: mdiThermometer,
|
||||||
timestamp: mdiClock,
|
timestamp: mdiClock,
|
||||||
volatile_organic_compounds: mdiMolecule,
|
volatile_organic_compounds: mdiMolecule,
|
||||||
volatile_organic_compounds_parts: mdiMolecule,
|
|
||||||
voltage: mdiSineWave,
|
voltage: mdiSineWave,
|
||||||
volume: mdiCarCoolantLevel,
|
volume: mdiCarCoolantLevel,
|
||||||
water: mdiWater,
|
water: mdiWater,
|
||||||
@@ -212,8 +205,6 @@ export const DOMAINS_INPUT_ROW = [
|
|||||||
"automation",
|
"automation",
|
||||||
"button",
|
"button",
|
||||||
"cover",
|
"cover",
|
||||||
"date",
|
|
||||||
"datetime",
|
|
||||||
"fan",
|
"fan",
|
||||||
"group",
|
"group",
|
||||||
"humidifier",
|
"humidifier",
|
||||||
@@ -232,7 +223,6 @@ export const DOMAINS_INPUT_ROW = [
|
|||||||
"select",
|
"select",
|
||||||
"switch",
|
"switch",
|
||||||
"text",
|
"text",
|
||||||
"time",
|
|
||||||
"vacuum",
|
"vacuum",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -1,23 +0,0 @@
|
|||||||
import { isSameDay, isSameYear } from "date-fns";
|
|
||||||
import { FrontendLocaleData } from "../../data/translation";
|
|
||||||
import {
|
|
||||||
formatShortDateTime,
|
|
||||||
formatShortDateTimeWithYear,
|
|
||||||
} from "./format_date_time";
|
|
||||||
import { formatTime } from "./format_time";
|
|
||||||
|
|
||||||
export const absoluteTime = (
|
|
||||||
from: Date,
|
|
||||||
locale: FrontendLocaleData,
|
|
||||||
to?: Date
|
|
||||||
): string => {
|
|
||||||
const _to = to ?? new Date();
|
|
||||||
|
|
||||||
if (isSameDay(from, _to)) {
|
|
||||||
return formatTime(from, locale);
|
|
||||||
}
|
|
||||||
if (isSameYear(from, _to)) {
|
|
||||||
return formatShortDateTime(from, locale);
|
|
||||||
}
|
|
||||||
return formatShortDateTimeWithYear(from, locale);
|
|
||||||
};
|
|
@@ -1,7 +1,11 @@
|
|||||||
import { getWeekStartByLocale } from "weekstart";
|
import { getWeekStartByLocale } from "weekstart";
|
||||||
import { FrontendLocaleData, FirstWeekday } from "../../data/translation";
|
import { FrontendLocaleData, FirstWeekday } from "../../data/translation";
|
||||||
|
|
||||||
import "../../resources/intl-polyfill";
|
import { polyfillsLoaded } from "../translations/localize";
|
||||||
|
|
||||||
|
if (__BUILD__ === "latest" && polyfillsLoaded) {
|
||||||
|
await polyfillsLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
export const weekdays = [
|
export const weekdays = [
|
||||||
"sunday",
|
"sunday",
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user