Compare commits

...

12 Commits

Author SHA1 Message Date
Bram Kragten
48543a2dad Bumped version to 20201021.2 2020-10-23 00:18:49 +02:00
Philip Allgaier
b22f5ae5c2 Add outline color for dark buttons (#7444) 2020-10-23 00:18:26 +02:00
J. Nick Koston
2acb6a28fe Update template time listener phrasing for core changes (#7450) 2020-10-23 00:16:40 +02:00
Donnie
1064cdb79d Fix quick bar dark mode contrast, filter returning all items, no primary text (#7430)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-10-23 00:16:18 +02:00
Bram Kragten
bd7cb1c877 Template dev tools: Print the type of the response and stringify objects (#7439) 2020-10-23 00:15:57 +02:00
Bram Kragten
6c314982dc Pass narrow to masonry view to calc columns (#7454) 2020-10-23 00:15:36 +02:00
Philip Allgaier
d54710f113 Fix capitalization of state attributes (#7448) 2020-10-23 00:15:20 +02:00
J. Nick Koston
1346156ecd Avoid fetching logbook data instead in addition to not displaying it (#7427)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2020-10-23 00:15:04 +02:00
Bram Kragten
a2d9f9b417 Fix ES5 build, fix virtualizer polyfill (#7451) 2020-10-23 00:14:48 +02:00
Bram Kragten
3de78cca2d Fix quickbar debounce (#7426)
* Fix quicbar debounce

* Clear search property when dialog is closed

Co-authored-by: Donnie <donniekarnsinsb@hotmail.com>
2020-10-23 00:14:28 +02:00
Bram Kragten
a27680b8c0 Merge pull request #7424 from home-assistant/dev 2020-10-21 23:43:52 +02:00
Bram Kragten
73be0fef75 Merge pull request #7422 from home-assistant/dev
20201021.0
2020-10-21 19:21:45 +02:00
22 changed files with 162 additions and 74 deletions

View File

@@ -55,7 +55,6 @@ module.exports.babelOptions = ({ latestBuild }) => ({
!latestBuild && [
require("@babel/preset-env").default,
{
modules: false,
useBuiltIns: "entry",
corejs: "3.6",
},
@@ -71,7 +70,6 @@ module.exports.babelOptions = ({ latestBuild }) => ({
// Only support the syntax, Webpack will handle it.
"@babel/plugin-syntax-import-meta",
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-top-level-await",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
[

View File

@@ -51,9 +51,6 @@ const createWebpackConfig = ({
}),
],
},
experiments: {
topLevelAwait: true,
},
plugins: [
new ManifestPlugin({
// Only include the JS of entrypoints
@@ -98,6 +95,15 @@ const createWebpackConfig = ({
new RegExp(bundle.emptyPackages({ latestBuild }).join("|")),
path.resolve(paths.polymer_dir, "src/util/empty.js")
),
// We need to change the import of the polyfill for EventTarget, so we replace the polyfill file with our customized one
new webpack.NormalModuleReplacementPlugin(
new RegExp(
require.resolve(
"lit-virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js"
)
),
path.resolve(paths.polymer_dir, "src/resources/EventTarget-ponyfill.js")
),
],
resolve: {
extensions: [".ts", ".js", ".json"],

View File

@@ -139,7 +139,6 @@
"@babel/plugin-proposal-optional-chaining": "^7.11.0",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-import-meta": "^7.10.4",
"@babel/plugin-syntax-top-level-await": "^7.10.4",
"@babel/preset-env": "^7.11.5",
"@babel/preset-typescript": "^7.10.4",
"@rollup/plugin-commonjs": "^11.1.0",

View File

@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="home-assistant-frontend",
version="20201021.1",
version="20201021.2",
description="The Home Assistant frontend",
url="https://github.com/home-assistant/home-assistant-polymer",
author="The Home Assistant Authors",

View File

@@ -59,7 +59,7 @@ export const fuzzyFilterSort: FuzzyFilterSort = (filter, items) => {
: fuzzySequentialMatch(filter, item.text);
return item;
})
.filter((item) => item.score === undefined || item.score > 0)
.filter((item) => item.score !== undefined && item.score > 0)
.sort(({ score: scoreA = 0 }, { score: scoreB = 0 }) =>
scoreA > scoreB ? -1 : scoreA < scoreB ? 1 : 0
);

View File

@@ -13,9 +13,12 @@ export interface FormatsType {
time: FormatType;
}
if (shouldPolyfill()) {
await import("@formatjs/intl-pluralrules/polyfill-locales");
}
let polyfillLoaded = !shouldPolyfill();
const polyfillProm = polyfillLoaded
? import("@formatjs/intl-pluralrules/polyfill-locales").then(() => {
polyfillLoaded = true;
})
: undefined;
/**
* Adapted from Polymer app-localize-behavior.
@@ -38,12 +41,16 @@ if (shouldPolyfill()) {
* }
*/
export const computeLocalize = (
export const computeLocalize = async (
cache: any,
language: string,
resources: Resources,
formats?: FormatsType
): LocalizeFunc => {
): Promise<LocalizeFunc> => {
if (!polyfillLoaded) {
await polyfillProm;
}
// Everytime any of the parameters change, invalidate the strings cache.
cache._localizationCache = {};

View File

@@ -34,7 +34,7 @@ class HaAttributes extends LitElement {
(attribute) => html`
<div class="data-entry">
<div class="key">
${attribute.replace(/_/g, " ").replace("id", "ID")}
${attribute.replace(/_/g, " ").replace(/\bid\b/g, "ID")}
</div>
<div class="value">
${this.formatAttribute(attribute)}

View File

@@ -89,6 +89,7 @@ export interface LovelaceViewConfig {
export interface LovelaceViewElement extends HTMLElement {
hass?: HomeAssistant;
lovelace?: Lovelace;
narrow?: boolean;
index?: number;
cards?: Array<LovelaceCard | HuiErrorCard>;
badges?: LovelaceBadge[];

View File

@@ -38,6 +38,7 @@ import { showConfirmationDialog } from "../generic/show-dialog-box";
import "./ha-more-info-history";
import "./ha-more-info-logbook";
import "./controls/more-info-default";
import { CONTINUOUS_DOMAINS } from "../../data/logbook";
const DOMAINS_NO_INFO = ["camera", "configurator"];
/**
@@ -169,7 +170,8 @@ export class MoreInfoDialog extends LitElement {
: ""}
</ha-header-bar>
${DOMAINS_WITH_MORE_INFO.includes(domain) &&
this._computeShowHistoryComponent(entityId)
(this._computeShowHistoryComponent(entityId) ||
this._computeShowLogBookComponent(entityId))
? html`
<mwc-tab-bar
.activeIndex=${this._currTabIndex}
@@ -206,13 +208,16 @@ export class MoreInfoDialog extends LitElement {
!this._computeShowHistoryComponent(entityId)
? ""
: html`<ha-more-info-history
.hass=${this.hass}
.entityId=${this._entityId}
></ha-more-info-history>
<ha-more-info-logbook
.hass=${this.hass}
.entityId=${this._entityId}
></ha-more-info-logbook>`}
.hass=${this.hass}
.entityId=${this._entityId}
></ha-more-info-history>`}
${DOMAINS_WITH_MORE_INFO.includes(domain) ||
!this._computeShowLogBookComponent(entityId)
? ""
: html`<ha-more-info-logbook
.hass=${this.hass}
.entityId=${this._entityId}
></ha-more-info-logbook>`}
${this._moreInfoType
? dynamicElement(this._moreInfoType, {
hass: this.hass,
@@ -264,12 +269,32 @@ export class MoreInfoDialog extends LitElement {
private _computeShowHistoryComponent(entityId) {
return (
(isComponentLoaded(this.hass, "history") ||
isComponentLoaded(this.hass, "logbook")) &&
isComponentLoaded(this.hass, "history") &&
!DOMAINS_MORE_INFO_NO_HISTORY.includes(computeDomain(entityId))
);
}
private _computeShowLogBookComponent(entityId): boolean {
if (!isComponentLoaded(this.hass, "logbook")) {
return false;
}
const stateObj = this.hass.states[entityId];
if (!stateObj || stateObj.attributes.unit_of_measurement) {
return false;
}
const domain = computeDomain(entityId);
if (
CONTINUOUS_DOMAINS.includes(domain) ||
DOMAINS_MORE_INFO_NO_HISTORY.includes(domain)
) {
return false;
}
return true;
}
private _removeEntity() {
const entityId = this._entityId!;
showConfirmationDialog(this, {

View File

@@ -13,11 +13,7 @@ import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { throttle } from "../../common/util/throttle";
import "../../components/ha-circular-progress";
import "../../components/state-history-charts";
import {
CONTINUOUS_DOMAINS,
getLogbookData,
LogbookEntry,
} from "../../data/logbook";
import { getLogbookData, LogbookEntry } from "../../data/logbook";
import "../../panels/logbook/ha-logbook";
import { haStyle, haStyleScrollbar } from "../../resources/styles";
import { HomeAssistant } from "../../types";
@@ -44,12 +40,7 @@ export class MoreInfoLogbook extends LitElement {
}
const stateObj = this.hass.states[this.entityId];
if (!stateObj || stateObj.attributes.unit_of_measurement) {
return html``;
}
const domain = computeStateDomain(stateObj);
if (CONTINUOUS_DOMAINS.includes(domain)) {
if (!stateObj) {
return html``;
}

View File

@@ -55,12 +55,12 @@ export class QuickBar extends LitElement {
@internalProperty() private _filter = "";
@internalProperty() private _search = "";
@internalProperty() private _opened = false;
@internalProperty() private _commandMode = false;
@internalProperty() private _commandTriggered = -1;
@internalProperty() private _done = false;
@query("search-input", false) private _filterInputField?: HTMLElement;
@@ -79,7 +79,7 @@ export class QuickBar extends LitElement {
this._done = false;
this._focusSet = false;
this._filter = "";
this._commandTriggered = -1;
this._search = "";
this._items = [];
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
@@ -116,7 +116,7 @@ export class QuickBar extends LitElement {
.label=${this.hass.localize(
"ui.dialogs.quick-bar.filter_placeholder"
)}
.filter=${this._commandMode ? `>${this._filter}` : this._filter}
.filter=${this._commandMode ? `>${this._search}` : this._search}
@keydown=${this._handleInputKeyDown}
@focus=${this._setFocusFirstListItem}
>
@@ -134,7 +134,6 @@ export class QuickBar extends LitElement {
active
></ha-circular-progress>`
: html`<mwc-list
activatable
@rangechange=${this._handleRangeChanged}
@keydown=${this._handleListItemKeyDown}
@selected=${this._handleSelected}
@@ -189,19 +188,12 @@ export class QuickBar extends LitElement {
<span slot="secondary" class="secondary">${item.altText}</span>
`
: null}
${this._commandTriggered === index
? html`<ha-circular-progress
size="small"
active
slot="meta"
></ha-circular-progress>`
: null}
</mwc-list-item>
`;
}
private async processItemAndCloseDialog(item: QuickBarItem, index: number) {
this._commandTriggered = index;
this._addSpinnerToCommandItem(index);
await item.action();
this.closeDialog();
@@ -231,18 +223,28 @@ export class QuickBar extends LitElement {
return this.renderRoot.querySelector(`mwc-list-item[index="${index}"]`);
}
private _addSpinnerToCommandItem(index: number): void {
const spinner = document.createElement("ha-circular-progress");
spinner.size = "small";
spinner.slot = "meta";
spinner.active = true;
this._getItemAtIndex(index)?.appendChild(spinner);
}
private _handleSearchChange(ev: CustomEvent): void {
const newFilter = ev.detail.value;
const oldCommandMode = this._commandMode;
if (newFilter.startsWith(">")) {
this._commandMode = true;
this._debouncedSetFilter(newFilter.substring(1));
this._search = newFilter.substring(1);
} else {
this._commandMode = false;
this._debouncedSetFilter(newFilter);
this._search = newFilter;
}
this._debouncedSetFilter(this._search);
if (oldCommandMode !== this._commandMode) {
this._items = undefined;
this._focusSet = false;
@@ -298,7 +300,7 @@ export class QuickBar extends LitElement {
private _generateEntityItems(): QuickBarItem[] {
return Object.keys(this.hass.states)
.map((entityId) => ({
text: computeStateName(this.hass.states[entityId]),
text: computeStateName(this.hass.states[entityId]) || entityId,
altText: entityId,
icon: domainIcon(computeDomain(entityId), this.hass.states[entityId]),
action: () => fireEvent(this, "hass-more-info", { entityId }),

View File

@@ -55,7 +55,7 @@ export const provideHass = (
function updateTranslations(fragment: null | string, language?: string) {
const lang = language || getLocalLanguage();
getTranslation(fragment, lang).then((translation) => {
getTranslation(fragment, lang).then(async (translation) => {
const resources = {
[lang]: {
...(hass().resources && hass().resources[lang]),
@@ -64,7 +64,7 @@ export const provideHass = (
};
hass().updateHass({
resources,
localize: computeLocalize(elements[0], lang, resources),
localize: await computeLocalize(elements[0], lang, resources),
});
});
}

View File

@@ -33,7 +33,7 @@ class NotificationManager extends LitElement {
@internalProperty() private _noCancelOnOutsideClick = false;
@query("ha-toast", true) private _toast!: HaToast;
@query("ha-toast") private _toast!: HaToast;
public async showDialog({
message,

View File

@@ -36,11 +36,13 @@ export const litLocalizeLiteMixin = <T extends Constructor<LitElement>>(
(changedProperties.has("language") ||
changedProperties.has("resources"))
) {
this.localize = computeLocalize(
computeLocalize(
this.constructor.prototype,
this.language,
this.resources
);
).then((localize) => {
this.localize = localize;
});
}
}

View File

@@ -82,6 +82,13 @@ class HaPanelDevTemplate extends LitElement {
}
protected render() {
const type = typeof this._templateResult?.result;
const resultType =
type === "object"
? Array.isArray(this._templateResult?.result)
? "list"
: "dict"
: type;
return html`
<div
class="content ${classMap({
@@ -141,16 +148,28 @@ class HaPanelDevTemplate extends LitElement {
</div>
<div class="render-pane">
<ha-circular-progress
class="render-spinner"
.active=${this._rendering}
size="small"
></ha-circular-progress>
${this._rendering
? html`<ha-circular-progress
class="render-spinner"
active
size="small"
></ha-circular-progress>`
: ""}
${this._templateResult
? html`${this.hass.localize(
"ui.panel.developer-tools.tabs.templates.result_type"
)}:
${resultType}`
: ""}
<!-- prettier-ignore -->
<pre
class="rendered ${classMap({ error: Boolean(this._error) })}"
><!-- display: block -->${this._error}${this._templateResult
?.result}</pre>
class="rendered ${classMap({
error: Boolean(this._error),
[resultType]: resultType,
})}"
>${this._error}${type === "object"
? JSON.stringify(this._templateResult!.result, null, 2)
: this._templateResult?.result}</pre>
${this._templateResult?.listeners.time
? html`
<p>
@@ -209,11 +228,13 @@ class HaPanelDevTemplate extends LitElement {
)}
</ul>
`
: html` <span class="all_listeners">
: !this._templateResult?.listeners.time
? html` <span class="all_listeners">
${this.hass.localize(
"ui.panel.developer-tools.tabs.templates.no_listeners"
)}
</span>`}
</span>`
: html``}
</div>
</div>
`;

View File

@@ -490,6 +490,10 @@ class HUIRoot extends LitElement {
huiView.hass = this.hass;
}
if (changedProperties.has("narrow") && huiView) {
huiView.narrow = this.narrow;
}
let newSelectView;
let force = false;
@@ -753,6 +757,7 @@ class HUIRoot extends LitElement {
view.lovelace = this.lovelace;
view.hass = this.hass;
view.narrow = this.narrow;
const configBackground = viewConfig.background || this.config.background;

View File

@@ -49,6 +49,8 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
@property({ attribute: false }) public lovelace?: Lovelace;
@property({ type: Boolean }) public narrow!: boolean;
@property({ type: Number }) public index?: number;
@property({ attribute: false }) public cards: Array<
@@ -128,6 +130,10 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
}
}
if (changedProperties.has("narrow")) {
this._updateColumns();
}
const oldLovelace = changedProperties.get("lovelace") as
| Lovelace
| undefined;
@@ -252,7 +258,8 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
// Do -1 column if the menu is docked and open
this._columns = Math.max(
1,
matchColumns - Number(this.hass!.dockedSidebar === "docked")
matchColumns -
Number(!this.narrow && this.hass!.dockedSidebar === "docked")
);
}

View File

@@ -31,6 +31,8 @@ export class HUIView extends UpdatingElement {
@property({ attribute: false }) public lovelace?: Lovelace;
@property({ type: Boolean }) public narrow!: boolean;
@property({ type: Number }) public index?: number;
@internalProperty() private _cards: Array<LovelaceCard | HuiErrorCard> = [];
@@ -111,6 +113,7 @@ export class HUIView extends UpdatingElement {
this._createCards(viewConfig!);
this._layoutElement!.hass = this.hass;
this._layoutElement!.narrow = this.narrow;
this._layoutElement!.lovelace = lovelace;
this._layoutElement!.index = this.index;
}
@@ -127,6 +130,10 @@ export class HUIView extends UpdatingElement {
this._layoutElement!.hass = this.hass;
}
if (changedProperties.has("narrow")) {
this._layoutElement!.narrow = this.narrow;
}
if (editModeChanged) {
this._layoutElement!.lovelace = lovelace;
}

View File

@@ -0,0 +1,14 @@
let ET;
export default async function EventTarget() {
return ET || init();
}
async function init() {
ET = window.EventTarget;
try {
// eslint-disable-next-line no-new
new ET();
} catch (_a) {
ET = (await import("event-target-shim")).default.EventTarget;
}
return ET;
}

View File

@@ -12,6 +12,7 @@ export const darkStyles = {
"switch-unchecked-button-color": "#999999",
"switch-unchecked-track-color": "#9b9b9b",
"divider-color": "rgba(225, 225, 225, .12)",
"mdc-ripple-color": "#AAAAAA",
"codemirror-keyword": "#C792EA",
"codemirror-operator": "#89DDFF",
"codemirror-variable": "#f07178",
@@ -89,6 +90,7 @@ export const derivedStyles = {
"mdc-radio-disabled-color": "var(--disabled-text-color)",
"mdc-tab-text-label-color-default": "var(--primary-text-color)",
"mdc-button-disabled-ink-color": "var(--disabled-text-color)",
"mdc-button-outline-color": "var(--divider-color)",
"mdc-dialog-scroll-divider-color": "var(--divider-color)",
};

View File

@@ -133,7 +133,7 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
return this.hass!.localize;
}
this._updateResources(language, resources);
await this._updateResources(language, resources);
return this.hass!.localize;
}
@@ -187,7 +187,7 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
return this.hass!.localize;
}
this._updateResources(language, resources);
await this._updateResources(language, resources);
return this.hass!.localize;
}
@@ -216,7 +216,7 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
}
}
private _updateResources(language: string, data: any) {
private async _updateResources(language: string, data: any) {
// Update the language in hass, and update the resources with the newly
// loaded resources. This merges the new data on top of the old data for
// this language, so that the full translation set can be loaded across
@@ -229,7 +229,7 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
};
const changes: Partial<HomeAssistant> = { resources };
if (this.hass && language === this.hass.language) {
changes.localize = computeLocalize(this, language, resources);
changes.localize = await computeLocalize(this, language, resources);
}
this._updateHass(changes);
}

View File

@@ -2956,12 +2956,13 @@
"description": "Templates are rendered using the Jinja2 template engine with some Home Assistant specific extensions.",
"editor": "Template editor",
"reset": "Reset to demo template",
"result_type": "Result type",
"jinja_documentation": "Jinja2 template documentation",
"template_extensions": "Home Assistant template extensions",
"unknown_error_template": "Unknown error rendering template",
"time": "This template updates every 60 seconds after the last state changed event.",
"time": "This template updates at the start of each minute.",
"all_listeners": "This template listens for all state changed events.",
"no_listeners": "This template does not listen for any state changed events and will not update automatically.",
"no_listeners": "This template does not listen for any events and will not update automatically.",
"listeners": "This template listens for the following state changed events:",
"entity": "Entity",
"domain": "Domain"