From ea64f7620266dc8b589a3bf7913ca3e575199d30 Mon Sep 17 00:00:00 2001 From: Maschga <88616799+Maschga@users.noreply.github.com> Date: Mon, 14 Jul 2025 08:19:07 +0200 Subject: [PATCH] Config UI: Add backup & restore (BC) (#22071) Co-authored-by: Michael Geers --- assets/css/app.css | 8 +- assets/js/api.ts | 24 +- assets/js/components/Auth/LoginModal.vue | 34 +- assets/js/components/Auth/PasswordInput.vue | 56 +++ .../components/Config/BackupRestoreModal.vue | 356 ++++++++++++++++++ .../components/Config/PropertyFileField.vue | 69 ++++ .../js/components/Footer/OfflineIndicator.vue | 2 +- assets/js/restart.ts | 4 + assets/js/views/Config.vue | 11 +- cmd/setup.go | 5 + core/session/db.go | 13 + i18n/de.json | 36 ++ i18n/en.json | 36 ++ server/db/db.go | 17 +- server/http.go | 9 +- server/http_site_handler.go | 176 ++++++++- tests/backup-restore.spec.ts | 250 ++++++++++++ tests/evcc.ts | 6 +- tests/vehicle-settings.spec.ts | 1 + 19 files changed, 1068 insertions(+), 45 deletions(-) create mode 100644 assets/js/components/Auth/PasswordInput.vue create mode 100644 assets/js/components/Config/BackupRestoreModal.vue create mode 100644 assets/js/components/Config/PropertyFileField.vue create mode 100644 tests/backup-restore.spec.ts diff --git a/assets/css/app.css b/assets/css/app.css index e69497075..45ce4f5c0 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -545,10 +545,10 @@ input::-webkit-datetime-edit { .form-control { color: var(--evcc-default-text); } -.form-control:disabled, -.form-control:read-only, -.dark .form-control:disabled, -.dark .form-control:read-only { +input.form-control:disabled, +input.form-control:read-only, +.dark input.form-control:disabled, +.dark input.form-control:read-only { background-color: var(--evcc-gray-10); color: var(--bs-default-text); opacity: 1; diff --git a/assets/js/api.ts b/assets/js/api.ts index 363931179..9b3753821 100644 --- a/assets/js/api.ts +++ b/assets/js/api.ts @@ -1,4 +1,4 @@ -import axios from "axios"; +import axios, { type AxiosResponse } from "axios"; import { openLoginModal } from "./components/Auth/auth"; const { protocol, hostname, port, pathname } = window.location; @@ -65,3 +65,25 @@ export const allowClientError = { return status >= 200 && status < 500; }, }; + +export function downloadFile(res: AxiosResponse) { + if (res.status === 200) { + const blob = new Blob([res.data]); + const url = window.URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + + // Try to get filename from Content-Disposition header + let filename = "evcc.txt"; + const disposition = res.headers["content-disposition"]; + if (disposition && disposition.indexOf("filename=") !== -1) { + filename = disposition.split("filename=")[1].replace(/['"]/g, "").trim(); + } + + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); + } +} diff --git a/assets/js/components/Auth/LoginModal.vue b/assets/js/components/Auth/LoginModal.vue index bd1a96356..0c63f3c79 100644 --- a/assets/js/components/Auth/LoginModal.vue +++ b/assets/js/components/Auth/LoginModal.vue @@ -11,33 +11,7 @@ {{ $t("loginModal.demoMode") }}
-
- - -
- -

{{ $t("loginModal.error") }}{{ error }}

- - {{ $t("loginModal.iframeHint") }} - +