20230703.0 (#17150)

This commit is contained in:
Bram Kragten 2023-07-03 19:05:09 +02:00 committed by GitHub
commit b309c64d7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 526 additions and 252 deletions

View File

@ -23,6 +23,7 @@ import {
SupervisorObject,
supervisorCollection,
SupervisorKeys,
cleanupSupervisorCollection,
} from "../../src/data/supervisor/supervisor";
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
import { urlSyncMixin } from "../../src/state/url-sync-mixin";
@ -67,6 +68,10 @@ export class SupervisorBaseElement extends urlSyncMixin(
this._unsubs[unsub]();
delete this._unsubs[unsub];
});
Object.keys(this._collections).forEach((collection) => {
cleanupSupervisorCollection(this.hass.connection, collection);
});
this._collections = {};
this.removeEventListener(
"supervisor-collection-refresh",
this._handleSupervisorStoreRefreshEvent
@ -114,7 +119,9 @@ export class SupervisorBaseElement extends urlSyncMixin(
private async _handleSupervisorStoreRefreshEvent(ev) {
const collection = ev.detail.collection;
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
this._collections[collection].refresh();
if (collection in this._collections) {
this._collections[collection].refresh();
}
return;
}
@ -129,11 +136,17 @@ export class SupervisorBaseElement extends urlSyncMixin(
if (this._unsubs[collection]) {
this._unsubs[collection]();
}
this._unsubs[collection] = this._collections[collection].subscribe((data) =>
this._updateSupervisor({
[collection]: data,
})
);
try {
this._unsubs[collection] = this._collections[collection].subscribe(
(data) =>
this._updateSupervisor({
[collection]: data,
})
);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
}
}
private async _initSupervisor(): Promise<void> {

View File

@ -52,7 +52,7 @@
"@lit-labs/context": "0.3.3",
"@lit-labs/motion": "1.0.3",
"@lit-labs/virtualizer": "2.0.3",
"@lrnwebcomponents/simple-tooltip": "7.0.10",
"@lrnwebcomponents/simple-tooltip": "7.0.11",
"@material/chips": "=14.0.0-canary.53b3cad2f.0",
"@material/data-table": "=14.0.0-canary.53b3cad2f.0",
"@material/mwc-button": "0.27.0",
@ -78,7 +78,7 @@
"@material/mwc-top-app-bar": "0.27.0",
"@material/mwc-top-app-bar-fixed": "0.27.0",
"@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0",
"@material/web": "=1.0.0-pre.11",
"@material/web": "=1.0.0-pre.12",
"@mdi/js": "7.2.96",
"@mdi/svg": "7.2.96",
"@polymer/app-layout": "3.1.0",
@ -112,7 +112,7 @@
"deep-freeze": "0.0.1",
"fuse.js": "6.6.2",
"google-timezones-json": "1.1.0",
"hls.js": "1.4.6",
"hls.js": "1.4.7",
"home-assistant-js-websocket": "8.1.0",
"idb-keyval": "6.2.1",
"intl-messageformat": "10.5.0",
@ -203,7 +203,7 @@
"esprima": "4.0.1",
"fancy-log": "2.0.0",
"fs-extra": "11.1.1",
"glob": "10.3.0",
"glob": "10.3.1",
"gulp": "4.0.2",
"gulp-flatmap": "1.0.2",
"gulp-json-transform": "0.4.8",
@ -214,7 +214,7 @@
"husky": "8.0.3",
"instant-mocha": "1.5.1",
"jszip": "3.10.1",
"lint-staged": "13.2.2",
"lint-staged": "13.2.3",
"lit-analyzer": "2.0.0-pre.3",
"lodash.template": "4.5.0",
"magic-string": "0.30.0",
@ -236,10 +236,10 @@
"tar": "6.1.15",
"terser-webpack-plugin": "5.3.9",
"ts-lit-plugin": "2.0.0-pre.1",
"typescript": "5.1.3",
"typescript": "5.1.6",
"vinyl-buffer": "1.0.1",
"vinyl-source-stream": "2.0.0",
"webpack": "5.88.0",
"webpack": "5.88.1",
"webpack-cli": "5.1.4",
"webpack-dev-server": "4.15.1",
"webpack-manifest-plugin": "5.0.0",

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
version = "20230630.0"
version = "20230703.0"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"

View File

@ -0,0 +1,27 @@
import memoizeOne from "memoize-one";
import "../../resources/intl-polyfill";
import { FrontendLocaleData } from "../../data/translation";
export const formatListWithAnds = (
locale: FrontendLocaleData,
list: string[]
) => formatConjunctionList(locale).format(list);
export const formatListWithOrs = (locale: FrontendLocaleData, list: string[]) =>
formatDisjunctionList(locale).format(list);
const formatConjunctionList = memoizeOne(
(locale: FrontendLocaleData) =>
new Intl.ListFormat(locale.language, {
style: "long",
type: "conjunction",
})
);
const formatDisjunctionList = memoizeOne(
(locale: FrontendLocaleData) =>
new Intl.ListFormat(locale.language, {
style: "long",
type: "disjunction",
})
);

View File

@ -12,6 +12,7 @@ import {
} from "../common/entity/compute_attribute_display";
import { computeStateDisplay } from "../common/entity/compute_state_display";
import { computeStateName } from "../common/entity/compute_state_name";
import "../resources/intl-polyfill";
import type { HomeAssistant } from "../types";
import { Condition, ForDict, Trigger } from "./automation";
import {
@ -21,7 +22,6 @@ import {
localizeDeviceAutomationTrigger,
} from "./device_automation";
import { EntityRegistryEntry } from "./entity_registry";
import "../resources/intl-polyfill";
import { FrontendLocaleData } from "./translation";
const triggerTranslationBaseKey =

View File

@ -31,6 +31,10 @@ import {
VariablesAction,
WaitForTriggerAction,
} from "./script";
import { formatListWithAnds } from "../common/string/format-list";
const actionTranslationBaseKey =
"ui.panel.config.automation.editor.actions.type";
export const describeAction = <T extends ActionType>(
hass: HomeAssistant,
@ -75,25 +79,8 @@ const tryDescribeAction = <T extends ActionType>(
if (actionType === "service") {
const config = action as ActionTypes["service"];
let base: string | undefined;
if (
config.service_template ||
(config.service && isTemplate(config.service))
) {
base = "Call a service based on a template";
} else if (config.service) {
const [domain, serviceName] = config.service.split(".", 2);
const service = hass.services[domain][serviceName];
base = service
? `${domainToName(hass.localize, domain)}: ${service.name}`
: `Call service: ${config.service}`;
} else {
return "Call a service";
}
const targets: string[] = [];
if (config.target) {
const targets: string[] = [];
for (const [key, label] of Object.entries({
area_id: "areas",
device_id: "devices",
@ -108,7 +95,12 @@ const tryDescribeAction = <T extends ActionType>(
for (const targetThing of keyConf) {
if (isTemplate(targetThing)) {
targets.push(`templated ${label}`);
targets.push(
hass.localize(
`${actionTranslationBaseKey}.service.description.target_template`,
{ name: label }
)
);
break;
} else if (key === "entity_id") {
if (targetThing.includes(".")) {
@ -125,7 +117,11 @@ const tryDescribeAction = <T extends ActionType>(
computeEntityRegistryName(hass, entityReg) || targetThing
);
} else {
targets.push("unknown entity");
targets.push(
hass.localize(
`${actionTranslationBaseKey}.service.description.target_unknown_entity`
)
);
}
}
} else if (key === "device_id") {
@ -133,46 +129,105 @@ const tryDescribeAction = <T extends ActionType>(
if (device) {
targets.push(computeDeviceName(device, hass));
} else {
targets.push("unknown device");
targets.push(
hass.localize(
`${actionTranslationBaseKey}.service.description.target_unknown_device`
)
);
}
} else if (key === "area_id") {
const area = hass.areas[targetThing];
if (area?.name) {
targets.push(area.name);
} else {
targets.push("unknown area");
targets.push(
hass.localize(
`${actionTranslationBaseKey}.service.description.target_unknown_area`
)
);
}
} else {
targets.push(targetThing);
}
}
}
if (targets.length > 0) {
base += ` ${targets.join(", ")}`;
}
}
return base;
if (
config.service_template ||
(config.service && isTemplate(config.service))
) {
return hass.localize(
`${actionTranslationBaseKey}.service.description.service_based_on_template`,
{ targets: formatListWithAnds(hass.locale, targets) }
);
}
if (config.service) {
const [domain, serviceName] = config.service.split(".", 2);
const service = hass.services[domain][serviceName];
return hass.localize(
`${actionTranslationBaseKey}.service.description.service_based_on_name`,
{
name: service
? `${domainToName(hass.localize, domain)}: ${service.name}`
: config.service,
targets: formatListWithAnds(hass.locale, targets),
}
);
}
return hass.localize(
`${actionTranslationBaseKey}.service.description.service`
);
}
if (actionType === "delay") {
const config = action as DelayAction;
let duration: string;
if (typeof config.delay === "number") {
duration = `for ${secondsToDuration(config.delay)!}`;
duration = hass.localize(
`${actionTranslationBaseKey}.delay.description.duration_string`,
{
duration: secondsToDuration(config.delay)!,
}
);
} else if (typeof config.delay === "string") {
duration = isTemplate(config.delay)
? "based on a template"
: `for ${config.delay || "a duration"}`;
? hass.localize(
`${actionTranslationBaseKey}.delay.description.duration_template`
)
: hass.localize(
`${actionTranslationBaseKey}.delay.description.duration_string`,
{
duration:
config.delay ||
hass.localize(
`${actionTranslationBaseKey}.delay.description.duration_unknown`
),
}
);
} else if (config.delay) {
duration = `for ${formatDuration(config.delay)}`;
duration = hass.localize(
`${actionTranslationBaseKey}.delay.description.duration_string`,
{
duration: formatDuration(config.delay),
}
);
} else {
duration = "for a duration";
duration = hass.localize(
`${actionTranslationBaseKey}.delay.description.duration_string`,
{
duration: hass.localize(
`${actionTranslationBaseKey}.delay.description.duration_unknown`
),
}
);
}
return `Delay ${duration}`;
return hass.localize(`${actionTranslationBaseKey}.delay.description.full`, {
duration: duration,
});
}
if (actionType === "activate_scene") {
@ -184,77 +239,139 @@ const tryDescribeAction = <T extends ActionType>(
entityId = config.target?.entity_id || config.entity_id;
}
if (!entityId) {
return "Activate a scene";
return hass.localize(
`${actionTranslationBaseKey}.activate_scene.description.activate_scene`
);
}
const sceneStateObj = entityId ? hass.states[entityId] : undefined;
return `Activate scene ${
sceneStateObj ? computeStateName(sceneStateObj) : entityId
}`;
return hass.localize(
`${actionTranslationBaseKey}.activate_scene.description.activate_scene_with_name`,
{ name: sceneStateObj ? computeStateName(sceneStateObj) : entityId }
);
}
if (actionType === "play_media") {
const config = action as PlayMediaAction;
const entityId = config.target?.entity_id || config.entity_id;
const mediaStateObj = entityId ? hass.states[entityId] : undefined;
return `Play ${
config.metadata.title || config.data.media_content_id || "media"
} on ${
mediaStateObj
? computeStateName(mediaStateObj)
: entityId || "a media player"
}`;
return hass.localize(
`${actionTranslationBaseKey}.play_media.description.full`,
{
hasMedia: config.metadata.title || config.data.media_content_id,
media: config.metadata.title || config.data.media_content_id,
hasMediaPlayer: mediaStateObj ? true : entityId !== undefined,
mediaPlayer: mediaStateObj ? computeStateName(mediaStateObj) : entityId,
}
);
}
if (actionType === "wait_for_trigger") {
const config = action as WaitForTriggerAction;
const triggers = ensureArray(config.wait_for_trigger);
if (!triggers || triggers.length === 0) {
return "Wait for a trigger";
return hass.localize(
`${actionTranslationBaseKey}.wait_for_trigger.description.wait_for_a_trigger`
);
}
return `Wait for ${triggers
.map((trigger) => describeTrigger(trigger, hass, entityRegistry))
.join(", ")}`;
const triggerNames = triggers.map((trigger) =>
describeTrigger(trigger, hass, entityRegistry)
);
return hass.localize(
`${actionTranslationBaseKey}.wait_for_trigger.description.wait_for_triggers_with_name`,
{ triggers: formatListWithAnds(hass.locale, triggerNames) }
);
}
if (actionType === "variables") {
const config = action as VariablesAction;
return `Define variables ${Object.keys(config.variables).join(", ")}`;
return hass.localize(
`${actionTranslationBaseKey}.variables.description.full`,
{
names: formatListWithAnds(hass.locale, Object.keys(config.variables)),
}
);
}
if (actionType === "fire_event") {
const config = action as EventAction;
if (isTemplate(config.event)) {
return "Fire event based on a template";
return hass.localize(
`${actionTranslationBaseKey}.event.description.full`,
{
name: hass.localize(
`${actionTranslationBaseKey}.event.description.template`
),
}
);
}
return `Fire event ${config.event}`;
return hass.localize(`${actionTranslationBaseKey}.event.description.full`, {
name: config.event,
});
}
if (actionType === "wait_template") {
return "Wait for a template to render true";
}
if (actionType === "check_condition") {
return describeCondition(action as Condition, hass, entityRegistry);
return hass.localize(
`${actionTranslationBaseKey}.wait_template.description.full`
);
}
if (actionType === "stop") {
const config = action as StopAction;
return `Stop${config.stop ? ` because: ${config.stop}` : ""}`;
return hass.localize(`${actionTranslationBaseKey}.stop.description.full`, {
hasReason: config.stop !== undefined,
reason: config.stop,
});
}
if (actionType === "if") {
const config = action as IfAction;
return `Perform an action if: ${
!config.if
? ""
: typeof config.if === "string"
? config.if
: ensureArray(config.if).length > 1
? `${ensureArray(config.if).length} conditions`
: ensureArray(config.if).length
? describeCondition(ensureArray(config.if)[0], hass, entityRegistry)
: ""
}${config.else ? " (or else!)" : ""}`;
let ifConditions: string[] = [];
if (Array.isArray(config.if)) {
const conditions = ensureArray(config.if);
conditions.forEach((condition) => {
ifConditions.push(describeCondition(condition, hass, entityRegistry));
});
} else {
ifConditions = [config.if];
}
let elseActions: string[] = [];
if (config.else) {
if (Array.isArray(config.else)) {
const actions = ensureArray(config.else);
actions.forEach((currentAction) => {
elseActions.push(
describeAction(hass, entityRegistry, currentAction, undefined)
);
});
} else {
elseActions = [
describeAction(hass, entityRegistry, config.else, undefined),
];
}
}
let thenActions: string[] = [];
if (Array.isArray(config.then)) {
const actions = ensureArray(config.then);
actions.forEach((currentAction) => {
thenActions.push(
describeAction(hass, entityRegistry, currentAction, undefined)
);
});
} else {
thenActions = [
describeAction(hass, entityRegistry, config.then, undefined),
];
}
return hass.localize(`${actionTranslationBaseKey}.if.description.full`, {
hasElse: config.else !== undefined,
action: formatListWithAnds(hass.locale, thenActions),
conditions: formatListWithAnds(hass.locale, ifConditions),
elseAction: formatListWithAnds(hass.locale, elseActions),
});
}
if (actionType === "choose") {
@ -262,42 +379,64 @@ const tryDescribeAction = <T extends ActionType>(
if (config.choose) {
const numActions =
ensureArray(config.choose).length + (config.default ? 1 : 0);
return `Choose between ${numActions} action${
numActions === 1 ? "" : "s"
}`;
return hass.localize(
`${actionTranslationBaseKey}.choose.description.full`,
{ number: numActions }
);
}
return "Choose an action";
return hass.localize(
`${actionTranslationBaseKey}.choose.description.no_action`
);
}
if (actionType === "repeat") {
const config = action as RepeatAction;
let base = "Repeat an action";
let chosenAction = "";
if ("count" in config.repeat) {
const count = config.repeat.count;
base += ` ${count} time${Number(count) === 1 ? "" : "s"}`;
chosenAction = hass.localize(
`${actionTranslationBaseKey}.repeat.description.count`,
{ count: count }
);
} else if ("while" in config.repeat) {
base += ` while ${ensureArray(config.repeat.while)
.map((condition) => describeCondition(condition, hass, entityRegistry))
.join(", ")} is true`;
const conditions = ensureArray(config.repeat.while).map((condition) =>
describeCondition(condition, hass, entityRegistry)
);
chosenAction = hass.localize(
`${actionTranslationBaseKey}.repeat.description.while`,
{ conditions: formatListWithAnds(hass.locale, conditions) }
);
} else if ("until" in config.repeat) {
base += ` until ${ensureArray(config.repeat.until)
.map((condition) => describeCondition(condition, hass, entityRegistry))
.join(", ")} is true`;
const conditions = ensureArray(config.repeat.until).map((condition) =>
describeCondition(condition, hass, entityRegistry)
);
chosenAction = hass.localize(
`${actionTranslationBaseKey}.repeat.description.until`,
{ conditions: formatListWithAnds(hass.locale, conditions) }
);
} else if ("for_each" in config.repeat) {
base += ` for every item: ${ensureArray(config.repeat.for_each)
.map((item) => JSON.stringify(item))
.join(", ")}`;
const items = ensureArray(config.repeat.for_each).map((item) =>
JSON.stringify(item)
);
chosenAction = hass.localize(
`${actionTranslationBaseKey}.repeat.description.for_each`,
{ items: formatListWithAnds(hass.locale, items) }
);
}
return base;
return hass.localize(
`${actionTranslationBaseKey}.repeat.description.full`,
{ chosenAction: chosenAction }
);
}
if (actionType === "check_condition") {
return `Test ${describeCondition(
action as Condition,
hass,
entityRegistry
)}`;
return hass.localize(
`${actionTranslationBaseKey}.check_condition.description.full`,
{
condition: describeCondition(action as Condition, hass, entityRegistry),
}
);
}
if (actionType === "device_action") {
@ -313,7 +452,7 @@ const tryDescribeAction = <T extends ActionType>(
if (localized) {
return localized;
}
const stateObj = hass.states[config.entity_id as string];
const stateObj = hass.states[config.entity_id];
return `${config.type || "Perform action with"} ${
stateObj ? computeStateName(stateObj) : config.entity_id
}`;
@ -322,7 +461,10 @@ const tryDescribeAction = <T extends ActionType>(
if (actionType === "parallel") {
const config = action as ParallelAction;
const numActions = ensureArray(config.parallel).length;
return `Run ${numActions} action${numActions === 1 ? "" : "s"} in parallel`;
return hass.localize(
`${actionTranslationBaseKey}.parallel.description.full`,
{ number: numActions }
);
}
return actionType;

View File

@ -132,3 +132,6 @@ export const getSupervisorEventCollection = (
subscribeSupervisorEventUpdates(connection, store, key),
{ unsubGrace: false }
);
export const cleanupSupervisorCollection = (conn: Connection, key: string) =>
delete conn[`_supervisor${key}Event`];

View File

@ -15,7 +15,6 @@ import {
mdiStopCircleOutline,
} from "@mdi/js";
import deepClone from "deep-clone-simple";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import {
CSSResultGroup,
LitElement,
@ -26,6 +25,7 @@ import {
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { consume } from "@lit-labs/context";
import { storage } from "../../../../common/decorators/storage";
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../../../common/dom/fire_event";
@ -40,10 +40,7 @@ import type { HaYamlEditor } from "../../../../components/ha-yaml-editor";
import { ACTION_TYPES, YAML_ONLY_ACTION_TYPES } from "../../../../data/action";
import { AutomationClipboard } from "../../../../data/automation";
import { validateConfig } from "../../../../data/config";
import {
EntityRegistryEntry,
subscribeEntityRegistry,
} from "../../../../data/entity_registry";
import { EntityRegistryEntry } from "../../../../data/entity_registry";
import {
Action,
NonConditionAction,
@ -73,6 +70,7 @@ import "./types/ha-automation-action-service";
import "./types/ha-automation-action-stop";
import "./types/ha-automation-action-wait_for_trigger";
import "./types/ha-automation-action-wait_template";
import { fullEntitiesContext } from "../../../../data/context";
export const getType = (action: Action | undefined) => {
if (!action) {
@ -137,7 +135,9 @@ export default class HaAutomationActionRow extends LitElement {
})
public _clipboard?: AutomationClipboard;
@state() private _entityReg: EntityRegistryEntry[] = [];
@state()
@consume({ context: fullEntitiesContext, subscribe: true })
_entityReg!: EntityRegistryEntry[];
@state() private _warnings?: string[];
@ -147,14 +147,6 @@ export default class HaAutomationActionRow extends LitElement {
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
public hassSubscribe(): UnsubscribeFunc[] {
return [
subscribeEntityRegistry(this.hass.connection!, (entities) => {
this._entityReg = entities;
}),
];
}
protected willUpdate(changedProperties: PropertyValues) {
if (!changedProperties.has("action")) {
return;

View File

@ -1,11 +1,9 @@
import { consume } from "@lit-labs/context";
import { css, html, LitElement, nothing } from "lit";
import { property, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-chip";
import "../../../../components/ha-chip-set";
import { showAutomationEditor } from "../../../../data/automation";
import { fullEntitiesContext } from "../../../../data/context";
import {
DeviceAction,
DeviceAutomation,
@ -32,11 +30,9 @@ export abstract class HaDeviceAutomationCard<
@property({ attribute: false }) public automations: T[] = [];
@state() public _showSecondary = false;
@property({ attribute: false }) entityReg?: EntityRegistryEntry[];
@state()
@consume({ context: fullEntitiesContext, subscribe: true })
_entityReg!: EntityRegistryEntry[];
@state() public _showSecondary = false;
abstract headerKey: Parameters<typeof this.hass.localize>[0];
@ -67,7 +63,7 @@ export abstract class HaDeviceAutomationCard<
}
protected render() {
if (this.automations.length === 0) {
if (this.automations.length === 0 || !this.entityReg) {
return nothing;
}
const automations = this._showSecondary
@ -89,7 +85,7 @@ export abstract class HaDeviceAutomationCard<
>
${this._localizeDeviceAutomation(
this.hass,
this._entityReg,
this.entityReg!,
automation
)}
</ha-chip>

View File

@ -109,6 +109,7 @@ export class DialogDeviceAutomation extends LitElement {
<ha-device-triggers-card
.hass=${this.hass}
.automations=${this._triggers}
.entityReg=${this._params.entityReg}
></ha-device-triggers-card>
`
: ""}
@ -117,6 +118,7 @@ export class DialogDeviceAutomation extends LitElement {
<ha-device-conditions-card
.hass=${this.hass}
.automations=${this._conditions}
.entityReg=${this._params.entityReg}
></ha-device-conditions-card>
`
: ""}
@ -126,6 +128,7 @@ export class DialogDeviceAutomation extends LitElement {
.hass=${this.hass}
.automations=${this._actions}
.script=${this._params.script}
.entityReg=${this._params.entityReg}
></ha-device-actions-card>
`
: ""}

View File

@ -1,8 +1,10 @@
import { fireEvent } from "../../../../common/dom/fire_event";
import { DeviceRegistryEntry } from "../../../../data/device_registry";
import { EntityRegistryEntry } from "../../../../data/entity_registry";
export interface DeviceAutomationDialogParams {
device: DeviceRegistryEntry;
entityReg: EntityRegistryEntry[];
script?: boolean;
}

View File

@ -20,6 +20,7 @@ import {
import { customElement, property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one";
import { consume } from "@lit-labs/context";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { SENSOR_ENTITIES } from "../../../common/const";
import { computeDomain } from "../../../common/entity/compute_domain";
@ -84,6 +85,7 @@ import {
loadDeviceRegistryDetailDialog,
showDeviceRegistryDetailDialog,
} from "./device-registry-detail/show-dialog-device-registry-detail";
import { fullEntitiesContext } from "../../../data/context";
export interface EntityRegistryStateEntry extends EntityRegistryEntry {
stateName?: string | null;
@ -137,6 +139,10 @@ export class HaConfigDevicePage extends LitElement {
@state() private _deviceAlerts?: DeviceAlert[];
@state()
@consume({ context: fullEntitiesContext, subscribe: true })
_entityReg!: EntityRegistryEntry[];
private _logbookTime = { recent: 86400 };
private _device = memoizeOne(
@ -422,12 +428,13 @@ export class HaConfigDevicePage extends LitElement {
)
: this.hass.localize(
"ui.panel.config.devices.automation.create",
"type",
this.hass.localize(
`ui.panel.config.devices.type.${
device.entry_type || "device"
}`
)
{
type: this.hass.localize(
`ui.panel.config.devices.type.${
device.entry_type || "device"
}`
),
}
)}
.path=${mdiPlusCircle}
></ha-icon-button>
@ -1180,6 +1187,7 @@ export class HaConfigDevicePage extends LitElement {
private _showScriptDialog() {
showDeviceAutomationDialog(this, {
device: this._device(this.deviceId, this.devices)!,
entityReg: this._entityReg,
script: true,
});
}
@ -1187,6 +1195,7 @@ export class HaConfigDevicePage extends LitElement {
private _showAutomationDialog() {
showDeviceAutomationDialog(this, {
device: this._device(this.deviceId, this.devices)!,
entityReg: this._entityReg,
script: false,
});
}

View File

@ -77,10 +77,13 @@ export class HaIntegrationActionCard extends LitElement {
font-weight: 400;
margin-top: 8px;
margin-bottom: 0;
max-width: 100%;
}
h3 {
font-size: 14px;
margin: 0;
max-width: 100%;
text-align: center;
}
.header-button {
position: absolute;

View File

@ -24,8 +24,6 @@ import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
import { computeRTL } from "../../../common/util/compute_rtl";
import "../../../components/ha-card";
import "../../../components/ha-icon-next";
import "../../../components/ha-list-item";
import "../../../components/ha-svg-icon";
import { ConfigEntry, ERROR_STATES } from "../../../data/config_entries";
import type { DeviceRegistryEntry } from "../../../data/device_registry";
@ -114,12 +112,6 @@ export class HaIntegrationCard extends LitElement {
: undefined}
.manifest=${this.manifest}
>
<ha-icon-next
slot="header-button"
.label=${this.hass.localize(
"ui.panel.config.integrations.config_entry.configure"
)}
></ha-icon-next>
</ha-integration-header>
</a>
@ -345,9 +337,6 @@ export class HaIntegrationCard extends LitElement {
text-decoration: none;
color: var(--primary-text-color);
}
a ha-icon-next {
color: var(--secondary-text-color);
}
.icons {
display: flex;
}

View File

@ -1,6 +1,7 @@
import { mdiAlertCircleOutline, mdiAlertOutline } from "@mdi/js";
import { LitElement, TemplateResult, css, html, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../components/ha-icon-next";
import "../../../components/ha-svg-icon";
import { IntegrationManifest, domainToName } from "../../../data/integration";
import { HomeAssistant } from "../../../types";
@ -40,27 +41,34 @@ export class HaIntegrationHeader extends LitElement {
/>
<div class="info">
<div
class="primary ${this.warning || this.error ? "hasError" : ""}"
class="primary ${this.warning || this.error ? "has-secondary" : ""}"
role="heading"
aria-level="1"
>
${domainName}
</div>
${this.error
? html`<div class="error">
<ha-svg-icon .path=${mdiAlertCircleOutline}></ha-svg-icon>${this
.error}
</div>`
? html`
<div class="secondary error">
<ha-svg-icon .path=${mdiAlertCircleOutline}></ha-svg-icon>
<span>${this.error}</span>
</div>
`
: this.warning
? html`<div class="warning">
<ha-svg-icon .path=${mdiAlertOutline}></ha-svg-icon>${this
.warning}
</div>`
? html`
<div class="secondary warning">
<ha-svg-icon .path=${mdiAlertOutline}></ha-svg-icon>
<span>${this.warning}</span>
</div>
`
: nothing}
</div>
<div class="header-button">
<slot name="header-button"></slot>
</div>
<ha-icon-next
class="header-button"
.label=${this.hass.localize(
"ui.panel.config.integrations.config_entry.configure"
)}
></ha-icon-next>
</div>
`;
}
@ -76,12 +84,15 @@ export class HaIntegrationHeader extends LitElement {
static styles = css`
.header {
display: flex;
align-items: center;
position: relative;
padding-top: 16px;
padding-bottom: 16px;
padding-inline-start: 16px;
padding-inline-end: 8px;
direction: var(--direction);
box-sizing: border-box;
min-width: 0;
}
.header img {
margin-inline-start: initial;
@ -91,50 +102,55 @@ export class HaIntegrationHeader extends LitElement {
direction: var(--direction);
}
.header .info {
position: relative;
display: flex;
flex-direction: column;
flex: 1;
align-self: center;
min-width: 0;
}
.primary,
.warning,
.error {
word-wrap: break-word;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
ha-icon-next {
color: var(--secondary-text-color);
}
.primary {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: 16px;
font-weight: 400;
word-break: break-word;
color: var(--primary-text-color);
-webkit-line-clamp: 2;
}
.hasError {
.has-secondary {
-webkit-line-clamp: 1;
font-size: 14px;
}
.warning,
.error {
line-height: 20px;
.secondary {
min-width: 0;
--mdc-icon-size: 20px;
-webkit-line-clamp: 1;
font-size: 0.9em;
font-size: 12px;
display: flex;
flex-direction: row;
}
.secondary > span {
position: relative;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.secondary > ha-svg-icon {
margin-right: 4px;
flex-shrink: 0;
}
.error ha-svg-icon {
margin-right: 4px;
color: var(--error-color);
}
.warning ha-svg-icon {
margin-right: 4px;
color: var(--warning-color);
}
.header-button {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
}
`;
}

View File

@ -336,11 +336,15 @@ class ViewMountDialog extends LitElement {
private async _connectMount() {
this._error = undefined;
this._waiting = true;
const mountData = { ...this._data! };
if (mountData.type === "cifs" && mountData.version === "auto") {
mountData.version = undefined;
}
try {
if (this._existing) {
await updateSupervisorMount(this.hass, this._data!);
await updateSupervisorMount(this.hass, mountData);
} else {
await createSupervisorMount(this.hass, this._data!);
await createSupervisorMount(this.hass, mountData);
}
} catch (err: any) {
this._error = extractApiErrorMessage(err);

View File

@ -21,6 +21,10 @@ import type { LovelaceCard } from "../../types";
import { severityMap } from "../hui-gauge-card";
import type { EnergyCarbonGaugeCardConfig } from "../types";
const FORMAT_OPTIONS = {
maximumFractionDigits: 0,
};
@customElement("hui-energy-carbon-consumed-gauge-card")
class HuiEnergyCarbonGaugeCard
extends SubscribeMixin(LitElement)
@ -129,6 +133,7 @@ class HuiEnergyCarbonGaugeCard
min="0"
max="100"
.value=${value}
.formatOptions=${FORMAT_OPTIONS}
.locale=${this.hass.locale}
label="%"
style=${styleMap({

View File

@ -19,6 +19,10 @@ import type { LovelaceCard } from "../../types";
import { severityMap } from "../hui-gauge-card";
import type { EnergySelfSufficiencyGaugeCardConfig } from "../types";
const FORMAT_OPTIONS = {
maximumFractionDigits: 0,
};
@customElement("hui-energy-self-sufficiency-gauge-card")
class HuiEnergySelfSufficiencyGaugeCard
extends SubscribeMixin(LitElement)
@ -174,8 +178,9 @@ class HuiEnergySelfSufficiencyGaugeCard
min="0"
max="100"
.value=${value}
.locale=${this.hass.locale}
label="%"
.formatOptions=${FORMAT_OPTIONS}
.locale=${this.hass.locale}
style=${styleMap({
"--gauge-color": this._computeSeverity(value),
})}

View File

@ -19,6 +19,10 @@ import type { LovelaceCard } from "../../types";
import { severityMap } from "../hui-gauge-card";
import type { EnergySolarGaugeCardConfig } from "../types";
const FORMAT_OPTIONS = {
maximumFractionDigits: 0,
};
@customElement("hui-energy-solar-consumed-gauge-card")
class HuiEnergySolarGaugeCard
extends SubscribeMixin(LitElement)
@ -109,8 +113,9 @@ class HuiEnergySolarGaugeCard
min="0"
max="100"
.value=${value}
.locale=${this.hass.locale}
label="%"
.formatOptions=${FORMAT_OPTIONS}
.locale=${this.hass.locale}
style=${styleMap({
"--gauge-color": this._computeSeverity(value),
})}

View File

@ -82,12 +82,12 @@ export class HuiGaugeCardEditor
{
name: "min",
default: DEFAULT_MIN,
selector: { number: { mode: "box" } },
selector: { number: { mode: "box", step: "any" } },
},
{
name: "max",
default: DEFAULT_MAX,
selector: { number: { mode: "box" } },
selector: { number: { mode: "box", step: "any" } },
},
],
},
@ -107,15 +107,15 @@ export class HuiGaugeCardEditor
schema: [
{
name: "green",
selector: { number: { mode: "box" } },
selector: { number: { mode: "box", step: "any" } },
},
{
name: "yellow",
selector: { number: { mode: "box" } },
selector: { number: { mode: "box", step: "any" } },
},
{
name: "red",
selector: { number: { mode: "box" } },
selector: { number: { mode: "box", step: "any" } },
},
],
},

View File

@ -2573,25 +2573,50 @@
"label": "Call service",
"response_variable": "Response variable",
"has_optional_response": "This service can return a response, if you want to use the response, enter the name of a variable the response will be saved in",
"has_response": "This service returns a response, enter the name of a variable the response will be saved in"
"has_response": "This service returns a response, enter the name of a variable the response will be saved in",
"description": {
"service_based_on_template": "Call a service based on a template on {targets}",
"service_based_on_name": "Call a service ''{name}'' on {targets}",
"service": "Call a service",
"target_template": "templated {name}",
"target_unknown_entity": "unknown entity",
"target_unknown_device": "unknown device",
"target_unknown_area": "unknown area"
}
},
"play_media": {
"label": "Play media"
"label": "Play media",
"description": {
"full": "Play {hasMedia, select, \n true {{media}} \n other {media}\n } on {hasMediaPlayer, select, \n true {{mediaPlayer}} \n other {a media player}\n }"
}
},
"delay": {
"label": "Wait for time to pass (delay)",
"delay": "Duration"
"delay": "Duration",
"description": {
"full": "Delay {duration}",
"duration_string": "for {string}",
"duration_template": "based on a template",
"duration_unknown": "a duration"
}
},
"wait_template": {
"label": "Wait for a template",
"wait_template": "Wait Template",
"timeout": "Timeout (optional)",
"continue_timeout": "Continue on timeout"
"continue_timeout": "Continue on timeout",
"description": {
"full": "Wait for a template to evaluate to true"
}
},
"wait_for_trigger": {
"label": "Wait for a trigger",
"timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::timeout%]",
"continue_timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::continue_timeout%]"
"continue_timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::continue_timeout%]",
"description": {
"wait_for_a_trigger": "Wait for a trigger",
"wait_for_triggers_with_name": "Wait for ''{triggers}''"
}
},
"condition": {
"label": "Condition"
@ -2599,7 +2624,11 @@
"event": {
"label": "Event",
"event": "[%key:ui::panel::config::automation::editor::triggers::type::event::label%]",
"event_data": "[%key:ui::panel::config::automation::editor::triggers::type::event::event_data%]"
"event_data": "[%key:ui::panel::config::automation::editor::triggers::type::event::event_data%]",
"description": {
"full": "Fire event {name}",
"template": "based on a template"
}
},
"device_id": {
"label": "Device",
@ -2618,7 +2647,11 @@
},
"activate_scene": {
"label": "Scene",
"scene": "Scene"
"scene": "Scene",
"description": {
"activate_scene": "Activate a scene",
"activate_scene_with_name": "Activate scene {name}"
}
},
"repeat": {
"label": "Repeat",
@ -2636,7 +2669,14 @@
"conditions": "Until conditions"
}
},
"sequence": "Actions"
"sequence": "Actions",
"description": {
"full": "Repeat an action {chosenAction}",
"count": "{count} {count, plural,\n one {time}\n other {times}\n}",
"while": "while ''{conditions}'' is true",
"until": "until ''{conditions}'' is true",
"for_each": "for every item: {items}"
}
},
"choose": {
"label": "Choose",
@ -2646,26 +2686,47 @@
"add_option": "Add option",
"remove_option": "Remove option",
"conditions": "Conditions",
"sequence": "Actions"
"sequence": "Actions",
"description": {
"full": "Choose between {number} {number, plural,\n one {action}\n other{actions}\n}",
"no_action": "Choose an action"
}
},
"if": {
"label": "If-then",
"if": "If",
"then": "Then",
"else": "Else",
"add_else": "Add else"
"add_else": "Add else",
"description": {
"full": "Perform ''{action}'' if ''{conditions}''{hasElse, select, \n true { otherwise ''{elseAction}''} \n other {}\n } "
}
},
"stop": {
"label": "Stop",
"stop": "Reason for stopping",
"response_variable": "The name of the variable to use as response",
"error": "Stop because of an unexpected error"
"error": "Stop because of an unexpected error",
"description": {
"full": "Stop {hasReason, select, \n true { because: {reason}} \n other {}\n }"
}
},
"parallel": {
"label": "Run in parallel"
"label": "Run in parallel",
"description": {
"full": "Run {number} {number, plural,\n one {action}\n other {actions}\n} in parallel"
}
},
"variables": {
"label": "Define variables"
"label": "Define variables",
"description": {
"full": "Define variables {names}"
}
},
"check_condition": {
"description": {
"full": "Test {condition}"
}
}
}
}
@ -2782,7 +2843,6 @@
},
"discover_blueprint_tip": "[%key:ui::panel::config::automation::dialog_new::discover_blueprint_tip%]"
},
"editor": {
"alias": "Name",
"icon": "Icon",

View File

@ -2107,12 +2107,12 @@ __metadata:
languageName: node
linkType: hard
"@lrnwebcomponents/simple-tooltip@npm:7.0.10":
version: 7.0.10
resolution: "@lrnwebcomponents/simple-tooltip@npm:7.0.10"
"@lrnwebcomponents/simple-tooltip@npm:7.0.11":
version: 7.0.11
resolution: "@lrnwebcomponents/simple-tooltip@npm:7.0.11"
dependencies:
lit: ^2.7.5
checksum: 4e355b580b21b246fed49d3625e6999777b12d8154b786ab27eeafba6d49d2efa4a49a8aa4e7b5e75874e68a1795f911f295f80eedeaf1ad5fbd633d6efeb7c4
checksum: 95c89d1f6ace6229b8661d953c792cef4d0842cbf4de830505a75f5fef9a312f730a7b0085aa11bb4e8e6c8a94d4c1d3512127d208695274f130e9f360f770b9
languageName: node
linkType: hard
@ -3141,14 +3141,14 @@ __metadata:
languageName: node
linkType: hard
"@material/web@npm:=1.0.0-pre.11":
version: 1.0.0-pre.11
resolution: "@material/web@npm:1.0.0-pre.11"
"@material/web@npm:=1.0.0-pre.12":
version: 1.0.0-pre.12
resolution: "@material/web@npm:1.0.0-pre.12"
dependencies:
lit: ^2.7.4
safevalues: ^0.4.3
tslib: ^2.4.0
checksum: 6c08d5d1b159472032d8a274eb29c22229dbcd29a80c478bbf680906903a9542dab9916d547e40c3b607a0ecfe51484bc8681b8c2f1fcd521b2b20fe23d84a66
checksum: 21132f90e004c84745bd9ba15aacc0ec74ee5c67e8dd610da14220cf0fa129882a82c409094b39226a82f9eaae0c1fbea9a6df07a6a056fc2ef5b771a14b078a
languageName: node
linkType: hard
@ -9156,18 +9156,18 @@ __metadata:
languageName: node
linkType: hard
"glob@npm:10.3.0, glob@npm:^10.2.2":
version: 10.3.0
resolution: "glob@npm:10.3.0"
"glob@npm:10.3.1, glob@npm:^10.2.2":
version: 10.3.1
resolution: "glob@npm:10.3.1"
dependencies:
foreground-child: ^3.1.0
jackspeak: ^2.0.3
minimatch: ^9.0.1
minipass: ^5.0.0 || ^6.0.2
path-scurry: ^1.7.0
path-scurry: ^1.10.0
bin:
glob: dist/cjs/src/bin.js
checksum: 6fa4ac0a86ffec1c5715a2e6fbdd63e1e7f1c2c8f5db08cc3256cdfcb81093678e7c80a3d100b502a1b9d141369ecf87bc24fe2bcb72acec7b14626d358a4eb0
checksum: 19c8c2805658b1002fecf0722cd609a33153d756a0d5260676bd0e9c5e6ef889ec9cce6d3dac0411aa90bce8de3d14f25b6f5589a3292582cccbfeddd0e98cc4
languageName: node
linkType: hard
@ -9578,10 +9578,10 @@ __metadata:
languageName: node
linkType: hard
"hls.js@npm:1.4.6":
version: 1.4.6
resolution: "hls.js@npm:1.4.6"
checksum: 7a44107c92e52859bfd5a37b6ea647cfea20848466286c1280b2cf956cfaccf8131fa54867cd8edfb60042a238025fb8788263fd9dfb9d1798ddbdc08f5aab50
"hls.js@npm:1.4.7":
version: 1.4.7
resolution: "hls.js@npm:1.4.7"
checksum: ca58d97d49048fa6f437b834b807d26f5b47750aae57a573f179155e63e39159aa304f3ef13504b42c19969984918b17557e9311a779b0b04641bd6b668b45db
languageName: node
linkType: hard
@ -9622,7 +9622,7 @@ __metadata:
"@lit-labs/context": 0.3.3
"@lit-labs/motion": 1.0.3
"@lit-labs/virtualizer": 2.0.3
"@lrnwebcomponents/simple-tooltip": 7.0.10
"@lrnwebcomponents/simple-tooltip": 7.0.11
"@material/chips": =14.0.0-canary.53b3cad2f.0
"@material/data-table": =14.0.0-canary.53b3cad2f.0
"@material/mwc-button": 0.27.0
@ -9648,7 +9648,7 @@ __metadata:
"@material/mwc-top-app-bar": 0.27.0
"@material/mwc-top-app-bar-fixed": 0.27.0
"@material/top-app-bar": =14.0.0-canary.53b3cad2f.0
"@material/web": =1.0.0-pre.11
"@material/web": =1.0.0-pre.12
"@mdi/js": 7.2.96
"@mdi/svg": 7.2.96
"@octokit/auth-oauth-device": 5.0.2
@ -9728,7 +9728,7 @@ __metadata:
fancy-log: 2.0.0
fs-extra: 11.1.1
fuse.js: 6.6.2
glob: 10.3.0
glob: 10.3.1
google-timezones-json: 1.1.0
gulp: 4.0.2
gulp-flatmap: 1.0.2
@ -9736,7 +9736,7 @@ __metadata:
gulp-merge-json: 2.1.2
gulp-rename: 2.0.0
gulp-zopfli-green: 6.0.1
hls.js: 1.4.6
hls.js: 1.4.7
home-assistant-js-websocket: 8.1.0
html-minifier-terser: 7.2.0
husky: 8.0.3
@ -9747,7 +9747,7 @@ __metadata:
jszip: 3.10.1
leaflet: 1.9.4
leaflet-draw: 1.0.4
lint-staged: 13.2.2
lint-staged: 13.2.3
lit: 2.7.5
lit-analyzer: 2.0.0-pre.3
lodash.template: 4.5.0
@ -9785,7 +9785,7 @@ __metadata:
ts-lit-plugin: 2.0.0-pre.1
tsparticles-engine: 2.10.1
tsparticles-preset-links: 2.10.1
typescript: 5.1.3
typescript: 5.1.6
unfetch: 5.0.0
vinyl-buffer: 1.0.1
vinyl-source-stream: 2.0.0
@ -9793,7 +9793,7 @@ __metadata:
vis-network: 9.1.6
vue: 2.7.14
vue2-daterange-picker: 0.6.8
webpack: 5.88.0
webpack: 5.88.1
webpack-cli: 5.1.4
webpack-dev-server: 4.15.1
webpack-manifest-plugin: 5.0.0
@ -11309,9 +11309,9 @@ __metadata:
languageName: node
linkType: hard
"lint-staged@npm:13.2.2":
version: 13.2.2
resolution: "lint-staged@npm:13.2.2"
"lint-staged@npm:13.2.3":
version: 13.2.3
resolution: "lint-staged@npm:13.2.3"
dependencies:
chalk: 5.2.0
cli-truncate: ^3.1.0
@ -11328,7 +11328,7 @@ __metadata:
yaml: ^2.2.2
bin:
lint-staged: bin/lint-staged.js
checksum: f34f6e2e85e827364658ab8717bf8b35239473c2d4959d746b053a4cf158ac657348444c755820a8ef3eac2d4753a37c52e9db3e201ee20b085f26d2f2fbc9ed
checksum: ff51a1e33072f488b28b938ed47323816a1ff278ef6d0e5cbe1704b292773a6c8ce945b504eae3a9b5702917a979523a741f17023e16077bd5fa35be687cc067
languageName: node
linkType: hard
@ -11622,10 +11622,10 @@ __metadata:
languageName: node
linkType: hard
"lru-cache@npm:^9.1.1":
version: 9.1.2
resolution: "lru-cache@npm:9.1.2"
checksum: d3415634be3908909081fc4c56371a8d562d9081eba70543d86871b978702fffd0e9e362b83921b27a29ae2b37b90f55675aad770a54ac83bb3e4de5049d4b15
"lru-cache@npm:^9.1.1 || ^10.0.0":
version: 10.0.0
resolution: "lru-cache@npm:10.0.0"
checksum: 18f101675fe283bc09cda0ef1e3cc83781aeb8373b439f086f758d1d91b28730950db785999cd060d3c825a8571c03073e8c14512b6655af2188d623031baf50
languageName: node
linkType: hard
@ -12954,13 +12954,13 @@ __metadata:
languageName: node
linkType: hard
"path-scurry@npm:^1.7.0":
version: 1.9.2
resolution: "path-scurry@npm:1.9.2"
"path-scurry@npm:^1.10.0":
version: 1.10.0
resolution: "path-scurry@npm:1.10.0"
dependencies:
lru-cache: ^9.1.1
lru-cache: ^9.1.1 || ^10.0.0
minipass: ^5.0.0 || ^6.0.2
checksum: 92888dfb68e285043c6d3291c8e971d5d2bc2f5082f4d7b5392896f34be47024c9d0a8b688dd7ae6d125acc424699195474927cb4f00049a9b1ec7c4256fa8e0
checksum: 3b66a4a6ab66e45755b577c966ecf0da92d3e068b3c992d8f69aa2cc908ef4eda9358253e9b4f86cad43d3ad810ec445be164105975f5cb3fdab68459c59dc6e
languageName: node
linkType: hard
@ -15428,13 +15428,13 @@ __metadata:
languageName: node
linkType: hard
"typescript@npm:5.1.3":
version: 5.1.3
resolution: "typescript@npm:5.1.3"
"typescript@npm:5.1.6":
version: 5.1.6
resolution: "typescript@npm:5.1.6"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: d9d51862d98efa46534f2800a1071a613751b1585dc78884807d0c179bcd93d6e9d4012a508e276742f5f33c480adefc52ffcafaf9e0e00ab641a14cde9a31c7
checksum: b2f2c35096035fe1f5facd1e38922ccb8558996331405eb00a5111cc948b2e733163cc22fab5db46992aba7dd520fff637f2c1df4996ff0e134e77d3249a7350
languageName: node
linkType: hard
@ -15448,13 +15448,13 @@ __metadata:
languageName: node
linkType: hard
"typescript@patch:typescript@5.1.3#~builtin<compat/typescript>":
version: 5.1.3
resolution: "typescript@patch:typescript@npm%3A5.1.3#~builtin<compat/typescript>::version=5.1.3&hash=5da071"
"typescript@patch:typescript@5.1.6#~builtin<compat/typescript>":
version: 5.1.6
resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin<compat/typescript>::version=5.1.6&hash=5da071"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 6f0a9dca6bf4ce9dcaf4e282aade55ef4c56ecb5fb98d0a4a5c0113398815aea66d871b5611e83353e5953a19ed9ef103cf5a76ac0f276d550d1e7cd5344f61e
checksum: f53bfe97f7c8b2b6d23cf572750d4e7d1e0c5fff1c36d859d0ec84556a827b8785077bc27676bf7e71fae538e517c3ecc0f37e7f593be913d884805d931bc8be
languageName: node
linkType: hard
@ -16135,9 +16135,9 @@ __metadata:
languageName: node
linkType: hard
"webpack@npm:5.88.0":
version: 5.88.0
resolution: "webpack@npm:5.88.0"
"webpack@npm:5.88.1":
version: 5.88.1
resolution: "webpack@npm:5.88.1"
dependencies:
"@types/eslint-scope": ^3.7.3
"@types/estree": ^1.0.0
@ -16168,7 +16168,7 @@ __metadata:
optional: true
bin:
webpack: bin/webpack.js
checksum: 9fd1568b34ec2e99ba97c8509a15ab2576ec80c396e7015551ec814b24cfc11de173acba3e114dafe95f1a6d460781b09d6201e6a1fb15110e1d01a09f61a283
checksum: 726e7e05ab2e7c142609a673dd6aa1a711ed97f349418a2a393d650c5ddad172d191257f60e1e37f6b2a77261571c202aabd5ce9240791a686774f0801cf5ec2
languageName: node
linkType: hard