Web App: fold integration cards; split Charging into two tabs
Settings → Integrations: the Toyota and Anker Solix cards are now collapsible, like the plugin rows in the API Server panel. Each header is a toggle with a rotating chevron; the Connected badge stays visible when collapsed. Bodies use v-show so loaded state and in-flight edits survive folding. Collapsed by default. Charging: split into "Public chargers" and "Home chargers" tabs. Public keeps the discovery map (public pins only) + demo session + nearby public stations. Home holds the real OCPP control card (moved here) and the user's home charger list, with a hint pointing to Settings when no control mode is active. Adds charging.tabs.*, stations.homeHeading and stations.noControlHint (en/pl/da). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
8656aaaee3
commit
f9b1bcc520
5 files changed
+173
-58
No files matched your search
@@ -18,6 +18,12 @@ const profile = ref(null);
|
||||
// in-flight edits survive a tab switch.
|
||||
const activeTab = ref("personal"); // "personal" | "integrations"
|
||||
|
||||
// Each integration card folds open/closed, like the plugin rows in the API
|
||||
// Server panel. Collapsed by default so the Integrations tab reads as a compact
|
||||
// list of connectors you expand to configure.
|
||||
const toyotaOpen = ref(false);
|
||||
const ankerOpen = ref(false);
|
||||
|
||||
async function load() {
|
||||
loading.value = true;
|
||||
loadError.value = "";
|
||||
@@ -922,20 +928,32 @@ onBeforeUnmount(() => {
|
||||
<p class="mb-4 mt-1 text-sm text-muted">{{ t("settings.integrations.subtitle") }}</p>
|
||||
|
||||
<div v-if="toyota" class="rounded-control border border-subtle p-4">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-start justify-between gap-3 text-left"
|
||||
:aria-expanded="toyotaOpen"
|
||||
@click="toyotaOpen = !toyotaOpen"
|
||||
>
|
||||
<div>
|
||||
<p class="text-sm font-semibold text-strong">{{ t("settings.integrations.toyota") }}</p>
|
||||
<p class="mt-0.5 text-xs text-muted">{{ t("settings.integrations.toyotaDesc") }}</p>
|
||||
</div>
|
||||
<span
|
||||
v-if="!toyotaEditingOrg"
|
||||
class="dh-badge shrink-0"
|
||||
:class="toyota.enabled ? 'dh-badge-success' : 'dh-badge-warning'"
|
||||
>
|
||||
{{ toyota.enabled ? t("settings.integrations.connected") : t("settings.integrations.notConnected") }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-2">
|
||||
<span
|
||||
v-if="!toyotaEditingOrg"
|
||||
class="dh-badge"
|
||||
:class="toyota.enabled ? 'dh-badge-success' : 'dh-badge-warning'"
|
||||
>
|
||||
{{ toyota.enabled ? t("settings.integrations.connected") : t("settings.integrations.notConnected") }}
|
||||
</span>
|
||||
<svg
|
||||
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
class="h-4 w-4 text-muted transition-transform" :class="toyotaOpen ? 'rotate-180' : ''"
|
||||
><path stroke-linecap="round" stroke-linejoin="round" d="m6 9 6 6 6-6" /></svg>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div v-show="toyotaOpen">
|
||||
<!-- Master / org gates -->
|
||||
<p v-if="!toyota.available" class="mt-3 text-sm text-warning">{{ t("settings.integrations.unavailable") }}</p>
|
||||
<p
|
||||
@@ -1035,24 +1053,37 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
|
||||
<p v-if="toyotaError" class="mt-2 text-sm text-danger">{{ toyotaError }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Anker Solix (V1 Smart EV Charger) -->
|
||||
<div v-if="anker" class="mt-4 rounded-control border border-subtle p-4">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-start justify-between gap-3 text-left"
|
||||
:aria-expanded="ankerOpen"
|
||||
@click="ankerOpen = !ankerOpen"
|
||||
>
|
||||
<div>
|
||||
<p class="text-sm font-semibold text-strong">{{ t("settings.integrations.ankerSolix") }}</p>
|
||||
<p class="mt-0.5 text-xs text-muted">{{ t("settings.integrations.ankerSolixDesc") }}</p>
|
||||
</div>
|
||||
<span
|
||||
v-if="!ankerEditingOrg"
|
||||
class="dh-badge shrink-0"
|
||||
:class="anker.enabled ? 'dh-badge-success' : 'dh-badge-warning'"
|
||||
>
|
||||
{{ anker.enabled ? t("settings.integrations.connected") : t("settings.integrations.notConnected") }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-2">
|
||||
<span
|
||||
v-if="!ankerEditingOrg"
|
||||
class="dh-badge"
|
||||
:class="anker.enabled ? 'dh-badge-success' : 'dh-badge-warning'"
|
||||
>
|
||||
{{ anker.enabled ? t("settings.integrations.connected") : t("settings.integrations.notConnected") }}
|
||||
</span>
|
||||
<svg
|
||||
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
class="h-4 w-4 text-muted transition-transform" :class="ankerOpen ? 'rotate-180' : ''"
|
||||
><path stroke-linecap="round" stroke-linejoin="round" d="m6 9 6 6 6-6" /></svg>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div v-show="ankerOpen">
|
||||
<!-- Master / org gates -->
|
||||
<p v-if="!anker.available" class="mt-3 text-sm text-warning">{{ t("settings.integrations.unavailable") }}</p>
|
||||
<p
|
||||
@@ -1220,6 +1251,7 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
|
||||
<p v-if="ankerError" class="mt-2 text-sm text-danger">{{ ankerError }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user