From 4203ca93db3307c401fba76fbdd3a48f422e2e7a Mon Sep 17 00:00:00 2001 From: tajniak81 <13187254+tajniak81@users.noreply.github.com> Date: Tue, 1 Sep 2026 11:12:17 +0200 Subject: [PATCH] What a charger is, readable without a CSMS to control it with MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Home chargers tab put a card where the control panel goes and, with neither Own nor Proxy CSMS turned on, filled it with a single sentence pointing at Settings — an empty box beside a list of two real chargers the app already knew the vendor, model and serial of. That knowledge now has somewhere to be. Charger information lists every imported charger with the fields its record actually holds; a field the service never sent is left out rather than shown as a dash, and the provider's own id appears only when it is something other than the serial. The selected charger carries the same accent ring the list beside it does, so picking one still reads as picking the one control drives. The card stands on its own either way: with control on it sits beneath it, and with control off the Settings hint becomes a footnote under something worth reading instead of the whole card. Co-Authored-By: Claude Opus 5 --- Web App/web/src/i18n/da.json | 12 +++++ Web App/web/src/i18n/en.json | 12 +++++ Web App/web/src/i18n/pl.json | 12 +++++ Web App/web/src/views/Charging.vue | 75 ++++++++++++++++++++++++++---- 4 files changed, 102 insertions(+), 9 deletions(-) diff --git a/Web App/web/src/i18n/da.json b/Web App/web/src/i18n/da.json index 68d1f67..9339a41 100644 --- a/Web App/web/src/i18n/da.json +++ b/Web App/web/src/i18n/da.json @@ -94,6 +94,18 @@ "resetConfirm": "Genstart denne lader nu? En igangværende opladning bliver afbrudt. Indtast din adgangskode igen for at bekræfte.", "resetPassword": "Din kontoadgangskode", "connectHint": "Indtast laderens serienummer og opdater. Laderen skal være forbundet til DriverVaults OCPP-backend (opsættes under Indstillinger → Integrationer)." + }, + "info": { + "title": "Laderoplysninger", + "empty": "Intet importeret endnu — en lader, du importerer, viser alt, den melder, her.", + "vendor": "Producent", + "model": "Model", + "serial": "Serienummer", + "site": "Placering", + "power": "Effekt", + "connector": "Stik", + "providerId": "Id hos tjenesten", + "added": "Tilføjet" } }, diff --git a/Web App/web/src/i18n/en.json b/Web App/web/src/i18n/en.json index b911664..b389f6f 100644 --- a/Web App/web/src/i18n/en.json +++ b/Web App/web/src/i18n/en.json @@ -81,6 +81,18 @@ "resetPassword": "Your account password", "connectHint": "Enter your charger's serial and refresh. The charger must be connected to DriverVault's OCPP backend (set up in Settings → Integrations)." }, + "info": { + "title": "Charger information", + "empty": "Nothing imported yet — a charger you import shows everything it reports here.", + "vendor": "Vendor", + "model": "Model", + "serial": "Serial", + "site": "Site", + "power": "Power", + "connector": "Connector", + "providerId": "Service id", + "added": "Added" + }, "stations": { "heading": "Nearby", "homeHeading": "Your chargers", diff --git a/Web App/web/src/i18n/pl.json b/Web App/web/src/i18n/pl.json index ea4d6ba..317c669 100644 --- a/Web App/web/src/i18n/pl.json +++ b/Web App/web/src/i18n/pl.json @@ -96,6 +96,18 @@ "resetConfirm": "Zrestartować teraz tę ładowarkę? Trwająca sesja ładowania zostanie przerwana. Wpisz ponownie hasło, aby potwierdzić.", "resetPassword": "Hasło do Twojego konta", "connectHint": "Wpisz numer seryjny ładowarki i odśwież. Ładowarka musi być połączona z backendem OCPP DriverVault (konfiguracja w Ustawienia → Integracje)." + }, + "info": { + "title": "Informacje o ładowarce", + "empty": "Nic jeszcze nie zaimportowano — zaimportowana ładowarka pokaże tutaj wszystko, co zgłasza.", + "vendor": "Producent", + "model": "Model", + "serial": "Numer seryjny", + "site": "Lokalizacja", + "power": "Moc", + "connector": "Złącze", + "providerId": "Identyfikator w usłudze", + "added": "Dodano" } }, diff --git a/Web App/web/src/views/Charging.vue b/Web App/web/src/views/Charging.vue index ccef7e6..c96ee70 100644 --- a/Web App/web/src/views/Charging.vue +++ b/Web App/web/src/views/Charging.vue @@ -2,6 +2,7 @@ import { ref, computed, onMounted } from "vue"; import { t } from "../i18n"; import { api } from "../api"; +import { formatDateTime } from "../lib/format.js"; import ChargerImportModal from "../components/ChargerImportModal.vue"; // Charging & map screen, mirroring the web-dashboard UI kit. There is no live @@ -103,9 +104,16 @@ function chargerLabel(c) { const homeChargers = ref([]); const homeChargersError = ref(""); const showChargerImport = ref(false); -// Importing only makes sense once a charger service is connected, so the button -// appears only then — same rule the garage's import button follows. -const canImportCharger = ref(false); +// The charger services this user could import from. Importing only makes sense +// once one of them is connected, so the button appears only then — same rule the +// garage's import button follows — and the list doubles as the id → label map +// the information card names a charger's origin with. +const chargerProviders = ref([]); +const canImportCharger = computed(() => chargerProviders.value.some((p) => p.connected)); + +function providerLabel(id) { + return chargerProviders.value.find((p) => p.id === id)?.label || id; +} async function loadHomeChargers() { homeChargersError.value = ""; @@ -145,6 +153,26 @@ function homeChargerSubtitle(c) { return [c.serial, c.model, c.siteName].filter(Boolean).join(" · "); } +// Everything the record holds about one charger, as label/value rows. A field +// the service never sent is left out rather than shown as a dash: the point of +// the card is what is known. The provider's own id for the charger is the serial +// for both services we speak to, so it appears only when it is something else. +function chargerInfoRows(c) { + const rows = [ + ["vendor", c.vendor], + ["model", c.model], + ["serial", c.serial], + ["site", c.siteName], + ["power", c.powerKw ? `${c.powerKw} kW` : ""], + ["connector", c.connector], + ["providerId", c.providerChargerId === c.serial ? "" : c.providerChargerId], + ["added", c.created ? formatDateTime(c.created) : ""], + ]; + return rows + .filter(([, value]) => value !== "" && value != null) + .map(([key, value]) => ({ key, label: t(`charging.info.${key}`), value })); +} + async function refreshCtl() { const sn = ctlSerial.value.trim(); if (!sn) { @@ -204,8 +232,8 @@ onMounted(async () => { await loadHomeChargers(); api .listChargerProviders() - .then((list) => (canImportCharger.value = list.some((p) => p.connected))) - .catch(() => (canImportCharger.value = false)); + .then((list) => (chargerProviders.value = list)) + .catch(() => (chargerProviders.value = [])); await loadCtlMode(); if (ctlActive.value) await loadChargers(); await refreshCtl(); @@ -442,10 +470,39 @@ onMounted(async () => {

{{ ctlError }}

- -
-

{{ t("charging.control.title") }}

-

{{ t("charging.stations.noControlHint") }}

+ +
+

{{ t("charging.info.title") }}

+ +
+
+

{{ c.name }}

+ + {{ providerLabel(c.provider) }} + +
+
+ +
+
+ +

+ {{ t("charging.info.empty") }} +

+ +

{{ t("charging.stations.noControlHint") }}