Add editor support.

This commit is contained in:
Dermot Duffy
2021-11-01 22:20:35 -07:00
parent e0daa17834
commit 3761f88170
2 changed files with 352 additions and 287 deletions
+309 -251
View File
@@ -1,8 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
// TODO Add editor for control sizes
// TODO reorganizse editor by section
import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit'; import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit';
import { customElement, property, state } from 'lit/decorators.js'; import { customElement, property, state } from 'lit/decorators.js';
@@ -23,28 +19,46 @@ const options = {
secondary: localize('editor.basic_secondary'), secondary: localize('editor.basic_secondary'),
show: true, show: true,
}, },
optional: { frigate: {
icon: 'tune', icon: 'alpha-f-box',
name: localize('editor.optional'), name: localize('editor.frigate'),
secondary: localize('editor.optional_secondary'), secondary: localize('editor.frigate_secondary'),
show: false, show: false,
}, },
appearance: { view: {
icon: 'palette', icon: 'eye',
name: localize('editor.appearance'), name: localize('editor.view'),
secondary: localize('editor.appearance_secondary'), secondary: localize('editor.view_secondary'),
show: false, show: false,
}, },
webrtc: { menu: {
icon: 'webrtc', icon: 'menu',
name: localize('editor.webrtc'), name: localize('editor.menu'),
secondary: localize('editor.webrtc_secondary'), secondary: localize('editor.menu_secondary'),
show: false, show: false,
}, },
advanced: { live: {
icon: 'cogs', icon: 'cctv',
name: localize('editor.advanced'), name: localize('editor.live'),
secondary: localize('editor.advanced_secondary'), secondary: localize('editor.live_secondary'),
show: false,
},
event_viewer: {
icon: 'filmstrip',
name: localize('editor.event_viewer'),
secondary: localize('editor.event_viewer_secondary'),
show: false,
},
image: {
icon: 'image',
name: localize('editor.image'),
secondary: localize('editor.image_secondary'),
show: false,
},
dimensions: {
icon: 'aspect-ratio',
name: localize('editor.dimensions'),
secondary: localize('editor.dimensions'),
show: false, show: false,
}, },
}; };
@@ -185,12 +199,62 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
})} })}
</paper-listbox> </paper-listbox>
</paper-dropdown-menu> </paper-dropdown-menu>
</div>
`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'frigate'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.frigate.icon}`}></ha-icon>
<div class="title">${options.frigate.name}</div>
</div>
<div class="secondary">${options.frigate.secondary}</div>
</div>
${options.frigate.show
? html`
<div class="values">
<paper-input <paper-input
label=${localize('config.frigate.camera_name')} label=${localize('config.frigate.camera_name')}
.value=${this._config?.frigate?.camera_name || ''} .value=${this._config?.frigate?.camera_name || ''}
.configValue=${'frigate.camera_name'} .configValue=${'frigate.camera_name'}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></paper-input> ></paper-input>
<paper-input
label=${localize('config.frigate.url')}
.value=${this._config?.frigate?.url || ''}
.configValue=${'frigate.url'}
@value-changed=${this._valueChanged}
></paper-input>
<paper-input
.label=${localize('config.frigate.label')}
.value=${this._config?.frigate?.label || ''}
.configValue=${'frigate.label'}
@value-changed=${this._valueChanged}
></paper-input>
<paper-input
.label=${localize('config.frigate.zone')}
.value=${this._config?.frigate?.zone || ''}
.configValue=${'frigate.zone'}
@value-changed=${this._valueChanged}
></paper-input>
<paper-input
label=${localize('config.frigate.client_id')}
.value=${this._config?.frigate?.client_id || ''}
.configValue=${'frigate.client_id'}
@value-changed=${this._valueChanged}
></paper-input>
</div>
`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'view'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.view.icon}`}></ha-icon>
<div class="title">${options.view.name}</div>
</div>
<div class="secondary">${options.view.secondary}</div>
</div>
${options.view.show
? html`
<div class="values">
<paper-dropdown-menu <paper-dropdown-menu
label=${localize('config.view.default')} label=${localize('config.view.default')}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
@@ -209,18 +273,170 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
})} })}
</paper-listbox> </paper-listbox>
</paper-dropdown-menu> </paper-dropdown-menu>
<paper-input
label=${localize('config.view.timeout')}
prevent-invalid-input
allowed-pattern="[0-9]"
.value=${this._config?.view?.timeout
? String(this._config?.view?.timeout)
: ''}
.configValue=${'view.timeout'}
@value-changed=${this._valueChanged}
></paper-input>
</div> </div>
` `
: ''} : ''}
<div class="option" @click=${this._toggleOption} .option=${'optional'}> <div class="option" @click=${this._toggleOption} .option=${'menu'}>
<div class="row"> <div class="row">
<ha-icon .icon=${`mdi:${options.optional.icon}`}></ha-icon> <ha-icon .icon=${`mdi:${options.menu.icon}`}></ha-icon>
<div class="title">${options.optional.name}</div> <div class="title">${options.menu.name}</div>
</div> </div>
<div class="secondary">${options.optional.secondary}</div> <div class="secondary">${options.menu.secondary}</div>
</div> </div>
${options.optional.show ${options.menu.show
? html` <div class="values"> ? html`
<div class="values">
<paper-dropdown-menu
.label=${localize('config.menu.mode')}
@value-changed=${this._valueChanged}
.configValue=${'menu.mode'}
>
<paper-listbox
slot="dropdown-content"
.selected=${Object.keys(menuModes).indexOf(
this._config?.menu?.mode || '',
)}
>
${Object.keys(menuModes).map((key) => {
return html`
<paper-item .label="${key}"> ${menuModes[key]} </paper-item>
`;
})}
</paper-listbox>
</paper-dropdown-menu>
<paper-input
label=${localize('config.menu.button_size')}
.value=${this._config?.menu?.button_size || ''}
.configValue=${'menu.button_size'}
@value-changed=${this._valueChanged}
></paper-input>
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.menu.buttons.frigate')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.frigate ??
defaults.menu.buttons.frigate}
.configValue=${'menu.buttons.frigate'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.view.views.live')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.live ??
defaults.menu.buttons.live}
.configValue=${'menu.buttons.live'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.view.views.clips')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.clips ??
defaults.menu.buttons.clips}
.configValue=${'menu.buttons.clips'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.view.views.snapshots')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.snapshots ??
defaults.menu.buttons.snapshots}
.configValue=${'menu.buttons.snapshots'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.view.views.image')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.image ??
defaults.menu.buttons.image}
.configValue=${'menu.buttons.image'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.menu.buttons.download')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.download ??
defaults.menu.buttons.download}
.configValue=${'menu.buttons.download'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.menu.buttons.frigate_ui')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.frigate_ui ??
defaults.menu.buttons.frigate_ui}
.configValue=${'menu.buttons.frigate_ui'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.menu.buttons.fullscreen')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.fullscreen ??
defaults.menu.buttons.fullscreen}
.configValue=${'menu.buttons.fullscreen'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
</div>
`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'live'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.live.icon}`}></ha-icon>
<div class="title">${options.live.name}</div>
</div>
<div class="secondary">${options.live.secondary}</div>
</div>
${options.live.show
? html`
<div class="values">
<br />
<ha-formfield .label=${localize('config.live.preload')}>
<ha-switch
.checked=${this._config?.live?.preload ?? defaults.live.preload}
.configValue=${'live.preload'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<paper-dropdown-menu <paper-dropdown-menu
.label=${localize('config.live.provider')} .label=${localize('config.live.provider')}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
@@ -239,28 +455,39 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
})} })}
</paper-listbox> </paper-listbox>
</paper-dropdown-menu> </paper-dropdown-menu>
<paper-dropdown-menu
.label=${localize('config.live.webrtc.entity')}
@value-changed=${this._valueChanged}
.configValue=${'live.webrtc.entity'}
>
<paper-listbox
slot="dropdown-content"
.selected=${cameraEntities.indexOf(webrtcCameraEntity)}
>
${cameraEntities.map((entity) => {
return html` <paper-item>${entity}</paper-item> `;
})}
</paper-listbox>
</paper-dropdown-menu>
<paper-input <paper-input
label=${localize('config.frigate.client_id')} label=${localize('config.live.webrtc.url')}
.value=${this._config?.frigate?.client_id || ''} .value=${this._config?.live?.webrtc?.url || ''}
.configValue=${'frigate.client_id'} .configValue=${'live.webrtc.url'}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></paper-input> ></paper-input>
<paper-input </div>
label=${localize('config.view.timeout')} `
prevent-invalid-input
allowed-pattern="[0-9]"
.value=${this._config?.view?.timeout
? String(this._config?.view?.timeout)
: ''} : ''}
.configValue=${'view.timeout'} <div class="option" @click=${this._toggleOption} .option=${'event_viewer'}>
@value-changed=${this._valueChanged} <div class="row">
></paper-input> <ha-icon .icon=${`mdi:${options.event_viewer.icon}`}></ha-icon>
<paper-input <div class="title">${options.event_viewer.name}</div>
label=${localize('config.frigate.url')} </div>
.value=${this._config?.frigate?.url || ''} <div class="secondary">${options.event_viewer.secondary}</div>
.configValue=${'frigate.url'} </div>
@value-changed=${this._valueChanged} ${options.event_viewer.show
></paper-input> ? html` <div class="values">
<br />
<ha-formfield .label=${localize('config.event_viewer.autoplay_clip')}> <ha-formfield .label=${localize('config.event_viewer.autoplay_clip')}>
<ha-switch <ha-switch
.checked=${this._config?.event_viewer?.autoplay_clip ?? .checked=${this._config?.event_viewer?.autoplay_clip ??
@@ -269,13 +496,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
@change=${this._valueChanged} @change=${this._valueChanged}
></ha-switch> ></ha-switch>
</ha-formfield> </ha-formfield>
<ha-formfield .label=${localize('config.live.preload')}>
<ha-switch
.checked=${this._config?.live?.preload ?? defaults.live.preload}
.configValue=${'live.preload'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<ha-formfield .label=${localize('config.event_viewer.lazy_load')}> <ha-formfield .label=${localize('config.event_viewer.lazy_load')}>
<ha-switch <ha-switch
.checked=${this._config?.event_viewer?.lazy_load ?? .checked=${this._config?.event_viewer?.lazy_load ??
@@ -284,35 +504,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
@change=${this._valueChanged} @change=${this._valueChanged}
></ha-switch> ></ha-switch>
</ha-formfield> </ha-formfield>
</div>`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'appearance'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.appearance.icon}`}></ha-icon>
<div class="title">${options.appearance.name}</div>
</div>
<div class="secondary">${options.appearance.secondary}</div>
</div>
${options.appearance.show
? html`<paper-dropdown-menu
.label=${localize('config.menu.mode')}
@value-changed=${this._valueChanged}
.configValue=${'menu.mode'}
>
<paper-listbox
slot="dropdown-content"
.selected=${Object.keys(menuModes).indexOf(
this._config?.menu?.mode || '',
)}
>
${Object.keys(menuModes).map((key) => {
return html`
<paper-item .label="${key}"> ${menuModes[key]} </paper-item>
`;
})}
</paper-listbox>
</paper-dropdown-menu>
<br />
<paper-dropdown-menu <paper-dropdown-menu
.label=${localize('config.event_viewer.controls.next_previous.style')} .label=${localize('config.event_viewer.controls.next_previous.style')}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
@@ -333,7 +524,43 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
})} })}
</paper-listbox> </paper-listbox>
</paper-dropdown-menu> </paper-dropdown-menu>
<br /> <paper-input
label=${localize('config.event_viewer.controls.next_previous.size')}
.value=${this._config?.event_viewer?.controls?.next_previous?.size || ''}
.configValue=${'event_viewer.controls.next_previous.size'}
@value-changed=${this._valueChanged}
></paper-input>
</div>`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'image'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.image.icon}`}></ha-icon>
<div class="title">${options.image.name}</div>
</div>
<div class="secondary">${options.image.secondary}</div>
</div>
${options.image.show
? html` <div class="values">
<paper-input
label=${localize('config.image.src')}
prevent-invalid-input
.value=${this._config?.image?.src
? String(this._config?.image?.src)
: ''}
.configValue=${'image.src'}
@value-changed=${this._valueChanged}
></paper-input>
</div>`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'dimensions'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.dimensions.icon}`}></ha-icon>
<div class="title">${options.dimensions.name}</div>
</div>
<div class="secondary">${options.dimensions.secondary}</div>
</div>
${options.dimensions.show
? html` <div class="values">
<paper-dropdown-menu <paper-dropdown-menu
.label=${localize('config.dimensions.aspect_ratio_mode')} .label=${localize('config.dimensions.aspect_ratio_mode')}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
@@ -352,7 +579,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
})} })}
</paper-listbox> </paper-listbox>
</paper-dropdown-menu> </paper-dropdown-menu>
<br />
<paper-input <paper-input
label=${localize('config.dimensions.aspect_ratio')} label=${localize('config.dimensions.aspect_ratio')}
prevent-invalid-input prevent-invalid-input
@@ -362,174 +588,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
.configValue=${'dimensions.aspect_ratio'} .configValue=${'dimensions.aspect_ratio'}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></paper-input> ></paper-input>
<paper-input
label=${localize('config.image.src')}
prevent-invalid-input
.value=${this._config?.image?.src
? String(this._config?.image?.src)
: ''}
.configValue=${'image.src'}
@value-changed=${this._valueChanged}
></paper-input>
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.menu.buttons.frigate')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.frigate ??
defaults.menu.buttons.frigate}
.configValue=${'menu.buttons.frigate'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<br />
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.view.views.live')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.live ??
defaults.menu.buttons.live}
.configValue=${'menu.buttons.live'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<br />
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.view.views.clips')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.clips ??
defaults.menu.buttons.clips}
.configValue=${'menu.buttons.clips'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<br />
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.view.views.snapshots')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.snapshots ??
defaults.menu.buttons.snapshots}
.configValue=${'menu.buttons.snapshots'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<br />
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.view.views.image')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.image ??
defaults.menu.buttons.image}
.configValue=${'menu.buttons.image'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<br />
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.menu.buttons.download')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.download ??
defaults.menu.buttons.download}
.configValue=${'menu.buttons.download'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<br />
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.menu.buttons.frigate_ui')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.frigate_ui ??
defaults.menu.buttons.frigate_ui}
.configValue=${'menu.buttons.frigate_ui'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<br />
<ha-formfield
.label=${localize('editor.show_button') +
': ' +
localize('config.menu.buttons.fullscreen')}
>
<ha-switch
.checked=${this._config?.menu?.buttons?.fullscreen ??
defaults.menu.buttons.fullscreen}
.configValue=${'menu.buttons.fullscreen'}
@change=${this._valueChanged}
></ha-switch>
</ha-formfield>
<br />`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'advanced'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.advanced.icon}`}></ha-icon>
<div class="title">${options.advanced.name}</div>
</div>
<div class="secondary">${options.advanced.secondary}</div>
</div>
${options.advanced.show
? html` <div class="values">
<paper-input
.label=${localize('config.frigate.label')}
.value=${this._config?.frigate?.label || ''}
.configValue=${'frigate.label'}
@value-changed=${this._valueChanged}
></paper-input>
</div>
<div class="values">
<paper-input
.label=${localize('config.frigate.zone')}
.value=${this._config?.frigate?.zone || ''}
.configValue=${'frigate.zone'}
@value-changed=${this._valueChanged}
></paper-input>
</div>`
: ''}
<div class="option" @click=${this._toggleOption} .option=${'webrtc'}>
<div class="row">
<ha-icon .icon=${`mdi:${options.webrtc.icon}`}></ha-icon>
<div class="title">${options.webrtc.name}</div>
</div>
<div class="secondary">${options.webrtc.secondary}</div>
</div>
${options.webrtc.show
? html` <div class="values">
<paper-dropdown-menu
.label=${localize('config.live.webrtc.entity')}
@value-changed=${this._valueChanged}
.configValue=${'live.webrtc.entity'}
>
<paper-listbox
slot="dropdown-content"
.selected=${cameraEntities.indexOf(webrtcCameraEntity)}
>
${cameraEntities.map((entity) => {
return html` <paper-item>${entity}</paper-item> `;
})}
</paper-listbox>
</paper-dropdown-menu>
<paper-input
label=${localize('config.live.webrtc.url')}
.value=${this._config?.live?.webrtc?.url || ''}
.configValue=${'live.webrtc.url'}
@value-changed=${this._valueChanged}
></paper-input>
</div>` </div>`
: ''} : ''}
</div> </div>
@@ -584,7 +642,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
} }
return obj[key]; return obj[key];
}, newConfig); }, newConfig);
key = parts[parts.length-1]; key = parts[parts.length - 1];
} }
if (value !== undefined && objectTarget[key] === value) { if (value !== undefined && objectTarget[key] === value) {
+22 -15
View File
@@ -15,9 +15,9 @@
"frigate": { "frigate": {
"camera_name": "Frigate camera name (Optional, autodetected from entity)", "camera_name": "Frigate camera name (Optional, autodetected from entity)",
"client_id": "Frigate client id (For >1 Frigate server)", "client_id": "Frigate client id (For >1 Frigate server)",
"label": "Label/object filter", "label": "Frigate label/object filter",
"url": "Frigate server URL", "url": "Frigate server URL",
"zone": "Zone" "zone": "Frigate zone"
}, },
"view": { "view": {
"default": "Default view", "default": "Default view",
@@ -29,15 +29,15 @@
"snapshots": "Snapshots gallery", "snapshots": "Snapshots gallery",
"image": "Static image" "image": "Static image"
}, },
"timeout": "View timeout (seconds)" "timeout": "View timeout secs (before returning to default, 0=never)"
}, },
"event_viewer": { "event_viewer": {
"autoplay_clip": "Autoplay most recent clip", "autoplay_clip": "Autoplay most recent clip (In 'clip' view)",
"lazy_load": "Lazily load event media", "lazy_load": "Lazily load event media",
"controls": { "controls": {
"next_previous": { "next_previous": {
"style": "Event Viewer Next & Previous Control style", "style": "Event Viewer Next & Previous Control style",
"size": "Event Viewer Next & Previous Control size", "size": "Event Viewer Next & Previous Control size (e.g. '48px')",
"styles": { "styles": {
"thumbnails": "Thumbnails", "thumbnails": "Thumbnails",
"chevrons": "Chevrons", "chevrons": "Chevrons",
@@ -86,10 +86,11 @@
"hover-right": "Hover right", "hover-right": "Hover right",
"above": "Above", "above": "Above",
"below": "Below" "below": "Below"
} },
"button_size": "Menu button size (e.g. '40px')"
}, },
"dimensions": { "dimensions": {
"aspect_ratio": "Default aspect ratio", "aspect_ratio": "Default aspect ratio (e.g. '16:9')",
"aspect_ratio_mode": "Aspect ratio mode", "aspect_ratio_mode": "Aspect ratio mode",
"aspect_ratio_modes": { "aspect_ratio_modes": {
"unconstrained": "Unconstrained aspect ratio", "unconstrained": "Unconstrained aspect ratio",
@@ -101,14 +102,20 @@
"editor": { "editor": {
"basic": "Basic", "basic": "Basic",
"basic_secondary": "Basic options for most users", "basic_secondary": "Basic options for most users",
"optional": "Optional", "frigate": "Frigate",
"optional_secondary": "Optional configuration to tweak card behavior", "frigate_secondary": "Frigate server options",
"appearance": "Appearance", "view": "View",
"appearance_secondary": "Appearance of the card", "view_secondary": "Card view options",
"webrtc": "WebRTC", "menu": "Menu",
"webrtc_secondary": "Optional WebRTC parameters", "menu_secondary": "Menu options",
"advanced": "Advanced", "live": "Live",
"advanced_secondary": "Advanced options", "live_secondary": "Live view options",
"event_viewer": "Event viewer",
"event_viewer_secondary": "Event viewer options",
"image": "Image",
"image_secondary": "Static image view options",
"dimensions": "Dimensions",
"dimensions_secondary": "Card dimensions options",
"show_button": "Show button" "show_button": "Show button"
}, },
"error": { "error": {