Handle errrors/wrong values on paste (#25245)

This commit is contained in:
Bram Kragten 2025-04-30 18:45:35 +03:00 committed by Paul Bottein
parent 46cc254f77
commit efd7b380a9
No known key found for this signature in database
4 changed files with 181 additions and 145 deletions

View File

@ -24,6 +24,10 @@ export class HaToast extends Snackbar {
max-width: 650px; max-width: 650px;
} }
.mdc-snackbar__actions {
color: rgba(255, 255, 255, 0.87);
}
/* Revert the default styles set by mwc-snackbar */ /* Revert the default styles set by mwc-snackbar */
@media (max-width: 480px), (max-width: 344px) { @media (max-width: 480px), (max-width: 344px) {
.mdc-snackbar__surface { .mdc-snackbar__surface {

View File

@ -314,104 +314,119 @@ export class HaManualAutomationEditor extends LitElement {
return; return;
} }
const loaded: any = load(paste); let loaded: any;
if (loaded) { try {
let config = loaded; loaded = load(paste);
} catch (_err: any) {
showToast(this, {
message: this.hass.localize(
"ui.panel.config.automation.editor.paste_invalid_yaml"
),
duration: 4000,
dismissable: true,
});
return;
}
if ("automation" in config) { if (!loaded || typeof loaded !== "object") {
config = config.automation; return;
if (Array.isArray(config)) { }
config = config[0];
}
}
let config = loaded;
if ("automation" in config) {
config = config.automation;
if (Array.isArray(config)) { if (Array.isArray(config)) {
if (config.length === 1) { config = config[0];
config = config[0]; }
} else { }
const newConfig: AutomationConfig = {
triggers: [], if (Array.isArray(config)) {
conditions: [], if (config.length === 1) {
actions: [], config = config[0];
}; } else {
let found = false; const newConfig: AutomationConfig = {
config.forEach((cfg: any) => { triggers: [],
if (isTrigger(cfg)) { conditions: [],
found = true; actions: [],
(newConfig.triggers as Trigger[]).push(cfg); };
} let found = false;
if (isCondition(cfg)) { config.forEach((cfg: any) => {
found = true; if (isTrigger(cfg)) {
(newConfig.conditions as Condition[]).push(cfg); found = true;
} (newConfig.triggers as Trigger[]).push(cfg);
if (getActionType(cfg) !== "unknown") { }
found = true; if (isCondition(cfg)) {
(newConfig.actions as Action[]).push(cfg); found = true;
} (newConfig.conditions as Condition[]).push(cfg);
}); }
if (found) { if (getActionType(cfg) !== "unknown") {
config = newConfig; found = true;
(newConfig.actions as Action[]).push(cfg);
} }
}
}
if (isTrigger(config)) {
config = { triggers: [config] };
}
if (isCondition(config)) {
config = { conditions: [config] };
}
if (getActionType(config) !== "unknown") {
config = { actions: [config] };
}
let normalized: AutomationConfig;
try {
normalized = normalizeAutomationConfig(config);
} catch (_err: any) {
return;
}
try {
assert(normalized, automationConfigStruct);
} catch (_err: any) {
showToast(this, {
message: this.hass.localize(
"ui.panel.config.automation.editor.paste_invalid_config"
),
duration: 4000,
dismissable: true,
}); });
return; if (found) {
} config = newConfig;
if (normalized) {
ev.preventDefault();
if (this.dirty) {
const result = await new Promise<boolean>((resolve) => {
showPasteReplaceDialog(this, {
domain: "automation",
pastedConfig: normalized,
onClose: () => resolve(false),
onAppend: () => {
this._appendToExistingConfig(normalized);
resolve(false);
},
onReplace: () => resolve(true),
});
});
if (!result) {
return;
}
} }
// replace the config completely
this._replaceExistingConfig(normalized);
} }
} }
if (isTrigger(config)) {
config = { triggers: [config] };
}
if (isCondition(config)) {
config = { conditions: [config] };
}
if (getActionType(config) !== "unknown") {
config = { actions: [config] };
}
let normalized: AutomationConfig;
try {
normalized = normalizeAutomationConfig(config);
} catch (_err: any) {
return;
}
try {
assert(normalized, automationConfigStruct);
} catch (_err: any) {
showToast(this, {
message: this.hass.localize(
"ui.panel.config.automation.editor.paste_invalid_config"
),
duration: 4000,
dismissable: true,
});
return;
}
if (normalized) {
ev.preventDefault();
if (this.dirty) {
const result = await new Promise<boolean>((resolve) => {
showPasteReplaceDialog(this, {
domain: "automation",
pastedConfig: normalized,
onClose: () => resolve(false),
onAppend: () => {
this._appendToExistingConfig(normalized);
resolve(false);
},
onReplace: () => resolve(true),
});
});
if (!result) {
return;
}
}
// replace the config completely
this._replaceExistingConfig(normalized);
}
}; };
private _appendToExistingConfig(config: ManualAutomationConfig) { private _appendToExistingConfig(config: ManualAutomationConfig) {

View File

@ -238,75 +238,90 @@ export class HaManualScriptEditor extends LitElement {
return; return;
} }
const loaded: any = load(paste); let loaded: any;
if (loaded) { try {
let config = loaded; loaded = load(paste);
} catch (_err: any) {
showToast(this, {
message: this.hass.localize(
"ui.panel.config.script.editor.paste_invalid_config"
),
duration: 4000,
dismissable: true,
});
return;
}
if ("script" in config) { if (!loaded || typeof loaded !== "object") {
config = config.script; return;
if (Object.keys(config).length) { }
config = config[Object.keys(config)[0]];
} let config = loaded;
if ("script" in config) {
config = config.script;
if (Object.keys(config).length) {
config = config[Object.keys(config)[0]];
} }
}
if (Array.isArray(config)) { if (Array.isArray(config)) {
if (config.length === 1) { if (config.length === 1) {
config = config[0]; config = config[0];
} else { } else {
config = { sequence: config }; config = { sequence: config };
}
} }
}
if (!["sequence", "unknown"].includes(getActionType(config))) { if (!["sequence", "unknown"].includes(getActionType(config))) {
config = { sequence: [config] }; config = { sequence: [config] };
} }
let normalized: ScriptConfig | undefined; let normalized: ScriptConfig | undefined;
try { try {
normalized = normalizeScriptConfig(config); normalized = normalizeScriptConfig(config);
} catch (_err: any) { } catch (_err: any) {
return; return;
} }
try { try {
assert(normalized, scriptConfigStruct); assert(normalized, scriptConfigStruct);
} catch (_err: any) { } catch (_err: any) {
showToast(this, { showToast(this, {
message: this.hass.localize( message: this.hass.localize(
"ui.panel.config.script.editor.paste_invalid_config" "ui.panel.config.script.editor.paste_invalid_config"
), ),
duration: 4000, duration: 4000,
dismissable: true, dismissable: true,
}); });
return; return;
} }
if (normalized) { if (normalized) {
ev.preventDefault(); ev.preventDefault();
if (this.dirty) { if (this.dirty) {
const result = await new Promise<boolean>((resolve) => { const result = await new Promise<boolean>((resolve) => {
showPasteReplaceDialog(this, { showPasteReplaceDialog(this, {
domain: "script", domain: "script",
pastedConfig: normalized, pastedConfig: normalized,
onClose: () => resolve(false), onClose: () => resolve(false),
onAppend: () => { onAppend: () => {
this._appendToExistingConfig(normalized); this._appendToExistingConfig(normalized);
resolve(false); resolve(false);
}, },
onReplace: () => resolve(true), onReplace: () => resolve(true),
});
}); });
});
if (!result) { if (!result) {
return; return;
}
} }
// replace the config completely
this._replaceExistingConfig(normalized);
} }
// replace the config completely
this._replaceExistingConfig(normalized);
} }
}; };

View File

@ -4356,6 +4356,7 @@
"text": "How do you want to paste your automation?" "text": "How do you want to paste your automation?"
}, },
"paste_toast_message": "Pasted automation from clipboard", "paste_toast_message": "Pasted automation from clipboard",
"paste_invalid_yaml": "Pasted value is not valid YAML",
"paste_invalid_config": "Pasted automation is not editable in the visual editor" "paste_invalid_config": "Pasted automation is not editable in the visual editor"
}, },
"trace": { "trace": {
@ -4595,6 +4596,7 @@
"text": "How do you want to paste your script?" "text": "How do you want to paste your script?"
}, },
"paste_toast_message": "Pasted script from clipboard", "paste_toast_message": "Pasted script from clipboard",
"paste_invalid_yaml": "Pasted value is not valid YAML",
"paste_invalid_config": "Pasted script is not editable in the visual editor" "paste_invalid_config": "Pasted script is not editable in the visual editor"
}, },
"trace": { "trace": {