-
Notifications
You must be signed in to change notification settings - Fork 264
feat: add visual editor #1128
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
Open
selvalt7
wants to merge
33
commits into
kalkih:dev
Choose a base branch
from
selvalt7:editor
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
feat: add visual editor #1128
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
bb5366f
ok
selvalt7 fc89200
Add editor
selvalt7 12f4c86
Fix
selvalt7 0d9c7d5
Improved visual editor
selvalt7 984ffae
Update naming
selvalt7 8834ab0
Added color selector
selvalt7 9f5ace9
Add visual editor
selvalt7 e7276f6
Fix
selvalt7 f43e017
Fix: color conversion functions
selvalt7 4224e50
Added support for color array
selvalt7 765fa0a
Added color thresholds editor
selvalt7 61c3f6f
Set default show values
selvalt7 00d2c09
Removed use color thresholds option
selvalt7 05b81a5
Added state map editor
selvalt7 f7fb286
Made subpage link focusable
selvalt7 83a7661
Removed color conversion functions
selvalt7 1ff2815
Merge branch 'dev' of https://github.com/selvalt7/mini-graph-card int…
selvalt7 56f324b
Merge branch 'dev' into editor
selvalt7 e210a83
ok
selvalt7 0a0f90f
fix: missing "resolved" and "integrity" field in "package-lock.json" …
selvalt7 78369e0
fix: visual glitch in "select" selector
selvalt7 b689ee5
feat: entity can be removed with button inside the selector
selvalt7 aa10d65
fix: unset show properties were treated as undefined
selvalt7 cbc8880
feat: display entity_id under entity selector
selvalt7 e16f430
Merge branch 'dev' into editor
selvalt7 87d963b
Added `ha-form-mgc-list` for use in `ha-form` schema
selvalt7 5f82f5f
add German translation
tr05t 1fcae0f
add German translation
tr05t 86cb9d8
Merge branch 'editor' of github.com:tr05t/mini-graph-card into editor
tr05t a69556c
add German translation
tr05t 138875d
Merge branch 'editor' of github.com:tr05t/mini-graph-card into editor
tr05t 86f544d
add German translation
selvalt7 100dd42
Added value localization
selvalt7 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,3 +14,4 @@ globals: | |
| window: true | ||
| Event: true | ||
| customElements: true | ||
| document: true | ||
Empty file.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| import { mdiClose } from '@mdi/js'; | ||
| import { fireEvent } from 'custom-card-helpers'; | ||
| import { css, html, LitElement } from 'lit-element'; | ||
| import { isValidHex, convertColorNameToHex } from '../editorUtils'; | ||
|
|
||
| export const colorSelector = { | ||
| hex_color: {}, | ||
| }; | ||
|
|
||
| export class CustomColorSelector extends LitElement { | ||
| static get properties() { | ||
| return { | ||
| hass: { attribute: false }, | ||
| selector: { attribute: false }, | ||
| value: {}, | ||
| label: {}, | ||
| }; | ||
| } | ||
|
|
||
| render() { | ||
| const isHex = isValidHex(this.value); | ||
| const colorValue = isHex ? this.value : convertColorNameToHex(this.value); | ||
| return html` | ||
| <div class="color-container"> | ||
| <label id="hex" for="color-input"> | ||
| <span class="label">${this.label}</span> | ||
| <span class="input-wrapper"> | ||
| <div class="overflow"> | ||
| <input class=${this.value ? '' : 'empty'} | ||
| id="color-input" | ||
| @input=${this.valueChanged} | ||
| type="color" | ||
| .value=${colorValue || '#000000'}> | ||
| </div> | ||
| </span> | ||
| </label> | ||
| ${this.selector.hex_color.clearable ? html` | ||
| <ha-icon-button | ||
| class="clear-button" | ||
| .label=${this.hass.localize('ui.common.clear')} | ||
| .path=${mdiClose} | ||
| @click=${this.clearValue} | ||
| ><ha-icon-button> | ||
| ` : html``} | ||
| </div> | ||
| `; | ||
| } | ||
|
|
||
| valueChanged(ev) { | ||
| const value = (ev.target).value || '#000000'; | ||
| fireEvent(this, 'value-changed', { value }); | ||
| } | ||
|
|
||
| clearValue() { | ||
| fireEvent(this, 'value-changed', { undefined }); | ||
| } | ||
|
|
||
| static get styles() { | ||
| return css` | ||
| #hex { | ||
| display: flex; | ||
| align-items: center; | ||
| margin: 4px 0px; | ||
| flex: 1; | ||
| } | ||
|
|
||
| .input-wrapper { | ||
| width: 48px; | ||
| height: 48px; | ||
| box-sizing: border-box; | ||
| border: 1px solid var(--outline-color); | ||
| position: relative; | ||
| border-radius: 50%; | ||
| } | ||
|
|
||
| #hex:hover .input-wrapper { | ||
| border: 2px solid var(--outline-color); | ||
| } | ||
|
|
||
| .label { | ||
| font-family: var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif)); | ||
| color: var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, .87)); | ||
| font-size: 1em; | ||
| line-height: var(--mdc-typography-body2-line-height, 1.25rem); | ||
| font-weight: var(--mdc-typography-body2-font-weight, 400); | ||
| flex-grow: 1; | ||
| padding-inline-start: 4px; | ||
| } | ||
|
|
||
| .overflow { | ||
| width: 100%; | ||
| height: 100%; | ||
| overflow: hidden; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| border-radius: inherit; | ||
| } | ||
|
|
||
| #hex input { | ||
| min-width: 200%; | ||
| min-height: 200%; | ||
| } | ||
|
|
||
| #hex .empty::before { | ||
| background: | ||
| repeating-conic-gradient( | ||
| var(--secondary-background-color) 0 90deg, | ||
| var(--disabled-text-color) 0 180deg) | ||
| 0 0/40px 40px round; | ||
| content: ''; | ||
| min-width: 200%; | ||
| min-height: 200%; | ||
| display: block; | ||
| } | ||
|
|
||
| .color-container { | ||
| display: flex; | ||
| align-items: center; | ||
| } | ||
|
|
||
| .clear-button { | ||
| --mdc-icon-size: 20px; | ||
| color: var(--input-dropdown-icon-color); | ||
| } | ||
| `; | ||
| } | ||
| } | ||
|
|
||
| customElements.define('ha-selector-hex_color', CustomColorSelector); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| import { mdiPencil, mdiDrag } from '@mdi/js'; | ||
| import { fireEvent } from 'custom-card-helpers'; | ||
| import { LitElement, html, css } from 'lit-element'; | ||
|
|
||
| const SCHEMA = [ | ||
| { | ||
| name: 'entity', | ||
| selector: { entity: {} }, | ||
| }, | ||
| ]; | ||
|
|
||
| class EntitiesEditor extends LitElement { | ||
| constructor() { | ||
| super(); | ||
| this.newEntity = {}; | ||
| } | ||
|
|
||
| static get properties() { | ||
| return { | ||
| hass: { attribute: false }, | ||
| entities: { attribute: false }, | ||
| newEntity: {}, | ||
| }; | ||
| } | ||
|
|
||
| computeLabel(schema) { | ||
| return this.hass.localize(`ui.panel.lovelace.editor.card.generic.${schema.name}`); | ||
| } | ||
|
|
||
| computeHelper(schema, data) { | ||
| if (schema.selector.entity) { | ||
| return data.entity; | ||
| } | ||
| return ''; | ||
| } | ||
|
|
||
| render() { | ||
| if (!this.entities) { | ||
| return html` | ||
| <div class="entity add-item"> | ||
| <ha-form | ||
| .hass=${this.hass} | ||
| .data=${this.newEntity} | ||
| .schema=${SCHEMA} | ||
| .computeLabel=${this.computeLabel} | ||
| @value-changed=${this.addEntity} | ||
| ></ha-form> | ||
| </div> | ||
| `; | ||
| } | ||
|
|
||
| return html` | ||
| <ha-sortable handle-selector=".handle" @item-moved=${this.rowMoved}> | ||
| <div class="entities"> | ||
| ${this.entities.map((entity, index) => html` | ||
| <div class="entity"> | ||
| <div class="handle"> | ||
| <ha-svg-icon .path=${mdiDrag}></ha-svg-icon> | ||
| </div> | ||
| <ha-form | ||
| .hass=${this.hass} | ||
| .data=${typeof entity === 'object' ? entity : { entity }} | ||
| .schema=${SCHEMA} | ||
| .index=${index} | ||
| .computeLabel=${this.computeLabel} | ||
| .computeHelper=${schema => this.computeHelper(schema, typeof entity === 'object' ? entity : { entity })} | ||
| @value-changed=${this.valueChanged} | ||
| ></ha-form> | ||
| <ha-icon-button class="edit-entity" | ||
| .label=${this.hass.localize('ui.components.entity.entity-picker.edit')} | ||
| .path=${mdiPencil} | ||
| .index=${index} | ||
| @click=${this.editRow} | ||
| ></ha-icon-button> | ||
| </div> | ||
| `)} | ||
| </div> | ||
| </div> | ||
| </ha-sortable> | ||
| <div class="entity add-item"> | ||
| <ha-form | ||
| .hass=${this.hass} | ||
| .data=${this.newEntity} | ||
| .schema=${SCHEMA} | ||
| .computeLabel=${this.computeLabel} | ||
| @value-changed=${this.addEntity} | ||
| ></ha-form> | ||
| </div> | ||
| `; | ||
| } | ||
|
|
||
| rowMoved(ev) { | ||
| ev.stopPropagation(); | ||
| if (!this.entities || !this.hass) { | ||
| return; | ||
| } | ||
| const { oldIndex, newIndex } = ev.detail; | ||
| const newEntities = this.entities.concat(); | ||
|
|
||
| newEntities.splice(newIndex, 0, newEntities.splice(oldIndex, 1)[0]); | ||
|
|
||
| fireEvent(this, 'config-changed', newEntities); | ||
| } | ||
|
|
||
| addEntity(ev) { | ||
| ev.stopPropagation(); | ||
| const value = ev.detail.value || ''; | ||
| if (this.entities === undefined) { | ||
| fireEvent(this, 'config-changed', [value]); | ||
| return; | ||
| } | ||
| if (value === '' || value.entity === undefined) { | ||
| return; | ||
| } | ||
| fireEvent(this, 'config-changed', [...this.entities, value]); | ||
| } | ||
|
|
||
| editRow(ev) { | ||
| const index = (ev.currentTarget).index || 0; | ||
| fireEvent(this, 'edit-row', index); | ||
| } | ||
|
|
||
| valueChanged(ev) { | ||
| if (!this.entities || !this.hass) { | ||
| return; | ||
| } | ||
| const value = ev.detail.value.entity || ''; | ||
| const index = (ev.target).index || 0; | ||
| const newConfigEntities = this.entities.concat(); | ||
|
|
||
| if (value === '' || value === undefined) { | ||
| newConfigEntities.splice(index, 1); | ||
| } else if (typeof newConfigEntities[index] === 'object') { | ||
| newConfigEntities[index] = { | ||
| ...newConfigEntities[index], | ||
| entity: value || '', | ||
| }; | ||
| } else { | ||
| newConfigEntities[index] = { | ||
| entity: value || '', | ||
| }; | ||
| } | ||
|
|
||
| fireEvent(this, 'config-changed', newConfigEntities); | ||
| } | ||
|
|
||
| static get styles() { | ||
| return css` | ||
| .entity { | ||
| display: flex; | ||
| align-items: center; | ||
| margin-bottom: 8px; | ||
| } | ||
|
|
||
| .entity > ha-form { | ||
| flex-grow: 1; | ||
| } | ||
|
|
||
| .handle { | ||
| cursor: grab; | ||
| padding-inline-end: 8px; | ||
| align-self: flex-start; | ||
| margin: 16px 0; | ||
| } | ||
|
|
||
| .add-item { | ||
| margin-bottom: 24px; | ||
| } | ||
|
|
||
| .edit-entity { | ||
| align-self: flex-start; | ||
| margin: 4px 0px; | ||
| } | ||
| `; | ||
| } | ||
| } | ||
|
|
||
| customElements.define('mini-graph-card-entities-editor', EntitiesEditor); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Is there a reason not to use the color picker provided by hass itself?
If it is the "clearable" feature, it could be handled in the usual hass way by having an enable/disable toggle in front of the color picker.
If it is the hex format, could it be converted "output-only" in the main
valueChangedfunction? I am not familiar enough with the way these things work...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.
Mainly it was the hex format. I've tried to do the convertion on output but this resulted in warnings in console about supplied color value to hass color picker but the selecter was rendering just fine.
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.
Ah, I see... I'd guess, we'd have to convert back and forth to not loose colours on each startup of the editor... At least in
setConfig,configChangedandentitiesChanged... Then use[r,g,b]internally in the editor and hex outside...Another idea: How about we allow
[r,g,b]as a new colour input format for the mini-graph-card itself? Better suited for a follow-up PR then, maybe... We'd still loose non-hex colours on first startup of the editor, I assume...I shall test, if losing colours is actually an issue...
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 did a test, and yes, loosing colours is an issue. Try this:
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 addressed this issue in the latest commit