-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add tile card feature for input_select domain #16650
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,95 @@ | ||||||
import { HassEntity } from "home-assistant-js-websocket"; | ||||||
import { html, LitElement, nothing } from "lit"; | ||||||
import { customElement, property, state } from "lit/decorators"; | ||||||
import memoizeOne from "memoize-one"; | ||||||
import { fireEvent } from "../../../../common/dom/fire_event"; | ||||||
import type { LocalizeFunc } from "../../../../common/translations/localize"; | ||||||
import type { SchemaUnion } from "../../../../components/ha-form/types"; | ||||||
import type { HomeAssistant } from "../../../../types"; | ||||||
import { | ||||||
LovelaceTileFeatureContext, | ||||||
InputSelectOptionsFeatureConfig, | ||||||
} from "../../tile-features/types"; | ||||||
import type { LovelaceTileFeatureEditor } from "../../types"; | ||||||
|
||||||
@customElement("hui-input_select-options-tile-feature-editor") | ||||||
export class HuiInputSelectOptionsTileFeatureEditor | ||||||
extends LitElement | ||||||
implements LovelaceTileFeatureEditor | ||||||
{ | ||||||
@property({ attribute: false }) public hass?: HomeAssistant; | ||||||
|
||||||
@property({ attribute: false }) public context?: LovelaceTileFeatureContext; | ||||||
|
||||||
@state() private _config?: InputSelectOptionsFeatureConfig; | ||||||
|
||||||
public setConfig(config: InputSelectOptionsFeatureConfig): void { | ||||||
this._config = config; | ||||||
} | ||||||
|
||||||
private _schema = memoizeOne( | ||||||
(localize: LocalizeFunc, stateObj?: HassEntity) => | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
[ | ||||||
{ | ||||||
name: "options", | ||||||
selector: { | ||||||
select: { | ||||||
multiple: true, | ||||||
mode: "list", | ||||||
options: stateObj!.attributes.options.map((option) => ({ | ||||||
value: option, | ||||||
label: option, | ||||||
})), | ||||||
}, | ||||||
}, | ||||||
}, | ||||||
] as const | ||||||
); | ||||||
|
||||||
protected render() { | ||||||
if (!this.hass || !this._config) { | ||||||
return nothing; | ||||||
} | ||||||
|
||||||
const stateObj = this.context?.entity_id | ||||||
? this.hass.states[this.context?.entity_id] | ||||||
: undefined; | ||||||
|
||||||
const schema = this._schema(this.hass.localize, stateObj); | ||||||
|
||||||
return html` | ||||||
<ha-form | ||||||
.hass=${this.hass} | ||||||
.data=${this._config} | ||||||
.schema=${schema} | ||||||
.computeLabel=${this._computeLabelCallback} | ||||||
@value-changed=${this._valueChanged} | ||||||
></ha-form> | ||||||
`; | ||||||
} | ||||||
|
||||||
private _valueChanged(ev: CustomEvent): void { | ||||||
fireEvent(this, "config-changed", { config: ev.detail.value }); | ||||||
} | ||||||
|
||||||
private _computeLabelCallback = ( | ||||||
schema: SchemaUnion<ReturnType<typeof this._schema>> | ||||||
) => { | ||||||
switch (schema.name) { | ||||||
case "options": | ||||||
return this.hass!.localize( | ||||||
`ui.panel.lovelace.editor.card.tile.features.types.alarm-modes.${schema.name}` | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
); | ||||||
default: | ||||||
return this.hass!.localize( | ||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}` | ||||||
); | ||||||
} | ||||||
}; | ||||||
} | ||||||
|
||||||
declare global { | ||||||
interface HTMLElementTagNameMap { | ||||||
"hui-input_select-options-tile-feature-editor": HuiInputSelectOptionsTileFeatureEditor; | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,118 @@ | ||||||||||||||||||||
import { HassEntity } from "home-assistant-js-websocket"; | ||||||||||||||||||||
import { css, html, LitElement, nothing } from "lit"; | ||||||||||||||||||||
import { customElement, property, state } from "lit/decorators"; | ||||||||||||||||||||
import { computeDomain } from "../../../common/entity/compute_domain"; | ||||||||||||||||||||
import { InputSelectEntity } from "../../../data/input_select"; | ||||||||||||||||||||
import { ControlSelectOption } from "../../../components/ha-control-select"; | ||||||||||||||||||||
import { HomeAssistant } from "../../../types"; | ||||||||||||||||||||
import { LovelaceTileFeature, LovelaceTileFeatureEditor } from "../types"; | ||||||||||||||||||||
import { InputSelectOptionsFeatureConfig } from "./types"; | ||||||||||||||||||||
|
||||||||||||||||||||
export const supportsInputSelectOptionsTileFeature = (stateObj: HassEntity) => { | ||||||||||||||||||||
const domain = computeDomain(stateObj.entity_id); | ||||||||||||||||||||
return domain === "input_select"; | ||||||||||||||||||||
}; | ||||||||||||||||||||
Comment on lines
+11
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should support |
||||||||||||||||||||
|
||||||||||||||||||||
@customElement("hui-input_select-options-tile-feature") | ||||||||||||||||||||
class HuiInputSelectOptionsTileFeature | ||||||||||||||||||||
extends LitElement | ||||||||||||||||||||
implements LovelaceTileFeature | ||||||||||||||||||||
{ | ||||||||||||||||||||
@property({ attribute: false }) public hass?: HomeAssistant; | ||||||||||||||||||||
|
||||||||||||||||||||
@property({ attribute: false }) public stateObj?: InputSelectEntity; | ||||||||||||||||||||
|
||||||||||||||||||||
@state() private _config?: InputSelectOptionsFeatureConfig; | ||||||||||||||||||||
|
||||||||||||||||||||
static getStubConfig( | ||||||||||||||||||||
_, | ||||||||||||||||||||
stateObj?: HassEntity | ||||||||||||||||||||
): InputSelectOptionsFeatureConfig { | ||||||||||||||||||||
return { | ||||||||||||||||||||
type: "input_select-options", | ||||||||||||||||||||
options: stateObj ? stateObj.attributes.options : [], | ||||||||||||||||||||
}; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
public static async getConfigElement(): Promise<LovelaceTileFeatureEditor> { | ||||||||||||||||||||
await import( | ||||||||||||||||||||
"../editor/config-elements/hui-input_select-options-tile-feature-editor" | ||||||||||||||||||||
); | ||||||||||||||||||||
return document.createElement( | ||||||||||||||||||||
"hui-input_select-options-tile-feature-editor" | ||||||||||||||||||||
); | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
public setConfig(config: InputSelectOptionsFeatureConfig): void { | ||||||||||||||||||||
if (!config) { | ||||||||||||||||||||
throw new Error("Invalid configuration"); | ||||||||||||||||||||
} | ||||||||||||||||||||
this._config = config; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
protected render() { | ||||||||||||||||||||
if ( | ||||||||||||||||||||
!this._config || | ||||||||||||||||||||
!this.hass || | ||||||||||||||||||||
!this.stateObj || | ||||||||||||||||||||
!supportsInputSelectOptionsTileFeature(this.stateObj) | ||||||||||||||||||||
) { | ||||||||||||||||||||
return nothing; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
const options = this.stateObj.attributes.options | ||||||||||||||||||||
.filter( | ||||||||||||||||||||
(option) => | ||||||||||||||||||||
this._config?.options?.includes(option) || | ||||||||||||||||||||
this._config?.options === undefined || | ||||||||||||||||||||
this._config?.options?.length === 0 | ||||||||||||||||||||
) | ||||||||||||||||||||
Comment on lines
+65
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
If options is empty we must display nothing. |
||||||||||||||||||||
.map<ControlSelectOption>((key) => ({ | ||||||||||||||||||||
value: key, | ||||||||||||||||||||
label: key, | ||||||||||||||||||||
})); | ||||||||||||||||||||
const value = this.stateObj.state; | ||||||||||||||||||||
|
||||||||||||||||||||
return html` | ||||||||||||||||||||
<div class="container"> | ||||||||||||||||||||
<ha-control-select | ||||||||||||||||||||
.options=${options} | ||||||||||||||||||||
.value=${value} | ||||||||||||||||||||
@value-changed=${this._valueChanged} | ||||||||||||||||||||
.ariaLabel=${options} | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This must be a label, not options |
||||||||||||||||||||
></ha-control-select> | ||||||||||||||||||||
</div> | ||||||||||||||||||||
`; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
private async _valueChanged(ev: CustomEvent) { | ||||||||||||||||||||
const value = (ev.detail as any).value as string; | ||||||||||||||||||||
|
||||||||||||||||||||
this.hass!.callService("input_select", "select_option", { | ||||||||||||||||||||
entity_id: this.stateObj!.entity_id, | ||||||||||||||||||||
option: value, | ||||||||||||||||||||
}); | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
static get styles() { | ||||||||||||||||||||
return css` | ||||||||||||||||||||
ha-control-select { | ||||||||||||||||||||
--control-select-color: var(--tile-color); | ||||||||||||||||||||
--control-select-padding: 0; | ||||||||||||||||||||
--control-select-thickness: 40px; | ||||||||||||||||||||
--control-select-border-radius: 10px; | ||||||||||||||||||||
--control-select-button-border-radius: 10px; | ||||||||||||||||||||
} | ||||||||||||||||||||
.container { | ||||||||||||||||||||
padding: 0 12px 12px 12px; | ||||||||||||||||||||
width: auto; | ||||||||||||||||||||
} | ||||||||||||||||||||
`; | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
declare global { | ||||||||||||||||||||
interface HTMLElementTagNameMap { | ||||||||||||||||||||
"hui-input_select-tile-feature": HuiInputSelectOptionsTileFeature; | ||||||||||||||||||||
} | ||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we rename it to
select-options
and add support forselect
entity too?