From 0ffc7b59d6892cc1df9722f7ff73d4314361ff5b Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:54:27 -0700 Subject: [PATCH] Prevent creating views with duplicate URL (#17871) --- src/panels/lovelace/editor/config-util.ts | 42 ++++++++++++++----- .../view-editor/hui-dialog-edit-view.ts | 13 ++++-- src/translations/en.json | 4 +- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/panels/lovelace/editor/config-util.ts b/src/panels/lovelace/editor/config-util.ts index ce8f11bfbb..928d1481fb 100644 --- a/src/panels/lovelace/editor/config-util.ts +++ b/src/panels/lovelace/editor/config-util.ts @@ -3,6 +3,7 @@ import { LovelaceConfig, LovelaceViewConfig, } from "../../../data/lovelace"; +import type { HomeAssistant } from "../../../types"; export const addCard = ( config: LovelaceConfig, @@ -253,23 +254,44 @@ export const moveCard = ( }; export const addView = ( + hass: HomeAssistant, config: LovelaceConfig, viewConfig: LovelaceViewConfig -): LovelaceConfig => ({ - ...config, - views: config.views.concat(viewConfig), -}); +): LovelaceConfig => { + if (viewConfig.path && config.views.some((v) => v.path === viewConfig.path)) { + throw new Error( + hass.localize("ui.panel.lovelace.editor.edit_view.error_same_url") + ); + } + return { + ...config, + views: config.views.concat(viewConfig), + }; +}; export const replaceView = ( + hass: HomeAssistant, config: LovelaceConfig, viewIndex: number, viewConfig: LovelaceViewConfig -): LovelaceConfig => ({ - ...config, - views: config.views.map((origView, index) => - index === viewIndex ? viewConfig : origView - ), -}); +): LovelaceConfig => { + if ( + viewConfig.path && + config.views.some( + (v, idx) => v.path === viewConfig.path && idx !== viewIndex + ) + ) { + throw new Error( + hass.localize("ui.panel.lovelace.editor.edit_view.error_same_url") + ); + } + return { + ...config, + views: config.views.map((origView, index) => + index === viewIndex ? viewConfig : origView + ), + }; +}; export const swapView = ( config: LovelaceConfig, diff --git a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts index d873e8d5e1..fc5b46aa26 100644 --- a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts +++ b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts @@ -405,8 +405,13 @@ export class HuiDialogEditView extends LitElement { try { await lovelace.saveConfig( this._creatingView - ? addView(lovelace.config, viewConf) - : replaceView(lovelace.config, this._params.viewIndex!, viewConf) + ? addView(this.hass!, lovelace.config, viewConf) + : replaceView( + this.hass!, + lovelace.config, + this._params.viewIndex!, + viewConf + ) ); if (this._params.saveCallback) { this._params.saveCallback( @@ -417,7 +422,9 @@ export class HuiDialogEditView extends LitElement { this.closeDialog(); } catch (err: any) { showAlertDialog(this, { - text: `Saving failed: ${err.message}`, + text: `${this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.saving_failed" + )}: ${err.message}`, }); } finally { this._saving = false; diff --git a/src/translations/en.json b/src/translations/en.json index f08aa1c7c2..c21d6da366 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -4641,7 +4641,9 @@ "subview": "Subview", "subview_helper": "Subviews don't appear in tabs and have a back button.", "edit_ui": "Edit in visual editor", - "edit_yaml": "Edit in YAML" + "edit_yaml": "Edit in YAML", + "saving_failed": "Saving failed", + "error_same_url": "You cannot save a view with the same URL as a different existing view." }, "edit_badges": { "view_no_badges": "Badges are not be supported by the current view type."