mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-29 02:59:25 +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}
|
||||
.header=${this.addon.name}
|
||||
.provider=${this.addon.slug}
|
||||
show
|
||||
.filter=${this._filter}
|
||||
>
|
||||
</error-log-card>
|
||||
|
18
package.json
18
package.json
@@ -35,14 +35,14 @@
|
||||
"@codemirror/state": "6.4.1",
|
||||
"@codemirror/view": "6.34.1",
|
||||
"@egjs/hammerjs": "2.0.17",
|
||||
"@formatjs/intl-datetimeformat": "6.16.3",
|
||||
"@formatjs/intl-displaynames": "6.8.3",
|
||||
"@formatjs/intl-getcanonicallocales": "2.5.2",
|
||||
"@formatjs/intl-listformat": "7.7.3",
|
||||
"@formatjs/intl-locale": "4.2.3",
|
||||
"@formatjs/intl-numberformat": "8.14.3",
|
||||
"@formatjs/intl-pluralrules": "5.3.3",
|
||||
"@formatjs/intl-relativetimeformat": "11.4.3",
|
||||
"@formatjs/intl-datetimeformat": "6.16.1",
|
||||
"@formatjs/intl-displaynames": "6.8.1",
|
||||
"@formatjs/intl-getcanonicallocales": "2.5.1",
|
||||
"@formatjs/intl-listformat": "7.7.1",
|
||||
"@formatjs/intl-locale": "4.2.1",
|
||||
"@formatjs/intl-numberformat": "8.14.1",
|
||||
"@formatjs/intl-pluralrules": "5.3.1",
|
||||
"@formatjs/intl-relativetimeformat": "11.4.1",
|
||||
"@fullcalendar/core": "6.1.15",
|
||||
"@fullcalendar/daygrid": "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",
|
||||
"home-assistant-js-websocket": "9.4.0",
|
||||
"idb-keyval": "6.2.1",
|
||||
"intl-messageformat": "10.7.5",
|
||||
"intl-messageformat": "10.7.3",
|
||||
"js-yaml": "4.1.0",
|
||||
"leaflet": "1.9.4",
|
||||
"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]
|
||||
name = "home-assistant-frontend"
|
||||
version = "20241106.0"
|
||||
version = "20241106.1"
|
||||
license = {text = "Apache-2.0"}
|
||||
description = "The Home Assistant frontend"
|
||||
readme = "README.md"
|
||||
|
@@ -117,8 +117,8 @@ export class HaPasswordField extends LitElement {
|
||||
.autocapitalize=${this.autocapitalize}
|
||||
.type=${this._unmaskedPassword ? "text" : "password"}
|
||||
.suffix=${html`<div style="width: 24px"></div>`}
|
||||
@input=${this._handleInputChange}
|
||||
@change=${this._reDispatchEvent}
|
||||
@input=${this._handleInputEvent}
|
||||
@change=${this._handleChangeEvent}
|
||||
></ha-textfield>
|
||||
<ha-icon-button
|
||||
toggles
|
||||
@@ -153,11 +153,16 @@ export class HaPasswordField extends LitElement {
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
private _handleInputChange(ev) {
|
||||
private _handleInputEvent(ev) {
|
||||
this.value = ev.target.value;
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
private _handleChangeEvent(ev) {
|
||||
this.value = ev.target.value;
|
||||
this._reDispatchEvent(ev);
|
||||
}
|
||||
|
||||
private _reDispatchEvent(oldEvent: Event) {
|
||||
const newEvent = new Event(oldEvent.type, oldEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
|
@@ -135,6 +135,10 @@ export class HaSortable extends LitElement {
|
||||
const Sortable = (await import("../resources/sortable")).default;
|
||||
|
||||
const options: SortableInstance.Options = {
|
||||
scroll: true,
|
||||
// Force the autoscroll fallback because it works better than the native one
|
||||
forceAutoScrollFallback: true,
|
||||
scrollSpeed: 20,
|
||||
animation: 150,
|
||||
...this.options,
|
||||
onChoose: this._handleChoose,
|
||||
|
@@ -185,6 +185,15 @@ export const fetchHassioInfo = async (
|
||||
export const fetchHassioBoots = async (hass: HomeAssistant) =>
|
||||
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 (
|
||||
hass: HomeAssistant,
|
||||
provider: string,
|
||||
|
@@ -209,17 +209,6 @@ export interface ZWaveJSNodeStatus {
|
||||
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 {
|
||||
node_id: number;
|
||||
exclusion: string;
|
||||
@@ -415,25 +404,6 @@ export interface RequestedGrant {
|
||||
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 = (
|
||||
hass: HomeAssistant,
|
||||
device_or_entry_id: {
|
||||
@@ -609,15 +579,6 @@ export const fetchZwaveNodeStatus = (
|
||||
device_id,
|
||||
});
|
||||
|
||||
export const fetchZwaveNodeCapabilities = (
|
||||
hass: HomeAssistant,
|
||||
device_id: string
|
||||
): Promise<ZWaveJSNodeCapabilities> =>
|
||||
hass.callWS({
|
||||
type: "zwave_js/node_capabilities",
|
||||
device_id,
|
||||
});
|
||||
|
||||
export const subscribeZwaveNodeStatus = (
|
||||
hass: HomeAssistant,
|
||||
device_id: string,
|
||||
|
@@ -5,7 +5,6 @@ import {
|
||||
mdiHospitalBox,
|
||||
mdiInformation,
|
||||
mdiUpload,
|
||||
mdiWrench,
|
||||
} from "@mdi/js";
|
||||
import { getConfigEntries } from "../../../../../../data/config_entries";
|
||||
import type { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
||||
@@ -99,13 +98,6 @@ export const getZwaveDeviceActions = async (
|
||||
showZWaveJSNodeStatisticsDialog(el, {
|
||||
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",
|
||||
load: () => import("./zwave_js-node-config"),
|
||||
},
|
||||
node_installer: {
|
||||
tag: "zwave_js-node-installer",
|
||||
load: () => import("./zwave_js-node-installer"),
|
||||
},
|
||||
logs: {
|
||||
tag: "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,
|
||||
mdiWrap,
|
||||
mdiWrapDisabled,
|
||||
mdiFolderTextOutline,
|
||||
} from "@mdi/js";
|
||||
import {
|
||||
css,
|
||||
@@ -49,6 +50,7 @@ import {
|
||||
fetchHassioBoots,
|
||||
fetchHassioLogs,
|
||||
fetchHassioLogsFollow,
|
||||
fetchHassioLogsLegacy,
|
||||
getHassioLogDownloadLinesUrl,
|
||||
getHassioLogDownloadUrl,
|
||||
} from "../../../data/hassio/supervisor";
|
||||
@@ -57,7 +59,7 @@ import {
|
||||
downloadFileSupported,
|
||||
fileDownload,
|
||||
} 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 { atLeastVersion } from "../../../common/config/version";
|
||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||
@@ -78,9 +80,10 @@ class ErrorLogCard extends LitElement {
|
||||
|
||||
@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;
|
||||
|
||||
@@ -129,26 +132,32 @@ class ErrorLogCard extends LitElement {
|
||||
|
||||
@state() private _wrapLines = true;
|
||||
|
||||
@state() private _downloadSupported;
|
||||
@state() private _downloadSupported?: boolean;
|
||||
|
||||
@state() private _logsFileLink;
|
||||
@state() private _logsFileLink?: string;
|
||||
|
||||
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;
|
||||
return html`
|
||||
<div class="error-log-intro">
|
||||
${this._error
|
||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||
: nothing}
|
||||
<ha-card outlined class=${classMap({ hidden: this.show === false })}>
|
||||
<ha-card outlined>
|
||||
<div class="header">
|
||||
<h1 class="card-header">
|
||||
${this.header || localize("ui.panel.config.logs.show_full_logs")}
|
||||
</h1>
|
||||
<div class="action-buttons">
|
||||
${this._streamSupported &&
|
||||
Array.isArray(this._boots) &&
|
||||
this._showBootsSelect
|
||||
${hasBoots && this._showBootsSelect
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
.title=${localize(
|
||||
@@ -174,7 +183,7 @@ class ErrorLogCard extends LitElement {
|
||||
id="boots-menu"
|
||||
positioning="fixed"
|
||||
>
|
||||
${this._boots.map(
|
||||
${this._boots!.map(
|
||||
(boot) => html`
|
||||
<ha-md-menu-item
|
||||
.value=${boot}
|
||||
@@ -231,27 +240,40 @@ class ErrorLogCard extends LitElement {
|
||||
`ui.panel.config.logs.${this._wrapLines ? "full_width" : "wrap_lines"}`
|
||||
)}
|
||||
></ha-icon-button>
|
||||
${!this._streamSupported || this._error
|
||||
${!streaming || this._error
|
||||
? html`<ha-icon-button
|
||||
.path=${mdiRefresh}
|
||||
@click=${this._loadLogs}
|
||||
.label=${localize("ui.common.refresh")}
|
||||
></ha-icon-button>`
|
||||
: nothing}
|
||||
${this._streamSupported && Array.isArray(this._boots)
|
||||
${(this.allowSwitch && this.provider === "core") || hasBoots
|
||||
? html`
|
||||
<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=${mdiFormatListNumbered}
|
||||
></ha-svg-icon>
|
||||
${localize(
|
||||
`ui.panel.config.logs.${this._showBootsSelect ? "hide" : "show"}_haos_boots`
|
||||
)}
|
||||
</ha-list-item>
|
||||
${this.allowSwitch && this.provider === "core"
|
||||
? html`<ha-list-item graphic="icon">
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiFolderTextOutline}
|
||||
></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.logs.show_condensed_logs"
|
||||
)}
|
||||
</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>
|
||||
`
|
||||
: nothing}
|
||||
@@ -304,47 +326,34 @@ class ErrorLogCard extends LitElement {
|
||||
slot="trailingIcon"
|
||||
></ha-svg-icon>
|
||||
</ha-button>
|
||||
${this._streamSupported &&
|
||||
this._loadingState !== "loading" &&
|
||||
!this._error
|
||||
${streaming && this._boot === 0 && !this._error
|
||||
? html`<div class="live-indicator">
|
||||
<ha-svg-icon path=${mdiCircle}></ha-svg-icon>
|
||||
Live
|
||||
</div>`
|
||||
: nothing}
|
||||
</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>
|
||||
`;
|
||||
}
|
||||
|
||||
public connectedCallback() {
|
||||
super.connectedCallback();
|
||||
protected willUpdate(changedProps: PropertyValues) {
|
||||
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) {
|
||||
this._streamSupported = atLeastVersion(
|
||||
this.hass.config.version,
|
||||
2024,
|
||||
11
|
||||
);
|
||||
}
|
||||
if (this._downloadSupported === undefined && this.hass) {
|
||||
this._downloadSupported = downloadFileSupported(this.hass);
|
||||
}
|
||||
window.addEventListener("connection-status", this._handleConnectionStatus);
|
||||
|
||||
this.hass.loadFragmentTranslation("config");
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
@@ -354,28 +363,11 @@ class ErrorLogCard extends LitElement {
|
||||
|
||||
this._scrolledToTopController.callback = this._handleTopScroll;
|
||||
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) {
|
||||
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) {
|
||||
this._newLogsIndicator = false;
|
||||
}
|
||||
@@ -409,7 +401,7 @@ class ErrorLogCard extends LitElement {
|
||||
}
|
||||
|
||||
private async _downloadLogs(): Promise<void> {
|
||||
if (this._streamSupported) {
|
||||
if (this._streamSupported && this.provider) {
|
||||
showDownloadLogsDialog(this, {
|
||||
header: this.header,
|
||||
provider: this.provider,
|
||||
@@ -431,10 +423,6 @@ class ErrorLogCard extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _showLogs(): void {
|
||||
this.show = true;
|
||||
}
|
||||
|
||||
private async _loadLogs(): Promise<void> {
|
||||
this._error = undefined;
|
||||
this._loadingState = "loading";
|
||||
@@ -446,15 +434,16 @@ class ErrorLogCard extends LitElement {
|
||||
try {
|
||||
if (this._logStreamAborter) {
|
||||
this._logStreamAborter.abort();
|
||||
this._logStreamAborter = undefined;
|
||||
}
|
||||
|
||||
this._logStreamAborter = new AbortController();
|
||||
|
||||
if (
|
||||
this._streamSupported &&
|
||||
isComponentLoaded(this.hass, "hassio") &&
|
||||
this.provider
|
||||
) {
|
||||
this._logStreamAborter = new AbortController();
|
||||
|
||||
// check if there are any logs at all
|
||||
const testResponse = await fetchHassioLogs(
|
||||
this.hass,
|
||||
@@ -545,8 +534,7 @@ class ErrorLogCard extends LitElement {
|
||||
this._streamSupported = false;
|
||||
let logs = "";
|
||||
if (isComponentLoaded(this.hass, "hassio") && this.provider) {
|
||||
const repsonse = await fetchHassioLogs(this.hass, this.provider);
|
||||
logs = await repsonse.text();
|
||||
logs = await fetchHassioLogsLegacy(this.hass, this.provider);
|
||||
} else {
|
||||
logs = await fetchErrorLog(this.hass);
|
||||
}
|
||||
@@ -598,60 +586,62 @@ class ErrorLogCard extends LitElement {
|
||||
if (ev.detail === "disconnected" && this._logStreamAborter) {
|
||||
this._logStreamAborter.abort();
|
||||
}
|
||||
if (ev.detail === "connected" && this.show) {
|
||||
if (ev.detail === "connected") {
|
||||
this._loadLogs();
|
||||
}
|
||||
};
|
||||
|
||||
private async _loadMoreLogs() {
|
||||
if (
|
||||
this._firstCursor &&
|
||||
this._loadingPrevState !== "loading" &&
|
||||
this._loadingState === "loaded" &&
|
||||
this._logElement
|
||||
!this._firstCursor ||
|
||||
this._loadingPrevState === "loading" ||
|
||||
this._loadingState !== "loaded" ||
|
||||
!this._logElement ||
|
||||
!this.provider
|
||||
) {
|
||||
const scrolledToBottom = this._scrolledToBottomController.value;
|
||||
const scrollPositionFromBottom =
|
||||
this._logElement.scrollHeight - this._logElement.scrollTop;
|
||||
this._loadingPrevState = "loading";
|
||||
const response = await fetchHassioLogs(
|
||||
this.hass,
|
||||
this.provider,
|
||||
`entries=${this._firstCursor}:-100:100`,
|
||||
this._boot
|
||||
);
|
||||
return;
|
||||
}
|
||||
const scrolledToBottom = this._scrolledToBottomController.value;
|
||||
const scrollPositionFromBottom =
|
||||
this._logElement.scrollHeight - this._logElement.scrollTop;
|
||||
this._loadingPrevState = "loading";
|
||||
const response = await fetchHassioLogs(
|
||||
this.hass,
|
||||
this.provider,
|
||||
`entries=${this._firstCursor}:-100:100`,
|
||||
this._boot
|
||||
);
|
||||
|
||||
if (response.headers.has("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 {
|
||||
if (response.headers.has("X-First-Cursor")) {
|
||||
if (this._firstCursor === response.headers.get("X-First-Cursor")!) {
|
||||
this._loadingPrevState = "end";
|
||||
return;
|
||||
}
|
||||
this._firstCursor = response.headers.get("X-First-Cursor")!;
|
||||
}
|
||||
|
||||
if (scrolledToBottom) {
|
||||
this._scrollToBottom();
|
||||
} else if (this._loadingPrevState !== "end" && this._logElement) {
|
||||
window.requestAnimationFrame(() => {
|
||||
this._logElement!.scrollTop =
|
||||
this._logElement!.scrollHeight - scrollPositionFromBottom;
|
||||
});
|
||||
}
|
||||
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";
|
||||
}
|
||||
|
||||
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>) {
|
||||
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:
|
||||
this._showBootsSelect = !this._showBootsSelect;
|
||||
break;
|
||||
|
@@ -3,20 +3,20 @@ import type { CSSResultGroup, TemplateResult } from "lit";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import { extractSearchParam } from "../../../common/url/search-params";
|
||||
import "../../../components/ha-button-menu";
|
||||
import "../../../components/ha-button";
|
||||
import "../../../components/ha-button-menu";
|
||||
import "../../../components/search-input";
|
||||
import type { LogProvider } from "../../../data/error_log";
|
||||
import { fetchHassioAddonsInfo } from "../../../data/hassio/addon";
|
||||
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||
import "../../../layouts/hass-subpage";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import "./error-log-card";
|
||||
import "./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[] = [
|
||||
{
|
||||
@@ -57,6 +57,8 @@ export class HaConfigLogs extends LitElement {
|
||||
|
||||
@state() private _filter = extractSearchParam("filter") || "";
|
||||
|
||||
@state() private _detail = false;
|
||||
|
||||
@query("system-log-card") private systemLog?: SystemLogCard;
|
||||
|
||||
@state() private _selectedLogProvider = "core";
|
||||
@@ -141,7 +143,7 @@ export class HaConfigLogs extends LitElement {
|
||||
: ""}
|
||||
${search}
|
||||
<div class="content">
|
||||
${this._selectedLogProvider === "core"
|
||||
${this._selectedLogProvider === "core" && !this._detail
|
||||
? html`
|
||||
<system-log-card
|
||||
.hass=${this.hass}
|
||||
@@ -149,23 +151,28 @@ export class HaConfigLogs extends LitElement {
|
||||
(p) => p.key === this._selectedLogProvider
|
||||
)!.name}
|
||||
.filter=${this._filter}
|
||||
@switch-log-view=${this._showDetail}
|
||||
></system-log-card>
|
||||
`
|
||||
: ""}
|
||||
<error-log-card
|
||||
.hass=${this.hass}
|
||||
.header=${this._logProviders.find(
|
||||
(p) => p.key === this._selectedLogProvider
|
||||
)!.name}
|
||||
.filter=${this._filter}
|
||||
.provider=${this._selectedLogProvider}
|
||||
.show=${this._selectedLogProvider !== "core"}
|
||||
></error-log-card>
|
||||
: html`<error-log-card
|
||||
.hass=${this.hass}
|
||||
.header=${this._logProviders.find(
|
||||
(p) => p.key === this._selectedLogProvider
|
||||
)!.name}
|
||||
.filter=${this._filter}
|
||||
.provider=${this._selectedLogProvider}
|
||||
@switch-log-view=${this._showDetail}
|
||||
allow-switch
|
||||
></error-log-card>`}
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
private _showDetail() {
|
||||
this._detail = !this._detail;
|
||||
}
|
||||
|
||||
private _selectProvider(ev) {
|
||||
this._selectedLogProvider = (ev.currentTarget as any).provider;
|
||||
this._filter = "";
|
||||
|
@@ -1,16 +1,20 @@
|
||||
import { mdiRefresh } from "@mdi/js";
|
||||
import "@material/mwc-list/mwc-list";
|
||||
import { mdiDotsVertical, mdiDownload, mdiRefresh, mdiText } from "@mdi/js";
|
||||
import type { CSSResultGroup } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import type { LocalizeFunc } from "../../../common/translations/localize";
|
||||
import "../../../components/buttons/ha-call-service-button";
|
||||
import "../../../components/buttons/ha-progress-button";
|
||||
import "../../../components/ha-button-menu";
|
||||
import "../../../components/ha-card";
|
||||
import "../../../components/ha-circular-progress";
|
||||
import "../../../components/ha-icon-button";
|
||||
import "../../../components/ha-list-item";
|
||||
import { getSignedPath } from "../../../data/auth";
|
||||
import { getErrorLogDownloadUrl } from "../../../data/error_log";
|
||||
import { domainToName } from "../../../data/integration";
|
||||
import type { LoggedError } from "../../../data/system_log";
|
||||
import {
|
||||
@@ -19,6 +23,7 @@ import {
|
||||
isCustomIntegrationError,
|
||||
} from "../../../data/system_log";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { fileDownload } from "../../../util/file_download";
|
||||
import { showSystemLogDetailDialog } from "./show-dialog-system-log-detail";
|
||||
import { formatSystemLogTime } from "./util";
|
||||
|
||||
@@ -104,11 +109,34 @@ export class SystemLogCard extends LitElement {
|
||||
: html`
|
||||
<div class="header">
|
||||
<h1 class="card-header">${this.header || "Logs"}</h1>
|
||||
<ha-icon-button
|
||||
.path=${mdiRefresh}
|
||||
@click=${this.fetchData}
|
||||
.label=${this.hass.localize("ui.common.refresh")}
|
||||
></ha-icon-button>
|
||||
<div class="header-buttons">
|
||||
<ha-icon-button
|
||||
.path=${mdiDownload}
|
||||
@click=${this._downloadLogs}
|
||||
.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>
|
||||
${this._items.length === 0
|
||||
? 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 {
|
||||
const item = (ev.currentTarget as any).logItem;
|
||||
showSystemLogDetailDialog(this, { item });
|
||||
@@ -203,7 +244,7 @@ export class SystemLogCard extends LitElement {
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
ha-card {
|
||||
padding-top: 16px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -212,6 +253,11 @@ export class SystemLogCard extends LitElement {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.header-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
color: var(--ha-card-header-color, var(--primary-text-color));
|
||||
font-family: var(--ha-card-header-font-family, inherit);
|
||||
@@ -243,6 +289,10 @@ export class SystemLogCard extends LitElement {
|
||||
color: var(--warning-color);
|
||||
}
|
||||
|
||||
.card-content {
|
||||
border-top: 1px solid var(--divider-color);
|
||||
}
|
||||
|
||||
.card-actions,
|
||||
.empty-content {
|
||||
direction: var(--direction);
|
||||
|
@@ -31,7 +31,7 @@ export class HuiRecoveryModeCard extends LitElement implements LovelaceCard {
|
||||
"ui.panel.lovelace.cards.recovery-mode.description"
|
||||
)}
|
||||
</div>
|
||||
<error-log-card .hass=${this.hass}></error-log-card>
|
||||
<error-log-card .hass=${this.hass} provider="core"></error-log-card>
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@ class HuiViewContainer extends LitElement {
|
||||
|
||||
private _isFixedBackground(background?: BackgroundConfig) {
|
||||
if (typeof background === "string") {
|
||||
return background.includes(" fixed");
|
||||
return background.split(" ").includes("fixed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ class HuiViewContainer extends LitElement {
|
||||
);
|
||||
background-attachment: scroll !important;
|
||||
}
|
||||
:host(:not(fixed-background)) {
|
||||
:host(:not([fixed-background])) {
|
||||
background: var(
|
||||
--view-background,
|
||||
var(--lovelace-background, var(--primary-background-color))
|
||||
|
@@ -1,10 +1,11 @@
|
||||
import type Sortable from "sortablejs";
|
||||
import SortableCore, {
|
||||
OnSpill,
|
||||
AutoScroll,
|
||||
OnSpill,
|
||||
} from "sortablejs/modular/sortable.core.esm";
|
||||
|
||||
SortableCore.mount(OnSpill, new AutoScroll());
|
||||
SortableCore.mount(OnSpill);
|
||||
SortableCore.mount(new AutoScroll());
|
||||
|
||||
export default SortableCore as typeof Sortable;
|
||||
|
||||
|
@@ -158,6 +158,7 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
||||
},
|
||||
callApi: async (method, path, parameters, headers) =>
|
||||
hassCallApi(auth, method, path, parameters, headers),
|
||||
// callApiRaw introduced in 2024.11
|
||||
callApiRaw: async (method, path, parameters, headers, signal) =>
|
||||
hassCallApiRaw(auth, method, path, parameters, headers, signal),
|
||||
fetchWithAuth: (
|
||||
|
@@ -2470,9 +2470,9 @@
|
||||
"search": "Search logs",
|
||||
"failed_get_logs": "Failed to get {provider} logs, {error}",
|
||||
"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",
|
||||
"loading_log": "Loading full log…",
|
||||
"loading_log": "Loading log…",
|
||||
"no_errors": "No errors have been reported",
|
||||
"no_issues": "There are no new issues!",
|
||||
"clear": "Clear",
|
||||
@@ -2489,7 +2489,8 @@
|
||||
},
|
||||
"custom_integration": "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",
|
||||
"lines": "Lines",
|
||||
"download_logs": "Download logs",
|
||||
@@ -4841,7 +4842,6 @@
|
||||
"node_id": "ID",
|
||||
"node_ready": "Ready",
|
||||
"device_config": "Configure",
|
||||
"installer_settings": "Installer settings",
|
||||
"reinterview_device": "Re-interview",
|
||||
"rebuild_routes": "Rebuild routes",
|
||||
"remove_failed": "Remove failed",
|
||||
@@ -5133,45 +5133,6 @@
|
||||
"subscribed_to_logs": "Subscribed to Z-Wave JS log messages…",
|
||||
"log_level_changed": "Log Level changed to: {level}",
|
||||
"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": {
|
||||
|
@@ -259,7 +259,7 @@ export interface HomeAssistant {
|
||||
parameters?: Record<string, any>,
|
||||
headers?: Record<string, string>
|
||||
): Promise<T>;
|
||||
callApiRaw(
|
||||
callApiRaw( // introduced in 2024.11
|
||||
method: "GET" | "POST" | "PUT" | "DELETE",
|
||||
path: string,
|
||||
parameters?: Record<string, any>,
|
||||
|
186
yarn.lock
186
yarn.lock
@@ -1413,150 +1413,150 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/ecma402-abstract@npm:2.2.3":
|
||||
version: 2.2.3
|
||||
resolution: "@formatjs/ecma402-abstract@npm:2.2.3"
|
||||
"@formatjs/ecma402-abstract@npm:2.2.1":
|
||||
version: 2.2.1
|
||||
resolution: "@formatjs/ecma402-abstract@npm:2.2.1"
|
||||
dependencies:
|
||||
"@formatjs/fast-memoize": "npm:2.2.3"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
||||
"@formatjs/fast-memoize": "npm:2.2.2"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/d39e9f0d36c296a635f52aa35e07a67b6aa90383a30a046a0508e5d730676399fd0e67188eff463fe2a4d5febc9f567af45788fdf881e070910be7eb9294dd8c
|
||||
checksum: 10/8c281e14cb5f12b8697225be6b0ac13d057911e257d3c23928aad985b535df90b7bb2a235aab22753a6e57aef98f00b826514fc3703e69018ccc98c8d9848f38
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/fast-memoize@npm:2.2.3":
|
||||
version: 2.2.3
|
||||
resolution: "@formatjs/fast-memoize@npm:2.2.3"
|
||||
"@formatjs/fast-memoize@npm:2.2.2":
|
||||
version: 2.2.2
|
||||
resolution: "@formatjs/fast-memoize@npm:2.2.2"
|
||||
dependencies:
|
||||
tslib: "npm:2"
|
||||
checksum: 10/a9634acb5e03d051e09881eea5484ab02271f7d6b5f96ae9485674ab3c359aa881bc45fc07a1181ae4b2d6e288dadc169f578d142d698913ebbefa373014cac2
|
||||
checksum: 10/c6e958753eb41bb0875734762a44126a0d570706a31b32bb409e759cd372184c28e294b02fce0b0f0999c171ef717d513eaf7936862c498d78428b97db446ff8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/icu-messageformat-parser@npm:2.9.3":
|
||||
version: 2.9.3
|
||||
resolution: "@formatjs/icu-messageformat-parser@npm:2.9.3"
|
||||
"@formatjs/icu-messageformat-parser@npm:2.9.1":
|
||||
version: 2.9.1
|
||||
resolution: "@formatjs/icu-messageformat-parser@npm:2.9.1"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/icu-skeleton-parser": "npm:1.8.7"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
"@formatjs/icu-skeleton-parser": "npm:1.8.5"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/b24a3db43e4bf612107e981d5b40c077543d2266a08aac5cf01d5f65bf60527d5d16795e2e30063cb180b1d36d401944cd2ffb3a19d79b0cd28fa59751d19b7c
|
||||
checksum: 10/f52c7c55b1dfc141910089a0494abd98d1c13c0a359cfb3bfa0668a5e2015c0c579bf161978fdb3ab40fa9a7374a37ac062f8710ed285429bf60abde4a5d1183
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/icu-skeleton-parser@npm:1.8.7":
|
||||
version: 1.8.7
|
||||
resolution: "@formatjs/icu-skeleton-parser@npm:1.8.7"
|
||||
"@formatjs/icu-skeleton-parser@npm:1.8.5":
|
||||
version: 1.8.5
|
||||
resolution: "@formatjs/icu-skeleton-parser@npm:1.8.5"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/1a39815e5048f3c12a8d6a5b553271437b62e302724fc15c3b6967dc3e24823fcd9b8d3231a064991e163c147e54e588c571a092d557e93e78e738d218c6ef43
|
||||
checksum: 10/5b9c57f80b751483bef8897ff9607a9eb215fd7a8d8ae9fa5c631edf6d16fa4532c853395f20b7f3f38d6d4d1a35b98cd06421291203c7ad333f52077ef2a406
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-datetimeformat@npm:6.16.3":
|
||||
version: 6.16.3
|
||||
resolution: "@formatjs/intl-datetimeformat@npm:6.16.3"
|
||||
"@formatjs/intl-datetimeformat@npm:6.16.1":
|
||||
version: 6.16.1
|
||||
resolution: "@formatjs/intl-datetimeformat@npm:6.16.1"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/4e213611b92eda40aa6053b9458be71fb752f020616bb0e93fc681efc4fc408dfec408ae33ded8678887730f8ee766568f90b6ca57de6e9d8f1de45dda794f08
|
||||
checksum: 10/494868322d396e0eede6a27c16047858944f42fd3b45cf5d155f963df62e694b842ac0bef07e23aa73fa55cf143956d642d05ea62a3e762632101451975b5fc4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-displaynames@npm:6.8.3":
|
||||
version: 6.8.3
|
||||
resolution: "@formatjs/intl-displaynames@npm:6.8.3"
|
||||
"@formatjs/intl-displaynames@npm:6.8.1":
|
||||
version: 6.8.1
|
||||
resolution: "@formatjs/intl-displaynames@npm:6.8.1"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/46c8d6e6d6d56d5f495c0bfb5784687a0af1ffd9eaeb72c1d9db8e21f8c7eeec346198871f8fe39f6eebfb19d6c3e46cbf92e213e6a6f0dfdb2f55fe96d43bcc
|
||||
checksum: 10/627fc625e14b4d1bea5b2bf41e40050eb9775d0f66780e155719e21c062f9b3331d08b488ebcd3608c60999498af5a39e67cb5fd2a6d54a0e7395d7a63bfe643
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-enumerator@npm:1.8.3":
|
||||
version: 1.8.3
|
||||
resolution: "@formatjs/intl-enumerator@npm:1.8.3"
|
||||
"@formatjs/intl-enumerator@npm:1.8.1":
|
||||
version: 1.8.1
|
||||
resolution: "@formatjs/intl-enumerator@npm:1.8.1"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/a51ed7e15835cc1612282de46139d0f49553f004439a728a9118d1b9b15a3d05916e8aad4001e18c4909a3d4287fc07c921540c5ba8f32499f3243ac50d68a42
|
||||
checksum: 10/0e4250de905e757fb88d6ff072968c72ed3a39de8ddaed73c38c0099825f11530c9b8e224573ae6e46cf49f1318e463f40ba2cdfa25cb7415382ba952b570bdc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-getcanonicallocales@npm:2.5.2":
|
||||
version: 2.5.2
|
||||
resolution: "@formatjs/intl-getcanonicallocales@npm:2.5.2"
|
||||
"@formatjs/intl-getcanonicallocales@npm:2.5.1":
|
||||
version: 2.5.1
|
||||
resolution: "@formatjs/intl-getcanonicallocales@npm:2.5.1"
|
||||
dependencies:
|
||||
tslib: "npm:2"
|
||||
checksum: 10/0d1738181911635d91d4a788d663fadd1aa045f40f0f05ac8b04adc06cd4f5ee3c50aa7c3a50c63ba7572f23e336720340c8240d6070d899e56adf25d0388f1b
|
||||
checksum: 10/5e83c0b3574333e5027c3c4f74ea20800e50e36fb8efa69361457b57f618738f478b5d22777ba30a2b7a15bdff60101d8119169c909b33577244747d52e59614
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-listformat@npm:7.7.3":
|
||||
version: 7.7.3
|
||||
resolution: "@formatjs/intl-listformat@npm:7.7.3"
|
||||
"@formatjs/intl-listformat@npm:7.7.1":
|
||||
version: 7.7.1
|
||||
resolution: "@formatjs/intl-listformat@npm:7.7.1"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/52ae02202a2bb0d8c16ea9a8f142d616e6ecb8400aa96ca618896cf529a3e3f5d88d64cb2644ad6a4ba7e17ee013d8fb3463419802afab5ca25afa51151ab62c
|
||||
checksum: 10/a64581f1d2e8e0c0c83c5d56334a3e3786ed251e1a882d7610d2588d8602eacb32c9167032891e2796c30df3437c9ce52c7284786dca6f1f44250301060169ea
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-locale@npm:4.2.3":
|
||||
version: 4.2.3
|
||||
resolution: "@formatjs/intl-locale@npm:4.2.3"
|
||||
"@formatjs/intl-locale@npm:4.2.1":
|
||||
version: 4.2.1
|
||||
resolution: "@formatjs/intl-locale@npm:4.2.1"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/intl-enumerator": "npm:1.8.3"
|
||||
"@formatjs/intl-getcanonicallocales": "npm:2.5.2"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
"@formatjs/intl-enumerator": "npm:1.8.1"
|
||||
"@formatjs/intl-getcanonicallocales": "npm:2.5.1"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/dab4090653e62f1c3453c074c3047d0e22ee6a3d33ac00afa45f1541b8686b453c671755e8faeeb1253b61131071c02506b56c094941efd6195d40163007182e
|
||||
checksum: 10/4cba0fbeded2c7c5806528806f176cb833c43765bf1717470f4e001ab42581d5f0b52bf1893afef9597fba96dc3d4659507e490030f231523d460ec6686b9562
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-localematcher@npm:0.5.7":
|
||||
version: 0.5.7
|
||||
resolution: "@formatjs/intl-localematcher@npm:0.5.7"
|
||||
"@formatjs/intl-localematcher@npm:0.5.6":
|
||||
version: 0.5.6
|
||||
resolution: "@formatjs/intl-localematcher@npm:0.5.6"
|
||||
dependencies:
|
||||
tslib: "npm:2"
|
||||
checksum: 10/52201f12212e7e9cba1a4f99020da587b13e44e06e03c4ccd4e5ac0829b411e73dfe0904a9039ef81eeabeea04ed8cfae9e727e6791acd0230745b7bd3ad059e
|
||||
checksum: 10/14eac6bb25dcfeedd7960f44dec5a137999729da00b294ddf1133abe760ced4342f37734bc750b4c47f8dd8d5633a7da38d274503f80d7e965bb1f6fb6f2988c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-numberformat@npm:8.14.3":
|
||||
version: 8.14.3
|
||||
resolution: "@formatjs/intl-numberformat@npm:8.14.3"
|
||||
"@formatjs/intl-numberformat@npm:8.14.1":
|
||||
version: 8.14.1
|
||||
resolution: "@formatjs/intl-numberformat@npm:8.14.1"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/7a4e52ace65589ceb441032a09b88616e71ba4220605e498b1a064f43672cad5cca8c98b72446ffd7d57ef098c658c245c08a16623e0b1bc10940ff7e71069c7
|
||||
checksum: 10/51152d1b9607a35c64e6089e44b90c7ec90be3b1925ba47ffc559ddb4fd72afae76e83af3d436831ea0fc47dc0e9fee9cd3d576280440f2dce03cb6bd24e0bed
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-pluralrules@npm:5.3.3":
|
||||
version: 5.3.3
|
||||
resolution: "@formatjs/intl-pluralrules@npm:5.3.3"
|
||||
"@formatjs/intl-pluralrules@npm:5.3.1":
|
||||
version: 5.3.1
|
||||
resolution: "@formatjs/intl-pluralrules@npm:5.3.1"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/3679c63aa2b9dde474572998b829ecb5d134f1efe508e1e5a06089480bbff9f2216235a7d5745c434030dc17c8a83385f0639a71a22f1d648fcbc6fff90f57e3
|
||||
checksum: 10/fc83c3547a9f0af6331c2970f265234fde967848ff738730f2e87ce816636d8778ead1185f5ecccc692cb8b63c11412dc85deac9d3425f44fe3a6a6c30c8b776
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/intl-relativetimeformat@npm:11.4.3":
|
||||
version: 11.4.3
|
||||
resolution: "@formatjs/intl-relativetimeformat@npm:11.4.3"
|
||||
"@formatjs/intl-relativetimeformat@npm:11.4.1":
|
||||
version: 11.4.1
|
||||
resolution: "@formatjs/intl-relativetimeformat@npm:11.4.1"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.7"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
"@formatjs/intl-localematcher": "npm:0.5.6"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/7c7548ba133031873683a37566d646e4e3f50ea979773de199b41769df23648be2b44b53975809bd53f97a95d1d44038c0a09b1c031e05f0de6f7bba843b1aad
|
||||
checksum: 10/80817403301baed257fbd8c793b9ed077a2e6dd0414a6895b5bfde3619aebc818f30535da9b560a6186fac783cf09561c495d2c6568a980bd635736194655af5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8759,14 +8759,14 @@ __metadata:
|
||||
"@codemirror/state": "npm:6.4.1"
|
||||
"@codemirror/view": "npm:6.34.1"
|
||||
"@egjs/hammerjs": "npm:2.0.17"
|
||||
"@formatjs/intl-datetimeformat": "npm:6.16.3"
|
||||
"@formatjs/intl-displaynames": "npm:6.8.3"
|
||||
"@formatjs/intl-getcanonicallocales": "npm:2.5.2"
|
||||
"@formatjs/intl-listformat": "npm:7.7.3"
|
||||
"@formatjs/intl-locale": "npm:4.2.3"
|
||||
"@formatjs/intl-numberformat": "npm:8.14.3"
|
||||
"@formatjs/intl-pluralrules": "npm:5.3.3"
|
||||
"@formatjs/intl-relativetimeformat": "npm:11.4.3"
|
||||
"@formatjs/intl-datetimeformat": "npm:6.16.1"
|
||||
"@formatjs/intl-displaynames": "npm:6.8.1"
|
||||
"@formatjs/intl-getcanonicallocales": "npm:2.5.1"
|
||||
"@formatjs/intl-listformat": "npm:7.7.1"
|
||||
"@formatjs/intl-locale": "npm:4.2.1"
|
||||
"@formatjs/intl-numberformat": "npm:8.14.1"
|
||||
"@formatjs/intl-pluralrules": "npm:5.3.1"
|
||||
"@formatjs/intl-relativetimeformat": "npm:11.4.1"
|
||||
"@fullcalendar/core": "npm:6.1.15"
|
||||
"@fullcalendar/daygrid": "npm:6.1.15"
|
||||
"@fullcalendar/interaction": "npm:6.1.15"
|
||||
@@ -8898,7 +8898,7 @@ __metadata:
|
||||
husky: "npm:9.1.6"
|
||||
idb-keyval: "npm:6.2.1"
|
||||
instant-mocha: "npm:1.5.3"
|
||||
intl-messageformat: "npm:10.7.5"
|
||||
intl-messageformat: "npm:10.7.3"
|
||||
js-yaml: "npm:4.1.0"
|
||||
jszip: "npm:3.10.1"
|
||||
leaflet: "npm:1.9.4"
|
||||
@@ -9348,15 +9348,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"intl-messageformat@npm:10.7.5":
|
||||
version: 10.7.5
|
||||
resolution: "intl-messageformat@npm:10.7.5"
|
||||
"intl-messageformat@npm:10.7.3":
|
||||
version: 10.7.3
|
||||
resolution: "intl-messageformat@npm:10.7.3"
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.3"
|
||||
"@formatjs/fast-memoize": "npm:2.2.3"
|
||||
"@formatjs/icu-messageformat-parser": "npm:2.9.3"
|
||||
"@formatjs/ecma402-abstract": "npm:2.2.1"
|
||||
"@formatjs/fast-memoize": "npm:2.2.2"
|
||||
"@formatjs/icu-messageformat-parser": "npm:2.9.1"
|
||||
tslib: "npm:2"
|
||||
checksum: 10/8880448d62bd0260eafd4ee7ccfabaea573476f28e6d6bf47e027ee9c1d46d4919a076df7abedaf282422ff80ade02b5c637c69cdf739ee405e4837098bac37e
|
||||
checksum: 10/e387f7f37a295d9d386af0c6392ba135a4580e86177161f1f400d470fed1f8c7b3cb6c724cbc2f50a7ded2e20f202977d8bf5e2bbc626f72016a5b5b6752b76d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
Reference in New Issue
Block a user