diff --git a/assets/js/components/Config/VehicleModal.vue b/assets/js/components/Config/VehicleModal.vue index 4dc1aa73e..37ada3ddf 100644 --- a/assets/js/components/Config/VehicleModal.vue +++ b/assets/js/components/Config/VehicleModal.vue @@ -318,6 +318,7 @@ export default defineComponent({ // remove icon if custom if (this.values.type === ConfigType.Custom) { delete data["icon"]; + delete data["title"]; } // trim and remove empty lines if (Array.isArray(data["identifiers"])) { diff --git a/server/http_config_device_handler.go b/server/http_config_device_handler.go index 578d2f226..c1692f26c 100644 --- a/server/http_config_device_handler.go +++ b/server/http_config_device_handler.go @@ -18,6 +18,7 @@ import ( "github.com/evcc-io/evcc/util/templates" "github.com/evcc-io/evcc/vehicle" "github.com/gorilla/mux" + "gopkg.in/yaml.v3" ) func devicesConfig[T any](class templates.Class, h config.Handler[T]) ([]map[string]any, error) { @@ -107,7 +108,25 @@ func deviceConfigMap[T any](class templates.Class, dev config.Device[T]) (map[st dc["config"] = params } else { // custom device, no masking - dc["config"] = conf.Other + config := make(map[string]any) + for k, v := range conf.Other { + config[k] = v + } + + // extract title & icon if possible (user-defined vehicle embeds) + if yamlStr, ok := conf.Other["yaml"].(string); ok && config["title"] == nil && config["icon"] == nil { + var yamlData map[string]any + if err := yaml.Unmarshal([]byte(yamlStr), &yamlData); err == nil { + if title, ok := yamlData["title"].(string); ok { + config["title"] = title + } + if icon, ok := yamlData["icon"].(string); ok { + config["icon"] = icon + } + } + } + + dc["config"] = config } } diff --git a/tests/config-vehicles.spec.ts b/tests/config-vehicles.spec.ts index dc622e77a..9283d1139 100644 --- a/tests/config-vehicles.spec.ts +++ b/tests/config-vehicles.spec.ts @@ -240,6 +240,7 @@ soc: await page.reload(); await expect(page.getByTestId("vehicle")).toHaveCount(1); + await expect(page.getByTestId("vehicle").nth(0)).toContainText("blue Honda"); await page.getByTestId("vehicle").getByRole("button", { name: "edit" }).click(); await expectModalVisible(modal); await expect(modal.getByLabel("Manufacturer")).toHaveValue("User-defined device"); @@ -265,6 +266,7 @@ soc: await modal.getByRole("button", { name: "Save" }).click(); await expectModalHidden(modal); await expect(page.getByTestId("vehicle")).toHaveCount(1); + await expect(page.getByTestId("vehicle").nth(0)).toContainText("pink Honda"); // delete await page.getByTestId("vehicle").getByRole("button", { name: "edit" }).click();