-
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
Picture Elements Visual editor #19718
Picture Elements Visual editor #19718
Conversation
Could be ready for a review. |
I've had a test run on your pull request and it makes the card easier to configure 👍 (even the yaml per element is great to have). Some quick notes:
About service control: service: fan.set_percentage
target:
entity_id: fan.ceiling_fan
data:
percentage: 100 would be equivalent to service: fan.set_percentage
service_data:
entity_id: fan.ceiling_fan
percentage: 100 |
Thanks for giving it a spin 👍
Good find, yeah I let a little bug slip in when modifying the string rendering, should be fixed now. |
@state() private _config?: StateBadgeElementConfig; | ||
|
||
public setConfig(config: StateBadgeElementConfig): void { | ||
this._config = config; |
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.
These should probably also check the config with the struct?
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.
I removed the struct validation for elements from the card editor, and put it in the element editors themselves. That way individual element validation failure doesn't yank the whole card out of visual mode, but just the single element will get a yaml editor, and everything else is still visually editable. Seems to work as intended, though this looks like a design departure from how entities-card editor handled row validation, which was sort of what I was basing this off of.
So I'm not sure if that will have any other consequences.
return this.value?.type; | ||
} | ||
|
||
protected async getConfigElement(): Promise< |
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.
This function should be part of the elements, so custom elements can also provide an editor.
So the same as cards.
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.
Think I've got this resolved.
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.
I've got the conditional element to work. 👍
The missing required selectors:
src/panels/lovelace/editor/config-elements/elements/hui-state-badge-element-editor.ts
Outdated
Show resolved
Hide resolved
src/panels/lovelace/editor/config-elements/elements/hui-state-icon-element-editor.ts
Outdated
Show resolved
Hide resolved
src/panels/lovelace/editor/config-elements/elements/hui-service-button-element-editor.ts
Outdated
Show resolved
Hide resolved
src/panels/lovelace/editor/config-elements/elements/hui-service-button-element-editor.ts
Outdated
Show resolved
Hide resolved
The service call button could have a service control, would be a great thing to have here but it's double. There's no usable selector and the config needs to be tweaked to what the card wants. The others can be added if really needed imo. |
… picture-elements-editor
…/frontend into picture-elements-editor
…e-button-element-editor.ts Co-authored-by: Simon Lamon <[email protected]>
…icon-element-editor.ts Co-authored-by: Simon Lamon <[email protected]>
…e-button-element-editor.ts Co-authored-by: Simon Lamon <[email protected]>
…badge-element-editor.ts Co-authored-by: Simon Lamon <[email protected]>
WalkthroughWalkthroughThe updates enhance the configuration and usability of Lovelace elements in the Home Assistant UI. Key improvements include the addition of a Changes
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configuration File (
|
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.
Actionable comments posted: 9
Outside diff range, codebase verification and nitpick comments (5)
src/panels/lovelace/elements/hui-state-icon-element.ts (1)
Line range hint
34-41
:
Add error handling for invalid configurations.The function currently does not handle invalid configurations gracefully. Consider adding a try-catch block to handle validation errors.
public setConfig(config: StateIconElementConfig): void { try { if (!config.entity) { throw Error("Entity required"); } this._config = { state_color: true, hold_action: { action: "more-info" }, ...config, }; } catch (error) { console.error("Invalid configuration:", error); // Handle the error appropriately, e.g., show a user-friendly message. } }src/panels/lovelace/elements/hui-image-element.ts (1)
Line range hint
22-31
:
Add error handling for invalid configurations.The function currently does not handle invalid configurations gracefully. Consider adding a try-catch block to handle validation errors.
public setConfig(config: ImageElementConfig): void { try { if (!config) { throw Error("Invalid configuration"); } this._config = { hold_action: { action: "more-info" }, ...config }; // eslint-disable-next-line wc/no-self-class this.classList.toggle( "clickable", this._config.tap_action && this._config.tap_action.action !== "none" ); } catch (error) { console.error("Invalid configuration:", error); // Handle the error appropriately, e.g., show a user-friendly message. } }src/panels/lovelace/cards/hui-picture-elements-card.ts (2)
Line range hint
38-55
: Consider adding error handling.Add error handling to manage potential issues during the configuration setup.
- this._elements = config.elements.map((element) => { - const cardElement = this._createElement(element); - return cardElement; - }); + try { + this._elements = config.elements.map((element) => { + const cardElement = this._createElement(element); + return cardElement; + }); + } catch (error) { + console.error("Failed to create elements:", error); + throw new Error("Failed to create elements"); + }
Line range hint
52-89
: Consider adding error handling.Add error handling to manage potential issues during the rendering process.
- return html` - <ha-card .header=${this._config.title}> - <div id="root"> - <hui-image - .hass=${this.hass} - .image=${stateObj ? computeImageUrl(stateObj) : this._config.image} - .stateImage=${this._config.state_image} - .stateFilter=${this._config.state_filter} - .cameraImage=${this._config.camera_image} - .cameraView=${this._config.camera_view} - .entity=${this._config.entity} - .aspectRatio=${this._config.aspect_ratio} - .darkModeFilter=${this._config.dark_mode_filter} - .darkModeImage=${this._config.dark_mode_image} - ></hui-image> - ${this._elements} - </div> - </ha-card> - `; + try { + return html` + <ha-card .header=${this._config.title}> + <div id="root"> + <hui-image + .hass=${this.hass} + .image=${stateObj ? computeImageUrl(stateObj) : this._config.image} + .stateImage=${this._config.state_image} + .stateFilter=${this._config.state_filter} + .cameraImage=${this._config.camera_image} + .cameraView=${this._config.camera_view} + .entity=${this._config.entity} + .aspectRatio=${this._config.aspect_ratio} + .darkModeFilter=${this._config.dark_mode_filter} + .darkModeImage=${this._config.dark_mode_image} + ></hui-image> + ${this._elements} + </div> + </ha-card> + `; + } catch (error) { + console.error("Failed to render card:", error); + return nothing; + }src/panels/lovelace/editor/config-elements/elements/hui-conditional-element-editor.ts (1)
47-50
: Consider adding error handling tosetConfig
method.While the
assert
statement is useful for validation, adding error handling can ensure the method handles unexpected runtime errors gracefully.
src/panels/lovelace/editor/config-elements/elements/hui-conditional-element-editor.ts
(Lines: 47-50)Analysis chain
Verify the configuration validation.
Ensure that the configuration validation covers all possible edge cases.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the configuration validation for `setConfig`. # Test: Search for the usage of `setConfig` to ensure all edge cases are handled. rg --type javascript -A 5 'setConfig'Length of output: 72
Script:
#!/bin/bash # Description: Verify the configuration validation for `setConfig`. # Test: Search for the usage of `setConfig` to ensure all edge cases are handled. rg --type js -A 5 'setConfig' rg --type ts -A 5 'setConfig'Length of output: 117543
protected async getConfigElement(): Promise< | ||
LovelacePictureElementEditor | undefined | ||
> { | ||
const elClass = await getPictureElementClass(this.configElementType!); | ||
|
||
// Check if a GUI editor exists | ||
if (elClass && elClass.getConfigElement) { | ||
return elClass.getConfigElement(); | ||
} | ||
|
||
return undefined; |
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.
Use Optional Chaining for Safety
The method getConfigElement
can be improved by using optional chaining to safely access getConfigElement
.
- if (elClass && elClass.getConfigElement) {
- return elClass.getConfigElement();
+ if (elClass?.getConfigElement) {
+ return elClass.getConfigElement();
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
protected async getConfigElement(): Promise< | |
LovelacePictureElementEditor | undefined | |
> { | |
const elClass = await getPictureElementClass(this.configElementType!); | |
// Check if a GUI editor exists | |
if (elClass && elClass.getConfigElement) { | |
return elClass.getConfigElement(); | |
} | |
return undefined; | |
protected async getConfigElement(): Promise< | |
LovelacePictureElementEditor | undefined | |
> { | |
const elClass = await getPictureElementClass(this.configElementType!); | |
// Check if a GUI editor exists | |
if (elClass?.getConfigElement) { | |
return elClass.getConfigElement(); | |
} | |
return undefined; |
Tools
Biome
[error] 19-19: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
public setConfig(config: StateIconElementConfig): void { | ||
assert(config, stateIconElementConfigStruct); | ||
this._config = config; | ||
} |
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.
Add error handling for invalid configurations.
The function currently does not handle invalid configurations gracefully. Consider adding a try-catch block to handle validation errors.
public setConfig(config: StateIconElementConfig): void {
try {
assert(config, stateIconElementConfigStruct);
this._config = config;
} catch (error) {
console.error("Invalid configuration:", error);
// Handle the error appropriately, e.g., show a user-friendly message.
}
}
protected render() { | ||
if (!this.hass || !this._config) { | ||
return nothing; | ||
} | ||
|
||
return html` | ||
<ha-form | ||
.hass=${this.hass} | ||
.data=${this._config} | ||
.schema=${SCHEMA} | ||
.computeLabel=${this._computeLabelCallback} | ||
@value-changed=${this._valueChanged} | ||
></ha-form> | ||
`; | ||
} |
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.
Consider adding a loading state or fallback UI.
When hass
or _config
are not available, the function returns nothing
. Consider adding a loading state or a fallback UI to improve user experience.
protected render() {
if (!this.hass || !this._config) {
return html`<p>Loading...</p>`; // or any other appropriate fallback UI
}
return html`
<ha-form
.hass=${this.hass}
.data=${this._config}
.schema=${SCHEMA}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
`;
}
public setConfig(config: StateLabelElementConfig): void { | ||
assert(config, stateLabelElementConfigStruct); | ||
this._config = config; | ||
} |
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.
Add error handling for invalid configurations.
The function currently does not handle invalid configurations gracefully. Consider adding a try-catch block to handle validation errors.
public setConfig(config: StateLabelElementConfig): void {
try {
assert(config, stateLabelElementConfigStruct);
this._config = config;
} catch (error) {
console.error("Invalid configuration:", error);
// Handle the error appropriately, e.g., show a user-friendly message.
}
}
protected render() { | ||
if (!this.hass || !this._config) { | ||
return nothing; | ||
} | ||
|
||
return html` | ||
<ha-form | ||
.hass=${this.hass} | ||
.data=${this._config} | ||
.schema=${SCHEMA} | ||
.computeLabel=${this._computeLabelCallback} | ||
@value-changed=${this._valueChanged} | ||
></ha-form> | ||
`; | ||
} |
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.
Consider adding a loading state or fallback UI.
When hass
or _config
are not available, the function returns nothing
. Consider adding a loading state or a fallback UI to improve user experience.
protected render() {
if (!this.hass || !this._config) {
return html`<p>Loading...</p>`; // or any other appropriate fallback UI
}
return html`
<ha-form
.hass=${this.hass}
.data=${this._config}
.schema=${SCHEMA}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
`;
}
public static async getConfigElement(): Promise<LovelaceCardEditor> { | ||
await import("../editor/config-elements/hui-picture-elements-card-editor"); | ||
return document.createElement("hui-picture-elements-card-editor"); |
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.
Consider adding error handling.
Add error handling to manage potential issues during the dynamic import.
- await import("../editor/config-elements/hui-picture-elements-card-editor");
- return document.createElement("hui-picture-elements-card-editor");
+ try {
+ await import("../editor/config-elements/hui-picture-elements-card-editor");
+ return document.createElement("hui-picture-elements-card-editor");
+ } catch (error) {
+ console.error("Failed to load editor:", error);
+ throw new Error("Failed to load editor");
+ }
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
public static async getConfigElement(): Promise<LovelaceCardEditor> { | |
await import("../editor/config-elements/hui-picture-elements-card-editor"); | |
return document.createElement("hui-picture-elements-card-editor"); | |
public static async getConfigElement(): Promise<LovelaceCardEditor> { | |
try { | |
await import("../editor/config-elements/hui-picture-elements-card-editor"); | |
return document.createElement("hui-picture-elements-card-editor"); | |
} catch (error) { | |
console.error("Failed to load editor:", error); | |
throw new Error("Failed to load editor"); | |
} |
public setConfig(config: ConditionalElementConfig): void { | ||
assert(config, conditionalElementConfigStruct); | ||
this._config = config; | ||
} |
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.
Consider adding error handling.
Add error handling to manage potential issues during the configuration setup.
- this._config = config;
+ try {
+ this._config = config;
+ } catch (error) {
+ console.error("Failed to set configuration:", error);
+ throw new Error("Failed to set configuration");
+ }
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
public setConfig(config: ConditionalElementConfig): void { | |
assert(config, conditionalElementConfigStruct); | |
this._config = config; | |
} | |
public setConfig(config: ConditionalElementConfig): void { | |
assert(config, conditionalElementConfigStruct); | |
try { | |
this._config = config; | |
} catch (error) { | |
console.error("Failed to set configuration:", error); | |
throw new Error("Failed to set configuration"); | |
} | |
} |
private _handleSubElementChanged(ev: CustomEvent): void { | ||
ev.stopPropagation(); | ||
if (!this._config || !this.hass) { | ||
return; | ||
} | ||
|
||
const configValue = this._subElementEditorConfig?.type; | ||
const value = ev.detail.config; | ||
|
||
if (configValue === "element") { | ||
const newConfigElements = this._config.elements!.concat(); | ||
if (!value) { | ||
newConfigElements.splice(this._subElementEditorConfig!.index!, 1); | ||
this._goBack(); | ||
} else { | ||
newConfigElements[this._subElementEditorConfig!.index!] = value; | ||
} | ||
|
||
this._config = { ...this._config!, elements: newConfigElements }; | ||
} | ||
|
||
this._subElementEditorConfig = { | ||
...this._subElementEditorConfig!, | ||
elementConfig: value, | ||
}; | ||
|
||
fireEvent(this, "config-changed", { config: this._config }); |
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.
Consider adding error handling.
Add error handling to manage potential issues during the sub-element handling process.
- this._config = { ...this._config!, elements: newConfigElements };
+ try {
+ this._config = { ...this._config!, elements: newConfigElements };
+ } catch (error) {
+ console.error("Failed to handle sub-element changes:", error);
+ throw new Error("Failed to handle sub-element changes");
+ }
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
private _handleSubElementChanged(ev: CustomEvent): void { | |
ev.stopPropagation(); | |
if (!this._config || !this.hass) { | |
return; | |
} | |
const configValue = this._subElementEditorConfig?.type; | |
const value = ev.detail.config; | |
if (configValue === "element") { | |
const newConfigElements = this._config.elements!.concat(); | |
if (!value) { | |
newConfigElements.splice(this._subElementEditorConfig!.index!, 1); | |
this._goBack(); | |
} else { | |
newConfigElements[this._subElementEditorConfig!.index!] = value; | |
} | |
this._config = { ...this._config!, elements: newConfigElements }; | |
} | |
this._subElementEditorConfig = { | |
...this._subElementEditorConfig!, | |
elementConfig: value, | |
}; | |
fireEvent(this, "config-changed", { config: this._config }); | |
private _handleSubElementChanged(ev: CustomEvent): void { | |
ev.stopPropagation(); | |
if (!this._config || !this.hass) { | |
return; | |
} | |
const configValue = this._subElementEditorConfig?.type; | |
const value = ev.detail.config; | |
if (configValue === "element") { | |
const newConfigElements = this._config.elements!.concat(); | |
if (!value) { | |
newConfigElements.splice(this._subElementEditorConfig!.index!, 1); | |
this._goBack(); | |
} else { | |
newConfigElements[this._subElementEditorConfig!.index!] = value; | |
} | |
try { | |
this._config = { ...this._config!, elements: newConfigElements }; | |
} catch (error) { | |
console.error("Failed to handle sub-element changes:", error); | |
throw new Error("Failed to handle sub-element changes"); | |
} | |
} | |
this._subElementEditorConfig = { | |
...this._subElementEditorConfig!, | |
elementConfig: value, | |
}; | |
fireEvent(this, "config-changed", { config: this._config }); |
protected render() { | ||
if (!this.hass || !this._config) { | ||
return nothing; | ||
} | ||
|
||
if (this._subElementEditorConfig) { | ||
return html` | ||
<hui-sub-element-editor | ||
.hass=${this.hass} | ||
.config=${this._subElementEditorConfig} | ||
@go-back=${this._goBack} | ||
@config-changed=${this._handleSubElementChanged} | ||
> | ||
</hui-sub-element-editor> | ||
`; | ||
} | ||
|
||
return html` | ||
<ha-form | ||
.hass=${this.hass} | ||
.data=${this._config} | ||
.schema=${SCHEMA} | ||
.computeLabel=${this._computeLabelCallback} | ||
@value-changed=${this._formChanged} | ||
></ha-form> | ||
<ha-card-conditions-editor | ||
.hass=${this.hass} | ||
.conditions=${this._config.conditions || []} | ||
@value-changed=${this._conditionChanged} | ||
> | ||
</ha-card-conditions-editor> | ||
<hui-picture-elements-card-row-editor | ||
.hass=${this.hass} | ||
.elements=${this._config.elements || []} | ||
@elements-changed=${this._elementsChanged} | ||
@edit-detail-element=${this._editDetailElement} | ||
></hui-picture-elements-card-row-editor> | ||
`; |
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.
Consider adding error handling.
Add error handling to manage potential issues during the rendering process.
- return html`
- <ha-form
- .hass=${this.hass}
- .data=${this._config}
- .schema=${SCHEMA}
- .computeLabel=${this._computeLabelCallback}
- @value-changed=${this._formChanged}
- ></ha-form>
- <ha-card-conditions-editor
- .hass=${this.hass}
- .conditions=${this._config.conditions || []}
- @value-changed=${this._conditionChanged}
- >
- </ha-card-conditions-editor>
- <hui-picture-elements-card-row-editor
- .hass=${this.hass}
- .elements=${this._config.elements || []}
- @elements-changed=${this._elementsChanged}
- @edit-detail-element=${this._editDetailElement}
- ></hui-picture-elements-card-row-editor>
- `;
+ try {
+ return html`
+ <ha-form
+ .hass=${this.hass}
+ .data=${this._config}
+ .schema=${SCHEMA}
+ .computeLabel=${this._computeLabelCallback}
+ @value-changed=${this._formChanged}
+ ></ha-form>
+ <ha-card-conditions-editor
+ .hass=${this.hass}
+ .conditions=${this._config.conditions || []}
+ @value-changed=${this._conditionChanged}
+ >
+ </ha-card-conditions-editor>
+ <hui-picture-elements-card-row-editor
+ .hass=${this.hass}
+ .elements=${this._config.elements || []}
+ @elements-changed=${this._elementsChanged}
+ @edit-detail-element=${this._editDetailElement}
+ ></hui-picture-elements-card-row-editor>
+ `;
+ } catch (error) {
+ console.error("Failed to render editor:", error);
+ return nothing;
+ }
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
protected render() { | |
if (!this.hass || !this._config) { | |
return nothing; | |
} | |
if (this._subElementEditorConfig) { | |
return html` | |
<hui-sub-element-editor | |
.hass=${this.hass} | |
.config=${this._subElementEditorConfig} | |
@go-back=${this._goBack} | |
@config-changed=${this._handleSubElementChanged} | |
> | |
</hui-sub-element-editor> | |
`; | |
} | |
return html` | |
<ha-form | |
.hass=${this.hass} | |
.data=${this._config} | |
.schema=${SCHEMA} | |
.computeLabel=${this._computeLabelCallback} | |
@value-changed=${this._formChanged} | |
></ha-form> | |
<ha-card-conditions-editor | |
.hass=${this.hass} | |
.conditions=${this._config.conditions || []} | |
@value-changed=${this._conditionChanged} | |
> | |
</ha-card-conditions-editor> | |
<hui-picture-elements-card-row-editor | |
.hass=${this.hass} | |
.elements=${this._config.elements || []} | |
@elements-changed=${this._elementsChanged} | |
@edit-detail-element=${this._editDetailElement} | |
></hui-picture-elements-card-row-editor> | |
`; | |
protected render() { | |
if (!this.hass || !this._config) { | |
return nothing; | |
} | |
if (this._subElementEditorConfig) { | |
return html` | |
<hui-sub-element-editor | |
.hass=${this.hass} | |
.config=${this._subElementEditorConfig} | |
@go-back=${this._goBack} | |
@config-changed=${this._handleSubElementChanged} | |
> | |
</hui-sub-element-editor> | |
`; | |
} | |
try { | |
return html` | |
<ha-form | |
.hass=${this.hass} | |
.data=${this._config} | |
.schema=${SCHEMA} | |
.computeLabel=${this._computeLabelCallback} | |
@value-changed=${this._formChanged} | |
></ha-form> | |
<ha-card-conditions-editor | |
.hass=${this.hass} | |
.conditions=${this._config.conditions || []} | |
@value-changed=${this._conditionChanged} | |
> | |
</ha-card-conditions-editor> | |
<hui-picture-elements-card-row-editor | |
.hass=${this.hass} | |
.elements=${this._config.elements || []} | |
@elements-changed=${this._elementsChanged} | |
@edit-detail-element=${this._editDetailElement} | |
></hui-picture-elements-card-row-editor> | |
`; | |
} catch (error) { | |
console.error("Failed to render editor:", error); | |
return nothing; | |
} |
{ name: "title", selector: { text: {} } }, | ||
{ name: "image", selector: { text: {} } }, |
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.
I think we should move some basic things out of the expandable, like the image, it feels too hidden now and is the most important setting
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.
Would just making the expandable opened by default be satisfactory? Idea was to avoid pushing the elements themselves down where you have to scroll so far down that the preview is no longer visible.
At some point we may also replace the image URL with the image selector, which is fairly large as well.
|
||
const SCHEMA = [{ name: "title", selector: { text: {} } }] as const; | ||
|
||
@customElement("hui-conditional-element-editor") |
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.
We should add support for visibility
for elements, and deprecate the conditional element :-)
import { ActionHandlerEvent } from "../../../data/lovelace/action_handler"; | ||
|
||
@customElement("hui-icon-element") | ||
export class HuiIconElement extends LitElement implements LovelaceElement { | ||
public static async getConfigElement(): Promise<LovelacePictureElementEditor> { |
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.
We should add support for getStubConfig
so the elements are not created with an invalid config
I think there are some improvements to make UX wise, as you mentioned yourself in the PR description, but this is good start! |
After #21440 is in, it will support target/data combination streamlined to other parts in Home Assistant. That should enable to show a service control component. |
remove comment Co-authored-by: Bram Kragten <[email protected]>
Proposed change
A visual editor for picture elements card.
Possible enhancements:
Early render:
More final styling:
Type of change
Example configuration
Additional information
Checklist
If user exposed functionality or configuration variables are added/changed:
Summary by CodeRabbit
New Features
title
property to several element configurations in Lovelace.LovelaceElementConstructor
andLovelacePictureElementEditor
interfaces for enhanced element editing.getConfigElement
method added to various Lovelace elements for better configuration handling.Improvements