mirror of
https://github.com/home-assistant/frontend.git
synced 2025-09-04 02:45:02 +00:00
Compare commits
13 Commits
add-suppor
...
20241106.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8a4b96f1ff | ||
![]() |
17b6bf0673 | ||
![]() |
387392713c | ||
![]() |
125ad9c794 | ||
![]() |
ae33b10cb2 | ||
![]() |
1181ddcbbf | ||
![]() |
f7103febdf | ||
![]() |
6e8c1f1a63 | ||
![]() |
ce39b1a2c8 | ||
![]() |
a6971d61d1 | ||
![]() |
452cfee2cd | ||
![]() |
deb077b5e9 | ||
![]() |
79e223cf8e |
@@ -47,7 +47,6 @@ class HassioAddonLogDashboard extends LitElement {
|
|||||||
.localizeFunc=${this.supervisor.localize}
|
.localizeFunc=${this.supervisor.localize}
|
||||||
.header=${this.addon.name}
|
.header=${this.addon.name}
|
||||||
.provider=${this.addon.slug}
|
.provider=${this.addon.slug}
|
||||||
show
|
|
||||||
.filter=${this._filter}
|
.filter=${this._filter}
|
||||||
>
|
>
|
||||||
</error-log-card>
|
</error-log-card>
|
||||||
|
18
package.json
18
package.json
@@ -35,14 +35,14 @@
|
|||||||
"@codemirror/state": "6.4.1",
|
"@codemirror/state": "6.4.1",
|
||||||
"@codemirror/view": "6.34.1",
|
"@codemirror/view": "6.34.1",
|
||||||
"@egjs/hammerjs": "2.0.17",
|
"@egjs/hammerjs": "2.0.17",
|
||||||
"@formatjs/intl-datetimeformat": "6.16.3",
|
"@formatjs/intl-datetimeformat": "6.16.1",
|
||||||
"@formatjs/intl-displaynames": "6.8.3",
|
"@formatjs/intl-displaynames": "6.8.1",
|
||||||
"@formatjs/intl-getcanonicallocales": "2.5.2",
|
"@formatjs/intl-getcanonicallocales": "2.5.1",
|
||||||
"@formatjs/intl-listformat": "7.7.3",
|
"@formatjs/intl-listformat": "7.7.1",
|
||||||
"@formatjs/intl-locale": "4.2.3",
|
"@formatjs/intl-locale": "4.2.1",
|
||||||
"@formatjs/intl-numberformat": "8.14.3",
|
"@formatjs/intl-numberformat": "8.14.1",
|
||||||
"@formatjs/intl-pluralrules": "5.3.3",
|
"@formatjs/intl-pluralrules": "5.3.1",
|
||||||
"@formatjs/intl-relativetimeformat": "11.4.3",
|
"@formatjs/intl-relativetimeformat": "11.4.1",
|
||||||
"@fullcalendar/core": "6.1.15",
|
"@fullcalendar/core": "6.1.15",
|
||||||
"@fullcalendar/daygrid": "6.1.15",
|
"@fullcalendar/daygrid": "6.1.15",
|
||||||
"@fullcalendar/interaction": "6.1.15",
|
"@fullcalendar/interaction": "6.1.15",
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
"hls.js": "patch:hls.js@npm%3A1.5.7#~/.yarn/patches/hls.js-npm-1.5.7-f5bbd3d060.patch",
|
"hls.js": "patch:hls.js@npm%3A1.5.7#~/.yarn/patches/hls.js-npm-1.5.7-f5bbd3d060.patch",
|
||||||
"home-assistant-js-websocket": "9.4.0",
|
"home-assistant-js-websocket": "9.4.0",
|
||||||
"idb-keyval": "6.2.1",
|
"idb-keyval": "6.2.1",
|
||||||
"intl-messageformat": "10.7.5",
|
"intl-messageformat": "10.7.3",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"leaflet": "1.9.4",
|
"leaflet": "1.9.4",
|
||||||
"leaflet-draw": "patch:leaflet-draw@npm%3A1.0.4#./.yarn/patches/leaflet-draw-npm-1.0.4-0ca0ebcf65.patch",
|
"leaflet-draw": "patch:leaflet-draw@npm%3A1.0.4#./.yarn/patches/leaflet-draw-npm-1.0.4-0ca0ebcf65.patch",
|
||||||
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "home-assistant-frontend"
|
name = "home-assistant-frontend"
|
||||||
version = "20241106.0"
|
version = "20241106.1"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
description = "The Home Assistant frontend"
|
description = "The Home Assistant frontend"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@@ -117,8 +117,8 @@ export class HaPasswordField extends LitElement {
|
|||||||
.autocapitalize=${this.autocapitalize}
|
.autocapitalize=${this.autocapitalize}
|
||||||
.type=${this._unmaskedPassword ? "text" : "password"}
|
.type=${this._unmaskedPassword ? "text" : "password"}
|
||||||
.suffix=${html`<div style="width: 24px"></div>`}
|
.suffix=${html`<div style="width: 24px"></div>`}
|
||||||
@input=${this._handleInputChange}
|
@input=${this._handleInputEvent}
|
||||||
@change=${this._reDispatchEvent}
|
@change=${this._handleChangeEvent}
|
||||||
></ha-textfield>
|
></ha-textfield>
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
toggles
|
toggles
|
||||||
@@ -153,11 +153,16 @@ export class HaPasswordField extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@eventOptions({ passive: true })
|
@eventOptions({ passive: true })
|
||||||
private _handleInputChange(ev) {
|
private _handleInputEvent(ev) {
|
||||||
this.value = ev.target.value;
|
this.value = ev.target.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@eventOptions({ passive: true })
|
@eventOptions({ passive: true })
|
||||||
|
private _handleChangeEvent(ev) {
|
||||||
|
this.value = ev.target.value;
|
||||||
|
this._reDispatchEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
private _reDispatchEvent(oldEvent: Event) {
|
private _reDispatchEvent(oldEvent: Event) {
|
||||||
const newEvent = new Event(oldEvent.type, oldEvent);
|
const newEvent = new Event(oldEvent.type, oldEvent);
|
||||||
this.dispatchEvent(newEvent);
|
this.dispatchEvent(newEvent);
|
||||||
|
@@ -135,6 +135,10 @@ export class HaSortable extends LitElement {
|
|||||||
const Sortable = (await import("../resources/sortable")).default;
|
const Sortable = (await import("../resources/sortable")).default;
|
||||||
|
|
||||||
const options: SortableInstance.Options = {
|
const options: SortableInstance.Options = {
|
||||||
|
scroll: true,
|
||||||
|
// Force the autoscroll fallback because it works better than the native one
|
||||||
|
forceAutoScrollFallback: true,
|
||||||
|
scrollSpeed: 20,
|
||||||
animation: 150,
|
animation: 150,
|
||||||
...this.options,
|
...this.options,
|
||||||
onChoose: this._handleChoose,
|
onChoose: this._handleChoose,
|
||||||
|
@@ -185,6 +185,15 @@ export const fetchHassioInfo = async (
|
|||||||
export const fetchHassioBoots = async (hass: HomeAssistant) =>
|
export const fetchHassioBoots = async (hass: HomeAssistant) =>
|
||||||
hass.callApi<HassioResponse<HassioBoots>>("GET", `hassio/host/logs/boots`);
|
hass.callApi<HassioResponse<HassioBoots>>("GET", `hassio/host/logs/boots`);
|
||||||
|
|
||||||
|
export const fetchHassioLogsLegacy = async (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
provider: string
|
||||||
|
) =>
|
||||||
|
hass.callApi<string>(
|
||||||
|
"GET",
|
||||||
|
`hassio/${provider.includes("_") ? `addons/${provider}` : provider}/logs`
|
||||||
|
);
|
||||||
|
|
||||||
export const fetchHassioLogs = async (
|
export const fetchHassioLogs = async (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
provider: string,
|
provider: string,
|
||||||
|
@@ -209,17 +209,6 @@ export interface ZWaveJSNodeStatus {
|
|||||||
has_firmware_update_cc: boolean;
|
has_firmware_update_cc: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ZWaveJSNodeCapabilities = {
|
|
||||||
[endpoint: number]: ZWaveJSEndpointCapability[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ZWaveJSEndpointCapability {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
version: number;
|
|
||||||
is_secure: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ZwaveJSNodeMetadata {
|
export interface ZwaveJSNodeMetadata {
|
||||||
node_id: number;
|
node_id: number;
|
||||||
exclusion: string;
|
exclusion: string;
|
||||||
@@ -415,25 +404,6 @@ export interface RequestedGrant {
|
|||||||
clientSideAuth: boolean;
|
clientSideAuth: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const invokeZWaveCCApi = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
device_id: string,
|
|
||||||
command_class: number,
|
|
||||||
endpoint: number | undefined,
|
|
||||||
method_name: string,
|
|
||||||
parameters: any[],
|
|
||||||
wait_for_result?: boolean
|
|
||||||
): Promise<unknown> =>
|
|
||||||
hass.callWS({
|
|
||||||
type: "zwave_js/invoke_cc_api",
|
|
||||||
device_id,
|
|
||||||
command_class,
|
|
||||||
endpoint,
|
|
||||||
method_name,
|
|
||||||
parameters,
|
|
||||||
wait_for_result,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchZwaveNetworkStatus = (
|
export const fetchZwaveNetworkStatus = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
device_or_entry_id: {
|
device_or_entry_id: {
|
||||||
@@ -609,15 +579,6 @@ export const fetchZwaveNodeStatus = (
|
|||||||
device_id,
|
device_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const fetchZwaveNodeCapabilities = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
device_id: string
|
|
||||||
): Promise<ZWaveJSNodeCapabilities> =>
|
|
||||||
hass.callWS({
|
|
||||||
type: "zwave_js/node_capabilities",
|
|
||||||
device_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const subscribeZwaveNodeStatus = (
|
export const subscribeZwaveNodeStatus = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
device_id: string,
|
device_id: string,
|
||||||
|
@@ -5,7 +5,6 @@ import {
|
|||||||
mdiHospitalBox,
|
mdiHospitalBox,
|
||||||
mdiInformation,
|
mdiInformation,
|
||||||
mdiUpload,
|
mdiUpload,
|
||||||
mdiWrench,
|
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import { getConfigEntries } from "../../../../../../data/config_entries";
|
import { getConfigEntries } from "../../../../../../data/config_entries";
|
||||||
import type { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
import type { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
||||||
@@ -99,13 +98,6 @@ export const getZwaveDeviceActions = async (
|
|||||||
showZWaveJSNodeStatisticsDialog(el, {
|
showZWaveJSNodeStatisticsDialog(el, {
|
||||||
device,
|
device,
|
||||||
}),
|
}),
|
||||||
},
|
|
||||||
{
|
|
||||||
label: hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.device_info.installer_settings"
|
|
||||||
),
|
|
||||||
icon: mdiWrench,
|
|
||||||
href: `/config/zwave_js/node_installer/${device.id}?config_entry=${entryId}`,
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,152 +0,0 @@
|
|||||||
import { LitElement, css, html } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators";
|
|
||||||
import "../../../../../../components/buttons/ha-progress-button";
|
|
||||||
import type { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
|
||||||
import type { HomeAssistant } from "../../../../../../types";
|
|
||||||
import { invokeZWaveCCApi } from "../../../../../../data/zwave_js";
|
|
||||||
import "../../../../../../components/ha-textfield";
|
|
||||||
import "../../../../../../components/ha-select";
|
|
||||||
import "../../../../../../components/ha-list-item";
|
|
||||||
import "../../../../../../components/ha-alert";
|
|
||||||
import "../../../../../../components/ha-formfield";
|
|
||||||
import "../../../../../../components/ha-switch";
|
|
||||||
import type { HaProgressButton } from "../../../../../../components/buttons/ha-progress-button";
|
|
||||||
import type { HaSelect } from "../../../../../../components/ha-select";
|
|
||||||
import type { HaTextField } from "../../../../../../components/ha-textfield";
|
|
||||||
import type { HaSwitch } from "../../../../../../components/ha-switch";
|
|
||||||
import { extractApiErrorMessage } from "../../../../../../data/hassio/common";
|
|
||||||
|
|
||||||
@customElement("zwave_js-capability-control-multilevel_switch")
|
|
||||||
class ZWaveJSCapabilityMultiLevelSwitch extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public device!: DeviceRegistryEntry;
|
|
||||||
|
|
||||||
@property({ type: Number }) public endpoint!: number;
|
|
||||||
|
|
||||||
@property({ type: Number }) public command_class!: number;
|
|
||||||
|
|
||||||
@property({ type: Number }) public version!: number;
|
|
||||||
|
|
||||||
@state() private _error?: string;
|
|
||||||
|
|
||||||
protected render() {
|
|
||||||
return html`
|
|
||||||
<h3>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.title"
|
|
||||||
)}
|
|
||||||
</h3>
|
|
||||||
${this._error
|
|
||||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
|
||||||
: ""}
|
|
||||||
<ha-select
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.direction"
|
|
||||||
)}
|
|
||||||
id="direction"
|
|
||||||
>
|
|
||||||
<ha-list-item .value=${"up"} selected
|
|
||||||
>${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.up"
|
|
||||||
)}</ha-list-item
|
|
||||||
>
|
|
||||||
<ha-list-item .value=${"down"}
|
|
||||||
>${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.down"
|
|
||||||
)}</ha-list-item
|
|
||||||
>
|
|
||||||
</ha-select>
|
|
||||||
<ha-formfield
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.ignore_start_level"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ha-switch id="ignore_start_level"></ha-switch>
|
|
||||||
</ha-formfield>
|
|
||||||
<ha-textfield
|
|
||||||
type="number"
|
|
||||||
id="start_level"
|
|
||||||
value="0"
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.start_level"
|
|
||||||
)}
|
|
||||||
></ha-textfield>
|
|
||||||
<div class="actions">
|
|
||||||
<ha-progress-button
|
|
||||||
.control=${"startLevelChange"}
|
|
||||||
@click=${this._controlTransition}
|
|
||||||
>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.start_transition"
|
|
||||||
)}
|
|
||||||
</ha-progress-button>
|
|
||||||
<ha-progress-button
|
|
||||||
.control=${"stopLevelChange"}
|
|
||||||
@click=${this._controlTransition}
|
|
||||||
>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.stop_transition"
|
|
||||||
)}
|
|
||||||
</ha-progress-button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _controlTransition(ev: any) {
|
|
||||||
const control = ev.currentTarget!.control;
|
|
||||||
const button = ev.currentTarget as HaProgressButton;
|
|
||||||
button.progress = true;
|
|
||||||
|
|
||||||
const direction = (this.shadowRoot!.getElementById("direction") as HaSelect)
|
|
||||||
.value;
|
|
||||||
|
|
||||||
const ignoreStartLevel = (
|
|
||||||
this.shadowRoot!.getElementById("ignore_start_level") as HaSwitch
|
|
||||||
).checked;
|
|
||||||
|
|
||||||
const startLevel = Number(
|
|
||||||
(this.shadowRoot!.getElementById("start_level") as HaTextField).value
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
button.actionSuccess();
|
|
||||||
await invokeZWaveCCApi(
|
|
||||||
this.hass,
|
|
||||||
this.device.id,
|
|
||||||
this.command_class,
|
|
||||||
this.endpoint,
|
|
||||||
control,
|
|
||||||
[{ direction, ignoreStartLevel, startLevel }],
|
|
||||||
true
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
button.actionError();
|
|
||||||
this._error = this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.control_failed",
|
|
||||||
{ error: extractApiErrorMessage(err) }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
button.progress = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = css`
|
|
||||||
ha-select,
|
|
||||||
ha-formfield,
|
|
||||||
ha-textfield {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
.actions {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"zwave_js-capability-control-multilevel_switch": ZWaveJSCapabilityMultiLevelSwitch;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,241 +0,0 @@
|
|||||||
import { LitElement, css, html } from "lit";
|
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
|
||||||
import type { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
|
||||||
import type { HomeAssistant } from "../../../../../../types";
|
|
||||||
import { invokeZWaveCCApi } from "../../../../../../data/zwave_js";
|
|
||||||
import "../../../../../../components/ha-button";
|
|
||||||
import "../../../../../../components/buttons/ha-progress-button";
|
|
||||||
import "../../../../../../components/ha-textfield";
|
|
||||||
import "../../../../../../components/ha-select";
|
|
||||||
import "../../../../../../components/ha-list-item";
|
|
||||||
import "../../../../../../components/ha-alert";
|
|
||||||
import type { HaSelect } from "../../../../../../components/ha-select";
|
|
||||||
import type { HaTextField } from "../../../../../../components/ha-textfield";
|
|
||||||
import { extractApiErrorMessage } from "../../../../../../data/hassio/common";
|
|
||||||
import type { HaProgressButton } from "../../../../../../components/buttons/ha-progress-button";
|
|
||||||
|
|
||||||
// enum with special states
|
|
||||||
enum SpecialState {
|
|
||||||
frost_protection = "Frost Protection",
|
|
||||||
energy_saving = "Energy Saving",
|
|
||||||
unused = "Unused",
|
|
||||||
}
|
|
||||||
|
|
||||||
const SETBACK_TYPE_OPTIONS = ["none", "temporary", "permanent"];
|
|
||||||
|
|
||||||
@customElement("zwave_js-capability-control-thermostat_setback")
|
|
||||||
class ZWaveJSCapabilityThermostatSetback extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public device!: DeviceRegistryEntry;
|
|
||||||
|
|
||||||
@property({ type: Number }) public endpoint!: number;
|
|
||||||
|
|
||||||
@property({ type: Number }) public command_class!: number;
|
|
||||||
|
|
||||||
@property({ type: Number }) public version!: number;
|
|
||||||
|
|
||||||
@state() private _disableSetbackState = false;
|
|
||||||
|
|
||||||
@query("#setback_type") private _setbackTypeInput!: HaSelect;
|
|
||||||
|
|
||||||
@query("#setback_state") private _setbackStateInput!: HaTextField;
|
|
||||||
|
|
||||||
@query("#setback_special_state")
|
|
||||||
private _setbackSpecialStateSelect!: HaSelect;
|
|
||||||
|
|
||||||
@state() private _error?: string;
|
|
||||||
|
|
||||||
@state() private _loading = true;
|
|
||||||
|
|
||||||
protected render() {
|
|
||||||
return html`
|
|
||||||
<h3>
|
|
||||||
${this.hass.localize(
|
|
||||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.title`
|
|
||||||
)}
|
|
||||||
</h3>
|
|
||||||
${this._error
|
|
||||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
|
||||||
: ""}
|
|
||||||
<ha-select
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_type.label`
|
|
||||||
)}
|
|
||||||
id="setback_type"
|
|
||||||
.value=${"0"}
|
|
||||||
.disabled=${this._loading}
|
|
||||||
>
|
|
||||||
${SETBACK_TYPE_OPTIONS.map(
|
|
||||||
(translationKey, index) =>
|
|
||||||
html`<ha-list-item .value=${String(index)}>
|
|
||||||
${this.hass.localize(
|
|
||||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_type.${translationKey}`
|
|
||||||
)}
|
|
||||||
</ha-list-item>`
|
|
||||||
)}
|
|
||||||
</ha-select>
|
|
||||||
<div class="setback-state">
|
|
||||||
<ha-textfield
|
|
||||||
type="number"
|
|
||||||
id="setback_state"
|
|
||||||
value="0"
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_state_label`
|
|
||||||
)}
|
|
||||||
min="-12.8"
|
|
||||||
max="12.0"
|
|
||||||
step=".1"
|
|
||||||
.helper=${this.hass.localize(
|
|
||||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_state_helper`
|
|
||||||
)}
|
|
||||||
.disabled=${this._disableSetbackState || this._loading}
|
|
||||||
></ha-textfield>
|
|
||||||
<ha-select
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_special_state.label`
|
|
||||||
)}
|
|
||||||
id="setback_special_state"
|
|
||||||
@change=${this._changeSpecialState}
|
|
||||||
.disabled=${this._loading}
|
|
||||||
>
|
|
||||||
<ha-list-item selected> </ha-list-item>
|
|
||||||
${Object.entries(SpecialState).map(
|
|
||||||
([translationKey, value]) =>
|
|
||||||
html`<ha-list-item .value=${value}>
|
|
||||||
${this.hass.localize(
|
|
||||||
`ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_special_state.${translationKey}`
|
|
||||||
)}
|
|
||||||
</ha-list-item>`
|
|
||||||
)}
|
|
||||||
</ha-select>
|
|
||||||
</div>
|
|
||||||
<div class="actions">
|
|
||||||
<ha-button
|
|
||||||
class="clear-button"
|
|
||||||
@click=${this._clear}
|
|
||||||
.disabled=${this._loading}
|
|
||||||
>${this.hass.localize("ui.common.clear")}</ha-button
|
|
||||||
>
|
|
||||||
<ha-progress-button
|
|
||||||
@click=${this._saveSetback}
|
|
||||||
.disabled=${this._loading}
|
|
||||||
>
|
|
||||||
${this.hass.localize("ui.common.save")}
|
|
||||||
</ha-progress-button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected firstUpdated() {
|
|
||||||
this._loadSetback();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _loadSetback() {
|
|
||||||
this._loading = true;
|
|
||||||
try {
|
|
||||||
const { setbackType, setbackState } = (await invokeZWaveCCApi(
|
|
||||||
this.hass,
|
|
||||||
this.device.id,
|
|
||||||
this.command_class,
|
|
||||||
this.endpoint,
|
|
||||||
"get",
|
|
||||||
[],
|
|
||||||
true
|
|
||||||
)) as { setbackType: number; setbackState: number | SpecialState };
|
|
||||||
|
|
||||||
this._setbackTypeInput.value = String(setbackType);
|
|
||||||
if (typeof setbackState === "number") {
|
|
||||||
this._setbackStateInput.value = String(setbackState);
|
|
||||||
this._setbackSpecialStateSelect.value = "";
|
|
||||||
} else {
|
|
||||||
this._setbackSpecialStateSelect.value = setbackState;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
this._error = this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.get_setback_failed",
|
|
||||||
{ error: extractApiErrorMessage(err) }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._loading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _changeSpecialState() {
|
|
||||||
this._disableSetbackState = !!this._setbackSpecialStateSelect.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _saveSetback(ev: CustomEvent) {
|
|
||||||
const button = ev.currentTarget as HaProgressButton;
|
|
||||||
button.progress = true;
|
|
||||||
|
|
||||||
this._error = undefined;
|
|
||||||
const setbackType = this._setbackTypeInput.value;
|
|
||||||
|
|
||||||
let setbackState: number | string = Number(this._setbackStateInput.value);
|
|
||||||
if (this._setbackSpecialStateSelect.value) {
|
|
||||||
setbackState = this._setbackSpecialStateSelect.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await invokeZWaveCCApi(
|
|
||||||
this.hass,
|
|
||||||
this.device.id,
|
|
||||||
this.command_class,
|
|
||||||
this.endpoint,
|
|
||||||
"set",
|
|
||||||
[Number(setbackType), setbackState],
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
button.actionSuccess();
|
|
||||||
} catch (err) {
|
|
||||||
button.actionError();
|
|
||||||
this._error = this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.save_setback_failed",
|
|
||||||
{ error: extractApiErrorMessage(err) }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
button.progress = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _clear() {
|
|
||||||
this._loadSetback();
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = css`
|
|
||||||
:host {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
:host > ha-select {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.actions {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
.actions .clear-button {
|
|
||||||
--mdc-theme-primary: var(--red-color);
|
|
||||||
}
|
|
||||||
.setback-state {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
.setback-state ha-select,
|
|
||||||
ha-textfield {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"zwave_js-capability-control-thermostat_setback": ZWaveJSCapabilityThermostatSetback;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -48,10 +48,6 @@ class ZWaveJSConfigRouter extends HassRouterPage {
|
|||||||
tag: "zwave_js-node-config",
|
tag: "zwave_js-node-config",
|
||||||
load: () => import("./zwave_js-node-config"),
|
load: () => import("./zwave_js-node-config"),
|
||||||
},
|
},
|
||||||
node_installer: {
|
|
||||||
tag: "zwave_js-node-installer",
|
|
||||||
load: () => import("./zwave_js-node-installer"),
|
|
||||||
},
|
|
||||||
logs: {
|
logs: {
|
||||||
tag: "zwave_js-logs",
|
tag: "zwave_js-logs",
|
||||||
load: () => import("./zwave_js-logs"),
|
load: () => import("./zwave_js-logs"),
|
||||||
|
@@ -1,210 +0,0 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
|
||||||
import "@material/mwc-list/mwc-list-item";
|
|
||||||
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
|
|
||||||
import { LitElement, css, html, nothing } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators";
|
|
||||||
import { dynamicElement } from "../../../../../common/dom/dynamic-element-directive";
|
|
||||||
import "../../../../../components/ha-card";
|
|
||||||
import { computeDeviceName } from "../../../../../data/device_registry";
|
|
||||||
import type {
|
|
||||||
ZWaveJSNodeCapabilities,
|
|
||||||
ZwaveJSNodeMetadata,
|
|
||||||
} from "../../../../../data/zwave_js";
|
|
||||||
import {
|
|
||||||
fetchZwaveNodeCapabilities,
|
|
||||||
fetchZwaveNodeMetadata,
|
|
||||||
} from "../../../../../data/zwave_js";
|
|
||||||
import "../../../../../layouts/hass-error-screen";
|
|
||||||
import "../../../../../layouts/hass-loading-screen";
|
|
||||||
import "../../../../../layouts/hass-subpage";
|
|
||||||
import { haStyle } from "../../../../../resources/styles";
|
|
||||||
import type { HomeAssistant, Route } from "../../../../../types";
|
|
||||||
import "../../../ha-config-section";
|
|
||||||
import "./capability-controls/zwave_js-capability-control-multilevel-switch";
|
|
||||||
import "./capability-controls/zwave_js-capability-control-thermostat-setback";
|
|
||||||
|
|
||||||
const CAPABILITY_CONTROLS = {
|
|
||||||
38: "multilevel_switch",
|
|
||||||
71: "thermostat_setback",
|
|
||||||
};
|
|
||||||
|
|
||||||
@customElement("zwave_js-node-installer")
|
|
||||||
class ZWaveJSNodeInstaller extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow = false;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public isWide = false;
|
|
||||||
|
|
||||||
@property() public configEntryId?: string;
|
|
||||||
|
|
||||||
@property() public deviceId!: string;
|
|
||||||
|
|
||||||
@state() private _nodeMetadata?: ZwaveJSNodeMetadata;
|
|
||||||
|
|
||||||
@state() private _capabilities?: ZWaveJSNodeCapabilities;
|
|
||||||
|
|
||||||
@state() private _error?: string;
|
|
||||||
|
|
||||||
public connectedCallback(): void {
|
|
||||||
super.connectedCallback();
|
|
||||||
this.deviceId = this.route.path.substr(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues): void {
|
|
||||||
if (!this._capabilities || changedProps.has("deviceId")) {
|
|
||||||
this._fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
if (this._error) {
|
|
||||||
return html`<hass-error-screen
|
|
||||||
.hass=${this.hass}
|
|
||||||
.error=${this.hass.localize(
|
|
||||||
`ui.panel.config.zwave_js.node_config.error_${this._error}`
|
|
||||||
)}
|
|
||||||
></hass-error-screen>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._capabilities || !this._nodeMetadata) {
|
|
||||||
return html`<hass-loading-screen></hass-loading-screen>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const device = this.hass.devices[this.deviceId];
|
|
||||||
|
|
||||||
const endpoints = Object.entries(this._capabilities).filter(
|
|
||||||
([_endpoint, capabilities]) => {
|
|
||||||
const filteredCapabilities = capabilities.filter(
|
|
||||||
(capability) => capability.id in CAPABILITY_CONTROLS
|
|
||||||
);
|
|
||||||
return filteredCapabilities.length > 0;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<hass-subpage
|
|
||||||
.hass=${this.hass}
|
|
||||||
.narrow=${this.narrow}
|
|
||||||
.route=${this.route}
|
|
||||||
>
|
|
||||||
<ha-config-section
|
|
||||||
.narrow=${this.narrow}
|
|
||||||
.isWide=${this.isWide}
|
|
||||||
vertical
|
|
||||||
>
|
|
||||||
<div slot="header">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.header"
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div slot="introduction">
|
|
||||||
${device
|
|
||||||
? html`
|
|
||||||
<div class="device-info">
|
|
||||||
<h2>${computeDeviceName(device, this.hass)}</h2>
|
|
||||||
<p>${device.manufacturer} ${device.model}</p>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
: ``}
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.introduction"
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
${endpoints.length
|
|
||||||
? endpoints.map(
|
|
||||||
([endpoint, capabilities]) => html`
|
|
||||||
<h3>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.endpoint"
|
|
||||||
)}:
|
|
||||||
${endpoint}
|
|
||||||
</h3>
|
|
||||||
<ha-card>
|
|
||||||
${capabilities.map(
|
|
||||||
(capability) => html`
|
|
||||||
${capability.id in CAPABILITY_CONTROLS
|
|
||||||
? html` <div class="capability">
|
|
||||||
<h4>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.command_class"
|
|
||||||
)}:
|
|
||||||
${capability.name}
|
|
||||||
</h4>
|
|
||||||
${dynamicElement(
|
|
||||||
`zwave_js-capability-control-${CAPABILITY_CONTROLS[capability.id]}`,
|
|
||||||
{
|
|
||||||
hass: this.hass,
|
|
||||||
device: device,
|
|
||||||
endpoint: endpoint,
|
|
||||||
command_class: capability.id,
|
|
||||||
version: capability.version,
|
|
||||||
is_secure: capability.is_secure,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</div>`
|
|
||||||
: nothing}
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</ha-card>
|
|
||||||
`
|
|
||||||
)
|
|
||||||
: html`<ha-card class="empty"
|
|
||||||
>${this.hass.localize(
|
|
||||||
"ui.panel.config.zwave_js.node_installer.no_settings"
|
|
||||||
)}</ha-card
|
|
||||||
>`}
|
|
||||||
</ha-config-section>
|
|
||||||
</hass-subpage>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _fetchData() {
|
|
||||||
if (!this.configEntryId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const device = this.hass.devices[this.deviceId];
|
|
||||||
if (!device) {
|
|
||||||
this._error = "device_not_found";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[this._nodeMetadata, this._capabilities] = await Promise.all([
|
|
||||||
fetchZwaveNodeMetadata(this.hass, device.id),
|
|
||||||
fetchZwaveNodeCapabilities(this.hass, device.id),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
|
||||||
return [
|
|
||||||
haStyle,
|
|
||||||
css`
|
|
||||||
ha-card {
|
|
||||||
margin-bottom: 40px;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
.capability {
|
|
||||||
border-bottom: 1px solid var(--divider-color);
|
|
||||||
padding: 4px 16px;
|
|
||||||
}
|
|
||||||
.capability:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
.empty {
|
|
||||||
margin-top: 32px;
|
|
||||||
padding: 24px 16px;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"zwave_js-node-installer": ZWaveJSNodeInstaller;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -11,6 +11,7 @@ import {
|
|||||||
mdiRefresh,
|
mdiRefresh,
|
||||||
mdiWrap,
|
mdiWrap,
|
||||||
mdiWrapDisabled,
|
mdiWrapDisabled,
|
||||||
|
mdiFolderTextOutline,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
@@ -49,6 +50,7 @@ import {
|
|||||||
fetchHassioBoots,
|
fetchHassioBoots,
|
||||||
fetchHassioLogs,
|
fetchHassioLogs,
|
||||||
fetchHassioLogsFollow,
|
fetchHassioLogsFollow,
|
||||||
|
fetchHassioLogsLegacy,
|
||||||
getHassioLogDownloadLinesUrl,
|
getHassioLogDownloadLinesUrl,
|
||||||
getHassioLogDownloadUrl,
|
getHassioLogDownloadUrl,
|
||||||
} from "../../../data/hassio/supervisor";
|
} from "../../../data/hassio/supervisor";
|
||||||
@@ -57,7 +59,7 @@ import {
|
|||||||
downloadFileSupported,
|
downloadFileSupported,
|
||||||
fileDownload,
|
fileDownload,
|
||||||
} from "../../../util/file_download";
|
} from "../../../util/file_download";
|
||||||
import type { HASSDomEvent } from "../../../common/dom/fire_event";
|
import { fireEvent, type HASSDomEvent } from "../../../common/dom/fire_event";
|
||||||
import type { ConnectionStatus } from "../../../data/connection-status";
|
import type { ConnectionStatus } from "../../../data/connection-status";
|
||||||
import { atLeastVersion } from "../../../common/config/version";
|
import { atLeastVersion } from "../../../common/config/version";
|
||||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||||
@@ -78,9 +80,10 @@ class ErrorLogCard extends LitElement {
|
|||||||
|
|
||||||
@property() public header?: string;
|
@property() public header?: string;
|
||||||
|
|
||||||
@property() public provider!: string;
|
@property() public provider?: string;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: true }) public show = false;
|
@property({ attribute: "allow-switch", type: Boolean }) public allowSwitch =
|
||||||
|
false;
|
||||||
|
|
||||||
@query(".error-log") private _logElement?: HTMLElement;
|
@query(".error-log") private _logElement?: HTMLElement;
|
||||||
|
|
||||||
@@ -129,26 +132,32 @@ class ErrorLogCard extends LitElement {
|
|||||||
|
|
||||||
@state() private _wrapLines = true;
|
@state() private _wrapLines = true;
|
||||||
|
|
||||||
@state() private _downloadSupported;
|
@state() private _downloadSupported?: boolean;
|
||||||
|
|
||||||
@state() private _logsFileLink;
|
@state() private _logsFileLink?: string;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
|
const streaming =
|
||||||
|
this._streamSupported &&
|
||||||
|
this.provider &&
|
||||||
|
isComponentLoaded(this.hass, "hassio") &&
|
||||||
|
this._loadingState !== "loading";
|
||||||
|
|
||||||
|
const hasBoots = this._streamSupported && Array.isArray(this._boots);
|
||||||
|
|
||||||
const localize = this.localizeFunc || this.hass.localize;
|
const localize = this.localizeFunc || this.hass.localize;
|
||||||
return html`
|
return html`
|
||||||
<div class="error-log-intro">
|
<div class="error-log-intro">
|
||||||
${this._error
|
${this._error
|
||||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||||
: nothing}
|
: nothing}
|
||||||
<ha-card outlined class=${classMap({ hidden: this.show === false })}>
|
<ha-card outlined>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1 class="card-header">
|
<h1 class="card-header">
|
||||||
${this.header || localize("ui.panel.config.logs.show_full_logs")}
|
${this.header || localize("ui.panel.config.logs.show_full_logs")}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
${this._streamSupported &&
|
${hasBoots && this._showBootsSelect
|
||||||
Array.isArray(this._boots) &&
|
|
||||||
this._showBootsSelect
|
|
||||||
? html`
|
? html`
|
||||||
<ha-assist-chip
|
<ha-assist-chip
|
||||||
.title=${localize(
|
.title=${localize(
|
||||||
@@ -174,7 +183,7 @@ class ErrorLogCard extends LitElement {
|
|||||||
id="boots-menu"
|
id="boots-menu"
|
||||||
positioning="fixed"
|
positioning="fixed"
|
||||||
>
|
>
|
||||||
${this._boots.map(
|
${this._boots!.map(
|
||||||
(boot) => html`
|
(boot) => html`
|
||||||
<ha-md-menu-item
|
<ha-md-menu-item
|
||||||
.value=${boot}
|
.value=${boot}
|
||||||
@@ -231,27 +240,40 @@ class ErrorLogCard extends LitElement {
|
|||||||
`ui.panel.config.logs.${this._wrapLines ? "full_width" : "wrap_lines"}`
|
`ui.panel.config.logs.${this._wrapLines ? "full_width" : "wrap_lines"}`
|
||||||
)}
|
)}
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
${!this._streamSupported || this._error
|
${!streaming || this._error
|
||||||
? html`<ha-icon-button
|
? html`<ha-icon-button
|
||||||
.path=${mdiRefresh}
|
.path=${mdiRefresh}
|
||||||
@click=${this._loadLogs}
|
@click=${this._loadLogs}
|
||||||
.label=${localize("ui.common.refresh")}
|
.label=${localize("ui.common.refresh")}
|
||||||
></ha-icon-button>`
|
></ha-icon-button>`
|
||||||
: nothing}
|
: nothing}
|
||||||
${this._streamSupported && Array.isArray(this._boots)
|
${(this.allowSwitch && this.provider === "core") || hasBoots
|
||||||
? html`
|
? html`
|
||||||
<ha-button-menu @action=${this._handleOverflowAction}>
|
<ha-button-menu @action=${this._handleOverflowAction}>
|
||||||
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
|
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
|
||||||
</ha-icon-button>
|
</ha-icon-button>
|
||||||
<ha-list-item graphic="icon">
|
${this.allowSwitch && this.provider === "core"
|
||||||
<ha-svg-icon
|
? html`<ha-list-item graphic="icon">
|
||||||
slot="graphic"
|
<ha-svg-icon
|
||||||
.path=${mdiFormatListNumbered}
|
slot="graphic"
|
||||||
></ha-svg-icon>
|
.path=${mdiFolderTextOutline}
|
||||||
${localize(
|
></ha-svg-icon>
|
||||||
`ui.panel.config.logs.${this._showBootsSelect ? "hide" : "show"}_haos_boots`
|
${this.hass.localize(
|
||||||
)}
|
"ui.panel.config.logs.show_condensed_logs"
|
||||||
</ha-list-item>
|
)}
|
||||||
|
</ha-list-item>`
|
||||||
|
: nothing}
|
||||||
|
${hasBoots
|
||||||
|
? html`<ha-list-item graphic="icon">
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${mdiFormatListNumbered}
|
||||||
|
></ha-svg-icon>
|
||||||
|
${localize(
|
||||||
|
`ui.panel.config.logs.${this._showBootsSelect ? "hide" : "show"}_haos_boots`
|
||||||
|
)}
|
||||||
|
</ha-list-item>`
|
||||||
|
: nothing}
|
||||||
</ha-button-menu>
|
</ha-button-menu>
|
||||||
`
|
`
|
||||||
: nothing}
|
: nothing}
|
||||||
@@ -304,47 +326,34 @@ class ErrorLogCard extends LitElement {
|
|||||||
slot="trailingIcon"
|
slot="trailingIcon"
|
||||||
></ha-svg-icon>
|
></ha-svg-icon>
|
||||||
</ha-button>
|
</ha-button>
|
||||||
${this._streamSupported &&
|
${streaming && this._boot === 0 && !this._error
|
||||||
this._loadingState !== "loading" &&
|
|
||||||
!this._error
|
|
||||||
? html`<div class="live-indicator">
|
? html`<div class="live-indicator">
|
||||||
<ha-svg-icon path=${mdiCircle}></ha-svg-icon>
|
<ha-svg-icon path=${mdiCircle}></ha-svg-icon>
|
||||||
Live
|
Live
|
||||||
</div>`
|
</div>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</ha-card>
|
</ha-card>
|
||||||
${this.show === false
|
|
||||||
? html`
|
|
||||||
${this._downloadSupported
|
|
||||||
? html`
|
|
||||||
<ha-button outlined @click=${this._downloadLogs}>
|
|
||||||
<ha-svg-icon .path=${mdiDownload}></ha-svg-icon>
|
|
||||||
${localize("ui.panel.config.logs.download_logs")}
|
|
||||||
</ha-button>
|
|
||||||
`
|
|
||||||
: nothing}
|
|
||||||
<mwc-button raised @click=${this._showLogs}>
|
|
||||||
${localize("ui.panel.config.logs.load_logs")}
|
|
||||||
</mwc-button>
|
|
||||||
`
|
|
||||||
: nothing}
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public connectedCallback() {
|
protected willUpdate(changedProps: PropertyValues) {
|
||||||
super.connectedCallback();
|
super.willUpdate(changedProps);
|
||||||
|
if (changedProps.has("provider")) {
|
||||||
|
this._boot = 0;
|
||||||
|
this._loadLogs();
|
||||||
|
}
|
||||||
|
if (this.hasUpdated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._streamSupported = atLeastVersion(this.hass.config.version, 2024, 11);
|
||||||
|
this._downloadSupported = downloadFileSupported(this.hass);
|
||||||
|
// just needs to be loaded once, because only the host endpoints provide boots information
|
||||||
|
this._loadBoots();
|
||||||
|
|
||||||
if (this._streamSupported === undefined) {
|
window.addEventListener("connection-status", this._handleConnectionStatus);
|
||||||
this._streamSupported = atLeastVersion(
|
|
||||||
this.hass.config.version,
|
this.hass.loadFragmentTranslation("config");
|
||||||
2024,
|
|
||||||
11
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (this._downloadSupported === undefined && this.hass) {
|
|
||||||
this._downloadSupported = downloadFileSupported(this.hass);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(changedProps: PropertyValues) {
|
protected firstUpdated(changedProps: PropertyValues) {
|
||||||
@@ -354,28 +363,11 @@ class ErrorLogCard extends LitElement {
|
|||||||
|
|
||||||
this._scrolledToTopController.callback = this._handleTopScroll;
|
this._scrolledToTopController.callback = this._handleTopScroll;
|
||||||
this._scrolledToTopController.observe(this._scrollTopMarkerElement!);
|
this._scrolledToTopController.observe(this._scrollTopMarkerElement!);
|
||||||
|
|
||||||
window.addEventListener("connection-status", this._handleConnectionStatus);
|
|
||||||
|
|
||||||
if (this.hass?.config.recovery_mode || this.show) {
|
|
||||||
this.hass.loadFragmentTranslation("config");
|
|
||||||
}
|
|
||||||
|
|
||||||
// just needs to be loaded once, because only the host endpoints provide boots information
|
|
||||||
this._loadBoots();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps) {
|
protected updated(changedProps) {
|
||||||
super.updated(changedProps);
|
super.updated(changedProps);
|
||||||
|
|
||||||
if (
|
|
||||||
(changedProps.has("show") && this.show) ||
|
|
||||||
(changedProps.has("provider") && this.show)
|
|
||||||
) {
|
|
||||||
this._boot = 0;
|
|
||||||
this._loadLogs();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._newLogsIndicator && this._scrolledToBottomController.value) {
|
if (this._newLogsIndicator && this._scrolledToBottomController.value) {
|
||||||
this._newLogsIndicator = false;
|
this._newLogsIndicator = false;
|
||||||
}
|
}
|
||||||
@@ -409,7 +401,7 @@ class ErrorLogCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _downloadLogs(): Promise<void> {
|
private async _downloadLogs(): Promise<void> {
|
||||||
if (this._streamSupported) {
|
if (this._streamSupported && this.provider) {
|
||||||
showDownloadLogsDialog(this, {
|
showDownloadLogsDialog(this, {
|
||||||
header: this.header,
|
header: this.header,
|
||||||
provider: this.provider,
|
provider: this.provider,
|
||||||
@@ -431,10 +423,6 @@ class ErrorLogCard extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _showLogs(): void {
|
|
||||||
this.show = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _loadLogs(): Promise<void> {
|
private async _loadLogs(): Promise<void> {
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._loadingState = "loading";
|
this._loadingState = "loading";
|
||||||
@@ -446,15 +434,16 @@ class ErrorLogCard extends LitElement {
|
|||||||
try {
|
try {
|
||||||
if (this._logStreamAborter) {
|
if (this._logStreamAborter) {
|
||||||
this._logStreamAborter.abort();
|
this._logStreamAborter.abort();
|
||||||
|
this._logStreamAborter = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._logStreamAborter = new AbortController();
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this._streamSupported &&
|
this._streamSupported &&
|
||||||
isComponentLoaded(this.hass, "hassio") &&
|
isComponentLoaded(this.hass, "hassio") &&
|
||||||
this.provider
|
this.provider
|
||||||
) {
|
) {
|
||||||
|
this._logStreamAborter = new AbortController();
|
||||||
|
|
||||||
// check if there are any logs at all
|
// check if there are any logs at all
|
||||||
const testResponse = await fetchHassioLogs(
|
const testResponse = await fetchHassioLogs(
|
||||||
this.hass,
|
this.hass,
|
||||||
@@ -545,8 +534,7 @@ class ErrorLogCard extends LitElement {
|
|||||||
this._streamSupported = false;
|
this._streamSupported = false;
|
||||||
let logs = "";
|
let logs = "";
|
||||||
if (isComponentLoaded(this.hass, "hassio") && this.provider) {
|
if (isComponentLoaded(this.hass, "hassio") && this.provider) {
|
||||||
const repsonse = await fetchHassioLogs(this.hass, this.provider);
|
logs = await fetchHassioLogsLegacy(this.hass, this.provider);
|
||||||
logs = await repsonse.text();
|
|
||||||
} else {
|
} else {
|
||||||
logs = await fetchErrorLog(this.hass);
|
logs = await fetchErrorLog(this.hass);
|
||||||
}
|
}
|
||||||
@@ -598,60 +586,62 @@ class ErrorLogCard extends LitElement {
|
|||||||
if (ev.detail === "disconnected" && this._logStreamAborter) {
|
if (ev.detail === "disconnected" && this._logStreamAborter) {
|
||||||
this._logStreamAborter.abort();
|
this._logStreamAborter.abort();
|
||||||
}
|
}
|
||||||
if (ev.detail === "connected" && this.show) {
|
if (ev.detail === "connected") {
|
||||||
this._loadLogs();
|
this._loadLogs();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private async _loadMoreLogs() {
|
private async _loadMoreLogs() {
|
||||||
if (
|
if (
|
||||||
this._firstCursor &&
|
!this._firstCursor ||
|
||||||
this._loadingPrevState !== "loading" &&
|
this._loadingPrevState === "loading" ||
|
||||||
this._loadingState === "loaded" &&
|
this._loadingState !== "loaded" ||
|
||||||
this._logElement
|
!this._logElement ||
|
||||||
|
!this.provider
|
||||||
) {
|
) {
|
||||||
const scrolledToBottom = this._scrolledToBottomController.value;
|
return;
|
||||||
const scrollPositionFromBottom =
|
}
|
||||||
this._logElement.scrollHeight - this._logElement.scrollTop;
|
const scrolledToBottom = this._scrolledToBottomController.value;
|
||||||
this._loadingPrevState = "loading";
|
const scrollPositionFromBottom =
|
||||||
const response = await fetchHassioLogs(
|
this._logElement.scrollHeight - this._logElement.scrollTop;
|
||||||
this.hass,
|
this._loadingPrevState = "loading";
|
||||||
this.provider,
|
const response = await fetchHassioLogs(
|
||||||
`entries=${this._firstCursor}:-100:100`,
|
this.hass,
|
||||||
this._boot
|
this.provider,
|
||||||
);
|
`entries=${this._firstCursor}:-100:100`,
|
||||||
|
this._boot
|
||||||
|
);
|
||||||
|
|
||||||
if (response.headers.has("X-First-Cursor")) {
|
if (response.headers.has("X-First-Cursor")) {
|
||||||
if (this._firstCursor === response.headers.get("X-First-Cursor")!) {
|
if (this._firstCursor === response.headers.get("X-First-Cursor")!) {
|
||||||
this._loadingPrevState = "end";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._firstCursor = response.headers.get("X-First-Cursor")!;
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = await response.text();
|
|
||||||
|
|
||||||
if (body) {
|
|
||||||
const lines = body
|
|
||||||
.split("\n")
|
|
||||||
.filter((line) => line.trim() !== "")
|
|
||||||
.reverse();
|
|
||||||
|
|
||||||
this._ansiToHtmlElement?.parseLinesToColoredPre(lines, true);
|
|
||||||
this._numberOfLines! += lines.length;
|
|
||||||
this._loadingPrevState = "loaded";
|
|
||||||
} else {
|
|
||||||
this._loadingPrevState = "end";
|
this._loadingPrevState = "end";
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this._firstCursor = response.headers.get("X-First-Cursor")!;
|
||||||
|
}
|
||||||
|
|
||||||
if (scrolledToBottom) {
|
const body = await response.text();
|
||||||
this._scrollToBottom();
|
|
||||||
} else if (this._loadingPrevState !== "end" && this._logElement) {
|
if (body) {
|
||||||
window.requestAnimationFrame(() => {
|
const lines = body
|
||||||
this._logElement!.scrollTop =
|
.split("\n")
|
||||||
this._logElement!.scrollHeight - scrollPositionFromBottom;
|
.filter((line) => line.trim() !== "")
|
||||||
});
|
.reverse();
|
||||||
}
|
|
||||||
|
this._ansiToHtmlElement?.parseLinesToColoredPre(lines, true);
|
||||||
|
this._numberOfLines! += lines.length;
|
||||||
|
this._loadingPrevState = "loaded";
|
||||||
|
} else {
|
||||||
|
this._loadingPrevState = "end";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrolledToBottom) {
|
||||||
|
this._scrollToBottom();
|
||||||
|
} else if (this._loadingPrevState !== "end" && this._logElement) {
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
this._logElement!.scrollTop =
|
||||||
|
this._logElement!.scrollHeight - scrollPositionFromBottom;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,7 +683,15 @@ class ErrorLogCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _handleOverflowAction(ev: CustomEvent<ActionDetail>) {
|
private _handleOverflowAction(ev: CustomEvent<ActionDetail>) {
|
||||||
switch (ev.detail.index) {
|
let index = ev.detail.index;
|
||||||
|
if (this.provider === "core") {
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
switch (index) {
|
||||||
|
case -1:
|
||||||
|
// @ts-ignore
|
||||||
|
fireEvent(this, "switch-log-view");
|
||||||
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
this._showBootsSelect = !this._showBootsSelect;
|
this._showBootsSelect = !this._showBootsSelect;
|
||||||
break;
|
break;
|
||||||
|
@@ -3,20 +3,20 @@ import type { CSSResultGroup, TemplateResult } from "lit";
|
|||||||
import { css, html, LitElement } from "lit";
|
import { css, html, LitElement } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||||
|
import { navigate } from "../../../common/navigate";
|
||||||
import { extractSearchParam } from "../../../common/url/search-params";
|
import { extractSearchParam } from "../../../common/url/search-params";
|
||||||
import "../../../components/ha-button-menu";
|
|
||||||
import "../../../components/ha-button";
|
import "../../../components/ha-button";
|
||||||
|
import "../../../components/ha-button-menu";
|
||||||
import "../../../components/search-input";
|
import "../../../components/search-input";
|
||||||
import type { LogProvider } from "../../../data/error_log";
|
import type { LogProvider } from "../../../data/error_log";
|
||||||
import { fetchHassioAddonsInfo } from "../../../data/hassio/addon";
|
import { fetchHassioAddonsInfo } from "../../../data/hassio/addon";
|
||||||
|
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||||
import "../../../layouts/hass-subpage";
|
import "../../../layouts/hass-subpage";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import type { HomeAssistant, Route } from "../../../types";
|
import type { HomeAssistant, Route } from "../../../types";
|
||||||
import "./error-log-card";
|
import "./error-log-card";
|
||||||
import "./system-log-card";
|
import "./system-log-card";
|
||||||
import type { SystemLogCard } from "./system-log-card";
|
import type { SystemLogCard } from "./system-log-card";
|
||||||
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
|
|
||||||
import { navigate } from "../../../common/navigate";
|
|
||||||
|
|
||||||
const logProviders: LogProvider[] = [
|
const logProviders: LogProvider[] = [
|
||||||
{
|
{
|
||||||
@@ -57,6 +57,8 @@ export class HaConfigLogs extends LitElement {
|
|||||||
|
|
||||||
@state() private _filter = extractSearchParam("filter") || "";
|
@state() private _filter = extractSearchParam("filter") || "";
|
||||||
|
|
||||||
|
@state() private _detail = false;
|
||||||
|
|
||||||
@query("system-log-card") private systemLog?: SystemLogCard;
|
@query("system-log-card") private systemLog?: SystemLogCard;
|
||||||
|
|
||||||
@state() private _selectedLogProvider = "core";
|
@state() private _selectedLogProvider = "core";
|
||||||
@@ -141,7 +143,7 @@ export class HaConfigLogs extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
${search}
|
${search}
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${this._selectedLogProvider === "core"
|
${this._selectedLogProvider === "core" && !this._detail
|
||||||
? html`
|
? html`
|
||||||
<system-log-card
|
<system-log-card
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
@@ -149,23 +151,28 @@ export class HaConfigLogs extends LitElement {
|
|||||||
(p) => p.key === this._selectedLogProvider
|
(p) => p.key === this._selectedLogProvider
|
||||||
)!.name}
|
)!.name}
|
||||||
.filter=${this._filter}
|
.filter=${this._filter}
|
||||||
|
@switch-log-view=${this._showDetail}
|
||||||
></system-log-card>
|
></system-log-card>
|
||||||
`
|
`
|
||||||
: ""}
|
: html`<error-log-card
|
||||||
<error-log-card
|
.hass=${this.hass}
|
||||||
.hass=${this.hass}
|
.header=${this._logProviders.find(
|
||||||
.header=${this._logProviders.find(
|
(p) => p.key === this._selectedLogProvider
|
||||||
(p) => p.key === this._selectedLogProvider
|
)!.name}
|
||||||
)!.name}
|
.filter=${this._filter}
|
||||||
.filter=${this._filter}
|
.provider=${this._selectedLogProvider}
|
||||||
.provider=${this._selectedLogProvider}
|
@switch-log-view=${this._showDetail}
|
||||||
.show=${this._selectedLogProvider !== "core"}
|
allow-switch
|
||||||
></error-log-card>
|
></error-log-card>`}
|
||||||
</div>
|
</div>
|
||||||
</hass-subpage>
|
</hass-subpage>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _showDetail() {
|
||||||
|
this._detail = !this._detail;
|
||||||
|
}
|
||||||
|
|
||||||
private _selectProvider(ev) {
|
private _selectProvider(ev) {
|
||||||
this._selectedLogProvider = (ev.currentTarget as any).provider;
|
this._selectedLogProvider = (ev.currentTarget as any).provider;
|
||||||
this._filter = "";
|
this._filter = "";
|
||||||
|
@@ -1,16 +1,20 @@
|
|||||||
import { mdiRefresh } from "@mdi/js";
|
|
||||||
import "@material/mwc-list/mwc-list";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { mdiDotsVertical, mdiDownload, mdiRefresh, mdiText } from "@mdi/js";
|
||||||
import type { CSSResultGroup } from "lit";
|
import type { CSSResultGroup } from "lit";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import type { LocalizeFunc } from "../../../common/translations/localize";
|
import type { LocalizeFunc } from "../../../common/translations/localize";
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
import "../../../components/buttons/ha-progress-button";
|
import "../../../components/buttons/ha-progress-button";
|
||||||
|
import "../../../components/ha-button-menu";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../../components/ha-circular-progress";
|
import "../../../components/ha-circular-progress";
|
||||||
import "../../../components/ha-icon-button";
|
import "../../../components/ha-icon-button";
|
||||||
import "../../../components/ha-list-item";
|
import "../../../components/ha-list-item";
|
||||||
|
import { getSignedPath } from "../../../data/auth";
|
||||||
|
import { getErrorLogDownloadUrl } from "../../../data/error_log";
|
||||||
import { domainToName } from "../../../data/integration";
|
import { domainToName } from "../../../data/integration";
|
||||||
import type { LoggedError } from "../../../data/system_log";
|
import type { LoggedError } from "../../../data/system_log";
|
||||||
import {
|
import {
|
||||||
@@ -19,6 +23,7 @@ import {
|
|||||||
isCustomIntegrationError,
|
isCustomIntegrationError,
|
||||||
} from "../../../data/system_log";
|
} from "../../../data/system_log";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import { fileDownload } from "../../../util/file_download";
|
||||||
import { showSystemLogDetailDialog } from "./show-dialog-system-log-detail";
|
import { showSystemLogDetailDialog } from "./show-dialog-system-log-detail";
|
||||||
import { formatSystemLogTime } from "./util";
|
import { formatSystemLogTime } from "./util";
|
||||||
|
|
||||||
@@ -104,11 +109,34 @@ export class SystemLogCard extends LitElement {
|
|||||||
: html`
|
: html`
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1 class="card-header">${this.header || "Logs"}</h1>
|
<h1 class="card-header">${this.header || "Logs"}</h1>
|
||||||
<ha-icon-button
|
<div class="header-buttons">
|
||||||
.path=${mdiRefresh}
|
<ha-icon-button
|
||||||
@click=${this.fetchData}
|
.path=${mdiDownload}
|
||||||
.label=${this.hass.localize("ui.common.refresh")}
|
@click=${this._downloadLogs}
|
||||||
></ha-icon-button>
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.logs.download_logs"
|
||||||
|
)}
|
||||||
|
></ha-icon-button>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiRefresh}
|
||||||
|
@click=${this.fetchData}
|
||||||
|
.label=${this.hass.localize("ui.common.refresh")}
|
||||||
|
></ha-icon-button>
|
||||||
|
|
||||||
|
<ha-button-menu @action=${this._handleOverflowAction}>
|
||||||
|
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
|
||||||
|
</ha-icon-button>
|
||||||
|
<ha-list-item graphic="icon">
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${mdiText}
|
||||||
|
></ha-svg-icon>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.logs.show_full_logs"
|
||||||
|
)}
|
||||||
|
</ha-list-item>
|
||||||
|
</ha-button-menu>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
${this._items.length === 0
|
${this._items.length === 0
|
||||||
? html`
|
? html`
|
||||||
@@ -195,6 +223,19 @@ export class SystemLogCard extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _handleOverflowAction() {
|
||||||
|
// @ts-ignore
|
||||||
|
fireEvent(this, "switch-log-view");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _downloadLogs() {
|
||||||
|
const timeString = new Date().toISOString().replace(/:/g, "-");
|
||||||
|
const downloadUrl = getErrorLogDownloadUrl;
|
||||||
|
const logFileName = `home-assistant_${timeString}.log`;
|
||||||
|
const signedUrl = await getSignedPath(this.hass, downloadUrl);
|
||||||
|
fileDownload(signedUrl.path, logFileName);
|
||||||
|
}
|
||||||
|
|
||||||
private _openLog(ev: Event): void {
|
private _openLog(ev: Event): void {
|
||||||
const item = (ev.currentTarget as any).logItem;
|
const item = (ev.currentTarget as any).logItem;
|
||||||
showSystemLogDetailDialog(this, { item });
|
showSystemLogDetailDialog(this, { item });
|
||||||
@@ -203,7 +244,7 @@ export class SystemLogCard extends LitElement {
|
|||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
ha-card {
|
ha-card {
|
||||||
padding-top: 16px;
|
padding-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
@@ -212,6 +253,11 @@ export class SystemLogCard extends LitElement {
|
|||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.card-header {
|
.card-header {
|
||||||
color: var(--ha-card-header-color, var(--primary-text-color));
|
color: var(--ha-card-header-color, var(--primary-text-color));
|
||||||
font-family: var(--ha-card-header-font-family, inherit);
|
font-family: var(--ha-card-header-font-family, inherit);
|
||||||
@@ -243,6 +289,10 @@ export class SystemLogCard extends LitElement {
|
|||||||
color: var(--warning-color);
|
color: var(--warning-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-content {
|
||||||
|
border-top: 1px solid var(--divider-color);
|
||||||
|
}
|
||||||
|
|
||||||
.card-actions,
|
.card-actions,
|
||||||
.empty-content {
|
.empty-content {
|
||||||
direction: var(--direction);
|
direction: var(--direction);
|
||||||
|
@@ -31,7 +31,7 @@ export class HuiRecoveryModeCard extends LitElement implements LovelaceCard {
|
|||||||
"ui.panel.lovelace.cards.recovery-mode.description"
|
"ui.panel.lovelace.cards.recovery-mode.description"
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<error-log-card .hass=${this.hass}></error-log-card>
|
<error-log-card .hass=${this.hass} provider="core"></error-log-card>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,7 @@ class HuiViewContainer extends LitElement {
|
|||||||
|
|
||||||
private _isFixedBackground(background?: BackgroundConfig) {
|
private _isFixedBackground(background?: BackgroundConfig) {
|
||||||
if (typeof background === "string") {
|
if (typeof background === "string") {
|
||||||
return background.includes(" fixed");
|
return background.split(" ").includes("fixed");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ class HuiViewContainer extends LitElement {
|
|||||||
);
|
);
|
||||||
background-attachment: scroll !important;
|
background-attachment: scroll !important;
|
||||||
}
|
}
|
||||||
:host(:not(fixed-background)) {
|
:host(:not([fixed-background])) {
|
||||||
background: var(
|
background: var(
|
||||||
--view-background,
|
--view-background,
|
||||||
var(--lovelace-background, var(--primary-background-color))
|
var(--lovelace-background, var(--primary-background-color))
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
import type Sortable from "sortablejs";
|
import type Sortable from "sortablejs";
|
||||||
import SortableCore, {
|
import SortableCore, {
|
||||||
OnSpill,
|
|
||||||
AutoScroll,
|
AutoScroll,
|
||||||
|
OnSpill,
|
||||||
} from "sortablejs/modular/sortable.core.esm";
|
} from "sortablejs/modular/sortable.core.esm";
|
||||||
|
|
||||||
SortableCore.mount(OnSpill, new AutoScroll());
|
SortableCore.mount(OnSpill);
|
||||||
|
SortableCore.mount(new AutoScroll());
|
||||||
|
|
||||||
export default SortableCore as typeof Sortable;
|
export default SortableCore as typeof Sortable;
|
||||||
|
|
||||||
|
@@ -158,6 +158,7 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
|||||||
},
|
},
|
||||||
callApi: async (method, path, parameters, headers) =>
|
callApi: async (method, path, parameters, headers) =>
|
||||||
hassCallApi(auth, method, path, parameters, headers),
|
hassCallApi(auth, method, path, parameters, headers),
|
||||||
|
// callApiRaw introduced in 2024.11
|
||||||
callApiRaw: async (method, path, parameters, headers, signal) =>
|
callApiRaw: async (method, path, parameters, headers, signal) =>
|
||||||
hassCallApiRaw(auth, method, path, parameters, headers, signal),
|
hassCallApiRaw(auth, method, path, parameters, headers, signal),
|
||||||
fetchWithAuth: (
|
fetchWithAuth: (
|
||||||
|
@@ -2470,9 +2470,9 @@
|
|||||||
"search": "Search logs",
|
"search": "Search logs",
|
||||||
"failed_get_logs": "Failed to get {provider} logs, {error}",
|
"failed_get_logs": "Failed to get {provider} logs, {error}",
|
||||||
"no_issues_search": "No issues found for search term ''{term}''",
|
"no_issues_search": "No issues found for search term ''{term}''",
|
||||||
"load_logs": "Load full logs",
|
"load_logs": "Load logs",
|
||||||
"nr_of_lines": "Number of lines",
|
"nr_of_lines": "Number of lines",
|
||||||
"loading_log": "Loading full log…",
|
"loading_log": "Loading log…",
|
||||||
"no_errors": "No errors have been reported",
|
"no_errors": "No errors have been reported",
|
||||||
"no_issues": "There are no new issues!",
|
"no_issues": "There are no new issues!",
|
||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
@@ -2489,7 +2489,8 @@
|
|||||||
},
|
},
|
||||||
"custom_integration": "custom integration",
|
"custom_integration": "custom integration",
|
||||||
"error_from_custom_integration": "This error originated from a custom integration.",
|
"error_from_custom_integration": "This error originated from a custom integration.",
|
||||||
"show_full_logs": "Show full logs",
|
"show_full_logs": "Show raw logs",
|
||||||
|
"show_condensed_logs": "Show condensed logs",
|
||||||
"select_number_of_lines": "Select number of lines to download",
|
"select_number_of_lines": "Select number of lines to download",
|
||||||
"lines": "Lines",
|
"lines": "Lines",
|
||||||
"download_logs": "Download logs",
|
"download_logs": "Download logs",
|
||||||
@@ -4841,7 +4842,6 @@
|
|||||||
"node_id": "ID",
|
"node_id": "ID",
|
||||||
"node_ready": "Ready",
|
"node_ready": "Ready",
|
||||||
"device_config": "Configure",
|
"device_config": "Configure",
|
||||||
"installer_settings": "Installer settings",
|
|
||||||
"reinterview_device": "Re-interview",
|
"reinterview_device": "Re-interview",
|
||||||
"rebuild_routes": "Rebuild routes",
|
"rebuild_routes": "Rebuild routes",
|
||||||
"remove_failed": "Remove failed",
|
"remove_failed": "Remove failed",
|
||||||
@@ -5133,45 +5133,6 @@
|
|||||||
"subscribed_to_logs": "Subscribed to Z-Wave JS log messages…",
|
"subscribed_to_logs": "Subscribed to Z-Wave JS log messages…",
|
||||||
"log_level_changed": "Log Level changed to: {level}",
|
"log_level_changed": "Log Level changed to: {level}",
|
||||||
"download_logs": "Download logs"
|
"download_logs": "Download logs"
|
||||||
},
|
|
||||||
"node_installer": {
|
|
||||||
"header": "Installer Settings",
|
|
||||||
"introduction": "Configure your device installer settings.",
|
|
||||||
"endpoint": "Endpoint",
|
|
||||||
"no_settings": "This device does not have any installer settings.",
|
|
||||||
"command_class": "Command Class",
|
|
||||||
"capability_controls": {
|
|
||||||
"thermostat_setback": {
|
|
||||||
"title": "Thermostat Setback",
|
|
||||||
"setback_state_label": "Setback in 1/10 degrees (Kelvin)",
|
|
||||||
"setback_state_helper": "Min: -12.8, max: 12.0",
|
|
||||||
"setback_special_state": {
|
|
||||||
"label": "Setback special state",
|
|
||||||
"frost_protection": "Frost protection",
|
|
||||||
"energy_saving": "Energy saving",
|
|
||||||
"unused": "Unused"
|
|
||||||
},
|
|
||||||
"setback_type": {
|
|
||||||
"label": "Setback Type",
|
|
||||||
"none": "None",
|
|
||||||
"temporary": "Temporary",
|
|
||||||
"permanent": "Permanent"
|
|
||||||
},
|
|
||||||
"get_setback_failed": "Failed to get setback state. {error}",
|
|
||||||
"save_setback_failed": "Failed to save setback state. {error}"
|
|
||||||
},
|
|
||||||
"multilevel_switch": {
|
|
||||||
"title": "Transition",
|
|
||||||
"direction": "Direction",
|
|
||||||
"up": "Up",
|
|
||||||
"down": "Down",
|
|
||||||
"ignore_start_level": "Ignore start level",
|
|
||||||
"start_level": "Start level",
|
|
||||||
"start_transition": "Start transition",
|
|
||||||
"stop_transition": "Stop transition",
|
|
||||||
"control_failed": "Failed to control transition. {error}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"matter": {
|
"matter": {
|
||||||
|
@@ -259,7 +259,7 @@ export interface HomeAssistant {
|
|||||||
parameters?: Record<string, any>,
|
parameters?: Record<string, any>,
|
||||||
headers?: Record<string, string>
|
headers?: Record<string, string>
|
||||||
): Promise<T>;
|
): Promise<T>;
|
||||||
callApiRaw(
|
callApiRaw( // introduced in 2024.11
|
||||||
method: "GET" | "POST" | "PUT" | "DELETE",
|
method: "GET" | "POST" | "PUT" | "DELETE",
|
||||||
path: string,
|
path: string,
|
||||||
parameters?: Record<string, any>,
|
parameters?: Record<string, any>,
|
||||||
|
186
yarn.lock
186
yarn.lock
@@ -1413,150 +1413,150 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/ecma402-abstract@npm:2.2.3":
|
"@formatjs/ecma402-abstract@npm:2.2.1":
|
||||||
version: 2.2.3
|
version: 2.2.1
|
||||||
resolution: "@formatjs/ecma402-abstract@npm:2.2.3"
|
resolution: "@formatjs/ecma402-abstract@npm:2.2.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/fast-memoize": "npm:2.2.3"
|
"@formatjs/fast-memoize": "npm:2.2.2"
|
||||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/d39e9f0d36c296a635f52aa35e07a67b6aa90383a30a046a0508e5d730676399fd0e67188eff463fe2a4d5febc9f567af45788fdf881e070910be7eb9294dd8c
|
checksum: 10/8c281e14cb5f12b8697225be6b0ac13d057911e257d3c23928aad985b535df90b7bb2a235aab22753a6e57aef98f00b826514fc3703e69018ccc98c8d9848f38
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/fast-memoize@npm:2.2.3":
|
"@formatjs/fast-memoize@npm:2.2.2":
|
||||||
version: 2.2.3
|
version: 2.2.2
|
||||||
resolution: "@formatjs/fast-memoize@npm:2.2.3"
|
resolution: "@formatjs/fast-memoize@npm:2.2.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/a9634acb5e03d051e09881eea5484ab02271f7d6b5f96ae9485674ab3c359aa881bc45fc07a1181ae4b2d6e288dadc169f578d142d698913ebbefa373014cac2
|
checksum: 10/c6e958753eb41bb0875734762a44126a0d570706a31b32bb409e759cd372184c28e294b02fce0b0f0999c171ef717d513eaf7936862c498d78428b97db446ff8
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/icu-messageformat-parser@npm:2.9.3":
|
"@formatjs/icu-messageformat-parser@npm:2.9.1":
|
||||||
version: 2.9.3
|
version: 2.9.1
|
||||||
resolution: "@formatjs/icu-messageformat-parser@npm:2.9.3"
|
resolution: "@formatjs/icu-messageformat-parser@npm:2.9.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
"@formatjs/icu-skeleton-parser": "npm:1.8.7"
|
"@formatjs/icu-skeleton-parser": "npm:1.8.5"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/b24a3db43e4bf612107e981d5b40c077543d2266a08aac5cf01d5f65bf60527d5d16795e2e30063cb180b1d36d401944cd2ffb3a19d79b0cd28fa59751d19b7c
|
checksum: 10/f52c7c55b1dfc141910089a0494abd98d1c13c0a359cfb3bfa0668a5e2015c0c579bf161978fdb3ab40fa9a7374a37ac062f8710ed285429bf60abde4a5d1183
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/icu-skeleton-parser@npm:1.8.7":
|
"@formatjs/icu-skeleton-parser@npm:1.8.5":
|
||||||
version: 1.8.7
|
version: 1.8.5
|
||||||
resolution: "@formatjs/icu-skeleton-parser@npm:1.8.7"
|
resolution: "@formatjs/icu-skeleton-parser@npm:1.8.5"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/1a39815e5048f3c12a8d6a5b553271437b62e302724fc15c3b6967dc3e24823fcd9b8d3231a064991e163c147e54e588c571a092d557e93e78e738d218c6ef43
|
checksum: 10/5b9c57f80b751483bef8897ff9607a9eb215fd7a8d8ae9fa5c631edf6d16fa4532c853395f20b7f3f38d6d4d1a35b98cd06421291203c7ad333f52077ef2a406
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-datetimeformat@npm:6.16.3":
|
"@formatjs/intl-datetimeformat@npm:6.16.1":
|
||||||
version: 6.16.3
|
version: 6.16.1
|
||||||
resolution: "@formatjs/intl-datetimeformat@npm:6.16.3"
|
resolution: "@formatjs/intl-datetimeformat@npm:6.16.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/4e213611b92eda40aa6053b9458be71fb752f020616bb0e93fc681efc4fc408dfec408ae33ded8678887730f8ee766568f90b6ca57de6e9d8f1de45dda794f08
|
checksum: 10/494868322d396e0eede6a27c16047858944f42fd3b45cf5d155f963df62e694b842ac0bef07e23aa73fa55cf143956d642d05ea62a3e762632101451975b5fc4
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-displaynames@npm:6.8.3":
|
"@formatjs/intl-displaynames@npm:6.8.1":
|
||||||
version: 6.8.3
|
version: 6.8.1
|
||||||
resolution: "@formatjs/intl-displaynames@npm:6.8.3"
|
resolution: "@formatjs/intl-displaynames@npm:6.8.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/46c8d6e6d6d56d5f495c0bfb5784687a0af1ffd9eaeb72c1d9db8e21f8c7eeec346198871f8fe39f6eebfb19d6c3e46cbf92e213e6a6f0dfdb2f55fe96d43bcc
|
checksum: 10/627fc625e14b4d1bea5b2bf41e40050eb9775d0f66780e155719e21c062f9b3331d08b488ebcd3608c60999498af5a39e67cb5fd2a6d54a0e7395d7a63bfe643
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-enumerator@npm:1.8.3":
|
"@formatjs/intl-enumerator@npm:1.8.1":
|
||||||
version: 1.8.3
|
version: 1.8.1
|
||||||
resolution: "@formatjs/intl-enumerator@npm:1.8.3"
|
resolution: "@formatjs/intl-enumerator@npm:1.8.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/a51ed7e15835cc1612282de46139d0f49553f004439a728a9118d1b9b15a3d05916e8aad4001e18c4909a3d4287fc07c921540c5ba8f32499f3243ac50d68a42
|
checksum: 10/0e4250de905e757fb88d6ff072968c72ed3a39de8ddaed73c38c0099825f11530c9b8e224573ae6e46cf49f1318e463f40ba2cdfa25cb7415382ba952b570bdc
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-getcanonicallocales@npm:2.5.2":
|
"@formatjs/intl-getcanonicallocales@npm:2.5.1":
|
||||||
version: 2.5.2
|
version: 2.5.1
|
||||||
resolution: "@formatjs/intl-getcanonicallocales@npm:2.5.2"
|
resolution: "@formatjs/intl-getcanonicallocales@npm:2.5.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/0d1738181911635d91d4a788d663fadd1aa045f40f0f05ac8b04adc06cd4f5ee3c50aa7c3a50c63ba7572f23e336720340c8240d6070d899e56adf25d0388f1b
|
checksum: 10/5e83c0b3574333e5027c3c4f74ea20800e50e36fb8efa69361457b57f618738f478b5d22777ba30a2b7a15bdff60101d8119169c909b33577244747d52e59614
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-listformat@npm:7.7.3":
|
"@formatjs/intl-listformat@npm:7.7.1":
|
||||||
version: 7.7.3
|
version: 7.7.1
|
||||||
resolution: "@formatjs/intl-listformat@npm:7.7.3"
|
resolution: "@formatjs/intl-listformat@npm:7.7.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/52ae02202a2bb0d8c16ea9a8f142d616e6ecb8400aa96ca618896cf529a3e3f5d88d64cb2644ad6a4ba7e17ee013d8fb3463419802afab5ca25afa51151ab62c
|
checksum: 10/a64581f1d2e8e0c0c83c5d56334a3e3786ed251e1a882d7610d2588d8602eacb32c9167032891e2796c30df3437c9ce52c7284786dca6f1f44250301060169ea
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-locale@npm:4.2.3":
|
"@formatjs/intl-locale@npm:4.2.1":
|
||||||
version: 4.2.3
|
version: 4.2.1
|
||||||
resolution: "@formatjs/intl-locale@npm:4.2.3"
|
resolution: "@formatjs/intl-locale@npm:4.2.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
"@formatjs/intl-enumerator": "npm:1.8.3"
|
"@formatjs/intl-enumerator": "npm:1.8.1"
|
||||||
"@formatjs/intl-getcanonicallocales": "npm:2.5.2"
|
"@formatjs/intl-getcanonicallocales": "npm:2.5.1"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/dab4090653e62f1c3453c074c3047d0e22ee6a3d33ac00afa45f1541b8686b453c671755e8faeeb1253b61131071c02506b56c094941efd6195d40163007182e
|
checksum: 10/4cba0fbeded2c7c5806528806f176cb833c43765bf1717470f4e001ab42581d5f0b52bf1893afef9597fba96dc3d4659507e490030f231523d460ec6686b9562
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-localematcher@npm:0.5.7":
|
"@formatjs/intl-localematcher@npm:0.5.6":
|
||||||
version: 0.5.7
|
version: 0.5.6
|
||||||
resolution: "@formatjs/intl-localematcher@npm:0.5.7"
|
resolution: "@formatjs/intl-localematcher@npm:0.5.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/52201f12212e7e9cba1a4f99020da587b13e44e06e03c4ccd4e5ac0829b411e73dfe0904a9039ef81eeabeea04ed8cfae9e727e6791acd0230745b7bd3ad059e
|
checksum: 10/14eac6bb25dcfeedd7960f44dec5a137999729da00b294ddf1133abe760ced4342f37734bc750b4c47f8dd8d5633a7da38d274503f80d7e965bb1f6fb6f2988c
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-numberformat@npm:8.14.3":
|
"@formatjs/intl-numberformat@npm:8.14.1":
|
||||||
version: 8.14.3
|
version: 8.14.1
|
||||||
resolution: "@formatjs/intl-numberformat@npm:8.14.3"
|
resolution: "@formatjs/intl-numberformat@npm:8.14.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/7a4e52ace65589ceb441032a09b88616e71ba4220605e498b1a064f43672cad5cca8c98b72446ffd7d57ef098c658c245c08a16623e0b1bc10940ff7e71069c7
|
checksum: 10/51152d1b9607a35c64e6089e44b90c7ec90be3b1925ba47ffc559ddb4fd72afae76e83af3d436831ea0fc47dc0e9fee9cd3d576280440f2dce03cb6bd24e0bed
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-pluralrules@npm:5.3.3":
|
"@formatjs/intl-pluralrules@npm:5.3.1":
|
||||||
version: 5.3.3
|
version: 5.3.1
|
||||||
resolution: "@formatjs/intl-pluralrules@npm:5.3.3"
|
resolution: "@formatjs/intl-pluralrules@npm:5.3.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/3679c63aa2b9dde474572998b829ecb5d134f1efe508e1e5a06089480bbff9f2216235a7d5745c434030dc17c8a83385f0639a71a22f1d648fcbc6fff90f57e3
|
checksum: 10/fc83c3547a9f0af6331c2970f265234fde967848ff738730f2e87ce816636d8778ead1185f5ecccc692cb8b63c11412dc85deac9d3425f44fe3a6a6c30c8b776
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@formatjs/intl-relativetimeformat@npm:11.4.3":
|
"@formatjs/intl-relativetimeformat@npm:11.4.1":
|
||||||
version: 11.4.3
|
version: 11.4.1
|
||||||
resolution: "@formatjs/intl-relativetimeformat@npm:11.4.3"
|
resolution: "@formatjs/intl-relativetimeformat@npm:11.4.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/7c7548ba133031873683a37566d646e4e3f50ea979773de199b41769df23648be2b44b53975809bd53f97a95d1d44038c0a09b1c031e05f0de6f7bba843b1aad
|
checksum: 10/80817403301baed257fbd8c793b9ed077a2e6dd0414a6895b5bfde3619aebc818f30535da9b560a6186fac783cf09561c495d2c6568a980bd635736194655af5
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -8759,14 +8759,14 @@ __metadata:
|
|||||||
"@codemirror/state": "npm:6.4.1"
|
"@codemirror/state": "npm:6.4.1"
|
||||||
"@codemirror/view": "npm:6.34.1"
|
"@codemirror/view": "npm:6.34.1"
|
||||||
"@egjs/hammerjs": "npm:2.0.17"
|
"@egjs/hammerjs": "npm:2.0.17"
|
||||||
"@formatjs/intl-datetimeformat": "npm:6.16.3"
|
"@formatjs/intl-datetimeformat": "npm:6.16.1"
|
||||||
"@formatjs/intl-displaynames": "npm:6.8.3"
|
"@formatjs/intl-displaynames": "npm:6.8.1"
|
||||||
"@formatjs/intl-getcanonicallocales": "npm:2.5.2"
|
"@formatjs/intl-getcanonicallocales": "npm:2.5.1"
|
||||||
"@formatjs/intl-listformat": "npm:7.7.3"
|
"@formatjs/intl-listformat": "npm:7.7.1"
|
||||||
"@formatjs/intl-locale": "npm:4.2.3"
|
"@formatjs/intl-locale": "npm:4.2.1"
|
||||||
"@formatjs/intl-numberformat": "npm:8.14.3"
|
"@formatjs/intl-numberformat": "npm:8.14.1"
|
||||||
"@formatjs/intl-pluralrules": "npm:5.3.3"
|
"@formatjs/intl-pluralrules": "npm:5.3.1"
|
||||||
"@formatjs/intl-relativetimeformat": "npm:11.4.3"
|
"@formatjs/intl-relativetimeformat": "npm:11.4.1"
|
||||||
"@fullcalendar/core": "npm:6.1.15"
|
"@fullcalendar/core": "npm:6.1.15"
|
||||||
"@fullcalendar/daygrid": "npm:6.1.15"
|
"@fullcalendar/daygrid": "npm:6.1.15"
|
||||||
"@fullcalendar/interaction": "npm:6.1.15"
|
"@fullcalendar/interaction": "npm:6.1.15"
|
||||||
@@ -8898,7 +8898,7 @@ __metadata:
|
|||||||
husky: "npm:9.1.6"
|
husky: "npm:9.1.6"
|
||||||
idb-keyval: "npm:6.2.1"
|
idb-keyval: "npm:6.2.1"
|
||||||
instant-mocha: "npm:1.5.3"
|
instant-mocha: "npm:1.5.3"
|
||||||
intl-messageformat: "npm:10.7.5"
|
intl-messageformat: "npm:10.7.3"
|
||||||
js-yaml: "npm:4.1.0"
|
js-yaml: "npm:4.1.0"
|
||||||
jszip: "npm:3.10.1"
|
jszip: "npm:3.10.1"
|
||||||
leaflet: "npm:1.9.4"
|
leaflet: "npm:1.9.4"
|
||||||
@@ -9348,15 +9348,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"intl-messageformat@npm:10.7.5":
|
"intl-messageformat@npm:10.7.3":
|
||||||
version: 10.7.5
|
version: 10.7.3
|
||||||
resolution: "intl-messageformat@npm:10.7.5"
|
resolution: "intl-messageformat@npm:10.7.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||||
"@formatjs/fast-memoize": "npm:2.2.3"
|
"@formatjs/fast-memoize": "npm:2.2.2"
|
||||||
"@formatjs/icu-messageformat-parser": "npm:2.9.3"
|
"@formatjs/icu-messageformat-parser": "npm:2.9.1"
|
||||||
tslib: "npm:2"
|
tslib: "npm:2"
|
||||||
checksum: 10/8880448d62bd0260eafd4ee7ccfabaea573476f28e6d6bf47e027ee9c1d46d4919a076df7abedaf282422ff80ade02b5c637c69cdf739ee405e4837098bac37e
|
checksum: 10/e387f7f37a295d9d386af0c6392ba135a4580e86177161f1f400d470fed1f8c7b3cb6c724cbc2f50a7ded2e20f202977d8bf5e2bbc626f72016a5b5b6752b76d
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user