From 21296b4224daa60f4608b4fe8e53a2f328dcbce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Tue, 19 May 2020 22:20:29 +0200 Subject: [PATCH 01/77] Adds more styling to markdown elements (#5904) --- .../hassio-addon-documentation-tab.ts | 3 + .../src/addon-view/info/hassio-addon-info.ts | 9 +- .../markdown/dialog-hassio-markdown.ts | 3 + src/components/ha-markdown-element.ts | 71 +++++++++++ src/components/ha-markdown.ts | 119 ++++++++++-------- .../lovelace/cards/hui-markdown-card.ts | 22 +--- 6 files changed, 151 insertions(+), 76 deletions(-) create mode 100644 src/components/ha-markdown-element.ts diff --git a/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts b/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts index 5a25c5e30d..34d0087120 100644 --- a/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts +++ b/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts @@ -64,6 +64,9 @@ class HassioAddonDocumentationDashboard extends LitElement { padding: 8px; max-width: 1024px; } + ha-markdown { + padding: 16px; + } `, ]; } diff --git a/hassio/src/addon-view/info/hassio-addon-info.ts b/hassio/src/addon-view/info/hassio-addon-info.ts index 59f0a88466..7ba518c194 100644 --- a/hassio/src/addon-view/info/hassio-addon-info.ts +++ b/hassio/src/addon-view/info/hassio-addon-info.ts @@ -630,14 +630,10 @@ class HassioAddonInfo extends LitElement { .right { float: right; } - ha-markdown img { - max-width: 100%; - } protection-enable mwc-button { --mdc-theme-primary: white; } - .description a, - ha-markdown a { + .description a { color: var(--primary-color); } .red { @@ -675,6 +671,9 @@ class HassioAddonInfo extends LitElement { text-decoration: underline; cursor: pointer; } + ha-markdown { + padding: 16px; + } `, ]; } diff --git a/hassio/src/dialogs/markdown/dialog-hassio-markdown.ts b/hassio/src/dialogs/markdown/dialog-hassio-markdown.ts index 947a42f236..8feae8e709 100644 --- a/hassio/src/dialogs/markdown/dialog-hassio-markdown.ts +++ b/hassio/src/dialogs/markdown/dialog-hassio-markdown.ts @@ -90,6 +90,9 @@ class HassioMarkdownDialog extends LitElement { color: var(--text-primary-color); background-color: var(--primary-color); } + ha-markdown { + padding: 16px; + } } `, ]; diff --git a/src/components/ha-markdown-element.ts b/src/components/ha-markdown-element.ts new file mode 100644 index 0000000000..69844b3ad2 --- /dev/null +++ b/src/components/ha-markdown-element.ts @@ -0,0 +1,71 @@ +import { customElement, property, UpdatingElement } from "lit-element"; +import { fireEvent } from "../common/dom/fire_event"; +import { renderMarkdown } from "../resources/render-markdown"; + +@customElement("ha-markdown-element") +class HaMarkdownElement extends UpdatingElement { + @property() public content?; + + @property({ type: Boolean }) public allowSvg = false; + + @property({ type: Boolean }) public breaks = false; + + protected update(changedProps) { + super.update(changedProps); + if (this.content !== undefined) { + this._render(); + } + } + + private async _render() { + this.innerHTML = await renderMarkdown( + this.content, + { + breaks: this.breaks, + gfm: true, + tables: true, + }, + { + allowSvg: this.allowSvg, + } + ); + + this._resize(); + + const walker = document.createTreeWalker( + this, + 1 /* SHOW_ELEMENT */, + null, + false + ); + + while (walker.nextNode()) { + const node = walker.currentNode; + + // Open external links in a new window + if ( + node instanceof HTMLAnchorElement && + node.host !== document.location.host + ) { + node.target = "_blank"; + node.rel = "noreferrer"; + + // protect referrer on external links and deny window.opener access for security reasons + // (see https://mathiasbynens.github.io/rel-noopener/) + node.rel = "noreferrer noopener"; + + // Fire a resize event when images loaded to notify content resized + } else if (node instanceof HTMLImageElement) { + node.addEventListener("load", this._resize); + } + } + } + + private _resize = () => fireEvent(this, "iron-resize"); +} + +declare global { + interface HTMLElementTagNameMap { + "ha-markdown-element": HaMarkdownElement; + } +} diff --git a/src/components/ha-markdown.ts b/src/components/ha-markdown.ts index 162a344daf..b3f6b6b0c8 100644 --- a/src/components/ha-markdown.ts +++ b/src/components/ha-markdown.ts @@ -1,65 +1,80 @@ -import { customElement, property, UpdatingElement } from "lit-element"; -import { fireEvent } from "../common/dom/fire_event"; -import { renderMarkdown } from "../resources/render-markdown"; +import { + css, + CSSResult, + customElement, + html, + LitElement, + property, + TemplateResult, +} from "lit-element"; + +import "./ha-markdown-element"; @customElement("ha-markdown") -class HaMarkdown extends UpdatingElement { - @property() public content = ""; +class HaMarkdown extends LitElement { + @property() public content?; @property({ type: Boolean }) public allowSvg = false; @property({ type: Boolean }) public breaks = false; - protected update(changedProps) { - super.update(changedProps); - this._render(); - } - - private async _render() { - this.innerHTML = await renderMarkdown( - this.content, - { - breaks: this.breaks, - gfm: true, - tables: true, - }, - { - allowSvg: this.allowSvg, - } - ); - - this._resize(); - - const walker = document.createTreeWalker( - this, - 1 /* SHOW_ELEMENT */, - null, - false - ); - - while (walker.nextNode()) { - const node = walker.currentNode; - - // Open external links in a new window - if ( - node instanceof HTMLAnchorElement && - node.host !== document.location.host - ) { - node.target = "_blank"; - node.rel = "noreferrer"; - - // protect referrer on external links and deny window.opener access for security reasons - // (see https://mathiasbynens.github.io/rel-noopener/) - node.rel = "noreferrer noopener"; - - // Fire a resize event when images loaded to notify content resized - } else if (node instanceof HTMLImageElement) { - node.addEventListener("load", this._resize); - } + protected render(): TemplateResult { + if (!this.content) { + return html``; } + + return html``; } - private _resize = () => fireEvent(this, "iron-resize"); + static get styles(): CSSResult { + return css` + :host { + display: block; + } + ha-markdown-element { + -ms-user-select: text; + -webkit-user-select: text; + -moz-user-select: text; + } + ha-markdown-element > *:first-child { + margin-top: 0; + } + ha-markdown-element > *:last-child { + margin-bottom: 0; + } + ha-markdown-element a { + color: var(--primary-color); + } + ha-markdown-element img { + max-width: 100%; + } + ha-markdown-element code, + pre { + background-color: var(--markdown-code-background-color, #f6f8fa); + border-radius: 3px; + } + ha-markdown-element code { + font-size: 85%; + padding: 0.2em 0.4em; + } + ha-markdown-element pre code { + padding: 0; + } + ha-markdown-element pre { + padding: 16px; + overflow: auto; + line-height: 1.45; + } + ha-markdown-element h2 { + font-size: 1.5em !important; + font-weight: bold !important; + } + `; + } } declare global { diff --git a/src/panels/lovelace/cards/hui-markdown-card.ts b/src/panels/lovelace/cards/hui-markdown-card.ts index 75ac449ad0..97ca5aab28 100644 --- a/src/panels/lovelace/cards/hui-markdown-card.ts +++ b/src/panels/lovelace/cards/hui-markdown-card.ts @@ -80,9 +80,9 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { @@ -162,27 +162,11 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { static get styles(): CSSResult { return css` ha-markdown { - display: block; padding: 0 16px 16px; - -ms-user-select: initial; - -webkit-user-select: initial; - -moz-user-select: initial; } - .markdown.no-header { + ha-markdown.no-header { padding-top: 16px; } - ha-markdown > *:first-child { - margin-top: 0; - } - ha-markdown > *:last-child { - margin-bottom: 0; - } - ha-markdown a { - color: var(--primary-color); - } - ha-markdown img { - max-width: 100%; - } `; } } From 6ae717bbfee89bb9ac19d7c950caf6cb7c4a8245 Mon Sep 17 00:00:00 2001 From: HomeAssistant Azure Date: Wed, 20 May 2020 00:32:38 +0000 Subject: [PATCH 02/77] [ci skip] Translation update --- translations/frontend/ca.json | 4 +++- translations/frontend/es.json | 2 ++ translations/frontend/fi.json | 5 ++++- translations/frontend/fr.json | 1 + translations/frontend/ko.json | 2 ++ translations/frontend/nb.json | 2 ++ translations/frontend/pl.json | 2 ++ translations/frontend/ru.json | 2 ++ translations/frontend/zh-Hant.json | 2 ++ 9 files changed, 20 insertions(+), 2 deletions(-) diff --git a/translations/frontend/ca.json b/translations/frontend/ca.json index 38b2b25f94..9f5169b4ba 100644 --- a/translations/frontend/ca.json +++ b/translations/frontend/ca.json @@ -1254,7 +1254,9 @@ "device_not_found": "Dispositiu no trobat.", "entities": { "add_entities_lovelace": "Afegeix a Lovelace", + "disabled_entities": "+{count} {count, plural,\n one {entitat desabilitada}\n other {entitats desabilitades}\n}", "entities": "Entitats", + "hide_disabled": "Amaga desactivades", "none": "Aquest dispositiu no té entitats" }, "name": "Nom", @@ -2286,7 +2288,7 @@ "confirm_delete": "Esborrar visualització?", "confirm_delete_existing_cards": "Si elimines aquesta vista, també s'eliminaran les targetes que conté", "confirm_delete_existing_cards_text": "Estàs segur que vols eliminar la vista ''{name}''? La vista conté {number} targetes que també s'eliminaran. Aquesta acció no és reversible.", - "confirm_delete_text": "Estàs segur que vols eliminar la vista '{name}'?" + "confirm_delete_text": "Estàs segur que vols eliminar la vista \"{name}\"?" }, "warning": { "attribute_not_found": "L'atribut {attribute} de {entity} no és disponible.", diff --git a/translations/frontend/es.json b/translations/frontend/es.json index 7f8986282b..02ef59e7ab 100644 --- a/translations/frontend/es.json +++ b/translations/frontend/es.json @@ -1254,7 +1254,9 @@ "device_not_found": "Dispositivo no encontrado.", "entities": { "add_entities_lovelace": "Añadir a Lovelace", + "disabled_entities": "+{count} {count, plural,\n one {entidad deshabilitada}\n other {entidades deshabilitadas}\n}", "entities": "Entidades", + "hide_disabled": "Ocultar deshabilitadas", "none": "Este dispositivo no tiene entidades" }, "name": "Nombre", diff --git a/translations/frontend/fi.json b/translations/frontend/fi.json index 6b0fdd780d..4ef1c899e2 100644 --- a/translations/frontend/fi.json +++ b/translations/frontend/fi.json @@ -1254,7 +1254,9 @@ "device_not_found": "Laitetta ei löydy.", "entities": { "add_entities_lovelace": "Lisää Lovelace näkymään", + "disabled_entities": "{count} {count, plural,\n one {kohde}\n other {kohdetta}\n}", "entities": "Kohteet", + "hide_disabled": "Piilota käytöstä poistetut", "none": "Tällä laitteella ei ole kohteita" }, "name": "Nimi", @@ -1374,7 +1376,8 @@ "restart_confirm": "Käynnistä Home Assistant uudellen viimeistelläksesi tämän integraation poistamisen", "settings_button": "Muokkaa {integration}-asetuksia", "system_options": "Järjestelmäasetukset", - "system_options_button": "{integration}-järjestelmän asetukset" + "system_options_button": "{integration}-järjestelmän asetukset", + "unnamed_entry": "Nimeämätön merkintä" }, "config_flow": { "aborted": "Keskeytetty", diff --git a/translations/frontend/fr.json b/translations/frontend/fr.json index a2d09c2c11..27fa326353 100644 --- a/translations/frontend/fr.json +++ b/translations/frontend/fr.json @@ -1255,6 +1255,7 @@ "entities": { "add_entities_lovelace": "Ajouter à Lovelace", "entities": "Entités", + "hide_disabled": "Masquer désactivé", "none": "Cet appareil n'a pas d'entités" }, "name": "Nom", diff --git a/translations/frontend/ko.json b/translations/frontend/ko.json index a894f92a5b..30ec48a1a7 100644 --- a/translations/frontend/ko.json +++ b/translations/frontend/ko.json @@ -1254,7 +1254,9 @@ "device_not_found": "기기를 찾을 수 없습니다.", "entities": { "add_entities_lovelace": "Lovelace 에 추가", + "disabled_entities": "+{count} {count, plural,\n one {비활성화 된 구성요소}\n other {비활성화 된 구성요소}\n}", "entities": "구성요소", + "hide_disabled": "비활성화 된 구성요소 숨김", "none": "이 기기는 구성요소가 없습니다" }, "name": "이름", diff --git a/translations/frontend/nb.json b/translations/frontend/nb.json index 7e032cf358..42cce0a713 100644 --- a/translations/frontend/nb.json +++ b/translations/frontend/nb.json @@ -1254,7 +1254,9 @@ "device_not_found": "Enhet ikke funnet", "entities": { "add_entities_lovelace": "Legg til i Lovelace", + "disabled_entities": "+{count} {antall, flertall,\n én {deaktivert enhet}\n andre {deaktiverte enheter}\n}", "entities": "Enheter", + "hide_disabled": "Skjul deaktiverte", "none": "Denne enheten har ingen enheter" }, "name": "Navn", diff --git a/translations/frontend/pl.json b/translations/frontend/pl.json index 3ed6bf40d6..2375de9805 100644 --- a/translations/frontend/pl.json +++ b/translations/frontend/pl.json @@ -1254,7 +1254,9 @@ "device_not_found": "Urządzenie nie zostało znalezione.", "entities": { "add_entities_lovelace": "Dodaj do interfejsu użytkownika Lovelace", + "disabled_entities": "+{count} {count, plural,\n one {wyłączona encja}\n few {wyłączone encje}\n many {wyłączonych encji}\n other {wyłączonych encji}\n}", "entities": "Encje", + "hide_disabled": "Ukryj wyłączone", "none": "To urządzenie nie ma żadnych encji" }, "name": "Nazwa", diff --git a/translations/frontend/ru.json b/translations/frontend/ru.json index ee22af500a..5fcf41b28c 100644 --- a/translations/frontend/ru.json +++ b/translations/frontend/ru.json @@ -1254,7 +1254,9 @@ "device_not_found": "Устройство не найдено", "entities": { "add_entities_lovelace": "Добавить объекты в Lovelace UI", + "disabled_entities": "+{count} {count, plural,\n one {скрытый объект}\n other {скрытых объектов}\n}", "entities": "Объекты", + "hide_disabled": "Не показывать скрытые", "none": "У этого устройства нет объектов" }, "name": "Название", diff --git a/translations/frontend/zh-Hant.json b/translations/frontend/zh-Hant.json index 655ceb66cb..9c6c741d01 100644 --- a/translations/frontend/zh-Hant.json +++ b/translations/frontend/zh-Hant.json @@ -1254,7 +1254,9 @@ "device_not_found": "未找到設備。", "entities": { "add_entities_lovelace": "新增至 Lovelace UI", + "disabled_entities": "{count} {count, plural,\n one {個已關閉物件}\n other {個已關閉物件}\n}", "entities": "物件列表面板", + "hide_disabled": "隱藏已關閉物件", "none": "此設備沒有物件。" }, "name": "名稱", From d2a1d11d16b521a412d2a72993c6949fed7d456d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 19 May 2020 23:55:17 -0700 Subject: [PATCH 03/77] limit manifest to entrypoints (#5936) --- build-scripts/webpack.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build-scripts/webpack.js b/build-scripts/webpack.js index 08d419c446..f5b397888f 100644 --- a/build-scripts/webpack.js +++ b/build-scripts/webpack.js @@ -53,7 +53,10 @@ const createWebpackConfig = ({ }, plugins: [ new WorkerPlugin(), - new ManifestPlugin(), + new ManifestPlugin({ + // Only include the JS of entrypoints + filter: (file) => file.isInitial && !file.name.endsWith(".map"), + }), new webpack.DefinePlugin({ __DEV__: !isProdBuild, __BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"), From 300c8d06c4c73601bcefbc1b0baeceef007fdba9 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 20 May 2020 10:01:33 +0200 Subject: [PATCH 04/77] Fix search for data-tables using the builtin search bar (#5937) --- src/components/data-table/ha-data-table.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/data-table/ha-data-table.ts b/src/components/data-table/ha-data-table.ts index 015f54130e..ce957a0ee4 100644 --- a/src/components/data-table/ha-data-table.ts +++ b/src/components/data-table/ha-data-table.ts @@ -382,7 +382,7 @@ export class HaDataTable extends LitElement { filteredData = await this._memFilterData( this.data, this._sortColumns, - this.filter + this._filter ); } From 28d26065e49560e87db73f567bfcb8efe36609d9 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 20 May 2020 16:23:50 +0200 Subject: [PATCH 05/77] Upgrade lazy loaded elements before setting config (#5944) --- src/panels/lovelace/create-element/create-element-base.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/lovelace/create-element/create-element-base.ts b/src/panels/lovelace/create-element/create-element-base.ts index c8379e8f3a..f409f6a3b6 100644 --- a/src/panels/lovelace/create-element/create-element-base.ts +++ b/src/panels/lovelace/create-element/create-element-base.ts @@ -126,6 +126,7 @@ const _lazyCreate = ( ) as CreateElementConfigTypes[T]["element"]; customElements.whenDefined(tag).then(() => { try { + customElements.upgrade(element); // @ts-ignore element.setConfig(config); } catch (err) { From dcd6c6f06f456548485eab0397544a6536acf1c7 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 20 May 2020 17:34:15 +0200 Subject: [PATCH 06/77] Fix picture header footer upgrade (#5945) --- .../header-footer/hui-picture-header-footer.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/panels/lovelace/header-footer/hui-picture-header-footer.ts b/src/panels/lovelace/header-footer/hui-picture-header-footer.ts index 9807c4a0e6..34d4c893b7 100644 --- a/src/panels/lovelace/header-footer/hui-picture-header-footer.ts +++ b/src/panels/lovelace/header-footer/hui-picture-header-footer.ts @@ -6,6 +6,7 @@ import { LitElement, property, TemplateResult, + PropertyValues, } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; import { ifDefined } from "lit-html/directives/if-defined"; @@ -30,7 +31,7 @@ export class HuiPictureHeaderFooter extends LitElement }; } - public hass?: HomeAssistant; + @property() public hass?: HomeAssistant; @property() protected _config?: PictureHeaderFooterConfig; @@ -42,6 +43,13 @@ export class HuiPictureHeaderFooter extends LitElement this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + if (changedProps.size === 1 && changedProps.has("hass")) { + return !changedProps.get("hass"); + } + return true; + } + protected render(): TemplateResult { if (!this._config || !this.hass) { return html``; From 28e0384b55d93f2c176a23dfda5756cdee17651b Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 20 May 2020 19:31:45 +0200 Subject: [PATCH 07/77] Fix disabled styling zone panel (#5950) --- src/panels/config/zone/ha-config-zone.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/panels/config/zone/ha-config-zone.ts b/src/panels/config/zone/ha-config-zone.ts index 475e3822a7..1d794fa3e4 100644 --- a/src/panels/config/zone/ha-config-zone.ts +++ b/src/panels/config/zone/ha-config-zone.ts @@ -489,6 +489,9 @@ export class HaConfigZone extends SubscribeMixin(LitElement) { mwc-icon-button:not([disabled]) { color: var(--secondary-text-color); } + mwc-icon-button { + --mdc-theme-text-disabled-on-light: var(--disabled-text-color); + } .empty { text-align: center; padding: 8px; From 3a453f58439a2505642aba6b795f63923d0acc62 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 20 May 2020 21:27:08 +0200 Subject: [PATCH 08/77] Fix resize observers and update gauge styling (#5949) --- src/panels/lovelace/cards/hui-gauge-card.ts | 45 ++++++++++--------- .../lovelace/cards/hui-media-control-card.ts | 6 +-- .../cards/hui-weather-forecast-card.ts | 6 +-- .../hui-media-player-entity-row.ts | 6 +-- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/panels/lovelace/cards/hui-gauge-card.ts b/src/panels/lovelace/cards/hui-gauge-card.ts index 3297515f53..c13ff98fef 100644 --- a/src/panels/lovelace/cards/hui-gauge-card.ts +++ b/src/panels/lovelace/cards/hui-gauge-card.ts @@ -238,9 +238,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { private async _attachObserver(): Promise { await installResizeObserver(); - this._resizeObserver = new ResizeObserver( - debounce(() => this._measureCard(), 250, false) - ); + this._resizeObserver = new ResizeObserver(this._debouncedMeasure); const card = this.shadowRoot!.querySelector("ha-card"); // If we show an error or warning there is no ha-card @@ -250,6 +248,8 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { this._resizeObserver.observe(card); } + private _debouncedMeasure = debounce(() => this._measureCard(), 250, true); + private _measureCard() { if (!this.isConnected) { return; @@ -277,7 +277,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { cursor: pointer; height: 100%; overflow: hidden; - padding: 16px 16px 0 16px; + padding: 16px; display: flex; align-items: center; justify-content: center; @@ -293,37 +293,39 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { round-slider { max-width: 200px; --round-slider-path-width: 35px; - --round-slider-path-color: var(--disabled-text-color); + --round-slider-path-color: var(--primary-background-color); --round-slider-linecap: "butt"; } .gauge-data { - line-height: 1; text-align: center; - position: relative; + line-height: initial; color: var(--primary-text-color); - margin-top: -28px; - margin-bottom: 14px; + margin-top: -26px; + width: 100%; } .gauge-data .percent { + white-space: nowrap; font-size: 28px; } .gauge-data .name { - padding-top: 6px; - font-size: 14px; + font-size: 15px; } /* ============= NARROW ============= */ + :host([narrow]) ha-card { + padding: 8px; + } + :host([narrow]) round-slider { --round-slider-path-width: 22px; } :host([narrow]) .gauge-data { - margin-top: -24px; - margin-bottom: 12px; + margin-top: -22px; } :host([narrow]) .gauge-data .percent { @@ -331,30 +333,29 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { } :host([narrow]) .gauge-data .name { - font-size: 12px; + font-size: 14px; } /* ============= VERY NARROW ============= */ + :host([narrow]) ha-card { + padding: 4px; + } + :host([veryNarrow]) round-slider { --round-slider-path-width: 15px; } - :host([veryNarrow]) ha-card { - padding-bottom: 16px; - } - :host([veryNarrow]) .gauge-data { - margin-top: 0; - margin-bottom: 0; + margin-top: -16px; } :host([veryNarrow]) .gauge-data .percent { - font-size: 20px; + font-size: 16px; } :host([veryNarrow]) .gauge-data .name { - font-size: 10px; + font-size: 12px; } `; } diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index f1e070ff65..c7e5ba8319 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -618,6 +618,8 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { ); } + private _debouncedMeasure = debounce(() => this._measureCard(), 250, true); + private _measureCard() { const card = this.shadowRoot!.querySelector("ha-card"); if (!card) { @@ -630,9 +632,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { private async _attachObserver(): Promise { await installResizeObserver(); - this._resizeObserver = new ResizeObserver( - debounce(() => this._measureCard(), 250, false) - ); + this._resizeObserver = new ResizeObserver(this._debouncedMeasure); const card = this.shadowRoot!.querySelector("ha-card"); // If we show an error or warning there is no ha-card diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index 74f0151a2e..69862bb4c3 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -290,9 +290,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { private async _attachObserver(): Promise { await installResizeObserver(); - this._resizeObserver = new ResizeObserver( - debounce(() => this._measureCard(), 250, false) - ); + this._resizeObserver = new ResizeObserver(this._debouncedMeasure); const card = this.shadowRoot!.querySelector("ha-card"); // If we show an error or warning there is no ha-card @@ -302,6 +300,8 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { this._resizeObserver.observe(card); } + private _debouncedMeasure = debounce(() => this._measureCard(), 250, true); + private _measureCard() { if (!this.isConnected) { return; diff --git a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts index a3a41ba6d2..ba9da31e08 100644 --- a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts @@ -53,7 +53,7 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { this._veryNarrow = (this.clientWidth || 0) < 225; }, 250, - false + true ); public setConfig(config: EntityConfig): void { @@ -216,9 +216,7 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { private _attachObserver(): void { installResizeObserver().then(() => { - this._resizeObserver = new ResizeObserver(() => - this._debouncedResizeListener() - ); + this._resizeObserver = new ResizeObserver(this._debouncedResizeListener); this._resizeObserver.observe(this); }); From 5cc4e2bb168ae1a11d6d07eaa477aaa27c44b389 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Wed, 20 May 2020 15:39:29 -0400 Subject: [PATCH 09/77] Weather Card: Fix Forecast Image Spacing (#5952) --- src/panels/lovelace/cards/hui-weather-forecast-card.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index 69862bb4c3..06b839075d 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -435,6 +435,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { .forecast-image-icon > * { width: 40px; + height: 40px; } .forecast-icon { From e35bd30ed337c0eafb8d5a137c513bd38f97ef51 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 20 May 2020 23:08:49 +0200 Subject: [PATCH 10/77] Upgrade lazy error card (#5955) --- src/panels/lovelace/create-element/create-element-base.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/panels/lovelace/create-element/create-element-base.ts b/src/panels/lovelace/create-element/create-element-base.ts index f409f6a3b6..1e9c09cf59 100644 --- a/src/panels/lovelace/create-element/create-element-base.ts +++ b/src/panels/lovelace/create-element/create-element-base.ts @@ -52,9 +52,10 @@ export const createErrorCardElement = (config: ErrorCardConfig) => { el.setConfig(config); } else { import("../cards/hui-error-card"); - customElements - .whenDefined("hui-error-card") - .then(() => el.setConfig(config)); + customElements.whenDefined("hui-error-card").then(() => { + customElements.upgrade(el); + el.setConfig(config); + }); } return el; }; From 389b7def0bf5a5ba9dd9efc93af04ea9d9e5b079 Mon Sep 17 00:00:00 2001 From: HomeAssistant Azure Date: Thu, 21 May 2020 00:32:27 +0000 Subject: [PATCH 11/77] [ci skip] Translation update --- translations/frontend/hu.json | 6 ++++-- translations/frontend/nb.json | 12 ++++++------ translations/frontend/pl.json | 2 +- translations/frontend/zh-Hans.json | 2 ++ 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/translations/frontend/hu.json b/translations/frontend/hu.json index cea4ef4bcb..70d247887d 100644 --- a/translations/frontend/hu.json +++ b/translations/frontend/hu.json @@ -743,7 +743,7 @@ "panel": { "calendar": { "my_calendars": "Saját naptáraim", - "today": "ma" + "today": "Ma" }, "config": { "advanced_mode": { @@ -848,7 +848,7 @@ "label": "Eszköz" }, "not": { - "label": "nem" + "label": "Nem" }, "numeric_state": { "above": "Felett", @@ -1254,7 +1254,9 @@ "device_not_found": "Eszköz nem található.", "entities": { "add_entities_lovelace": "Hozzáadás a Lovelace-hez", + "disabled_entities": "+{count} {count, plural,\n one {letiltott entitás}\n other {letiltott entitás}\n}", "entities": "Entitások", + "hide_disabled": "Letiltottak elrejtése", "none": "Ennek az eszköznek nincsenek entitásai" }, "name": "Név", diff --git a/translations/frontend/nb.json b/translations/frontend/nb.json index 42cce0a713..4eb76201fb 100644 --- a/translations/frontend/nb.json +++ b/translations/frontend/nb.json @@ -1882,17 +1882,17 @@ "custom_uis": "Tilpassede brukergrensesnitt:", "developed_by": "Utviklet av en gjeng med fantastiske mennesker.", "documentation": "Dokumentasjon", - "frontend": "", + "frontend": "frontend", "frontend_version": "Brukergrensesnittet-versjon: {version} - {type}", - "home_assistant_logo": "Logo for Home Assistant", - "icons_by": "Ikoner av", + "home_assistant_logo": "", + "icons_by": "Ikoner fra", "integrations": "Integrasjoner", "issues": "Problemer", "license": "Publisert under Apache 2.0-lisensen", "path_configuration": "Sti til configurasjon.yaml: {path}", - "server": "Server", - "source": "Kilde:", - "system_health_error": "System Health-komponenten er ikke lastet. Legg til 'system_health:' til configurasjon.yaml", + "server": "core", + "source": "Kilder:", + "system_health_error": "System tilstand komponenten er ikke lastet inn. Legg til 'system_health:' i configuration.yaml", "title": "Informasjon" }, "logs": { diff --git a/translations/frontend/pl.json b/translations/frontend/pl.json index 2375de9805..b39d62dc17 100644 --- a/translations/frontend/pl.json +++ b/translations/frontend/pl.json @@ -2242,7 +2242,7 @@ "close": "Zamknij", "empty_config": "Zacznij od pustego dashboardu", "header": "Przejmij kontrolę nad interfejsem użytkownika Lovelace", - "para": "Domyślnie Home Assistant będzie zarządzać interfejsem użytkownika, aktualizując go, gdy pojawią się nowe encje lub komponenty Lovelace. Jeśli przejmiesz kontrolę, Home Assistant nie będzie już automatycznie wprowadzać dla ciebie zmian.", + "para": "Domyślnie Home Assistant będzie zarządzać interfejsem użytkownika, aktualizując go, gdy pojawią się nowe encje lub komponenty Lovelace. Jeśli przejmiesz kontrolę, Home Assistant nie będzie już automatycznie wprowadzać dla ciebie zmian. Możesz także dodać nowy dashboard w konfiguracji, aby go wypróbować.", "para_sure": "Czy na pewno chcesz przejąć kontrolę nad interfejsem użytkownika?", "save": "Przejmuję kontrolę", "yaml_config": "Aby rozpocząć, zapoznaj się z aktualną konfiguracją tego dashboardu:", diff --git a/translations/frontend/zh-Hans.json b/translations/frontend/zh-Hans.json index dce48ff3d2..5d183951c6 100644 --- a/translations/frontend/zh-Hans.json +++ b/translations/frontend/zh-Hans.json @@ -1254,7 +1254,9 @@ "device_not_found": "未找到设备。", "entities": { "add_entities_lovelace": "添加设备的所有实体到 Lovelace UI", + "disabled_entities": "+{count} {count, plural,\n one {个已禁用实体}\n other {个已禁用实体}\n}", "entities": "实体", + "hide_disabled": "隐藏已禁用的实体", "none": "这个设备没有实体" }, "name": "名称", From e4607735ff5f2c720ba8fe70de7e7897c06e4cf2 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 21 May 2020 13:00:33 +0200 Subject: [PATCH 12/77] Fix markdown card crashing the demo (#5962) --- .../lovelace/cards/hui-markdown-card.ts | 36 +++++++++---------- .../cards/hui-weather-forecast-card.ts | 1 + .../lovelace/common/compute-card-size.ts | 2 +- .../editor/card-editor/hui-card-picker.ts | 15 +++++--- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/panels/lovelace/cards/hui-markdown-card.ts b/src/panels/lovelace/cards/hui-markdown-card.ts index 97ca5aab28..54f6d3fda2 100644 --- a/src/panels/lovelace/cards/hui-markdown-card.ts +++ b/src/panels/lovelace/cards/hui-markdown-card.ts @@ -41,7 +41,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { @property() private _content = ""; - @property() private _unsubRenderTemplate?: Promise; + @property() private _unsubRenderTemplate?: UnsubscribeFunc; public getCardSize(): number { return this._config === undefined @@ -121,24 +121,25 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { return; } - this._unsubRenderTemplate = subscribeRenderTemplate( - this.hass.connection, - (result) => { - this._content = result; - }, - { - template: this._config.content, - entity_ids: this._config.entity_id, - variables: { - config: this._config, - user: this.hass.user!.name, + try { + this._unsubRenderTemplate = await subscribeRenderTemplate( + this.hass.connection, + (result) => { + this._content = result; }, - } - ); - this._unsubRenderTemplate.catch(() => { + { + template: this._config.content, + entity_ids: this._config.entity_id, + variables: { + config: this._config, + user: this.hass.user!.name, + }, + } + ); + } catch { this._content = this._config!.content; this._unsubRenderTemplate = undefined; - }); + } } private async _tryDisconnect(): Promise { @@ -147,9 +148,8 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { } try { - const unsub = await this._unsubRenderTemplate; + this._unsubRenderTemplate(); this._unsubRenderTemplate = undefined; - unsub(); } catch (e) { if (e.code === "not_found") { // If we get here, the connection was probably already closed. Ignore. diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index 06b839075d..d9d7e5ce4f 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -115,6 +115,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { oldConfig.theme !== this._config.theme ) { applyThemesOnElement(this, this.hass.themes, this._config.theme); + this.requestUpdate(); } } diff --git a/src/panels/lovelace/common/compute-card-size.ts b/src/panels/lovelace/common/compute-card-size.ts index a8f884f75c..b572b0b5e3 100644 --- a/src/panels/lovelace/common/compute-card-size.ts +++ b/src/panels/lovelace/common/compute-card-size.ts @@ -1,5 +1,5 @@ import { LovelaceCard } from "../types"; export const computeCardSize = (card: LovelaceCard): number => { - return typeof card.getCardSize === "function" ? card.getCardSize() : 1; + return typeof card.getCardSize === "function" ? card.getCardSize() : 4; }; diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index cf2870801e..9b0216d155 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -284,16 +284,23 @@ export class HuiCardPicker extends LitElement { "ll-rebuild", (ev) => { ev.stopPropagation(); - element.parentElement!.replaceChild( - this._createCardElement(cardConfig), - element - ); + this._rebuildCard(element, cardConfig); }, { once: true } ); return element; } + private _rebuildCard( + cardElToReplace: LovelaceCard, + config: LovelaceCardConfig + ): void { + const newCardEl = this._createCardElement(config); + if (cardElToReplace.parentElement) { + cardElToReplace.parentElement!.replaceChild(newCardEl, cardElToReplace); + } + } + private async _renderCardElement(card: Card): Promise { let { type } = card; const { showElement, isCustom, name, description } = card; From df3b70a53372feeda19a4da7e5421c0c2a94719d Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 21 May 2020 14:54:10 +0200 Subject: [PATCH 13/77] Fix weather card (#5966) --- .../cards/hui-weather-forecast-card.ts | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index d9d7e5ce4f..e2b49a2d4b 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -97,6 +97,14 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + + protected firstUpdated(): void { + this._attachObserver(); + } + protected updated(changedProps: PropertyValues): void { super.updated(changedProps); if (!this._config || !this.hass) { @@ -109,10 +117,10 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { | undefined; if ( - !oldHass || - !oldConfig || - oldHass.themes !== this.hass.themes || - oldConfig.theme !== this._config.theme + (changedProps.has("hass") && !oldHass) || + (changedProps.has("_config") && !oldConfig) || + (changedProps.has("hass") && oldHass!.themes !== this.hass.themes) || + (changedProps.has("_config") && oldConfig!.theme !== this._config.theme) ) { applyThemesOnElement(this, this.hass.themes, this._config.theme); this.requestUpdate(); @@ -277,22 +285,15 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { `; } - protected shouldUpdate(changedProps: PropertyValues): boolean { - return hasConfigOrEntityChanged(this, changedProps); - } - - protected firstUpdated(): void { - this._attachObserver(); - } - private _handleAction(): void { fireEvent(this, "hass-more-info", { entityId: this._config!.entity }); } private async _attachObserver(): Promise { - await installResizeObserver(); - this._resizeObserver = new ResizeObserver(this._debouncedMeasure); - + if (!this._resizeObserver) { + await installResizeObserver(); + this._resizeObserver = new ResizeObserver(this._debouncedMeasure); + } const card = this.shadowRoot!.querySelector("ha-card"); // If we show an error or warning there is no ha-card if (!card) { From 5f81a204f2f414bfec3486812fd23c12d7bdcc60 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 21 May 2020 15:10:32 +0200 Subject: [PATCH 14/77] Don't set hass when not defined (#5967) --- src/panels/lovelace/cards/hui-picture-elements-card.ts | 4 +++- src/panels/lovelace/cards/hui-stack-card.ts | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/panels/lovelace/cards/hui-picture-elements-card.ts b/src/panels/lovelace/cards/hui-picture-elements-card.ts index 9a178f22d4..29c78c9650 100644 --- a/src/panels/lovelace/cards/hui-picture-elements-card.ts +++ b/src/panels/lovelace/cards/hui-picture-elements-card.ts @@ -76,7 +76,9 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard { this._elements = this._config.elements.map( (elementConfig: LovelaceElementConfig) => { const element = createStyledHuiElement(elementConfig); - element.hass = this.hass; + if (this.hass) { + element.hass = this.hass; + } return element as LovelaceElement; } ); diff --git a/src/panels/lovelace/cards/hui-stack-card.ts b/src/panels/lovelace/cards/hui-stack-card.ts index 547aad6357..92e8e3f1e4 100644 --- a/src/panels/lovelace/cards/hui-stack-card.ts +++ b/src/panels/lovelace/cards/hui-stack-card.ts @@ -58,8 +58,12 @@ export abstract class HuiStackCard extends LitElement implements LovelaceCard { } for (const element of this._cards) { - element.hass = this.hass; - element.editMode = this.editMode; + if (this.hass) { + element.hass = this.hass; + } + if (this.editMode !== undefined) { + element.editMode = this.editMode; + } } } From e179404a9e6346a40301cf20a3a8e8d91d386268 Mon Sep 17 00:00:00 2001 From: HomeAssistant Azure Date: Fri, 22 May 2020 00:32:48 +0000 Subject: [PATCH 15/77] [ci skip] Translation update --- translations/frontend/da.json | 2 ++ translations/frontend/fr.json | 1 + translations/frontend/it.json | 9 ++++++--- translations/frontend/nl.json | 14 +++++++++++--- translations/frontend/ru.json | 2 +- 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/translations/frontend/da.json b/translations/frontend/da.json index 61ffa87ab4..3d58aea27c 100644 --- a/translations/frontend/da.json +++ b/translations/frontend/da.json @@ -1254,7 +1254,9 @@ "device_not_found": "Enhed blev ikke fundet.", "entities": { "add_entities_lovelace": "Tilføj til Lovelace", + "disabled_entities": "+{count} {count, plural,\n one {deaktiveret entitet}\n other {deaktiverede entiteter}\n}", "entities": "Entiteter", + "hide_disabled": "Skjul deaktiverede", "none": "Denne enhed har ingen entiteter" }, "name": "Navn", diff --git a/translations/frontend/fr.json b/translations/frontend/fr.json index 27fa326353..e42a02a2a9 100644 --- a/translations/frontend/fr.json +++ b/translations/frontend/fr.json @@ -1254,6 +1254,7 @@ "device_not_found": "Appareil non trouvé.", "entities": { "add_entities_lovelace": "Ajouter à Lovelace", + "disabled_entities": "+{count} {count, plural,\none {entité désactivée}\nother {entité désactivée}\n}", "entities": "Entités", "hide_disabled": "Masquer désactivé", "none": "Cet appareil n'a pas d'entités" diff --git a/translations/frontend/it.json b/translations/frontend/it.json index 8f5ee6d880..9a07b4099c 100644 --- a/translations/frontend/it.json +++ b/translations/frontend/it.json @@ -1254,7 +1254,9 @@ "device_not_found": "Dispositivo non trovato.", "entities": { "add_entities_lovelace": "Aggiungi a Lovelace", + "disabled_entities": "+{count} {count, plural,\n one {entità disabilitata}\n other {entità disabilitate}\n}", "entities": "Entità", + "hide_disabled": "Nascondi disabilitato", "none": "Questo dispositivo non ha entità" }, "name": "Nome", @@ -1374,7 +1376,8 @@ "restart_confirm": "Riavvia Home Assistant per completare la rimozione di questa integrazione", "settings_button": "Modificare le impostazioni per {integration}.", "system_options": "Opzioni di sistema", - "system_options_button": "Opzioni di sistema per {integration}" + "system_options_button": "Opzioni di sistema per {integration}", + "unnamed_entry": "Voce senza nome" }, "config_flow": { "aborted": "Interrotto", @@ -2284,8 +2287,8 @@ "views": { "confirm_delete": "Eliminare vista?", "confirm_delete_existing_cards": "L'eliminazione di questa vista rimuoverà anche le schede", - "confirm_delete_existing_cards_text": "Sei sicuro di voler eliminare la tua vista \"{name}\"? La vista contiene {number} schede che sarranno eliminate. Questa azione non può essere annullata.", - "confirm_delete_text": "Sei sicuro di voler eliminare la tua vista \"{name}\"?" + "confirm_delete_existing_cards_text": "Sei sicuro di voler eliminare la tua vista ''{name}''? La vista contiene {number} schede che sarranno eliminate. Questa azione non può essere annullata.", + "confirm_delete_text": "Sei sicuro di voler eliminare la tua vista ''{name}''?" }, "warning": { "attribute_not_found": "Attributo {attribute} non disponibile in: {entity}", diff --git a/translations/frontend/nl.json b/translations/frontend/nl.json index 048c1c4d0d..e29a1a4e59 100644 --- a/translations/frontend/nl.json +++ b/translations/frontend/nl.json @@ -1254,7 +1254,9 @@ "device_not_found": "Apparaat niet gevonden.", "entities": { "add_entities_lovelace": "Voeg toe aan de Lovelace gebruikersinterface", + "disabled_entities": "+{count} {count, plural,\n one {uitgeschakelde entiteit}\n other {uitgeschakelde entiteiten}\n}", "entities": "Entiteiten", + "hide_disabled": "Verberg uitgeschakeld", "none": "Dit apparaat heeft geen entiteiten" }, "name": "Naam", @@ -1374,7 +1376,8 @@ "restart_confirm": "Herstart Home Assistant om het verwijderen van deze integratie te voltooien", "settings_button": "Instellingen bewerken voor {integration}", "system_options": "Systeeminstellingen", - "system_options_button": "Systeeminstellingen voor {integration}" + "system_options_button": "Systeeminstellingen voor {integration}", + "unnamed_entry": "Naamloze invoer" }, "config_flow": { "aborted": "Afgebroken", @@ -1878,10 +1881,13 @@ "built_using": "Gebouwd met behulp van", "custom_uis": "Aangepaste UI's:", "developed_by": "Ontwikkeld door een stel geweldige mensen.", + "documentation": "Documentatie", "frontend": "Frontend", "frontend_version": "Frontend-versie: {version} - {type}", "home_assistant_logo": "Home Assistant-logo", "icons_by": "Icons door", + "integrations": "Integraties", + "issues": "Problemen", "license": "Gepubliceerd onder de Apache 2.0-licentie", "path_configuration": "Pad naar configuration.yaml: {path}", "server": "Server", @@ -2072,6 +2078,7 @@ "name": "Naam", "no_theme": "Geen thema", "refresh_interval": "Vernieuwingsinterval", + "secondary_info_attribute": "Secundair Info attribuut", "show_icon": "Pictogram Weergeven?", "show_name": "Naam weergeven?", "show_state": "Staat tonen?", @@ -2162,7 +2169,8 @@ }, "weather-forecast": { "description": "De Weather Forecast-kaart geeft het weer weer. Erg handig om op te nemen op interfaces die mensen aan de muur hangen.", - "name": "Weersverwachting" + "name": "Weersverwachting", + "show_forecast": "Toon Weersvoorspelling" } }, "cardpicker": { @@ -2280,7 +2288,7 @@ "confirm_delete": "Weergave verwijderen?", "confirm_delete_existing_cards": "Als u deze weergave verwijdert, worden ook de kaarten verwijderd", "confirm_delete_existing_cards_text": "Weet u zeker dat u uw weergave ''{name}'' wilt verwijderen? De weergave bevat {number} kaarten die worden verwijderd. Deze actie kan niet ongedaan gemaakt worden.", - "confirm_delete_text": "Weet u zeker dat u uw ''{naam}''-weergave wilt verwijderen?" + "confirm_delete_text": "Weet u zeker dat u uw ''{name}''-weergave wilt verwijderen?" }, "warning": { "attribute_not_found": "Kenmerk {attribute} niet beschikbaar in: {entity}", diff --git a/translations/frontend/ru.json b/translations/frontend/ru.json index 5fcf41b28c..7093a2809a 100644 --- a/translations/frontend/ru.json +++ b/translations/frontend/ru.json @@ -1067,7 +1067,7 @@ "webhooks": { "disable_hook_error_msg": "Не удалось отключить Webhook", "info": "Всему, что настроено на срабатывание через Webhook, может быть предоставлен общедоступный URL-адрес. Это позволяет отправлять данные в Home Assistant откуда угодно, не выставляя свой сервер в Интернете.", - "link_learn_more": "Узнайте больше о создании автоматизаций на базе Webhook.", + "link_learn_more": "Узнайте больше о создании автоматизации на базе Webhook.", "loading": "Загрузка ...", "manage": "Управление", "no_hooks_yet": "У Вас еще нет добавленных Webhook. Начните с настройки ", From 34e06351fbc44f1b0d6ee5b46cf029a6ea190c76 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Fri, 22 May 2020 14:44:06 +0200 Subject: [PATCH 16/77] Add translations for buttons and error string on the auth page (#5933) --- src/auth/ha-auth-flow.ts | 16 ++++++++++++++-- src/translations/en.json | 3 +++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/auth/ha-auth-flow.ts b/src/auth/ha-auth-flow.ts index 05f48449f7..88afcbedae 100644 --- a/src/auth/ha-auth-flow.ts +++ b/src/auth/ha-auth-flow.ts @@ -83,12 +83,24 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) { ${this._renderStep(this._step)}
${this._step.type === "form" ? "Next" : "Start over"}${this._step.type === "form" + ? this.localize("ui.panel.page-authorize.form.next") + : this.localize( + "ui.panel.page-authorize.form.start_over" + )}
`; case "error": - return html`
Error: ${this._errorMessage}
`; + return html` +
+ ${this.localize( + "ui.panel.page-authorize.form.error", + "error", + this._errorMessage + )} +
+ `; case "loading": return html` ${this.localize("ui.panel.page-authorize.form.working")} `; default: diff --git a/src/translations/en.json b/src/translations/en.json index b1414fcdd5..c3791de3ef 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2045,6 +2045,9 @@ "form": { "working": "Please wait", "unknown_error": "Something went wrong", + "next": "Next", + "start_over": "Start over", + "error": "Error: {error}", "providers": { "command_line": { "step": { From b8d2c551e0deeeee2881c881a4c956b181beb514 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 22 May 2020 14:44:17 +0200 Subject: [PATCH 17/77] Fix show password toggle (#5979) --- src/components/ha-form/ha-form-string.ts | 5 ++--- src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/ha-form/ha-form-string.ts b/src/components/ha-form/ha-form-string.ts index 4b7c78848f..c940e5e7c6 100644 --- a/src/components/ha-form/ha-form-string.ts +++ b/src/components/ha-form/ha-form-string.ts @@ -49,7 +49,6 @@ export class HaFormString extends LitElement implements HaFormElement { > From 6bb3b843776aeb28ac3bf4e579a3e2cdc5bee785 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 22 May 2020 15:36:30 +0200 Subject: [PATCH 18/77] Fix device entities not updating (#5983) --- .../device-detail/ha-device-entities-card.ts | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/panels/config/devices/device-detail/ha-device-entities-card.ts b/src/panels/config/devices/device-detail/ha-device-entities-card.ts index b82d7e4dd0..a586d15f5a 100644 --- a/src/panels/config/devices/device-detail/ha-device-entities-card.ts +++ b/src/panels/config/devices/device-detail/ha-device-entities-card.ts @@ -9,7 +9,6 @@ import { LitElement, property, PropertyValues, - queryAll, TemplateResult, } from "lit-element"; import { computeDomain } from "../../../../common/entity/compute_domain"; @@ -23,6 +22,7 @@ import { addEntitiesToLovelaceView } from "../../../lovelace/editor/add-entities import { LovelaceRow } from "../../../lovelace/entity-rows/types"; import { showEntityEditorDialog } from "../../entities/show-dialog-entity-editor"; import { EntityRegistryStateEntry } from "../ha-config-device-page"; +import { HuiErrorCard } from "../../../lovelace/cards/hui-error-card"; @customElement("ha-device-entities-card") export class HaDeviceEntitiesCard extends LitElement { @@ -32,20 +32,21 @@ export class HaDeviceEntitiesCard extends LitElement { @property() private _showDisabled = false; - @queryAll("#entities > *") private _entityRows?: LovelaceRow[]; + private _entityRows: Array = []; protected shouldUpdate(changedProps: PropertyValues) { - if (changedProps.has("hass")) { - this._entityRows?.forEach((element) => { + if (changedProps.has("hass") && changedProps.size === 1) { + this._entityRows.forEach((element) => { element.hass = this.hass; }); - return changedProps.size > 1; + return false; } return true; } protected render(): TemplateResult { const disabledEntities: EntityRegistryStateEntry[] = []; + this._entityRows = []; return html` ${this.entities.length ? html` -
+
${this.entities.map((entry: EntityRegistryStateEntry) => { if (entry.disabled_by) { disabledEntities.push(entry); @@ -127,8 +128,7 @@ export class HaDeviceEntitiesCard extends LitElement { } // @ts-ignore element.entry = entry; - element.addEventListener("hass-more-info", (ev) => this._openEditEntry(ev)); - + this._entityRows.push(element); return html`
${element}
`; } @@ -148,8 +148,16 @@ export class HaDeviceEntitiesCard extends LitElement { `; } - private _openEditEntry(ev: Event): void { + private _overrideMoreInfo(ev: Event): void { ev.stopPropagation(); + const entry = (ev.target! as any).entry; + showEntityEditorDialog(this, { + entry, + entity_id: entry.entity_id, + }); + } + + private _openEditEntry(ev: Event): void { const entry = (ev.currentTarget! as any).entry; showEntityEditorDialog(this, { entry, @@ -173,7 +181,7 @@ export class HaDeviceEntitiesCard extends LitElement { display: block; } ha-icon { - width: 40px; + margin-left: 8px; } .entity-id { color: var(--secondary-text-color); From 0a128db269986fc90f0c9c036911936f263171df Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 22 May 2020 15:36:43 +0200 Subject: [PATCH 19/77] Picture glance: Use icon button instead of icon with button styles. (#5977) --- .../lovelace/cards/hui-picture-glance-card.ts | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/panels/lovelace/cards/hui-picture-glance-card.ts b/src/panels/lovelace/cards/hui-picture-glance-card.ts index a1fb3bec86..e1b6c22f91 100644 --- a/src/panels/lovelace/cards/hui-picture-glance-card.ts +++ b/src/panels/lovelace/cards/hui-picture-glance-card.ts @@ -17,7 +17,7 @@ import { computeStateDisplay } from "../../../common/entity/compute_state_displa import { computeStateName } from "../../../common/entity/compute_state_name"; import { stateIcon } from "../../../common/entity/state_icon"; import "../../../components/ha-card"; -import "../../../components/ha-icon"; +import "../../../components/ha-icon-button"; import { ActionHandlerEvent } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; import { actionHandler } from "../common/directives/action-handler-directive"; @@ -240,15 +240,16 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard { return html`
- + > ${this._config!.show_state !== true && entityConf.show_state !== true ? html`
` : html` @@ -326,19 +327,15 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard { margin-left: 8px; } - ha-icon { - cursor: pointer; + ha-icon-button { + --mdc-icon-button-size: 40px; + --disabled-text-color: currentColor; color: #a9a9a9; } - ha-icon.state-on { + ha-icon-button.state-on { color: white; } - ha-icon:focus { - outline: none; - background: var(--divider-color); - border-radius: 100%; - } .state { display: block; font-size: 12px; From 10957deb1f71f1d68ee7fc3afdaacd8129c812be Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 22 May 2020 16:33:54 +0200 Subject: [PATCH 20/77] Add release drafter action (#5984) --- .github/workflows/release-drafter.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/release-drafter.yaml diff --git a/.github/workflows/release-drafter.yaml b/.github/workflows/release-drafter.yaml new file mode 100644 index 0000000000..25a0484746 --- /dev/null +++ b/.github/workflows/release-drafter.yaml @@ -0,0 +1,15 @@ +name: Release Drafter + +on: + push: + branches: + - dev + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5 + with: + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 4ad3dbf3e224148748cbef4a5d10ec700765c93a Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 22 May 2020 16:36:00 +0200 Subject: [PATCH 21/77] Update release-drafter.yaml --- .github/workflows/release-drafter.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release-drafter.yaml b/.github/workflows/release-drafter.yaml index 25a0484746..00954a2615 100644 --- a/.github/workflows/release-drafter.yaml +++ b/.github/workflows/release-drafter.yaml @@ -10,6 +10,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: release-drafter/release-drafter@v5 - with: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 364096048691c66762a2f3948c7e1b2aee60995d Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 22 May 2020 17:55:28 +0200 Subject: [PATCH 22/77] Fix for icons with firefox private mode (#5985) --- src/components/ha-icon.ts | 9 ++++++++- src/data/iconsets.ts | 13 ++++++++++--- src/panels/lovelace/cards/hui-markdown-card.ts | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/components/ha-icon.ts b/src/components/ha-icon.ts index 7f1bfc57c9..7a8eee1896 100644 --- a/src/components/ha-icon.ts +++ b/src/components/ha-icon.ts @@ -90,7 +90,14 @@ export class HaIcon extends LitElement { return; } - const databaseIcon: string = await getIcon(iconName); + let databaseIcon: string | undefined; + try { + databaseIcon = await getIcon(iconName); + } catch (_err) { + // Firefox in private mode doesn't support IDB + databaseIcon = undefined; + } + if (databaseIcon) { this._path = databaseIcon; cachedIcons[iconName] = databaseIcon; diff --git a/src/data/iconsets.ts b/src/data/iconsets.ts index 1f28e7dd80..941f84cd74 100644 --- a/src/data/iconsets.ts +++ b/src/data/iconsets.ts @@ -14,12 +14,12 @@ export const iconStore = new Store("hass-icon-db", "mdi-icon-store"); export const MDI_PREFIXES = ["mdi", "hass", "hassio", "hademo"]; -let toRead: Array<[string, (string) => void]> = []; +let toRead: Array<[string, (string) => void, () => void]> = []; // Queue up as many icon fetches in 1 transaction export const getIcon = (iconName: string) => - new Promise((resolve) => { - toRead.push([iconName, resolve]); + new Promise((resolve, reject) => { + toRead.push([iconName, resolve, reject]); if (toRead.length > 1) { return; @@ -38,6 +38,13 @@ export const getIcon = (iconName: string) => for (const [resolve_, request] of results) { resolve_(request.result); } + }) + .catch(() => { + // Firefox in private mode doesn't support IDB + for (const [, , reject_] of toRead) { + reject_(); + } + toRead = []; }); }); diff --git a/src/panels/lovelace/cards/hui-markdown-card.ts b/src/panels/lovelace/cards/hui-markdown-card.ts index 54f6d3fda2..475531c578 100644 --- a/src/panels/lovelace/cards/hui-markdown-card.ts +++ b/src/panels/lovelace/cards/hui-markdown-card.ts @@ -136,7 +136,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { }, } ); - } catch { + } catch (_err) { this._content = this._config!.content; this._unsubRenderTemplate = undefined; } From 06667455aebd983d46d3398f3e62518106dd3f4f Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 22 May 2020 18:16:45 +0200 Subject: [PATCH 23/77] Missed paper icon button (#5987) --- .../automation/condition/ha-automation-condition-row.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/config/automation/condition/ha-automation-condition-row.ts b/src/panels/config/automation/condition/ha-automation-condition-row.ts index af0850e5f6..d25bd7d0e1 100644 --- a/src/panels/config/automation/condition/ha-automation-condition-row.ts +++ b/src/panels/config/automation/condition/ha-automation-condition-row.ts @@ -68,10 +68,10 @@ export default class HaAutomationConditionRow extends LitElement { vertical-offset="-5" close-on-activate > - + > ${this._yamlMode From c5b223988aa91f124768b31c568853f8f91def32 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 22 May 2020 10:02:05 -0700 Subject: [PATCH 24/77] Split generic bundle config from webpack config (#5917) --- build-scripts/babel.js | 5 +- build-scripts/bundle.js | 160 ++++++++++++++++++++++++++++++++++++ build-scripts/webpack.js | 170 ++++++++++++--------------------------- 3 files changed, 213 insertions(+), 122 deletions(-) create mode 100644 build-scripts/bundle.js diff --git a/build-scripts/babel.js b/build-scripts/babel.js index 8e8abee81c..978d84899e 100644 --- a/build-scripts/babel.js +++ b/build-scripts/babel.js @@ -1,4 +1,4 @@ -const options = ({ latestBuild }) => ({ +module.exports.options = ({ latestBuild }) => ({ presets: [ !latestBuild && [require("@babel/preset-env").default, { modules: false }], require("@babel/preset-typescript").default, @@ -30,10 +30,11 @@ module.exports.babelLoaderConfig = ({ latestBuild }) => { } return { test: /\.m?js$|\.tsx?$/, + // Are already ES5, cause warnings when babelified. exclude: [require.resolve("@mdi/js/mdi.js"), require.resolve("hls.js")], use: { loader: "babel-loader", - options: options({ latestBuild }), + options: module.exports.options({ latestBuild }), }, }; }; diff --git a/build-scripts/bundle.js b/build-scripts/bundle.js new file mode 100644 index 0000000000..7627d8588b --- /dev/null +++ b/build-scripts/bundle.js @@ -0,0 +1,160 @@ +const path = require("path"); +const env = require("./env.js"); +const paths = require("./paths.js"); + +// Files from NPM Packages that should not be imported +module.exports.ignorePackages = [ + // Bloats bundle and it's not used. + path.resolve(require.resolve("moment"), "../locale"), + // Part of yaml.js and only used for !!js functions that we don't use + require.resolve("esprima"), +]; + +// Files from NPM packages that we should replace with empty file +module.exports.emptyPackages = [ + // Contains all color definitions for all material color sets. + // We don't use it + require.resolve("@polymer/paper-styles/color.js"), + // Loads stuff from a CDN + require.resolve("@polymer/font-roboto/roboto.js"), + require.resolve("@vaadin/vaadin-material-styles/font-roboto.js"), +]; + +module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({ + __DEV__: !isProdBuild, + __BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"), + __VERSION__: JSON.stringify(env.version()), + __DEMO__: false, + __BACKWARDS_COMPAT__: false, + __STATIC_PATH__: "/static/", + "process.env.NODE_ENV": JSON.stringify( + isProdBuild ? "production" : "development" + ), + ...defineOverlay, +}); + +module.exports.terserOptions = (latestBuild) => ({ + safari10: true, + ecma: latestBuild ? undefined : 5, +}); + +const outputPath = (outputRoot, latestBuild) => + path.resolve(outputRoot, latestBuild ? "frontend_latest" : "frontend_es5"); + +const publicPath = (latestBuild) => + latestBuild ? "/frontend_latest/" : "/frontend_es5/"; + +/* +BundleConfig { + // Object with entrypoints that need to be bundled + entry: { [name: string]: pathToFile }, + // Folder where bundled files need to be written + outputPath: string, + // absolute url-path where bundled files can be found + publicPath: string, + // extra definitions that we need to replace in source + defineOverlay: {[name: string]: value }, + // if this is a production build + isProdBuild: boolean, + // If we're targeting latest browsers + latestBuild: boolean, + // If we're doing a stats build (create nice chunk names) + isStatsBuild: boolean, + // Names of entrypoints that should not be hashed + dontHash: Set +} +*/ + +module.exports.config = { + app({ isProdBuild, latestBuild, isStatsBuild }) { + return { + entry: { + service_worker: "./src/entrypoints/service_worker.ts", + app: "./src/entrypoints/app.ts", + authorize: "./src/entrypoints/authorize.ts", + onboarding: "./src/entrypoints/onboarding.ts", + core: "./src/entrypoints/core.ts", + compatibility: "./src/entrypoints/compatibility.ts", + "custom-panel": "./src/entrypoints/custom-panel.ts", + }, + outputPath: outputPath(paths.root, latestBuild), + publicPath: publicPath(latestBuild), + isProdBuild, + latestBuild, + isStatsBuild, + }; + }, + + demo({ isProdBuild, latestBuild, isStatsBuild }) { + return { + entry: { + main: path.resolve(paths.demo_dir, "src/entrypoint.ts"), + compatibility: path.resolve( + paths.polymer_dir, + "src/entrypoints/compatibility.ts" + ), + }, + outputPath: outputPath(paths.demo_root, latestBuild), + publicPath: publicPath(latestBuild), + defineOverlay: { + __VERSION__: JSON.stringify(`DEMO-${env.version()}`), + __DEMO__: true, + }, + isProdBuild, + latestBuild, + isStatsBuild, + }; + }, + + cast({ isProdBuild, latestBuild }) { + const entry = { + launcher: path.resolve(paths.cast_dir, "src/launcher/entrypoint.ts"), + }; + + if (latestBuild) { + entry.receiver = path.resolve( + paths.cast_dir, + "src/receiver/entrypoint.ts" + ); + } + + return { + entry, + outputPath: outputPath(paths.cast_root, latestBuild), + publicPath: publicPath(latestBuild), + isProdBuild, + latestBuild, + defineOverlay: { + __BACKWARDS_COMPAT__: true, + }, + }; + }, + + hassio({ isProdBuild, latestBuild }) { + if (latestBuild) { + throw new Error("Hass.io does not support latest build!"); + } + return { + entry: { + entrypoint: path.resolve(paths.hassio_dir, "src/entrypoint.ts"), + }, + outputPath: paths.hassio_root, + publicPath: paths.hassio_publicPath, + isProdBuild, + latestBuild, + dontHash: new Set(["entrypoint"]), + }; + }, + + gallery({ isProdBuild, latestBuild }) { + return { + entry: { + entrypoint: path.resolve(paths.gallery_dir, "src/entrypoint.js"), + }, + outputPath: outputPath(paths.gallery_root, latestBuild), + publicPath: publicPath(latestBuild), + isProdBuild, + latestBuild, + }; + }, +}; diff --git a/build-scripts/webpack.js b/build-scripts/webpack.js index f5b397888f..7b88936d8a 100644 --- a/build-scripts/webpack.js +++ b/build-scripts/webpack.js @@ -4,12 +4,13 @@ const TerserPlugin = require("terser-webpack-plugin"); const ManifestPlugin = require("webpack-manifest-plugin"); const WorkerPlugin = require("worker-plugin"); const paths = require("./paths.js"); -const env = require("./env.js"); const { babelLoaderConfig } = require("./babel.js"); +const bundle = require("./bundle"); const createWebpackConfig = ({ entry, - outputRoot, + outputPath, + publicPath, defineOverlay, isProdBuild, latestBuild, @@ -25,6 +26,7 @@ const createWebpackConfig = ({ ? "cheap-module-source-map" : "eval-cheap-module-source-map", entry, + node: false, module: { rules: [ babelLoaderConfig({ latestBuild }), @@ -34,9 +36,6 @@ const createWebpackConfig = ({ }, ], }, - externals: { - esprima: "esprima", - }, optimization: { minimizer: [ new TerserPlugin({ @@ -44,10 +43,7 @@ const createWebpackConfig = ({ parallel: true, extractComments: true, sourceMap: true, - terserOptions: { - safari10: true, - ecma: latestBuild ? undefined : 5, - }, + terserOptions: bundle.terserOptions(latestBuild), }), ], }, @@ -57,40 +53,40 @@ const createWebpackConfig = ({ // Only include the JS of entrypoints filter: (file) => file.isInitial && !file.name.endsWith(".map"), }), - new webpack.DefinePlugin({ - __DEV__: !isProdBuild, - __BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"), - __VERSION__: JSON.stringify(env.version()), - __DEMO__: false, - __BACKWARDS_COMPAT__: false, - __STATIC_PATH__: "/static/", - "process.env.NODE_ENV": JSON.stringify( - isProdBuild ? "production" : "development" - ), - ...defineOverlay, + new webpack.DefinePlugin( + bundle.definedVars({ isProdBuild, latestBuild, defineOverlay }) + ), + new webpack.IgnorePlugin({ + checkResource(resource, context) { + // Only use ignore to intercept imports that we don't control + // inside node_module dependencies. + if ( + !context.includes("/node_modules/") || + // calling define.amd will call require("!!webpack amd options") + resource.startsWith("!!webpack") + ) { + return false; + } + let fullPath; + try { + fullPath = resource.startsWith(".") + ? path.resolve(context, resource) + : require.resolve(resource); + } catch (err) { + console.error("Error in ignore plugin", resource, context); + throw err; + } + + return bundle.ignorePackages.some((toIgnorePath) => + fullPath.startsWith(toIgnorePath) + ); + }, }), - // Ignore moment.js locales - new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), - // Color.js is bloated, it contains all color definitions for all material color sets. new webpack.NormalModuleReplacementPlugin( - /@polymer\/paper-styles\/color\.js$/, + new RegExp(bundle.emptyPackages.join("|")), path.resolve(paths.polymer_dir, "src/util/empty.js") ), - // Ignore roboto pointing at CDN. We use local font-roboto-local. - new webpack.NormalModuleReplacementPlugin( - /@polymer\/font-roboto\/roboto\.js$/, - path.resolve(paths.polymer_dir, "src/util/empty.js") - ), - new webpack.NormalModuleReplacementPlugin( - /@vaadin\/vaadin-material-styles\/font-roboto\.js$/, - path.resolve(paths.polymer_dir, "src/util/empty.js") - ), - // Ignore mwc icons pointing at CDN. - new webpack.NormalModuleReplacementPlugin( - /@material\/mwc-icon\/mwc-icon-font\.js$/, - path.resolve(paths.polymer_dir, "src/util/empty.js") - ), - ].filter(Boolean), + ], resolve: { extensions: [".ts", ".js", ".json"], }, @@ -105,11 +101,8 @@ const createWebpackConfig = ({ isProdBuild && !isStatsBuild ? "chunk.[chunkhash].js" : "[name].chunk.js", - path: path.resolve( - outputRoot, - latestBuild ? "frontend_latest" : "frontend_es5" - ), - publicPath: latestBuild ? "/frontend_latest/" : "/frontend_es5/", + path: outputPath, + publicPath, // To silence warning in worker plugin globalObject: "self", }, @@ -117,94 +110,31 @@ const createWebpackConfig = ({ }; const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => { - return createWebpackConfig({ - entry: { - service_worker: "./src/entrypoints/service_worker.ts", - app: "./src/entrypoints/app.ts", - authorize: "./src/entrypoints/authorize.ts", - onboarding: "./src/entrypoints/onboarding.ts", - core: "./src/entrypoints/core.ts", - compatibility: "./src/entrypoints/compatibility.ts", - "custom-panel": "./src/entrypoints/custom-panel.ts", - }, - outputRoot: paths.root, - isProdBuild, - latestBuild, - isStatsBuild, - }); + return createWebpackConfig( + bundle.config.app({ isProdBuild, latestBuild, isStatsBuild }) + ); }; const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => { - return createWebpackConfig({ - entry: { - main: path.resolve(paths.demo_dir, "src/entrypoint.ts"), - compatibility: path.resolve( - paths.polymer_dir, - "src/entrypoints/compatibility.ts" - ), - }, - outputRoot: paths.demo_root, - defineOverlay: { - __VERSION__: JSON.stringify(`DEMO-${env.version()}`), - __DEMO__: true, - }, - isProdBuild, - latestBuild, - isStatsBuild, - }); + return createWebpackConfig( + bundle.config.demo({ isProdBuild, latestBuild, isStatsBuild }) + ); }; const createCastConfig = ({ isProdBuild, latestBuild }) => { - const entry = { - launcher: path.resolve(paths.cast_dir, "src/launcher/entrypoint.ts"), - }; - - if (latestBuild) { - entry.receiver = path.resolve(paths.cast_dir, "src/receiver/entrypoint.ts"); - } - - return createWebpackConfig({ - entry, - outputRoot: paths.cast_root, - isProdBuild, - latestBuild, - defineOverlay: { - __BACKWARDS_COMPAT__: true, - }, - }); + return createWebpackConfig(bundle.config.cast({ isProdBuild, latestBuild })); }; const createHassioConfig = ({ isProdBuild, latestBuild }) => { - if (latestBuild) { - throw new Error("Hass.io does not support latest build!"); - } - const config = createWebpackConfig({ - entry: { - entrypoint: path.resolve(paths.hassio_dir, "src/entrypoint.ts"), - }, - outputRoot: "", - isProdBuild, - latestBuild, - dontHash: new Set(["entrypoint"]), - }); - - config.output.path = paths.hassio_root; - config.output.publicPath = paths.hassio_publicPath; - - return config; + return createWebpackConfig( + bundle.config.hassio({ isProdBuild, latestBuild }) + ); }; const createGalleryConfig = ({ isProdBuild, latestBuild }) => { - const config = createWebpackConfig({ - entry: { - entrypoint: path.resolve(paths.gallery_dir, "src/entrypoint.js"), - }, - outputRoot: paths.gallery_root, - isProdBuild, - latestBuild, - }); - - return config; + return createWebpackConfig( + bundle.config.gallery({ isProdBuild, latestBuild }) + ); }; module.exports = { From 7daafcbe1bfe1742d4af41265ca0ca5913cffbc0 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 22 May 2020 22:24:37 +0200 Subject: [PATCH 25/77] Fix aria label icon name (#5992) --- src/components/ha-icon-button.ts | 2 +- src/panels/lovelace/hui-root.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ha-icon-button.ts b/src/components/ha-icon-button.ts index ba8e55a143..311e4fb368 100644 --- a/src/components/ha-icon-button.ts +++ b/src/components/ha-icon-button.ts @@ -25,7 +25,7 @@ export class HaIconButton extends LitElement { protected render(): TemplateResult { return html` diff --git a/src/panels/lovelace/hui-root.ts b/src/panels/lovelace/hui-root.ts index e25f870708..289100b08c 100644 --- a/src/panels/lovelace/hui-root.ts +++ b/src/panels/lovelace/hui-root.ts @@ -183,7 +183,7 @@ class HUIRoot extends LitElement { ${this._conversation(this.hass.config.components) ? html` From 7e281f66c2a78f115ebaf37cc0a9a9a3985aa00e Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 22 May 2020 23:05:47 -0700 Subject: [PATCH 26/77] Rollup (#5995) --- build-scripts/babel.js | 19 +- build-scripts/bundle.js | 1 + build-scripts/env.js | 7 +- build-scripts/gulp/app.js | 13 +- build-scripts/gulp/cast.js | 7 +- build-scripts/gulp/demo.js | 7 +- build-scripts/gulp/entry-html.js | 63 +-- build-scripts/gulp/gallery.js | 7 +- build-scripts/gulp/gather-static.js | 25 +- build-scripts/gulp/hassio.js | 9 +- build-scripts/gulp/rollup.js | 149 +++++++ build-scripts/gulp/webpack.js | 8 +- .../rollup-plugins/dont-hash-plugin.js | 14 + .../rollup-plugins/manifest-plugin.js | 34 ++ build-scripts/rollup-plugins/worker-plugin.js | 148 +++++++ build-scripts/rollup.js | 141 +++++++ build-scripts/webpack.js | 11 +- cast/rollup.config.js | 10 + cast/src/html/launcher-faq.html.template | 8 +- cast/src/html/launcher.html.template | 8 +- demo/rollup.config.js | 10 + demo/src/html/index.html.template | 12 +- gallery/rollup.config.js | 10 + hassio/rollup.config.js | 10 + package.json | 13 + rollup.config.js | 10 + src/components/data-table/sort-filter.ts | 6 +- .../data-table/sort_filter_worker.ts | 5 +- src/html/_js_base.html.template | 1 + src/html/authorize.html.template | 12 +- src/html/index.html.template | 21 +- src/html/onboarding.html.template | 12 +- src/resources/markdown_worker.ts | 5 +- src/resources/render-markdown.ts | 4 +- yarn.lock | 380 ++++++++++++++++-- 35 files changed, 1080 insertions(+), 120 deletions(-) create mode 100644 build-scripts/gulp/rollup.js create mode 100644 build-scripts/rollup-plugins/dont-hash-plugin.js create mode 100644 build-scripts/rollup-plugins/manifest-plugin.js create mode 100644 build-scripts/rollup-plugins/worker-plugin.js create mode 100644 build-scripts/rollup.js create mode 100644 cast/rollup.config.js create mode 100644 demo/rollup.config.js create mode 100644 gallery/rollup.config.js create mode 100644 hassio/rollup.config.js create mode 100644 rollup.config.js diff --git a/build-scripts/babel.js b/build-scripts/babel.js index 978d84899e..c02b53e413 100644 --- a/build-scripts/babel.js +++ b/build-scripts/babel.js @@ -24,17 +24,8 @@ module.exports.options = ({ latestBuild }) => ({ ], }); -module.exports.babelLoaderConfig = ({ latestBuild }) => { - if (latestBuild === undefined) { - throw Error("latestBuild not defined for babel loader config"); - } - return { - test: /\.m?js$|\.tsx?$/, - // Are already ES5, cause warnings when babelified. - exclude: [require.resolve("@mdi/js/mdi.js"), require.resolve("hls.js")], - use: { - loader: "babel-loader", - options: module.exports.options({ latestBuild }), - }, - }; -}; +// Are already ES5, cause warnings when babelified. +module.exports.exclude = [ + require.resolve("@mdi/js/mdi.js"), + require.resolve("hls.js"), +]; diff --git a/build-scripts/bundle.js b/build-scripts/bundle.js index 7627d8588b..51f3bc345d 100644 --- a/build-scripts/bundle.js +++ b/build-scripts/bundle.js @@ -36,6 +36,7 @@ module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({ module.exports.terserOptions = (latestBuild) => ({ safari10: true, ecma: latestBuild ? undefined : 5, + output: { comments: false }, }); const outputPath = (outputRoot, latestBuild) => diff --git a/build-scripts/env.js b/build-scripts/env.js index 72a9e794d2..8980d3bf92 100644 --- a/build-scripts/env.js +++ b/build-scripts/env.js @@ -3,8 +3,13 @@ const path = require("path"); const paths = require("./paths.js"); module.exports = { + useRollup() { + return process.env.ROLLUP === "1"; + }, isProdBuild() { - return process.env.NODE_ENV === "production"; + return ( + process.env.NODE_ENV === "production" || module.exports.isStatsBuild() + ); }, isStatsBuild() { return process.env.STATS === "1"; diff --git a/build-scripts/gulp/app.js b/build-scripts/gulp/app.js index 1bd5c4750b..9429260617 100644 --- a/build-scripts/gulp/app.js +++ b/build-scripts/gulp/app.js @@ -1,7 +1,7 @@ // Run HA develop mode const gulp = require("gulp"); -const envVars = require("../env"); +const env = require("../env"); require("./clean.js"); require("./translations.js"); @@ -11,6 +11,7 @@ require("./compress.js"); require("./webpack.js"); require("./service-worker.js"); require("./entry-html.js"); +require("./rollup.js"); gulp.task( "develop-app", @@ -26,8 +27,8 @@ gulp.task( "gen-index-app-dev", "build-translations" ), - "copy-static", - "webpack-watch-app" + "copy-static-app", + env.useRollup() ? "rollup-watch-app" : "webpack-watch-app" ) ); @@ -39,10 +40,10 @@ gulp.task( }, "clean", gulp.parallel("gen-icons-json", "build-translations"), - "copy-static", - "webpack-prod-app", + "copy-static-app", + env.useRollup() ? "rollup-prod-app" : "webpack-prod-app", ...// Don't compress running tests - (envVars.isTest() ? [] : ["compress-app"]), + (env.isTest() ? [] : ["compress-app"]), gulp.parallel( "gen-pages-prod", "gen-index-app-prod", diff --git a/build-scripts/gulp/cast.js b/build-scripts/gulp/cast.js index ad393f74b4..4d9a7fe34f 100644 --- a/build-scripts/gulp/cast.js +++ b/build-scripts/gulp/cast.js @@ -1,11 +1,14 @@ const gulp = require("gulp"); +const env = require("../env"); + require("./clean.js"); require("./translations.js"); require("./gather-static.js"); require("./webpack.js"); require("./service-worker.js"); require("./entry-html.js"); +require("./rollup.js"); gulp.task( "develop-cast", @@ -17,7 +20,7 @@ gulp.task( "translations-enable-merge-backend", gulp.parallel("gen-icons-json", "build-translations"), "copy-static-cast", - "webpack-dev-server-cast" + env.useRollup() ? "rollup-dev-server-cast" : "webpack-dev-server-cast" ) ); @@ -31,7 +34,7 @@ gulp.task( "translations-enable-merge-backend", gulp.parallel("gen-icons-json", "build-translations"), "copy-static-cast", - "webpack-prod-cast", + env.useRollup() ? "rollup-prod-cast" : "webpack-prod-cast", "gen-index-cast-prod" ) ); diff --git a/build-scripts/gulp/demo.js b/build-scripts/gulp/demo.js index eef9ebbecf..466ade84b2 100644 --- a/build-scripts/gulp/demo.js +++ b/build-scripts/gulp/demo.js @@ -1,6 +1,8 @@ // Run demo develop mode const gulp = require("gulp"); +const env = require("../env"); + require("./clean.js"); require("./translations.js"); require("./gen-icons-json.js"); @@ -8,6 +10,7 @@ require("./gather-static.js"); require("./webpack.js"); require("./service-worker.js"); require("./entry-html.js"); +require("./rollup.js"); gulp.task( "develop-demo", @@ -19,7 +22,7 @@ gulp.task( "translations-enable-merge-backend", gulp.parallel("gen-icons-json", "gen-index-demo-dev", "build-translations"), "copy-static-demo", - "webpack-dev-server-demo" + env.useRollup() ? "rollup-dev-server-demo" : "webpack-dev-server-demo" ) ); @@ -34,7 +37,7 @@ gulp.task( "translations-enable-merge-backend", gulp.parallel("gen-icons-json", "build-translations"), "copy-static-demo", - "webpack-prod-demo", + env.useRollup() ? "rollup-prod-demo" : "webpack-prod-demo", "gen-index-demo-prod" ) ); diff --git a/build-scripts/gulp/entry-html.js b/build-scripts/gulp/entry-html.js index 71fd5dd0e8..094a41cc47 100644 --- a/build-scripts/gulp/entry-html.js +++ b/build-scripts/gulp/entry-html.js @@ -6,31 +6,36 @@ const fs = require("fs-extra"); const path = require("path"); const template = require("lodash.template"); const minify = require("html-minifier").minify; -const config = require("../paths.js"); +const paths = require("../paths.js"); +const env = require("../env.js"); const templatePath = (tpl) => - path.resolve(config.polymer_dir, "src/html/", `${tpl}.html.template`); + 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, renderTemplate }); + return compiled({ + ...data, + useRollup: env.useRollup(), + renderTemplate, + }); }; const renderDemoTemplate = (pth, data = {}) => renderTemplate(pth, data, (tpl) => - path.resolve(config.demo_dir, "src/html/", `${tpl}.html.template`) + path.resolve(paths.demo_dir, "src/html/", `${tpl}.html.template`) ); const renderCastTemplate = (pth, data = {}) => renderTemplate(pth, data, (tpl) => - path.resolve(config.cast_dir, "src/html/", `${tpl}.html.template`) + path.resolve(paths.cast_dir, "src/html/", `${tpl}.html.template`) ); const renderGalleryTemplate = (pth, data = {}) => renderTemplate(pth, data, (tpl) => - path.resolve(config.gallery_dir, "src/html/", `${tpl}.html.template`) + path.resolve(paths.gallery_dir, "src/html/", `${tpl}.html.template`) ); const minifyHtml = (content) => @@ -52,14 +57,14 @@ gulp.task("gen-pages-dev", (done) => { es5PageJS: `/frontend_es5/${page}.js`, }); - fs.outputFileSync(path.resolve(config.root, `${page}.html`), content); + fs.outputFileSync(path.resolve(paths.root, `${page}.html`), content); } done(); }); gulp.task("gen-pages-prod", (done) => { - const latestManifest = require(path.resolve(config.output, "manifest.json")); - const es5Manifest = require(path.resolve(config.output_es5, "manifest.json")); + const latestManifest = require(path.resolve(paths.output, "manifest.json")); + const es5Manifest = require(path.resolve(paths.output_es5, "manifest.json")); for (const page of PAGES) { const content = renderTemplate(page, { @@ -70,7 +75,7 @@ gulp.task("gen-pages-prod", (done) => { }); fs.outputFileSync( - path.resolve(config.root, `${page}.html`), + path.resolve(paths.root, `${page}.html`), minifyHtml(content) ); } @@ -91,13 +96,13 @@ gulp.task("gen-index-app-dev", (done) => { es5CustomPanelJS: "/frontend_es5/custom-panel.js", }).replace(/#THEMEC/g, "{{ theme_color }}"); - fs.outputFileSync(path.resolve(config.root, "index.html"), content); + fs.outputFileSync(path.resolve(paths.root, "index.html"), content); done(); }); gulp.task("gen-index-app-prod", (done) => { - const latestManifest = require(path.resolve(config.output, "manifest.json")); - const es5Manifest = require(path.resolve(config.output_es5, "manifest.json")); + const latestManifest = require(path.resolve(paths.output, "manifest.json")); + const es5Manifest = require(path.resolve(paths.output_es5, "manifest.json")); const content = renderTemplate("index", { latestAppJS: latestManifest["app.js"], latestCoreJS: latestManifest["core.js"], @@ -110,7 +115,7 @@ gulp.task("gen-index-app-prod", (done) => { }); const minified = minifyHtml(content).replace(/#THEMEC/g, "{{ theme_color }}"); - fs.outputFileSync(path.resolve(config.root, "index.html"), minified); + fs.outputFileSync(path.resolve(paths.root, "index.html"), minified); done(); }); @@ -119,7 +124,7 @@ gulp.task("gen-index-cast-dev", (done) => { latestReceiverJS: "/frontend_latest/receiver.js", }); fs.outputFileSync( - path.resolve(config.cast_root, "receiver.html"), + path.resolve(paths.cast_root, "receiver.html"), contentReceiver ); @@ -127,14 +132,14 @@ gulp.task("gen-index-cast-dev", (done) => { latestLauncherJS: "/frontend_latest/launcher.js", es5LauncherJS: "/frontend_es5/launcher.js", }); - fs.outputFileSync(path.resolve(config.cast_root, "faq.html"), contentFAQ); + fs.outputFileSync(path.resolve(paths.cast_root, "faq.html"), contentFAQ); const contentLauncher = renderCastTemplate("launcher", { latestLauncherJS: "/frontend_latest/launcher.js", es5LauncherJS: "/frontend_es5/launcher.js", }); fs.outputFileSync( - path.resolve(config.cast_root, "index.html"), + path.resolve(paths.cast_root, "index.html"), contentLauncher ); done(); @@ -142,11 +147,11 @@ gulp.task("gen-index-cast-dev", (done) => { gulp.task("gen-index-cast-prod", (done) => { const latestManifest = require(path.resolve( - config.cast_output, + paths.cast_output, "manifest.json" )); const es5Manifest = require(path.resolve( - config.cast_output_es5, + paths.cast_output_es5, "manifest.json" )); @@ -154,7 +159,7 @@ gulp.task("gen-index-cast-prod", (done) => { latestReceiverJS: latestManifest["receiver.js"], }); fs.outputFileSync( - path.resolve(config.cast_root, "receiver.html"), + path.resolve(paths.cast_root, "receiver.html"), contentReceiver ); @@ -162,14 +167,14 @@ gulp.task("gen-index-cast-prod", (done) => { latestLauncherJS: latestManifest["launcher.js"], es5LauncherJS: es5Manifest["launcher.js"], }); - fs.outputFileSync(path.resolve(config.cast_root, "faq.html"), contentFAQ); + fs.outputFileSync(path.resolve(paths.cast_root, "faq.html"), contentFAQ); const contentLauncher = renderCastTemplate("launcher", { latestLauncherJS: latestManifest["launcher.js"], es5LauncherJS: es5Manifest["launcher.js"], }); fs.outputFileSync( - path.resolve(config.cast_root, "index.html"), + path.resolve(paths.cast_root, "index.html"), contentLauncher ); done(); @@ -185,17 +190,17 @@ gulp.task("gen-index-demo-dev", (done) => { es5DemoJS: "/frontend_es5/main.js", }); - fs.outputFileSync(path.resolve(config.demo_root, "index.html"), content); + fs.outputFileSync(path.resolve(paths.demo_root, "index.html"), content); done(); }); gulp.task("gen-index-demo-prod", (done) => { const latestManifest = require(path.resolve( - config.demo_output, + paths.demo_output, "manifest.json" )); const es5Manifest = require(path.resolve( - config.demo_output_es5, + paths.demo_output_es5, "manifest.json" )); const content = renderDemoTemplate("index", { @@ -206,7 +211,7 @@ gulp.task("gen-index-demo-prod", (done) => { }); const minified = minifyHtml(content); - fs.outputFileSync(path.resolve(config.demo_root, "index.html"), minified); + fs.outputFileSync(path.resolve(paths.demo_root, "index.html"), minified); done(); }); @@ -217,13 +222,13 @@ gulp.task("gen-index-gallery-dev", (done) => { latestGalleryJS: "./frontend_latest/entrypoint.js", }); - fs.outputFileSync(path.resolve(config.gallery_root, "index.html"), content); + fs.outputFileSync(path.resolve(paths.gallery_root, "index.html"), content); done(); }); gulp.task("gen-index-gallery-prod", (done) => { const latestManifest = require(path.resolve( - config.gallery_output, + paths.gallery_output, "manifest.json" )); const content = renderGalleryTemplate("index", { @@ -231,6 +236,6 @@ gulp.task("gen-index-gallery-prod", (done) => { }); const minified = minifyHtml(content); - fs.outputFileSync(path.resolve(config.gallery_root, "index.html"), minified); + fs.outputFileSync(path.resolve(paths.gallery_root, "index.html"), minified); done(); }); diff --git a/build-scripts/gulp/gallery.js b/build-scripts/gulp/gallery.js index 559b0debde..ec430118e5 100644 --- a/build-scripts/gulp/gallery.js +++ b/build-scripts/gulp/gallery.js @@ -1,6 +1,8 @@ // Run demo develop mode const gulp = require("gulp"); +const env = require("../env"); + require("./clean.js"); require("./translations.js"); require("./gen-icons-json.js"); @@ -8,6 +10,7 @@ require("./gather-static.js"); require("./webpack.js"); require("./service-worker.js"); require("./entry-html.js"); +require("./rollup.js"); gulp.task( "develop-gallery", @@ -20,7 +23,7 @@ gulp.task( gulp.parallel("gen-icons-json", "build-translations"), "copy-static-gallery", "gen-index-gallery-dev", - "webpack-dev-server-gallery" + env.useRollup() ? "rollup-dev-server-gallery" : "webpack-dev-server-gallery" ) ); @@ -34,7 +37,7 @@ gulp.task( "translations-enable-merge-backend", gulp.parallel("gen-icons-json", "build-translations"), "copy-static-gallery", - "webpack-prod-gallery", + env.useRollup() ? "rollup-prod-gallery" : "webpack-prod-gallery", "gen-index-gallery-prod" ) ); diff --git a/build-scripts/gulp/gather-static.js b/build-scripts/gulp/gather-static.js index 7dc4e19443..55ad3ec1ca 100644 --- a/build-scripts/gulp/gather-static.js +++ b/build-scripts/gulp/gather-static.js @@ -51,6 +51,12 @@ function copyPolyfills(staticDir) { ); } +function copyLoaderJS(staticDir) { + const staticPath = genStaticPath(staticDir); + copyFileDir(npmPath("systemjs/dist/s.min.js"), staticPath("js")); + copyFileDir(npmPath("systemjs/dist/s.min.js.map"), staticPath("js")); +} + function copyFonts(staticDir) { const staticPath = genStaticPath(staticDir); // Local fonts @@ -72,17 +78,17 @@ function copyMapPanel(staticDir) { ); } -gulp.task("copy-translations", (done) => { +gulp.task("copy-translations-app", async () => { const staticDir = paths.static; copyTranslations(staticDir); - done(); }); -gulp.task("copy-static", (done) => { +gulp.task("copy-static-app", async () => { const staticDir = paths.static; // Basic static files fs.copySync(polyPath("public"), paths.root); + copyLoaderJS(staticDir); copyPolyfills(staticDir); copyFonts(staticDir); copyTranslations(staticDir); @@ -90,10 +96,9 @@ gulp.task("copy-static", (done) => { // Panel assets copyMapPanel(staticDir); - done(); }); -gulp.task("copy-static-demo", (done) => { +gulp.task("copy-static-demo", async () => { // Copy app static files fs.copySync( polyPath("public/static"), @@ -102,28 +107,29 @@ gulp.task("copy-static-demo", (done) => { // Copy demo static files fs.copySync(path.resolve(paths.demo_dir, "public"), paths.demo_root); + copyLoaderJS(paths.demo_static); copyPolyfills(paths.demo_static); copyMapPanel(paths.demo_static); copyFonts(paths.demo_static); copyTranslations(paths.demo_static); copyMdiIcons(paths.demo_static); - done(); }); -gulp.task("copy-static-cast", (done) => { +gulp.task("copy-static-cast", async () => { // Copy app static files fs.copySync(polyPath("public/static"), paths.cast_static); // Copy cast static files fs.copySync(path.resolve(paths.cast_dir, "public"), paths.cast_root); + copyLoaderJS(paths.cast_static); + copyPolyfills(paths.cast_static); copyMapPanel(paths.cast_static); copyFonts(paths.cast_static); copyTranslations(paths.cast_static); copyMdiIcons(paths.cast_static); - done(); }); -gulp.task("copy-static-gallery", (done) => { +gulp.task("copy-static-gallery", async () => { // Copy app static files fs.copySync(polyPath("public/static"), paths.gallery_static); // Copy gallery static files @@ -133,5 +139,4 @@ gulp.task("copy-static-gallery", (done) => { copyFonts(paths.gallery_static); copyTranslations(paths.gallery_static); copyMdiIcons(paths.gallery_static); - done(); }); diff --git a/build-scripts/gulp/hassio.js b/build-scripts/gulp/hassio.js index 9591d60278..595752008c 100644 --- a/build-scripts/gulp/hassio.js +++ b/build-scripts/gulp/hassio.js @@ -1,11 +1,12 @@ const gulp = require("gulp"); -const envVars = require("../env"); +const env = require("../env"); require("./clean.js"); require("./gen-icons-json.js"); require("./webpack.js"); require("./compress.js"); +require("./rollup.js"); gulp.task( "develop-hassio", @@ -15,7 +16,7 @@ gulp.task( }, "clean-hassio", "gen-icons-json", - "webpack-watch-hassio" + env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio" ) ); @@ -27,8 +28,8 @@ gulp.task( }, "clean-hassio", "gen-icons-json", - "webpack-prod-hassio", + env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio", ...// Don't compress running tests - (envVars.isTest() ? [] : ["compress-hassio"]) + (env.isTest() ? [] : ["compress-hassio"]) ) ); diff --git a/build-scripts/gulp/rollup.js b/build-scripts/gulp/rollup.js new file mode 100644 index 0000000000..606432c634 --- /dev/null +++ b/build-scripts/gulp/rollup.js @@ -0,0 +1,149 @@ +// Tasks to run Rollup +const path = require("path"); +const gulp = require("gulp"); +const rollup = require("rollup"); +const handler = require("serve-handler"); +const http = require("http"); +const log = require("fancy-log"); +const rollupConfig = require("../rollup"); +const paths = require("../paths"); +const open = require("open"); + +const bothBuilds = (createConfigFunc, params) => + gulp.series( + async function buildLatest() { + await buildRollup( + createConfigFunc({ + ...params, + latestBuild: true, + }) + ); + }, + async function buildES5() { + await buildRollup( + createConfigFunc({ + ...params, + latestBuild: false, + }) + ); + } + ); + +function createServer(serveOptions) { + const server = http.createServer((request, response) => { + return handler(request, response, { + public: serveOptions.root, + }); + }); + + server.listen( + serveOptions.port, + serveOptions.networkAccess ? "0.0.0.0" : undefined, + () => { + log.info(`Available at http://localhost:${serveOptions.port}`); + open(`http://localhost:${serveOptions.port}`); + } + ); +} + +function watchRollup(createConfig, extraWatchSrc = [], serveOptions) { + const { inputOptions, outputOptions } = createConfig({ + isProdBuild: false, + latestBuild: true, + }); + + const watcher = rollup.watch({ + ...inputOptions, + output: [outputOptions], + watch: { + include: ["src"] + extraWatchSrc, + }, + }); + + let startedHttp = false; + + watcher.on("event", (event) => { + if (event.code === "ERROR") { + log.error(event.error); + } else if (event.code === "END") { + if (startedHttp || !serveOptions) { + return; + } + startedHttp = true; + createServer(serveOptions); + } + }); + + gulp.watch( + path.join(paths.translations_src, "en.json"), + gulp.series("build-translations", "copy-translations-app") + ); +} + +async function buildRollup(config) { + const bundle = await rollup.rollup(config.inputOptions); + await bundle.write(config.outputOptions); +} + +gulp.task("rollup-watch-app", () => { + watchRollup(rollupConfig.createAppConfig); +}); + +gulp.task("rollup-watch-hassio", () => { + watchRollup(rollupConfig.createHassioConfig, ["hassio/src"]); +}); + +gulp.task("rollup-dev-server-demo", () => { + watchRollup(rollupConfig.createDemoConfig, ["demo/src"], { + root: paths.demo_root, + port: 8090, + }); +}); + +gulp.task("rollup-dev-server-cast", () => { + watchRollup(rollupConfig.createCastConfig, ["cast/src"], { + root: paths.cast_root, + port: 8080, + networkAccess: true, + }); +}); + +gulp.task("rollup-dev-server-gallery", () => { + watchRollup(rollupConfig.createGalleryConfig, ["gallery/src"], { + root: paths.gallery_root, + port: 8100, + }); +}); + +gulp.task( + "rollup-prod-app", + bothBuilds(rollupConfig.createAppConfig, { isProdBuild: true }) +); + +gulp.task( + "rollup-prod-demo", + bothBuilds(rollupConfig.createDemoConfig, { isProdBuild: true }) +); + +gulp.task( + "rollup-prod-cast", + bothBuilds(rollupConfig.createCastConfig, { isProdBuild: true }) +); + +gulp.task("rollup-prod-hassio", () => + buildRollup( + rollupConfig.createHassioConfig({ + isProdBuild: true, + latestBuild: false, + }) + ) +); + +gulp.task("rollup-prod-gallery", () => + buildRollup( + rollupConfig.createGalleryConfig({ + isProdBuild: true, + latestBuild: true, + }) + ) +); diff --git a/build-scripts/gulp/webpack.js b/build-scripts/gulp/webpack.js index a9e39c7bd5..226bb967bc 100644 --- a/build-scripts/gulp/webpack.js +++ b/build-scripts/gulp/webpack.js @@ -38,9 +38,9 @@ const runDevServer = ({ const handler = (done) => (err, stats) => { if (err) { - console.log(err.stack || err); + log.error(err.stack || err); if (err.details) { - console.log(err.details); + log.error(err.details); } return; } @@ -48,7 +48,7 @@ const handler = (done) => (err, stats) => { log(`Build done @ ${new Date().toLocaleTimeString()}`); if (stats.hasErrors() || stats.hasWarnings()) { - console.log(stats.toString("minimal")); + log.warn(stats.toString("minimal")); } if (done) { @@ -64,7 +64,7 @@ gulp.task("webpack-watch-app", () => { ); gulp.watch( path.join(paths.translations_src, "en.json"), - gulp.series("build-translations", "copy-translations") + gulp.series("build-translations", "copy-translations-app") ); }); diff --git a/build-scripts/rollup-plugins/dont-hash-plugin.js b/build-scripts/rollup-plugins/dont-hash-plugin.js new file mode 100644 index 0000000000..89082b90c2 --- /dev/null +++ b/build-scripts/rollup-plugins/dont-hash-plugin.js @@ -0,0 +1,14 @@ +module.exports = function (opts = {}) { + const dontHash = opts.dontHash || new Set(); + + return { + name: "dont-hash", + renderChunk(_code, chunk, _options) { + if (!chunk.isEntry || !dontHash.has(chunk.name)) { + return null; + } + chunk.fileName = `${chunk.name}.js`; + return null; + }, + }; +}; diff --git a/build-scripts/rollup-plugins/manifest-plugin.js b/build-scripts/rollup-plugins/manifest-plugin.js new file mode 100644 index 0000000000..bf4bbaac05 --- /dev/null +++ b/build-scripts/rollup-plugins/manifest-plugin.js @@ -0,0 +1,34 @@ +const url = require("url"); + +const defaultOptions = { + publicPath: "", +}; + +module.exports = function (userOptions = {}) { + const options = { ...defaultOptions, ...userOptions }; + + return { + name: "manifest", + generateBundle(outputOptions, bundle) { + const manifest = {}; + + for (const chunk of Object.values(bundle)) { + if (!chunk.isEntry) { + continue; + } + // Add js extension to mimic Webpack manifest. + manifest[`${chunk.name}.js`] = url.resolve( + options.publicPath, + chunk.fileName + ); + } + + this.emitFile({ + type: "asset", + source: JSON.stringify(manifest, undefined, 2), + name: "manifest.json", + fileName: "manifest.json", + }); + }, + }; +}; diff --git a/build-scripts/rollup-plugins/worker-plugin.js b/build-scripts/rollup-plugins/worker-plugin.js new file mode 100644 index 0000000000..c075a08495 --- /dev/null +++ b/build-scripts/rollup-plugins/worker-plugin.js @@ -0,0 +1,148 @@ +// Worker plugin +// Each worker will include all of its dependencies +// instead of relying on an importer. + +// Forked from v.1.4.1 +// https://github.com/surma/rollup-plugin-off-main-thread +/** + * Copyright 2018 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const rollup = require("rollup"); +const path = require("path"); +const MagicString = require("magic-string"); + +const defaultOpts = { + // A RegExp to find `new Workers()` calls. The second capture group _must_ + // capture the provided file name without the quotes. + workerRegexp: /new Worker\((["'])(.+?)\1(,[^)]+)?\)/g, + plugins: ["node-resolve", "commonjs", "babel"], +}; + +async function getBundledWorker(workerPath, rollupOptions) { + const bundle = await rollup.rollup({ + ...rollupOptions, + input: { + worker: workerPath, + }, + }); + const { output } = await bundle.generate({ + // Generates cleanest output, we shouldn't have any imports/exports + // that would be incompatible with ES5. + format: "es", + // We should not export anything. This will fail build if we are. + exports: "none", + }); + + let code; + + for (const chunkOrAsset of output) { + if (chunkOrAsset.name === "worker") { + code = chunkOrAsset.code; + } else if (chunkOrAsset.type !== "asset") { + throw new Error("Unexpected extra output"); + } + } + + return code; +} + +module.exports = function (opts = {}) { + opts = { ...defaultOpts, ...opts }; + + let rollupOptions; + let refIds; + + return { + name: "hass-worker", + + async buildStart(options) { + refIds = {}; + rollupOptions = { + plugins: options.plugins.filter((plugin) => + opts.plugins.includes(plugin.name) + ), + }; + }, + + async transform(code, id) { + // Copy the regexp as they are stateful and this hook is async. + const workerRegexp = new RegExp( + opts.workerRegexp.source, + opts.workerRegexp.flags + ); + if (!workerRegexp.test(code)) { + return; + } + + const ms = new MagicString(code); + // Reset the regexp + workerRegexp.lastIndex = 0; + while (true) { + const match = workerRegexp.exec(code); + if (!match) { + break; + } + + const workerFile = match[2]; + let optionsObject = {}; + // Parse the optional options object + if (match[3] && match[3].length > 0) { + // FIXME: ooooof! + optionsObject = new Function(`return ${match[3].slice(1)};`)(); + } + delete optionsObject.type; + + if (!new RegExp("^.*/").test(workerFile)) { + this.warn( + `Paths passed to the Worker constructor must be relative or absolute, i.e. start with /, ./ or ../ (just like dynamic import!). Ignoring "${workerFile}".` + ); + continue; + } + + // Find worker file and store it as a chunk with ID prefixed for our loader + const resolvedWorkerFile = (await this.resolve(workerFile, id)).id; + let chunkRefId; + if (resolvedWorkerFile in refIds) { + chunkRefId = refIds[resolvedWorkerFile]; + } else { + const source = await getBundledWorker( + resolvedWorkerFile, + rollupOptions + ); + chunkRefId = refIds[resolvedWorkerFile] = this.emitFile({ + name: path.basename(resolvedWorkerFile), + source, + type: "asset", + }); + } + + const workerParametersStartIndex = match.index + "new Worker(".length; + const workerParametersEndIndex = + match.index + match[0].length - ")".length; + + ms.overwrite( + workerParametersStartIndex, + workerParametersEndIndex, + `import.meta.ROLLUP_FILE_URL_${chunkRefId}, ${JSON.stringify( + optionsObject + )}` + ); + } + + return { + code: ms.toString(), + map: ms.generateMap({ hires: true }), + }; + }, + }; +}; diff --git a/build-scripts/rollup.js b/build-scripts/rollup.js new file mode 100644 index 0000000000..ad3474a73b --- /dev/null +++ b/build-scripts/rollup.js @@ -0,0 +1,141 @@ +const path = require("path"); + +const commonjs = require("@rollup/plugin-commonjs"); +const resolve = require("@rollup/plugin-node-resolve"); +const json = require("@rollup/plugin-json"); +const babel = require("rollup-plugin-babel"); +const replace = require("@rollup/plugin-replace"); +const visualizer = require("rollup-plugin-visualizer"); +const { string } = require("rollup-plugin-string"); +const { terser } = require("rollup-plugin-terser"); +const manifest = require("./rollup-plugins/manifest-plugin"); +const worker = require("./rollup-plugins/worker-plugin"); +const dontHashPlugin = require("./rollup-plugins/dont-hash-plugin"); + +const babelConfig = require("./babel"); +const bundle = require("./bundle"); + +const extensions = [".js", ".ts"]; + +/** + * @param {Object} arg + * @param { import("rollup").InputOption } arg.input + */ +const createRollupConfig = ({ + entry, + outputPath, + defineOverlay, + isProdBuild, + latestBuild, + isStatsBuild, + publicPath, + dontHash, +}) => { + return { + /** + * @type { import("rollup").InputOptions } + */ + inputOptions: { + input: entry, + // Some entry points contain no JavaScript. This setting silences a warning about that. + // https://rollupjs.org/guide/en/#preserveentrysignatures + preserveEntrySignatures: false, + external: bundle.ignorePackages + bundle.emptyPackages, + plugins: [ + resolve({ extensions, preferBuiltins: false, browser: true }), + commonjs({ + namedExports: { + "js-yaml": ["safeDump", "safeLoad"], + }, + }), + json(), + babel({ + ...babelConfig.options({ latestBuild }), + extensions, + babelrc: false, + exclude: babelConfig.exclude, + }), + string({ + // Import certain extensions as strings + include: ["**/*.css"], + }), + replace( + bundle.definedVars({ isProdBuild, latestBuild, defineOverlay }) + ), + manifest({ + publicPath, + }), + worker(), + dontHashPlugin({ dontHash }), + isProdBuild && terser(bundle.terserOptions(latestBuild)), + isStatsBuild && + visualizer({ + // https://github.com/btd/rollup-plugin-visualizer#options + open: true, + sourcemap: true, + }), + ], + }, + /** + * @type { import("rollup").OutputOptions } + */ + outputOptions: { + // https://rollupjs.org/guide/en/#outputdir + dir: outputPath, + // https://rollupjs.org/guide/en/#outputformat + format: latestBuild ? "es" : "systemjs", + // https://rollupjs.org/guide/en/#outputexternallivebindings + externalLiveBindings: false, + // https://rollupjs.org/guide/en/#outputentryfilenames + // https://rollupjs.org/guide/en/#outputchunkfilenames + // https://rollupjs.org/guide/en/#outputassetfilenames + entryFileNames: isProdBuild ? "[name]-[hash].js" : "[name].js", + chunkFileNames: isProdBuild ? "c.[hash].js" : "[name].js", + assetFileNames: isProdBuild ? "a.[hash].js" : "[name].js", + // https://rollupjs.org/guide/en/#outputsourcemap + sourcemap: isProdBuild ? true : "inline", + }, + }; +}; + +const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => { + return createRollupConfig( + bundle.config.app({ + isProdBuild, + latestBuild, + isStatsBuild, + }) + ); +}; + +const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => { + return createRollupConfig( + bundle.config.demo({ + isProdBuild, + latestBuild, + isStatsBuild, + }) + ); +}; + +const createCastConfig = ({ isProdBuild, latestBuild }) => { + return createRollupConfig(bundle.config.cast({ isProdBuild, latestBuild })); +}; + +const createHassioConfig = ({ isProdBuild, latestBuild }) => { + return createRollupConfig(bundle.config.hassio({ isProdBuild, latestBuild })); +}; + +const createGalleryConfig = ({ isProdBuild, latestBuild }) => { + return createRollupConfig( + bundle.config.gallery({ isProdBuild, latestBuild }) + ); +}; + +module.exports = { + createAppConfig, + createDemoConfig, + createCastConfig, + createHassioConfig, + createGalleryConfig, +}; diff --git a/build-scripts/webpack.js b/build-scripts/webpack.js index 7b88936d8a..eb940caccb 100644 --- a/build-scripts/webpack.js +++ b/build-scripts/webpack.js @@ -4,7 +4,7 @@ const TerserPlugin = require("terser-webpack-plugin"); const ManifestPlugin = require("webpack-manifest-plugin"); const WorkerPlugin = require("worker-plugin"); const paths = require("./paths.js"); -const { babelLoaderConfig } = require("./babel.js"); +const babel = require("./babel.js"); const bundle = require("./bundle"); const createWebpackConfig = ({ @@ -29,7 +29,14 @@ const createWebpackConfig = ({ node: false, module: { rules: [ - babelLoaderConfig({ latestBuild }), + { + test: /\.js$|\.ts$/, + exclude: babel.exclude, + use: { + loader: "babel-loader", + options: babel.options({ latestBuild }), + }, + }, { test: /\.css$/, use: "raw-loader", diff --git a/cast/rollup.config.js b/cast/rollup.config.js new file mode 100644 index 0000000000..5460a82216 --- /dev/null +++ b/cast/rollup.config.js @@ -0,0 +1,10 @@ +const rollup = require("../build-scripts/rollup.js"); +const env = require("../build-scripts/env.js"); + +const config = rollup.createCastConfig({ + isProdBuild: env.isProdBuild(), + latestBuild: true, + isStatsBuild: env.isStatsBuild(), +}); + +module.exports = { ...config.inputOptions, output: config.outputOptions }; diff --git a/cast/src/html/launcher-faq.html.template b/cast/src/html/launcher-faq.html.template index 20640e8b54..30589f2703 100644 --- a/cast/src/html/launcher-faq.html.template +++ b/cast/src/html/launcher-faq.html.template @@ -46,7 +46,13 @@ // // Safari 10.1 supports type=module but ignores nomodule, so we add this check. if (!isS101) { _ls("/static/polyfills/custom-elements-es5-adapter.js"); - _ls("<%= es5LauncherJS %>"); + <% if (useRollup) { %> + _ls("/static/js/s.min.js").onload = function() { + System.import("<%= es5LauncherJS %>"); + }; + <% } else { %> + _ls("<%= es5LauncherJS %>"); + <% } %> } })(); diff --git a/cast/src/html/launcher.html.template b/cast/src/html/launcher.html.template index 25b2eba1a5..fd176a1e59 100644 --- a/cast/src/html/launcher.html.template +++ b/cast/src/html/launcher.html.template @@ -37,7 +37,13 @@ // // Safari 10.1 supports type=module but ignores nomodule, so we add this check. if (!isS101) { _ls("/static/polyfills/custom-elements-es5-adapter.js"); - _ls("<%= es5LauncherJS %>"); + <% if (useRollup) { %> + _ls("/static/js/s.min.js").onload = function() { + System.import("<%= es5LauncherJS %>"); + }; + <% } else { %> + _ls("<%= es5LauncherJS %>"); + <% } %> } })(); diff --git a/demo/rollup.config.js b/demo/rollup.config.js new file mode 100644 index 0000000000..d236491002 --- /dev/null +++ b/demo/rollup.config.js @@ -0,0 +1,10 @@ +const rollup = require("../build-scripts/rollup.js"); +const env = require("../build-scripts/env.js"); + +const config = rollup.createDemoConfig({ + isProdBuild: env.isProdBuild(), + latestBuild: true, + isStatsBuild: env.isStatsBuild(), +}); + +module.exports = { ...config.inputOptions, output: config.outputOptions }; diff --git a/demo/src/html/index.html.template b/demo/src/html/index.html.template index a9decd4502..c626161b69 100644 --- a/demo/src/html/index.html.template +++ b/demo/src/html/index.html.template @@ -104,8 +104,16 @@ // // Safari 10.1 supports type=module but ignores nomodule, so we add this check. if (!isS101) { _ls("/static/polyfills/custom-elements-es5-adapter.js"); - _ls("<%= es5Compatibility %>"); - _ls("<%= es5DemoJS %>"); + <% if (useRollup) { %> + _ls("/static/js/s.min.js").onload = function() { + System.import("<%= es5Compatibility %>").then(function() { + System.import("<%= es5DemoJS %>"); + }); + }; + <% } else { %> + _ls("<%= es5Compatibility %>"); + _ls("<%= es5DemoJS %>"); + <% } %> } })(); diff --git a/gallery/rollup.config.js b/gallery/rollup.config.js new file mode 100644 index 0000000000..787bf5a448 --- /dev/null +++ b/gallery/rollup.config.js @@ -0,0 +1,10 @@ +const rollup = require("../build-scripts/rollup.js"); +const env = require("../build-scripts/env.js"); + +const config = rollup.createGalleryConfig({ + isProdBuild: env.isProdBuild(), + latestBuild: true, + isStatsBuild: env.isStatsBuild(), +}); + +module.exports = { ...config.inputOptions, output: config.outputOptions }; diff --git a/hassio/rollup.config.js b/hassio/rollup.config.js new file mode 100644 index 0000000000..4beee60e48 --- /dev/null +++ b/hassio/rollup.config.js @@ -0,0 +1,10 @@ +const rollup = require("../build-scripts/rollup.js"); +const env = require("../build-scripts/env.js"); + +const config = rollup.createHassioConfig({ + isProdBuild: env.isProdBuild(), + latestBuild: false, + isStatsBuild: env.isStatsBuild(), +}); + +module.exports = { ...config.inputOptions, output: config.outputOptions }; diff --git a/package.json b/package.json index 4252ee18a7..cb89179ba0 100644 --- a/package.json +++ b/package.json @@ -126,6 +126,10 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/preset-env": "^7.9.5", "@babel/preset-typescript": "^7.9.0", + "@rollup/plugin-commonjs": "^11.1.0", + "@rollup/plugin-json": "^4.0.3", + "@rollup/plugin-node-resolve": "^7.1.3", + "@rollup/plugin-replace": "^2.3.2", "@types/chai": "^4.1.7", "@types/chromecast-caf-receiver": "^3.0.12", "@types/codemirror": "^0.0.78", @@ -165,15 +169,24 @@ "lint-staged": "^8.1.5", "lit-analyzer": "^1.1.10", "lodash.template": "^4.5.0", + "magic-string": "^0.25.7", "map-stream": "^0.0.7", "merge-stream": "^1.0.1", "mocha": "^6.0.2", "object-hash": "^2.0.3", + "open": "^7.0.4", "prettier": "^2.0.4", "raw-loader": "^2.0.0", "require-dir": "^1.2.0", + "rollup": "^2.8.2", + "rollup-plugin-babel": "^4.4.0", + "rollup-plugin-string": "^3.0.0", + "rollup-plugin-terser": "^5.3.0", + "rollup-plugin-visualizer": "^4.0.4", + "serve": "^11.3.0", "sinon": "^7.3.1", "source-map-url": "^0.4.0", + "systemjs": "^6.3.2", "terser-webpack-plugin": "^1.2.3", "ts-lit-plugin": "^1.1.10", "ts-mocha": "^6.0.0", diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000000..2eb552dbfe --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,10 @@ +const rollup = require("./build-scripts/rollup.js"); +const env = require("./build-scripts/env.js"); + +const config = rollup.createAppConfig({ + isProdBuild: env.isProdBuild(), + latestBuild: true, + isStatsBuild: env.isStatsBuild(), +}); + +module.exports = { ...config.inputOptions, output: config.outputOptions }; diff --git a/src/components/data-table/sort-filter.ts b/src/components/data-table/sort-filter.ts index 9e89e866df..33fa6ecdb9 100644 --- a/src/components/data-table/sort-filter.ts +++ b/src/components/data-table/sort-filter.ts @@ -1,9 +1,11 @@ import { wrap } from "comlink"; -type FilterDataType = typeof import("./sort_filter_worker").api["filterData"]; +import type { api } from "./sort_filter_worker"; + +type FilterDataType = api["filterData"]; type FilterDataParamTypes = Parameters; -type SortDataType = typeof import("./sort_filter_worker").api["sortData"]; +type SortDataType = api["sortData"]; type SortDataParamTypes = Parameters; let worker: any | undefined; diff --git a/src/components/data-table/sort_filter_worker.ts b/src/components/data-table/sort_filter_worker.ts index de3e1c67b2..4c0d6d1987 100644 --- a/src/components/data-table/sort_filter_worker.ts +++ b/src/components/data-table/sort_filter_worker.ts @@ -67,10 +67,11 @@ const sortData = ( return 0; }); -// Export for types -export const api = { +const api = { filterData, sortData, }; +export type api = typeof api; + expose(api); diff --git a/src/html/_js_base.html.template b/src/html/_js_base.html.template index c9bf4d4b49..2864581ce2 100644 --- a/src/html/_js_base.html.template +++ b/src/html/_js_base.html.template @@ -7,6 +7,7 @@ ); script.defer = true; script.src = src; + return script; } window.Polymer = { lazyRegister: true, diff --git a/src/html/authorize.html.template b/src/html/authorize.html.template index 3169c62b45..ed3bbb27b0 100644 --- a/src/html/authorize.html.template +++ b/src/html/authorize.html.template @@ -59,8 +59,16 @@ // Safari 10.1 supports type=module but ignores nomodule, so we add this check. if (!isS101) { _ls("/static/polyfills/custom-elements-es5-adapter.js"); - _ls("<%= es5Compatibility %>"); - _ls("<%= es5PageJS %>"); + <% if (useRollup) { %> + _ls("/static/js/s.min.js").onload = function() { + System.import("<%= es5Compatibility %>").then(function() { + System.import("<%= es5PageJS %>"); + }); + } + <% } else { %> + _ls("<%= es5Compatibility %>"); + _ls("<%= es5PageJS %>"); + <% } %> } })(); diff --git a/src/html/index.html.template b/src/html/index.html.template index 1c36cc718d..47deba231b 100644 --- a/src/html/index.html.template +++ b/src/html/index.html.template @@ -70,17 +70,28 @@ {% for extra_module in extra_modules -%} {% endfor -%} - + diff --git a/src/resources/markdown_worker.ts b/src/resources/markdown_worker.ts index 70507bb9fa..f248520b6a 100644 --- a/src/resources/markdown_worker.ts +++ b/src/resources/markdown_worker.ts @@ -49,9 +49,10 @@ const renderMarkdown = ( }); }; -// Export for types -export const api = { +const api = { renderMarkdown, }; +export type api = typeof api; + expose(api); diff --git a/src/resources/render-markdown.ts b/src/resources/render-markdown.ts index d4a4397f21..4df0794ea0 100644 --- a/src/resources/render-markdown.ts +++ b/src/resources/render-markdown.ts @@ -1,6 +1,8 @@ import { wrap } from "comlink"; -type RenderMarkdownType = typeof import("./markdown_worker").api["renderMarkdown"]; +import type { api } from "./markdown_worker"; + +type RenderMarkdownType = api["renderMarkdown"]; type renderMarkdownParamTypes = Parameters; let worker: any | undefined; diff --git a/yarn.lock b/yarn.lock index 8bca36beda..55bef23820 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2772,7 +2772,27 @@ resolved "https://registry.yarnpkg.com/@polymer/test-fixture/-/test-fixture-0.0.3.tgz#4443752697d4d9293bbc412ea0b5e4d341f149d9" integrity sha1-REN1JpfU2Sk7vEEuoLXk00HxSdk= -"@rollup/plugin-node-resolve@^7.1.1": +"@rollup/plugin-commonjs@^11.1.0": + version "11.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-11.1.0.tgz#60636c7a722f54b41e419e1709df05c7234557ef" + integrity sha512-Ycr12N3ZPN96Fw2STurD21jMqzKwL9QuFhms3SD7KKRK7oaXUsBU9Zt0jL/rOPHiPYisI21/rXGO3jr9BnLHUA== + dependencies: + "@rollup/pluginutils" "^3.0.8" + commondir "^1.0.1" + estree-walker "^1.0.1" + glob "^7.1.2" + is-reference "^1.1.2" + magic-string "^0.25.2" + resolve "^1.11.0" + +"@rollup/plugin-json@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.0.3.tgz#747e2c2884c5a0fa00b66c9c0f3f1012cddca534" + integrity sha512-QMUT0HZNf4CX17LMdwaslzlYHUKTYGuuk34yYIgZrNdu+pMEfqMS55gck7HEeHBKXHM4cz5Dg1OVwythDdbbuQ== + dependencies: + "@rollup/pluginutils" "^3.0.8" + +"@rollup/plugin-node-resolve@^7.1.1", "@rollup/plugin-node-resolve@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz#80de384edfbd7bfc9101164910f86078151a3eca" integrity sha512-RxtSL3XmdTAE2byxekYLnx+98kEUOrPHF/KRVjLH+DEIHy6kjIw7YINQzn+NXiH/NTrQLAwYs0GWB+csWygA9Q== @@ -2783,7 +2803,7 @@ is-module "^1.0.0" resolve "^1.14.2" -"@rollup/plugin-replace@^2.3.1": +"@rollup/plugin-replace@^2.3.1", "@rollup/plugin-replace@^2.3.2": version "2.3.2" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.3.2.tgz#da4e0939047f793c2eb5eedfd6c271232d0a033f" integrity sha512-KEEL7V2tMNOsbAoNMKg91l1sNXBDoiP31GFlqXVOuV5691VQKzKBh91+OKKOG4uQWYqcFskcjFyh1d5YnZd0Zw== @@ -3652,6 +3672,11 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +"@zeit/schemas@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3" + integrity sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -3752,6 +3777,16 @@ ajv-keywords@^3.4.1: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== +ajv@6.5.3: + version "6.5.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9" + integrity sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ajv@^6.1.0, ajv@^6.5.5, ajv@^6.9.1: version "6.10.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" @@ -3886,7 +3921,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== @@ -3952,6 +3987,11 @@ aproba@^1.0.3, aproba@^1.1.1: resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +arch@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.2.tgz#0c52bbe7344bb4fa260c443d2cbad9c00ff2f0bf" + integrity sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ== + archiver-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-1.3.0.tgz#e50b4c09c70bf3d680e32ff1b7994e9f9d895174" @@ -3991,6 +4031,11 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +arg@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arg/-/arg-2.0.0.tgz#c06e7ff69ab05b3a4a03ebe0407fac4cba657545" + integrity sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -4812,7 +4857,7 @@ bower-config@^1.4.0, bower-config@^1.4.1: osenv "^0.1.3" untildify "^2.1.0" -boxen@^1.2.1: +boxen@1.3.0, boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== @@ -5249,6 +5294,15 @@ chai@^4.2.0: pathval "^1.1.0" type-detect "^4.0.5" +chalk@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -5488,6 +5542,14 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= +clipboardy@1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef" + integrity sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA== + dependencies: + arch "^2.1.0" + execa "^0.8.0" + cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -5515,6 +5577,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" @@ -5741,6 +5812,13 @@ compress-commons@^1.2.0: normalize-path "^2.0.0" readable-stream "^2.0.0" +compressible@~2.0.14: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + compressible@~2.0.16: version "2.0.16" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.16.tgz#a49bf9858f3821b64ce1be0296afc7380466a77f" @@ -5748,6 +5826,19 @@ compressible@~2.0.16: dependencies: mime-db ">= 1.38.0 < 2" +compression@1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.3.tgz#27e0e176aaf260f7f2c2813c3e440adb9f1993db" + integrity sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.14" + debug "2.6.9" + on-headers "~1.0.1" + safe-buffer "5.1.2" + vary "~1.1.2" + compression@^1.6.2, compression@^1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" @@ -6781,6 +6872,11 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.1" es6-symbol "^3.1.1" +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -7089,6 +7185,19 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + integrity sha1-2NdrvBtVIX7RkP1t1J08d07PyNo= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -7349,6 +7458,13 @@ fast-safe-stringify@^2.0.4: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz#04b26106cc56681f51a044cfc0d76cf0008ac2c2" integrity sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg== +fast-url-parser@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= + dependencies: + punycode "^1.3.2" + fastq@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.7.0.tgz#fcd79a08c5bd7ec5b55cd3f5c4720db551929801" @@ -7545,6 +7661,14 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + findup-sync@2.0.0, findup-sync@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" @@ -7768,6 +7892,11 @@ fsevents@^1.0.0, fsevents@^1.2.7: nan "^2.12.1" node-pre-gyp "^0.12.0" +fsevents@~2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -8940,6 +9069,11 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= +is-docker@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" + integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -9146,6 +9280,13 @@ is-redirect@^1.0.0: resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= +is-reference@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.1.4.tgz#3f95849886ddb70256a3e6d062b1a68c13c51427" + integrity sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw== + dependencies: + "@types/estree" "0.0.39" + is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" @@ -9226,6 +9367,13 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -9751,6 +9899,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash._escapehtmlchar@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz#df67c3bb6b7e8e1e831ab48bfa0795b92afe899d" @@ -10051,7 +10206,7 @@ magic-string@^0.22.4: dependencies: vlq "^0.2.2" -magic-string@^0.25.0, magic-string@^0.25.5: +magic-string@^0.25.0, magic-string@^0.25.2, magic-string@^0.25.5, magic-string@^0.25.7: version "0.25.7" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== @@ -10308,6 +10463,23 @@ mime-db@1.40.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== +"mime-db@>= 1.43.0 < 2": + version "1.44.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== + +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== + +mime-types@2.1.18: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== + dependencies: + mime-db "~1.33.0" + mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.22" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" @@ -10606,6 +10778,11 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== +nanoid@^3.0.1: + version "3.1.9" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.9.tgz#1f148669c70bb2072dc5af0666e46edb6cd31fb2" + integrity sha512-fFiXlFo4Wkuei3i6w9SQI6yuzGRTGi8Z2zZKZpUxv/bQlBi4jtbVPBSNFZHQA9PNjofWqtIa8p+pnsc0kgZrhQ== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -11044,7 +11221,7 @@ on-finished@^2.3.0, on-finished@~2.3.0: dependencies: ee-first "1.1.1" -on-headers@~1.0.2: +on-headers@~1.0.1, on-headers@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== @@ -11075,6 +11252,14 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +open@^7.0.3, open@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/open/-/open-7.0.4.tgz#c28a9d315e5c98340bf979fdcb2e58664aa10d83" + integrity sha512-brSA+/yq+b08Hsr4c8fsEW2CRzk1BmfN3SAK/5VCHQ9bdoZJ4qa/+AfR0xHjlbbZUyPkUHs1b8x1RqdyZdkVqQ== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + opn@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a" @@ -11199,6 +11384,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -11213,6 +11405,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-map@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" @@ -11440,12 +11639,17 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@1.0.2, path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= @@ -11477,6 +11681,11 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-to-regexp@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" + integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== + path-to-regexp@^1.0.1, path-to-regexp@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" @@ -12027,7 +12236,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.4.1: +punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -12037,6 +12246,13 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +pupa@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726" + integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA== + dependencies: + escape-goat "^2.0.0" + q@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" @@ -12101,16 +12317,16 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" +range-parser@1.2.0, range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= + range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -range-parser@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= - raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" @@ -12366,6 +12582,14 @@ regexpu-core@^4.7.0: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.2.0" +registry-auth-token@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" + integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + registry-auth-token@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e" @@ -12374,7 +12598,7 @@ registry-auth-token@^3.0.1: rc "^1.1.6" safe-buffer "^5.0.1" -registry-url@^3.0.3: +registry-url@3.1.0, registry-url@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= @@ -12583,10 +12807,17 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.4.0, dependencies: path-parse "^1.0.6" +resolve@^1.11.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.16.0.tgz#063dc704fa3413e13ac1d0d1756a7cbfe95dd1a7" + integrity sha512-LarL/PIKJvc09k1jaeT4kQb/8/7P+qV4qSnN2K80AES+OHdfZELAKVOBjxsvtToT/uLOfFbvYvKfZmV8cee7nA== + dependencies: + path-parse "^1.0.6" + resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + version "1.15.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" + integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== dependencies: path-parse "^1.0.6" @@ -12653,7 +12884,7 @@ roboto-fontface@^0.10.0: resolved "https://registry.yarnpkg.com/roboto-fontface/-/roboto-fontface-0.10.0.tgz#7eee40cfa18b1f7e4e605eaf1a2740afb6fd71b0" integrity sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g== -rollup-plugin-babel@^4.3.3: +rollup-plugin-babel@^4.3.3, rollup-plugin-babel@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz#d15bd259466a9d1accbdb2fe2fff17c52d030acb" integrity sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw== @@ -12661,7 +12892,14 @@ rollup-plugin-babel@^4.3.3: "@babel/helper-module-imports" "^7.0.0" rollup-pluginutils "^2.8.1" -rollup-plugin-terser@^5.2.0: +rollup-plugin-string@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-string/-/rollup-plugin-string-3.0.0.tgz#fed2d6301fae1e59eb610957df757ef13fada3f0" + integrity sha512-vqyzgn9QefAgeKi+Y4A7jETeIAU1zQmS6VotH6bzm/zmUQEnYkpIGRaOBPY41oiWYV4JyBoGAaBjYMYuv+6wVw== + dependencies: + rollup-pluginutils "^2.4.1" + +rollup-plugin-terser@^5.2.0, rollup-plugin-terser@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.3.0.tgz#9c0dd33d5771df9630cd027d6a2559187f65885e" integrity sha512-XGMJihTIO3eIBsVGq7jiNYOdDMb3pVxuzY0uhOE/FM4x/u9nQgr3+McsjzqBn3QfHIpNSZmFnpoKAwHBEcsT7g== @@ -12672,7 +12910,18 @@ rollup-plugin-terser@^5.2.0: serialize-javascript "^2.1.2" terser "^4.6.2" -rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2: +rollup-plugin-visualizer@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-4.0.4.tgz#69b9140c6faf46328997ed2d08b974252bf9d683" + integrity sha512-odkyLiVxCEXh4AWFSl75+pbIapzhEZkOVww8pKUgraOHicSH67MYMnAOHWQVK/BYeD1cCiF/0kk8/XNX2+LM9A== + dependencies: + nanoid "^3.0.1" + open "^7.0.3" + pupa "^2.0.0" + source-map "^0.7.3" + yargs "^15.0.0" + +rollup-pluginutils@^2.4.1, rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2: version "2.8.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== @@ -12697,6 +12946,13 @@ rollup@^1.31.1: "@types/node" "*" acorn "^7.1.0" +rollup@^2.8.2: + version "2.8.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.8.2.tgz#08427a8eb118e6e4ac8d80eba22774bc1d059c81" + integrity sha512-LRzMcB8V1M69pSvf6uCbR+W9OPCy5FuxcIwqioWg5RKidrrqKbzjJF9pEGXceaMVkbptNFZgIVJlUokCU0sfng== + optionalDependencies: + fsevents "~2.1.2" + run-async@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" @@ -12913,6 +13169,20 @@ serialize-javascript@^2.1.2: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== +serve-handler@6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.2.tgz#f05b0421a313fff2d257838cba00cbcc512cd2b6" + integrity sha512-RFh49wX7zJmmOVDcIjiDSJnMH+ItQEvyuYLYuDBVoA/xmQSCuj+uRmk1cmBB5QQlI3qOiWKp6p4DUGY+Z5AB2A== + dependencies: + bytes "3.0.0" + content-disposition "0.5.2" + fast-url-parser "1.1.3" + mime-types "2.1.18" + minimatch "3.0.4" + path-is-inside "1.0.2" + path-to-regexp "2.2.1" + range-parser "1.2.0" + serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -12946,6 +13216,21 @@ serve-static@1.14.1: parseurl "~1.3.3" send "0.17.1" +serve@^11.3.0: + version "11.3.0" + resolved "https://registry.yarnpkg.com/serve/-/serve-11.3.0.tgz#1d342e13e310501ecf17b6602f1f35da640d6448" + integrity sha512-AU0g50Q1y5EVFX56bl0YX5OtVjUX1N737/Htj93dQGKuHiuLvVB45PD8Muar70W6Kpdlz8aNJfoUqTyAq9EE/A== + dependencies: + "@zeit/schemas" "2.6.0" + ajv "6.5.3" + arg "2.0.0" + boxen "1.3.0" + chalk "2.4.1" + clipboardy "1.2.3" + compression "1.7.3" + serve-handler "6.1.2" + update-check "1.5.2" + server-destroy@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" @@ -13504,7 +13789,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0: +string-width@^4.1.0, string-width@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== @@ -13765,6 +14050,11 @@ synchronous-promise@^2.0.5: resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.7.tgz#3574b3d2fae86b145356a4b89103e1577f646fe3" integrity sha512-16GbgwTmFMYFyQMLvtQjvNWh30dsFe1cAW5Fg1wm5+dg84L9Pe36mftsIRU95/W2YsISxsz/xq4VB23sqpgb/A== +systemjs@^6.3.2: + version "6.3.2" + resolved "https://registry.yarnpkg.com/systemjs/-/systemjs-6.3.2.tgz#2c3407f949260fdfb3b837c191869db933d1fe0f" + integrity sha512-zcALS1RIYtsQBG4fbaE+cJzKx+UoEuSM8xCkGGH99i7p7Ym3ALvhi9QrpF2lo0CMQaejqrE1GnbkuG2m/+H7ew== + table-layout@^0.4.3: version "0.4.4" resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-0.4.4.tgz#bc5398b2a05e58b67b05dd9238354b89ef27be0f" @@ -13925,9 +14215,9 @@ terser@^4.1.2: source-map-support "~0.5.12" terser@^4.6.2: - version "4.6.13" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.13.tgz#e879a7364a5e0db52ba4891ecde007422c56a916" - integrity sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw== + version "4.6.6" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.6.tgz#da2382e6cafbdf86205e82fb9a115bd664d54863" + integrity sha512-4lYPyeNmstjIIESr/ysHg2vUPRGf2tzF9z2yYwnowXVuVzLEamPN1Gfrz7f8I9uEPuHcbFlW4PLIAsJoxXyJ1g== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -14477,6 +14767,14 @@ upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +update-check@1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.2.tgz#2fe09f725c543440b3d7dabe8971f2d5caaedc28" + integrity sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ== + dependencies: + registry-auth-token "3.3.2" + registry-url "3.1.0" + update-notifier@^2.2.0, update-notifier@^2.3.0: version "2.5.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" @@ -15331,6 +15629,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -15468,6 +15775,14 @@ yargs-parser@^13.1.0: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^18.1.1: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" @@ -15519,6 +15834,23 @@ yargs@13.2.4: y18n "^4.0.0" yargs-parser "^13.1.0" +yargs@^15.0.0: + version "15.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" + integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.1" + yargs@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" From ad386c0e22d89ec45d416ca784a5e1aa5bf3c3c1 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 23 May 2020 00:06:23 -0700 Subject: [PATCH 27/77] Cleanups (#5997) --- build-scripts/babel.js | 31 ----------- build-scripts/bundle.js | 47 ++++++++++++++--- build-scripts/gulp/clean.js | 10 ++-- build-scripts/gulp/compress.js | 24 ++++----- build-scripts/gulp/entry-html.js | 78 ++++++++++++++++++++-------- build-scripts/gulp/gather-static.js | 53 ++++++++++--------- build-scripts/gulp/rollup.js | 6 +-- build-scripts/gulp/service-worker.js | 24 +++++---- build-scripts/gulp/webpack.js | 6 +-- build-scripts/paths.js | 34 +++++++----- build-scripts/rollup.js | 10 ++-- build-scripts/webpack.js | 10 ++-- 12 files changed, 193 insertions(+), 140 deletions(-) delete mode 100644 build-scripts/babel.js diff --git a/build-scripts/babel.js b/build-scripts/babel.js deleted file mode 100644 index c02b53e413..0000000000 --- a/build-scripts/babel.js +++ /dev/null @@ -1,31 +0,0 @@ -module.exports.options = ({ latestBuild }) => ({ - presets: [ - !latestBuild && [require("@babel/preset-env").default, { modules: false }], - require("@babel/preset-typescript").default, - ].filter(Boolean), - plugins: [ - // Part of ES2018. Converts {...a, b: 2} to Object.assign({}, a, {b: 2}) - [ - "@babel/plugin-proposal-object-rest-spread", - { loose: true, useBuiltIns: true }, - ], - // Only support the syntax, Webpack will handle it. - "@babel/syntax-dynamic-import", - "@babel/plugin-proposal-optional-chaining", - "@babel/plugin-proposal-nullish-coalescing-operator", - [ - require("@babel/plugin-proposal-decorators").default, - { decoratorsBeforeExport: true }, - ], - [ - require("@babel/plugin-proposal-class-properties").default, - { loose: true }, - ], - ], -}); - -// Are already ES5, cause warnings when babelified. -module.exports.exclude = [ - require.resolve("@mdi/js/mdi.js"), - require.resolve("hls.js"), -]; diff --git a/build-scripts/bundle.js b/build-scripts/bundle.js index 51f3bc345d..c000b5af30 100644 --- a/build-scripts/bundle.js +++ b/build-scripts/bundle.js @@ -3,7 +3,7 @@ const env = require("./env.js"); const paths = require("./paths.js"); // Files from NPM Packages that should not be imported -module.exports.ignorePackages = [ +module.exports.ignorePackages = ({ latestBuild }) => [ // Bloats bundle and it's not used. path.resolve(require.resolve("moment"), "../locale"), // Part of yaml.js and only used for !!js functions that we don't use @@ -11,7 +11,7 @@ module.exports.ignorePackages = [ ]; // Files from NPM packages that we should replace with empty file -module.exports.emptyPackages = [ +module.exports.emptyPackages = ({ latestBuild }) => [ // Contains all color definitions for all material color sets. // We don't use it require.resolve("@polymer/paper-styles/color.js"), @@ -39,6 +39,39 @@ module.exports.terserOptions = (latestBuild) => ({ output: { comments: false }, }); +module.exports.babelOptions = ({ latestBuild }) => ({ + babelrc: false, + presets: [ + !latestBuild && [require("@babel/preset-env").default, { modules: false }], + require("@babel/preset-typescript").default, + ].filter(Boolean), + plugins: [ + // Part of ES2018. Converts {...a, b: 2} to Object.assign({}, a, {b: 2}) + [ + "@babel/plugin-proposal-object-rest-spread", + { loose: true, useBuiltIns: true }, + ], + // Only support the syntax, Webpack will handle it. + "@babel/syntax-dynamic-import", + "@babel/plugin-proposal-optional-chaining", + "@babel/plugin-proposal-nullish-coalescing-operator", + [ + require("@babel/plugin-proposal-decorators").default, + { decoratorsBeforeExport: true }, + ], + [ + require("@babel/plugin-proposal-class-properties").default, + { loose: true }, + ], + ], +}); + +// Are already ES5, cause warnings when babelified. +module.exports.babelExclude = () => [ + require.resolve("@mdi/js/mdi.js"), + require.resolve("hls.js"), +]; + const outputPath = (outputRoot, latestBuild) => path.resolve(outputRoot, latestBuild ? "frontend_latest" : "frontend_es5"); @@ -78,7 +111,7 @@ module.exports.config = { compatibility: "./src/entrypoints/compatibility.ts", "custom-panel": "./src/entrypoints/custom-panel.ts", }, - outputPath: outputPath(paths.root, latestBuild), + outputPath: outputPath(paths.app_output_root, latestBuild), publicPath: publicPath(latestBuild), isProdBuild, latestBuild, @@ -95,7 +128,7 @@ module.exports.config = { "src/entrypoints/compatibility.ts" ), }, - outputPath: outputPath(paths.demo_root, latestBuild), + outputPath: outputPath(paths.demo_output_root, latestBuild), publicPath: publicPath(latestBuild), defineOverlay: { __VERSION__: JSON.stringify(`DEMO-${env.version()}`), @@ -121,7 +154,7 @@ module.exports.config = { return { entry, - outputPath: outputPath(paths.cast_root, latestBuild), + outputPath: outputPath(paths.cast_output_root, latestBuild), publicPath: publicPath(latestBuild), isProdBuild, latestBuild, @@ -139,7 +172,7 @@ module.exports.config = { entry: { entrypoint: path.resolve(paths.hassio_dir, "src/entrypoint.ts"), }, - outputPath: paths.hassio_root, + outputPath: paths.hassio_output_root, publicPath: paths.hassio_publicPath, isProdBuild, latestBuild, @@ -152,7 +185,7 @@ module.exports.config = { entry: { entrypoint: path.resolve(paths.gallery_dir, "src/entrypoint.js"), }, - outputPath: outputPath(paths.gallery_root, latestBuild), + outputPath: outputPath(paths.gallery_output_root, latestBuild), publicPath: publicPath(latestBuild), isProdBuild, latestBuild, diff --git a/build-scripts/gulp/clean.js b/build-scripts/gulp/clean.js index 41fec51e69..4b90f98828 100644 --- a/build-scripts/gulp/clean.js +++ b/build-scripts/gulp/clean.js @@ -6,34 +6,34 @@ require("./translations"); gulp.task( "clean", gulp.parallel("clean-translations", function cleanOutputAndBuildDir() { - return del([config.root, config.build_dir]); + return del([config.app_output_root, config.build_dir]); }) ); gulp.task( "clean-demo", gulp.parallel("clean-translations", function cleanOutputAndBuildDir() { - return del([config.demo_root, config.build_dir]); + return del([config.demo_output_root, config.build_dir]); }) ); gulp.task( "clean-cast", gulp.parallel("clean-translations", function cleanOutputAndBuildDir() { - return del([config.cast_root, config.build_dir]); + return del([config.cast_output_root, config.build_dir]); }) ); gulp.task( "clean-hassio", gulp.parallel("clean-translations", function cleanOutputAndBuildDir() { - return del([config.hassio_root, config.build_dir]); + return del([config.hassio_output_root, config.build_dir]); }) ); gulp.task( "clean-gallery", gulp.parallel("clean-translations", function cleanOutputAndBuildDir() { - return del([config.gallery_root, config.build_dir]); + return del([config.gallery_output_root, config.build_dir]); }) ); diff --git a/build-scripts/gulp/compress.js b/build-scripts/gulp/compress.js index aee165c5f7..12157bc637 100644 --- a/build-scripts/gulp/compress.js +++ b/build-scripts/gulp/compress.js @@ -8,36 +8,36 @@ const paths = require("../paths"); gulp.task("compress-app", function compressApp() { const jsLatest = gulp - .src(path.resolve(paths.output, "**/*.js")) + .src(path.resolve(paths.app_output_latest, "**/*.js")) .pipe(zopfli({ threshold: 150 })) - .pipe(gulp.dest(paths.output)); + .pipe(gulp.dest(paths.app_output_latest)); const jsEs5 = gulp - .src(path.resolve(paths.output_es5, "**/*.js")) + .src(path.resolve(paths.app_output_es5, "**/*.js")) .pipe(zopfli({ threshold: 150 })) - .pipe(gulp.dest(paths.output_es5)); + .pipe(gulp.dest(paths.app_output_es5)); const polyfills = gulp - .src(path.resolve(paths.static, "polyfills/*.js")) + .src(path.resolve(paths.app_output_static, "polyfills/*.js")) .pipe(zopfli({ threshold: 150 })) - .pipe(gulp.dest(path.resolve(paths.static, "polyfills"))); + .pipe(gulp.dest(path.resolve(paths.app_output_static, "polyfills"))); const translations = gulp - .src(path.resolve(paths.static, "translations/**/*.json")) + .src(path.resolve(paths.app_output_static, "translations/**/*.json")) .pipe(zopfli({ threshold: 150 })) - .pipe(gulp.dest(path.resolve(paths.static, "translations"))); + .pipe(gulp.dest(path.resolve(paths.app_output_static, "translations"))); const icons = gulp - .src(path.resolve(paths.static, "mdi/*.json")) + .src(path.resolve(paths.app_output_static, "mdi/*.json")) .pipe(zopfli({ threshold: 150 })) - .pipe(gulp.dest(path.resolve(paths.static, "mdi"))); + .pipe(gulp.dest(path.resolve(paths.app_output_static, "mdi"))); return merge(jsLatest, jsEs5, polyfills, translations, icons); }); gulp.task("compress-hassio", function compressApp() { return gulp - .src(path.resolve(paths.hassio_root, "**/*.js")) + .src(path.resolve(paths.hassio_output_root, "**/*.js")) .pipe(zopfli()) - .pipe(gulp.dest(paths.hassio_root)); + .pipe(gulp.dest(paths.hassio_output_root)); }); diff --git a/build-scripts/gulp/entry-html.js b/build-scripts/gulp/entry-html.js index 094a41cc47..9af75cf318 100644 --- a/build-scripts/gulp/entry-html.js +++ b/build-scripts/gulp/entry-html.js @@ -57,14 +57,23 @@ gulp.task("gen-pages-dev", (done) => { es5PageJS: `/frontend_es5/${page}.js`, }); - fs.outputFileSync(path.resolve(paths.root, `${page}.html`), content); + fs.outputFileSync( + path.resolve(paths.app_output_root, `${page}.html`), + content + ); } done(); }); gulp.task("gen-pages-prod", (done) => { - const latestManifest = require(path.resolve(paths.output, "manifest.json")); - const es5Manifest = require(path.resolve(paths.output_es5, "manifest.json")); + const latestManifest = require(path.resolve( + paths.app_output_latest, + "manifest.json" + )); + const es5Manifest = require(path.resolve( + paths.app_output_es5, + "manifest.json" + )); for (const page of PAGES) { const content = renderTemplate(page, { @@ -75,7 +84,7 @@ gulp.task("gen-pages-prod", (done) => { }); fs.outputFileSync( - path.resolve(paths.root, `${page}.html`), + path.resolve(paths.app_output_root, `${page}.html`), minifyHtml(content) ); } @@ -96,13 +105,19 @@ gulp.task("gen-index-app-dev", (done) => { es5CustomPanelJS: "/frontend_es5/custom-panel.js", }).replace(/#THEMEC/g, "{{ theme_color }}"); - fs.outputFileSync(path.resolve(paths.root, "index.html"), content); + fs.outputFileSync(path.resolve(paths.app_output_root, "index.html"), content); done(); }); gulp.task("gen-index-app-prod", (done) => { - const latestManifest = require(path.resolve(paths.output, "manifest.json")); - const es5Manifest = require(path.resolve(paths.output_es5, "manifest.json")); + 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"], @@ -115,7 +130,10 @@ gulp.task("gen-index-app-prod", (done) => { }); const minified = minifyHtml(content).replace(/#THEMEC/g, "{{ theme_color }}"); - fs.outputFileSync(path.resolve(paths.root, "index.html"), minified); + fs.outputFileSync( + path.resolve(paths.app_output_root, "index.html"), + minified + ); done(); }); @@ -124,7 +142,7 @@ gulp.task("gen-index-cast-dev", (done) => { latestReceiverJS: "/frontend_latest/receiver.js", }); fs.outputFileSync( - path.resolve(paths.cast_root, "receiver.html"), + path.resolve(paths.cast_output_root, "receiver.html"), contentReceiver ); @@ -132,14 +150,17 @@ gulp.task("gen-index-cast-dev", (done) => { latestLauncherJS: "/frontend_latest/launcher.js", es5LauncherJS: "/frontend_es5/launcher.js", }); - fs.outputFileSync(path.resolve(paths.cast_root, "faq.html"), contentFAQ); + 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_root, "index.html"), + path.resolve(paths.cast_output_root, "index.html"), contentLauncher ); done(); @@ -147,7 +168,7 @@ gulp.task("gen-index-cast-dev", (done) => { gulp.task("gen-index-cast-prod", (done) => { const latestManifest = require(path.resolve( - paths.cast_output, + paths.cast_output_latest, "manifest.json" )); const es5Manifest = require(path.resolve( @@ -159,7 +180,7 @@ gulp.task("gen-index-cast-prod", (done) => { latestReceiverJS: latestManifest["receiver.js"], }); fs.outputFileSync( - path.resolve(paths.cast_root, "receiver.html"), + path.resolve(paths.cast_output_root, "receiver.html"), contentReceiver ); @@ -167,14 +188,17 @@ gulp.task("gen-index-cast-prod", (done) => { latestLauncherJS: latestManifest["launcher.js"], es5LauncherJS: es5Manifest["launcher.js"], }); - fs.outputFileSync(path.resolve(paths.cast_root, "faq.html"), contentFAQ); + 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_root, "index.html"), + path.resolve(paths.cast_output_root, "index.html"), contentLauncher ); done(); @@ -190,13 +214,16 @@ gulp.task("gen-index-demo-dev", (done) => { es5DemoJS: "/frontend_es5/main.js", }); - fs.outputFileSync(path.resolve(paths.demo_root, "index.html"), content); + fs.outputFileSync( + path.resolve(paths.demo_output_root, "index.html"), + content + ); done(); }); gulp.task("gen-index-demo-prod", (done) => { const latestManifest = require(path.resolve( - paths.demo_output, + paths.demo_output_latest, "manifest.json" )); const es5Manifest = require(path.resolve( @@ -211,7 +238,10 @@ gulp.task("gen-index-demo-prod", (done) => { }); const minified = minifyHtml(content); - fs.outputFileSync(path.resolve(paths.demo_root, "index.html"), minified); + fs.outputFileSync( + path.resolve(paths.demo_output_root, "index.html"), + minified + ); done(); }); @@ -222,13 +252,16 @@ gulp.task("gen-index-gallery-dev", (done) => { latestGalleryJS: "./frontend_latest/entrypoint.js", }); - fs.outputFileSync(path.resolve(paths.gallery_root, "index.html"), content); + fs.outputFileSync( + path.resolve(paths.gallery_output_root, "index.html"), + content + ); done(); }); gulp.task("gen-index-gallery-prod", (done) => { const latestManifest = require(path.resolve( - paths.gallery_output, + paths.gallery_output_latest, "manifest.json" )); const content = renderGalleryTemplate("index", { @@ -236,6 +269,9 @@ gulp.task("gen-index-gallery-prod", (done) => { }); const minified = minifyHtml(content); - fs.outputFileSync(path.resolve(paths.gallery_root, "index.html"), minified); + fs.outputFileSync( + path.resolve(paths.gallery_output_root, "index.html"), + minified + ); done(); }); diff --git a/build-scripts/gulp/gather-static.js b/build-scripts/gulp/gather-static.js index 55ad3ec1ca..0a16bf636e 100644 --- a/build-scripts/gulp/gather-static.js +++ b/build-scripts/gulp/gather-static.js @@ -79,14 +79,14 @@ function copyMapPanel(staticDir) { } gulp.task("copy-translations-app", async () => { - const staticDir = paths.static; + const staticDir = paths.app_output_static; copyTranslations(staticDir); }); gulp.task("copy-static-app", async () => { - const staticDir = paths.static; + const staticDir = paths.app_output_static; // Basic static files - fs.copySync(polyPath("public"), paths.root); + fs.copySync(polyPath("public"), paths.app_output_root); copyLoaderJS(staticDir); copyPolyfills(staticDir); @@ -102,41 +102,44 @@ gulp.task("copy-static-demo", async () => { // Copy app static files fs.copySync( polyPath("public/static"), - path.resolve(paths.demo_root, "static") + path.resolve(paths.demo_output_root, "static") ); // Copy demo static files - fs.copySync(path.resolve(paths.demo_dir, "public"), paths.demo_root); + fs.copySync(path.resolve(paths.demo_dir, "public"), paths.demo_output_root); - copyLoaderJS(paths.demo_static); - copyPolyfills(paths.demo_static); - copyMapPanel(paths.demo_static); - copyFonts(paths.demo_static); - copyTranslations(paths.demo_static); - copyMdiIcons(paths.demo_static); + copyLoaderJS(paths.demo_output_static); + copyPolyfills(paths.demo_output_static); + copyMapPanel(paths.demo_output_static); + copyFonts(paths.demo_output_static); + copyTranslations(paths.demo_output_static); + copyMdiIcons(paths.demo_output_static); }); gulp.task("copy-static-cast", async () => { // Copy app static files - fs.copySync(polyPath("public/static"), paths.cast_static); + fs.copySync(polyPath("public/static"), paths.cast_output_static); // Copy cast static files - fs.copySync(path.resolve(paths.cast_dir, "public"), paths.cast_root); + fs.copySync(path.resolve(paths.cast_dir, "public"), paths.cast_output_root); - copyLoaderJS(paths.cast_static); - copyPolyfills(paths.cast_static); - copyMapPanel(paths.cast_static); - copyFonts(paths.cast_static); - copyTranslations(paths.cast_static); - copyMdiIcons(paths.cast_static); + copyLoaderJS(paths.cast_output_static); + copyPolyfills(paths.cast_output_static); + copyMapPanel(paths.cast_output_static); + copyFonts(paths.cast_output_static); + copyTranslations(paths.cast_output_static); + copyMdiIcons(paths.cast_output_static); }); gulp.task("copy-static-gallery", async () => { // Copy app static files - fs.copySync(polyPath("public/static"), paths.gallery_static); + fs.copySync(polyPath("public/static"), paths.gallery_output_static); // Copy gallery static files - fs.copySync(path.resolve(paths.gallery_dir, "public"), paths.gallery_root); + fs.copySync( + path.resolve(paths.gallery_dir, "public"), + paths.gallery_output_root + ); - copyMapPanel(paths.gallery_static); - copyFonts(paths.gallery_static); - copyTranslations(paths.gallery_static); - copyMdiIcons(paths.gallery_static); + copyMapPanel(paths.gallery_output_static); + copyFonts(paths.gallery_output_static); + copyTranslations(paths.gallery_output_static); + copyMdiIcons(paths.gallery_output_static); }); diff --git a/build-scripts/gulp/rollup.js b/build-scripts/gulp/rollup.js index 606432c634..5cccc7d58f 100644 --- a/build-scripts/gulp/rollup.js +++ b/build-scripts/gulp/rollup.js @@ -95,14 +95,14 @@ gulp.task("rollup-watch-hassio", () => { gulp.task("rollup-dev-server-demo", () => { watchRollup(rollupConfig.createDemoConfig, ["demo/src"], { - root: paths.demo_root, + root: paths.demo_output_root, port: 8090, }); }); gulp.task("rollup-dev-server-cast", () => { watchRollup(rollupConfig.createCastConfig, ["cast/src"], { - root: paths.cast_root, + root: paths.cast_output_root, port: 8080, networkAccess: true, }); @@ -110,7 +110,7 @@ gulp.task("rollup-dev-server-cast", () => { gulp.task("rollup-dev-server-gallery", () => { watchRollup(rollupConfig.createGalleryConfig, ["gallery/src"], { - root: paths.gallery_root, + root: paths.gallery_output_root, port: 8100, }); }); diff --git a/build-scripts/gulp/service-worker.js b/build-scripts/gulp/service-worker.js index 01e7a97323..d0b16f7c9c 100644 --- a/build-scripts/gulp/service-worker.js +++ b/build-scripts/gulp/service-worker.js @@ -9,7 +9,7 @@ const workboxBuild = require("workbox-build"); const sourceMapUrl = require("source-map-url"); const paths = require("../paths.js"); -const swDest = path.resolve(paths.root, "service_worker.js"); +const swDest = path.resolve(paths.app_output_root, "service_worker.js"); const writeSW = (content) => fs.outputFileSync(swDest, content.trim() + "\n"); @@ -31,32 +31,38 @@ self.addEventListener('install', (event) => { gulp.task("gen-service-worker-app-prod", async () => { // Read bundled source file const bundleManifestLatest = require(path.resolve( - paths.output, + paths.app_output_latest, "manifest.json" )); let serviceWorkerContent = fs.readFileSync( - paths.root + bundleManifestLatest["service_worker.js"], + paths.app_output_root + bundleManifestLatest["service_worker.js"], "utf-8" ); // Delete old file from frontend_latest so manifest won't pick it up - fs.removeSync(paths.root + bundleManifestLatest["service_worker.js"]); - fs.removeSync(paths.root + bundleManifestLatest["service_worker.js.map"]); + fs.removeSync( + paths.app_output_root + bundleManifestLatest["service_worker.js"] + ); + fs.removeSync( + paths.app_output_root + bundleManifestLatest["service_worker.js.map"] + ); // Remove ES5 const bundleManifestES5 = require(path.resolve( - paths.output_es5, + paths.app_output_es5, "manifest.json" )); - fs.removeSync(paths.root + bundleManifestES5["service_worker.js"]); - fs.removeSync(paths.root + bundleManifestES5["service_worker.js.map"]); + fs.removeSync(paths.app_output_root + bundleManifestES5["service_worker.js"]); + fs.removeSync( + paths.app_output_root + bundleManifestES5["service_worker.js.map"] + ); const workboxManifest = await workboxBuild.getManifest({ // Files that mach this pattern will be considered unique and skip revision check // ignore JS files + translation files dontCacheBustURLsMatching: /(frontend_latest\/.+|static\/translations\/.+)/, - globDirectory: paths.root, + globDirectory: paths.app_output_root, globPatterns: [ "frontend_latest/*.js", // Cache all English translations because we catch them as fallback diff --git a/build-scripts/gulp/webpack.js b/build-scripts/gulp/webpack.js index 226bb967bc..e7e58eb726 100644 --- a/build-scripts/gulp/webpack.js +++ b/build-scripts/gulp/webpack.js @@ -82,7 +82,7 @@ gulp.task( gulp.task("webpack-dev-server-demo", () => { runDevServer({ compiler: webpack(bothBuilds(createDemoConfig, { isProdBuild: false })), - contentBase: paths.demo_root, + contentBase: paths.demo_output_root, port: 8090, }); }); @@ -103,7 +103,7 @@ gulp.task( gulp.task("webpack-dev-server-cast", () => { runDevServer({ compiler: webpack(bothBuilds(createCastConfig, { isProdBuild: false })), - contentBase: paths.cast_root, + contentBase: paths.cast_output_root, port: 8080, // Accessible from the network, because that's how Cast hits it. listenHost: "0.0.0.0", @@ -152,7 +152,7 @@ gulp.task("webpack-dev-server-gallery", () => { runDevServer({ // We don't use the es5 build, but the dev server will fuck up the publicPath if we don't compiler: webpack(bothBuilds(createGalleryConfig, { isProdBuild: false })), - contentBase: paths.gallery_root, + contentBase: paths.gallery_output_root, port: 8100, }); }); diff --git a/build-scripts/paths.js b/build-scripts/paths.js index 315cd554db..8289890c59 100644 --- a/build-scripts/paths.js +++ b/build-scripts/paths.js @@ -4,30 +4,36 @@ module.exports = { polymer_dir: path.resolve(__dirname, ".."), build_dir: path.resolve(__dirname, "../build"), - root: path.resolve(__dirname, "../hass_frontend"), - static: path.resolve(__dirname, "../hass_frontend/static"), - output: path.resolve(__dirname, "../hass_frontend/frontend_latest"), - output_es5: path.resolve(__dirname, "../hass_frontend/frontend_es5"), + app_output_root: path.resolve(__dirname, "../hass_frontend"), + app_output_static: path.resolve(__dirname, "../hass_frontend/static"), + app_output_latest: path.resolve( + __dirname, + "../hass_frontend/frontend_latest" + ), + app_output_es5: path.resolve(__dirname, "../hass_frontend/frontend_es5"), demo_dir: path.resolve(__dirname, "../demo"), - demo_root: path.resolve(__dirname, "../demo/dist"), - demo_static: path.resolve(__dirname, "../demo/dist/static"), - demo_output: path.resolve(__dirname, "../demo/dist/frontend_latest"), + demo_output_root: path.resolve(__dirname, "../demo/dist"), + demo_output_static: path.resolve(__dirname, "../demo/dist/static"), + demo_output_latest: path.resolve(__dirname, "../demo/dist/frontend_latest"), demo_output_es5: path.resolve(__dirname, "../demo/dist/frontend_es5"), cast_dir: path.resolve(__dirname, "../cast"), - cast_root: path.resolve(__dirname, "../cast/dist"), - cast_static: path.resolve(__dirname, "../cast/dist/static"), - cast_output: path.resolve(__dirname, "../cast/dist/frontend_latest"), + cast_output_root: path.resolve(__dirname, "../cast/dist"), + cast_output_static: path.resolve(__dirname, "../cast/dist/static"), + cast_output_latest: path.resolve(__dirname, "../cast/dist/frontend_latest"), cast_output_es5: path.resolve(__dirname, "../cast/dist/frontend_es5"), gallery_dir: path.resolve(__dirname, "../gallery"), - gallery_root: path.resolve(__dirname, "../gallery/dist"), - gallery_output: path.resolve(__dirname, "../gallery/dist/frontend_latest"), - gallery_static: path.resolve(__dirname, "../gallery/dist/static"), + gallery_output_root: path.resolve(__dirname, "../gallery/dist"), + gallery_output_latest: path.resolve( + __dirname, + "../gallery/dist/frontend_latest" + ), + gallery_output_static: path.resolve(__dirname, "../gallery/dist/static"), hassio_dir: path.resolve(__dirname, "../hassio"), - hassio_root: path.resolve(__dirname, "../hassio/build"), + hassio_output_root: path.resolve(__dirname, "../hassio/build"), hassio_publicPath: "/api/hassio/app/", translations_src: path.resolve(__dirname, "../src/translations"), diff --git a/build-scripts/rollup.js b/build-scripts/rollup.js index ad3474a73b..7f7739990c 100644 --- a/build-scripts/rollup.js +++ b/build-scripts/rollup.js @@ -12,7 +12,6 @@ const manifest = require("./rollup-plugins/manifest-plugin"); const worker = require("./rollup-plugins/worker-plugin"); const dontHashPlugin = require("./rollup-plugins/dont-hash-plugin"); -const babelConfig = require("./babel"); const bundle = require("./bundle"); const extensions = [".js", ".ts"]; @@ -40,7 +39,9 @@ const createRollupConfig = ({ // Some entry points contain no JavaScript. This setting silences a warning about that. // https://rollupjs.org/guide/en/#preserveentrysignatures preserveEntrySignatures: false, - external: bundle.ignorePackages + bundle.emptyPackages, + external: + bundle.ignorePackages({ latestBuild }) + + bundle.emptyPackages({ latestBuild }), plugins: [ resolve({ extensions, preferBuiltins: false, browser: true }), commonjs({ @@ -50,10 +51,9 @@ const createRollupConfig = ({ }), json(), babel({ - ...babelConfig.options({ latestBuild }), + ...bundle.babelOptions({ latestBuild }), extensions, - babelrc: false, - exclude: babelConfig.exclude, + exclude: bundle.babelExclude(), }), string({ // Import certain extensions as strings diff --git a/build-scripts/webpack.js b/build-scripts/webpack.js index eb940caccb..df310b5532 100644 --- a/build-scripts/webpack.js +++ b/build-scripts/webpack.js @@ -4,7 +4,6 @@ const TerserPlugin = require("terser-webpack-plugin"); const ManifestPlugin = require("webpack-manifest-plugin"); const WorkerPlugin = require("worker-plugin"); const paths = require("./paths.js"); -const babel = require("./babel.js"); const bundle = require("./bundle"); const createWebpackConfig = ({ @@ -20,6 +19,7 @@ const createWebpackConfig = ({ if (!dontHash) { dontHash = new Set(); } + const ignorePackages = bundle.ignorePackages({ latestBuild }); return { mode: isProdBuild ? "production" : "development", devtool: isProdBuild @@ -31,10 +31,10 @@ const createWebpackConfig = ({ rules: [ { test: /\.js$|\.ts$/, - exclude: babel.exclude, + exclude: bundle.babelExclude(), use: { loader: "babel-loader", - options: babel.options({ latestBuild }), + options: bundle.babelOptions({ latestBuild }), }, }, { @@ -84,13 +84,13 @@ const createWebpackConfig = ({ throw err; } - return bundle.ignorePackages.some((toIgnorePath) => + return ignorePackages.some((toIgnorePath) => fullPath.startsWith(toIgnorePath) ); }, }), new webpack.NormalModuleReplacementPlugin( - new RegExp(bundle.emptyPackages.join("|")), + new RegExp(bundle.emptyPackages({ latestBuild }).join("|")), path.resolve(paths.polymer_dir, "src/util/empty.js") ), ], From 872e46a076c8d1096f3175dada4910ed6abde0dd Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 23 May 2020 13:53:26 -0700 Subject: [PATCH 28/77] Exclude packages rollup (#6007) --- build-scripts/rollup-plugins/ignore-plugin.js | 51 +++++++++++++++++++ build-scripts/rollup.js | 19 +++++-- 2 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 build-scripts/rollup-plugins/ignore-plugin.js diff --git a/build-scripts/rollup-plugins/ignore-plugin.js b/build-scripts/rollup-plugins/ignore-plugin.js new file mode 100644 index 0000000000..4c6a7e61c0 --- /dev/null +++ b/build-scripts/rollup-plugins/ignore-plugin.js @@ -0,0 +1,51 @@ +const path = require("path"); + +module.exports = function (userOptions = {}) { + // Files need to be absolute paths. + // This only works if the file has no exports + // and only is imported for its side effects + const files = userOptions.files || []; + + if (files.length === 0) { + return { + name: "ignore", + }; + } + + return { + name: "ignore", + resolveId(importee, importer) { + // Only use ignore to intercept imports that we don't control + // inside node_module dependencies. + if ( + importee.endsWith("commonjsHelpers.js") || + importee.endsWith("?commonjs-proxy") || + !importer || + !importer.includes("/node_modules/") + ) { + return null; + } + let fullPath; + try { + fullPath = importee.startsWith(".") + ? path.resolve(importee, importer) + : require.resolve(importee); + } catch (err) { + console.error("Error in ignore plugin", { importee, importer }, err); + throw err; + } + + return files.some((toIgnorePath) => fullPath.startsWith(toIgnorePath)) + ? fullPath + : null; + }, + + load(id) { + return files.some((toIgnorePath) => id.startsWith(toIgnorePath)) + ? { + code: "", + } + : null; + }, + }; +}; diff --git a/build-scripts/rollup.js b/build-scripts/rollup.js index 7f7739990c..c27cee625a 100644 --- a/build-scripts/rollup.js +++ b/build-scripts/rollup.js @@ -11,8 +11,10 @@ const { terser } = require("rollup-plugin-terser"); const manifest = require("./rollup-plugins/manifest-plugin"); const worker = require("./rollup-plugins/worker-plugin"); const dontHashPlugin = require("./rollup-plugins/dont-hash-plugin"); +const ignore = require("./rollup-plugins/ignore-plugin"); const bundle = require("./bundle"); +const paths = require("./paths"); const extensions = [".js", ".ts"]; @@ -39,11 +41,18 @@ const createRollupConfig = ({ // Some entry points contain no JavaScript. This setting silences a warning about that. // https://rollupjs.org/guide/en/#preserveentrysignatures preserveEntrySignatures: false, - external: - bundle.ignorePackages({ latestBuild }) + - bundle.emptyPackages({ latestBuild }), plugins: [ - resolve({ extensions, preferBuiltins: false, browser: true }), + ignore({ + files: bundle + .ignorePackages({ latestBuild }) + .concat(bundle.emptyPackages({ latestBuild })), + }), + resolve({ + extensions, + preferBuiltins: false, + browser: true, + rootDir: paths.polymer_dir, + }), commonjs({ namedExports: { "js-yaml": ["safeDump", "safeLoad"], @@ -57,7 +66,7 @@ const createRollupConfig = ({ }), string({ // Import certain extensions as strings - include: ["**/*.css"], + include: [path.join(paths.polymer_dir, "node_modules/**/*.css")], }), replace( bundle.definedVars({ isProdBuild, latestBuild, defineOverlay }) From 1bc3b3befcb61fd719dfa4bc926529cfc0286ade Mon Sep 17 00:00:00 2001 From: HomeAssistant Azure Date: Sun, 24 May 2020 00:32:49 +0000 Subject: [PATCH 29/77] [ci skip] Translation update --- translations/frontend/ca.json | 13 +-- translations/frontend/en.json | 3 + translations/frontend/es.json | 5 +- translations/frontend/fi.json | 6 +- translations/frontend/fr.json | 3 + translations/frontend/hu.json | 3 + translations/frontend/is.json | 126 +++++++++++++++++++++++++++-- translations/frontend/ko.json | 7 +- translations/frontend/nb.json | 15 ++-- translations/frontend/pl.json | 71 ++++++++-------- translations/frontend/pt.json | 6 +- translations/frontend/ru.json | 9 ++- translations/frontend/sv.json | 12 ++- translations/frontend/zh-Hans.json | 3 + translations/frontend/zh-Hant.json | 3 + 15 files changed, 218 insertions(+), 67 deletions(-) diff --git a/translations/frontend/ca.json b/translations/frontend/ca.json index 9f5169b4ba..4008af994b 100644 --- a/translations/frontend/ca.json +++ b/translations/frontend/ca.json @@ -357,7 +357,7 @@ "cooling": "{name} refredant", "current_temperature": "Temperatura actual de {name}", "currently": "Actualment", - "fan_mode": "Mode ventilació", + "fan_mode": "Velocitat ventilador", "heating": "{name} escalfant", "high": "alt", "low": "baix", @@ -1297,7 +1297,7 @@ "show_readonly": "Mostra entitats de només lectura", "show_unavailable": "Mostra entitats no disponibles" }, - "header": "Registre d'entitats", + "header": "Entitats", "headers": { "entity_id": "ID de l'entitat", "integration": "Integració", @@ -1403,7 +1403,7 @@ "ignore": { "confirm_delete_ignore": "Això farà que quan la integració es descobreixi torni a aparèixer a les integracions descobertes. Pot ser que tardi una estona o es necessiti reiniciar.", "confirm_delete_ignore_title": "Vols deixar d'ignorar {name}?", - "confirm_ignore": "Estàs segur que no vols per a configurar aquesta integració? Pots desfer-ho fent clic a 'Mostra les integracions ignorades' al menú de la part superior dreta.", + "confirm_ignore": "Estàs segur que no vols configurar aquesta integració? Pots desfer-ho fent clic a 'Mostra les integracions ignorades' al menú de la part superior dreta.", "confirm_ignore_title": "Ignorar descobriment de {name}?", "hide_ignored": "Amaga les integracions ignorades", "ignore": "Ignora", @@ -1608,7 +1608,7 @@ "automation": "Actualitza automatitzacions", "core": "Recarrega ubicacions i automatitzacions", "group": "Actualitza grups", - "heading": "Torna a carregar la configuració", + "heading": "Tornant a carregar la configuració", "introduction": "Algunes parts de la configuració de Home Assistant es poden recarregar sense necessitat de reiniciar. Els botons de sota esborraran la configuració antiga i en carregaran la nova.", "person": "Actualitza persones", "scene": "Actualitza escenes", @@ -1789,7 +1789,7 @@ "required_error_msg": "Aquest camp és obligatori", "update": "Actualitza" }, - "edit_home_zone": "La ubicació de casa es pot canviar des de la configuració general.", + "edit_home_zone": "El radi de la zona principal (casa) encara no pot ser editat des del \"frontend\". Arrossega el mercador del mapa per moure la zona principal.", "edit_home_zone_narrow": "El radi de la zona principal (casa) encara no es pot editar des del \"frontend\". Sí que pots canviar-ne la ubicació des de la configuració general.", "go_to_core_config": "Anar a la configuració general?", "home_zone_core_config": "La ubicació de la zona principal (casa) és pot canviar des de la pàgina de configuració general. El radi d'aquesta zona encara no es pot editar des d'aquí. Vols anar a la configuració general?", @@ -2307,6 +2307,8 @@ "abort_intro": "S'ha avortat l'inici de sessió", "authorizing_client": "Esteu a punt de permetre l'accés a la vostra instància de Home Assistant al client {clientId}.", "form": { + "error": "Error: {error}", + "next": "Següent", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "Comença de nou", "unknown_error": "Alguna cosa no ha anat bé", "working": "Si us plau, espereu" }, diff --git a/translations/frontend/en.json b/translations/frontend/en.json index a0e54ab4a4..856e1aa879 100644 --- a/translations/frontend/en.json +++ b/translations/frontend/en.json @@ -2307,6 +2307,8 @@ "abort_intro": "Login aborted", "authorizing_client": "You're about to give {clientId} access to your Home Assistant instance.", "form": { + "error": "Error: {error}", + "next": "Next", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "Start over", "unknown_error": "Something went wrong", "working": "Please wait" }, diff --git a/translations/frontend/es.json b/translations/frontend/es.json index 02ef59e7ab..99905b8431 100644 --- a/translations/frontend/es.json +++ b/translations/frontend/es.json @@ -1215,7 +1215,7 @@ }, "warning": { "include_link": "incluir customize.yaml", - "include_sentence": "Parece que tu configuration.yaml no es correcto, debe", + "include_sentence": "Parece que tu configuration.yaml no es correcta, debe", "not_applied": "Los cambios realizados aquí se escriben en él, pero no se aplicarán después de una recarga de configuración a menos que la inclusión esté en su lugar." } }, @@ -2307,6 +2307,8 @@ "abort_intro": "Inicio de sesión cancelado", "authorizing_client": "Estás a punto de dar acceso a {clientId} a tu instancia de Home Assistant.", "form": { + "error": "Error: {error}", + "next": "Siguiente", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "Empezar de nuevo", "unknown_error": "Algo salió mal", "working": "Por favor, espere" }, diff --git a/translations/frontend/fi.json b/translations/frontend/fi.json index 4ef1c899e2..aff42fb830 100644 --- a/translations/frontend/fi.json +++ b/translations/frontend/fi.json @@ -1327,7 +1327,7 @@ "clear": "Tyhjennä", "filtering_by": "Suodatus" }, - "header": "Säädä Home Assistanttia", + "header": "Säädä Home Assistantia", "helpers": { "caption": "Auttajat", "description": "Elementit, jotka voivat auttaa rakentamaan automaatioita.", @@ -1399,7 +1399,7 @@ "description": "Hallitse liitettyjä laitteita ja palveluita", "details": "Integroinnin yksityiskohdat", "discovered": "Löydetty", - "home_assistant_website": "Home Assistant – sivusto", + "home_assistant_website": "Home Assistant -sivusto", "ignore": { "confirm_delete_ignore": "Tämä saa integroinnin näkymään löydetyissä integroinneissa uudelleen, kun se löydetään. Tämä saattaa vaatia uudelleenkäynnistyksen tai kestää jonkin aikaa.", "confirm_delete_ignore_title": "Lopeta integraation {name} ohittaminen?", @@ -2513,7 +2513,7 @@ "create_failed": "Käyttötunnussanoman luominen epäonnistui.", "created_at": "Luotu {date}", "delete_failed": "Käyttötunnussanoman poistaminen epäonnistui.", - "description": "Luo pitkäikäisiä käyttöoikeustunnuksia, jotta komentosarjasi voivat vuorovaikutttaa Home Assistantin kanssa. Jokainen tunnus on voimassa 10 vuotta luomisesta. Seuraavat pitkäikäiset käyttöoikeustunnukset ovat tällä hetkellä käytössä.", + "description": "Luo pitkäikäisiä käyttöoikeustunnuksia, jotta komentosarjasi voivat vuorovaikuttaa Home Assistantin kanssa. Jokainen tunnus on voimassa 10 vuotta luomisesta. Seuraavat pitkäikäiset käyttöoikeustunnukset ovat tällä hetkellä käytössä.", "empty_state": "Sinulla ei ole vielä pitkäaikaisia käyttötunnussanomia", "header": "Pitkäaikaiset käyttötunnussanomat", "last_used": "Viimeksi käytetty {date} sijainnista {location}", diff --git a/translations/frontend/fr.json b/translations/frontend/fr.json index e42a02a2a9..e85a48cbe9 100644 --- a/translations/frontend/fr.json +++ b/translations/frontend/fr.json @@ -2307,6 +2307,8 @@ "abort_intro": "Connexion interrompue", "authorizing_client": "Vous êtes sur le point de donner accès à {clientId} à votre instance de Home Assistant.", "form": { + "error": "Erreur: {error}", + "next": "Suivant", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "Recommencer", "unknown_error": "Quelque chose a mal tourné", "working": "Veuillez patienter" }, diff --git a/translations/frontend/hu.json b/translations/frontend/hu.json index 70d247887d..004adca90c 100644 --- a/translations/frontend/hu.json +++ b/translations/frontend/hu.json @@ -2307,6 +2307,8 @@ "abort_intro": "Bejelentkezés megszakítva", "authorizing_client": "Éppen a {clientId} számára készülsz hozzáférést biztosítani a Home Assistant példányodhoz.", "form": { + "error": "Hiba: {error}", + "next": "Tovább", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "Újrakezdés", "unknown_error": "Valami hiba történt", "working": "Kérlek várj" }, diff --git a/translations/frontend/is.json b/translations/frontend/is.json index 949b7ef0c9..a11c207ebf 100644 --- a/translations/frontend/is.json +++ b/translations/frontend/is.json @@ -420,6 +420,7 @@ "attributes": { "air_pressure": "Loftþrýstingur", "humidity": "Rakastig", + "precipitation": "Úrkoma", "temperature": "Hitastig", "visibility": "Skyggni", "wind_speed": "Vindhraði" @@ -446,17 +447,24 @@ } }, "common": { + "and": "og", "cancel": "Hætta við", "close": "Loka", + "delete": "Eyða", "loading": "Hleð", + "next": "Næsta", "no": "Nei", + "previous": "Fyrri", + "refresh": "Endurnýja", "save": "Vista", + "undo": "Afturkalla", "yes": "Já" }, "components": { "area-picker": { "add_dialog": { "add": "Bæta við", + "failed_create_area": "Ekki tókst að stofna svæði.", "name": "Nafn" }, "clear": "Hreinsa" @@ -477,6 +485,7 @@ "no_history_found": "Engin stöðusaga fannst." }, "related-items": { + "area": "Svæði", "device": "Tæki", "integration": "Samþætting" }, @@ -506,12 +515,16 @@ "dismiss": "Vísa frá", "editor": { "delete": "Eyða", + "icon": "Yfirskrifa táknmynd", "update": "Uppfæra" - } + }, + "related": "Tengt", + "settings": "Stillingar" }, "generic": { "cancel": "Hætta við", "close": "loka", + "default_confirmation_title": "Ertu viss?", "ok": "Í lagi" }, "helper_settings": { @@ -521,8 +534,12 @@ }, "input_datetime": { "date": "Dagsetning", + "datetime": "Dagsetning og tími", "time": "Tími" }, + "input_number": { + "unit_of_measurement": "Mælieining" + }, "input_select": { "add": "Bæta við" }, @@ -543,8 +560,14 @@ }, "updater": { "title": "Uppfærslu leiðbeiningar" + }, + "vacuum": { + "status": "Staða" } }, + "mqtt_device_debug_info": { + "entities": "Einingar" + }, "options_flow": { "form": { "header": "Valkostir" @@ -552,6 +575,7 @@ }, "voice_command": { "error": "Úbbs, villa kom upp", + "found": "Ég fann eftirfarandi fyrir þig:", "how_can_i_help": "Hvernig get ég aðstoðað?" }, "zha_device_info": { @@ -597,9 +621,16 @@ "service_call_failed": "Ekki tókst að kalla á þjónustu {service}." }, "panel": { + "calendar": { + "my_calendars": "Dagatölin mín", + "today": "Í dag" + }, "config": { "areas": { "caption": "Svæðaskrá", + "data_table": { + "area": "Svæði" + }, "description": "Yfirlit yfir öll svæði á heimilinu þínu.", "editor": { "create": "STOFNA", @@ -680,6 +711,9 @@ }, "label": "Tæki" }, + "not": { + "label": "Ekki" + }, "numeric_state": { "above": "Yfir", "below": "Undir", @@ -723,6 +757,7 @@ "label": "Lýsing", "placeholder": "Valfrjáls lýsing" }, + "enable_disable": "Virkja/slökkva á sjálfvirkni", "introduction": "Notaðu sjálfvirkni til að glæða húsið þitt lífi", "load_error_not_editable": "Eingöngu er hægt að breyta sjálfvirkni í automations.yaml", "load_error_unknown": "Villa kom upp við að hlaða inn sjálfvirkni ({err_no}).", @@ -820,6 +855,9 @@ "delete_automation": "Eyða sjálfvirkni", "edit_automation": "Breyta sjálfvirkni", "header": "Sjálfvirkniritill", + "headers": { + "name": "Nafn" + }, "learn_more": "Læra meira um sjálfvirkni", "no_automations": "Við fundum ekki neinar sjálfvirkni-skilgreiningar sem hægt er að breyta", "only_editable": "Eingöngu er hægt að breyta sjálfvirkni sem skilgreind er í automations.yaml", @@ -916,7 +954,9 @@ "edit_requires_storage": "Ritill er óvirkur af því að stillingar eru vistaðar í configuration.yaml.", "elevation": "Hækkun", "elevation_meters": "metrar", + "external_url": "Ytri vefslóð", "imperial_example": "Fahrenheit, pund", + "internal_url": "Innri vefslóð", "latitude": "Breiddargráða", "location_name": "Nafnið á Home Assistant uppsetningunni", "longitude": "Lengdargráða", @@ -952,6 +992,7 @@ } }, "caption": "Tæki", + "confirm_delete": "Ertu viss um að þú viljir eyða þessu tæki?", "data_table": { "area": "Svæði", "battery": "Rafhlaða", @@ -962,6 +1003,7 @@ }, "delete": "Eyða", "description": "Stjórna tengdum tækjum", + "device_info": "Upplýsingar um tæki", "device_not_found": "Tæki fannst ekki.", "entities": { "entities": "Einingar" @@ -972,8 +1014,13 @@ "scenes": "Senur" }, "scenes": "Senur", + "script": { + "scripts": "Skriftur" + }, + "scripts": "Skriftur", "unknown_error": "Óþekkt villa", - "unnamed_device": "Ónefnt tæki" + "unnamed_device": "Ónefnt tæki", + "update": "Uppfæra" }, "entities": { "caption": "Einingarskrá", @@ -990,6 +1037,7 @@ }, "header": "Einingarskrá", "headers": { + "integration": "Samþætting", "name": "Nafn", "status": "Staða" }, @@ -1000,10 +1048,14 @@ "status": { "disabled": "Afvirkjað", "ok": "í lagi", + "readonly": "Ritvarið", "unavailable": "Ekki tiltækt" } } }, + "filtering": { + "clear": "Hreinsa" + }, "header": "Stilla af Home Assistant", "helpers": { "dialog": { @@ -1016,13 +1068,17 @@ } }, "types": { + "input_datetime": "Dagsetning og/eða tími", + "input_number": "Númer", "input_text": "Texti" } }, "integrations": { + "add_integration": "Bæta við samþættingu", "caption": "Samþættingar", "config_entry": { "area": "Í {area}", + "delete": "Eyða", "delete_button": "Eyða {integration}", "delete_confirm": "Ertu viss um að þú viljir eyða þessari samþættingu?", "device_unavailable": "Tæki ekki tiltækt", @@ -1033,6 +1089,7 @@ "no_area": "Ekkert svæði", "no_device": "Einingar án tækja", "no_devices": "Þessi samþætting hefur engin tæki.", + "rename": "Endurnefna", "restart_confirm": "Endurræsa Home Assitant til að klára að fjarlægja þessa samþættingu", "settings_button": "Breyta stillingum fyrir {integration}" }, @@ -1057,12 +1114,16 @@ "ignored": "Hunsað", "show_ignored": "Sýna hunsaðar samþættingar" }, + "integration": "samþætting", + "integration_not_found": "Samþætting fannst ekki.", "new": "Setja upp nýja samþættingu", "none": "Ekkert skilgreint sem stendur" }, "introduction": "Hér er mögulegt að stilla af íhluti og Home Assistant. Því miður er ekki hægt að breyta öllu í gegnum viðmótið ennþá, en við erum að vinna í því.", "lovelace": { + "caption": "Lovelace mælaborð", "dashboards": { + "caption": "Mælaborð", "conf_mode": { "yaml": "YAML skrá" }, @@ -1070,14 +1131,20 @@ "create": "Stofna", "delete": "Eyða", "dismiss": "Loka", + "edit_dashboard": "Breyta mælaborði", "icon": "Táknmynd", + "new_dashboard": "bæta við nýju mælaborði", + "show_sidebar": "Sýna í hliðarstiku", "title": "Titill", - "update": "Uppfæra" + "update": "Uppfæra", + "url": "Slóð" }, "picker": { + "add_dashboard": "Bættu við mælaborði", "headers": { "default": "Sjálfgefið", "filename": "Skráarnafn", + "sidebar": "Sýna í hliðarstiku", "title": "Titill" }, "open": "Opna" @@ -1088,12 +1155,21 @@ "create": "Stofna", "delete": "Eyða", "dismiss": "Loka", - "update": "Uppfæra" + "update": "Uppfæra", + "url": "Slóð", + "warning_header": "Farðu varlega!" }, "picker": { "headers": { - "type": "Gerð" + "type": "Gerð", + "url": "Slóð" } + }, + "types": { + "css": "Stílsnið", + "html": "HTML (úrelt)", + "js": "JavaScript skrá (úrelt)", + "module": "JavaScript eining" } } }, @@ -1116,7 +1192,8 @@ "name_error_msg": "Nafn er skilyrt", "new_person": "Ný persóna", "update": "Uppfæra" - } + }, + "no_persons_created_yet": "Það lítur út fyrir að þú hafir ekki búið til neina einstaklinga ennþá." }, "scene": { "activated": "Virkjuð sena {name}.", @@ -1144,6 +1221,9 @@ "delete_scene": "Eyða senu", "edit_scene": "Breyta senu", "header": "Senuritill", + "headers": { + "name": "Nafn" + }, "learn_more": "Læra meira um senur", "only_editable": "Það er eingöngu hægt að breyta senum skilgreindum í scenes.yaml.", "pick_scene": "Veldu senu til að breyta", @@ -1158,6 +1238,9 @@ "link_available_actions": "Læra meira um tiltækar aðgerðir." }, "picker": { + "headers": { + "name": "Nafn" + }, "learn_more": "Læra meira um skriftur" } }, @@ -1204,14 +1287,17 @@ "editor": { "activate_user": "Virkja notanda", "active": "Virkur", + "admin": "Stjórnandi", "caption": "Skoða notanda", "change_password": "Breyta lykilorði", "deactivate_user": "Gera notanda óvirkan", "delete_user": "Eyða notanda", "group": "Hópur", "id": "ID", + "name": "Nafn", "owner": "Eigandi", - "unnamed_user": "Ónefndur notandi" + "unnamed_user": "Ónefndur notandi", + "update_user": "Uppfæra" } }, "zha": { @@ -1257,6 +1343,7 @@ "create": "Stofna", "delete": "Eyða", "icon": "Táknmynd", + "icon_error_msg": "Táknmyndin ætti að vera á forminu forskeyti:nafn_a_taknmynd, til dæmis: mdi:home", "latitude": "Breiddargráða", "longitude": "Lengdargráða", "name": "Nafn", @@ -1306,7 +1393,9 @@ "title": "Viðburðir" }, "info": { + "documentation": "Skjölun", "icons_by": "Smátákn eftir", + "integrations": "Samþættingar", "title": "Upplýsingar" }, "logs": { @@ -1388,6 +1477,9 @@ "entity-filter": { "name": "Eininga sía" }, + "entity": { + "name": "Eining" + }, "gauge": { "name": "Mælir", "severity": { @@ -1410,6 +1502,7 @@ "maximum": "Hámark", "minimum": "Lágmark", "name": "Nafn", + "no_theme": "Ekkert þema", "show_icon": "Birta táknmynd?", "show_name": "Birta nafn?", "show_state": "Birta stöðu?", @@ -1437,6 +1530,7 @@ "map": { "dark_mode": "Dökkur hamur?", "default_zoom": "Sjálfgefinn aðdráttur", + "hours_to_show": "Klukkutímar sem á að birta", "name": "Kort" }, "markdown": { @@ -1460,6 +1554,10 @@ }, "vertical-stack": { "name": "Lóðréttur stafli" + }, + "weather-forecast": { + "name": "Veðurspá", + "show_forecast": "Sýna veðurspá" } }, "edit_card": { @@ -1481,7 +1579,9 @@ "add": "Bæta við sýn", "delete": "Eyða sýn", "edit": "Breyta sýn", - "header": "Skoða stillingar" + "header": "Skoða stillingar", + "tab_settings": "Stillingar", + "tab_visibility": "Sýnileiki" }, "header": "Breyta notendaviðmóti", "menu": { @@ -1519,6 +1619,7 @@ "reload_lovelace": "Endurhlaða Lovelace", "unused_entities": { "domain": "Lén", + "entity": "Eining", "last_changed": "Síðast breytt" }, "warning": { @@ -1535,6 +1636,7 @@ "abort_intro": "Hætt var við innskráningu", "authorizing_client": "Þú ert að fara að veita {clientId} aðgang að Home Assistant uppsetningunni.", "form": { + "error": "Villa: {error}", "providers": { "command_line": { "abort": { @@ -1616,6 +1718,7 @@ } } }, + "start_over": "Byrja upp á nýtt", "unknown_error": "Eitthvað fór úrskeiðis", "working": "Vinsamlegast bíðið" }, @@ -1696,6 +1799,9 @@ } }, "profile": { + "advanced_mode": { + "link_promo": "Læra meira" + }, "change_password": { "confirm_new_password": "Staðfesta nýtt lykilorð", "current_password": "Núverandi lykilorð", @@ -1705,6 +1811,10 @@ "submit": "Senda" }, "current_user": "Þú ert skráð(ur) inn sem {fullName}.", + "dashboard": { + "dropdown_label": "Mælaborð", + "header": "Mælaborð" + }, "force_narrow": { "description": "Þetta mun fela hliðarstikuna með sambærilegum hætti og á snjalltækum.", "header": "Alltaf fela hliðarstikuna" diff --git a/translations/frontend/ko.json b/translations/frontend/ko.json index 30ec48a1a7..3e3afd98e2 100644 --- a/translations/frontend/ko.json +++ b/translations/frontend/ko.json @@ -2307,6 +2307,8 @@ "abort_intro": "로그인이 중단되었습니다", "authorizing_client": "{clientId} 에 Home Assistant 구성요소에 대한 액세스 권한을 부여하려고 합니다.", "form": { + "error": "오류: {error}", + "next": "다음", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "다시 시작", "unknown_error": "문제가 발생했습니다", "working": "잠시 기다려주세요" }, @@ -2517,7 +2520,7 @@ "empty_state": "장기 액세스 토큰이 없습니다.", "header": "장기 액세스 토큰", "last_used": "{date} 에 {location} 에서 마지막으로 사용됨", - "learn_auth_requests": "인증 요청을 생성하는 방법에 대해 알아 보세요.", + "learn_auth_requests": "인증 요청을 생성하는 방법에 대해 알아보세요.", "not_used": "사용된 적이 없음", "prompt_copy_token": "Ctrl + C 를 눌러 액세스 토큰을 복사하세요. 이 안내는 다시 표시되지 않습니다.", "prompt_name": "토큰 이름을 지어주세요." @@ -2548,7 +2551,7 @@ "created_at": "{date} 에 생성 됨", "current_token_tooltip": "현재 리프레시 토큰을 삭제할 수 없음", "delete_failed": "리프레시 토큰을 삭제할 수 없습니다.", - "description": "각 리프레시 토큰은 로그인 세션을 나타냅니다. 로그아웃을 클릭하면 리프레시 토큰은 자동으로 제거됩니다. 다음의 리프레시 토큰이 현재 접속한 계정에 대해 활성화 되어 있습니다.", + "description": "각 리프레시 토큰은 로그인 세션을 나타냅니다. 로그아웃을 클릭하면 리프레시 토큰은 자동으로 제거됩니다. 다음의 리프레시 토큰이 현재 접속한 계정에 대해 활성화되어 있습니다.", "header": "리프레시 토큰", "last_used": "{date} 에 {location} 에서 마지막으로 사용됨", "not_used": "사용된 적이 없음", diff --git a/translations/frontend/nb.json b/translations/frontend/nb.json index 4eb76201fb..5ae5dbfa72 100644 --- a/translations/frontend/nb.json +++ b/translations/frontend/nb.json @@ -1254,7 +1254,7 @@ "device_not_found": "Enhet ikke funnet", "entities": { "add_entities_lovelace": "Legg til i Lovelace", - "disabled_entities": "+{count} {antall, flertall,\n én {deaktivert enhet}\n andre {deaktiverte enheter}\n}", + "disabled_entities": "+{count} {count, plural,\n one {deaktivert entitet}\n other {deaktiverte entiteter}\n}", "entities": "Enheter", "hide_disabled": "Skjul deaktiverte", "none": "Denne enheten har ingen enheter" @@ -1685,9 +1685,9 @@ "attributes_of_cluster": "Attributter for den valgte klyngen", "get_zigbee_attribute": "Hent ZigBee-attributt", "header": "Klyngeattributter", - "help_attribute_dropdown": "Velg en attributt for å se eller angi verdien.", + "help_attribute_dropdown": "Velg et attributt for å se eller angi verdien.", "help_get_zigbee_attribute": "Hent verdien for det valgte attributtet.", - "help_set_zigbee_attribute": "Angi attributtverdi for klusteret på den angitte entiteten.", + "help_set_zigbee_attribute": "Angi attributtverdi for den spesifiserte klyngen på den angitte entiteten.", "introduction": "Se og rediger klyngeattributter.", "set_zigbee_attribute": "Angi Zigbee-attributt" }, @@ -1701,7 +1701,7 @@ "clusters": { "header": "Klynger", "help_cluster_dropdown": "Velg en klynge for å vise attributter og kommandoer.", - "introduction": "Klynger er byggesteinene for ZigBee-funksjonalitet. De skiller funksjonalitet i logiske enheter. Det finnes klient-og server typer, og som består av attributter og kommandoer." + "introduction": "Klynger er byggesteinene for ZigBee-funksjonalitet. De skiller funksjonalitet i logiske enheter. Det finnes klient og server typer som består av attributter og kommandoer." }, "common": { "add_devices": "Legg til enheter", @@ -2060,7 +2060,7 @@ }, "generic": { "aspect_ratio": "Størrelsesforholdet", - "attribute": "Attributtet", + "attribute": "Attributt", "camera_image": "Kameraentitet", "camera_view": "Kameravisning", "double_tap_action": "Dobbeltklikk Handling", @@ -2078,7 +2078,7 @@ "name": "Navn", "no_theme": "Ingen tema", "refresh_interval": "Oppdateringsintervall", - "secondary_info_attribute": "Sekundær attribute info", + "secondary_info_attribute": "Sekundær informasjonsattributt", "show_icon": "Vis ikon?", "show_name": "Vis navn?", "show_state": "Vis tilstand?", @@ -2307,6 +2307,8 @@ "abort_intro": "Innlogging avbrutt", "authorizing_client": "Du er i ferd med å gi {clientId} tilgang til din Home Assistant", "form": { + "error": "Feil: {error}", + "next": "Neste", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "Start på nytt", "unknown_error": "Noe gikk galt", "working": "Vennligst vent" }, diff --git a/translations/frontend/pl.json b/translations/frontend/pl.json index b39d62dc17..8f6901a562 100644 --- a/translations/frontend/pl.json +++ b/translations/frontend/pl.json @@ -563,7 +563,7 @@ "confirm_delete": "Czy na pewno chcesz usunąć ten wpis?", "delete": "USUŃ", "enabled_cause": "Wyłączone przez {cause}.", - "enabled_description": "Wyłączone encje nie zostaną dodane do Home Assistant'a.", + "enabled_description": "Wyłączone encje nie zostaną dodane do Home Assistanta.", "enabled_label": "Włącz encję", "entity_id": "Identyfikator encji", "icon": "Nadpisanie ikony", @@ -786,7 +786,7 @@ "delete_confirm": "Czy na pewno chcesz to usunąć?", "duplicate": "Duplikuj", "header": "Akcje", - "introduction": "Akcje są wykonywane przez Home Assistant'a po uruchomieniu automatyzacji.", + "introduction": "Akcje są wykonywane przez Home Assistanta po uruchomieniu automatyzacji.", "learn_more": "Dowiedz się więcej o akcjach", "name": "Akcja", "type_select": "Typ akcji", @@ -1017,9 +1017,9 @@ "config_documentation": "Dokumentacja konfiguracji", "disable": "Wyłącz", "enable": "Włącz", - "enable_ha_skill": "Włącz skill Home Assistant'a dla Alexy", + "enable_ha_skill": "Włącz skill Home Assistanta dla Alexy", "enable_state_reporting": "Włącz raportowanie stanów", - "info": "Dzięki integracji z Alexą dla Chmury Home Assistant będzie możliwe kontrolowanie wszystkich urządzeń Home Assistant'a za pośrednictwem dowolnego urządzenia obsługującego Amazon Alexa.", + "info": "Dzięki integracji z Alexą dla Chmury Home Assistant będzie możliwe kontrolowanie wszystkich urządzeń Home Assistanta za pośrednictwem dowolnego urządzenia obsługującego Amazon Alexa.", "info_state_reporting": "Jeśli włączysz raportowanie stanów, Home Assistant wyśle wszystkie zmiany stanu udostępnionych encji na serwery Amazona. Dzięki temu zawsze możesz zobaczyć najnowsze stany w aplikacji Alexa i używać zmian stanów do tworzenia rutyn.", "manage_entities": "Zarządzanie encjami", "state_reporting_error": "Nie można przesłać stanu {enable_disable}.", @@ -1033,12 +1033,12 @@ "google": { "config_documentation": "Dokumentacja konfiguracji", "devices_pin": "Kod PIN urządzeń bezpieczeństwa", - "enable_ha_skill": "Włącz skill Home Assistant'a dla Asystenta Google", + "enable_ha_skill": "Włącz skill Home Assistanta dla Asystenta Google", "enable_state_reporting": "Włącz raportowanie stanów", "enter_pin_error": "Nie można zapisać kodu PIN:", "enter_pin_hint": "Wprowadź kod PIN, aby korzystać z urządzeń bezpieczeństwa", "enter_pin_info": "Wpisz kod PIN, aby wejść w interakcję z urządzeniami bezpieczeństwa. Urządzeniami bezpieczeństwa są drzwi, drzwi garażowe i zamki. Podczas interakcji z takimi urządzeniami za pośrednictwem Asystenta Google zostaniesz poproszony o wprowadzenie tego kodu PIN.", - "info": "Dzięki integracji z Asystentem Google dla Chmury Home Assistant będzie możliwe kontrolowanie wszystkich urządzeń Home Assistant'a za pośrednictwem dowolnego urządzenia obsługującego Asystenta Google.", + "info": "Dzięki integracji z Asystentem Google dla Chmury Home Assistant będzie możliwe kontrolowanie wszystkich urządzeń Home Assistanta za pośrednictwem dowolnego urządzenia obsługującego Asystenta Google.", "info_state_reporting": "Jeśli włączysz raportowanie stanów, Home Assistant wyśle wszystkie zmiany stanu udostępnionych encji na serwery Google. Dzięki temu zawsze możesz zobaczyć najnowsze stany w aplikacji Google.", "manage_entities": "Zarządzanie encjami", "security_devices": "Urządzenia bezpieczeństwa", @@ -1056,7 +1056,7 @@ "remote": { "access_is_being_prepared": "Trwa przygotowywanie dostępu zdalnego. Powiadomimy Cię, gdy będzie gotowy.", "certificate_info": "Informacje o certyfikacie", - "info": "Chmura Home Assistant umożliwia bezpieczny zdalny dostęp do instancji Home Assistant'a z dala od domu.", + "info": "Chmura Home Assistant umożliwia bezpieczny zdalny dostęp do instancji Home Assistanta z dala od domu.", "instance_is_available": "Twoja instancja jest dostępna pod adresem", "instance_will_be_available": "Twoja instancja będzie dostępna pod adresem", "link_learn_how_it_works": "Dowiedz się, jak to działa", @@ -1067,14 +1067,14 @@ "webhooks": { "disable_hook_error_msg": "Nie udało się wyłączyć webhook:", "info": "Wszystko, co jest skonfigurowane do działania poprzez webhook, może otrzymać publicznie dostępny adres URL, aby umożliwić wysyłanie danych do Home Assistant z dowolnego miejsca, bez narażania instancji na publiczny dostęp z Internetu.", - "link_learn_more": "Dowiedz się więcej o tworzeniu automatyzacji opartych na webhook'ach.", + "link_learn_more": "Dowiedz się więcej o tworzeniu automatyzacji opartych na webhookach.", "loading": "Wczytywanie...", "manage": "Zarządzanie", - "no_hooks_yet": "Wygląda na to, że nie ma jeszcze żadnych webhook'ów. Rozpocznij od skonfigurowania ", + "no_hooks_yet": "Wygląda na to, że nie ma jeszcze żadnych webhooków. Rozpocznij od skonfigurowania ", "no_hooks_yet_link_automation": "Automatyzacja webhook", - "no_hooks_yet_link_integration": "Integracja oparta na webhook'ach", + "no_hooks_yet_link_integration": "Integracja oparta na webhookach", "no_hooks_yet2": " lub tworząc ", - "title": "Webhook'i" + "title": "Webhooki" } }, "alexa": { @@ -1085,7 +1085,7 @@ "title": "Alexa" }, "caption": "Chmura Home Assistant", - "description_features": "Sterowanie spoza domu, integracja z Alexą i Google Assistant'em.", + "description_features": "Sterowanie spoza domu, integracja z Alexą i Google Assistantem.", "description_login": "Zalogowany jako {email}", "description_not_login": "Nie zalogowany", "dialog_certificate": { @@ -1100,7 +1100,7 @@ "close": "Zamknij", "confirm_disable": "Czy na pewno chcesz wyłączyć ten webhook?", "copied_to_clipboard": "Skopiowano do schowka", - "info_disable_webhook": "Jeśli nie chcesz już używać tego webhook'a, możesz", + "info_disable_webhook": "Jeśli nie chcesz już używać tego webhooka, możesz", "link_disable_webhook": "wyłączyć go", "managed_by_integration": "Ten webhook jest zarządzany przez integrację i nie można go wyłączyć.", "view_documentation": "Dokumentacja", @@ -1150,8 +1150,8 @@ "email_error_msg": "Niepoprawny adres e-mail", "feature_amazon_alexa": "integracja z Amazon Alexa", "feature_google_home": "integracja z Google Assistant", - "feature_remote_control": "kontrola Home Assistant'em z dala od domu", - "feature_webhook_apps": "prosta integracja z aplikacjami opartymi na webhook'ach, takimi jak OwnTracks", + "feature_remote_control": "kontrola Home Assistantem z dala od domu", + "feature_webhook_apps": "prosta integracja z aplikacjami opartymi na webhookach, takimi jak OwnTracks", "headline": "Rozpocznij darmowy okres próbny", "information": "Utwórz konto, aby rozpocząć bezpłatny miesięczny okres próbny Chmury Home Assistant. Informacje o środkach płatności nie są konieczne.", "information2": "Wersja próbna zapewni Ci dostęp do wszystkich zalet Chmury Home Assistant, w tym:", @@ -1174,7 +1174,7 @@ }, "core": { "caption": "Ogólne", - "description": "Zmień podstawowe opcje Home Assistant'a", + "description": "Zmień podstawowe opcje Home Assistanta", "section": { "core": { "core_config": { @@ -1283,7 +1283,7 @@ "picker": { "disable_selected": { "button": "Wyłącz wybrane", - "confirm_text": "Wyłączone encje nie zostaną dodane do Home Assistant'a.", + "confirm_text": "Wyłączone encje nie zostaną dodane do Home Assistanta.", "confirm_title": "Czy chcesz wyłączyć {number} encj(ę/e/i)?" }, "enable_selected": { @@ -1308,7 +1308,7 @@ "introduction2": "Użyj rejestru encji, aby nadpisać jej nazwę, zmienić jej identyfikator lub usunąć ją z Home Assistant'a. Uwaga: usunięcie wpisu rejestru encji nie spowoduje usunięcia encji. Aby to zrobić, kliknij poniższy link i usuń integracje encji.", "remove_selected": { "button": "Usuń zaznaczone", - "confirm_partly_text": "Można usunąć tylko {removable} z wybranych {selected} encji. Encje można usunąć tylko wtedy, gdy integracja wspiera taka możliwość. Czasami trzeba ponownie uruchomić Home Assistant'a, zanim będzie można usunąć encje usuniętej integracji. Czy na pewno chcesz usunąć usuwalne encje?", + "confirm_partly_text": "Można usunąć tylko {removable} z wybranych {selected} encji. Encje można usunąć tylko wtedy, gdy integracja wspiera taka możliwość. Czasami trzeba ponownie uruchomić Home Assistanta, zanim będzie można usunąć encje usuniętej integracji. Czy na pewno chcesz usunąć usuwalne encje?", "confirm_partly_title": "Tylko {number} wybrane encje można usunąć.", "confirm_text": "Encje mogą zostać usunięte tylko wtedy, gdy ich integracja na to zezwala.", "confirm_title": "Czy chcesz usunąć {number} encj(ę/e/i)?" @@ -1327,7 +1327,7 @@ "clear": "Wyczyść", "filtering_by": "Filtrowanie przez" }, - "header": "Konfiguruj Home Assistant'a", + "header": "Konfiguruj Home Assistanta", "helpers": { "caption": "Pomocnicy", "description": "Elementy, które mogą pomóc w tworzeniu automatyzacji", @@ -1373,7 +1373,7 @@ "no_devices": "Ta integracja nie ma żadnych urządzeń.", "options": "Opcje", "rename": "Zmień nazwę", - "restart_confirm": "Zrestartuj Home Assistant'a, aby zakończyć usuwanie tej integracji", + "restart_confirm": "Zrestartuj Home Assistanta, aby zakończyć usuwanie tej integracji", "settings_button": "Edytuj ustawienia dla {integration}", "system_options": "Opcje systemowe", "system_options_button": "Opcje systemowe dla {integration}", @@ -1399,7 +1399,7 @@ "description": "Zarządzaj integracjami", "details": "Szczegóły integracji", "discovered": "Wykryte", - "home_assistant_website": "Home Assistant'a", + "home_assistant_website": "Home Assistanta", "ignore": { "confirm_delete_ignore": "Spowoduje to, że integracja pojawi się ponownie w wykrytych integracjach. Może to wymagać ponownego uruchomienia lub czasu.", "confirm_delete_ignore_title": "Wyłączenie ignorowania {name}", @@ -1423,12 +1423,12 @@ "rename_dialog": "Edytuj nazwę tego wpisu konfiguracji", "rename_input_label": "Nazwa wpisu" }, - "introduction": "Tutaj możesz skonfigurować Home Assistant'a i jego komponenty. Nie wszystkie opcje można konfigurować z interfejsu użytkownika, ale pracujemy nad tym.", + "introduction": "Tutaj możesz skonfigurować Home Assistanta i jego komponenty. Nie wszystkie opcje można konfigurować z interfejsu użytkownika, ale pracujemy nad tym.", "lovelace": { "caption": "Dashboardy", "dashboards": { "cant_edit_default": "Standardowego dashboardu Lovelace nie można edytować za pomocą interfejsu użytkownika. Możesz go ukryć, ustawiając jako domyślny inny dashboard.", - "cant_edit_yaml": "Dashboard'y zdefiniowane w plikach YAML nie mogą być edytowane z poziomu interfejsu użytkownika. Zmień je w pliku configuration.yaml.", + "cant_edit_yaml": "Dashboardy zdefiniowane w plikach YAML nie mogą być edytowane z poziomu interfejsu użytkownika. Zmień je w pliku configuration.yaml.", "caption": "Dashboardy", "conf_mode": { "storage": "Konfigurowalny z interfejsu użytkownika", @@ -1602,7 +1602,7 @@ }, "server_control": { "caption": "Kontrola serwera", - "description": "Uruchom ponownie i zatrzymaj serwer Home Assistant'a", + "description": "Uruchom ponownie i zatrzymaj serwer Home Assistanta", "section": { "reloading": { "automation": "Automatyzacje", @@ -1616,10 +1616,10 @@ "zone": "Strefy" }, "server_management": { - "confirm_restart": "Czy na pewno chcesz ponownie uruchomić Home Assistant'a?", - "confirm_stop": "Czy na pewno chcesz zatrzymać Home Assistant'a?", + "confirm_restart": "Czy na pewno chcesz ponownie uruchomić Home Assistanta?", + "confirm_stop": "Czy na pewno chcesz zatrzymać Home Assistanta?", "heading": "Zarządzanie serwerem", - "introduction": "Kontroluj serwer Home Assistant'a.", + "introduction": "Kontroluj serwer Home Assistanta.", "restart": "Uruchom ponownie", "stop": "Zatrzymaj" }, @@ -1898,7 +1898,7 @@ "logs": { "clear": "Wyczyść", "details": "Szczegóły loga ({level})", - "load_full_log": "Załaduj cały log Home Assistant'a", + "load_full_log": "Załaduj cały log Home Assistanta", "loading_log": "Ładowanie loga błędów…", "multiple_messages": "wiadomość pojawiła się po raz pierwszy o godzinie {time} i powtarzała się {counter} razy", "no_errors": "Nie zgłoszono żadnych błędów.", @@ -1937,7 +1937,7 @@ "alert_entity_field": "Encja jest polem obowiązkowym", "attributes": "Atrybuty", "current_entities": "Bieżące encje", - "description1": "Ustaw stany encji urządzeń Home Assistant'a.", + "description1": "Ustaw stany encji urządzeń Home Assistanta.", "description2": "Nie wpłynie to na rzeczywiste urządzenia.", "entity": "Encja", "filter_attributes": "filtr atrybutów", @@ -1951,10 +1951,10 @@ "title": "Stany" }, "templates": { - "description": "Szablony są renderowane przy użyciu silnika szablonów Jinja2 z kilkoma specyficznymi rozszerzeniami Home Assistant'a.", + "description": "Szablony są renderowane przy użyciu silnika szablonów Jinja2 z kilkoma specyficznymi rozszerzeniami Home Assistanta.", "editor": "Edytor szablonów", "jinja_documentation": "Dokumentacja szablonów Jinja2", - "template_extensions": "Rozszerzenia szablonów Home Assistant'a", + "template_extensions": "Rozszerzenia szablonów Home Assistanta", "title": "Szablon", "unknown_error_template": "Nieznany błąd podczas renderowania szablonu." } @@ -2305,8 +2305,10 @@ }, "page-authorize": { "abort_intro": "Logowanie przerwane", - "authorizing_client": "Uzyskujesz dostęp do instancji Home Assistant'a w lokalizacji {clientId}.", + "authorizing_client": "Uzyskujesz dostęp do instancji Home Assistanta w lokalizacji {clientId}.", "form": { + "error": "Błąd: {error}", + "next": "Dalej", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "Zacznij od nowa", "unknown_error": "Coś poszło nie tak", "working": "Proszę czekać" }, @@ -2476,7 +2479,7 @@ }, "profile": { "advanced_mode": { - "description": "Home Assistant domyślnie ukrywa zaawansowane funkcje i opcje. Możesz włączyć do nich dostęp za pomocą tej opcji. Jest to ustawienie przyporządkowane do użytkownika i nie wpływa na pozostałych użytkowników korzystających z Home Assistant'a.", + "description": "Home Assistant domyślnie ukrywa zaawansowane funkcje i opcje. Możesz włączyć do nich dostęp za pomocą tej opcji. Jest to ustawienie przyporządkowane do użytkownika i nie wpływa na pozostałych użytkowników korzystających z Home Assistanta.", "link_promo": "Dowiedz się więcej", "title": "Tryb zaawansowany" }, @@ -2513,7 +2516,7 @@ "create_failed": "Nie udało się utworzyć tokena.", "created_at": "Utworzony {date}", "delete_failed": "Nie udało się usunąć tokena.", - "description": "Długoterminowe tokeny dostępu umożliwiają skryptom interakcję z Home Assistant'em. Każdy token będzie ważny przez 10 lat od utworzenia. Następujące tokeny są obecnie aktywne.", + "description": "Długoterminowe tokeny dostępu umożliwiają skryptom interakcję z Home Assistantem. Każdy token będzie ważny przez 10 lat od utworzenia. Następujące tokeny są obecnie aktywne.", "empty_state": "Nie masz jeszcze żadnych tokenów.", "header": "Tokeny dostępu", "last_used": "Ostatnio używany {date} z {location}", diff --git a/translations/frontend/pt.json b/translations/frontend/pt.json index 414191f2d8..41e640f80c 100644 --- a/translations/frontend/pt.json +++ b/translations/frontend/pt.json @@ -1253,6 +1253,7 @@ "entities": { "add_entities_lovelace": "Adicionar ao Lovelace", "entities": "Entidades", + "hide_disabled": "Mostrar entidades desativadas", "none": "Este dispositivo não possui entidades" }, "name": "Nome", @@ -2168,7 +2169,7 @@ "edit_card": { "add": "Adicionar Cartão", "delete": "Apagar Cartão", - "duplicate": "Cartão duplicado", + "duplicate": "Duplicar cartão", "edit": "Editar", "header": "Configuração do cartão", "move": "Mover para Vista", @@ -2295,6 +2296,8 @@ "abort_intro": "Início de sessão cancelado", "authorizing_client": "Está prestes a dar acesso a {clientId} à sua instância do Home Assistant.", "form": { + "error": "Erro: {error}", + "next": "Seguinte", "providers": { "command_line": { "abort": { @@ -2380,6 +2383,7 @@ } } }, + "start_over": "Iniciar novamente", "unknown_error": "Algo correu mal", "working": "Por favor, aguarde" }, diff --git a/translations/frontend/ru.json b/translations/frontend/ru.json index 7093a2809a..0d8fdc6439 100644 --- a/translations/frontend/ru.json +++ b/translations/frontend/ru.json @@ -896,7 +896,7 @@ }, "edit_ui": "Форма ввода", "edit_yaml": "Текстовый редактор", - "enable_disable": "Включение или отключение правила автоматизации", + "enable_disable": "Включить / выключить автоматизацию", "introduction": "Используйте автоматизацию, чтобы оживить Ваш дом.", "load_error_not_editable": "Доступны для редактирования только автоматизации из automations.yaml.", "load_error_unknown": "Ошибка загрузки автоматизации ({err_no}).", @@ -1362,8 +1362,8 @@ "delete_button": "Удалить интеграцию {integration}", "delete_confirm": "Вы уверены, что хотите удалить эту интеграцию?", "device_unavailable": "устройство недоступно", - "devices": "{count} {count, plural,\n one {device}\n other {devices}\n}", - "entities": "{count} {count, plural,\n one {entity}\n other {entities}\n}", + "devices": "{count} {count, plural,\n one {устройство}\n other {устройств}\n}", + "entities": "{count} {count, plural,\n one {объект}\n other {объектов}\n}", "entity_unavailable": "объект недоступен", "firmware": "Прошивка: {version}", "hub": "Подключено через", @@ -2307,6 +2307,8 @@ "abort_intro": "Вход прерван", "authorizing_client": "Получение доступа к {clientId}.", "form": { + "error": "Ошибка: {error}", + "next": "Далее", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "Начать сначала", "unknown_error": "Что-то пошло не так", "working": "Пожалуйста, подождите" }, diff --git a/translations/frontend/sv.json b/translations/frontend/sv.json index 1ba8aac447..8688771274 100644 --- a/translations/frontend/sv.json +++ b/translations/frontend/sv.json @@ -903,7 +903,7 @@ "triggers": { "add": "Lägg till händelse", "delete": "Radera", - "delete_confirm": "Säker på att du vill radera?", + "delete_confirm": "Är du säker på att du vill radera detta?", "duplicate": "Duplicera", "header": "Händelse", "introduction": "Triggers är det som startar en automation. Det är möjligt att ange flera triggers för samma regel. När en trigger inträffar kommer Home Assistant att validera eventuella villkor och sedan köra åtgärden.", @@ -1030,7 +1030,7 @@ "connection_status": "Status för molnanslutning", "fetching_subscription": "Hämtar prenumeration...", "google": { - "config_documentation": "Konfigureringsdokumentation", + "config_documentation": "Dokumentation av Inställningar", "devices_pin": "Säkerhetsenheter Pin", "enable_ha_skill": "Aktivera Home Assistant-färdigheten för Google Assistant", "enable_state_reporting": "Aktivera tillståndsrapportering", @@ -1874,10 +1874,12 @@ "built_using": "Byggt med", "custom_uis": "Anpassade användargränssnitt:", "developed_by": "Utvecklad av ett gäng grymma människor.", + "documentation": "Dokumentation", "frontend": "frontend-UI", "frontend_version": "Frontend-version: {version} - {type}", "home_assistant_logo": "Home Assistant logotyp", "icons_by": "Ikoner av", + "issues": "Problem", "license": "Publicerad under Apache 2.0-licensen", "path_configuration": "Sökväg till configuration.yaml: {path}", "server": "server", @@ -2227,7 +2229,7 @@ "save": "Ta kontroll", "yaml_config": "För att hjälpa dig igång, så är här nuvarande inställning för denna instrumentpanel:", "yaml_control": "Om du vill ta kontroll i YAML-läge skapar du en YAML-fil med det namn du angav i konfigurationen för den här instrumentpanelen eller standard \"ui-lovelace.yaml\".", - "yaml_mode": "Du använder YAML-läge, vilket betyder att du inte kan ändra dina Lovelace-inställning från användargränssnittet. Om du vill ändra Lovelace från användargränssnittet, ta bort 'mode: yaml' från dina Lovelaceinställningar i 'configuration.yaml'" + "yaml_mode": "Du använder YAML-läge, vilket betyder att du inte kan ändra dina Lovelace-inställning från användargränssnittet. Om du vill hantera Lovelace från användargränssnittet, ta bort 'mode: yaml' från din Lovelace-inställning i 'configuration.yaml'" }, "suggest_card": { "add": "Lägg till i Lovelace-gränsnitt", @@ -2287,6 +2289,7 @@ "abort_intro": "Inloggning avbruten", "authorizing_client": "Du håller på att ge {clientId} behörighet till din Home Assistant.", "form": { + "next": "Nästa", "providers": { "command_line": { "abort": { @@ -2348,7 +2351,7 @@ "data": { "password": "API-lösenord" }, - "description": "Lägg in ett API-lösenord i din http konfig:" + "description": "Lägg in ett API-lösenord i din HTTP-konfiguration:" }, "mfa": { "data": { @@ -2372,6 +2375,7 @@ } } }, + "start_over": "Börja om", "unknown_error": "Något gick fel", "working": "Vänligen vänta" }, diff --git a/translations/frontend/zh-Hans.json b/translations/frontend/zh-Hans.json index 5d183951c6..52186c2cb1 100644 --- a/translations/frontend/zh-Hans.json +++ b/translations/frontend/zh-Hans.json @@ -2307,6 +2307,8 @@ "abort_intro": "登录中断", "authorizing_client": "您即将授权 {clientId} 访问 Home Assistant 实例。", "form": { + "error": "错误:{error}", + "next": "下一步", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "重新开始", "unknown_error": "出现了一些问题", "working": "请稍候" }, diff --git a/translations/frontend/zh-Hant.json b/translations/frontend/zh-Hant.json index 9c6c741d01..7e4f53e774 100644 --- a/translations/frontend/zh-Hant.json +++ b/translations/frontend/zh-Hant.json @@ -2307,6 +2307,8 @@ "abort_intro": "登入中止", "authorizing_client": "即將授與 {clientId} 訪問 Home Assistant 系統權限。", "form": { + "error": "錯誤:{error}", + "next": "下一步", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "重新開始", "unknown_error": "發生錯誤", "working": "請稍候" }, From 71397e519964865543f51fa7130fc9520372c417 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 23 May 2020 20:20:36 -0700 Subject: [PATCH 30/77] Exclude default polymer theme (#6010) --- build-scripts/bundle.js | 1 + build-scripts/rollup.js | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/build-scripts/bundle.js b/build-scripts/bundle.js index c000b5af30..848c386632 100644 --- a/build-scripts/bundle.js +++ b/build-scripts/bundle.js @@ -15,6 +15,7 @@ module.exports.emptyPackages = ({ latestBuild }) => [ // Contains all color definitions for all material color sets. // We don't use it require.resolve("@polymer/paper-styles/color.js"), + require.resolve("@polymer/paper-styles/default-theme.js"), // Loads stuff from a CDN require.resolve("@polymer/font-roboto/roboto.js"), require.resolve("@vaadin/vaadin-material-styles/font-roboto.js"), diff --git a/build-scripts/rollup.js b/build-scripts/rollup.js index c27cee625a..52cacdb6b3 100644 --- a/build-scripts/rollup.js +++ b/build-scripts/rollup.js @@ -43,9 +43,7 @@ const createRollupConfig = ({ preserveEntrySignatures: false, plugins: [ ignore({ - files: bundle - .ignorePackages({ latestBuild }) - .concat(bundle.emptyPackages({ latestBuild })), + files: bundle.emptyPackages({ latestBuild }), }), resolve({ extensions, From 7427b209a70f01cdb53acee7b8d721c56ffb7925 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 23 May 2020 22:08:49 -0700 Subject: [PATCH 31/77] Fix ignore plugin for ES5 builds --- build-scripts/rollup-plugins/ignore-plugin.js | 1 + 1 file changed, 1 insertion(+) diff --git a/build-scripts/rollup-plugins/ignore-plugin.js b/build-scripts/rollup-plugins/ignore-plugin.js index 4c6a7e61c0..e696bbe6c9 100644 --- a/build-scripts/rollup-plugins/ignore-plugin.js +++ b/build-scripts/rollup-plugins/ignore-plugin.js @@ -19,6 +19,7 @@ module.exports = function (userOptions = {}) { // inside node_module dependencies. if ( importee.endsWith("commonjsHelpers.js") || + importee.endsWith("rollupPluginBabelHelpers.js") || importee.endsWith("?commonjs-proxy") || !importer || !importer.includes("/node_modules/") From c5ef33cc785315768e2280d0a23b8a803598d5be Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 24 May 2020 01:39:07 -0700 Subject: [PATCH 32/77] Upgrade Fuse (#6012) --- hassio/src/components/hassio-filter-addons.ts | 8 ++++---- package.json | 2 +- src/dialogs/config-flow/step-flow-pick-handler.ts | 8 ++++---- .../config/integrations/ha-config-integrations.ts | 14 +++++++------- .../lovelace/editor/card-editor/hui-card-picker.ts | 8 ++++---- yarn.lock | 8 ++++---- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/hassio/src/components/hassio-filter-addons.ts b/hassio/src/components/hassio-filter-addons.ts index 270c8e7612..ddb56188aa 100644 --- a/hassio/src/components/hassio-filter-addons.ts +++ b/hassio/src/components/hassio-filter-addons.ts @@ -1,13 +1,13 @@ -import * as Fuse from "fuse.js"; +import Fuse from "fuse.js"; import { HassioAddonInfo } from "../../../src/data/hassio/addon"; export function filterAndSort(addons: HassioAddonInfo[], filter: string) { - const options: Fuse.FuseOptions = { + const options: Fuse.IFuseOptions = { keys: ["name", "description", "slug"], - caseSensitive: false, + isCaseSensitive: false, minMatchCharLength: 2, threshold: 0.2, }; const fuse = new Fuse(addons, options); - return fuse.search(filter); + return fuse.search(filter).map((result) => result.item); } diff --git a/package.json b/package.json index cb89179ba0..b6485dd03d 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "deep-freeze": "^0.0.1", "es6-object-assign": "^1.1.0", "fecha": "^4.2.0", - "fuse.js": "^3.4.4", + "fuse.js": "^6.0.0", "google-timezones-json": "^1.0.2", "hls.js": "^0.12.4", "home-assistant-js-websocket": "^5.1.2", diff --git a/src/dialogs/config-flow/step-flow-pick-handler.ts b/src/dialogs/config-flow/step-flow-pick-handler.ts index 879824a657..68a54c92dd 100644 --- a/src/dialogs/config-flow/step-flow-pick-handler.ts +++ b/src/dialogs/config-flow/step-flow-pick-handler.ts @@ -1,7 +1,7 @@ import "@polymer/paper-item/paper-icon-item"; import "@polymer/paper-item/paper-item-body"; import "@polymer/paper-spinner/paper-spinner-lite"; -import * as Fuse from "fuse.js"; +import Fuse from "fuse.js"; import { css, CSSResult, @@ -52,14 +52,14 @@ class StepFlowPickHandler extends LitElement { }); if (filter) { - const options: Fuse.FuseOptions = { + const options: Fuse.IFuseOptions = { keys: ["name", "slug"], - caseSensitive: false, + isCaseSensitive: false, minMatchCharLength: 2, threshold: 0.2, }; const fuse = new Fuse(handlers, options); - return fuse.search(filter); + return fuse.search(filter).map((result) => result.item); } return handlers.sort((a, b) => a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1 diff --git a/src/panels/config/integrations/ha-config-integrations.ts b/src/panels/config/integrations/ha-config-integrations.ts index 9fb28efcb8..0de2540d1d 100644 --- a/src/panels/config/integrations/ha-config-integrations.ts +++ b/src/panels/config/integrations/ha-config-integrations.ts @@ -11,7 +11,7 @@ import { TemplateResult, } from "lit-element"; import memoizeOne from "memoize-one"; -import * as Fuse from "fuse.js"; +import Fuse from "fuse.js"; import { caseInsensitiveCompare } from "../../../common/string/compare"; import { computeRTL } from "../../../common/util/compute_rtl"; import { nextRender } from "../../../common/util/render-status"; @@ -149,14 +149,14 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { if (!filter) { return [...configEntries]; } - const options: Fuse.FuseOptions = { + const options: Fuse.IFuseOptions = { keys: ["domain", "localized_domain_name", "title"], - caseSensitive: false, + isCaseSensitive: false, minMatchCharLength: 2, threshold: 0.2, }; const fuse = new Fuse(configEntries, options); - return fuse.search(filter); + return fuse.search(filter).map((result) => result.item); } ); @@ -193,14 +193,14 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { if (!filter) { return configEntriesInProgress; } - const options: Fuse.FuseOptions = { + const options: Fuse.IFuseOptions = { keys: ["handler", "localized_title"], - caseSensitive: false, + isCaseSensitive: false, minMatchCharLength: 2, threshold: 0.2, }; const fuse = new Fuse(configEntriesInProgress, options); - return fuse.search(filter); + return fuse.search(filter).map((result) => result.item); } ); diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index 9b0216d155..14bd738d1d 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -1,4 +1,4 @@ -import * as Fuse from "fuse.js"; +import Fuse from "fuse.js"; import { css, CSSResult, @@ -60,14 +60,14 @@ export class HuiCardPicker extends LitElement { let cards = cardElements.map( (cardElement: CardElement) => cardElement.card ); - const options: Fuse.FuseOptions = { + const options: Fuse.IFuseOptions = { keys: ["type", "name", "description"], - caseSensitive: false, + isCaseSensitive: false, minMatchCharLength: 2, threshold: 0.2, }; const fuse = new Fuse(cards, options); - cards = fuse.search(filter); + cards = fuse.search(filter).map((result) => result.item); cardElements = cardElements.filter((cardElement: CardElement) => cards.includes(cardElement.card) ); diff --git a/yarn.lock b/yarn.lock index 55bef23820..14e56d7066 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7907,10 +7907,10 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -fuse.js@^3.4.4: - version "3.4.4" - resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.4.tgz#f98f55fcb3b595cf6a3e629c5ffaf10982103e95" - integrity sha512-pyLQo/1oR5Ywf+a/tY8z4JygnIglmRxVUOiyFAbd11o9keUDpUJSMGRWJngcnkURj30kDHPmhoKY8ChJiz3EpQ== +fuse.js@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-6.0.0.tgz#6fc16cd7555648deda392892402d4188553552b2" + integrity sha512-e5Ap6mhF/WQ9bKqsMFTTR5/DS9qbYab4VXHtMdxCanH+VZkdUV2LqcgMO31etSQv53NXsguQF1bdqkrrPAM2HQ== g-status@^2.0.2: version "2.0.2" From 38d3b8d08751f2cff7e15f5237c4c65db354971b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 24 May 2020 01:41:05 -0700 Subject: [PATCH 33/77] Ignore proxy-polyfill in workers (#6011) --- build-scripts/bundle.js | 21 +++++++++++-------- build-scripts/rollup-plugins/worker-plugin.js | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/build-scripts/bundle.js b/build-scripts/bundle.js index 848c386632..6123a7a095 100644 --- a/build-scripts/bundle.js +++ b/build-scripts/bundle.js @@ -11,15 +11,18 @@ module.exports.ignorePackages = ({ latestBuild }) => [ ]; // Files from NPM packages that we should replace with empty file -module.exports.emptyPackages = ({ latestBuild }) => [ - // Contains all color definitions for all material color sets. - // We don't use it - require.resolve("@polymer/paper-styles/color.js"), - require.resolve("@polymer/paper-styles/default-theme.js"), - // Loads stuff from a CDN - require.resolve("@polymer/font-roboto/roboto.js"), - require.resolve("@vaadin/vaadin-material-styles/font-roboto.js"), -]; +module.exports.emptyPackages = ({ latestBuild }) => + [ + // Contains all color definitions for all material color sets. + // We don't use it + require.resolve("@polymer/paper-styles/color.js"), + require.resolve("@polymer/paper-styles/default-theme.js"), + // Loads stuff from a CDN + require.resolve("@polymer/font-roboto/roboto.js"), + require.resolve("@vaadin/vaadin-material-styles/font-roboto.js"), + // Polyfill only needed for ES5 workers so filter out in latestBuild + latestBuild && require.resolve("proxy-polyfill/src/index.js"), + ].filter(Boolean); module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({ __DEV__: !isProdBuild, diff --git a/build-scripts/rollup-plugins/worker-plugin.js b/build-scripts/rollup-plugins/worker-plugin.js index c075a08495..96dc7c8acd 100644 --- a/build-scripts/rollup-plugins/worker-plugin.js +++ b/build-scripts/rollup-plugins/worker-plugin.js @@ -25,7 +25,7 @@ const defaultOpts = { // A RegExp to find `new Workers()` calls. The second capture group _must_ // capture the provided file name without the quotes. workerRegexp: /new Worker\((["'])(.+?)\1(,[^)]+)?\)/g, - plugins: ["node-resolve", "commonjs", "babel"], + plugins: ["node-resolve", "commonjs", "babel", "terser", "ignore"], }; async function getBundledWorker(workerPath, rollupOptions) { From 1876b3827f8ab39007b6526a6dbd63d9f936c609 Mon Sep 17 00:00:00 2001 From: HomeAssistant Azure Date: Mon, 25 May 2020 00:32:56 +0000 Subject: [PATCH 34/77] [ci skip] Translation update --- translations/frontend/ca.json | 14 +++++++------- translations/frontend/da.json | 3 +++ translations/frontend/de.json | 4 ++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/translations/frontend/ca.json b/translations/frontend/ca.json index 4008af994b..251b972dad 100644 --- a/translations/frontend/ca.json +++ b/translations/frontend/ca.json @@ -751,7 +751,7 @@ "link_profile_page": "la teva pàgina de perfil" }, "areas": { - "caption": "Registre d'àrees", + "caption": "Àrees", "data_table": { "area": "Àrea", "devices": "Dispositius" @@ -769,7 +769,7 @@ }, "picker": { "create_area": "Crea àrea", - "header": "Registre d'àrees", + "header": "Àrees", "integrations_page": "Pàgina d'integracions", "introduction": "Les àrees s'utilitzen per organitzar la situació dels dispositius. Aquesta informació serà utilitzada per Home Assistant per ajudar-te a organitzar millor la teva interfície, els permisos i les integracions amb d'altres sistemes.", "introduction2": "Per col·locar dispositius en una àrea, utilitza l'enllaç de sota per anar a la pàgina d'integracions i, a continuació, fes clic a una integració configurada per accedir a les targetes del dispositiu.", @@ -831,7 +831,7 @@ "delete_confirm": "Segur que vols eliminar-ho?", "duplicate": "Duplica", "header": "Condicions", - "introduction": "Les condicions són part opcional d'una automatització i es poden utilitzar per permetre o evitar que es produeixi una acció quan es dispari l'automatització. Les condicions són similars als activadors però funcionen de forma diferent: un activador analitza els esdeveniments que ocorren en el sistema mentre que una condició només observa com està el sistema en un moment determinat, per exemple, un activador se n'adonarà de quan s'està activant un interruptor mentre que una condició només pot veure si un interruptor està activat o desactivat.", + "introduction": "Les condicions són opcionals i impedeixen que continui l'execució mentre totes elles no es satisfacin.", "learn_more": "Més informació sobre les condicions", "name": "Condició", "type_select": "Tipus de condició", @@ -1210,7 +1210,7 @@ "different_include": "Possiblement a través d'un domini o una altra inclusió diferent.", "pick_attribute": "Selecciona un atribut per substituir-lo", "picker": { - "header": "Personalització", + "header": "Personalitzacions", "introduction": "Personalitza els atributs de les entitats al teu gust. Les personalitzacions afegides/modificades apareixeran immediatament, les que s'hagin eliminat tindran efecte quan l'entitat s'actualitzi." }, "warning": { @@ -1278,7 +1278,7 @@ "update": "Actualitza" }, "entities": { - "caption": "Registre d'entitats", + "caption": "Entitats", "description": "Visió general de totes les entitats conegudes.", "picker": { "disable_selected": { @@ -2182,10 +2182,10 @@ "delete": "Elimina", "duplicate": "Duplica targeta", "edit": "Editar", - "header": "(configuració de la targeta)", + "header": "Configuració de la targeta", "move": "Moure a la Vista", "options": "Més opcions", - "pick_card": "Tria una targeta que vulguis afegir.", + "pick_card": "Quina targeta vols afegir?", "pick_card_view_title": "Quina targeta vols afegir a la visualització {name}?", "show_code_editor": "Mostra l'editor de codi", "show_visual_editor": "Mostra l'editor visual", diff --git a/translations/frontend/da.json b/translations/frontend/da.json index 3d58aea27c..81f01eddc2 100644 --- a/translations/frontend/da.json +++ b/translations/frontend/da.json @@ -2307,6 +2307,8 @@ "abort_intro": "Login afbrudt", "authorizing_client": "Du er ved at give {clientId} adgang til din Home Assistant-instans.", "form": { + "error": "Fejl: {error}", + "next": "Næste", "providers": { "command_line": { "abort": { @@ -2392,6 +2394,7 @@ } } }, + "start_over": "Start forfra", "unknown_error": "Noget gik galt", "working": "Vent venligst" }, diff --git a/translations/frontend/de.json b/translations/frontend/de.json index 900c7724d4..a54b8dffe1 100644 --- a/translations/frontend/de.json +++ b/translations/frontend/de.json @@ -1255,6 +1255,7 @@ "entities": { "add_entities_lovelace": "Zu Lovelace hinzufügen", "entities": "Entitäten", + "hide_disabled": "Ausblenden deaktiviert", "none": "Dieses Gerät hat keine Entitäten" }, "name": "Name", @@ -2305,6 +2306,8 @@ "abort_intro": "Anmeldung abgebrochen", "authorizing_client": "Sie sind dabei, {clientId} Zugriff auf Ihre Home Assistant-Instanz zu gewähren.", "form": { + "error": "Fehler", + "next": "Weiter", "providers": { "command_line": { "abort": { @@ -2390,6 +2393,7 @@ } } }, + "start_over": "Neu anfangen", "unknown_error": "Etwas lief schief", "working": "Bitte warten" }, From b8e71609db2494a107fdbe76436cd3dfe63aed4d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 25 May 2020 01:12:42 -0700 Subject: [PATCH 35/77] Random Rollup tweaks (#6034) --- build-scripts/gulp/rollup.js | 14 ++++++++------ build-scripts/rollup-plugins/worker-plugin.js | 1 + build-scripts/rollup.js | 9 ++++++--- demo/public/manifest.json | 4 ++-- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/build-scripts/gulp/rollup.js b/build-scripts/gulp/rollup.js index 5cccc7d58f..07b6781d01 100644 --- a/build-scripts/gulp/rollup.js +++ b/build-scripts/gulp/rollup.js @@ -56,14 +56,16 @@ function watchRollup(createConfig, extraWatchSrc = [], serveOptions) { ...inputOptions, output: [outputOptions], watch: { - include: ["src"] + extraWatchSrc, + include: ["src/**"] + extraWatchSrc, }, }); let startedHttp = false; watcher.on("event", (event) => { - if (event.code === "ERROR") { + if (event.code === "BUNDLE_END") { + log(`Build done @ ${new Date().toLocaleTimeString()}`); + } else if (event.code === "ERROR") { log.error(event.error); } else if (event.code === "END") { if (startedHttp || !serveOptions) { @@ -90,18 +92,18 @@ gulp.task("rollup-watch-app", () => { }); gulp.task("rollup-watch-hassio", () => { - watchRollup(rollupConfig.createHassioConfig, ["hassio/src"]); + watchRollup(rollupConfig.createHassioConfig, ["hassio/src/**"]); }); gulp.task("rollup-dev-server-demo", () => { - watchRollup(rollupConfig.createDemoConfig, ["demo/src"], { + watchRollup(rollupConfig.createDemoConfig, ["demo/src/**"], { root: paths.demo_output_root, port: 8090, }); }); gulp.task("rollup-dev-server-cast", () => { - watchRollup(rollupConfig.createCastConfig, ["cast/src"], { + watchRollup(rollupConfig.createCastConfig, ["cast/src/**"], { root: paths.cast_output_root, port: 8080, networkAccess: true, @@ -109,7 +111,7 @@ gulp.task("rollup-dev-server-cast", () => { }); gulp.task("rollup-dev-server-gallery", () => { - watchRollup(rollupConfig.createGalleryConfig, ["gallery/src"], { + watchRollup(rollupConfig.createGalleryConfig, ["gallery/src/**"], { root: paths.gallery_output_root, port: 8100, }); diff --git a/build-scripts/rollup-plugins/worker-plugin.js b/build-scripts/rollup-plugins/worker-plugin.js index 96dc7c8acd..0aa05273ca 100644 --- a/build-scripts/rollup-plugins/worker-plugin.js +++ b/build-scripts/rollup-plugins/worker-plugin.js @@ -115,6 +115,7 @@ module.exports = function (opts = {}) { if (resolvedWorkerFile in refIds) { chunkRefId = refIds[resolvedWorkerFile]; } else { + this.addWatchFile(resolvedWorkerFile); const source = await getBundledWorker( resolvedWorkerFile, rollupOptions diff --git a/build-scripts/rollup.js b/build-scripts/rollup.js index 52cacdb6b3..3757f25866 100644 --- a/build-scripts/rollup.js +++ b/build-scripts/rollup.js @@ -96,9 +96,12 @@ const createRollupConfig = ({ // https://rollupjs.org/guide/en/#outputentryfilenames // https://rollupjs.org/guide/en/#outputchunkfilenames // https://rollupjs.org/guide/en/#outputassetfilenames - entryFileNames: isProdBuild ? "[name]-[hash].js" : "[name].js", - chunkFileNames: isProdBuild ? "c.[hash].js" : "[name].js", - assetFileNames: isProdBuild ? "a.[hash].js" : "[name].js", + entryFileNames: + isProdBuild && !isStatsBuild ? "[name]-[hash].js" : "[name].js", + chunkFileNames: + isProdBuild && !isStatsBuild ? "c.[hash].js" : "[name].js", + assetFileNames: + isProdBuild && !isStatsBuild ? "a.[hash].js" : "[name].js", // https://rollupjs.org/guide/en/#outputsourcemap sourcemap: isProdBuild ? true : "inline", }, diff --git a/demo/public/manifest.json b/demo/public/manifest.json index f364cab750..901a8780a1 100644 --- a/demo/public/manifest.json +++ b/demo/public/manifest.json @@ -1,6 +1,6 @@ { "background_color": "#FFFFFF", - "description": "Open-source home automation platform running on Python 3.", + "description": "Home automation platform that puts local control and privacy first.", "dir": "ltr", "display": "standalone", "icons": [ @@ -31,7 +31,7 @@ ], "lang": "en-US", "name": "Home Assistant Demo", - "short_name": "Demo", + "short_name": "HA Demo", "start_url": "/?homescreen=1", "theme_color": "#03A9F4" } From af231100743077e61f78da437b4d655832ce5da5 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 25 May 2020 01:16:01 -0700 Subject: [PATCH 36/77] Move legacy styles to their own files (#6033) --- cast/src/receiver/second-load.ts | 1 + demo/src/entrypoint.ts | 1 - gallery/src/entrypoint.js | 1 - gallery/src/ha-gallery.js | 1 + hassio/src/hassio-panel.ts | 1 - .../config-flow/dialog-data-entry-flow.ts | 1 - src/dialogs/config-flow/step-flow-form.ts | 1 - src/dialogs/ha-more-info-dialog.js | 2 +- src/dialogs/ha-store-auth-card.js | 2 +- src/dialogs/more-info/more-info-controls.js | 2 +- src/entrypoints/app.ts | 6 ++--- src/layouts/home-assistant.ts | 1 - .../config/cloud/account/cloud-account.js | 2 +- .../forgot-password/cloud-forgot-password.js | 2 +- src/panels/config/cloud/login/cloud-login.js | 2 +- .../config/cloud/register/cloud-register.js | 2 +- src/panels/config/core/ha-config-core.js | 2 +- .../config/core/ha-config-section-core.js | 2 +- .../config/customize/ha-config-customize.js | 2 +- .../config/customize/ha-form-customize.js | 2 ++ src/panels/config/ha-entity-config.js | 1 + .../ha-config-section-server-control.js | 2 +- .../ha-config-server-control.js | 2 +- src/panels/config/zwave/ha-config-zwave.js | 2 +- src/panels/config/zwave/zwave-groups.js | 1 + src/panels/config/zwave/zwave-log-dialog.js | 2 +- src/panels/config/zwave/zwave-log.js | 1 + .../config/zwave/zwave-node-protection.js | 1 + src/panels/config/zwave/zwave-usercodes.js | 1 + .../event/developer-tools-event.js | 2 +- .../service/developer-tools-service.js | 2 +- .../state/developer-tools-state.js | 2 +- .../template/developer-tools-template.js | 2 +- src/panels/history/ha-panel-history.js | 2 +- src/panels/iframe/ha-panel-iframe.js | 2 +- src/panels/logbook/ha-panel-logbook.js | 2 +- .../mailbox/ha-dialog-show-audio-message.js | 2 +- src/panels/mailbox/ha-panel-mailbox.js | 2 +- src/panels/map/ha-panel-map.js | 1 + src/panels/profile/ha-change-password-card.js | 2 +- .../ha-long-lived-access-tokens-card.js | 2 +- .../profile/ha-mfa-module-setup-flow.js | 2 +- src/panels/profile/ha-mfa-modules-card.js | 2 +- src/panels/profile/ha-panel-profile.ts | 1 - .../shopping-list/ha-panel-shopping-list.js | 1 + src/resources/ha-style.ts | 22 ++++--------------- src/styles/polymer-ha-style-dialog.ts | 15 +++++++++++++ src/styles/polymer-ha-style.ts | 15 +++++++++++++ 48 files changed, 74 insertions(+), 56 deletions(-) create mode 100644 src/styles/polymer-ha-style-dialog.ts create mode 100644 src/styles/polymer-ha-style.ts diff --git a/cast/src/receiver/second-load.ts b/cast/src/receiver/second-load.ts index 39dd115e96..bb691527f6 100644 --- a/cast/src/receiver/second-load.ts +++ b/cast/src/receiver/second-load.ts @@ -1,3 +1,4 @@ import "web-animations-js/web-animations-next-lite.min"; import "../../../src/resources/roboto"; +import "../../../src/resources/ha-style"; import "./layout/hc-lovelace"; diff --git a/demo/src/entrypoint.ts b/demo/src/entrypoint.ts index e2b8c447ce..5ddbcc0ca4 100644 --- a/demo/src/entrypoint.ts +++ b/demo/src/entrypoint.ts @@ -1,4 +1,3 @@ -import "@polymer/paper-styles/typography"; import "@polymer/polymer/lib/elements/dom-if"; import "@polymer/polymer/lib/elements/dom-repeat"; import "../../src/resources/ha-style"; diff --git a/gallery/src/entrypoint.js b/gallery/src/entrypoint.js index f803a3c6a3..095530ec00 100644 --- a/gallery/src/entrypoint.js +++ b/gallery/src/entrypoint.js @@ -1,4 +1,3 @@ -import "@polymer/paper-styles/typography"; import "@polymer/polymer/lib/elements/dom-if"; import "@polymer/polymer/lib/elements/dom-repeat"; import "../../src/resources/ha-style"; diff --git a/gallery/src/ha-gallery.js b/gallery/src/ha-gallery.js index de8c424e5a..3352048e38 100644 --- a/gallery/src/ha-gallery.js +++ b/gallery/src/ha-gallery.js @@ -10,6 +10,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../src/components/ha-card"; import "../../src/managers/notification-manager"; +import "../../src/styles/polymer-ha-style"; // eslint-disable-next-line no-undef const DEMOS = require.context("./demos", true, /^(.*\.(ts$))[^.]*$/im); diff --git a/hassio/src/hassio-panel.ts b/hassio/src/hassio-panel.ts index b5f4770807..1e92ec923b 100644 --- a/hassio/src/hassio-panel.ts +++ b/hassio/src/hassio-panel.ts @@ -12,7 +12,6 @@ import { HassioSupervisorInfo, } from "../../src/data/hassio/supervisor"; import type { PageNavigation } from "../../src/layouts/hass-tabs-subpage"; -import "../../src/resources/ha-style"; import { HomeAssistant, Route } from "../../src/types"; import "./hassio-panel-router"; diff --git a/src/dialogs/config-flow/dialog-data-entry-flow.ts b/src/dialogs/config-flow/dialog-data-entry-flow.ts index 3ece18035b..8ee7b60587 100644 --- a/src/dialogs/config-flow/dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/dialog-data-entry-flow.ts @@ -28,7 +28,6 @@ import { subscribeDeviceRegistry, } from "../../data/device_registry"; import { PolymerChangedEvent } from "../../polymer-types"; -import "../../resources/ha-style"; import { haStyleDialog } from "../../resources/styles"; import type { HomeAssistant } from "../../types"; import { DataEntryFlowDialogParams } from "./show-dialog-data-entry-flow"; diff --git a/src/dialogs/config-flow/step-flow-form.ts b/src/dialogs/config-flow/step-flow-form.ts index 21644637ab..7822a21f6f 100644 --- a/src/dialogs/config-flow/step-flow-form.ts +++ b/src/dialogs/config-flow/step-flow-form.ts @@ -16,7 +16,6 @@ import "../../components/ha-form/ha-form"; import type { HaFormSchema } from "../../components/ha-form/ha-form"; import "../../components/ha-markdown"; import type { DataEntryFlowStepForm } from "../../data/data_entry_flow"; -import "../../resources/ha-style"; import type { HomeAssistant } from "../../types"; import type { FlowConfig } from "./show-dialog-data-entry-flow"; import { configFlowContentStyles } from "./styles"; diff --git a/src/dialogs/ha-more-info-dialog.js b/src/dialogs/ha-more-info-dialog.js index 6f716ada0d..1f80d19aec 100644 --- a/src/dialogs/ha-more-info-dialog.js +++ b/src/dialogs/ha-more-info-dialog.js @@ -5,7 +5,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import { computeStateDomain } from "../common/entity/compute_state_domain"; import DialogMixin from "../mixins/dialog-mixin"; -import "../resources/ha-style"; +import "../styles/polymer-ha-style-dialog"; import "./more-info/more-info-controls"; /* diff --git a/src/dialogs/ha-store-auth-card.js b/src/dialogs/ha-store-auth-card.js index 28df7c7249..a3b39c1681 100644 --- a/src/dialogs/ha-store-auth-card.js +++ b/src/dialogs/ha-store-auth-card.js @@ -4,7 +4,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import { enableWrite } from "../common/auth/token_storage"; import LocalizeMixin from "../mixins/localize-mixin"; -import "../resources/ha-style"; +import "../styles/polymer-ha-style"; class HaStoreAuth extends LocalizeMixin(PolymerElement) { static get template() { diff --git a/src/dialogs/more-info/more-info-controls.js b/src/dialogs/more-info/more-info-controls.js index bb12335b21..34d5e97ebc 100644 --- a/src/dialogs/more-info/more-info-controls.js +++ b/src/dialogs/more-info/more-info-controls.js @@ -17,7 +17,7 @@ import "../../data/ha-state-history-data"; import { EventsMixin } from "../../mixins/events-mixin"; import LocalizeMixin from "../../mixins/localize-mixin"; import { showEntityEditorDialog } from "../../panels/config/entities/show-dialog-entity-editor"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style-dialog"; import "../../state-summary/state-card-content"; import { showConfirmationDialog } from "../generic/show-dialog-box"; import "./controls/more-info-content"; diff --git a/src/entrypoints/app.ts b/src/entrypoints/app.ts index 9be05793ac..2e9f6294e0 100644 --- a/src/entrypoints/app.ts +++ b/src/entrypoints/app.ts @@ -1,10 +1,8 @@ -// Load polyfill first so HTML imports start resolving -/* eslint-disable import/first */ -import "@polymer/paper-styles/typography"; import { setPassiveTouchGestures } from "@polymer/polymer/lib/utils/settings"; +import "../resources/roboto"; +import "../resources/ha-style"; import "../layouts/home-assistant"; import "../resources/html-import/polyfill"; -import "../resources/roboto"; import "../util/legacy-support"; setPassiveTouchGestures(true); diff --git a/src/layouts/home-assistant.ts b/src/layouts/home-assistant.ts index c9594d1d54..e38acec094 100644 --- a/src/layouts/home-assistant.ts +++ b/src/layouts/home-assistant.ts @@ -3,7 +3,6 @@ import { html, property, PropertyValues } from "lit-element"; import { navigate } from "../common/navigate"; import { getStorageDefaultPanelUrlPath } from "../data/panel"; import "../resources/custom-card-support"; -import "../resources/ha-style"; import { HassElement } from "../state/hass-element"; import { HomeAssistant, Route } from "../types"; import { diff --git a/src/panels/config/cloud/account/cloud-account.js b/src/panels/config/cloud/account/cloud-account.js index 5f47122819..b622c8a9ff 100644 --- a/src/panels/config/cloud/account/cloud-account.js +++ b/src/panels/config/cloud/account/cloud-account.js @@ -10,7 +10,7 @@ import { fetchCloudSubscriptionInfo } from "../../../../data/cloud"; import "../../../../layouts/hass-subpage"; import { EventsMixin } from "../../../../mixins/events-mixin"; import LocalizeMixin from "../../../../mixins/localize-mixin"; -import "../../../../resources/ha-style"; +import "../../../../styles/polymer-ha-style"; import "../../ha-config-section"; import "./cloud-alexa-pref"; import "./cloud-google-pref"; diff --git a/src/panels/config/cloud/forgot-password/cloud-forgot-password.js b/src/panels/config/cloud/forgot-password/cloud-forgot-password.js index 656db3782c..6d82355c14 100644 --- a/src/panels/config/cloud/forgot-password/cloud-forgot-password.js +++ b/src/panels/config/cloud/forgot-password/cloud-forgot-password.js @@ -7,7 +7,7 @@ import "../../../../components/ha-card"; import "../../../../layouts/hass-subpage"; import { EventsMixin } from "../../../../mixins/events-mixin"; import LocalizeMixin from "../../../../mixins/localize-mixin"; -import "../../../../resources/ha-style"; +import "../../../../styles/polymer-ha-style"; /* * @appliesMixin EventsMixin diff --git a/src/panels/config/cloud/login/cloud-login.js b/src/panels/config/cloud/login/cloud-login.js index d90dd01eeb..f8d27ffcd0 100644 --- a/src/panels/config/cloud/login/cloud-login.js +++ b/src/panels/config/cloud/login/cloud-login.js @@ -14,7 +14,7 @@ import "../../../../layouts/hass-subpage"; import { EventsMixin } from "../../../../mixins/events-mixin"; import LocalizeMixin from "../../../../mixins/localize-mixin"; import NavigateMixin from "../../../../mixins/navigate-mixin"; -import "../../../../resources/ha-style"; +import "../../../../styles/polymer-ha-style"; import "../../ha-config-section"; /* diff --git a/src/panels/config/cloud/register/cloud-register.js b/src/panels/config/cloud/register/cloud-register.js index 90d43735f5..9373b10a16 100644 --- a/src/panels/config/cloud/register/cloud-register.js +++ b/src/panels/config/cloud/register/cloud-register.js @@ -7,7 +7,7 @@ import "../../../../components/ha-card"; import "../../../../layouts/hass-subpage"; import { EventsMixin } from "../../../../mixins/events-mixin"; import LocalizeMixin from "../../../../mixins/localize-mixin"; -import "../../../../resources/ha-style"; +import "../../../../styles/polymer-ha-style"; import "../../ha-config-section"; /* diff --git a/src/panels/config/core/ha-config-core.js b/src/panels/config/core/ha-config-core.js index 383d1f5e99..75d59b5aa5 100644 --- a/src/panels/config/core/ha-config-core.js +++ b/src/panels/config/core/ha-config-core.js @@ -6,7 +6,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../../layouts/hass-tabs-subpage"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; import { configSections } from "../ha-panel-config"; import "./ha-config-section-core"; diff --git a/src/panels/config/core/ha-config-section-core.js b/src/panels/config/core/ha-config-section-core.js index 0ce4653489..b73161c709 100644 --- a/src/panels/config/core/ha-config-section-core.js +++ b/src/panels/config/core/ha-config-section-core.js @@ -7,7 +7,7 @@ import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-card"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; import "../ha-config-section"; import "./ha-config-core-form"; import "./ha-config-name-form"; diff --git a/src/panels/config/customize/ha-config-customize.js b/src/panels/config/customize/ha-config-customize.js index e142dbc2a7..c178afa646 100644 --- a/src/panels/config/customize/ha-config-customize.js +++ b/src/panels/config/customize/ha-config-customize.js @@ -6,7 +6,7 @@ import { computeStateName } from "../../../common/entity/compute_state_name"; import { sortStatesByName } from "../../../common/entity/states_sort_by_name"; import "../../../layouts/hass-tabs-subpage"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; import "../ha-config-section"; import "../ha-entity-config"; import { configSections } from "../ha-panel-config"; diff --git a/src/panels/config/customize/ha-form-customize.js b/src/panels/config/customize/ha-form-customize.js index 90844f93f4..4c85d7b27f 100644 --- a/src/panels/config/customize/ha-form-customize.js +++ b/src/panels/config/customize/ha-form-customize.js @@ -8,6 +8,8 @@ import { computeStateDomain } from "../../../common/entity/compute_state_domain" import LocalizeMixin from "../../../mixins/localize-mixin"; import hassAttributeUtil from "../../../util/hass-attributes-util"; import "./ha-form-customize-attributes"; +import "../ha-form-style"; +import "../../../styles/polymer-ha-style"; class HaFormCustomize extends LocalizeMixin(PolymerElement) { static get template() { diff --git a/src/panels/config/ha-entity-config.js b/src/panels/config/ha-entity-config.js index da870762c0..ed3bed78eb 100644 --- a/src/panels/config/ha-entity-config.js +++ b/src/panels/config/ha-entity-config.js @@ -8,6 +8,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import { computeStateName } from "../../common/entity/compute_state_name"; import "../../components/ha-card"; +import "../../styles/polymer-ha-style"; class HaEntityConfig extends PolymerElement { static get template() { diff --git a/src/panels/config/server_control/ha-config-section-server-control.js b/src/panels/config/server_control/ha-config-section-server-control.js index e26a9f76db..97afdccba9 100644 --- a/src/panels/config/server_control/ha-config-section-server-control.js +++ b/src/panels/config/server_control/ha-config-section-server-control.js @@ -7,7 +7,7 @@ import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-card"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; import "../ha-config-section"; /* diff --git a/src/panels/config/server_control/ha-config-server-control.js b/src/panels/config/server_control/ha-config-server-control.js index 8c69bd5e5b..2cd4e8f87e 100644 --- a/src/panels/config/server_control/ha-config-server-control.js +++ b/src/panels/config/server_control/ha-config-server-control.js @@ -5,7 +5,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../../layouts/hass-tabs-subpage"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; import { configSections } from "../ha-panel-config"; import "./ha-config-section-server-control"; diff --git a/src/panels/config/zwave/ha-config-zwave.js b/src/panels/config/zwave/ha-config-zwave.js index f971fe447b..b5ad855e7f 100644 --- a/src/panels/config/zwave/ha-config-zwave.js +++ b/src/panels/config/zwave/ha-config-zwave.js @@ -19,7 +19,7 @@ import "../../../components/ha-service-description"; import "../../../layouts/ha-app-layout"; import { EventsMixin } from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; import "../ha-config-section"; import "../ha-form-style"; import "./zwave-groups"; diff --git a/src/panels/config/zwave/zwave-groups.js b/src/panels/config/zwave/zwave-groups.js index 165cfbbcfd..9d98ee7df3 100644 --- a/src/panels/config/zwave/zwave-groups.js +++ b/src/panels/config/zwave/zwave-groups.js @@ -7,6 +7,7 @@ import { PolymerElement } from "@polymer/polymer/polymer-element"; import { computeStateName } from "../../../common/entity/compute_state_name"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-card"; +import "../../../styles/polymer-ha-style"; class ZwaveGroups extends PolymerElement { static get template() { diff --git a/src/panels/config/zwave/zwave-log-dialog.js b/src/panels/config/zwave/zwave-log-dialog.js index 8f2c271c62..f3e16d2c63 100644 --- a/src/panels/config/zwave/zwave-log-dialog.js +++ b/src/panels/config/zwave/zwave-log-dialog.js @@ -4,7 +4,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../../components/dialog/ha-paper-dialog"; import { EventsMixin } from "../../../mixins/events-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style-dialog"; class ZwaveLogDialog extends EventsMixin(PolymerElement) { static get template() { diff --git a/src/panels/config/zwave/zwave-log.js b/src/panels/config/zwave/zwave-log.js index b933bdd7ee..1c05969536 100755 --- a/src/panels/config/zwave/zwave-log.js +++ b/src/panels/config/zwave/zwave-log.js @@ -9,6 +9,7 @@ import "../../../components/ha-card"; import { EventsMixin } from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; import "../ha-config-section"; +import "../../../styles/polymer-ha-style"; let registeredDialog = false; diff --git a/src/panels/config/zwave/zwave-node-protection.js b/src/panels/config/zwave/zwave-node-protection.js index c980187c5c..b3ff759a64 100644 --- a/src/panels/config/zwave/zwave-node-protection.js +++ b/src/panels/config/zwave/zwave-node-protection.js @@ -7,6 +7,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../../components/buttons/ha-call-api-button"; import "../../../components/ha-card"; +import "../../../styles/polymer-ha-style"; class ZwaveNodeProtection extends PolymerElement { static get template() { diff --git a/src/panels/config/zwave/zwave-usercodes.js b/src/panels/config/zwave/zwave-usercodes.js index 2ab33eba5d..316bc5e7f6 100644 --- a/src/panels/config/zwave/zwave-usercodes.js +++ b/src/panels/config/zwave/zwave-usercodes.js @@ -7,6 +7,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-card"; +import "../../../styles/polymer-ha-style"; class ZwaveUsercodes extends PolymerElement { static get template() { diff --git a/src/panels/developer-tools/event/developer-tools-event.js b/src/panels/developer-tools/event/developer-tools-event.js index 2ccf0a9a8f..7b1c9856de 100644 --- a/src/panels/developer-tools/event/developer-tools-event.js +++ b/src/panels/developer-tools/event/developer-tools-event.js @@ -9,7 +9,7 @@ import "../../../components/ha-code-editor"; import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box"; import { EventsMixin } from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; import "./event-subscribe-card"; import "./events-list"; diff --git a/src/panels/developer-tools/service/developer-tools-service.js b/src/panels/developer-tools/service/developer-tools-service.js index c34299a020..528022b263 100644 --- a/src/panels/developer-tools/service/developer-tools-service.js +++ b/src/panels/developer-tools/service/developer-tools-service.js @@ -9,7 +9,7 @@ import "../../../components/ha-service-picker"; import { ENTITY_COMPONENT_DOMAINS } from "../../../data/entity"; import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; import "../../../util/app-localstorage-document"; const ERROR_SENTINEL = {}; diff --git a/src/panels/developer-tools/state/developer-tools-state.js b/src/panels/developer-tools/state/developer-tools-state.js index 76fecb5d97..5febdc282e 100644 --- a/src/panels/developer-tools/state/developer-tools-state.js +++ b/src/panels/developer-tools/state/developer-tools-state.js @@ -12,7 +12,7 @@ import "../../../components/ha-code-editor"; import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box"; import { EventsMixin } from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; import { mdiInformationOutline } from "@mdi/js"; const ERROR_SENTINEL = {}; diff --git a/src/panels/developer-tools/template/developer-tools-template.js b/src/panels/developer-tools/template/developer-tools-template.js index 5f7c0ae198..55aba598eb 100644 --- a/src/panels/developer-tools/template/developer-tools-template.js +++ b/src/panels/developer-tools/template/developer-tools-template.js @@ -6,7 +6,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../../components/ha-code-editor"; import LocalizeMixin from "../../../mixins/localize-mixin"; -import "../../../resources/ha-style"; +import "../../../styles/polymer-ha-style"; class HaPanelDevTemplate extends LocalizeMixin(PolymerElement) { static get template() { diff --git a/src/panels/history/ha-panel-history.js b/src/panels/history/ha-panel-history.js index 464c452722..93e2a8b2ba 100644 --- a/src/panels/history/ha-panel-history.js +++ b/src/panels/history/ha-panel-history.js @@ -16,7 +16,7 @@ import "../../components/state-history-charts"; import "../../data/ha-state-history-data"; import LocalizeMixin from "../../mixins/localize-mixin"; import "../../resources/ha-date-picker-style"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style"; /* * @appliesMixin LocalizeMixin diff --git a/src/panels/iframe/ha-panel-iframe.js b/src/panels/iframe/ha-panel-iframe.js index ea7826dfc3..b7ebf03359 100644 --- a/src/panels/iframe/ha-panel-iframe.js +++ b/src/panels/iframe/ha-panel-iframe.js @@ -3,7 +3,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; /* eslint-plugin-disable lit */ import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../components/ha-menu-button"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style"; class HaPanelIframe extends PolymerElement { static get template() { diff --git a/src/panels/logbook/ha-panel-logbook.js b/src/panels/logbook/ha-panel-logbook.js index 9d2c96adba..293092dc0a 100644 --- a/src/panels/logbook/ha-panel-logbook.js +++ b/src/panels/logbook/ha-panel-logbook.js @@ -14,7 +14,7 @@ import "../../components/entity/ha-entity-picker"; import "../../components/ha-menu-button"; import LocalizeMixin from "../../mixins/localize-mixin"; import "../../resources/ha-date-picker-style"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style"; import "./ha-logbook"; import "./ha-logbook-data"; diff --git a/src/panels/mailbox/ha-dialog-show-audio-message.js b/src/panels/mailbox/ha-dialog-show-audio-message.js index 64f3de1369..1088141acc 100644 --- a/src/panels/mailbox/ha-dialog-show-audio-message.js +++ b/src/panels/mailbox/ha-dialog-show-audio-message.js @@ -5,7 +5,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../components/dialog/ha-paper-dialog"; import LocalizeMixin from "../../mixins/localize-mixin"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style-dialog"; /* * @appliesMixin LocalizeMixin diff --git a/src/panels/mailbox/ha-panel-mailbox.js b/src/panels/mailbox/ha-panel-mailbox.js index 4d15814302..922d7d3d0a 100644 --- a/src/panels/mailbox/ha-panel-mailbox.js +++ b/src/panels/mailbox/ha-panel-mailbox.js @@ -15,7 +15,7 @@ import "../../components/ha-card"; import "../../components/ha-menu-button"; import { EventsMixin } from "../../mixins/events-mixin"; import LocalizeMixin from "../../mixins/localize-mixin"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style"; let registeredDialog = false; diff --git a/src/panels/map/ha-panel-map.js b/src/panels/map/ha-panel-map.js index 15850155dc..4490504b65 100644 --- a/src/panels/map/ha-panel-map.js +++ b/src/panels/map/ha-panel-map.js @@ -11,6 +11,7 @@ import "../../components/ha-menu-button"; import { defaultRadiusColor } from "../../data/zone"; import LocalizeMixin from "../../mixins/localize-mixin"; import "./ha-entity-marker"; +import "../../styles/polymer-ha-style"; /* * @appliesMixin LocalizeMixin diff --git a/src/panels/profile/ha-change-password-card.js b/src/panels/profile/ha-change-password-card.js index 93fd8aa26e..5c2588baea 100644 --- a/src/panels/profile/ha-change-password-card.js +++ b/src/panels/profile/ha-change-password-card.js @@ -6,7 +6,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../components/ha-card"; import LocalizeMixin from "../../mixins/localize-mixin"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style"; /* * @appliesMixin LocalizeMixin diff --git a/src/panels/profile/ha-long-lived-access-tokens-card.js b/src/panels/profile/ha-long-lived-access-tokens-card.js index e673444926..4b9697de48 100644 --- a/src/panels/profile/ha-long-lived-access-tokens-card.js +++ b/src/panels/profile/ha-long-lived-access-tokens-card.js @@ -12,7 +12,7 @@ import { } from "../../dialogs/generic/show-dialog-box"; import { EventsMixin } from "../../mixins/events-mixin"; import LocalizeMixin from "../../mixins/localize-mixin"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style"; import "./ha-settings-row"; /* diff --git a/src/panels/profile/ha-mfa-module-setup-flow.js b/src/panels/profile/ha-mfa-module-setup-flow.js index d8e050144f..6462dc2716 100644 --- a/src/panels/profile/ha-mfa-module-setup-flow.js +++ b/src/panels/profile/ha-mfa-module-setup-flow.js @@ -9,7 +9,7 @@ import "../../components/ha-form/ha-form"; import "../../components/ha-markdown"; import { EventsMixin } from "../../mixins/events-mixin"; import LocalizeMixin from "../../mixins/localize-mixin"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style-dialog"; let instance = 0; diff --git a/src/panels/profile/ha-mfa-modules-card.js b/src/panels/profile/ha-mfa-modules-card.js index 0dfda6b718..f350af6e10 100644 --- a/src/panels/profile/ha-mfa-modules-card.js +++ b/src/panels/profile/ha-mfa-modules-card.js @@ -8,7 +8,7 @@ import "../../components/ha-card"; import { EventsMixin } from "../../mixins/events-mixin"; import LocalizeMixin from "../../mixins/localize-mixin"; import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box"; -import "../../resources/ha-style"; +import "../../styles/polymer-ha-style"; let registeredDialog = false; diff --git a/src/panels/profile/ha-panel-profile.ts b/src/panels/profile/ha-panel-profile.ts index 429f2557f2..f32e10ce47 100644 --- a/src/panels/profile/ha-panel-profile.ts +++ b/src/panels/profile/ha-panel-profile.ts @@ -22,7 +22,6 @@ import { getOptimisticFrontendUserDataCollection, } from "../../data/frontend"; import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box"; -import "../../resources/ha-style"; import { haStyle } from "../../resources/styles"; import { HomeAssistant } from "../../types"; import "./ha-advanced-mode-row"; diff --git a/src/panels/shopping-list/ha-panel-shopping-list.js b/src/panels/shopping-list/ha-panel-shopping-list.js index 791b516864..db11be6cc0 100644 --- a/src/panels/shopping-list/ha-panel-shopping-list.js +++ b/src/panels/shopping-list/ha-panel-shopping-list.js @@ -17,6 +17,7 @@ import "../../components/ha-card"; import "../../components/ha-menu-button"; import { showVoiceCommandDialog } from "../../dialogs/voice-command-dialog/show-ha-voice-command-dialog"; import LocalizeMixin from "../../mixins/localize-mixin"; +import "../../styles/polymer-ha-style"; /* * @appliesMixin LocalizeMixin diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index 2fd3023518..6dfbfe1eed 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -1,6 +1,6 @@ import "@polymer/paper-styles/paper-styles"; import "@polymer/polymer/lib/elements/custom-style"; -import { derivedStyles, haStyle, haStyleDialog } from "./styles"; +import { derivedStyles } from "./styles"; const documentContainer = document.createElement("template"); documentContainer.setAttribute("style", "display: none;"); @@ -98,35 +98,21 @@ documentContainer.innerHTML = ` .map(([key, value]) => `--${key}: ${value};`) .join("")} } - - - - - - -`; +`; document.head.appendChild(documentContainer.content); diff --git a/src/styles/polymer-ha-style-dialog.ts b/src/styles/polymer-ha-style-dialog.ts new file mode 100644 index 0000000000..04e28b93e1 --- /dev/null +++ b/src/styles/polymer-ha-style-dialog.ts @@ -0,0 +1,15 @@ +import "@polymer/polymer/lib/elements/dom-module"; +import { haStyleDialog } from "../resources/styles"; + +const documentContainer = document.createElement("template"); +documentContainer.setAttribute("style", "display: none;"); + +documentContainer.innerHTML = ` + +`; + +document.head.appendChild(documentContainer.content); diff --git a/src/styles/polymer-ha-style.ts b/src/styles/polymer-ha-style.ts new file mode 100644 index 0000000000..22d8c38cc6 --- /dev/null +++ b/src/styles/polymer-ha-style.ts @@ -0,0 +1,15 @@ +import "@polymer/polymer/lib/elements/dom-module"; +import { haStyle } from "../resources/styles"; + +const documentContainer = document.createElement("template"); +documentContainer.setAttribute("style", "display: none;"); + +documentContainer.innerHTML = ` + +`; + +document.head.appendChild(documentContainer.content); From bfb11790a2ff06dfb6826765fa475c04285b1913 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Mon, 25 May 2020 14:46:34 +0200 Subject: [PATCH 37/77] Add translations for 'No area' strings (#6000) --- src/components/device/ha-device-picker.ts | 6 ++++-- src/panels/config/devices/ha-config-devices-dashboard.ts | 4 +++- src/translations/en.json | 6 ++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/components/device/ha-device-picker.ts b/src/components/device/ha-device-picker.ts index 73686240ec..be4fb6bbe4 100644 --- a/src/components/device/ha-device-picker.ts +++ b/src/components/device/ha-device-picker.ts @@ -52,7 +52,7 @@ const rowRenderer = (root: HTMLElement, _owner, model: { item: Device }) => { } - +
[[item.name]]
[[item.area]]
@@ -188,7 +188,9 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) { this.hass, deviceEntityLookup[device.id] ), - area: device.area_id ? areaLookup[device.area_id].name : "No area", + area: device.area_id + ? areaLookup[device.area_id].name + : this.hass.localize("ui.components.device-picker.no_area"), }; }); if (outputDevices.length === 1) { diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index 9d31f80da3..907756ad5f 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -154,7 +154,9 @@ export class HaConfigDeviceDashboard extends LitElement { ), model: device.model || "", manufacturer: device.manufacturer || "", - area: device.area_id ? areaLookup[device.area_id].name : "No area", + area: device.area_id + ? areaLookup[device.area_id].name + : this.hass.localize("ui.panel.config.devices.data_table.no_area"), integration: device.config_entries.length ? device.config_entries .filter((entId) => entId in entryLookup) diff --git a/src/translations/en.json b/src/translations/en.json index c3791de3ef..8817ecd26f 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -258,7 +258,8 @@ "clear": "Clear", "toggle": "Toggle", "show_devices": "Show devices", - "device": "Device" + "device": "Device", + "no_area": "No area" }, "area-picker": { "clear": "Clear", @@ -1244,7 +1245,8 @@ "area": "Area", "integration": "Integration", "battery": "Battery", - "no_devices": "No devices" + "no_devices": "No devices", + "no_area": "No area" }, "delete": "Delete", "confirm_delete": "Are you sure you want to delete this device?" From deb179ad38b69279e7a52e11b0718bc9ba983c51 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Mon, 25 May 2020 14:50:58 +0200 Subject: [PATCH 38/77] Add translation to the back button on the helpers page (#5999) --- src/panels/config/helpers/dialog-helper-detail.ts | 2 +- src/translations/en.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/panels/config/helpers/dialog-helper-detail.ts b/src/panels/config/helpers/dialog-helper-detail.ts index f52d5c5178..b22ca67e77 100644 --- a/src/panels/config/helpers/dialog-helper-detail.ts +++ b/src/panels/config/helpers/dialog-helper-detail.ts @@ -108,7 +108,7 @@ export class DialogHelperDetail extends LitElement { @click="${this._goBack}" .disabled=${this._submitting} > - Back + ${this.hass!.localize("ui.common.back")} ` : html` diff --git a/src/translations/en.json b/src/translations/en.json index 8817ecd26f..b05c162ca2 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -244,7 +244,8 @@ "yes": "Yes", "no": "No", "successfully_saved": "Successfully saved", - "successfully_deleted": "Successfully deleted" + "successfully_deleted": "Successfully deleted", + "back": "Back" }, "components": { "entity": { From acc024bcf9e9db81a08db72f01626fcacf362a93 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 25 May 2020 16:47:21 +0200 Subject: [PATCH 39/77] Fix entity marker border color (#6041) --- src/panels/map/ha-entity-marker.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/panels/map/ha-entity-marker.js b/src/panels/map/ha-entity-marker.js index 21c399bf62..2fb0a59637 100644 --- a/src/panels/map/ha-entity-marker.js +++ b/src/panels/map/ha-entity-marker.js @@ -23,8 +23,7 @@ class HaEntityMarker extends EventsMixin(PolymerElement) { line-height: 2.5em; font-size: 1.5em; border-radius: 50%; - border: 0.1em solid - var(--ha-marker-color, var(--default-primary-color)); + border: 0.1em solid var(--ha-marker-color, var(--primary-color)); color: rgb(76, 76, 76); background-color: white; } From d73b3d77ea05030ecff7d7d51e73247abb10be17 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 25 May 2020 09:55:50 -0700 Subject: [PATCH 40/77] Split out HTML imports from entrypoint (#6030) --- src/entrypoints/app.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/entrypoints/app.ts b/src/entrypoints/app.ts index 2e9f6294e0..934affb498 100644 --- a/src/entrypoints/app.ts +++ b/src/entrypoints/app.ts @@ -2,7 +2,6 @@ import { setPassiveTouchGestures } from "@polymer/polymer/lib/utils/settings"; import "../resources/roboto"; import "../resources/ha-style"; import "../layouts/home-assistant"; -import "../resources/html-import/polyfill"; import "../util/legacy-support"; setPassiveTouchGestures(true); @@ -10,3 +9,5 @@ setPassiveTouchGestures(true); document.createElement = Document.prototype.createElement; (window as any).frontendVersion = __VERSION__; + +import("../resources/html-import/polyfill"); From 050cdf3783acfb9e6870c3380e8ef2a87489430b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 25 May 2020 10:36:22 -0700 Subject: [PATCH 41/77] Integrate compatibility into other entrypoints (#6029) --- build-scripts/bundle.js | 10 +++---- build-scripts/gulp/entry-html.js | 6 ----- build-scripts/rollup-plugins/ignore-plugin.js | 26 ------------------- demo/src/ha-demo.ts | 1 + demo/src/html/index.html.template | 5 +--- src/entrypoints/authorize.ts | 2 ++ src/entrypoints/core.ts | 2 ++ src/entrypoints/custom-panel.ts | 2 +- src/entrypoints/onboarding.ts | 2 ++ src/html/authorize.html.template | 5 +--- src/html/index.html.template | 5 +--- src/html/onboarding.html.template | 5 +--- .../compatibility.ts | 0 13 files changed, 16 insertions(+), 55 deletions(-) rename src/{entrypoints => resources}/compatibility.ts (100%) diff --git a/build-scripts/bundle.js b/build-scripts/bundle.js index 6123a7a095..c62c9175e9 100644 --- a/build-scripts/bundle.js +++ b/build-scripts/bundle.js @@ -20,7 +20,10 @@ module.exports.emptyPackages = ({ latestBuild }) => // Loads stuff from a CDN require.resolve("@polymer/font-roboto/roboto.js"), require.resolve("@vaadin/vaadin-material-styles/font-roboto.js"), - // Polyfill only needed for ES5 workers so filter out in latestBuild + // Compatibility not needed for latest builds + latestBuild && + path.resolve(paths.polymer_dir, "src/entrypoints/compatibility.ts"), + // This polyfill is loaded in workers to support ES5, filter it out. latestBuild && require.resolve("proxy-polyfill/src/index.js"), ].filter(Boolean); @@ -112,7 +115,6 @@ module.exports.config = { authorize: "./src/entrypoints/authorize.ts", onboarding: "./src/entrypoints/onboarding.ts", core: "./src/entrypoints/core.ts", - compatibility: "./src/entrypoints/compatibility.ts", "custom-panel": "./src/entrypoints/custom-panel.ts", }, outputPath: outputPath(paths.app_output_root, latestBuild), @@ -127,10 +129,6 @@ module.exports.config = { return { entry: { main: path.resolve(paths.demo_dir, "src/entrypoint.ts"), - compatibility: path.resolve( - paths.polymer_dir, - "src/entrypoints/compatibility.ts" - ), }, outputPath: outputPath(paths.demo_output_root, latestBuild), publicPath: publicPath(latestBuild), diff --git a/build-scripts/gulp/entry-html.js b/build-scripts/gulp/entry-html.js index 9af75cf318..c1be430039 100644 --- a/build-scripts/gulp/entry-html.js +++ b/build-scripts/gulp/entry-html.js @@ -53,7 +53,6 @@ gulp.task("gen-pages-dev", (done) => { const content = renderTemplate(page, { latestPageJS: `/frontend_latest/${page}.js`, - es5Compatibility: "/frontend_es5/compatibility.js", es5PageJS: `/frontend_es5/${page}.js`, }); @@ -79,7 +78,6 @@ gulp.task("gen-pages-prod", (done) => { const content = renderTemplate(page, { latestPageJS: latestManifest[`${page}.js`], - es5Compatibility: es5Manifest["compatibility.js"], es5PageJS: es5Manifest[`${page}.js`], }); @@ -99,7 +97,6 @@ gulp.task("gen-index-app-dev", (done) => { latestCoreJS: "/frontend_latest/core.js", latestCustomPanelJS: "/frontend_latest/custom-panel.js", - es5Compatibility: "/frontend_es5/compatibility.js", es5AppJS: "/frontend_es5/app.js", es5CoreJS: "/frontend_es5/core.js", es5CustomPanelJS: "/frontend_es5/custom-panel.js", @@ -123,7 +120,6 @@ gulp.task("gen-index-app-prod", (done) => { latestCoreJS: latestManifest["core.js"], latestCustomPanelJS: latestManifest["custom-panel.js"], - es5Compatibility: es5Manifest["compatibility.js"], es5AppJS: es5Manifest["app.js"], es5CoreJS: es5Manifest["core.js"], es5CustomPanelJS: es5Manifest["custom-panel.js"], @@ -210,7 +206,6 @@ gulp.task("gen-index-demo-dev", (done) => { const content = renderDemoTemplate("index", { latestDemoJS: "/frontend_latest/main.js", - es5Compatibility: "/frontend_es5/compatibility.js", es5DemoJS: "/frontend_es5/main.js", }); @@ -233,7 +228,6 @@ gulp.task("gen-index-demo-prod", (done) => { const content = renderDemoTemplate("index", { latestDemoJS: latestManifest["main.js"], - es5Compatibility: es5Manifest["compatibility.js"], es5DemoJS: es5Manifest["main.js"], }); const minified = minifyHtml(content); diff --git a/build-scripts/rollup-plugins/ignore-plugin.js b/build-scripts/rollup-plugins/ignore-plugin.js index e696bbe6c9..4bebb69095 100644 --- a/build-scripts/rollup-plugins/ignore-plugin.js +++ b/build-scripts/rollup-plugins/ignore-plugin.js @@ -14,32 +14,6 @@ module.exports = function (userOptions = {}) { return { name: "ignore", - resolveId(importee, importer) { - // Only use ignore to intercept imports that we don't control - // inside node_module dependencies. - if ( - importee.endsWith("commonjsHelpers.js") || - importee.endsWith("rollupPluginBabelHelpers.js") || - importee.endsWith("?commonjs-proxy") || - !importer || - !importer.includes("/node_modules/") - ) { - return null; - } - let fullPath; - try { - fullPath = importee.startsWith(".") - ? path.resolve(importee, importer) - : require.resolve(importee); - } catch (err) { - console.error("Error in ignore plugin", { importee, importer }, err); - throw err; - } - - return files.some((toIgnorePath) => fullPath.startsWith(toIgnorePath)) - ? fullPath - : null; - }, load(id) { return files.some((toIgnorePath) => id.startsWith(toIgnorePath)) diff --git a/demo/src/ha-demo.ts b/demo/src/ha-demo.ts index 6fd33b7f57..c49d522d65 100644 --- a/demo/src/ha-demo.ts +++ b/demo/src/ha-demo.ts @@ -1,3 +1,4 @@ +import "../../src/resources/compatibility"; import { isNavigationClick } from "../../src/common/dom/is-navigation-click"; import { navigate } from "../../src/common/navigate"; import { diff --git a/demo/src/html/index.html.template b/demo/src/html/index.html.template index c626161b69..dc3d4994e2 100644 --- a/demo/src/html/index.html.template +++ b/demo/src/html/index.html.template @@ -106,12 +106,9 @@ _ls("/static/polyfills/custom-elements-es5-adapter.js"); <% if (useRollup) { %> _ls("/static/js/s.min.js").onload = function() { - System.import("<%= es5Compatibility %>").then(function() { - System.import("<%= es5DemoJS %>"); - }); + System.import("<%= es5DemoJS %>"); }; <% } else { %> - _ls("<%= es5Compatibility %>"); _ls("<%= es5DemoJS %>"); <% } %> } diff --git a/src/entrypoints/authorize.ts b/src/entrypoints/authorize.ts index 959a8fc0ef..2a691c973f 100644 --- a/src/entrypoints/authorize.ts +++ b/src/entrypoints/authorize.ts @@ -1,3 +1,5 @@ +// Compat needs to be first import +import "../resources/compatibility"; import "@polymer/polymer/lib/elements/dom-if"; import "@polymer/polymer/lib/elements/dom-repeat"; import "../auth/ha-authorize"; diff --git a/src/entrypoints/core.ts b/src/entrypoints/core.ts index a80af0d428..dc2ee49e8b 100644 --- a/src/entrypoints/core.ts +++ b/src/entrypoints/core.ts @@ -1,3 +1,5 @@ +// Compat needs to be first import +import "../resources/compatibility"; import { Auth, Connection, diff --git a/src/entrypoints/custom-panel.ts b/src/entrypoints/custom-panel.ts index 6ba448c0b4..82d6cb4267 100644 --- a/src/entrypoints/custom-panel.ts +++ b/src/entrypoints/custom-panel.ts @@ -21,7 +21,7 @@ window.loadES5Adapter = () => { loadJS( `${__STATIC_PATH__}polyfills/custom-elements-es5-adapter.js` ).catch(), - import(/* webpackChunkName: "compat" */ "./compatibility"), + import(/* webpackChunkName: "compat" */ "../resources/compatibility"), ]); } return es5Loaded; diff --git a/src/entrypoints/onboarding.ts b/src/entrypoints/onboarding.ts index ffe47dc55e..0c30daed0a 100644 --- a/src/entrypoints/onboarding.ts +++ b/src/entrypoints/onboarding.ts @@ -1,3 +1,5 @@ +// Compat needs to be first import +import "../resources/compatibility"; import "../onboarding/ha-onboarding"; import "../resources/ha-style"; import "../resources/roboto"; diff --git a/src/html/authorize.html.template b/src/html/authorize.html.template index ed3bbb27b0..f57c709147 100644 --- a/src/html/authorize.html.template +++ b/src/html/authorize.html.template @@ -61,12 +61,9 @@ _ls("/static/polyfills/custom-elements-es5-adapter.js"); <% if (useRollup) { %> _ls("/static/js/s.min.js").onload = function() { - System.import("<%= es5Compatibility %>").then(function() { - System.import("<%= es5PageJS %>"); - }); + System.import("<%= es5PageJS %>"); } <% } else { %> - _ls("<%= es5Compatibility %>"); _ls("<%= es5PageJS %>"); <% } %> } diff --git a/src/html/index.html.template b/src/html/index.html.template index 47deba231b..231534cdcc 100644 --- a/src/html/index.html.template +++ b/src/html/index.html.template @@ -81,14 +81,11 @@ <% if (useRollup) { %> _ls("/static/js/s.min.js").onload = function() { - System.import("<%= es5Compatibility %>").then(function() { - return System.import("<%= es5CoreJS %>"); - }).then(function() { + return System.import("<%= es5CoreJS %>").then(function() { System.import("<%= es5AppJS %>"); }); } <% } else { %> - _ls("<%= es5Compatibility %>"); _ls("<%= es5CoreJS %>"); _ls("<%= es5AppJS %>"); <% } %> diff --git a/src/html/onboarding.html.template b/src/html/onboarding.html.template index 00a5826ef1..ef2eb537c5 100644 --- a/src/html/onboarding.html.template +++ b/src/html/onboarding.html.template @@ -63,12 +63,9 @@ _ls("/static/polyfills/custom-elements-es5-adapter.js"); <% if (useRollup) { %> _ls("/static/js/s.min.js").onload = function() { - System.import("<%= es5Compatibility %>").then(function() { - System.import("<%= es5PageJS %>"); - }); + System.import("<%= es5PageJS %>"); } <% } else { %> - _ls("<%= es5Compatibility %>"); _ls("<%= es5PageJS %>"); <% } %> } diff --git a/src/entrypoints/compatibility.ts b/src/resources/compatibility.ts similarity index 100% rename from src/entrypoints/compatibility.ts rename to src/resources/compatibility.ts From 2fd64af737ec4860d177789f235a4947e9c70649 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 25 May 2020 19:36:47 +0200 Subject: [PATCH 42/77] Dont recreate resize observers and replace polyfill (#6043) --- package.json | 2 +- src/data/area_registry.ts | 18 +++++++--- src/panels/lovelace/cards/hui-gauge-card.ts | 13 +++---- src/panels/lovelace/cards/hui-map-card.ts | 34 ++++++------------- .../lovelace/cards/hui-media-control-card.ts | 12 ++++--- .../cards/hui-weather-forecast-card.ts | 7 ++-- .../common/install-resize-observer.ts | 3 +- .../hui-media-player-entity-row.ts | 34 +++++++++---------- yarn.lock | 5 --- 9 files changed, 61 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index b6485dd03d..e069fc7c98 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "node-vibrant": "^3.1.5", "proxy-polyfill": "^0.3.1", "regenerator-runtime": "^0.13.2", - "resize-observer": "^1.0.0", + "resize-observer-polyfill": "^1.5.1", "roboto-fontface": "^0.10.0", "superstruct": "^0.6.1", "unfetch": "^4.1.0", diff --git a/src/data/area_registry.ts b/src/data/area_registry.ts index 63e8a38301..d59a7ff69d 100644 --- a/src/data/area_registry.ts +++ b/src/data/area_registry.ts @@ -2,6 +2,7 @@ import { Connection, createCollection } from "home-assistant-js-websocket"; import { compare } from "../common/string/compare"; import { debounce } from "../common/util/debounce"; import { HomeAssistant } from "../types"; +import { Store } from "home-assistant-js-websocket/dist/store"; export interface AreaRegistryEntry { area_id: string; @@ -38,18 +39,27 @@ export const deleteAreaRegistryEntry = (hass: HomeAssistant, areaId: string) => area_id: areaId, }); -const fetchAreaRegistry = (conn) => +const fetchAreaRegistry = (conn: Connection) => conn .sendMessagePromise({ type: "config/area_registry/list", }) - .then((areas) => areas.sort((ent1, ent2) => compare(ent1.name, ent2.name))); + .then((areas) => + (areas as AreaRegistryEntry[]).sort((ent1, ent2) => + compare(ent1.name, ent2.name) + ) + ); -const subscribeAreaRegistryUpdates = (conn, store) => +const subscribeAreaRegistryUpdates = ( + conn: Connection, + store: Store +) => conn.subscribeEvents( debounce( () => - fetchAreaRegistry(conn).then((areas) => store.setState(areas, true)), + fetchAreaRegistry(conn).then((areas: AreaRegistryEntry[]) => + store.setState(areas, true) + ), 500, true ), diff --git a/src/panels/lovelace/cards/hui-gauge-card.ts b/src/panels/lovelace/cards/hui-gauge-card.ts index c13ff98fef..37d9f761af 100644 --- a/src/panels/lovelace/cards/hui-gauge-card.ts +++ b/src/panels/lovelace/cards/hui-gauge-card.ts @@ -175,6 +175,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { } protected firstUpdated(): void { + this._measureCard(); this._attachObserver(); } @@ -236,10 +237,12 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { } private async _attachObserver(): Promise { - await installResizeObserver(); - - this._resizeObserver = new ResizeObserver(this._debouncedMeasure); - + if (!this._resizeObserver) { + await installResizeObserver(); + this._resizeObserver = new ResizeObserver( + debounce(() => this._measureCard(), 250, false) + ); + } const card = this.shadowRoot!.querySelector("ha-card"); // If we show an error or warning there is no ha-card if (!card) { @@ -248,8 +251,6 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { this._resizeObserver.observe(card); } - private _debouncedMeasure = debounce(() => this._measureCard(), 250, true); - private _measureCard() { if (!this.isConnected) { return; diff --git a/src/panels/lovelace/cards/hui-map-card.ts b/src/panels/lovelace/cards/hui-map-card.ts index 1a8f72a1b4..de7bd3a434 100644 --- a/src/panels/lovelace/cards/hui-map-card.ts +++ b/src/panels/lovelace/cards/hui-map-card.ts @@ -39,6 +39,7 @@ import { EntityConfig } from "../entity-rows/types"; import { LovelaceCard } from "../types"; import "../../../components/ha-card"; import { MapCardConfig } from "./types"; +import { installResizeObserver } from "../common/install-resize-observer"; @customElement("hui-map-card") class HuiMapCard extends LitElement implements LovelaceCard { @@ -90,17 +91,16 @@ class HuiMapCard extends LitElement implements LovelaceCard { private _leafletMap?: Map; - // @ts-ignore private _resizeObserver?: ResizeObserver; private _debouncedResizeListener = debounce( () => { - if (!this._leafletMap) { + if (!this.isConnected || !this._leafletMap) { return; } this._leafletMap.invalidateSize(); }, - 100, + 250, false ); @@ -110,8 +110,6 @@ class HuiMapCard extends LitElement implements LovelaceCard { private _mapPaths: Array = []; - private _connected = false; - private _colorDict: { [key: string]: string } = {}; private _colorIndex = 0; @@ -174,16 +172,14 @@ class HuiMapCard extends LitElement implements LovelaceCard { public connectedCallback(): void { super.connectedCallback(); - this._connected = true; + this._attachObserver(); if (this.hasUpdated) { this.loadMap(); - this._attachObserver(); } } public disconnectedCallback(): void { super.disconnectedCallback(); - this._connected = false; if (this._leafletMap) { this._leafletMap.remove(); @@ -193,8 +189,6 @@ class HuiMapCard extends LitElement implements LovelaceCard { if (this._resizeObserver) { this._resizeObserver.unobserve(this._mapEl); - } else { - window.removeEventListener("resize", this._debouncedResizeListener); } } @@ -250,9 +244,7 @@ class HuiMapCard extends LitElement implements LovelaceCard { return; } - if (this._connected) { - this._attachObserver(); - } + this._attachObserver(); if (!this._config.aspect_ratio) { root.style.paddingBottom = "100%"; @@ -564,20 +556,14 @@ class HuiMapCard extends LitElement implements LovelaceCard { this._mapPaths.forEach((marker) => map.addLayer(marker)); } - private _attachObserver(): void { + private async _attachObserver(): Promise { // Observe changes to map size and invalidate to prevent broken rendering - // Uses ResizeObserver in Chrome, otherwise window resize event - // @ts-ignore - if (typeof ResizeObserver === "function") { - // @ts-ignore - this._resizeObserver = new ResizeObserver(() => - this._debouncedResizeListener() - ); - this._resizeObserver.observe(this._mapEl); - } else { - window.addEventListener("resize", this._debouncedResizeListener); + if (!this._resizeObserver) { + await installResizeObserver(); + this._resizeObserver = new ResizeObserver(this._debouncedResizeListener); } + this._resizeObserver.observe(this); } private async _getHistory(): Promise { diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index c7e5ba8319..340689a843 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -431,6 +431,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { } protected firstUpdated(): void { + this._measureCard(); this._attachObserver(); } @@ -618,8 +619,6 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { ); } - private _debouncedMeasure = debounce(() => this._measureCard(), 250, true); - private _measureCard() { const card = this.shadowRoot!.querySelector("ha-card"); if (!card) { @@ -631,9 +630,12 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { } private async _attachObserver(): Promise { - await installResizeObserver(); - this._resizeObserver = new ResizeObserver(this._debouncedMeasure); - + if (!this._resizeObserver) { + await installResizeObserver(); + this._resizeObserver = new ResizeObserver( + debounce(() => this._measureCard(), 250, false) + ); + } const card = this.shadowRoot!.querySelector("ha-card"); // If we show an error or warning there is no ha-card if (!card) { diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index e2b49a2d4b..23155a918a 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -102,6 +102,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { } protected firstUpdated(): void { + this._measureCard(); this._attachObserver(); } @@ -292,7 +293,9 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { private async _attachObserver(): Promise { if (!this._resizeObserver) { await installResizeObserver(); - this._resizeObserver = new ResizeObserver(this._debouncedMeasure); + this._resizeObserver = new ResizeObserver( + debounce(() => this._measureCard(), 250, false) + ); } const card = this.shadowRoot!.querySelector("ha-card"); // If we show an error or warning there is no ha-card @@ -302,8 +305,6 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { this._resizeObserver.observe(card); } - private _debouncedMeasure = debounce(() => this._measureCard(), 250, true); - private _measureCard() { if (!this.isConnected) { return; diff --git a/src/panels/lovelace/common/install-resize-observer.ts b/src/panels/lovelace/common/install-resize-observer.ts index f675858d99..1018ea38ca 100644 --- a/src/panels/lovelace/common/install-resize-observer.ts +++ b/src/panels/lovelace/common/install-resize-observer.ts @@ -1,6 +1,5 @@ export const installResizeObserver = async () => { if (typeof ResizeObserver !== "function") { - const modules = await import("resize-observer"); - modules.install(); + window.ResizeObserver = (await import("resize-observer-polyfill")).default; } }; diff --git a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts index ba9da31e08..16bed1f07b 100644 --- a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts @@ -47,15 +47,6 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { private _resizeObserver?: ResizeObserver; - private _debouncedResizeListener = debounce( - () => { - this._narrow = (this.clientWidth || 0) < 300; - this._veryNarrow = (this.clientWidth || 0) < 225; - }, - 250, - true - ); - public setConfig(config: EntityConfig): void { if (!config || !config.entity) { throw new Error("Invalid Configuration: 'entity' required"); @@ -66,9 +57,7 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { public connectedCallback(): void { super.connectedCallback(); - if (!this._resizeObserver) { - this._attachObserver(); - } + this._attachObserver(); } public disconnectedCallback(): void { @@ -76,6 +65,7 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { } protected firstUpdated(): void { + this._measureCard(); this._attachObserver(); } @@ -214,12 +204,22 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { `; } - private _attachObserver(): void { - installResizeObserver().then(() => { - this._resizeObserver = new ResizeObserver(this._debouncedResizeListener); + private async _attachObserver(): Promise { + if (!this._resizeObserver) { + await installResizeObserver(); + this._resizeObserver = new ResizeObserver( + debounce(() => this._measureCard(), 250, false) + ); + } + this._resizeObserver.observe(this); + } - this._resizeObserver.observe(this); - }); + private _measureCard() { + if (!this.isConnected) { + return; + } + this._narrow = (this.clientWidth || 0) < 300; + this._veryNarrow = (this.clientWidth || 0) < 225; } private _computeControlIcon(stateObj: HassEntity): string { diff --git a/yarn.lock b/yarn.lock index 14e56d7066..1dc67290fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12758,11 +12758,6 @@ resize-observer-polyfill@^1.5.1: resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== -resize-observer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resize-observer/-/resize-observer-1.0.0.tgz#4f8380b73b411af4ed7d916fe85a2d59900e71ef" - integrity sha512-D7UFShDm2TgrEDEyeg+/tTEbvOgPWlvPAfJtxiKp+qutu6HowmcGJKjECgGru0PPDIj3SAucn3ZPpOx54fF7DQ== - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" From 6b8cfe661c341057262b33aa6621c018e235a3a2 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Mon, 25 May 2020 19:37:17 +0200 Subject: [PATCH 43/77] Add missing translations on the area registry page (#5998) --- .../areas/dialog-area-registry-detail.ts | 21 +++++++++++++++---- src/translations/en.json | 6 +++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/panels/config/areas/dialog-area-registry-detail.ts b/src/panels/config/areas/dialog-area-registry-detail.ts index cf6b1a32a1..63a4360c7f 100644 --- a/src/panels/config/areas/dialog-area-registry-detail.ts +++ b/src/panels/config/areas/dialog-area-registry-detail.ts @@ -56,13 +56,24 @@ class DialogAreaDetail extends LitElement { ${this._error ? html`
${this._error}
` : ""}
- ${entry ? html`
Area ID: ${entry.area_id}
` : ""} + ${entry + ? html` +
+ ${this.hass.localize( + "ui.panel.config.areas.editor.area_id" + )}: + ${entry.area_id} +
+ ` + : ""}
@@ -110,7 +121,9 @@ class DialogAreaDetail extends LitElement { } this._params = undefined; } catch (err) { - this._error = err.message || "Unknown error"; + this._error = + err.message || + this.hass.localize("ui.panel.config.areas.editor.unknown_error"); } finally { this._submitting = false; } diff --git a/src/translations/en.json b/src/translations/en.json index b05c162ca2..556fe91f9a 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -541,7 +541,11 @@ "default_name": "New Area", "delete": "Delete", "update": "Update", - "create": "Create" + "create": "Create", + "name": "Name", + "name_required": "Name is required", + "area_id": "Area ID", + "unknown_error": "Unknown error" }, "delete": { "confirmation_title": "Are you sure you want to delete this area?", From 3faebaeb4bd7dec074932846b622c2c435f775f5 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Mon, 25 May 2020 19:37:44 +0200 Subject: [PATCH 44/77] Add missing translations to actions, triggers and conditions of device automations (#6002) --- .../action/types/ha-automation-action-device_id.ts | 10 +++++++--- .../condition/types/ha-automation-condition-device.ts | 8 ++++++-- .../trigger/types/ha-automation-trigger-device.ts | 8 ++++++-- src/translations/en.json | 3 +++ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/panels/config/automation/action/types/ha-automation-action-device_id.ts b/src/panels/config/automation/action/types/ha-automation-action-device_id.ts index db56b9aa84..059d1835eb 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-device_id.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-device_id.ts @@ -51,14 +51,18 @@ export class HaDeviceAction extends LitElement { .value=${deviceId} @value-changed=${this._devicePicked} .hass=${this.hass} - label="Device" + label=${this.hass.localize( + "ui.panel.config.automation.editor.actions.type.device_id.label" + )} > ${extraFieldsData ? html` @@ -125,7 +129,7 @@ export class HaDeviceAction extends LitElement { // Returns a callback for ha-form to calculate labels per schema object return (schema) => localize( - `ui.panel.config.automation.editor.actions.type.device.extra_fields.${schema.name}` + `ui.panel.config.automation.editor.actions.type.device_id.extra_fields.${schema.name}` ) || schema.name; } } diff --git a/src/panels/config/automation/condition/types/ha-automation-condition-device.ts b/src/panels/config/automation/condition/types/ha-automation-condition-device.ts index 8ce4b90277..40eca3eb45 100644 --- a/src/panels/config/automation/condition/types/ha-automation-condition-device.ts +++ b/src/panels/config/automation/condition/types/ha-automation-condition-device.ts @@ -45,14 +45,18 @@ export class HaDeviceCondition extends LitElement { .value=${deviceId} @value-changed=${this._devicePicked} .hass=${this.hass} - label="Device" + label=${this.hass.localize( + "ui.panel.config.automation.editor.conditions.type.device.label" + )} > ${extraFieldsData ? html` diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts index bc41a6da57..1dea9a2391 100644 --- a/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts +++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts @@ -45,14 +45,18 @@ export class HaDeviceTrigger extends LitElement { .value=${deviceId} @value-changed=${this._devicePicked} .hass=${this.hass} - label="Device" + label=${this.hass.localize( + "ui.panel.config.automation.editor.triggers.type.device.label" + )} > ${extraFieldsData ? html` diff --git a/src/translations/en.json b/src/translations/en.json index 556fe91f9a..d297cc2d3e 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -781,6 +781,7 @@ "type": { "device": { "label": "Device", + "trigger": "Trigger", "extra_fields": { "above": "Above", "below": "Below", @@ -875,6 +876,7 @@ }, "device": { "label": "Device", + "condition": "Condition", "extra_fields": { "above": "Above", "below": "Below", @@ -957,6 +959,7 @@ }, "device_id": { "label": "Device", + "action": "Action", "extra_fields": { "code": "Code" } From cf5e808a96173148c79e4d6a45ac980131df1502 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 25 May 2020 21:57:04 +0200 Subject: [PATCH 45/77] Remove mwc-icon-button from dev tools states (#6046) --- .../developer-tools/state/developer-tools-state.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/panels/developer-tools/state/developer-tools-state.js b/src/panels/developer-tools/state/developer-tools-state.js index 5febdc282e..f846418520 100644 --- a/src/panels/developer-tools/state/developer-tools-state.js +++ b/src/panels/developer-tools/state/developer-tools-state.js @@ -1,5 +1,4 @@ import "@material/mwc-button"; -import "@material/mwc-icon-button"; import "@polymer/paper-checkbox/paper-checkbox"; import "@polymer/paper-input/paper-input"; import { html } from "@polymer/polymer/lib/utils/html-tag"; @@ -59,9 +58,10 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) { .entities td { padding: 4px; } - .entities mwc-icon-button { - --mdc-icon-button-size: 24px; + .entities ha-svg-icon { --mdc-icon-size: 20px; + padding: 4px; + cursor: pointer; } .entities td:nth-child(3) { white-space: pre-wrap; @@ -153,12 +153,12 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) { @@ -91,7 +103,7 @@ class ZwaveGroups extends PolymerElement { service="change_association" service-data="[[_addAssocServiceData]]" > - Add To Group + [[localize('ui.panel.config.zwave.node_management.add_to_group')]]
diff --git a/src/panels/config/zwave/zwave-log.js b/src/panels/config/zwave/zwave-log.js index 1c05969536..05ea015bb6 100755 --- a/src/panels/config/zwave/zwave-log.js +++ b/src/panels/config/zwave/zwave-log.js @@ -42,12 +42,12 @@ class OzwLog extends LocalizeMixin(EventsMixin(PolymerElement)) {
- +
- Load - Tail + [[localize('ui.panel.config.zwave.ozw_log.load')]] + [[localize('ui.panel.config.zwave.ozw_log.tail')]] `; diff --git a/src/panels/config/zwave/zwave-node-protection.js b/src/panels/config/zwave/zwave-node-protection.js index b3ff759a64..292fb80bfe 100644 --- a/src/panels/config/zwave/zwave-node-protection.js +++ b/src/panels/config/zwave/zwave-node-protection.js @@ -33,9 +33,9 @@ class ZwaveNodeProtection extends PolymerElement {
- +
- +