Update popup design. Add form popups
This commit is contained in:
parent
a641617671
commit
bb7b7fa6ff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -5,7 +5,7 @@
|
|||||||
"dependencies": ["panel_custom", "websocket_api", "http", "frontend", "lovelace"],
|
"dependencies": ["panel_custom", "websocket_api", "http", "frontend", "lovelace"],
|
||||||
"codeowners": [],
|
"codeowners": [],
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
"version": "2.0.0b2",
|
"version": "2.0.0b3",
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"config_flow": true
|
"config_flow": true
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,38 @@ data:
|
|||||||
left_button: Left button
|
left_button: Left button
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Displaying a dashboard card in a popup
|
## Size
|
||||||
|
|
||||||
|
The `size` parameter can be set to `normal`, `wide` and `fullscreen` with results as below (background blur has been exagerated for clarity):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## HTML content
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
service: browser_mod.popup
|
service: browser_mod.popup
|
||||||
data:
|
data:
|
||||||
title: The title
|
title: HTML content
|
||||||
right_button: Right button
|
content: |
|
||||||
left_button: Left button
|
An <b>HTML</b> string.
|
||||||
|
<p> Pretty much any HTML works: <ha-icon icon="mdi:lamp" style="color: red;"></ha-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Dashboard card content
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
service: browser_mod.popup
|
||||||
|
data:
|
||||||
|
title: HTML content
|
||||||
content:
|
content:
|
||||||
type: entities
|
type: entities
|
||||||
entities:
|
entities:
|
||||||
@ -28,10 +50,53 @@ data:
|
|||||||
- light.kitchen_lights
|
- light.kitchen_lights
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Form content
|
||||||
|
`content` can be a list of ha-form schemas and the popup will then contain a form for user input:
|
||||||
|
|
||||||
|
```
|
||||||
|
<ha-form schema>:
|
||||||
|
name: <string>
|
||||||
|
[label: <string>]
|
||||||
|
[default: <any>]
|
||||||
|
selector: <Home Assistant Selector>
|
||||||
|
```
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|-|-|
|
||||||
|
| `name` | A unique parameter name |
|
||||||
|
| `label` | A description of the parameter |
|
||||||
|
| `default` | The default value for the parameter |
|
||||||
|
| `selector` | A [Home Assistant selector](https://www.home-assistant.io/docs/blueprint/selectors) |
|
||||||
|
|
||||||
|
The data from the form will be forwarded as data for any `right_button_action` or `left_button_action` of the popup.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
service: browser_mod.popup
|
||||||
|
data:
|
||||||
|
title: Form content
|
||||||
|
content:
|
||||||
|
- name: parameter_name
|
||||||
|
label: Descriptive name
|
||||||
|
selector:
|
||||||
|
text: null
|
||||||
|
- name: another_parameter
|
||||||
|
label: A number
|
||||||
|
default: 5
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
min: 0
|
||||||
|
max: 10
|
||||||
|
slider: true
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Actionable popups
|
## Actionable popups
|
||||||
|
|
||||||
|
Example of a popup with actions opening more popups or calling Home Assistant services:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
service: browser_mod.popup
|
service: browser_mod.popup
|
||||||
data:
|
data:
|
||||||
@ -62,4 +127,35 @@ data:
|
|||||||
entity_id: light.bed_light
|
entity_id: light.bed_light
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Forward form data
|
||||||
|
|
||||||
|
The following popup would ask the user for a list of rooms to vacuum and then populate the `params` parameter of the `vacuum.send_command` service call from the result:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
service: browser_mod.popup
|
||||||
|
data:
|
||||||
|
title: Where to vacuum?
|
||||||
|
right_button: Go!
|
||||||
|
right_button_action:
|
||||||
|
service: vacuum.send_command
|
||||||
|
data:
|
||||||
|
entity_id: vacuum.xiaomi
|
||||||
|
command: app_segment_clean
|
||||||
|
content:
|
||||||
|
- name: params
|
||||||
|
label: Rooms to clean
|
||||||
|
selector:
|
||||||
|
select:
|
||||||
|
multiple: true
|
||||||
|
options:
|
||||||
|
- label: Kitchen
|
||||||
|
value: 11
|
||||||
|
- label: Living room
|
||||||
|
value: 13
|
||||||
|
- label: Bedroom
|
||||||
|
value: 12
|
||||||
|
```
|
||||||
|
|
||||||
|

|
@ -125,7 +125,7 @@ Display a popup dialog
|
|||||||
service: browser_mod.popup
|
service: browser_mod.popup
|
||||||
data:
|
data:
|
||||||
[title: <string>]
|
[title: <string>]
|
||||||
content: <string / Dashboard card configuration>
|
content: <string / Dashboard card configuration / ha-form schema>
|
||||||
[size: <NORMAL/wide/fullscreen>]
|
[size: <NORMAL/wide/fullscreen>]
|
||||||
[right_button: <string>]
|
[right_button: <string>]
|
||||||
[right_button_action: <service call>]
|
[right_button_action: <service call>]
|
||||||
@ -143,7 +143,7 @@ data:
|
|||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
|`title` | The title of the popup window.|
|
|`title` | The title of the popup window.|
|
||||||
|`content`| HTML or a dashboard card configuration to display.|
|
|`content`| HTML, a dashboard card configuration or ha-form schema to display.|
|
||||||
| `size` | `wide` will make the popup window wider. `fullscreen` will make it cover the entire screen. |
|
| `size` | `wide` will make the popup window wider. `fullscreen` will make it cover the entire screen. |
|
||||||
| `right_button`| The text of the right action button.|
|
| `right_button`| The text of the right action button.|
|
||||||
| `right_button_action`| Action to perform when the right action button is pressed. |
|
| `right_button_action`| Action to perform when the right action button is pressed. |
|
||||||
@ -171,7 +171,9 @@ style:
|
|||||||
|
|
||||||
Note that any Browser Mod services performed as `_action`s here will be performed only on the same Browser as initiated the action unless `browser_id` is given.
|
Note that any Browser Mod services performed as `_action`s here will be performed only on the same Browser as initiated the action unless `browser_id` is given.
|
||||||
|
|
||||||
For usage examples, see [popups.md](popups.md).
|
If a ha-form schema is used for `content` the resulting data will be inserted into the `data` for any `_action`.
|
||||||
|
|
||||||
|
See [popups.md](popups.md) for more information and usage examples.
|
||||||
|
|
||||||
|
|
||||||
## `browser_mod.close_popup`
|
## `browser_mod.close_popup`
|
||||||
|
@ -14,9 +14,7 @@ class BrowserModRegisteredBrowsersCard extends LitElement {
|
|||||||
const browserID = ev.currentTarget.browserID;
|
const browserID = ev.currentTarget.browserID;
|
||||||
|
|
||||||
const unregisterCallback = () => {
|
const unregisterCallback = () => {
|
||||||
console.log(browserID, window.browser_mod.browserID);
|
|
||||||
if (browserID === window.browser_mod.browserID) {
|
if (browserID === window.browser_mod.browserID) {
|
||||||
console.log("Unregister self");
|
|
||||||
window.browser_mod.registered = false;
|
window.browser_mod.registered = false;
|
||||||
} else {
|
} else {
|
||||||
window.browser_mod.connection.sendMessage({
|
window.browser_mod.connection.sendMessage({
|
||||||
|
@ -81,9 +81,9 @@ export const loadHaForm = async () => {
|
|||||||
await loadLoadCardHelpers();
|
await loadLoadCardHelpers();
|
||||||
const helpers = await window.loadCardHelpers();
|
const helpers = await window.loadCardHelpers();
|
||||||
if (!helpers) return;
|
if (!helpers) return;
|
||||||
const card = await helpers.createCardElement({ type: "entity" });
|
const card = await helpers.createCardElement({ type: "button" });
|
||||||
if (!card) return;
|
if (!card) return;
|
||||||
await card.getConfigElement();
|
await card.constructor.getConfigElement();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Loads in ha-config-dashboard which is used to copy styling
|
// Loads in ha-config-dashboard which is used to copy styling
|
||||||
@ -120,3 +120,15 @@ export const loadDeveloperToolsTemplate = async () => {
|
|||||||
await dtRouter?.routerOptions?.routes?.template?.load?.();
|
await dtRouter?.routerOptions?.routes?.template?.load?.();
|
||||||
await customElements.whenDefined("developer-tools-template");
|
await customElements.whenDefined("developer-tools-template");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function throttle(timeout) {
|
||||||
|
return function (target, propertyKey, descriptor) {
|
||||||
|
const fn = descriptor.value;
|
||||||
|
let cooldown = undefined;
|
||||||
|
descriptor.value = function (...rest) {
|
||||||
|
if (cooldown) return;
|
||||||
|
cooldown = setTimeout(() => (cooldown = undefined), timeout);
|
||||||
|
return fn.bind(this)(...rest);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import "./browser-player";
|
import "./browser-player";
|
||||||
|
|
||||||
// import { BrowserModConnection } from "./connection";
|
|
||||||
import { ConnectionMixin } from "./connection";
|
import { ConnectionMixin } from "./connection";
|
||||||
import { ScreenSaverMixin } from "./screensaver";
|
import { ScreenSaverMixin } from "./screensaver";
|
||||||
import { MediaPlayerMixin } from "./mediaPlayer";
|
import { MediaPlayerMixin } from "./mediaPlayer";
|
||||||
@ -19,7 +18,8 @@ import { BrowserIDMixin } from "./browserID";
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
- Fix nomenclature
|
- More pictures for documentation
|
||||||
|
x Fix nomenclature
|
||||||
x Command -> Service
|
x Command -> Service
|
||||||
x Device -> Browser
|
x Device -> Browser
|
||||||
- Popups
|
- Popups
|
||||||
@ -28,6 +28,8 @@ import { BrowserIDMixin } from "./browserID";
|
|||||||
X Timeout
|
X Timeout
|
||||||
X Fullscreen
|
X Fullscreen
|
||||||
x Popup-card
|
x Popup-card
|
||||||
|
x Auto-close
|
||||||
|
x Forms that are forwarded to service calls
|
||||||
x Motion/occupancy tracker
|
x Motion/occupancy tracker
|
||||||
x Information about interaction requirement
|
x Information about interaction requirement
|
||||||
x Information about fullykiosk
|
x Information about fullykiosk
|
||||||
@ -39,29 +41,28 @@ import { BrowserIDMixin } from "./browserID";
|
|||||||
x ll-custom handling
|
x ll-custom handling
|
||||||
- Commands
|
- Commands
|
||||||
x popup
|
x popup
|
||||||
x Auto-close
|
|
||||||
x close_popup
|
x close_popup
|
||||||
x more-info
|
x more-info
|
||||||
x navigate
|
x navigate
|
||||||
- lovelace-reload?
|
o lovelace-reload?
|
||||||
- Not needed
|
o Not needed
|
||||||
x window-reload
|
x window-reload
|
||||||
- screensaver ?
|
o screensaver ?
|
||||||
- Refer to automations instead
|
o Refer to automations instead
|
||||||
x sequence
|
x sequence
|
||||||
x delay
|
x delay
|
||||||
x javascript eval
|
x javascript eval
|
||||||
- toast?
|
o toast?
|
||||||
- Replaced with popups with timeout
|
o Replaced with popups with timeout
|
||||||
x Redesign services to target devices
|
x Redesign services to target devices
|
||||||
x frontend editor for popup cards
|
x frontend editor for popup cards
|
||||||
- also screensavers
|
o also screensavers
|
||||||
- Saved frontend settings
|
x Saved frontend settings
|
||||||
X Framework
|
X Framework
|
||||||
x Save sidebar
|
x Save sidebar
|
||||||
x Kiosk mode
|
x Kiosk mode
|
||||||
x Default dashboard
|
x Default dashboard
|
||||||
- Screensaver?
|
o Screensaver?
|
||||||
x Favicon templates
|
x Favicon templates
|
||||||
x Title templates
|
x Title templates
|
||||||
- Tweaks
|
- Tweaks
|
||||||
@ -69,9 +70,9 @@ import { BrowserIDMixin } from "./browserID";
|
|||||||
x Card-mod preload
|
x Card-mod preload
|
||||||
x Video player
|
x Video player
|
||||||
x Media_seek
|
x Media_seek
|
||||||
- Screensavers
|
o Screensavers
|
||||||
x IMPORTANT: FIX DEFAULT HIDING OF ENTITIES
|
x IMPORTANT: FIX DEFAULT HIDING OF ENTITIES
|
||||||
- NOFIX. Home Assistant bug
|
o NOFIX. Home Assistant bug
|
||||||
X Check functionality with CAST - may need to add frontend part as a lovelace resource
|
X Check functionality with CAST - may need to add frontend part as a lovelace resource
|
||||||
*/
|
*/
|
||||||
export class BrowserMod extends ServicesMixin(
|
export class BrowserMod extends ServicesMixin(
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import { selectTree } from "../helpers";
|
import { selectTree, throttle } from "../helpers";
|
||||||
|
|
||||||
export const MediaPlayerMixin = (SuperClass) => {
|
export const MediaPlayerMixin = (SuperClass) => {
|
||||||
return class MediaPlayerMixinClass extends SuperClass {
|
class MediaPlayerMixinClass extends SuperClass {
|
||||||
public player;
|
public player;
|
||||||
private _audio_player;
|
private _audio_player;
|
||||||
private _video_player;
|
private _video_player;
|
||||||
private _player_enabled;
|
private _player_enabled;
|
||||||
private _player_update_cooldown;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -24,10 +23,10 @@ export const MediaPlayerMixin = (SuperClass) => {
|
|||||||
}
|
}
|
||||||
for (const ev of ["timeupdate"]) {
|
for (const ev of ["timeupdate"]) {
|
||||||
this._audio_player.addEventListener(ev, () =>
|
this._audio_player.addEventListener(ev, () =>
|
||||||
this._player_update_choked()
|
this._player_update_throttled()
|
||||||
);
|
);
|
||||||
this._video_player.addEventListener(ev, () =>
|
this._video_player.addEventListener(ev, () =>
|
||||||
this._player_update_choked()
|
this._player_update_throttled()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,12 +98,8 @@ export const MediaPlayerMixin = (SuperClass) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _player_update_choked() {
|
@throttle(3000)
|
||||||
if (this._player_update_cooldown) return;
|
_player_update_throttled() {
|
||||||
this._player_update_cooldown = window.setTimeout(
|
|
||||||
() => (this._player_update_cooldown = undefined),
|
|
||||||
3000
|
|
||||||
);
|
|
||||||
this._player_update();
|
this._player_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,5 +124,7 @@ export const MediaPlayerMixin = (SuperClass) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
return MediaPlayerMixinClass;
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@ import { LitElement, html, css } from "lit";
|
|||||||
import { property, query } from "lit/decorators.js";
|
import { property, query } from "lit/decorators.js";
|
||||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||||
import { provideHass, loadLoadCardHelpers, hass_base_el } from "../helpers";
|
import { provideHass, loadLoadCardHelpers, hass_base_el } from "../helpers";
|
||||||
|
import { loadHaForm } from "../helpers";
|
||||||
|
|
||||||
class BrowserModPopup extends LitElement {
|
class BrowserModPopup extends LitElement {
|
||||||
@property() open;
|
@property() open;
|
||||||
@ -23,6 +24,7 @@ class BrowserModPopup extends LitElement {
|
|||||||
_timeoutStart;
|
_timeoutStart;
|
||||||
_timeoutTimer;
|
_timeoutTimer;
|
||||||
_resolveClosed;
|
_resolveClosed;
|
||||||
|
_formdata;
|
||||||
|
|
||||||
async closeDialog() {
|
async closeDialog() {
|
||||||
this.open = false;
|
this.open = false;
|
||||||
@ -76,10 +78,30 @@ class BrowserModPopup extends LitElement {
|
|||||||
autoclose = false,
|
autoclose = false,
|
||||||
} = {}
|
} = {}
|
||||||
) {
|
) {
|
||||||
|
this._formdata = undefined;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
this.card = undefined;
|
||||||
if (content && content instanceof HTMLElement) {
|
if (content && content instanceof HTMLElement) {
|
||||||
this.card = undefined;
|
|
||||||
this.content = content;
|
this.content = content;
|
||||||
|
} else if (content && Array.isArray(content)) {
|
||||||
|
loadHaForm();
|
||||||
|
const form: any = document.createElement("ha-form");
|
||||||
|
form.schema = content;
|
||||||
|
form.computeLabel = (s) => s.label ?? s.name;
|
||||||
|
form.hass = window.browser_mod.hass;
|
||||||
|
this._formdata = {};
|
||||||
|
for (const i of content) {
|
||||||
|
if (i.name && i.default !== undefined) {
|
||||||
|
this._formdata[i.name] = i.default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
form.data = this._formdata;
|
||||||
|
provideHass(form);
|
||||||
|
form.addEventListener("value-changed", (ev) => {
|
||||||
|
this._formdata = { ...ev.detail.value };
|
||||||
|
form.data = this._formdata;
|
||||||
|
});
|
||||||
|
this.content = form;
|
||||||
} else if (content && typeof content === "object") {
|
} else if (content && typeof content === "object") {
|
||||||
// Create a card from config in content
|
// Create a card from config in content
|
||||||
this.card = true;
|
this.card = true;
|
||||||
@ -90,7 +112,6 @@ class BrowserModPopup extends LitElement {
|
|||||||
this.content = card;
|
this.content = card;
|
||||||
} else {
|
} else {
|
||||||
// Basic HTML content
|
// Basic HTML content
|
||||||
this.card = undefined;
|
|
||||||
this.content = unsafeHTML(content);
|
this.content = unsafeHTML(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,12 +136,12 @@ class BrowserModPopup extends LitElement {
|
|||||||
async _primary() {
|
async _primary() {
|
||||||
if (this._actions?.dismiss_action) this._actions.dismiss_action = undefined;
|
if (this._actions?.dismiss_action) this._actions.dismiss_action = undefined;
|
||||||
this.dialog?.close();
|
this.dialog?.close();
|
||||||
this._actions?.right_button_action?.();
|
this._actions?.right_button_action?.(this._formdata);
|
||||||
}
|
}
|
||||||
async _secondary() {
|
async _secondary() {
|
||||||
if (this._actions?.dismiss_action) this._actions.dismiss_action = undefined;
|
if (this._actions?.dismiss_action) this._actions.dismiss_action = undefined;
|
||||||
this.dialog?.close();
|
this.dialog?.close();
|
||||||
this._actions?.left_button_action?.();
|
this._actions?.left_button_action?.(this._formdata);
|
||||||
}
|
}
|
||||||
async _dismiss(ev?) {
|
async _dismiss(ev?) {
|
||||||
this.dialog?.close();
|
this.dialog?.close();
|
||||||
@ -150,16 +171,21 @@ class BrowserModPopup extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
${this.title
|
${this.title
|
||||||
? html`
|
? html`
|
||||||
<app-toolbar slot="heading">
|
<div slot="heading">
|
||||||
${this.dismissable
|
<ha-header-bar>
|
||||||
? html`
|
${this.dismissable
|
||||||
<ha-icon-button dialogAction="cancel">
|
? html`
|
||||||
<ha-icon .icon=${"mdi:close"}></ha-icon>
|
<ha-icon-button
|
||||||
</ha-icon-button>
|
dialogAction="cancel"
|
||||||
`
|
slot="navigationIcon"
|
||||||
: ""}
|
>
|
||||||
<div class="main-title">${this.title}</div>
|
<ha-icon .icon=${"mdi:close"}></ha-icon>
|
||||||
</app-toolbar>
|
</ha-icon-button>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
<div slot="title" class="main-title">${this.title}</div>
|
||||||
|
</ha-header-bar>
|
||||||
|
</div>
|
||||||
`
|
`
|
||||||
: html``}
|
: html``}
|
||||||
|
|
||||||
@ -171,6 +197,7 @@ class BrowserModPopup extends LitElement {
|
|||||||
slot="primaryAction"
|
slot="primaryAction"
|
||||||
.label=${this.right_button}
|
.label=${this.right_button}
|
||||||
@click=${this._primary}
|
@click=${this._primary}
|
||||||
|
class="action-button"
|
||||||
></mwc-button>
|
></mwc-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@ -180,6 +207,7 @@ class BrowserModPopup extends LitElement {
|
|||||||
slot="secondaryAction"
|
slot="secondaryAction"
|
||||||
.label=${this.left_button}
|
.label=${this.left_button}
|
||||||
@click=${this._secondary}
|
@click=${this._secondary}
|
||||||
|
class="action-button"
|
||||||
></mwc-button>
|
></mwc-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@ -195,6 +223,7 @@ class BrowserModPopup extends LitElement {
|
|||||||
static get styles() {
|
static get styles() {
|
||||||
return css`
|
return css`
|
||||||
ha-dialog {
|
ha-dialog {
|
||||||
|
--dialog-backdrop-filter: blur(5px);
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
--mdc-dialog-min-width: var(--popup-min-width, 400px);
|
--mdc-dialog-min-width: var(--popup-min-width, 400px);
|
||||||
--mdc-dialog-max-width: var(--popup-max-width, 600px);
|
--mdc-dialog-max-width: var(--popup-max-width, 600px);
|
||||||
@ -202,13 +231,12 @@ class BrowserModPopup extends LitElement {
|
|||||||
--mdc-dialog-content-ink-color: var(--primary-text-color);
|
--mdc-dialog-content-ink-color: var(--primary-text-color);
|
||||||
--justify-action-buttons: space-between;
|
--justify-action-buttons: space-between;
|
||||||
|
|
||||||
--mdc-dialog-box-shadow: 0px 0px 0px
|
--dialog-box-shadow: 0px 0px 0px
|
||||||
var(--popup-border-width, var(--ha-card-border-width, 2px))
|
var(--popup-border-width, var(--ha-card-border-width, 2px))
|
||||||
var(
|
var(
|
||||||
--popup-border-color,
|
--popup-border-color,
|
||||||
var(--ha-card-border-color, var(--divider-color, #e0e0e0))
|
var(--ha-card-border-color, var(--divider-color, #e0e0e0))
|
||||||
);
|
);
|
||||||
--ha-dialog-border-radius: var(--popup-border-radius, 8px);
|
|
||||||
--mdc-theme-surface: var(
|
--mdc-theme-surface: var(
|
||||||
--popup-background-color,
|
--popup-background-color,
|
||||||
var(--ha-card-background, var(--card-background-color, white))
|
var(--ha-card-background, var(--card-background-color, white))
|
||||||
@ -224,6 +252,7 @@ class BrowserModPopup extends LitElement {
|
|||||||
--mdc-dialog-max-height: 100%;
|
--mdc-dialog-max-height: 100%;
|
||||||
--mdc-shape-medium: 0px;
|
--mdc-shape-medium: 0px;
|
||||||
--vertial-align-dialog: flex-end;
|
--vertial-align-dialog: flex-end;
|
||||||
|
--ha-dialog-border-radius: 0px;
|
||||||
}
|
}
|
||||||
.progress::before {
|
.progress::before {
|
||||||
content: "";
|
content: "";
|
||||||
@ -236,23 +265,20 @@ class BrowserModPopup extends LitElement {
|
|||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
app-toolbar {
|
ha-header-bar {
|
||||||
|
--mdc-theme-on-primary: var(--primary-text-color);
|
||||||
|
--mdc-theme-primary: var(--mdc-theme-surface);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
color: var(--primary-text-color);
|
display: block;
|
||||||
background-color: var(
|
|
||||||
--popup-header-background-color,
|
|
||||||
var(--popup-background-color, var(--sidebar-background-color))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-icon-button > * {
|
ha-icon-button > * {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
.main-title {
|
.main-title {
|
||||||
margin-left: 16px;
|
|
||||||
line-height: 1.3em;
|
|
||||||
max-height: 2.6em;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
.content {
|
.content {
|
||||||
--padding-x: 24px;
|
--padding-x: 24px;
|
||||||
@ -269,9 +295,11 @@ class BrowserModPopup extends LitElement {
|
|||||||
:host([card]) .content {
|
:host([card]) .content {
|
||||||
--padding-x: 0px;
|
--padding-x: 0px;
|
||||||
--padding-y: 0px;
|
--padding-y: 0px;
|
||||||
|
--ha-card-box-shadow: none;
|
||||||
}
|
}
|
||||||
:host([actions]) .content {
|
:host([actions]) .content {
|
||||||
border-bottom: 1px solid var(--popup-border-color, var(--divider-color));
|
xborder-bottom: 2px solid
|
||||||
|
var(--popup-border-color, var(--divider-color));
|
||||||
--footer-height: 54px;
|
--footer-height: 54px;
|
||||||
}
|
}
|
||||||
:host([wide]) .content {
|
:host([wide]) .content {
|
||||||
@ -280,10 +308,14 @@ class BrowserModPopup extends LitElement {
|
|||||||
:host([fullscreen]) .content {
|
:host([fullscreen]) .content {
|
||||||
height: calc(
|
height: calc(
|
||||||
100vh - var(--header-height) - var(--footer-height) - 2 *
|
100vh - var(--header-height) - var(--footer-height) - 2 *
|
||||||
var(--padding-y)
|
var(--padding-y) - 16px
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-button {
|
||||||
|
margin-bottom: -24px;
|
||||||
|
}
|
||||||
|
|
||||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||||
ha-dialog {
|
ha-dialog {
|
||||||
--mdc-dialog-min-width: 100vw;
|
--mdc-dialog-min-width: 100vw;
|
||||||
|
@ -128,7 +128,13 @@ export const ServicesMixin = (SuperClass) => {
|
|||||||
const { title, content, ...d } = data;
|
const { title, content, ...d } = data;
|
||||||
for (const [k, v] of Object.entries(d)) {
|
for (const [k, v] of Object.entries(d)) {
|
||||||
if (k.endsWith("_action")) {
|
if (k.endsWith("_action")) {
|
||||||
d[k] = () => this._service_action(v as any);
|
d[k] = (ext_data?) => {
|
||||||
|
const { service, data } = v as any;
|
||||||
|
this._service_action({
|
||||||
|
service,
|
||||||
|
data: { ...data, ...ext_data },
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.showPopup(title, content, d);
|
this.showPopup(title, content, d);
|
||||||
@ -147,18 +153,21 @@ export const ServicesMixin = (SuperClass) => {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "console":
|
case "console":
|
||||||
console.log(data.message);
|
if (
|
||||||
|
Object.keys(data).length > 1 ||
|
||||||
|
(data && data.message === undefined)
|
||||||
|
)
|
||||||
|
console.dir(data);
|
||||||
|
else console.log(data.message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "javascript":
|
case "javascript":
|
||||||
const code = `
|
const code = `
|
||||||
"use strict";
|
"use strict";
|
||||||
// Insert global definitions here
|
|
||||||
const hass = (document.querySelector("home-assistant") || document.querySelector("hc-main")).hass;
|
|
||||||
${data.code}
|
${data.code}
|
||||||
`;
|
`;
|
||||||
const fn = new Function(code);
|
const fn = new Function("hass", "data", code);
|
||||||
fn();
|
fn(this.hass, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "browser_mod",
|
"name": "browser_mod",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.0.0b2",
|
"version": "2.0.0b3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user