Basic configuration upgrade support.

This commit is contained in:
Dermot Duffy
2021-11-06 10:11:12 -07:00
parent 80218957b6
commit be76d5bb24
8 changed files with 462 additions and 147 deletions
+270 -136
View File
@@ -4,15 +4,40 @@ import { customElement, property, state } from 'lit/decorators.js';
import { HomeAssistant, LovelaceCardEditor, fireEvent } from 'custom-card-helpers';
import { localize } from './localize/localize.js';
import {
FrigateCardConfig,
frigateCardConfigDefaults,
frigateCardConfigSchema,
} from './types.js';
import { frigateCardConfigDefaults, RawFrigateCardConfig } from './types.js';
import frigate_card_editor_style from './scss/editor.scss';
import {
copyConfig,
deleteConfigValue,
getConfigValue,
isConfigUpgradeable,
setConfigValue,
trimConfig,
upgradeConfig,
} from './config-mgmt.js';
const options = {
interface EditorOptionsSet {
icon: string;
name: string;
secondary: string;
show: boolean;
}
interface EditorOptions {
[setName: string]: EditorOptionsSet;
}
interface EditorOptionTarget {
configValue: string;
checked?: boolean;
value?: string;
}
interface EditorOptionSetTarget {
optionSetName: string;
}
const options: EditorOptions = {
basic: {
icon: 'cog',
name: localize('editor.basic'),
@@ -58,7 +83,7 @@ const options = {
dimensions: {
icon: 'aspect-ratio',
name: localize('editor.dimensions'),
secondary: localize('editor.dimensions'),
secondary: localize('editor.dimensions_secondary'),
show: false,
},
};
@@ -66,16 +91,18 @@ const options = {
@customElement('frigate-card-editor')
export class FrigateCardEditor extends LitElement implements LovelaceCardEditor {
@property({ attribute: false }) public hass?: HomeAssistant;
@state() private _config?: FrigateCardConfig;
@state() private _toggle?: boolean;
@state() private _helpers?: any;
private _initialized = false;
@state() protected _config?: RawFrigateCardConfig;
@state() protected _helpers?: any;
protected _initialized = false;
protected _configUpgradeable = false;
public setConfig(config: FrigateCardConfig): void {
public setConfig(config: RawFrigateCardConfig): void {
// Note: This does not use Zod to parse the configuration, so it may be
// partially or completely invalid. It's more useful to have a partially
// valid configuration here, to allow the user to fix the broken parts.
// valid configuration here, to allow the user to fix the broken parts. As
// such, RawFrigateCardConfig is used as the type.
this._config = config;
this._configUpgradeable = isConfigUpgradeable(config);
this.loadCardHelpers();
}
@@ -102,7 +129,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
}
protected render(): TemplateResult | void {
if (!this.hass || !this._helpers) {
if (!this.hass || !this._helpers || !this._config) {
return html``;
}
@@ -111,11 +138,9 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
this._helpers.importMoreInfoControl('climate');
const cameraEntities = this._getEntities('camera');
const webrtcCameraEntity =
this._config?.live?.webrtc && (this._config?.live.webrtc as any).entity
? (this._config?.live.webrtc as any).entity
: '';
const webrtcCameraEntity = String(
getConfigValue(this._config, 'live.webrtc.entity', ''),
);
const viewModes = {
'': '',
@@ -172,8 +197,35 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
const defaults = frigateCardConfigDefaults;
return html`
${this._configUpgradeable
? html` <div class="upgrade">
<span>${localize('editor.upgrade_available')}</span>
<span>
<mwc-button
raised
label="${localize('editor.upgrade')}"
@click=${() => {
if (this._config) {
const upgradedConfig = copyConfig(this._config);
upgradeConfig(upgradedConfig);
this._config = upgradedConfig;
fireEvent(this, 'config-changed', { config: this._config });
this.requestUpdate();
}
}}
>
</mwc-button>
</span>
</div>
<br />`
: html``}
<div class="card-config">
<div class="option" @click=${this._toggleOption} .option=${'basic'}>
<div
class="option"
@click=${this._toggleOptionHandler}
.optionSetName=${'basic'}
>
<div class="row">
<ha-icon .icon=${`mdi:${options.basic.icon}`}></ha-icon>
<div class="title">${options.basic.name}</div>
@@ -185,13 +237,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
<div class="values">
<paper-dropdown-menu
label=${localize('config.camera_entity')}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
.configValue=${'camera_entity'}
>
<paper-listbox
slot="dropdown-content"
.selected=${cameraEntities.indexOf(
this._config?.camera_entity || '',
String(getConfigValue(this._config, 'camera_entity', '')),
)}
>
${cameraEntities.map((entity) => {
@@ -202,7 +254,11 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
</div>
`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'frigate'}>
<div
class="option"
@click=${this._toggleOptionHandler}
.optionSetName=${'frigate'}
>
<div class="row">
<ha-icon .icon=${`mdi:${options.frigate.icon}`}></ha-icon>
<div class="title">${options.frigate.name}</div>
@@ -214,38 +270,38 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
<div class="values">
<paper-input
label=${localize('config.frigate.camera_name')}
.value=${this._config?.frigate?.camera_name || ''}
.value=${getConfigValue(this._config, 'frigate.camera_name', '')}
.configValue=${'frigate.camera_name'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
<paper-input
label=${localize('config.frigate.url')}
.value=${this._config?.frigate?.url || ''}
.value=${getConfigValue(this._config, 'frigate.url', '')}
.configValue=${'frigate.url'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
<paper-input
.label=${localize('config.frigate.label')}
.value=${this._config?.frigate?.label || ''}
.value=${getConfigValue(this._config, 'frigate.label', '')}
.configValue=${'frigate.label'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
<paper-input
.label=${localize('config.frigate.zone')}
.value=${this._config?.frigate?.zone || ''}
.value=${getConfigValue(this._config, 'frigate.zone', '')}
.configValue=${'frigate.zone'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
<paper-input
label=${localize('config.frigate.client_id')}
.value=${this._config?.frigate?.client_id || ''}
.value=${getConfigValue(this._config, 'frigate.client_id', '')}
.configValue=${'frigate.client_id'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
</div>
`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'view'}>
<div class="option" @click=${this._toggleOptionHandler} .optionSetName=${'view'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.view.icon}`}></ha-icon>
<div class="title">${options.view.name}</div>
@@ -257,13 +313,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
<div class="values">
<paper-dropdown-menu
label=${localize('config.view.default')}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
.configValue=${'view.default'}
>
<paper-listbox
slot="dropdown-content"
.selected=${Object.keys(viewModes).indexOf(
this._config?.view?.default || '',
String(getConfigValue(this._config, 'view.default', '')),
)}
>
${Object.keys(viewModes).map((key) => {
@@ -277,16 +333,14 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
label=${localize('config.view.timeout')}
prevent-invalid-input
allowed-pattern="[0-9]"
.value=${this._config?.view?.timeout
? String(this._config?.view?.timeout)
: ''}
.value=${getConfigValue(this._config, 'view.timeout', '')}
.configValue=${'view.timeout'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
</div>
`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'menu'}>
<div class="option" @click=${this._toggleOptionHandler} .optionSetName=${'menu'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.menu.icon}`}></ha-icon>
<div class="title">${options.menu.name}</div>
@@ -298,13 +352,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
<div class="values">
<paper-dropdown-menu
.label=${localize('config.menu.mode')}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
.configValue=${'menu.mode'}
>
<paper-listbox
slot="dropdown-content"
.selected=${Object.keys(menuModes).indexOf(
this._config?.menu?.mode || '',
String(getConfigValue(this._config, 'menu.mode', '')),
)}
>
${Object.keys(menuModes).map((key) => {
@@ -316,9 +370,9 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
</paper-dropdown-menu>
<paper-input
label=${localize('config.menu.button_size')}
.value=${this._config?.menu?.button_size || ''}
.value=${getConfigValue(this._config, 'menu.button_size', '')}
.configValue=${'menu.button_size'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
<ha-formfield
.label=${localize('editor.show_button') +
@@ -326,10 +380,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
localize('config.menu.buttons.frigate')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.frigate ??
defaults.menu.buttons.frigate}
.checked="${getConfigValue(
this._config,
'menu.buttons.frigate',
defaults.menu.buttons.frigate,
)},"
.configValue=${'menu.buttons.frigate'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<ha-formfield
@@ -338,10 +395,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
localize('config.view.views.live')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.live ??
defaults.menu.buttons.live}
.checked=${getConfigValue(
this._config,
'menu.buttons.live',
defaults.menu.buttons.live,
)}
.configValue=${'menu.buttons.live'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<ha-formfield
@@ -350,10 +410,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
localize('config.view.views.clips')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.clips ??
defaults.menu.buttons.clips}
.checked=${getConfigValue(
this._config,
'menu.buttons.clips',
defaults.menu.buttons.clips,
)}
.configValue=${'menu.buttons.clips'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<ha-formfield
@@ -362,10 +425,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
localize('config.view.views.snapshots')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.snapshots ??
defaults.menu.buttons.snapshots}
.checked=${getConfigValue(
this._config,
'menu.buttons.snapshots',
defaults.menu.buttons.snapshots,
)}
.configValue=${'menu.buttons.snapshots'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<ha-formfield
@@ -374,10 +440,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
localize('config.view.views.image')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.image ??
defaults.menu.buttons.image}
.checked=${getConfigValue(
this._config,
'menu.buttons.image',
defaults.menu.buttons.image,
)}
.configValue=${'menu.buttons.image'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<ha-formfield
@@ -386,10 +455,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
localize('config.menu.buttons.download')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.download ??
defaults.menu.buttons.download}
.checked=${getConfigValue(
this._config,
'menu.buttons.download',
defaults.menu.buttons.download,
)}
.configValue=${'menu.buttons.download'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<ha-formfield
@@ -398,10 +470,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
localize('config.menu.buttons.frigate_ui')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.frigate_ui ??
defaults.menu.buttons.frigate_ui}
.checked=${getConfigValue(
this._config,
'menu.buttons.frigate_ui',
defaults.menu.buttons.frigate_ui,
)}
.configValue=${'menu.buttons.frigate_ui'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<ha-formfield
@@ -410,16 +485,19 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
localize('config.menu.buttons.fullscreen')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.fullscreen ??
defaults.menu.buttons.fullscreen}
.checked=${getConfigValue(
this._config,
'menu.buttons.fullscreen',
defaults.menu.buttons.fullscreen,
)}
.configValue=${'menu.buttons.fullscreen'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
</div>
`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'live'}>
<div class="option" @click=${this._toggleOptionHandler} .optionSetName=${'live'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.live.icon}`}></ha-icon>
<div class="title">${options.live.name}</div>
@@ -432,20 +510,24 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
<br />
<ha-formfield .label=${localize('config.live.preload')}>
<ha-switch
.checked=${this._config?.live?.preload ?? defaults.live.preload}
.checked=${getConfigValue(
this._config,
'live.preload',
defaults.live.preload,
)}
.configValue=${'live.preload'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<paper-dropdown-menu
.label=${localize('config.live.provider')}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
.configValue=${'live.provider'}
>
<paper-listbox
slot="dropdown-content"
.selected=${Object.keys(liveProviders).indexOf(
this._config?.live?.provider || '',
String(getConfigValue(this._config, 'live.provider', '')),
)}
>
${Object.keys(liveProviders).map((key) => {
@@ -457,7 +539,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
</paper-dropdown-menu>
<paper-dropdown-menu
.label=${localize('config.live.webrtc.entity')}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
.configValue=${'live.webrtc.entity'}
>
<paper-listbox
@@ -471,14 +553,18 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
</paper-dropdown-menu>
<paper-input
label=${localize('config.live.webrtc.url')}
.value=${this._config?.live?.webrtc?.url || ''}
.value=${getConfigValue(this._config, 'live.webrtc.url', '')}
.configValue=${'live.webrtc.url'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
</div>
`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'event_viewer'}>
<div
class="option"
@click=${this._toggleOptionHandler}
.optionSetName=${'event_viewer'}
>
<div class="row">
<ha-icon .icon=${`mdi:${options.event_viewer.icon}`}></ha-icon>
<div class="title">${options.event_viewer.name}</div>
@@ -490,29 +576,41 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
<br />
<ha-formfield .label=${localize('config.event_viewer.autoplay_clip')}>
<ha-switch
.checked=${this._config?.event_viewer?.autoplay_clip ??
defaults.event_viewer.autoplay_clip}
.checked=${getConfigValue(
this._config,
'event_viewer.autoplay_clip',
defaults.event_viewer.autoplay_clip,
)}
.configValue=${'event_viewer.autoplay_clip'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<ha-formfield .label=${localize('config.event_viewer.lazy_load')}>
<ha-switch
.checked=${this._config?.event_viewer?.lazy_load ??
defaults.event_viewer.lazy_load}
.checked=${getConfigValue(
this._config,
'event_viewer.lazy_load',
defaults.event_viewer.lazy_load,
)}
.configValue=${'event_viewer.lazy_load'}
@change=${this._valueChanged}
@change=${this._valueChangedHandler}
></ha-switch>
</ha-formfield>
<paper-dropdown-menu
.label=${localize('config.event_viewer.controls.next_previous.style')}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
.configValue=${'event_viewer.controls.next_previous.style'}
>
<paper-listbox
slot="dropdown-content"
.selected=${Object.keys(eventViewerNextPreviousControlStyles).indexOf(
this._config?.event_viewer?.controls?.next_previous?.style || '',
String(
getConfigValue(
this._config,
'event_viewer.controls.next_previous.style',
'',
),
),
)}
>
${Object.keys(eventViewerNextPreviousControlStyles).map((key) => {
@@ -526,13 +624,21 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
</paper-dropdown-menu>
<paper-input
label=${localize('config.event_viewer.controls.next_previous.size')}
.value=${this._config?.event_viewer?.controls?.next_previous?.size || ''}
.value=${getConfigValue(
this._config,
'event_viewer.controls.next_previous.size',
'',
)}
.configValue=${'event_viewer.controls.next_previous.size'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
</div>`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'image'}>
<div
class="option"
@click=${this._toggleOptionHandler}
.optionSetName=${'image'}
>
<div class="row">
<ha-icon .icon=${`mdi:${options.image.icon}`}></ha-icon>
<div class="title">${options.image.name}</div>
@@ -544,15 +650,17 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
<paper-input
label=${localize('config.image.src')}
prevent-invalid-input
.value=${this._config?.image?.src
? String(this._config?.image?.src)
: ''}
.value=${getConfigValue(this._config, 'image.src', '')}
.configValue=${'image.src'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
</div>`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'dimensions'}>
<div
class="option"
@click=${this._toggleOptionHandler}
.optionSetName=${'dimensions'}
>
<div class="row">
<ha-icon .icon=${`mdi:${options.dimensions.icon}`}></ha-icon>
<div class="title">${options.dimensions.name}</div>
@@ -563,13 +671,15 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
? html` <div class="values">
<paper-dropdown-menu
.label=${localize('config.dimensions.aspect_ratio_mode')}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
.configValue=${'dimensions.aspect_ratio_mode'}
>
<paper-listbox
slot="dropdown-content"
.selected=${Object.keys(aspectRatioModes).indexOf(
this._config?.dimensions?.aspect_ratio_mode || '',
String(
getConfigValue(this._config, 'dimensions.aspect_ratio_mode', ''),
),
)}
>
${Object.keys(aspectRatioModes).map((key) => {
@@ -582,11 +692,9 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
<paper-input
label=${localize('config.dimensions.aspect_ratio')}
prevent-invalid-input
.value=${this._config?.dimensions?.aspect_ratio
? String(this._config?.dimensions?.aspect_ratio)
: ''}
.value=${getConfigValue(this._config, 'dimensions.aspect_ratio', '')}
.configValue=${'dimensions.aspect_ratio'}
@value-changed=${this._valueChanged}
@value-changed=${this._valueChangedHandler}
></paper-input>
</div>`
: ''}
@@ -594,69 +702,95 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
`;
}
private _initialize(): void {
/**
* Verify editor is initialized.
*/
protected _initialize(): void {
if (this.hass === undefined) return;
if (this._config === undefined) return;
if (this._helpers === undefined) return;
this._initialized = true;
}
private async loadCardHelpers(): Promise<void> {
/**
* Load card helpers.
*/
protected async loadCardHelpers(): Promise<void> {
this._helpers = await (window as any).loadCardHelpers();
}
private _toggleOption(ev): void {
this._toggleThing(ev, options);
/**
* Handle a toggled set of options.
* @param ev The event triggering the change.
*/
protected _toggleOptionHandler(ev: { target: EditorOptionSetTarget | null }): void {
this._toggleOptionSet(ev, options);
}
private _toggleThing(ev, optionList): void {
const show = !optionList[ev.target.option].show;
for (const [key] of Object.entries(optionList)) {
optionList[key].show = false;
/**
* Toggle display of a set of options (e.g. 'Live')
* @param ev The event triggering the change.
* @param options The EditorOptions object.
*/
protected _toggleOptionSet(
ev: { target: EditorOptionSetTarget | null },
options: EditorOptions,
): void {
if (ev && ev.target) {
const show = !options[ev.target.optionSetName].show;
for (const [key] of Object.entries(options)) {
options[key].show = false;
}
options[ev.target.optionSetName].show = show;
this.requestUpdate();
}
optionList[ev.target.option].show = show;
this._toggle = !this._toggle;
}
private _valueChanged(ev): void {
if (!this._config || !this.hass) {
/**
* Handle a changed option value.
* @param ev Event triggering the change.
* @returns
*/
protected _valueChangedHandler(ev: {
target: (EditorOptionTarget & HTMLElement) | null;
}): void {
const target = ev.target;
if (!this._config || !this.hass || !target) {
return;
}
const target = ev.target;
const value = target.value?.trim();
let key: string = target.configValue;
let value;
if ('checked' in target) {
value = target.checked;
} else {
value = target.value?.trim();
}
const key: string = target.configValue;
if (!key) {
return;
}
// Need to deep copy the config so cannot use Object.assign.
const newConfig = JSON.parse(JSON.stringify(this._config));
let objectTarget = newConfig;
if (key.includes('.')) {
const parts = key.split('.');
objectTarget = parts.slice(0, -1).reduce((obj, key) => {
if (!(key in obj)) {
obj[key] = {};
}
return obj[key];
}, newConfig);
key = parts[parts.length - 1];
}
if (value !== undefined && objectTarget[key] === value) {
return;
} else if (value === '') {
delete objectTarget[key];
const newConfig = copyConfig(this._config);
if (value === '' || typeof value === 'undefined') {
// Don't delete empty properties that are from a dropdown menu. An empty
// property in that context may just be a user-entered value that is not
// in the valid choices in the dropdown. This probably won't end well for
// the user anyway, but having the whole property deleted the moment they
// press a key is very jarring.
if (target.tagName != 'PAPER-DROPDOWN-MENU') {
deleteConfigValue(newConfig, key);
}
} else {
objectTarget[key] = target.checked !== undefined ? target.checked : value;
setConfigValue(newConfig, key, value);
}
trimConfig(newConfig);
this._config = newConfig;
fireEvent(this, 'config-changed', { config: this._config });
}
// Return compiled CSS styles (thus safe to use with unsafeCSS).
/**
* Return compiled CSS styles.
*/
static get styles(): CSSResultGroup {
return unsafeCSS(frigate_card_editor_style);
}