2022-02-01 19:52:09 +01:00
|
|
|
|
console.info("Config Editor 3.5");
|
2021-12-03 02:46:05 +01:00
|
|
|
|
const LitElement = window.LitElement || Object.getPrototypeOf(customElements.get("hui-masonry-view") );
|
2021-12-01 03:01:04 +01:00
|
|
|
|
const html = LitElement.prototype.html;
|
2022-01-18 21:01:53 +01:00
|
|
|
|
const css = LitElement.prototype.css;
|
2021-12-01 03:01:04 +01:00
|
|
|
|
|
|
|
|
|
class ConfigEditor extends LitElement {
|
2022-01-18 21:01:53 +01:00
|
|
|
|
|
2021-12-01 03:01:04 +01:00
|
|
|
|
static get properties() {
|
|
|
|
|
return {
|
2021-12-03 02:46:05 +01:00
|
|
|
|
_hass: {type: Object},
|
2021-12-01 03:01:04 +01:00
|
|
|
|
code: {type: String},
|
|
|
|
|
fileList: {type: Array},
|
|
|
|
|
openedFile: {type: String},
|
2022-01-17 18:54:19 +01:00
|
|
|
|
infoLine: {type: String},
|
|
|
|
|
alertLine: {type: String},
|
|
|
|
|
edit: {},
|
2021-12-03 02:46:05 +01:00
|
|
|
|
};
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
super();
|
|
|
|
|
this.code = '';
|
|
|
|
|
this.fileList = [];
|
|
|
|
|
this.openedFile = '';
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.infoLine = '';
|
|
|
|
|
this.alertLine = '';
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-18 21:01:53 +01:00
|
|
|
|
static get styles() {
|
|
|
|
|
return css`
|
|
|
|
|
textarea{
|
|
|
|
|
width:98%;
|
|
|
|
|
height:80vh;
|
|
|
|
|
padding:5px;
|
|
|
|
|
overflow-wrap:normal;
|
|
|
|
|
white-space:pre}
|
|
|
|
|
.top{min-height:calc(100vh - var(--header-height))}
|
|
|
|
|
.pin{text-align:right}
|
|
|
|
|
.pin label{cursor:pointer}
|
|
|
|
|
.bar{
|
|
|
|
|
position:-webkit-sticky;
|
|
|
|
|
position:sticky;
|
|
|
|
|
bottom:0;
|
|
|
|
|
z-index:2;
|
|
|
|
|
background:var(--app-header-background-color);
|
|
|
|
|
color:var(--app-header-text-color,white)}
|
|
|
|
|
.bar i{background:#ff7a81;cursor:pointer}
|
|
|
|
|
`;
|
|
|
|
|
}
|
2021-12-01 03:01:04 +01:00
|
|
|
|
render() {
|
2022-01-18 21:01:53 +01:00
|
|
|
|
const hver=this._hass.states['config_editor.version'];
|
2022-01-18 15:52:29 +01:00
|
|
|
|
if(!hver){return html`<ha-card>Missing 'config_editor:' in configuration.yaml
|
|
|
|
|
for github.com/htmltiger/config-editor</ha-card>`;}
|
2022-01-18 21:01:53 +01:00
|
|
|
|
if(hver.state != '3'){return html`<ha-card>Please upgrade
|
2022-01-18 15:52:29 +01:00
|
|
|
|
github.com/htmltiger/config-editor</ha-card>`;}
|
2021-12-01 03:01:04 +01:00
|
|
|
|
if(this.fileList.length<1){
|
2022-01-18 21:01:53 +01:00
|
|
|
|
this.openedFile = this.localGet('Open')||'';
|
|
|
|
|
this.edit.ext = this.localGet('Ext')||'yaml';
|
|
|
|
|
this.edit.plainBox = this.localGet('Plain')||'';
|
|
|
|
|
if(this.fileList = JSON.parse(this.localGet('List'+this.edit.ext))){
|
|
|
|
|
if(this.openedFile.endsWith("."+this.edit.ext)){
|
|
|
|
|
setTimeout(this.oldText, 500, this);
|
|
|
|
|
}
|
|
|
|
|
}else{this.List();}
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
2022-01-08 20:11:27 +01:00
|
|
|
|
|
2021-12-01 03:01:04 +01:00
|
|
|
|
return html`
|
|
|
|
|
<ha-card>
|
2022-01-18 21:01:53 +01:00
|
|
|
|
<div class="top">
|
|
|
|
|
<div class="pin">
|
2022-01-18 03:27:10 +01:00
|
|
|
|
<select @change=${this.extChange}>
|
2022-01-18 15:52:29 +01:00
|
|
|
|
${["yaml","py","json","conf","js","txt","log"].map(value =>
|
|
|
|
|
html`<option ?selected=${value === this.edit.ext }
|
|
|
|
|
value=${value}>${value.toUpperCase()}</option>`)}
|
2022-01-18 03:27:10 +01:00
|
|
|
|
</select>
|
2022-02-01 19:52:09 +01:00
|
|
|
|
<label>Basic Editor<input type="checkbox"
|
2022-01-18 21:01:53 +01:00
|
|
|
|
?checked=${this.edit.plainBox=='1'}
|
2022-01-18 15:52:29 +01:00
|
|
|
|
name="plain" value="1" @change=${this.plainChange}></label>
|
2021-12-01 03:01:04 +01:00
|
|
|
|
</div>
|
2022-01-18 15:52:29 +01:00
|
|
|
|
${this.edit.plainBox ?
|
2022-02-01 21:59:03 +01:00
|
|
|
|
html`<textarea rows="10" id="code" @keydown=${this.saveKey}
|
|
|
|
|
@change=${this.updateText}>${this.code}</textarea>`:
|
|
|
|
|
html`<ha-code-editor id="code" @keydown=${this.saveKey} hasAutocomplete mode="yaml"
|
|
|
|
|
@value-changed=${this.updateText} dir="ltr" .hass=${this._hass}></ha-code-editor>`}
|
2022-01-18 15:52:29 +01:00
|
|
|
|
</div>
|
2022-01-18 21:01:53 +01:00
|
|
|
|
<div class="bar">
|
2022-01-17 18:54:19 +01:00
|
|
|
|
<div>${this.alertLine}</div>
|
2022-01-11 20:21:14 +01:00
|
|
|
|
<div>
|
|
|
|
|
<button @click="${this.List}">Get List</button>
|
|
|
|
|
<select @change=${this.Load}>
|
2022-01-18 15:52:29 +01:00
|
|
|
|
${[''].concat(this.fileList).map(value =>
|
|
|
|
|
html`<option ?selected=${value === this.openedFile}
|
|
|
|
|
value=${value}>${value}</option>`)}
|
2022-01-11 20:21:14 +01:00
|
|
|
|
</select>
|
|
|
|
|
<button @click="${this.Save}">Save</button>
|
|
|
|
|
</div>
|
2022-01-17 18:54:19 +01:00
|
|
|
|
<code>#${this.infoLine}</code>
|
2022-01-04 17:50:54 +01:00
|
|
|
|
</div>
|
2021-12-01 03:01:04 +01:00
|
|
|
|
</ha-card>
|
|
|
|
|
`;
|
2022-02-01 19:52:09 +01:00
|
|
|
|
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-18 03:27:10 +01:00
|
|
|
|
extChange(e){
|
|
|
|
|
this.edit.ext = e.target.value;
|
2022-01-18 21:01:53 +01:00
|
|
|
|
this.localSet('Ext', this.edit.ext);
|
2022-01-18 03:27:10 +01:00
|
|
|
|
this.openedFile = '';
|
|
|
|
|
this.oldText(this);
|
|
|
|
|
this.List();
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-18 21:01:53 +01:00
|
|
|
|
plainChange(){
|
|
|
|
|
this.edit.plainBox = this.edit.plainBox?'':'1';
|
|
|
|
|
this.localSet('Plain', this.edit.plainBox);
|
2022-01-17 15:37:25 +01:00
|
|
|
|
this.List();
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-01 03:01:04 +01:00
|
|
|
|
updateText(e) {
|
2022-02-01 19:52:09 +01:00
|
|
|
|
e.stopPropagation();
|
2022-01-17 15:37:25 +01:00
|
|
|
|
this.code = this.edit.plainBox ? e.target.value : e.detail.value;
|
2022-01-18 21:01:53 +01:00
|
|
|
|
if(this.openedFile){this.localSet('Text', this.code);}
|
2022-01-08 20:11:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-10 22:00:35 +01:00
|
|
|
|
Unsave(){
|
2022-01-18 21:01:53 +01:00
|
|
|
|
this.code = this.localGet('Unsaved');
|
2022-01-10 22:00:35 +01:00
|
|
|
|
this.renderRoot.querySelector('#code').value=this.code;
|
2022-01-18 21:01:53 +01:00
|
|
|
|
this.localSet('Unsaved','');
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.alertLine = '';
|
2022-01-22 02:50:34 +01:00
|
|
|
|
this.Toast("Loaded from browser",1500);
|
2022-01-10 22:00:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-18 21:01:53 +01:00
|
|
|
|
localGet(e){
|
|
|
|
|
return localStorage.getItem('config_editor'+e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
localSet(k,v){
|
|
|
|
|
localStorage.setItem('config_editor'+k,v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd(action, data, file){
|
|
|
|
|
return this._hass.callWS({type: "config_editor/ws", action: action,
|
|
|
|
|
data: data, file: file, ext: this.edit.ext});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
saveList(){
|
|
|
|
|
this.localSet('List'+this.edit.ext, JSON.stringify(this.fileList));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oldText(dhis){
|
2022-01-10 22:00:35 +01:00
|
|
|
|
dhis.Load({target:{value:dhis.openedFile}});
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-01 19:52:09 +01:00
|
|
|
|
saveKey(e) {
|
|
|
|
|
if((e.key == 'S' || e.key == 's' ) && (e.ctrlKey || e.metaKey)){
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
this.Save();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Toast(message, duration){
|
2022-01-22 02:50:34 +01:00
|
|
|
|
const e = new Event("hass-notification",
|
|
|
|
|
{bubbles: true, cancelable: false, composed: true});
|
2022-02-01 19:52:09 +01:00
|
|
|
|
e.detail = {message, duration, dismissable: true,
|
|
|
|
|
//action: {text:"Save",action:()=>{this.sureSave();}},
|
|
|
|
|
};
|
2022-01-22 02:50:34 +01:00
|
|
|
|
document.querySelector("home-assistant").dispatchEvent(e);
|
|
|
|
|
}
|
2022-02-01 19:52:09 +01:00
|
|
|
|
//sureSave(){console.log(this.openedFile);}
|
2022-01-22 02:50:34 +01:00
|
|
|
|
|
2021-12-03 02:46:05 +01:00
|
|
|
|
async Coder(){
|
2022-02-01 19:52:09 +01:00
|
|
|
|
const c="ha-yaml-editor";
|
|
|
|
|
if(customElements.get(c)){return;}
|
2021-12-03 02:46:05 +01:00
|
|
|
|
await customElements.whenDefined("partial-panel-resolver");
|
|
|
|
|
const p = document.createElement('partial-panel-resolver');
|
2022-02-01 19:52:09 +01:00
|
|
|
|
p.hass = {panels: [{url_path: "tmp", component_name: "config"}]};
|
2021-12-03 02:46:05 +01:00
|
|
|
|
p._updateRoutes();
|
2022-01-18 21:01:53 +01:00
|
|
|
|
await p.routerOptions.routes.tmp.load();
|
2022-02-01 19:52:09 +01:00
|
|
|
|
const d=document.createElement("ha-panel-config");
|
|
|
|
|
await d.routerOptions.routes.automation.load();
|
|
|
|
|
if(!customElements.get(c)){
|
|
|
|
|
this.localSet('Plain', 1);
|
|
|
|
|
console.log('failed '+c);
|
|
|
|
|
}
|
2021-12-03 02:46:05 +01:00
|
|
|
|
}
|
2022-01-18 21:01:53 +01:00
|
|
|
|
|
2021-12-01 03:01:04 +01:00
|
|
|
|
async List(){
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.infoLine = 'List Loading...';
|
2022-01-18 21:01:53 +01:00
|
|
|
|
const e=await this.cmd('list','','');
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.infoLine = e.msg;
|
2021-12-30 03:44:32 +01:00
|
|
|
|
this.fileList = e.file.slice().sort();
|
2022-01-18 21:01:53 +01:00
|
|
|
|
this.saveList();
|
2022-01-18 03:27:10 +01:00
|
|
|
|
if(this.openedFile.endsWith("."+this.edit.ext)){
|
2022-01-10 22:00:35 +01:00
|
|
|
|
setTimeout(this.oldText, 500, this);
|
2022-01-08 20:11:27 +01:00
|
|
|
|
}
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
2022-01-17 18:54:19 +01:00
|
|
|
|
|
2021-12-01 03:01:04 +01:00
|
|
|
|
async Load(x) {
|
2022-02-01 19:52:09 +01:00
|
|
|
|
if(x.target.value == this.openedFile && this.code){return;}
|
|
|
|
|
if(this.edit.orgCode.trim() != this.code.trim()){
|
|
|
|
|
if(!confirm("Switch without Saving?")){x.target.value = this.openedFile; return;}
|
|
|
|
|
}
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.code = ''; this.renderRoot.querySelector('#code').value='';this.infoLine = '';
|
2022-01-18 21:01:53 +01:00
|
|
|
|
this.openedFile = x.target.value;
|
2022-01-08 20:11:27 +01:00
|
|
|
|
if(this.openedFile){
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.infoLine = 'Loading: '+this.openedFile;
|
2022-01-18 21:01:53 +01:00
|
|
|
|
const e=await this.cmd('load','',this.openedFile);
|
2022-01-08 20:11:27 +01:00
|
|
|
|
this.openedFile = e.file;
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.infoLine = e.msg;
|
2022-02-01 19:52:09 +01:00
|
|
|
|
this.Toast(this.infoLine,1000);
|
2022-01-18 21:01:53 +01:00
|
|
|
|
const uns={f:this.localGet('Open'),
|
|
|
|
|
d:this.localGet('Text')};
|
2022-01-10 22:00:35 +01:00
|
|
|
|
if(uns.f == this.openedFile && uns.d && uns.d != e.data){
|
2022-01-18 21:01:53 +01:00
|
|
|
|
this.localSet('Unsaved', uns.d);
|
|
|
|
|
this.alertLine = html`<i @click="${this.Unsave}">
|
|
|
|
|
Load unsaved from browser </i>`;
|
2022-01-10 22:00:35 +01:00
|
|
|
|
}else{
|
2022-01-18 21:01:53 +01:00
|
|
|
|
this.localSet('Text','');this.alertLine = '';
|
2022-01-10 22:00:35 +01:00
|
|
|
|
}
|
2022-01-08 20:11:27 +01:00
|
|
|
|
this.renderRoot.querySelector('#code').value=e.data;
|
|
|
|
|
this.code = e.data;
|
|
|
|
|
}
|
2022-02-01 19:52:09 +01:00
|
|
|
|
this.edit.orgCode = this.code;
|
2022-01-18 21:01:53 +01:00
|
|
|
|
this.localSet('Open', this.openedFile);
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
2022-01-18 21:01:53 +01:00
|
|
|
|
|
2021-12-01 03:01:04 +01:00
|
|
|
|
async Save() {
|
2021-12-05 04:28:10 +01:00
|
|
|
|
if(this.renderRoot.querySelector('#code').value != this.code){
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.infoLine='Something not right!';
|
2021-12-01 03:01:04 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
2022-01-18 21:01:53 +01:00
|
|
|
|
let savenew=0;
|
2021-12-05 04:28:10 +01:00
|
|
|
|
if(!this.openedFile && this.code){
|
2022-01-18 13:21:10 +01:00
|
|
|
|
this.openedFile=prompt("type abc."+this.edit.ext+" or folder/abc."+this.edit.ext);
|
2022-01-18 21:01:53 +01:00
|
|
|
|
savenew=1;
|
2021-12-05 04:28:10 +01:00
|
|
|
|
}
|
2022-01-18 13:21:10 +01:00
|
|
|
|
if(this.openedFile && this.openedFile.endsWith("."+this.edit.ext)){
|
2022-02-01 19:52:09 +01:00
|
|
|
|
if(!confirm("Save?")){if(savenew){this.openedFile='';}return;}
|
2022-01-18 21:01:53 +01:00
|
|
|
|
if(!this.code){this.infoLine=''; this.infoLine = 'Text is empty!'; return;}
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.infoLine = 'Saving: '+this.openedFile;
|
2022-01-18 21:01:53 +01:00
|
|
|
|
const e=await this.cmd('save', this.code, this.openedFile);
|
2022-01-17 18:54:19 +01:00
|
|
|
|
this.infoLine = e.msg;
|
2022-01-22 02:50:34 +01:00
|
|
|
|
this.Toast(this.infoLine,2000);
|
2022-01-18 21:01:53 +01:00
|
|
|
|
if(e.msg.includes('Saved:')){
|
|
|
|
|
this.localSet('Text','');
|
|
|
|
|
if(savenew){
|
|
|
|
|
this.fileList.unshift(this.openedFile);
|
|
|
|
|
this.saveList();
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-12-05 04:28:10 +01:00
|
|
|
|
}else{this.openedFile='';}
|
2022-02-01 19:52:09 +01:00
|
|
|
|
this.edit.orgCode = this.code;
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getCardSize() {
|
|
|
|
|
return 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setConfig(config) {
|
2022-02-01 19:52:09 +01:00
|
|
|
|
this.edit = {options: config, plainBox: false, ext: '', orgCode: ''};
|
2021-12-03 02:46:05 +01:00
|
|
|
|
this.Coder();
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set hass(hass) {
|
|
|
|
|
this._hass = hass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shouldUpdate(changedProps) {
|
2022-01-18 15:52:29 +01:00
|
|
|
|
for(const e of ['code','openedFile','fileList','infoLine','alertLine','edit']) {
|
|
|
|
|
if(changedProps.has(e)){return true;}
|
|
|
|
|
}
|
2021-12-01 03:01:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} customElements.define('config-editor-card', ConfigEditor);
|
|
|
|
|
|
|
|
|
|
window.customCards = window.customCards || [];
|
|
|
|
|
window.customCards.push({
|
|
|
|
|
type: 'config-editor-card',
|
|
|
|
|
name: 'Config Editor Card',
|
|
|
|
|
preview: false,
|
|
|
|
|
description: 'Basic editor for configuration.yaml'
|
|
|
|
|
});
|