mirror of
https://github.com/home-assistant/frontend.git
synced 2026-06-18 14:21:59 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 439e103aef |
+325
-325
File diff suppressed because one or more lines are too long
+1
-1
@@ -13,4 +13,4 @@ nodeLinker: node-modules
|
||||
|
||||
npmMinimalAgeGate: 3d
|
||||
|
||||
yarnPath: .yarn/releases/yarn-4.17.0.cjs
|
||||
yarnPath: .yarn/releases/yarn-4.16.0.cjs
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ContextProvider } from "@lit/context";
|
||||
import type { PropertyValues, TemplateResult } from "lit";
|
||||
import type { TemplateResult } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
||||
@@ -15,11 +14,6 @@ import "../../../../src/components/ha-selector/ha-selector";
|
||||
import "../../../../src/components/ha-settings-row";
|
||||
import type { AreaRegistryEntry } from "../../../../src/data/area/area_registry";
|
||||
import type { BlueprintInput } from "../../../../src/data/blueprint";
|
||||
import {
|
||||
configContext,
|
||||
internationalizationContext,
|
||||
} from "../../../../src/data/context";
|
||||
import { updateHassGroups } from "../../../../src/data/context/updateContext";
|
||||
import type { DeviceRegistryEntry } from "../../../../src/data/device/device_registry";
|
||||
import type { FloorRegistryEntry } from "../../../../src/data/floor_registry";
|
||||
import type { LabelRegistryEntry } from "../../../../src/data/label/label_registry";
|
||||
@@ -524,17 +518,6 @@ class DemoHaSelector extends LitElement implements ProvideHassElement {
|
||||
|
||||
private data = SCHEMAS.map(() => ({}));
|
||||
|
||||
// The date/datetime selectors and the date-picker dialog consume these
|
||||
// contexts (provided by the root element in the real app). Provide them here
|
||||
// so they work in the gallery.
|
||||
private _i18nProvider = new ContextProvider(this, {
|
||||
context: internationalizationContext,
|
||||
});
|
||||
|
||||
private _configProvider = new ContextProvider(this, {
|
||||
context: configContext,
|
||||
});
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const hass = provideHass(this);
|
||||
@@ -556,16 +539,6 @@ class DemoHaSelector extends LitElement implements ProvideHassElement {
|
||||
el.hass = this.hass;
|
||||
}
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
super.willUpdate(changedProps);
|
||||
if (changedProps.has("hass") && this.hass) {
|
||||
this._i18nProvider.setValue(
|
||||
updateHassGroups.internationalization(this.hass)
|
||||
);
|
||||
this._configProvider.setValue(updateHassGroups.config(this.hass));
|
||||
}
|
||||
}
|
||||
|
||||
public connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.addEventListener("show-dialog", this._dialogManager);
|
||||
|
||||
+3
-3
@@ -154,7 +154,7 @@
|
||||
"@types/qrcode": "1.5.6",
|
||||
"@types/sortablejs": "1.15.9",
|
||||
"@types/tar": "7.0.87",
|
||||
"@vitest/coverage-v8": "4.1.9",
|
||||
"@vitest/coverage-v8": "4.1.8",
|
||||
"babel-loader": "10.1.1",
|
||||
"babel-plugin-template-html-minifier": "4.1.0",
|
||||
"browserslist-useragent-regexp": "4.1.4",
|
||||
@@ -197,7 +197,7 @@
|
||||
"typescript": "6.0.3",
|
||||
"typescript-eslint": "8.61.0",
|
||||
"vite-tsconfig-paths": "6.1.1",
|
||||
"vitest": "4.1.9",
|
||||
"vitest": "4.1.8",
|
||||
"webpack-stats-plugin": "1.1.3",
|
||||
"webpackbar": "7.0.0",
|
||||
"workbox-build": "patch:workbox-build@npm%3A7.4.1#~/.yarn/patches/workbox-build-npm-7.4.1-c84561662c.patch"
|
||||
@@ -213,7 +213,7 @@
|
||||
"@material/mwc-list@^0.27.0": "patch:@material/mwc-list@npm%3A0.27.0#~/.yarn/patches/@material-mwc-list-npm-0.27.0-5344fc9de4.patch",
|
||||
"glob@^10.2.2": "^10.5.0"
|
||||
},
|
||||
"packageManager": "yarn@4.17.0",
|
||||
"packageManager": "yarn@4.16.0",
|
||||
"volta": {
|
||||
"node": "24.17.0"
|
||||
}
|
||||
|
||||
@@ -86,10 +86,7 @@ export class HaDateTimeSelector extends LitElement {
|
||||
static styles = css`
|
||||
.input {
|
||||
display: flex;
|
||||
/* Align the input fields by their top edge so the date field's underline
|
||||
lines up with the time field, since ha-date-input reserves extra space
|
||||
below for its hint while ha-time-input does not. */
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { consumeEntityState } from "../../common/decorators/consume-context-entry";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import "../ha-state-icon";
|
||||
|
||||
@customElement("ha-entity-marker")
|
||||
class HaEntityMarker extends LitElement {
|
||||
@property({ attribute: "entity-id", reflect: true }) public entityId?: string;
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state()
|
||||
@consumeEntityState({ entityIdPath: ["entityId"] })
|
||||
private _stateObj?: HassEntity;
|
||||
@property({ attribute: "entity-id", reflect: true }) public entityId?: string;
|
||||
|
||||
@property({ attribute: "entity-name" }) public entityName?: string;
|
||||
|
||||
@@ -39,7 +36,9 @@ class HaEntityMarker extends LitElement {
|
||||
})}
|
||||
></div>`
|
||||
: this.showIcon && this.entityId
|
||||
? html`<ha-state-icon .stateObj=${this._stateObj}></ha-state-icon>`
|
||||
? html`<ha-state-icon
|
||||
.stateObj=${this.hass?.states[this.entityId]}
|
||||
></ha-state-icon>`
|
||||
: !this.entityUnit
|
||||
? this.entityName
|
||||
: html`
|
||||
|
||||
@@ -128,6 +128,7 @@ export class HaLocationsEditor extends LitElement {
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<ha-map
|
||||
.hass=${this.hass}
|
||||
.layers=${this._getLayers(this._circles, this._locationMarkers)}
|
||||
.zoom=${this.zoom}
|
||||
.autoFit=${this.autoFit}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { consume } from "@lit/context";
|
||||
import { isToday } from "date-fns";
|
||||
import type { HassConfig, HassEntities } from "home-assistant-js-websocket";
|
||||
import type {
|
||||
Circle,
|
||||
CircleMarker,
|
||||
@@ -20,7 +18,6 @@ import {
|
||||
formatTimeWeekday,
|
||||
formatTimeWithSeconds,
|
||||
} from "../../common/datetime/format_time";
|
||||
import { transform } from "../../common/decorators/transform";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import type { LeafletModuleType } from "../../common/dom/setup-leaflet-map";
|
||||
import { setupLeafletMap } from "../../common/dom/setup-leaflet-map";
|
||||
@@ -29,22 +26,7 @@ import { computeStateName } from "../../common/entity/compute_state_name";
|
||||
import { getEntityLocation } from "../../common/entity/get_entity_location";
|
||||
import { DecoratedMarker } from "../../common/map/decorated_marker";
|
||||
import { filterXSS } from "../../common/util/xss";
|
||||
import {
|
||||
configContext,
|
||||
connectionContext,
|
||||
formattersContext,
|
||||
internationalizationContext,
|
||||
statesContext,
|
||||
uiContext,
|
||||
} from "../../data/context";
|
||||
import type {
|
||||
HomeAssistantConfig,
|
||||
HomeAssistantConnection,
|
||||
HomeAssistantFormatters,
|
||||
HomeAssistantInternationalization,
|
||||
HomeAssistantUI,
|
||||
ThemeMode,
|
||||
} from "../../types";
|
||||
import type { HomeAssistant, ThemeMode } from "../../types";
|
||||
import { isTouch } from "../../util/is_touch";
|
||||
import "../ha-icon-button";
|
||||
import "./ha-entity-marker";
|
||||
@@ -94,32 +76,7 @@ export interface HaMapEntity {
|
||||
|
||||
@customElement("ha-map")
|
||||
export class HaMap extends ReactiveElement {
|
||||
@state()
|
||||
@consume({ context: statesContext, subscribe: true })
|
||||
private _states!: HassEntities;
|
||||
|
||||
@state()
|
||||
@consume({ context: configContext, subscribe: true })
|
||||
@transform<HomeAssistantConfig, HassConfig>({
|
||||
transformer: ({ config }) => config,
|
||||
})
|
||||
private _config!: HassConfig;
|
||||
|
||||
@state()
|
||||
@consume({ context: uiContext, subscribe: true })
|
||||
private _ui!: HomeAssistantUI;
|
||||
|
||||
@state()
|
||||
@consume({ context: internationalizationContext, subscribe: true })
|
||||
private _i18n!: HomeAssistantInternationalization;
|
||||
|
||||
@state()
|
||||
@consume({ context: formattersContext, subscribe: true })
|
||||
private _formatters!: HomeAssistantFormatters;
|
||||
|
||||
@state()
|
||||
@consume({ context: connectionContext, subscribe: true })
|
||||
private _connection!: HomeAssistantConnection;
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public entities?: string[] | HaMapEntity[];
|
||||
|
||||
@@ -218,16 +175,17 @@ export class HaMap extends ReactiveElement {
|
||||
return;
|
||||
}
|
||||
let autoFitRequired = false;
|
||||
const oldStates = changedProps.get("_states") as HassEntities | undefined;
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
|
||||
if (changedProps.has("_loaded") || changedProps.has("entities")) {
|
||||
this._drawEntities();
|
||||
autoFitRequired = !this._pauseAutoFit;
|
||||
} else if (this._loaded && oldStates && this.entities) {
|
||||
} else if (this._loaded && oldHass && this.entities) {
|
||||
// Check if any state has changed
|
||||
for (const entity of this.entities) {
|
||||
if (
|
||||
oldStates[getEntityId(entity)] !== this._states[getEntityId(entity)]
|
||||
oldHass.states[getEntityId(entity)] !==
|
||||
this.hass!.states[getEntityId(entity)]
|
||||
) {
|
||||
this._drawEntities();
|
||||
autoFitRequired = !this._pauseAutoFit;
|
||||
@@ -261,11 +219,10 @@ export class HaMap extends ReactiveElement {
|
||||
}, PROGRAMMITIC_FIT_DELAY);
|
||||
}
|
||||
|
||||
const oldUi = changedProps.get("_ui") as HomeAssistantUI | undefined;
|
||||
if (
|
||||
!changedProps.has("themeMode") &&
|
||||
(!changedProps.has("_ui") ||
|
||||
(oldUi && oldUi.themes?.darkMode === this._ui.themes?.darkMode))
|
||||
(!changedProps.has("hass") ||
|
||||
(oldHass && oldHass.themes?.darkMode === this.hass.themes?.darkMode))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -276,7 +233,7 @@ export class HaMap extends ReactiveElement {
|
||||
private get _darkMode() {
|
||||
return (
|
||||
this.themeMode === "dark" ||
|
||||
(this.themeMode === "auto" && Boolean(this._ui?.themes.darkMode))
|
||||
(this.themeMode === "auto" && Boolean(this.hass.themes.darkMode))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -301,8 +258,8 @@ export class HaMap extends ReactiveElement {
|
||||
this._loading = true;
|
||||
try {
|
||||
[this.leafletMap, this.Leaflet] = await setupLeafletMap(map, {
|
||||
latitude: this._config?.latitude ?? 52.3731339,
|
||||
longitude: this._config?.longitude ?? 4.8903147,
|
||||
latitude: this.hass?.config.latitude ?? 52.3731339,
|
||||
longitude: this.hass?.config.longitude ?? 4.8903147,
|
||||
zoom: this.zoom,
|
||||
});
|
||||
this._updateMapStyle();
|
||||
@@ -343,7 +300,7 @@ export class HaMap extends ReactiveElement {
|
||||
if (options?.unpause_autofit) {
|
||||
this._pauseAutoFit = false;
|
||||
}
|
||||
if (!this.leafletMap || !this.Leaflet || !this._config) {
|
||||
if (!this.leafletMap || !this.Leaflet || !this.hass) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -354,7 +311,10 @@ export class HaMap extends ReactiveElement {
|
||||
) {
|
||||
this._isProgrammaticFit = true;
|
||||
this.leafletMap.setView(
|
||||
new this.Leaflet.LatLng(this._config.latitude, this._config.longitude),
|
||||
new this.Leaflet.LatLng(
|
||||
this.hass.config.latitude,
|
||||
this.hass.config.longitude
|
||||
),
|
||||
options?.zoom || this.zoom
|
||||
);
|
||||
setTimeout(() => {
|
||||
@@ -391,7 +351,7 @@ export class HaMap extends ReactiveElement {
|
||||
boundingbox: LatLngExpression[],
|
||||
options?: { zoom?: number; pad?: number }
|
||||
) {
|
||||
if (!this.leafletMap || !this.Leaflet) {
|
||||
if (!this.leafletMap || !this.Leaflet || !this.hass) {
|
||||
return;
|
||||
}
|
||||
const bounds = this.Leaflet.latLngBounds(boundingbox).pad(
|
||||
@@ -422,31 +382,32 @@ export class HaMap extends ReactiveElement {
|
||||
if (path.fullDatetime) {
|
||||
formattedTime = formatDateTime(
|
||||
point.timestamp,
|
||||
this._i18n.locale,
|
||||
this._config
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
);
|
||||
} else if (isToday(point.timestamp)) {
|
||||
formattedTime = formatTimeWithSeconds(
|
||||
point.timestamp,
|
||||
this._i18n.locale,
|
||||
this._config
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
);
|
||||
} else {
|
||||
formattedTime = formatTimeWeekday(
|
||||
point.timestamp,
|
||||
this._i18n.locale,
|
||||
this._config
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
);
|
||||
}
|
||||
return `${filterXSS(path.name ?? "")}<br>${formattedTime}`;
|
||||
}
|
||||
|
||||
private _drawPaths(): void {
|
||||
const hass = this.hass;
|
||||
const map = this.leafletMap;
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const Leaflet = this.Leaflet;
|
||||
|
||||
if (!this._i18n || !this._config || !map || !Leaflet) {
|
||||
if (!hass || !map || !Leaflet) {
|
||||
return;
|
||||
}
|
||||
if (this._mapPaths.length) {
|
||||
@@ -574,12 +535,12 @@ export class HaMap extends ReactiveElement {
|
||||
}
|
||||
|
||||
private _drawEntities(): void {
|
||||
const states = this._states;
|
||||
const hass = this.hass;
|
||||
const map = this.leafletMap;
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const Leaflet = this.Leaflet;
|
||||
|
||||
if (!states || !map || !Leaflet) {
|
||||
if (!hass || !map || !Leaflet) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -617,7 +578,7 @@ export class HaMap extends ReactiveElement {
|
||||
const className = this._darkMode ? "dark" : "light";
|
||||
|
||||
for (const entity of this.entities) {
|
||||
const stateObj = states[getEntityId(entity)];
|
||||
const stateObj = hass.states[getEntityId(entity)];
|
||||
if (!stateObj) {
|
||||
continue;
|
||||
}
|
||||
@@ -630,7 +591,7 @@ export class HaMap extends ReactiveElement {
|
||||
entity_picture: entityPicture,
|
||||
} = stateObj.attributes;
|
||||
|
||||
const location = getEntityLocation(stateObj, states);
|
||||
const location = getEntityLocation(stateObj, hass.states);
|
||||
if (!location) {
|
||||
continue;
|
||||
}
|
||||
@@ -687,14 +648,11 @@ export class HaMap extends ReactiveElement {
|
||||
// create icon
|
||||
const entityName =
|
||||
typeof entity !== "string" && entity.label_mode === "state"
|
||||
? this._formatters.formatEntityState(stateObj)
|
||||
? this.hass.formatEntityState(stateObj)
|
||||
: typeof entity !== "string" &&
|
||||
entity.label_mode === "attribute" &&
|
||||
entity.attribute !== undefined
|
||||
? this._formatters.formatEntityAttributeValue(
|
||||
stateObj,
|
||||
entity.attribute
|
||||
)
|
||||
? this.hass.formatEntityAttributeValue(stateObj, entity.attribute)
|
||||
: (customTitle ??
|
||||
title
|
||||
.split(" ")
|
||||
@@ -703,6 +661,7 @@ export class HaMap extends ReactiveElement {
|
||||
.substr(0, 3));
|
||||
|
||||
const entityMarker = document.createElement("ha-entity-marker");
|
||||
entityMarker.hass = this.hass;
|
||||
entityMarker.showIcon =
|
||||
typeof entity !== "string" && entity.label_mode === "icon";
|
||||
entityMarker.entityId = getEntityId(entity);
|
||||
@@ -715,7 +674,7 @@ export class HaMap extends ReactiveElement {
|
||||
: "";
|
||||
entityMarker.entityPicture =
|
||||
entityPicture && (typeof entity === "string" || !entity.label_mode)
|
||||
? this._connection.hassUrl(entityPicture)
|
||||
? this.hass.hassUrl(entityPicture)
|
||||
: "";
|
||||
if (typeof entity !== "string") {
|
||||
entityMarker.entityColor = entity.color;
|
||||
|
||||
+2
-2
@@ -39,7 +39,6 @@ import {
|
||||
mdiMicrophoneMessage,
|
||||
mdiMotionSensor,
|
||||
mdiPalette,
|
||||
mdiRadioTower,
|
||||
mdiRayVertex,
|
||||
mdiRemote,
|
||||
mdiRobot,
|
||||
@@ -53,6 +52,7 @@ import {
|
||||
mdiThermostat,
|
||||
mdiTimerOutline,
|
||||
mdiToggleSwitch,
|
||||
mdiVideoInputAntenna,
|
||||
mdiWater,
|
||||
mdiWaterPercent,
|
||||
mdiWeatherPartlyCloudy,
|
||||
@@ -129,7 +129,7 @@ export const FALLBACK_DOMAIN_ICONS = {
|
||||
plant: mdiFlower,
|
||||
power: mdiFlash,
|
||||
proximity: mdiAppleSafari,
|
||||
radio_frequency: mdiRadioTower,
|
||||
radio_frequency: mdiVideoInputAntenna,
|
||||
remote: mdiRemote,
|
||||
scene: mdiPalette,
|
||||
schedule: mdiCalendarClock,
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import type { HomeAssistant } from "../types";
|
||||
|
||||
export const DOMAIN = "radio_frequency";
|
||||
|
||||
export interface RadioFrequencyTransmitter {
|
||||
entity_id: string;
|
||||
device_id: string | null;
|
||||
config_entry_id: string | null;
|
||||
supported_frequency_ranges: [number, number][];
|
||||
supported_modulations: string[];
|
||||
}
|
||||
|
||||
interface RadioFrequencyTransmitterList {
|
||||
transmitters: RadioFrequencyTransmitter[];
|
||||
}
|
||||
|
||||
export const fetchRadioFrequencyTransmitters = (
|
||||
hass: HomeAssistant
|
||||
): Promise<RadioFrequencyTransmitterList> =>
|
||||
hass.callWS({
|
||||
type: "radio_frequency/list",
|
||||
});
|
||||
+10
-12
@@ -38,9 +38,8 @@ import {
|
||||
} from "../common/const";
|
||||
import { supportsFeature } from "../common/entity/supports-feature";
|
||||
import { round } from "../common/number/round";
|
||||
import type { LocalizeFunc } from "../common/translations/localize";
|
||||
import "../components/ha-svg-icon";
|
||||
import type { HomeAssistant, HomeAssistantFormatters } from "../types";
|
||||
import type { HomeAssistant } from "../types";
|
||||
|
||||
export enum WeatherEntityFeature {
|
||||
FORECAST_DAILY = 1,
|
||||
@@ -221,20 +220,19 @@ const getWindBearing = (bearing: number | string): string => {
|
||||
};
|
||||
|
||||
export const getWind = (
|
||||
formatEntityAttributeValue: HomeAssistantFormatters["formatEntityAttributeValue"],
|
||||
localize: LocalizeFunc,
|
||||
hass: HomeAssistant,
|
||||
stateObj: WeatherEntity,
|
||||
speed?: number,
|
||||
bearing?: number | string
|
||||
): string => {
|
||||
const speedText =
|
||||
speed !== undefined && speed !== null
|
||||
? formatEntityAttributeValue(stateObj, "wind_speed", speed)
|
||||
? hass.formatEntityAttributeValue(stateObj, "wind_speed", speed)
|
||||
: "-";
|
||||
if (bearing !== undefined && bearing !== null) {
|
||||
const cardinalDirection = getWindBearing(bearing);
|
||||
return `${speedText} (${
|
||||
localize(
|
||||
hass.localize(
|
||||
`ui.card.weather.cardinal_direction.${cardinalDirection.toLowerCase()}`
|
||||
) || cardinalDirection
|
||||
})`;
|
||||
@@ -280,13 +278,13 @@ export const getWeatherUnit = (
|
||||
};
|
||||
|
||||
export const getSecondaryWeatherAttribute = (
|
||||
hass: Pick<HomeAssistant, "formatEntityAttributeValue" | "localize">,
|
||||
hass: HomeAssistant,
|
||||
stateObj: WeatherEntity,
|
||||
forecast: ForecastAttribute[],
|
||||
temperatureFractionDigits?: number
|
||||
): TemplateResult | undefined => {
|
||||
const extrema = getWeatherExtrema(
|
||||
hass.formatEntityAttributeValue,
|
||||
hass,
|
||||
stateObj,
|
||||
forecast,
|
||||
temperatureFractionDigits
|
||||
@@ -322,13 +320,13 @@ export const getSecondaryWeatherAttribute = (
|
||||
? html`
|
||||
<ha-svg-icon class="attr-icon" .path=${weatherAttrIcon}></ha-svg-icon>
|
||||
`
|
||||
: hass.localize(`ui.card.weather.attributes.${attribute}`)}
|
||||
: hass!.localize(`ui.card.weather.attributes.${attribute}`)}
|
||||
${hass.formatEntityAttributeValue(stateObj, attribute, roundedValue)}
|
||||
`;
|
||||
};
|
||||
|
||||
const getWeatherExtrema = (
|
||||
formatEntityAttributeValue: HomeAssistantFormatters["formatEntityAttributeValue"],
|
||||
hass: HomeAssistant,
|
||||
stateObj: WeatherEntity,
|
||||
forecast: ForecastAttribute[],
|
||||
temperatureFractionDigits?: number
|
||||
@@ -371,11 +369,11 @@ const getWeatherExtrema = (
|
||||
|
||||
return html`
|
||||
${tempHigh
|
||||
? formatEntityAttributeValue(stateObj, "temperature", tempHigh)
|
||||
? hass.formatEntityAttributeValue(stateObj, "temperature", tempHigh)
|
||||
: ""}
|
||||
${tempLow && tempHigh ? " / " : ""}
|
||||
${tempLow
|
||||
? formatEntityAttributeValue(stateObj, "temperature", tempLow)
|
||||
? hass.formatEntityAttributeValue(stateObj, "temperature", tempLow)
|
||||
: ""}
|
||||
`;
|
||||
};
|
||||
|
||||
@@ -1,46 +1,28 @@
|
||||
import { consume } from "@lit/context";
|
||||
import type { HassEntities, HassEntity } from "home-assistant-js-websocket";
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { consumeLocalize } from "../../../common/decorators/consume-context-entry";
|
||||
import { transform } from "../../../common/decorators/transform";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { getEntityLocation } from "../../../common/entity/get_entity_location";
|
||||
import type { LocalizeFunc } from "../../../common/translations/localize";
|
||||
import "../../../components/ha-button";
|
||||
import "../../../components/map/ha-map";
|
||||
import { configContext, statesContext } from "../../../data/context";
|
||||
import { showZoneEditor } from "../../../data/zone";
|
||||
import type { CurrentUser, HomeAssistantConfig } from "../../../types";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
|
||||
@customElement("more-info-person")
|
||||
class MoreInfoPerson extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public stateObj?: HassEntity;
|
||||
|
||||
@state()
|
||||
@consumeLocalize()
|
||||
private _localize!: LocalizeFunc;
|
||||
|
||||
@state()
|
||||
@consume({ context: statesContext, subscribe: true })
|
||||
private _states!: HassEntities;
|
||||
|
||||
@state()
|
||||
@consume({ context: configContext, subscribe: true })
|
||||
@transform<HomeAssistantConfig, CurrentUser | undefined>({
|
||||
transformer: ({ user }) => user,
|
||||
})
|
||||
private _user?: CurrentUser;
|
||||
|
||||
private _entityArray = memoizeOne((entityId: string) => [entityId]);
|
||||
|
||||
protected render() {
|
||||
if (!this._localize || !this.stateObj) {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const location = getEntityLocation(this.stateObj, this._states);
|
||||
const location = getEntityLocation(this.stateObj, this.hass.states);
|
||||
const hasOwnCoordinates =
|
||||
typeof this.stateObj.attributes.latitude === "number" &&
|
||||
typeof this.stateObj.attributes.longitude === "number";
|
||||
@@ -49,12 +31,13 @@ class MoreInfoPerson extends LitElement {
|
||||
${location
|
||||
? html`
|
||||
<ha-map
|
||||
.hass=${this.hass}
|
||||
.entities=${this._entityArray(this.stateObj.entity_id)}
|
||||
auto-fit
|
||||
></ha-map>
|
||||
`
|
||||
: ""}
|
||||
${!__DEMO__ && this._user?.is_admin && hasOwnCoordinates
|
||||
${!__DEMO__ && this.hass.user?.is_admin && hasOwnCoordinates
|
||||
? html`
|
||||
<div class="actions">
|
||||
<ha-button
|
||||
@@ -62,7 +45,7 @@ class MoreInfoPerson extends LitElement {
|
||||
size="s"
|
||||
@click=${this._handleAction}
|
||||
>
|
||||
${this._localize(
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.person.create_zone"
|
||||
)}
|
||||
</ha-button>
|
||||
|
||||
@@ -1,42 +1,18 @@
|
||||
import { consume } from "@lit/context";
|
||||
import type { HassConfig, HassEntity } from "home-assistant-js-websocket";
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { formatTime } from "../../../common/datetime/format_time";
|
||||
import { transform } from "../../../common/decorators/transform";
|
||||
import "../../../components/ha-relative-time";
|
||||
import {
|
||||
configContext,
|
||||
formattersContext,
|
||||
internationalizationContext,
|
||||
} from "../../../data/context";
|
||||
import type {
|
||||
HomeAssistantConfig,
|
||||
HomeAssistantFormatters,
|
||||
HomeAssistantInternationalization,
|
||||
} from "../../../types";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
|
||||
@customElement("more-info-sun")
|
||||
class MoreInfoSun extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public stateObj?: HassEntity;
|
||||
|
||||
@state()
|
||||
@consume({ context: internationalizationContext, subscribe: true })
|
||||
private _i18n!: HomeAssistantInternationalization;
|
||||
|
||||
@state()
|
||||
@consume({ context: formattersContext, subscribe: true })
|
||||
private _formatters!: HomeAssistantFormatters;
|
||||
|
||||
@state()
|
||||
@consume({ context: configContext, subscribe: true })
|
||||
@transform<HomeAssistantConfig, HassConfig>({
|
||||
transformer: ({ config }) => config,
|
||||
})
|
||||
private _config!: HassConfig;
|
||||
|
||||
protected render() {
|
||||
if (!this._i18n || !this.stateObj) {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
@@ -52,10 +28,10 @@ class MoreInfoSun extends LitElement {
|
||||
<div class="key">
|
||||
<span
|
||||
>${item === "ris"
|
||||
? this._i18n.localize(
|
||||
? this.hass.localize(
|
||||
"ui.dialogs.more_info_control.sun.rising"
|
||||
)
|
||||
: this._i18n.localize(
|
||||
: this.hass.localize(
|
||||
"ui.dialogs.more_info_control.sun.setting"
|
||||
)}</span
|
||||
>
|
||||
@@ -66,8 +42,8 @@ class MoreInfoSun extends LitElement {
|
||||
<div class="value">
|
||||
${formatTime(
|
||||
item === "ris" ? risingDate : settingDate,
|
||||
this._i18n.locale,
|
||||
this._config
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,24 +51,18 @@ class MoreInfoSun extends LitElement {
|
||||
)}
|
||||
<div class="row">
|
||||
<div class="key">
|
||||
${this._i18n.localize("ui.dialogs.more_info_control.sun.elevation")}
|
||||
${this.hass.localize("ui.dialogs.more_info_control.sun.elevation")}
|
||||
</div>
|
||||
<div class="value">
|
||||
${this._formatters.formatEntityAttributeValue(
|
||||
this.stateObj,
|
||||
"elevation"
|
||||
)}
|
||||
${this.hass.formatEntityAttributeValue(this.stateObj, "elevation")}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="key">
|
||||
${this._i18n.localize("ui.dialogs.more_info_control.sun.azimuth")}
|
||||
${this.hass.localize("ui.dialogs.more_info_control.sun.azimuth")}
|
||||
</div>
|
||||
<div class="value">
|
||||
${this._formatters.formatEntityAttributeValue(
|
||||
this.stateObj,
|
||||
"azimuth"
|
||||
)}
|
||||
${this.hass.formatEntityAttributeValue(this.stateObj, "azimuth")}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { consume } from "@lit/context";
|
||||
import { mdiEye, mdiGauge, mdiWaterPercent, mdiWeatherWindy } from "@mdi/js";
|
||||
import type { HassConfig } from "home-assistant-js-websocket";
|
||||
import type { CSSResultGroup, PropertyValues } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
@@ -9,7 +7,6 @@ import memoizeOne from "memoize-one";
|
||||
import { DragScrollController } from "../../../common/controllers/drag-scroll-controller";
|
||||
import { formatDateWeekdayShort } from "../../../common/datetime/format_date";
|
||||
import { formatTime } from "../../../common/datetime/format_time";
|
||||
import { transform } from "../../../common/decorators/transform";
|
||||
import { formatNumber } from "../../../common/number/format_number";
|
||||
import "../../../components/ha-alert";
|
||||
import "../../../components/ha-relative-time";
|
||||
@@ -19,12 +16,6 @@ import "../../../components/ha-svg-icon";
|
||||
import "../../../components/ha-tab-group";
|
||||
import "../../../components/ha-tab-group-tab";
|
||||
import "../../../components/ha-tooltip";
|
||||
import {
|
||||
configContext,
|
||||
connectionContext,
|
||||
formattersContext,
|
||||
internationalizationContext,
|
||||
} from "../../../data/context";
|
||||
import type {
|
||||
ForecastAttribute,
|
||||
ForecastEvent,
|
||||
@@ -42,36 +33,14 @@ import {
|
||||
subscribeForecast,
|
||||
weatherSVGStyles,
|
||||
} from "../../../data/weather";
|
||||
import type {
|
||||
HomeAssistantConfig,
|
||||
HomeAssistantConnection,
|
||||
HomeAssistantFormatters,
|
||||
HomeAssistantInternationalization,
|
||||
} from "../../../types";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
|
||||
@customElement("more-info-weather")
|
||||
class MoreInfoWeather extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public stateObj?: WeatherEntity;
|
||||
|
||||
@state()
|
||||
@consume({ context: internationalizationContext, subscribe: true })
|
||||
private _i18n!: HomeAssistantInternationalization;
|
||||
|
||||
@state()
|
||||
@consume({ context: formattersContext, subscribe: true })
|
||||
private _formatters!: HomeAssistantFormatters;
|
||||
|
||||
@state()
|
||||
@consume({ context: configContext, subscribe: true })
|
||||
@transform<HomeAssistantConfig, HassConfig>({
|
||||
transformer: ({ config }) => config,
|
||||
})
|
||||
private _config!: HassConfig;
|
||||
|
||||
@state()
|
||||
@consume({ context: connectionContext, subscribe: true })
|
||||
private _connection!: HomeAssistantConnection;
|
||||
|
||||
@state() private _forecastEvent?: ForecastEvent;
|
||||
|
||||
@state() private _forecastType?: ModernForecastType;
|
||||
@@ -95,7 +64,7 @@ class MoreInfoWeather extends LitElement {
|
||||
this._unsubscribeForecastEvents();
|
||||
if (
|
||||
!this.isConnected ||
|
||||
!this._connection ||
|
||||
!this.hass ||
|
||||
!this.stateObj ||
|
||||
!this._forecastType
|
||||
) {
|
||||
@@ -103,8 +72,8 @@ class MoreInfoWeather extends LitElement {
|
||||
}
|
||||
|
||||
this._subscribed = subscribeForecast(
|
||||
this._connection.connection,
|
||||
this.stateObj.entity_id,
|
||||
this.hass!.connection,
|
||||
this.stateObj!.entity_id,
|
||||
this._forecastType,
|
||||
(event) => {
|
||||
this._forecastEvent = event;
|
||||
@@ -124,6 +93,23 @@ class MoreInfoWeather extends LitElement {
|
||||
this._unsubscribeForecastEvents();
|
||||
}
|
||||
|
||||
protected shouldUpdate(changedProps: PropertyValues<this>): boolean {
|
||||
if (changedProps.has("stateObj")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (
|
||||
!oldHass ||
|
||||
oldHass.locale !== this.hass.locale ||
|
||||
oldHass.config.unit_system !== this.hass.config.unit_system
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
super.willUpdate(changedProps);
|
||||
|
||||
@@ -180,7 +166,7 @@ class MoreInfoWeather extends LitElement {
|
||||
});
|
||||
|
||||
protected render() {
|
||||
if (!this._i18n || !this._formatters || !this._config || !this.stateObj) {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
@@ -210,7 +196,7 @@ class MoreInfoWeather extends LitElement {
|
||||
<div class="info">
|
||||
<div class="name-state">
|
||||
<div class="state">
|
||||
${this._formatters.formatEntityState(this.stateObj)}
|
||||
${this.hass.formatEntityState(this.stateObj)}
|
||||
</div>
|
||||
<div class="time-ago">
|
||||
<ha-relative-time
|
||||
@@ -221,7 +207,7 @@ class MoreInfoWeather extends LitElement {
|
||||
<ha-tooltip for="relative-time">
|
||||
<div class="row">
|
||||
<span class="column-name">
|
||||
${this._i18n.localize(
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.last_changed"
|
||||
)}:
|
||||
</span>
|
||||
@@ -232,7 +218,7 @@ class MoreInfoWeather extends LitElement {
|
||||
</div>
|
||||
<div class="row">
|
||||
<span>
|
||||
${this._i18n.localize(
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.last_updated"
|
||||
)}:
|
||||
</span>
|
||||
@@ -251,10 +237,10 @@ class MoreInfoWeather extends LitElement {
|
||||
? html`
|
||||
${formatNumber(
|
||||
this.stateObj.attributes.temperature,
|
||||
this._i18n.locale
|
||||
this.hass.locale
|
||||
)} <span
|
||||
>${getWeatherUnit(
|
||||
this._config,
|
||||
this.hass.config,
|
||||
this.stateObj,
|
||||
"temperature"
|
||||
)}</span
|
||||
@@ -264,11 +250,7 @@ class MoreInfoWeather extends LitElement {
|
||||
</div>
|
||||
<div class="attribute">
|
||||
${getSecondaryWeatherAttribute(
|
||||
{
|
||||
formatEntityAttributeValue:
|
||||
this._formatters.formatEntityAttributeValue,
|
||||
localize: this._i18n.localize,
|
||||
},
|
||||
this.hass,
|
||||
this.stateObj,
|
||||
forecast!
|
||||
)}
|
||||
@@ -281,12 +263,10 @@ class MoreInfoWeather extends LitElement {
|
||||
<div class="flex">
|
||||
<ha-svg-icon .path=${mdiGauge}></ha-svg-icon>
|
||||
<div class="main">
|
||||
${this._i18n.localize(
|
||||
"ui.card.weather.attributes.air_pressure"
|
||||
)}
|
||||
${this.hass.localize("ui.card.weather.attributes.air_pressure")}
|
||||
</div>
|
||||
<div>
|
||||
${this._formatters.formatEntityAttributeValue(
|
||||
${this.hass.formatEntityAttributeValue(
|
||||
this.stateObj,
|
||||
"pressure"
|
||||
)}
|
||||
@@ -299,10 +279,10 @@ class MoreInfoWeather extends LitElement {
|
||||
<div class="flex">
|
||||
<ha-svg-icon .path=${mdiWaterPercent}></ha-svg-icon>
|
||||
<div class="main">
|
||||
${this._i18n.localize("ui.card.weather.attributes.humidity")}
|
||||
${this.hass.localize("ui.card.weather.attributes.humidity")}
|
||||
</div>
|
||||
<div>
|
||||
${this._formatters.formatEntityAttributeValue(
|
||||
${this.hass.formatEntityAttributeValue(
|
||||
this.stateObj,
|
||||
"humidity"
|
||||
)}
|
||||
@@ -315,12 +295,11 @@ class MoreInfoWeather extends LitElement {
|
||||
<div class="flex">
|
||||
<ha-svg-icon .path=${mdiWeatherWindy}></ha-svg-icon>
|
||||
<div class="main">
|
||||
${this._i18n.localize("ui.card.weather.attributes.wind_speed")}
|
||||
${this.hass.localize("ui.card.weather.attributes.wind_speed")}
|
||||
</div>
|
||||
<div>
|
||||
${getWind(
|
||||
this._formatters.formatEntityAttributeValue,
|
||||
this._i18n.localize,
|
||||
this.hass,
|
||||
this.stateObj,
|
||||
this.stateObj.attributes.wind_speed!,
|
||||
this.stateObj.attributes.wind_bearing
|
||||
@@ -334,10 +313,10 @@ class MoreInfoWeather extends LitElement {
|
||||
<div class="flex">
|
||||
<ha-svg-icon .path=${mdiEye}></ha-svg-icon>
|
||||
<div class="main">
|
||||
${this._i18n.localize("ui.card.weather.attributes.visibility")}
|
||||
${this.hass.localize("ui.card.weather.attributes.visibility")}
|
||||
</div>
|
||||
<div>
|
||||
${this._formatters.formatEntityAttributeValue(
|
||||
${this.hass.formatEntityAttributeValue(
|
||||
this.stateObj,
|
||||
"visibility"
|
||||
)}
|
||||
@@ -348,7 +327,7 @@ class MoreInfoWeather extends LitElement {
|
||||
${supportedForecasts?.length
|
||||
? html`
|
||||
<div class="section">
|
||||
${this._i18n.localize("ui.card.weather.forecast")}:
|
||||
${this.hass.localize("ui.card.weather.forecast")}:
|
||||
</div>
|
||||
${supportedForecasts?.length > 1
|
||||
? html`<ha-tab-group
|
||||
@@ -361,7 +340,7 @@ class MoreInfoWeather extends LitElement {
|
||||
.panel=${forecastType}
|
||||
.active=${this._forecastType === forecastType}
|
||||
>
|
||||
${this._i18n.localize(
|
||||
${this.hass!.localize(
|
||||
`ui.card.weather.${forecastType}`
|
||||
)}
|
||||
</ha-tab-group-tab>`
|
||||
@@ -383,8 +362,8 @@ class MoreInfoWeather extends LitElement {
|
||||
? html`<div class="forecast-day-header">
|
||||
${formatDateWeekdayShort(
|
||||
new Date(dayForecast[0].datetime),
|
||||
this._i18n.locale,
|
||||
this._config
|
||||
this.hass!.locale,
|
||||
this.hass!.config
|
||||
)}
|
||||
</div>`
|
||||
: nothing}
|
||||
@@ -402,23 +381,23 @@ class MoreInfoWeather extends LitElement {
|
||||
${hourly
|
||||
? formatTime(
|
||||
new Date(item.datetime),
|
||||
this._i18n.locale,
|
||||
this._config
|
||||
this.hass!.locale,
|
||||
this.hass!.config
|
||||
)
|
||||
: dayNight
|
||||
? html`<div class="daynight">
|
||||
${item.is_daytime !== false
|
||||
? this._i18n.localize(
|
||||
? this.hass!.localize(
|
||||
"ui.card.weather.day"
|
||||
)
|
||||
: this._i18n.localize(
|
||||
: this.hass!.localize(
|
||||
"ui.card.weather.night"
|
||||
)}
|
||||
</div>`
|
||||
: formatDateWeekdayShort(
|
||||
new Date(item.datetime),
|
||||
this._i18n.locale,
|
||||
this._config
|
||||
this.hass!.locale,
|
||||
this.hass!.config
|
||||
)}
|
||||
</div>
|
||||
${this._showValue(item.condition)
|
||||
@@ -439,7 +418,7 @@ class MoreInfoWeather extends LitElement {
|
||||
${this._showValue(item.temperature)
|
||||
? html`${formatNumber(
|
||||
item.temperature,
|
||||
this._i18n.locale
|
||||
this.hass!.locale
|
||||
)}°`
|
||||
: "—"}
|
||||
</div>
|
||||
@@ -447,7 +426,7 @@ class MoreInfoWeather extends LitElement {
|
||||
${this._showValue(item.templow)
|
||||
? html`${formatNumber(
|
||||
item.templow!,
|
||||
this._i18n.locale
|
||||
this.hass!.locale
|
||||
)}°`
|
||||
: nothing}
|
||||
</div>
|
||||
|
||||
@@ -136,6 +136,7 @@ class HaConfigSectionGeneral extends LitElement {
|
||||
? html`
|
||||
<div class="card-content">
|
||||
<ha-map
|
||||
.hass=${this.hass}
|
||||
.entities=${["zone.home"]}
|
||||
.zoom=${14}
|
||||
.autoFit=${true}
|
||||
|
||||
@@ -9,6 +9,7 @@ import "../../../../components/ha-card";
|
||||
import "../../../../components/ha-icon";
|
||||
import "../../../../components/ha-list";
|
||||
import "../../../../components/ha-list-item";
|
||||
import { computeEntityEntryName } from "../../../../common/entity/compute_entity_name";
|
||||
import type { EntityRegistryEntry } from "../../../../data/entity/entity_registry";
|
||||
import { entryIcon } from "../../../../data/icons";
|
||||
import { showMoreInfoDialog } from "../../../../dialogs/more-info/show-ha-more-info-dialog";
|
||||
@@ -57,20 +58,29 @@ export class HaDeviceEntitiesCard extends LitElement {
|
||||
}
|
||||
});
|
||||
|
||||
// Main entities (those without their own name, shown as the device name)
|
||||
// are listed first, separated from the additional entities by a divider.
|
||||
const mainEntities: EntityRegistryStateEntry[] = [];
|
||||
const additionalEntities: EntityRegistryStateEntry[] = [];
|
||||
enabledEntities.forEach((entry) => {
|
||||
if (computeEntityEntryName(entry, this.hass.devices)) {
|
||||
additionalEntities.push(entry);
|
||||
} else {
|
||||
mainEntities.push(entry);
|
||||
}
|
||||
});
|
||||
|
||||
return html`
|
||||
<ha-card outlined .header=${this.header}>
|
||||
${enabledEntities.length
|
||||
? html`
|
||||
<div id="entities" class="move-up">
|
||||
<ha-list>
|
||||
${repeat(
|
||||
enabledEntities,
|
||||
(entry) => entry.entity_id,
|
||||
(entry) =>
|
||||
this.hass.states[entry.entity_id]
|
||||
? this._renderEntity(entry)
|
||||
: this._renderUnavailableEntity(entry)
|
||||
)}
|
||||
${this._renderEntities(mainEntities)}
|
||||
${mainEntities.length && additionalEntities.length
|
||||
? html`<div class="divider" role="separator"></div>`
|
||||
: nothing}
|
||||
${this._renderEntities(additionalEntities)}
|
||||
</ha-list>
|
||||
</div>
|
||||
`
|
||||
@@ -115,6 +125,17 @@ export class HaDeviceEntitiesCard extends LitElement {
|
||||
this.showHidden = !this.showHidden;
|
||||
}
|
||||
|
||||
private _renderEntities(entries: EntityRegistryStateEntry[]) {
|
||||
return repeat(
|
||||
entries,
|
||||
(entry) => entry.entity_id,
|
||||
(entry) =>
|
||||
this.hass.states[entry.entity_id]
|
||||
? this._renderEntity(entry)
|
||||
: this._renderUnavailableEntity(entry)
|
||||
);
|
||||
}
|
||||
|
||||
private _renderEntity(entry: EntityRegistryStateEntry): TemplateResult {
|
||||
let name = entry.stateName || this.deviceName;
|
||||
if (entry.hidden_by) {
|
||||
@@ -187,6 +208,11 @@ export class HaDeviceEntitiesCard extends LitElement {
|
||||
.disabled-entry {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.divider {
|
||||
height: 1px;
|
||||
background-color: var(--divider-color);
|
||||
margin: 8px 16px;
|
||||
}
|
||||
.move-up {
|
||||
margin-top: -13px;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
mdiPalette,
|
||||
mdiPaletteSwatch,
|
||||
mdiPuzzle,
|
||||
mdiRadioTower,
|
||||
mdiRemote,
|
||||
mdiRobot,
|
||||
mdiScrewdriver,
|
||||
@@ -185,15 +184,6 @@ export const configSections: Record<string, PageNavigation[]> = {
|
||||
adminOnly: true,
|
||||
filter: getHasDomainCheck("infrared"),
|
||||
},
|
||||
{
|
||||
path: "/config/radio-frequency",
|
||||
iconPath: mdiRadioTower,
|
||||
iconColor: "#E74011",
|
||||
component: "radio_frequency",
|
||||
translationKey: "radio_frequency",
|
||||
adminOnly: true,
|
||||
filter: getHasDomainCheck("radio_frequency"),
|
||||
},
|
||||
{
|
||||
path: "/insteon",
|
||||
iconPath:
|
||||
@@ -695,11 +685,6 @@ class HaPanelConfig extends HassRouterPage {
|
||||
tag: "ha-config-section-updates",
|
||||
load: () => import("./core/ha-config-section-updates"),
|
||||
},
|
||||
"radio-frequency": {
|
||||
tag: "radio-frequency-config-dashboard-router",
|
||||
load: () =>
|
||||
import("./integrations/integration-panels/radio_frequency/radio-frequency-config-dashboard-router"),
|
||||
},
|
||||
repairs: {
|
||||
tag: "ha-config-repairs-dashboard",
|
||||
load: () => import("./repairs/ha-config-repairs-dashboard"),
|
||||
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
import type { PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import type { RadioFrequencyTransmitter } from "../../../../../data/radio_frequency";
|
||||
import { fetchRadioFrequencyTransmitters } from "../../../../../data/radio_frequency";
|
||||
import { showAlertDialog } from "../../../../../dialogs/generic/show-dialog-box";
|
||||
import type { RouterOptions } from "../../../../../layouts/hass-router-page";
|
||||
import { HassRouterPage } from "../../../../../layouts/hass-router-page";
|
||||
import type { HomeAssistant } from "../../../../../types";
|
||||
|
||||
@customElement("radio-frequency-config-dashboard-router")
|
||||
class RadioFrequencyConfigDashboardRouter extends HassRouterPage {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@state() private _transmitters: RadioFrequencyTransmitter[] = [];
|
||||
|
||||
private _fetched = false;
|
||||
|
||||
protected routerOptions: RouterOptions = {
|
||||
defaultPage: "dashboard",
|
||||
showLoading: true,
|
||||
routes: {
|
||||
dashboard: {
|
||||
tag: "radio-frequency-config-dashboard",
|
||||
load: () => import("./radio-frequency-config-dashboard"),
|
||||
},
|
||||
devices: {
|
||||
tag: "radio-frequency-devices-page",
|
||||
load: () => import("./radio-frequency-devices-page"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
super.willUpdate(changedProps);
|
||||
if (!this._fetched && this.hass) {
|
||||
this._fetched = true;
|
||||
this._fetchTransmitters();
|
||||
}
|
||||
}
|
||||
|
||||
private async _fetchTransmitters(): Promise<void> {
|
||||
try {
|
||||
const result = await fetchRadioFrequencyTransmitters(this.hass);
|
||||
this._transmitters = result.transmitters;
|
||||
} catch (err: any) {
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.radio_frequency.loading_error"
|
||||
),
|
||||
text: err.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected updatePageEl(el): void {
|
||||
el.route = this.routeTail;
|
||||
el.hass = this.hass;
|
||||
el.isWide = this.isWide;
|
||||
el.narrow = this.narrow;
|
||||
el.transmitters = this._transmitters;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"radio-frequency-config-dashboard-router": RadioFrequencyConfigDashboardRouter;
|
||||
}
|
||||
}
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
import { mdiCheck, mdiCloseCircleOutline } from "@mdi/js";
|
||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import "../../../../../components/ha-card";
|
||||
import "../../../../../components/ha-icon-next";
|
||||
import "../../../../../components/ha-md-list";
|
||||
import "../../../../../components/ha-md-list-item";
|
||||
import "../../../../../components/ha-svg-icon";
|
||||
import { UNAVAILABLE } from "../../../../../data/entity/entity";
|
||||
import { FALLBACK_DOMAIN_ICONS } from "../../../../../data/icons";
|
||||
import type { RadioFrequencyTransmitter } from "../../../../../data/radio_frequency";
|
||||
import { DOMAIN } from "../../../../../data/radio_frequency";
|
||||
import "../../../../../layouts/hass-subpage";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../../../types";
|
||||
|
||||
@customElement("radio-frequency-config-dashboard")
|
||||
export class RadioFrequencyConfigDashboard extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public route!: Route;
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
|
||||
|
||||
@property({ attribute: false })
|
||||
public transmitters: RadioFrequencyTransmitter[] = [];
|
||||
|
||||
protected render(): TemplateResult {
|
||||
const total = this.transmitters.length;
|
||||
const online = this.transmitters.filter((transmitter) => {
|
||||
const stateObj = this.hass.states[transmitter.entity_id];
|
||||
return stateObj && stateObj.state !== UNAVAILABLE;
|
||||
}).length;
|
||||
const isOffline = online === 0;
|
||||
const status = isOffline ? "offline" : "online";
|
||||
const statusIcon = isOffline ? mdiCloseCircleOutline : mdiCheck;
|
||||
|
||||
return html`
|
||||
<hass-subpage
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.header=${this.hass.localize("ui.panel.config.radio_frequency.title")}
|
||||
back-path="/config"
|
||||
>
|
||||
<div class="container">
|
||||
<ha-card class="network-status">
|
||||
<div class="card-content">
|
||||
<div class="heading">
|
||||
<div class="icon ${status}">
|
||||
<ha-svg-icon .path=${statusIcon}></ha-svg-icon>
|
||||
</div>
|
||||
<div class="details">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.radio_frequency.status_${status}`
|
||||
)}<br />
|
||||
<small>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.radio_frequency.devices_online_summary",
|
||||
{ online, total }
|
||||
)}
|
||||
</small>
|
||||
</div>
|
||||
<ha-svg-icon
|
||||
class="logo"
|
||||
.path=${FALLBACK_DOMAIN_ICONS[DOMAIN]}
|
||||
></ha-svg-icon>
|
||||
</div>
|
||||
</div>
|
||||
</ha-card>
|
||||
|
||||
<ha-card class="network-card">
|
||||
<div class="card-content">
|
||||
<ha-md-list>
|
||||
<ha-md-list-item
|
||||
type="link"
|
||||
href="/config/radio-frequency/devices"
|
||||
>
|
||||
<ha-svg-icon
|
||||
slot="start"
|
||||
.path=${FALLBACK_DOMAIN_ICONS[DOMAIN]}
|
||||
></ha-svg-icon>
|
||||
<div slot="headline">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.radio_frequency.devices_count",
|
||||
{ count: total }
|
||||
)}
|
||||
</div>
|
||||
<ha-icon-next slot="end"></ha-icon-next>
|
||||
</ha-md-list-item>
|
||||
</ha-md-list>
|
||||
</div>
|
||||
</ha-card>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.container {
|
||||
padding: var(--ha-space-2) var(--ha-space-4) var(--ha-space-4);
|
||||
}
|
||||
|
||||
ha-card {
|
||||
margin: 0px auto var(--ha-space-4);
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
ha-md-list {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.network-card {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.network-card .card-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.network-status div.heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: var(--ha-space-4);
|
||||
}
|
||||
|
||||
.network-status div.heading .logo {
|
||||
margin-inline-start: auto;
|
||||
--mdc-icon-size: 40px;
|
||||
}
|
||||
|
||||
.network-status div.heading .icon {
|
||||
position: relative;
|
||||
border-radius: var(--ha-border-radius-2xl);
|
||||
width: var(--ha-space-10);
|
||||
height: var(--ha-space-10);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
--icon-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.network-status div.heading .icon.online {
|
||||
--icon-color: var(--success-color);
|
||||
}
|
||||
|
||||
.network-status div.heading .icon.offline {
|
||||
--icon-color: var(--error-color);
|
||||
}
|
||||
|
||||
.network-status div.heading .icon::before {
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-color: var(--icon-color, var(--primary-color));
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.network-status div.heading .icon ha-svg-icon {
|
||||
color: var(--icon-color, var(--primary-color));
|
||||
width: var(--ha-space-6);
|
||||
height: var(--ha-space-6);
|
||||
}
|
||||
|
||||
.network-status div.heading .details {
|
||||
font-size: var(--ha-font-size-xl);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
line-height: var(--ha-line-height-condensed);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.network-status small {
|
||||
font-size: var(--ha-font-size-m);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
line-height: var(--ha-line-height-condensed);
|
||||
letter-spacing: 0.25px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"radio-frequency-config-dashboard": RadioFrequencyConfigDashboard;
|
||||
}
|
||||
}
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||
import { html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { navigate } from "../../../../../common/navigate";
|
||||
import { computeStateName } from "../../../../../common/entity/compute_state_name";
|
||||
import type { HASSDomEvent } from "../../../../../common/dom/fire_event";
|
||||
import type { LocalizeFunc } from "../../../../../common/translations/localize";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
RowClickedEvent,
|
||||
} from "../../../../../components/data-table/ha-data-table";
|
||||
import "../../../../../components/ha-relative-time";
|
||||
import { UNAVAILABLE, UNKNOWN } from "../../../../../data/entity/entity";
|
||||
import type { RadioFrequencyTransmitter } from "../../../../../data/radio_frequency";
|
||||
import "../../../../../layouts/hass-tabs-subpage-data-table";
|
||||
import type { PageNavigation } from "../../../../../layouts/hass-tabs-subpage";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../../../types";
|
||||
|
||||
interface RadioFrequencyTransmitterRow {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
last_used?: string;
|
||||
device_id: string | null;
|
||||
}
|
||||
|
||||
@customElement("radio-frequency-devices-page")
|
||||
export class RadioFrequencyDevicesPage extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public route!: Route;
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
|
||||
|
||||
@property({ attribute: false })
|
||||
public transmitters: RadioFrequencyTransmitter[] = [];
|
||||
|
||||
private _tabs: PageNavigation[] = [
|
||||
{
|
||||
translationKey: "ui.panel.config.radio_frequency.devices_navigation",
|
||||
path: "/config/radio-frequency/devices",
|
||||
},
|
||||
];
|
||||
|
||||
private _columns = memoizeOne(
|
||||
(localize: LocalizeFunc): DataTableColumnContainer => {
|
||||
const columns: DataTableColumnContainer<RadioFrequencyTransmitterRow> = {
|
||||
name: {
|
||||
title: localize("ui.panel.config.radio_frequency.name"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
showNarrow: true,
|
||||
main: true,
|
||||
flex: 2,
|
||||
direction: "asc",
|
||||
},
|
||||
type: {
|
||||
title: localize("ui.panel.config.radio_frequency.type"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
groupable: true,
|
||||
},
|
||||
last_used: {
|
||||
title: localize("ui.panel.config.radio_frequency.last_used"),
|
||||
sortable: true,
|
||||
template: (transmitter) =>
|
||||
transmitter.last_used
|
||||
? html`<ha-relative-time
|
||||
.hass=${this.hass}
|
||||
.datetime=${transmitter.last_used}
|
||||
capitalize
|
||||
></ha-relative-time>`
|
||||
: "—",
|
||||
},
|
||||
};
|
||||
|
||||
return columns;
|
||||
}
|
||||
);
|
||||
|
||||
private _data = memoizeOne(
|
||||
(
|
||||
transmitters: RadioFrequencyTransmitter[],
|
||||
states: HomeAssistant["states"],
|
||||
localize: LocalizeFunc
|
||||
): RadioFrequencyTransmitterRow[] =>
|
||||
transmitters.map((transmitter) => {
|
||||
const stateObj = states[transmitter.entity_id];
|
||||
// The entity state holds the timestamp the transmitter was last used
|
||||
// (or unknown/unavailable when it never has been).
|
||||
const state = stateObj?.state;
|
||||
const last_used =
|
||||
state &&
|
||||
state !== UNAVAILABLE &&
|
||||
state !== UNKNOWN &&
|
||||
!isNaN(new Date(state).getTime())
|
||||
? state
|
||||
: undefined;
|
||||
return {
|
||||
id: transmitter.entity_id,
|
||||
name: stateObj ? computeStateName(stateObj) : transmitter.entity_id,
|
||||
type: localize("component.radio_frequency.entity_component._.name"),
|
||||
last_used,
|
||||
device_id: transmitter.device_id,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<hass-tabs-subpage-data-table
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.route=${this.route}
|
||||
.tabs=${this._tabs}
|
||||
back-path="/config/radio-frequency/dashboard"
|
||||
.columns=${this._columns(this.hass.localize)}
|
||||
.data=${this._data(
|
||||
this.transmitters,
|
||||
this.hass.states,
|
||||
this.hass.localize
|
||||
)}
|
||||
.noDataText=${this.hass.localize(
|
||||
"ui.panel.config.radio_frequency.no_devices"
|
||||
)}
|
||||
@row-click=${this._handleRowClicked}
|
||||
clickable
|
||||
></hass-tabs-subpage-data-table>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleRowClicked(ev: HASSDomEvent<RowClickedEvent>) {
|
||||
const transmitter = this.transmitters.find(
|
||||
(t) => t.entity_id === ev.detail.id
|
||||
);
|
||||
if (transmitter?.device_id) {
|
||||
navigate(`/config/devices/device/${transmitter.device_id}`);
|
||||
}
|
||||
}
|
||||
|
||||
static styles: CSSResultGroup = haStyle;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"radio-frequency-devices-page": RadioFrequencyDevicesPage;
|
||||
}
|
||||
}
|
||||
@@ -211,6 +211,7 @@ class HuiMapCard extends LitElement implements LovelaceCard {
|
||||
<ha-card id="card" .header=${this._config.title}>
|
||||
<div id="root">
|
||||
<ha-map
|
||||
.hass=${this.hass}
|
||||
.entities=${this._filteredMapEntities}
|
||||
.zoom=${this._config.default_zoom ?? DEFAULT_ZOOM}
|
||||
.paths=${this._getHistoryPaths(this._config, this._stateHistory)}
|
||||
|
||||
@@ -378,8 +378,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
|
||||
${this._config.secondary_info_attribute ===
|
||||
"wind_speed"
|
||||
? getWind(
|
||||
this.hass.formatEntityAttributeValue,
|
||||
this.hass.localize,
|
||||
this.hass,
|
||||
stateObj,
|
||||
stateObj.attributes.wind_speed,
|
||||
stateObj.attributes.wind_bearing
|
||||
|
||||
@@ -32,7 +32,7 @@ import type { HomeAssistant } from "../../../../types";
|
||||
import { computeShowHeaderToggle } from "../../cards/hui-entities-card";
|
||||
import type { EntitiesCardConfig } from "../../cards/types";
|
||||
import { processConfigEntities } from "../../common/process-config-entities";
|
||||
import { timeFormatConfigStruct } from "../../components/types";
|
||||
import { TIMESTAMP_RENDERING_FORMATS } from "../../components/types";
|
||||
import type { LovelaceRowConfig } from "../../entity-rows/types";
|
||||
import { headerFooterConfigStructs } from "../../header-footer/structs";
|
||||
import type { LovelaceCardEditor } from "../../types";
|
||||
@@ -119,7 +119,7 @@ const attributeEntitiesRowConfigStruct = object({
|
||||
suffix: optional(string()),
|
||||
name: optional(string()),
|
||||
icon: optional(string()),
|
||||
format: optional(timeFormatConfigStruct),
|
||||
format: optional(enums(TIMESTAMP_RENDERING_FORMATS)),
|
||||
});
|
||||
|
||||
const textEntitiesRowConfigStruct = object({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { union, object, string, optional, boolean } from "superstruct";
|
||||
import { timeFormatConfigStruct } from "../../components/types";
|
||||
import { union, object, string, optional, boolean, enums } from "superstruct";
|
||||
import { TIMESTAMP_RENDERING_FORMATS } from "../../components/types";
|
||||
import {
|
||||
actionConfigStruct,
|
||||
actionConfigStructConfirmation,
|
||||
@@ -13,7 +13,7 @@ export const entitiesConfigStruct = union([
|
||||
icon: optional(string()),
|
||||
image: optional(string()),
|
||||
secondary_info: optional(string()),
|
||||
format: optional(timeFormatConfigStruct),
|
||||
format: optional(enums(TIMESTAMP_RENDERING_FORMATS)),
|
||||
state_color: optional(boolean()),
|
||||
tap_action: optional(actionConfigStruct),
|
||||
hold_action: optional(actionConfigStruct),
|
||||
|
||||
@@ -31,7 +31,12 @@ class HaPanelMap extends LitElement {
|
||||
@click=${this._openZonesEditor}
|
||||
></ha-icon-button>`
|
||||
: ""}
|
||||
<ha-map .entities=${this._entities} auto-fit interactive-zones></ha-map>
|
||||
<ha-map
|
||||
.hass=${this.hass}
|
||||
.entities=${this._entities}
|
||||
auto-fit
|
||||
interactive-zones
|
||||
></ha-map>
|
||||
</ha-top-app-bar-fixed>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -1558,7 +1558,6 @@
|
||||
"zwave_js": "[%key:ui::panel::config::dashboard::zwave_js::main%]",
|
||||
"thread": "[%key:ui::panel::config::dashboard::thread::main%]",
|
||||
"bluetooth": "[%key:ui::panel::config::dashboard::bluetooth::main%]",
|
||||
"radio_frequency": "[%key:ui::panel::config::dashboard::radio_frequency::main%]",
|
||||
"knx": "[%key:ui::panel::config::dashboard::knx::main%]",
|
||||
"insteon": "[%key:ui::panel::config::dashboard::insteon::main%]",
|
||||
"voice-assistants": "[%key:ui::panel::config::dashboard::voice_assistants::main%]",
|
||||
@@ -2658,10 +2657,6 @@
|
||||
"main": "Bluetooth",
|
||||
"secondary": "Local device connectivity"
|
||||
},
|
||||
"radio_frequency": {
|
||||
"main": "Radio frequency",
|
||||
"secondary": "Control radio-based devices."
|
||||
},
|
||||
"knx": {
|
||||
"main": "KNX",
|
||||
"secondary": "Building automation standard"
|
||||
@@ -7143,19 +7138,6 @@
|
||||
"known_devices": "Known devices",
|
||||
"unknown_devices": "Unknown devices"
|
||||
},
|
||||
"radio_frequency": {
|
||||
"title": "Radio frequency",
|
||||
"status_online": "Online",
|
||||
"status_offline": "Offline",
|
||||
"devices_online_summary": "{online}/{total} devices online",
|
||||
"devices_count": "{count} {count, plural,\n one {device}\n other {devices}\n}",
|
||||
"no_devices": "No radio frequency devices found",
|
||||
"loading_error": "Failed to load radio frequency devices",
|
||||
"name": "Name",
|
||||
"type": "Type",
|
||||
"last_used": "Last used",
|
||||
"devices_navigation": "Devices"
|
||||
},
|
||||
"dhcp": {
|
||||
"title": "DHCP discovery",
|
||||
"mac_address": "MAC address",
|
||||
|
||||
@@ -4926,12 +4926,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vitest/coverage-v8@npm:4.1.9":
|
||||
version: 4.1.9
|
||||
resolution: "@vitest/coverage-v8@npm:4.1.9"
|
||||
"@vitest/coverage-v8@npm:4.1.8":
|
||||
version: 4.1.8
|
||||
resolution: "@vitest/coverage-v8@npm:4.1.8"
|
||||
dependencies:
|
||||
"@bcoe/v8-coverage": "npm:^1.0.2"
|
||||
"@vitest/utils": "npm:4.1.9"
|
||||
"@vitest/utils": "npm:4.1.8"
|
||||
ast-v8-to-istanbul: "npm:^1.0.0"
|
||||
istanbul-lib-coverage: "npm:^3.2.2"
|
||||
istanbul-lib-report: "npm:^3.0.1"
|
||||
@@ -4941,34 +4941,34 @@ __metadata:
|
||||
std-env: "npm:^4.0.0-rc.1"
|
||||
tinyrainbow: "npm:^3.1.0"
|
||||
peerDependencies:
|
||||
"@vitest/browser": 4.1.9
|
||||
vitest: 4.1.9
|
||||
"@vitest/browser": 4.1.8
|
||||
vitest: 4.1.8
|
||||
peerDependenciesMeta:
|
||||
"@vitest/browser":
|
||||
optional: true
|
||||
checksum: 10/1f236e17336973868aa6e7662b863b1c519d07840107daab3465429652741fc1f8a8988d1b7b28b8cfa883c7280f7479927a85e56c7874a0ddc5cc8ceda25cd6
|
||||
checksum: 10/08d9ea65ca4cc007a1f1cdc85ea36d51bfa91a9b2f0e9ad27436b777629b4138e33dba2f68c8e68b01343310bf9d5624ad1d6d24553a5b289b66da51561259eb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vitest/expect@npm:4.1.9":
|
||||
version: 4.1.9
|
||||
resolution: "@vitest/expect@npm:4.1.9"
|
||||
"@vitest/expect@npm:4.1.8":
|
||||
version: 4.1.8
|
||||
resolution: "@vitest/expect@npm:4.1.8"
|
||||
dependencies:
|
||||
"@standard-schema/spec": "npm:^1.1.0"
|
||||
"@types/chai": "npm:^5.2.2"
|
||||
"@vitest/spy": "npm:4.1.9"
|
||||
"@vitest/utils": "npm:4.1.9"
|
||||
"@vitest/spy": "npm:4.1.8"
|
||||
"@vitest/utils": "npm:4.1.8"
|
||||
chai: "npm:^6.2.2"
|
||||
tinyrainbow: "npm:^3.1.0"
|
||||
checksum: 10/aba1a06cd28199f9c861d97797b014c0584fa6f6197e78345da0db5f74914d47f18958bb848658e889ca44452aa61e07ae851c16ea7b2175afd50d649dd4ed8c
|
||||
checksum: 10/cb7d78e250ec77b7e180ac3e5f543501488c69b237d7ed97ffe9196c5e946b0e4a37be05a2ec38af7ce7750c1a98286480acdd247286a29c239b08a13b085d4b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vitest/mocker@npm:4.1.9":
|
||||
version: 4.1.9
|
||||
resolution: "@vitest/mocker@npm:4.1.9"
|
||||
"@vitest/mocker@npm:4.1.8":
|
||||
version: 4.1.8
|
||||
resolution: "@vitest/mocker@npm:4.1.8"
|
||||
dependencies:
|
||||
"@vitest/spy": "npm:4.1.9"
|
||||
"@vitest/spy": "npm:4.1.8"
|
||||
estree-walker: "npm:^3.0.3"
|
||||
magic-string: "npm:^0.30.21"
|
||||
peerDependencies:
|
||||
@@ -4979,56 +4979,56 @@ __metadata:
|
||||
optional: true
|
||||
vite:
|
||||
optional: true
|
||||
checksum: 10/3e35ff3e2ecbdfbcae598e9c5c83978dd5f0cf3b16df37cf947c80faabce797ab275ca2075c3bb8ca85f595f3070267f93cb6798bbe415f1af2698f51833974c
|
||||
checksum: 10/fc977703b07d950aa170bafdef988bc7ba88f0a80159d1563ce95696763729ec1f6d015012aad36cf4e1b522d327b205292c56d76692d2a9f72285d694ed3cba
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vitest/pretty-format@npm:4.1.9":
|
||||
version: 4.1.9
|
||||
resolution: "@vitest/pretty-format@npm:4.1.9"
|
||||
"@vitest/pretty-format@npm:4.1.8":
|
||||
version: 4.1.8
|
||||
resolution: "@vitest/pretty-format@npm:4.1.8"
|
||||
dependencies:
|
||||
tinyrainbow: "npm:^3.1.0"
|
||||
checksum: 10/52512b300c000594c54bebbbfe31fab39e416a35d3686e2c46bc8e48ef8476d32306605f7736139608c3962943e0d22790dc15a3e6b1ffa436143d31f743a7c8
|
||||
checksum: 10/56a4b685cdf9f2e9708025f17dab8c0fa990ab06e5b38606a1ddde52a09830a099843da6a1b127ee48217ab023bad7bd23c49eb4969d77dff07df363fad0bb0e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vitest/runner@npm:4.1.9":
|
||||
version: 4.1.9
|
||||
resolution: "@vitest/runner@npm:4.1.9"
|
||||
"@vitest/runner@npm:4.1.8":
|
||||
version: 4.1.8
|
||||
resolution: "@vitest/runner@npm:4.1.8"
|
||||
dependencies:
|
||||
"@vitest/utils": "npm:4.1.9"
|
||||
"@vitest/utils": "npm:4.1.8"
|
||||
pathe: "npm:^2.0.3"
|
||||
checksum: 10/52e4e16e627faa62676f17683e570f505d58d2ce0ef421a3ae60e70c0ec5606d4af090fa6c7d5717d6e949f4401d6357b1f69cf06e52a5455a0ad9c9040268c0
|
||||
checksum: 10/278d1482123877343731b3bb822d0280af928252ee263aab73ca189c39de3bb767ce715581870b2e1eb408f7cba01106a6989406cb2ada1332f181912558a3c1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vitest/snapshot@npm:4.1.9":
|
||||
version: 4.1.9
|
||||
resolution: "@vitest/snapshot@npm:4.1.9"
|
||||
"@vitest/snapshot@npm:4.1.8":
|
||||
version: 4.1.8
|
||||
resolution: "@vitest/snapshot@npm:4.1.8"
|
||||
dependencies:
|
||||
"@vitest/pretty-format": "npm:4.1.9"
|
||||
"@vitest/utils": "npm:4.1.9"
|
||||
"@vitest/pretty-format": "npm:4.1.8"
|
||||
"@vitest/utils": "npm:4.1.8"
|
||||
magic-string: "npm:^0.30.21"
|
||||
pathe: "npm:^2.0.3"
|
||||
checksum: 10/c83349b1ad08d48284c1d3393168a7b7faffd24ace1ef337751a568dad322d83b0f9bc29378a4a60379cf2a13a268092b1d802936d6adb1ca28859f02dad8b87
|
||||
checksum: 10/162ca0eccb72db02081b04307d21ac8d14c8fcd4a840872459274f589b1665f108bd4119dff19d5a2150a0e26b90531791ebec7ee74f0c2c5285b491cebbcfcb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vitest/spy@npm:4.1.9":
|
||||
version: 4.1.9
|
||||
resolution: "@vitest/spy@npm:4.1.9"
|
||||
checksum: 10/8b8e42cc8e4b20d29bd8b312f34b9dbf2e20d4b4cdc24e3bcf6fd4d3b1f49e8924636d2730cca3946fbb45de893dfb531c77b832eb853c2624fdc2b800444e75
|
||||
"@vitest/spy@npm:4.1.8":
|
||||
version: 4.1.8
|
||||
resolution: "@vitest/spy@npm:4.1.8"
|
||||
checksum: 10/53e948d8f5e229e969e704dc8a54fd42ad715b2b18f401592f4bba97dcf33bd4cf01d11af577d4efe42dc2d90c9e6574ec991531fd8f1bdfee916a1dd0828547
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vitest/utils@npm:4.1.9":
|
||||
version: 4.1.9
|
||||
resolution: "@vitest/utils@npm:4.1.9"
|
||||
"@vitest/utils@npm:4.1.8":
|
||||
version: 4.1.8
|
||||
resolution: "@vitest/utils@npm:4.1.8"
|
||||
dependencies:
|
||||
"@vitest/pretty-format": "npm:4.1.9"
|
||||
"@vitest/pretty-format": "npm:4.1.8"
|
||||
convert-source-map: "npm:^2.0.0"
|
||||
tinyrainbow: "npm:^3.1.0"
|
||||
checksum: 10/78f5969fc09b1a95fda9dadd37e84a3a6ead35f66af15ad3b792eef35f80407047803e7afd53df86a8d794f59bf25ffbdc4146099140a3d5f9b51ea061bf2308
|
||||
checksum: 10/13250b9e7825d425cc9a3d22aeb2e8d117c93e96a192138e93d76bfe7d5a391ab3888c5aa9e0394b0314bdff41e441ad7a32b0c0caa00cd202223b88087dcc78
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8506,7 +8506,7 @@ __metadata:
|
||||
"@types/sortablejs": "npm:1.15.9"
|
||||
"@types/tar": "npm:7.0.87"
|
||||
"@vibrant/color": "npm:4.0.4"
|
||||
"@vitest/coverage-v8": "npm:4.1.9"
|
||||
"@vitest/coverage-v8": "npm:4.1.8"
|
||||
"@webcomponents/scoped-custom-element-registry": "npm:0.0.10"
|
||||
"@webcomponents/webcomponentsjs": "npm:2.8.0"
|
||||
babel-loader: "npm:10.1.1"
|
||||
@@ -8591,7 +8591,7 @@ __metadata:
|
||||
typescript: "npm:6.0.3"
|
||||
typescript-eslint: "npm:8.61.0"
|
||||
vite-tsconfig-paths: "npm:6.1.1"
|
||||
vitest: "npm:4.1.9"
|
||||
vitest: "npm:4.1.8"
|
||||
webpack-stats-plugin: "npm:1.1.3"
|
||||
webpackbar: "npm:7.0.0"
|
||||
weekstart: "npm:2.0.0"
|
||||
@@ -13945,17 +13945,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vitest@npm:4.1.9":
|
||||
version: 4.1.9
|
||||
resolution: "vitest@npm:4.1.9"
|
||||
"vitest@npm:4.1.8":
|
||||
version: 4.1.8
|
||||
resolution: "vitest@npm:4.1.8"
|
||||
dependencies:
|
||||
"@vitest/expect": "npm:4.1.9"
|
||||
"@vitest/mocker": "npm:4.1.9"
|
||||
"@vitest/pretty-format": "npm:4.1.9"
|
||||
"@vitest/runner": "npm:4.1.9"
|
||||
"@vitest/snapshot": "npm:4.1.9"
|
||||
"@vitest/spy": "npm:4.1.9"
|
||||
"@vitest/utils": "npm:4.1.9"
|
||||
"@vitest/expect": "npm:4.1.8"
|
||||
"@vitest/mocker": "npm:4.1.8"
|
||||
"@vitest/pretty-format": "npm:4.1.8"
|
||||
"@vitest/runner": "npm:4.1.8"
|
||||
"@vitest/snapshot": "npm:4.1.8"
|
||||
"@vitest/spy": "npm:4.1.8"
|
||||
"@vitest/utils": "npm:4.1.8"
|
||||
es-module-lexer: "npm:^2.0.0"
|
||||
expect-type: "npm:^1.3.0"
|
||||
magic-string: "npm:^0.30.21"
|
||||
@@ -13973,12 +13973,12 @@ __metadata:
|
||||
"@edge-runtime/vm": "*"
|
||||
"@opentelemetry/api": ^1.9.0
|
||||
"@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0
|
||||
"@vitest/browser-playwright": 4.1.9
|
||||
"@vitest/browser-preview": 4.1.9
|
||||
"@vitest/browser-webdriverio": 4.1.9
|
||||
"@vitest/coverage-istanbul": 4.1.9
|
||||
"@vitest/coverage-v8": 4.1.9
|
||||
"@vitest/ui": 4.1.9
|
||||
"@vitest/browser-playwright": 4.1.8
|
||||
"@vitest/browser-preview": 4.1.8
|
||||
"@vitest/browser-webdriverio": 4.1.8
|
||||
"@vitest/coverage-istanbul": 4.1.8
|
||||
"@vitest/coverage-v8": 4.1.8
|
||||
"@vitest/ui": 4.1.8
|
||||
happy-dom: "*"
|
||||
jsdom: "*"
|
||||
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
@@ -14008,8 +14008,8 @@ __metadata:
|
||||
vite:
|
||||
optional: false
|
||||
bin:
|
||||
vitest: ./vitest.mjs
|
||||
checksum: 10/64f9d1a0aae92c493c39822ecae8ec5b5a336fc27166f776d08c01ae79ef1ec5485a1826ef1451bb05df2edaae109894125c2ecceadaa56c17be2690f66f9758
|
||||
vitest: vitest.mjs
|
||||
checksum: 10/b9f1308436717da9558b36e149cac6bab8e3730aa7e90b49f9d7a84ba853e353d8afba7d406dc0abec731fb2a9ea9e92b89aba06b94b1a2802203048b43468af
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user