mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-01 13:37:47 +00:00
Convert YAMLTextArea to code mirror editor (#3980)
* Convert YAMLTextArea to code mirror editor * Review comments * Clean up
This commit is contained in:
parent
ab75365636
commit
88c480759f
@ -3,9 +3,7 @@ import CodeMirror from "codemirror";
|
|||||||
import "codemirror/mode/yaml/yaml";
|
import "codemirror/mode/yaml/yaml";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import codeMirrorCSS from "codemirror/lib/codemirror.css";
|
import codeMirrorCSS from "codemirror/lib/codemirror.css";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
|
||||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
|
||||||
import { customElement } from "lit-element";
|
import { customElement } from "lit-element";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -17,12 +15,11 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@customElement("hui-yaml-editor")
|
@customElement("ha-yaml-editor")
|
||||||
export class HuiYamlEditor extends HTMLElement {
|
export class HaYamlEditor extends HTMLElement {
|
||||||
public _hass?: HomeAssistant;
|
public codemirror?: any;
|
||||||
|
private _autofocus = false;
|
||||||
public codemirror!: any;
|
private _rtl = false;
|
||||||
|
|
||||||
private _value: string;
|
private _value: string;
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
@ -47,8 +44,11 @@ export class HuiYamlEditor extends HTMLElement {
|
|||||||
background-color: var(--paper-dialog-background-color, var(--primary-background-color));
|
background-color: var(--paper-dialog-background-color, var(--primary-background-color));
|
||||||
transition: 0.2s ease border-right;
|
transition: 0.2s ease border-right;
|
||||||
}
|
}
|
||||||
|
:host(.error-state) .CodeMirror-gutters {
|
||||||
|
border-color: var(--error-state-color, red);
|
||||||
|
}
|
||||||
.CodeMirror-focused .CodeMirror-gutters {
|
.CodeMirror-focused .CodeMirror-gutters {
|
||||||
border-right: 2px solid var(--paper-input-container-focus-color, var(--primary-color));;
|
border-right: 2px solid var(--paper-input-container-focus-color, var(--primary-color));
|
||||||
}
|
}
|
||||||
.CodeMirror-linenumber {
|
.CodeMirror-linenumber {
|
||||||
color: var(--paper-dialog-color, var(--primary-text-color));
|
color: var(--paper-dialog-color, var(--primary-text-color));
|
||||||
@ -63,13 +63,6 @@ export class HuiYamlEditor extends HTMLElement {
|
|||||||
</style>`;
|
</style>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
set hass(hass: HomeAssistant) {
|
|
||||||
this._hass = hass;
|
|
||||||
if (this._hass) {
|
|
||||||
this.setScrollBarDirection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set value(value: string) {
|
set value(value: string) {
|
||||||
if (this.codemirror) {
|
if (this.codemirror) {
|
||||||
if (value !== this.codemirror.getValue()) {
|
if (value !== this.codemirror.getValue()) {
|
||||||
@ -83,6 +76,22 @@ export class HuiYamlEditor extends HTMLElement {
|
|||||||
return this.codemirror.getValue();
|
return this.codemirror.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set rtl(rtl: boolean) {
|
||||||
|
this._rtl = rtl;
|
||||||
|
this.setScrollBarDirection();
|
||||||
|
}
|
||||||
|
|
||||||
|
set autofocus(autofocus: boolean) {
|
||||||
|
this._autofocus = autofocus;
|
||||||
|
if (this.codemirror) {
|
||||||
|
this.codemirror.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set error(error: boolean) {
|
||||||
|
this.classList.toggle("error-state", error);
|
||||||
|
}
|
||||||
|
|
||||||
get hasComments(): boolean {
|
get hasComments(): boolean {
|
||||||
return this.shadowRoot!.querySelector("span.cm-comment") ? true : false;
|
return this.shadowRoot!.querySelector("span.cm-comment") ? true : false;
|
||||||
}
|
}
|
||||||
@ -96,16 +105,13 @@ export class HuiYamlEditor extends HTMLElement {
|
|||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
mode: "yaml",
|
mode: "yaml",
|
||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
autofocus: true,
|
autofocus: this._autofocus,
|
||||||
viewportMargin: Infinity,
|
viewportMargin: Infinity,
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
Tab: "indentMore",
|
Tab: "indentMore",
|
||||||
"Shift-Tab": "indentLess",
|
"Shift-Tab": "indentLess",
|
||||||
},
|
},
|
||||||
gutters:
|
gutters: this._rtl ? ["rtl-gutter", "CodeMirror-linenumbers"] : [],
|
||||||
this._hass && computeRTL(this._hass!)
|
|
||||||
? ["rtl-gutter", "CodeMirror-linenumbers"]
|
|
||||||
: [],
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.setScrollBarDirection();
|
this.setScrollBarDirection();
|
||||||
@ -120,18 +126,14 @@ export class HuiYamlEditor extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private setScrollBarDirection(): void {
|
private setScrollBarDirection(): void {
|
||||||
if (!this.codemirror) {
|
if (this.codemirror) {
|
||||||
return;
|
this.codemirror.getWrapperElement().classList.toggle("rtl", this._rtl);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.codemirror
|
|
||||||
.getWrapperElement()
|
|
||||||
.classList.toggle("rtl", computeRTL(this._hass!));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"hui-yaml-editor": HuiYamlEditor;
|
"ha-yaml-editor": HaYamlEditor;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ declare global {
|
|||||||
"ha-device-picker": any;
|
"ha-device-picker": any;
|
||||||
"ha-device-condition-picker": any;
|
"ha-device-condition-picker": any;
|
||||||
"ha-textarea": any;
|
"ha-textarea": any;
|
||||||
|
"ha-yaml-editor": any;
|
||||||
"ha-service-picker": any;
|
"ha-service-picker": any;
|
||||||
"mwc-button": any;
|
"mwc-button": any;
|
||||||
"ha-device-trigger-picker": any;
|
"ha-device-trigger-picker": any;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { h, Component } from "preact";
|
import { h, Component } from "preact";
|
||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
import "../../../components/ha-textarea";
|
import "../../../components/ha-yaml-editor";
|
||||||
|
// tslint:disable-next-line
|
||||||
|
import { HaYamlEditor } from "../../../components/ha-yaml-editor";
|
||||||
|
|
||||||
const isEmpty = (obj: object) => {
|
const isEmpty = (obj: object) => {
|
||||||
for (const key in obj) {
|
for (const key in obj) {
|
||||||
@ -12,6 +14,8 @@ const isEmpty = (obj: object) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default class YAMLTextArea extends Component<any, any> {
|
export default class YAMLTextArea extends Component<any, any> {
|
||||||
|
private _yamlEditor!: HaYamlEditor;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -34,7 +38,7 @@ export default class YAMLTextArea extends Component<any, any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onChange(ev) {
|
public onChange(ev) {
|
||||||
const value = ev.target.value;
|
const value = ev.detail.value;
|
||||||
let parsed;
|
let parsed;
|
||||||
let isValid = true;
|
let isValid = true;
|
||||||
|
|
||||||
@ -59,22 +63,30 @@ export default class YAMLTextArea extends Component<any, any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._yamlEditor.codemirror.refresh();
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
public render({ label }, { value, isValid }) {
|
public render({ label }, { value, isValid }) {
|
||||||
const style: any = {
|
const style: any = {
|
||||||
minWidth: 300,
|
minWidth: 300,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
};
|
};
|
||||||
if (!isValid) {
|
|
||||||
style.border = "1px solid red";
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<ha-textarea
|
<div>
|
||||||
label={label}
|
<p>{label}</p>
|
||||||
value={value}
|
<ha-yaml-editor
|
||||||
style={style}
|
ref={this._storeYamlEditorRef}
|
||||||
onvalue-changed={this.onChange}
|
style={style}
|
||||||
dir="ltr"
|
value={value}
|
||||||
/>
|
error={isValid === false}
|
||||||
|
onyaml-changed={this.onChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _storeYamlEditorRef = (yamlEditor) => (this._yamlEditor = yamlEditor);
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,12 @@ import { HomeAssistant } from "../../../../types";
|
|||||||
import { LovelaceCardConfig } from "../../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../../data/lovelace";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { getCardElementTag } from "../../common/get-card-element-tag";
|
import { getCardElementTag } from "../../common/get-card-element-tag";
|
||||||
|
import { computeRTL } from "../../../../common/util/compute_rtl";
|
||||||
|
|
||||||
import "../../components/hui-yaml-editor";
|
import "../../../../components/ha-yaml-editor";
|
||||||
// This is not a duplicate import, one is for types, one is for element.
|
// This is not a duplicate import, one is for types, one is for element.
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
import { HuiYamlEditor } from "../../components/hui-yaml-editor";
|
import { HaYamlEditor } from "../../../../components/ha-yaml-editor";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { EntityConfig } from "../../entity-rows/types";
|
import { EntityConfig } from "../../entity-rows/types";
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ export interface UIConfigChangedEvent extends Event {
|
|||||||
|
|
||||||
@customElement("hui-card-editor")
|
@customElement("hui-card-editor")
|
||||||
export class HuiCardEditor extends LitElement {
|
export class HuiCardEditor extends LitElement {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() private _yaml?: string;
|
@property() private _yaml?: string;
|
||||||
@property() private _config?: LovelaceCardConfig;
|
@property() private _config?: LovelaceCardConfig;
|
||||||
@ -93,8 +94,8 @@ export class HuiCardEditor extends LitElement {
|
|||||||
return this._error !== undefined;
|
return this._error !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _yamlEditor(): HuiYamlEditor {
|
private get _yamlEditor(): HaYamlEditor {
|
||||||
return this.shadowRoot!.querySelector("hui-yaml-editor")!;
|
return this.shadowRoot!.querySelector("ha-yaml-editor")!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleMode() {
|
public toggleMode() {
|
||||||
@ -120,11 +121,12 @@ export class HuiCardEditor extends LitElement {
|
|||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<div class="yaml-editor">
|
<div class="yaml-editor">
|
||||||
<hui-yaml-editor
|
<ha-yaml-editor
|
||||||
.hass=${this.hass}
|
.autofocus=${true}
|
||||||
|
.rtl=${computeRTL(this.hass)}
|
||||||
.value=${this.yaml}
|
.value=${this.yaml}
|
||||||
@yaml-changed=${this._handleYAMLChanged}
|
@yaml-changed=${this._handleYAMLChanged}
|
||||||
></hui-yaml-editor>
|
></ha-yaml-editor>
|
||||||
</div>
|
</div>
|
||||||
`}
|
`}
|
||||||
${this._error
|
${this._error
|
||||||
|
@ -14,11 +14,12 @@ import { Lovelace } from "./types";
|
|||||||
|
|
||||||
import "../../components/ha-icon";
|
import "../../components/ha-icon";
|
||||||
import { haStyle } from "../../resources/styles";
|
import { haStyle } from "../../resources/styles";
|
||||||
import "./components/hui-yaml-editor";
|
import "../../components/ha-yaml-editor";
|
||||||
// This is not a duplicate import, one is for types, one is for element.
|
// This is not a duplicate import, one is for types, one is for element.
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
import { HuiYamlEditor } from "./components/hui-yaml-editor";
|
import { HaYamlEditor } from "../../components/ha-yaml-editor";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
|
import { computeRTL } from "../../common/util/compute_rtl";
|
||||||
|
|
||||||
const lovelaceStruct = struct.interface({
|
const lovelaceStruct = struct.interface({
|
||||||
title: "string?",
|
title: "string?",
|
||||||
@ -27,7 +28,7 @@ const lovelaceStruct = struct.interface({
|
|||||||
});
|
});
|
||||||
|
|
||||||
class LovelaceFullConfigEditor extends LitElement {
|
class LovelaceFullConfigEditor extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
public hass!: HomeAssistant;
|
||||||
public lovelace?: Lovelace;
|
public lovelace?: Lovelace;
|
||||||
public closeEditor?: () => void;
|
public closeEditor?: () => void;
|
||||||
private _saving?: boolean;
|
private _saving?: boolean;
|
||||||
@ -80,12 +81,14 @@ class LovelaceFullConfigEditor extends LitElement {
|
|||||||
</app-toolbar>
|
</app-toolbar>
|
||||||
</app-header>
|
</app-header>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<hui-yaml-editor
|
<ha-yaml-editor
|
||||||
|
.autofocus=${true}
|
||||||
|
.rtl=${computeRTL(this.hass)}
|
||||||
.hass="${this.hass}"
|
.hass="${this.hass}"
|
||||||
@yaml-changed="${this._yamlChanged}"
|
@yaml-changed="${this._yamlChanged}"
|
||||||
@yaml-save="${this._handleSave}"
|
@yaml-save="${this._handleSave}"
|
||||||
>
|
>
|
||||||
</hui-yaml-editor>
|
</ha-yaml-editor>
|
||||||
</div>
|
</div>
|
||||||
</app-header-layout>
|
</app-header-layout>
|
||||||
`;
|
`;
|
||||||
@ -205,8 +208,8 @@ class LovelaceFullConfigEditor extends LitElement {
|
|||||||
this._changed = false;
|
this._changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private get yamlEditor(): HuiYamlEditor {
|
private get yamlEditor(): HaYamlEditor {
|
||||||
return this.shadowRoot!.querySelector("hui-yaml-editor")!;
|
return this.shadowRoot!.querySelector("ha-yaml-editor")!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@ documentContainer.innerHTML = `<custom-style>
|
|||||||
|
|
||||||
--scrollbar-thumb-color: rgb(194, 194, 194);
|
--scrollbar-thumb-color: rgb(194, 194, 194);
|
||||||
|
|
||||||
|
--error-state-color: #db4437;
|
||||||
|
|
||||||
/* states and badges */
|
/* states and badges */
|
||||||
--state-icon-color: #44739e;
|
--state-icon-color: #44739e;
|
||||||
--state-icon-active-color: #FDD835;
|
--state-icon-active-color: #FDD835;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user