UI: move vehicle settings from charging plan modal to own modal (#31775)
This commit is contained in:
parent
f673c6d0c8
commit
2a86cc44b1
65 changed files with 690 additions and 796 deletions
|
|
@ -745,6 +745,14 @@ html.app .modal-dialog {
|
||||||
outline: revert;
|
outline: revert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* selects match :focus-visible on click, CustomSelect sets .focus-ring-visible instead */
|
||||||
|
.keyboard-focus-ring:focus-visible,
|
||||||
|
.keyboard-focus-ring.focus-ring-visible {
|
||||||
|
outline: var(--bs-focus-ring-width) solid var(--bs-focus-ring-color);
|
||||||
|
outline-offset: 2px;
|
||||||
|
border-radius: var(--bs-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
.round-box {
|
.round-box {
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
color: var(--evcc-default-text);
|
color: var(--evcc-default-text);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
<MoreItem
|
<MoreItem
|
||||||
:active="moreActive"
|
:active="moreActive"
|
||||||
|
:vehicles="vehicles"
|
||||||
:auth-providers="authProviders"
|
:auth-providers="authProviders"
|
||||||
:sponsor="sponsor"
|
:sponsor="sponsor"
|
||||||
:fatal="fatal"
|
:fatal="fatal"
|
||||||
|
|
@ -50,7 +51,15 @@ import BatteryIcon from "../Energyflow/BatteryIcon.vue";
|
||||||
import Item from "./Item.vue";
|
import Item from "./Item.vue";
|
||||||
import MoreItem from "./MoreItem.vue";
|
import MoreItem from "./MoreItem.vue";
|
||||||
import { defineComponent, type PropType } from "vue";
|
import { defineComponent, type PropType } from "vue";
|
||||||
import type { FatalError, Forecast, Sponsor, EvOpt, AuthProviders, Battery } from "@/types/evcc";
|
import type {
|
||||||
|
FatalError,
|
||||||
|
Forecast,
|
||||||
|
Sponsor,
|
||||||
|
EvOpt,
|
||||||
|
AuthProviders,
|
||||||
|
Battery,
|
||||||
|
Vehicle,
|
||||||
|
} from "@/types/evcc";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "BottomTabBar",
|
name: "BottomTabBar",
|
||||||
|
|
@ -66,6 +75,7 @@ export default defineComponent({
|
||||||
batteryGridChargeActive: Boolean,
|
batteryGridChargeActive: Boolean,
|
||||||
batteryMode: { type: String as PropType<string> },
|
batteryMode: { type: String as PropType<string> },
|
||||||
forecast: { type: Object as PropType<Forecast> },
|
forecast: { type: Object as PropType<Forecast> },
|
||||||
|
vehicles: { type: Object as PropType<Record<string, Vehicle>>, default: () => ({}) },
|
||||||
authProviders: { type: Object as PropType<AuthProviders>, default: () => ({}) },
|
authProviders: { type: Object as PropType<AuthProviders>, default: () => ({}) },
|
||||||
sponsor: { type: Object as PropType<Sponsor>, default: () => ({}) },
|
sponsor: { type: Object as PropType<Sponsor>, default: () => ({}) },
|
||||||
fatal: { type: Array as PropType<FatalError[]>, default: () => [] },
|
fatal: { type: Array as PropType<FatalError[]>, default: () => [] },
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
<template #menu>
|
<template #menu>
|
||||||
<MoreMenu
|
<MoreMenu
|
||||||
:open="open"
|
:open="open"
|
||||||
|
:vehicles="vehicles"
|
||||||
:auth-providers="authProviders"
|
:auth-providers="authProviders"
|
||||||
:sponsor="sponsor"
|
:sponsor="sponsor"
|
||||||
:fatal="fatal"
|
:fatal="fatal"
|
||||||
|
|
@ -34,13 +35,14 @@ import MoreMenu from "./MoreMenu.vue";
|
||||||
import { isUserConfigError } from "@/utils/fatal";
|
import { isUserConfigError } from "@/utils/fatal";
|
||||||
import { isNewVersionAvailable, isNewVersionUnacknowledged } from "@/utils/version";
|
import { isNewVersionAvailable, isNewVersionUnacknowledged } from "@/utils/version";
|
||||||
import settings from "@/settings";
|
import settings from "@/settings";
|
||||||
import type { FatalError, Sponsor, EvOpt, AuthProviders } from "@/types/evcc";
|
import type { FatalError, Sponsor, EvOpt, AuthProviders, Vehicle } from "@/types/evcc";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "MoreItem",
|
name: "MoreItem",
|
||||||
components: { Item, MoreIcon, MoreMenu },
|
components: { Item, MoreIcon, MoreMenu },
|
||||||
props: {
|
props: {
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
|
vehicles: { type: Object as PropType<Record<string, Vehicle>>, default: () => ({}) },
|
||||||
authProviders: { type: Object as PropType<AuthProviders>, default: () => ({}) },
|
authProviders: { type: Object as PropType<AuthProviders>, default: () => ({}) },
|
||||||
sponsor: { type: Object as PropType<Sponsor>, default: () => ({}) },
|
sponsor: { type: Object as PropType<Sponsor>, default: () => ({}) },
|
||||||
fatal: { type: Array as PropType<FatalError[]>, default: () => [] },
|
fatal: { type: Array as PropType<FatalError[]>, default: () => [] },
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,14 @@
|
||||||
<button type="button" class="dropdown-item" @click="openSettingsModal">
|
<button type="button" class="dropdown-item" @click="openSettingsModal">
|
||||||
{{ $t("settings.title") }}
|
{{ $t("settings.title") }}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="hasVehicles"
|
||||||
|
type="button"
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="openVehicleSettingsModal"
|
||||||
|
>
|
||||||
|
{{ $t("main.vehicleSettings.menu") }}
|
||||||
|
</button>
|
||||||
<router-link class="dropdown-item" to="/config" active-class="active">
|
<router-link class="dropdown-item" to="/config" active-class="active">
|
||||||
<span v-if="showConfigBadge" class="circle-badge me-1" :class="badgeClass"></span>
|
<span v-if="showConfigBadge" class="circle-badge me-1" :class="badgeClass"></span>
|
||||||
{{ $t("config.main.title") }}
|
{{ $t("config.main.title") }}
|
||||||
|
|
@ -88,12 +96,13 @@ import {
|
||||||
import settings from "@/settings";
|
import settings from "@/settings";
|
||||||
import { isUserConfigError } from "@/utils/fatal";
|
import { isUserConfigError } from "@/utils/fatal";
|
||||||
import { defineComponent, type PropType } from "vue";
|
import { defineComponent, type PropType } from "vue";
|
||||||
import type { FatalError, Sponsor, EvOpt, AuthProviders } from "@/types/evcc";
|
import type { FatalError, Sponsor, EvOpt, AuthProviders, Vehicle } from "@/types/evcc";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "MoreMenu",
|
name: "MoreMenu",
|
||||||
props: {
|
props: {
|
||||||
open: { type: Boolean, default: false },
|
open: { type: Boolean, default: false },
|
||||||
|
vehicles: { type: Object as PropType<Record<string, Vehicle>>, default: () => ({}) },
|
||||||
authProviders: { type: Object as PropType<AuthProviders>, default: () => ({}) },
|
authProviders: { type: Object as PropType<AuthProviders>, default: () => ({}) },
|
||||||
sponsor: { type: Object as PropType<Sponsor>, default: () => ({}) },
|
sponsor: { type: Object as PropType<Sponsor>, default: () => ({}) },
|
||||||
fatal: { type: Array as PropType<FatalError[]>, default: () => [] },
|
fatal: { type: Array as PropType<FatalError[]>, default: () => [] },
|
||||||
|
|
@ -155,6 +164,9 @@ export default defineComponent({
|
||||||
showLogout() {
|
showLogout() {
|
||||||
return !this.authDisabled && isLoggedIn();
|
return !this.authDisabled && isLoggedIn();
|
||||||
},
|
},
|
||||||
|
hasVehicles() {
|
||||||
|
return Object.keys(this.vehicles).length > 0;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.onClickOutside = (e: MouseEvent) => {
|
this.onClickOutside = (e: MouseEvent) => {
|
||||||
|
|
@ -191,6 +203,12 @@ export default defineComponent({
|
||||||
);
|
);
|
||||||
modal.show();
|
modal.show();
|
||||||
},
|
},
|
||||||
|
openVehicleSettingsModal() {
|
||||||
|
const modal = Modal.getOrCreateInstance(
|
||||||
|
document.getElementById("vehicleSettingsModal") as HTMLElement
|
||||||
|
);
|
||||||
|
modal.show();
|
||||||
|
},
|
||||||
openNativeSettings() {
|
openNativeSettings() {
|
||||||
sendToApp({ type: "settings" });
|
sendToApp({ type: "settings" });
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,162 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="mt-4 container">
|
|
||||||
<div class="row mb-4">
|
|
||||||
<label :for="formId('mode')" class="col-12 col-md-4 col-lg-3 col-form-label">
|
|
||||||
{{ $t("config.loadpoint.defaultModeLabel") }}
|
|
||||||
</label>
|
|
||||||
<div class="col-12 col-md-8 col-lg-6">
|
|
||||||
<select
|
|
||||||
:id="formId('mode')"
|
|
||||||
v-model="selectedMode"
|
|
||||||
class="form-select"
|
|
||||||
@change="changeMode"
|
|
||||||
>
|
|
||||||
<option v-for="opt in modeOptions" :key="opt.value" :value="opt.value">
|
|
||||||
{{ opt.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<small class="form-text text-muted">{{ modeHelp }}</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<template v-if="socSettingsVisible">
|
|
||||||
<div class="row mb-4">
|
|
||||||
<label :for="formId('minsoc')" class="col-12 col-md-4 col-lg-3 col-form-label">
|
|
||||||
{{ $t("main.loadpointSettings.minSoc.label") }}
|
|
||||||
</label>
|
|
||||||
<div class="col-12 col-md-8 col-lg-6">
|
|
||||||
<select
|
|
||||||
:id="formId('minsoc')"
|
|
||||||
v-model.number="selectedMinSoc"
|
|
||||||
class="form-select"
|
|
||||||
@change="changeMinSoc"
|
|
||||||
>
|
|
||||||
<option v-for="soc in minSocOptions" :key="soc.value" :value="soc.value">
|
|
||||||
{{ soc.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<small class="form-text text-muted">
|
|
||||||
{{
|
|
||||||
$t("main.loadpointSettings.minSoc.description", [
|
|
||||||
selectedMinSoc ? fmtPercentage(selectedMinSoc) : "x",
|
|
||||||
])
|
|
||||||
}}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-4">
|
|
||||||
<label :for="formId('limitsoc')" class="col-12 col-md-4 col-lg-3 col-form-label">
|
|
||||||
{{ $t("main.loadpointSettings.limitSoc.label") }}
|
|
||||||
</label>
|
|
||||||
<div class="col-12 col-md-8 col-lg-6">
|
|
||||||
<select
|
|
||||||
:id="formId('limitsoc')"
|
|
||||||
v-model.number="selectedLimitSoc"
|
|
||||||
class="form-select"
|
|
||||||
@change="changeLimitSoc"
|
|
||||||
>
|
|
||||||
<option v-for="soc in limitSocOptions" :key="soc.value" :value="soc.value">
|
|
||||||
{{ soc.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<small class="form-text text-muted">
|
|
||||||
{{ $t("main.loadpointSettings.limitSoc.description") }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { distanceUnit } from "@/units";
|
|
||||||
import formatter from "@/mixins/formatter";
|
|
||||||
import { CHARGE_MODE, type SelectOption } from "@/types/evcc";
|
|
||||||
import { defineComponent } from "vue";
|
|
||||||
|
|
||||||
const { OFF, PV, MINPV, NOW } = CHARGE_MODE;
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "ChargingPlanArrival",
|
|
||||||
mixins: [formatter],
|
|
||||||
props: {
|
|
||||||
id: [String, Number],
|
|
||||||
minSoc: { type: Number, default: 0 },
|
|
||||||
limitSoc: { type: Number, default: 0 },
|
|
||||||
mode: { type: String, default: "" },
|
|
||||||
vehicleName: String,
|
|
||||||
vehicleNotReachable: Boolean,
|
|
||||||
socBasedCharging: Boolean,
|
|
||||||
rangePerSoc: Number,
|
|
||||||
},
|
|
||||||
emits: ["minsoc-updated", "limitsoc-updated", "mode-updated"],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
selectedMinSoc: this.minSoc,
|
|
||||||
selectedLimitSoc: this.limitSoc,
|
|
||||||
selectedMode: this.mode,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
modeOptions(): SelectOption<string>[] {
|
|
||||||
return [
|
|
||||||
{ value: "", name: this.$t("config.loadpoint.defaultModeKeep") },
|
|
||||||
...[OFF, PV, MINPV, NOW].map((mode) => ({
|
|
||||||
value: mode,
|
|
||||||
name: this.$t(`main.mode.${mode}`),
|
|
||||||
})),
|
|
||||||
];
|
|
||||||
},
|
|
||||||
modeHelp(): string {
|
|
||||||
return this.selectedMode === ""
|
|
||||||
? this.$t("config.loadpoint.defaultModeHelpKeep")
|
|
||||||
: this.$t("config.loadpoint.defaultModeHelp.charging");
|
|
||||||
},
|
|
||||||
minSocOptions(): SelectOption<number>[] {
|
|
||||||
// a list of entries from 0 to 95 with a step of 5
|
|
||||||
return Array.from(Array(20).keys())
|
|
||||||
.map((i) => i * 5)
|
|
||||||
.map(this.socOption);
|
|
||||||
},
|
|
||||||
limitSocOptions(): SelectOption<number>[] {
|
|
||||||
// a list of entries from 0 to 100 with a step of 5
|
|
||||||
return Array.from(Array(21).keys())
|
|
||||||
.map((i) => i * 5)
|
|
||||||
.map(this.socOption);
|
|
||||||
},
|
|
||||||
socSettingsVisible(): boolean {
|
|
||||||
return this.socBasedCharging || this.vehicleNotReachable;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
minSoc(value: number): void {
|
|
||||||
this.selectedMinSoc = value;
|
|
||||||
},
|
|
||||||
limitSoc(value: number): void {
|
|
||||||
this.selectedLimitSoc = value;
|
|
||||||
},
|
|
||||||
mode(value: string): void {
|
|
||||||
this.selectedMode = value;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
socOption(soc: number): SelectOption<number> {
|
|
||||||
return {
|
|
||||||
value: soc,
|
|
||||||
name: soc === 0 ? "---" : this.fmtSocOption(soc, this.rangePerSoc, distanceUnit()),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
formId(name: string): string {
|
|
||||||
return `chargingplan_${this.id}_${name}`;
|
|
||||||
},
|
|
||||||
changeMinSoc(): void {
|
|
||||||
this.$emit("minsoc-updated", this.selectedMinSoc);
|
|
||||||
},
|
|
||||||
changeLimitSoc(): void {
|
|
||||||
this.$emit("limitsoc-updated", this.selectedLimitSoc);
|
|
||||||
},
|
|
||||||
changeMode(): void {
|
|
||||||
this.$emit("mode-updated", this.selectedMode);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
>
|
>
|
||||||
<div class="value m-0 d-block align-items-baseline justify-content-center">
|
<div class="value m-0 d-block align-items-baseline justify-content-center">
|
||||||
<button
|
<button
|
||||||
class="value-button p-0"
|
class="value-button p-0 keyboard-focus-ring"
|
||||||
:class="buttonColor"
|
:class="buttonColor"
|
||||||
data-testid="charging-plan-button"
|
data-testid="charging-plan-button"
|
||||||
@click="openModal"
|
@click="openModal"
|
||||||
|
|
|
||||||
|
|
@ -9,72 +9,33 @@
|
||||||
@open="modalVisible"
|
@open="modalVisible"
|
||||||
@closed="modalInvisible"
|
@closed="modalInvisible"
|
||||||
>
|
>
|
||||||
<div class="pt-2">
|
<div v-if="isModalVisible">
|
||||||
<ul v-if="vehicle" class="nav nav-tabs">
|
<PlansSettings
|
||||||
<li class="nav-item">
|
:id="id"
|
||||||
<a
|
:staticPlan="staticPlan"
|
||||||
class="nav-link"
|
:repeatingPlans="repeatingPlans"
|
||||||
:class="{ active: departureTabActive }"
|
:effectiveLimitSoc="loadpoint?.effectiveLimitSoc"
|
||||||
href="#"
|
:effectivePlanTime="loadpoint?.effectivePlanTime ?? undefined"
|
||||||
@click.prevent="showDepartureTab"
|
:effectivePlanSoc="loadpoint?.effectivePlanSoc"
|
||||||
>
|
:effectivePlanStrategy="loadpoint?.effectivePlanStrategy"
|
||||||
{{ $t("main.chargingPlan.departureTab") }}
|
:planEnergy="loadpoint?.planEnergy"
|
||||||
</a>
|
:limitEnergy="loadpoint?.limitEnergy"
|
||||||
</li>
|
:socBasedPlanning="!!loadpoint?.socBasedPlanning"
|
||||||
<li v-if="vehicle" class="nav-item">
|
:socPerKwh="loadpoint?.socPerKwh"
|
||||||
<a
|
:rangePerSoc="loadpoint?.rangePerSoc"
|
||||||
class="nav-link"
|
:smartCostType="smartCostType"
|
||||||
:class="{ active: arrivalTabActive }"
|
:currency="currency"
|
||||||
href="#"
|
:mode="loadpoint?.mode"
|
||||||
@click.prevent="showArrivalTab"
|
:capacity="vehicle?.capacity"
|
||||||
>
|
:vehicle="vehicle"
|
||||||
{{ $t("main.chargingPlan.arrivalTab") }}
|
:vehicleLimitSoc="loadpoint?.vehicleLimitSoc"
|
||||||
</a>
|
:planOverrun="loadpoint?.planOverrun"
|
||||||
</li>
|
:forecast="forecast"
|
||||||
</ul>
|
@static-plan-updated="updateStaticPlan"
|
||||||
<div v-if="isModalVisible">
|
@static-plan-removed="removeStaticPlan"
|
||||||
<PlansSettings
|
@repeating-plans-updated="updateRepeatingPlans"
|
||||||
v-if="departureTabActive"
|
@plan-strategy-updated="updatePlanStrategy"
|
||||||
:id="id"
|
/>
|
||||||
:staticPlan="staticPlan"
|
|
||||||
:repeatingPlans="repeatingPlans"
|
|
||||||
:effectiveLimitSoc="loadpoint?.effectiveLimitSoc"
|
|
||||||
:effectivePlanTime="loadpoint?.effectivePlanTime ?? undefined"
|
|
||||||
:effectivePlanSoc="loadpoint?.effectivePlanSoc"
|
|
||||||
:effectivePlanStrategy="loadpoint?.effectivePlanStrategy"
|
|
||||||
:planEnergy="loadpoint?.planEnergy"
|
|
||||||
:limitEnergy="loadpoint?.limitEnergy"
|
|
||||||
:socBasedPlanning="!!loadpoint?.socBasedPlanning"
|
|
||||||
:socPerKwh="loadpoint?.socPerKwh"
|
|
||||||
:rangePerSoc="loadpoint?.rangePerSoc"
|
|
||||||
:smartCostType="smartCostType"
|
|
||||||
:currency="currency"
|
|
||||||
:mode="loadpoint?.mode"
|
|
||||||
:capacity="vehicle?.capacity"
|
|
||||||
:vehicle="vehicle"
|
|
||||||
:vehicleLimitSoc="loadpoint?.vehicleLimitSoc"
|
|
||||||
:planOverrun="loadpoint?.planOverrun"
|
|
||||||
:forecast="forecast"
|
|
||||||
@static-plan-updated="updateStaticPlan"
|
|
||||||
@static-plan-removed="removeStaticPlan"
|
|
||||||
@repeating-plans-updated="updateRepeatingPlans"
|
|
||||||
@plan-strategy-updated="updatePlanStrategy"
|
|
||||||
/>
|
|
||||||
<Arrival
|
|
||||||
v-if="arrivalTabActive"
|
|
||||||
:id="id"
|
|
||||||
:minSoc="vehicle?.minSoc"
|
|
||||||
:limitSoc="vehicle?.limitSoc"
|
|
||||||
:mode="vehicle?.mode"
|
|
||||||
:vehicleName="vehicle?.name"
|
|
||||||
:vehicleNotReachable="loadpoint?.vehicleNotReachable"
|
|
||||||
:socBasedCharging="loadpoint?.socBasedCharging"
|
|
||||||
:rangePerSoc="loadpoint?.rangePerSoc"
|
|
||||||
@minsoc-updated="setMinSoc"
|
|
||||||
@limitsoc-updated="setLimitSoc"
|
|
||||||
@mode-updated="setMode"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
|
|
@ -84,7 +45,6 @@
|
||||||
import { defineComponent, type PropType } from "vue";
|
import { defineComponent, type PropType } from "vue";
|
||||||
import GenericModal from "../Helper/GenericModal.vue";
|
import GenericModal from "../Helper/GenericModal.vue";
|
||||||
import PlansSettings from "./PlansSettings.vue";
|
import PlansSettings from "./PlansSettings.vue";
|
||||||
import Arrival from "./Arrival.vue";
|
|
||||||
import api from "@/api";
|
import api from "@/api";
|
||||||
import type {
|
import type {
|
||||||
PlanStrategy,
|
PlanStrategy,
|
||||||
|
|
@ -93,21 +53,13 @@ import type {
|
||||||
StaticPlan,
|
StaticPlan,
|
||||||
StaticSocPlan,
|
StaticSocPlan,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import type {
|
import type { CURRENCY, Forecast, SMART_COST_TYPE, UiLoadpoint, Vehicle } from "@/types/evcc";
|
||||||
CHARGE_MODE,
|
|
||||||
CURRENCY,
|
|
||||||
Forecast,
|
|
||||||
SMART_COST_TYPE,
|
|
||||||
UiLoadpoint,
|
|
||||||
Vehicle,
|
|
||||||
} from "@/types/evcc";
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ChargingPlanModal",
|
name: "ChargingPlanModal",
|
||||||
components: {
|
components: {
|
||||||
GenericModal,
|
GenericModal,
|
||||||
PlansSettings,
|
PlansSettings,
|
||||||
Arrival,
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
loadpoints: { type: Array as PropType<UiLoadpoint[]>, default: () => [] },
|
loadpoints: { type: Array as PropType<UiLoadpoint[]>, default: () => [] },
|
||||||
|
|
@ -119,7 +71,6 @@ export default defineComponent({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isModalVisible: false,
|
isModalVisible: false,
|
||||||
activeTab: "departure",
|
|
||||||
id: undefined as string | number | undefined,
|
id: undefined as string | number | undefined,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -151,18 +102,11 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
modalTitle(): string {
|
modalTitle(): string {
|
||||||
const baseTitle = this.$t("main.chargingPlan.modalTitle");
|
const baseTitle = this.$t("main.chargingPlan.modalTitle");
|
||||||
const withVehicle = this.arrivalTabActive || this.loadpoint?.socBasedPlanning;
|
if (this.loadpoint?.socBasedPlanning && this.vehicle) {
|
||||||
if (withVehicle && this.vehicle) {
|
|
||||||
return `${baseTitle}: ${this.vehicle.title}`;
|
return `${baseTitle}: ${this.vehicle.title}`;
|
||||||
}
|
}
|
||||||
return baseTitle;
|
return baseTitle;
|
||||||
},
|
},
|
||||||
departureTabActive(): boolean {
|
|
||||||
return this.activeTab === "departure" || !this.vehicle;
|
|
||||||
},
|
|
||||||
arrivalTabActive(): boolean {
|
|
||||||
return this.activeTab === "arrival" && !!this.vehicle;
|
|
||||||
},
|
|
||||||
apiVehicle(): string {
|
apiVehicle(): string {
|
||||||
return `vehicles/${this.vehicle?.name}/`;
|
return `vehicles/${this.vehicle?.name}/`;
|
||||||
},
|
},
|
||||||
|
|
@ -192,19 +136,6 @@ export default defineComponent({
|
||||||
modalInvisible(): void {
|
modalInvisible(): void {
|
||||||
this.isModalVisible = false;
|
this.isModalVisible = false;
|
||||||
},
|
},
|
||||||
setMinSoc(soc: number): void {
|
|
||||||
api.post(`${this.apiVehicle}minsoc/${soc}`);
|
|
||||||
},
|
|
||||||
setLimitSoc(soc: number): void {
|
|
||||||
api.post(`${this.apiVehicle}limitsoc/${soc}`);
|
|
||||||
},
|
|
||||||
setMode(mode: CHARGE_MODE | ""): void {
|
|
||||||
if (mode === "") {
|
|
||||||
api.delete(`${this.apiVehicle}mode`);
|
|
||||||
} else {
|
|
||||||
api.post(`${this.apiVehicle}mode/${mode}`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateStaticPlan(plan: StaticPlan): void {
|
updateStaticPlan(plan: StaticPlan): void {
|
||||||
const timeISO = plan.time.toISOString();
|
const timeISO = plan.time.toISOString();
|
||||||
if (this.loadpoint?.socBasedPlanning) {
|
if (this.loadpoint?.socBasedPlanning) {
|
||||||
|
|
@ -232,12 +163,6 @@ export default defineComponent({
|
||||||
api.post(`${this.apiLoadpoint}plan/strategy`, strategy);
|
api.post(`${this.apiLoadpoint}plan/strategy`, strategy);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showDepartureTab(): void {
|
|
||||||
this.activeTab = "departure";
|
|
||||||
},
|
|
||||||
showArrivalTab(): void {
|
|
||||||
this.activeTab = "arrival";
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mt-4">
|
<div>
|
||||||
<div class="form-group d-lg-flex align-items-baseline justify-content-between">
|
<div class="form-group d-lg-flex align-items-baseline justify-content-between">
|
||||||
<div class="container px-0">
|
<div class="container px-0">
|
||||||
<ChargingPlanStaticSettings
|
<ChargingPlanStaticSettings
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@
|
||||||
<small v-if="expiryLabel(client)" class="text-muted ms-2 me-2 text-end">
|
<small v-if="expiryLabel(client)" class="text-muted ms-2 me-2 text-end">
|
||||||
{{ expiryLabel(client) }}
|
{{ expiryLabel(client) }}
|
||||||
</small>
|
</small>
|
||||||
<span v-if="isActive(client)" class="badge bg-success ms-2 me-2">
|
<Badge v-if="isActive(client)" class="ms-2 me-2">
|
||||||
{{ $t("config.remote.active") }}
|
{{ $t("config.remote.active") }}
|
||||||
</span>
|
</Badge>
|
||||||
<small
|
<small
|
||||||
v-else-if="activityLabel(client)"
|
v-else-if="activityLabel(client)"
|
||||||
class="text-muted ms-2 me-2 text-end d-block"
|
class="text-muted ms-2 me-2 text-end d-block"
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, type PropType } from "vue";
|
import { defineComponent, type PropType } from "vue";
|
||||||
import "@h2d2/shopicons/es/regular/trash";
|
import "@h2d2/shopicons/es/regular/trash";
|
||||||
|
import Badge from "../../Helper/Badge.vue";
|
||||||
import formatter from "@/mixins/formatter";
|
import formatter from "@/mixins/formatter";
|
||||||
import minuteTicker from "@/mixins/minuteTicker";
|
import minuteTicker from "@/mixins/minuteTicker";
|
||||||
import type { RemoteClient } from "@/types/evcc";
|
import type { RemoteClient } from "@/types/evcc";
|
||||||
|
|
@ -59,6 +60,7 @@ import { isRemoteClientActive } from "@/utils/remote";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "RemoteClientList",
|
name: "RemoteClientList",
|
||||||
|
components: { Badge },
|
||||||
mixins: [formatter, minuteTicker],
|
mixins: [formatter, minuteTicker],
|
||||||
props: {
|
props: {
|
||||||
clients: { type: Array as PropType<RemoteClient[]>, required: true },
|
clients: { type: Array as PropType<RemoteClient[]>, required: true },
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,15 @@
|
||||||
data-testid="energyflow"
|
data-testid="energyflow"
|
||||||
@click="toggleDetails"
|
@click="toggleDetails"
|
||||||
>
|
>
|
||||||
<div class="row">
|
<div
|
||||||
|
class="row keyboard-focus-ring"
|
||||||
|
:role="detailsAlwaysOpen ? undefined : 'button'"
|
||||||
|
:tabindex="detailsAlwaysOpen ? undefined : 0"
|
||||||
|
:aria-expanded="detailsAlwaysOpen ? undefined : detailsOpen"
|
||||||
|
:aria-label="detailsAlwaysOpen ? undefined : $t('main.energyflow.toggleDetails')"
|
||||||
|
@keydown.enter.prevent="toggleDetails"
|
||||||
|
@keydown.space.prevent="toggleDetails"
|
||||||
|
>
|
||||||
<Visualization
|
<Visualization
|
||||||
class="col-12 mb-3 mb-md-4"
|
class="col-12 mb-3 mb-md-4"
|
||||||
:gridImport="gridImport"
|
:gridImport="gridImport"
|
||||||
|
|
@ -33,6 +41,7 @@
|
||||||
class="details"
|
class="details"
|
||||||
:style="{ height: detailsHeight }"
|
:style="{ height: detailsHeight }"
|
||||||
:class="{ 'details--ready': ready }"
|
:class="{ 'details--ready': ready }"
|
||||||
|
:inert="!detailsOpen && !detailsAlwaysOpen"
|
||||||
>
|
>
|
||||||
<div ref="detailsInner" class="details-inner row">
|
<div ref="detailsInner" class="details-inner row">
|
||||||
<div class="col-12 d-flex justify-content-between pt-2 mb-4">
|
<div class="col-12 d-flex justify-content-between pt-2 mb-4">
|
||||||
|
|
|
||||||
26
assets/js/components/Helper/Badge.stories.ts
Normal file
26
assets/js/components/Helper/Badge.stories.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import Badge from "./Badge.vue";
|
||||||
|
import type { Meta, StoryFn } from "@storybook/vue3";
|
||||||
|
|
||||||
|
const variants = ["success", "muted"] as const;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Helper/Badge",
|
||||||
|
component: Badge,
|
||||||
|
argTypes: {
|
||||||
|
variant: { control: "select", options: variants },
|
||||||
|
},
|
||||||
|
} as Meta<typeof Badge>;
|
||||||
|
|
||||||
|
const Template: StoryFn<typeof Badge> = (args) => ({
|
||||||
|
components: { Badge },
|
||||||
|
setup() {
|
||||||
|
return { args };
|
||||||
|
},
|
||||||
|
template: '<Badge v-bind="args">connected to Garage</Badge>',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const Success = Template.bind({});
|
||||||
|
Success.args = { variant: "success" };
|
||||||
|
|
||||||
|
export const Muted = Template.bind({});
|
||||||
|
Muted.args = { variant: "muted" };
|
||||||
34
assets/js/components/Helper/Badge.vue
Normal file
34
assets/js/components/Helper/Badge.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<template>
|
||||||
|
<span class="badge rounded-pill" :class="`badge--${variant}`">
|
||||||
|
<slot />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, type PropType } from "vue";
|
||||||
|
|
||||||
|
type Variant = "success" | "muted";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "Badge",
|
||||||
|
props: {
|
||||||
|
variant: { type: String as PropType<Variant>, default: "success" },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.badge {
|
||||||
|
--bs-badge-font-size: 0.75rem;
|
||||||
|
--bs-badge-padding-y: 0.25em;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.badge--success {
|
||||||
|
background: var(--evcc-green);
|
||||||
|
color: var(--evcc-darkest-green);
|
||||||
|
}
|
||||||
|
.badge--muted {
|
||||||
|
background: var(--evcc-gray-10);
|
||||||
|
color: var(--evcc-gray);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,11 +1,25 @@
|
||||||
<template>
|
<template>
|
||||||
<label
|
<label
|
||||||
class="root position-relative"
|
class="root position-relative keyboard-focus-ring"
|
||||||
:class="inline ? 'd-inline-block align-baseline' : 'd-block'"
|
:class="[
|
||||||
|
inline ? 'd-inline-block align-baseline' : 'd-block',
|
||||||
|
{ 'focus-ring-visible': showFocusRing },
|
||||||
|
]"
|
||||||
:for="id"
|
:for="id"
|
||||||
role="button"
|
role="button"
|
||||||
|
@mousedown="mouseDown = true"
|
||||||
>
|
>
|
||||||
<select :id="id" :value="selected" class="custom-select" tabindex="0" @change="change">
|
<select
|
||||||
|
:id="id"
|
||||||
|
:value="selected"
|
||||||
|
:aria-label="ariaLabel"
|
||||||
|
class="custom-select"
|
||||||
|
tabindex="0"
|
||||||
|
@change="change"
|
||||||
|
@focus="handleFocus"
|
||||||
|
@keydown="showFocusRing = true"
|
||||||
|
@blur="handleBlur"
|
||||||
|
>
|
||||||
<option
|
<option
|
||||||
v-for="{ name, value, count, disabled } in options"
|
v-for="{ name, value, count, disabled } in options"
|
||||||
:key="value"
|
:key="value"
|
||||||
|
|
@ -30,8 +44,16 @@ export default defineComponent({
|
||||||
selected: { type: [String, Number] },
|
selected: { type: [String, Number] },
|
||||||
id: { type: String },
|
id: { type: String },
|
||||||
inline: Boolean,
|
inline: Boolean,
|
||||||
|
ariaLabel: { type: String },
|
||||||
},
|
},
|
||||||
emits: ["change"],
|
emits: ["change"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// selects match :focus-visible even on mouse interaction, track modality manually
|
||||||
|
mouseDown: false,
|
||||||
|
showFocusRing: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
text(name: string, count?: number) {
|
text(name: string, count?: number) {
|
||||||
if (count === undefined) {
|
if (count === undefined) {
|
||||||
|
|
@ -42,6 +64,14 @@ export default defineComponent({
|
||||||
change(event: Event) {
|
change(event: Event) {
|
||||||
this.$emit("change", event);
|
this.$emit("change", event);
|
||||||
},
|
},
|
||||||
|
handleFocus() {
|
||||||
|
this.showFocusRing = !this.mouseDown;
|
||||||
|
this.mouseDown = false;
|
||||||
|
},
|
||||||
|
handleBlur() {
|
||||||
|
this.showFocusRing = false;
|
||||||
|
this.mouseDown = false;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -55,13 +85,7 @@ export default defineComponent({
|
||||||
position: absolute;
|
position: absolute;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
-webkit-appearance: menulist-button;
|
-webkit-appearance: menulist-button;
|
||||||
}
|
/* WebKit propagates the select's intrinsic option width as overflow, causing page scroll */
|
||||||
.root {
|
contain: paint;
|
||||||
border-radius: var(--bs-border-radius);
|
|
||||||
}
|
|
||||||
.root:focus-within {
|
|
||||||
outline: var(--bs-focus-ring-width) solid var(--bs-focus-ring-color);
|
|
||||||
outline-width: var(--bs-focus-ring-width);
|
|
||||||
outline-offset: var(--bs-focus-ring-width);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ export default defineComponent({
|
||||||
methods: {
|
methods: {
|
||||||
handleShow() {
|
handleShow() {
|
||||||
this.$emit("open");
|
this.$emit("open");
|
||||||
|
this.isModalVisible = true;
|
||||||
},
|
},
|
||||||
handleShown() {
|
handleShown() {
|
||||||
this.$emit("opened");
|
this.$emit("opened");
|
||||||
|
|
@ -107,14 +108,19 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.isModalVisible = true;
|
// bootstrap removes the attribute on show, Vue only rewrites it on state change
|
||||||
|
(this.$refs["modal"] as HTMLElement)?.setAttribute("aria-hidden", "false");
|
||||||
},
|
},
|
||||||
handleHide() {
|
handleHide() {
|
||||||
this.$emit("close");
|
this.$emit("close");
|
||||||
|
this.isModalVisible = false;
|
||||||
},
|
},
|
||||||
handleHidden() {
|
handleHidden() {
|
||||||
|
// stale event from a previous close, modal was reopened while still fading out
|
||||||
|
if (this.isModalVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.$emit("closed");
|
this.$emit("closed");
|
||||||
this.isModalVisible = false;
|
|
||||||
if (this.configModalName) {
|
if (this.configModalName) {
|
||||||
if (onModalHidden(this.configModalName)) {
|
if (onModalHidden(this.configModalName)) {
|
||||||
this.$emit("dismiss");
|
this.$emit("dismiss");
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<div class="mb-2 label text-truncate" :class="labelClass" :style="{ color }">
|
<div class="label text-truncate" :class="labelClass" :style="{ color }">
|
||||||
<slot name="label">{{ label }}</slot>
|
<slot name="label">{{ label }}</slot>
|
||||||
</div>
|
</div>
|
||||||
<slot>
|
<slot>
|
||||||
|
|
@ -54,6 +54,9 @@ export default defineComponent({
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--evcc-gray);
|
color: var(--evcc-gray);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
/* focus ring clearance, keeps mb-2 spacing */
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin: -0.5rem -0.5rem 0;
|
||||||
}
|
}
|
||||||
.value {
|
.value {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
|
|
||||||
30
assets/js/components/Helper/SettingsFormRow.vue
Normal file
30
assets/js/components/Helper/SettingsFormRow.vue
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
<template>
|
||||||
|
<div class="mb-3 row">
|
||||||
|
<label :for="id" class="col-sm-4 col-form-label pt-0 pt-sm-2">
|
||||||
|
{{ label }}
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<small v-if="description" class="d-block text-muted mt-1">
|
||||||
|
{{ description }}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "SettingsFormRow",
|
||||||
|
props: {
|
||||||
|
id: String,
|
||||||
|
label: String,
|
||||||
|
description: String,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -98,7 +98,7 @@
|
||||||
@remove-vehicle="removeVehicle"
|
@remove-vehicle="removeVehicle"
|
||||||
@open-loadpoint-settings="openSettingsModal"
|
@open-loadpoint-settings="openSettingsModal"
|
||||||
@batteryboost-updated="setBatteryBoost"
|
@batteryboost-updated="setBatteryBoost"
|
||||||
@open-modal="(openArrivalTab) => $emit('open-charging-plan-modal', openArrivalTab)"
|
@open-modal="$emit('open-charging-plan-modal')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,7 @@
|
||||||
class="h-100"
|
class="h-100"
|
||||||
:class="{ 'loadpoint-unselected': !selected(loadpoint.id) }"
|
:class="{ 'loadpoint-unselected': !selected(loadpoint.id) }"
|
||||||
@click="goTo(loadpoint.id)"
|
@click="goTo(loadpoint.id)"
|
||||||
@open-charging-plan-modal="
|
@open-charging-plan-modal="openChargingPlanModal(loadpoint.id)"
|
||||||
(openArrivalTab) => openChargingPlanModal(loadpoint.id, openArrivalTab)
|
|
||||||
"
|
|
||||||
@open-settings-modal="openSettingsModal(loadpoint.id)"
|
@open-settings-modal="openSettingsModal(loadpoint.id)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -224,17 +222,10 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
},
|
},
|
||||||
openChargingPlanModal(loadpointId: string, openArrivalTab = false) {
|
openChargingPlanModal(loadpointId: string) {
|
||||||
const modal = this.$refs["chargingPlanModal"] as
|
const modal = this.$refs["chargingPlanModal"] as
|
||||||
| InstanceType<typeof ChargingPlanModal>
|
| InstanceType<typeof ChargingPlanModal>
|
||||||
| undefined;
|
| undefined;
|
||||||
|
|
||||||
if (openArrivalTab) {
|
|
||||||
modal?.showArrivalTab();
|
|
||||||
} else {
|
|
||||||
modal?.showDepartureTab();
|
|
||||||
}
|
|
||||||
|
|
||||||
modal?.open(loadpointId);
|
modal?.open(loadpointId);
|
||||||
},
|
},
|
||||||
openSettingsModal(loadpointId: string) {
|
openSettingsModal(loadpointId: string) {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
<LabelAndValue class="d-block" align="end">
|
<LabelAndValue class="d-block" align="end">
|
||||||
<template #label>
|
<template #label>
|
||||||
<CustomSelect
|
<CustomSelect
|
||||||
|
inline
|
||||||
:selected="selectedKey"
|
:selected="selectedKey"
|
||||||
:options="selectOptions"
|
:options="selectOptions"
|
||||||
data-testid="sessionInfoSelect"
|
data-testid="sessionInfoSelect"
|
||||||
|
|
@ -197,8 +198,10 @@ export default defineComponent({
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.sessionInfo * {
|
.sessionInfo * {
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
}
|
}
|
||||||
|
.sessionInfo .value {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-sm btn-outline-secondary position-relative border-0 p-2 evcc-gray"
|
class="btn btn-sm btn-outline-secondary position-relative border-0 p-2 evcc-gray keyboard-focus-ring"
|
||||||
data-testid="loadpoint-settings-button"
|
data-testid="loadpoint-settings-button"
|
||||||
>
|
>
|
||||||
<shopicon-regular-adjust size="s"></shopicon-regular-adjust>
|
<shopicon-regular-adjust size="s"></shopicon-regular-adjust>
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,9 @@ import type {
|
||||||
FatalError,
|
FatalError,
|
||||||
EvOpt,
|
EvOpt,
|
||||||
BATTERY_MODE,
|
BATTERY_MODE,
|
||||||
|
Vehicle,
|
||||||
} from "@/types/evcc";
|
} from "@/types/evcc";
|
||||||
|
import vehicleList from "@/utils/vehicleList";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import type { Grid } from "./types";
|
import type { Grid } from "./types";
|
||||||
|
|
||||||
|
|
@ -130,7 +132,7 @@ export default defineComponent({
|
||||||
bufferSoc: Number,
|
bufferSoc: Number,
|
||||||
bufferStartSoc: Number,
|
bufferStartSoc: Number,
|
||||||
siteTitle: String,
|
siteTitle: String,
|
||||||
vehicles: Object,
|
vehicles: Object as PropType<Record<string, Vehicle>>,
|
||||||
authProviders: { type: Object as PropType<AuthProviders>, default: () => ({}) },
|
authProviders: { type: Object as PropType<AuthProviders>, default: () => ({}) },
|
||||||
currency: { type: String as PropType<CURRENCY> },
|
currency: { type: String as PropType<CURRENCY> },
|
||||||
tariffFeedIn: Number,
|
tariffFeedIn: Number,
|
||||||
|
|
@ -178,8 +180,7 @@ export default defineComponent({
|
||||||
return this.collectProps(Energyflow);
|
return this.collectProps(Energyflow);
|
||||||
},
|
},
|
||||||
vehicleList() {
|
vehicleList() {
|
||||||
const vehicles = this.vehicles || {};
|
return vehicleList(this.vehicles);
|
||||||
return Object.entries(vehicles).map(([name, vehicle]) => ({ name, ...vehicle }));
|
|
||||||
},
|
},
|
||||||
showParkingLot() {
|
showParkingLot() {
|
||||||
// work in progess
|
// work in progess
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,7 @@
|
||||||
data-testid="limit-energy"
|
data-testid="limit-energy"
|
||||||
>
|
>
|
||||||
<h3 class="value m-0">
|
<h3 class="value m-0">
|
||||||
<label class="position-relative" role="button">
|
<CustomSelect inline :options="selectOptions" :selected="limitEnergy" @change="change">
|
||||||
<select :value="limitEnergy" class="custom-select" @change="change">
|
|
||||||
<option
|
|
||||||
v-for="{ energy, text, disabled } in options"
|
|
||||||
:key="energy"
|
|
||||||
:value="energy"
|
|
||||||
:disabled="disabled"
|
|
||||||
>
|
|
||||||
{{ text }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<span
|
<span
|
||||||
class="text-decoration-underline"
|
class="text-decoration-underline"
|
||||||
:class="{ 'text-gray fw-normal': !limitEnergy }"
|
:class="{ 'text-gray fw-normal': !limitEnergy }"
|
||||||
|
|
@ -24,7 +14,7 @@
|
||||||
>
|
>
|
||||||
<AnimatedNumber :to="limitEnergy" :format="fmtEnergy" />
|
<AnimatedNumber :to="limitEnergy" :format="fmtEnergy" />
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</CustomSelect>
|
||||||
|
|
||||||
<div v-if="estimated" class="extraValue text-nowrap">
|
<div v-if="estimated" class="extraValue text-nowrap">
|
||||||
<AnimatedNumber :to="estimated" :format="fmtSoc" />
|
<AnimatedNumber :to="estimated" :format="fmtSoc" />
|
||||||
|
|
@ -36,13 +26,14 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import LabelAndValue from "../Helper/LabelAndValue.vue";
|
import LabelAndValue from "../Helper/LabelAndValue.vue";
|
||||||
import AnimatedNumber from "../Helper/AnimatedNumber.vue";
|
import AnimatedNumber from "../Helper/AnimatedNumber.vue";
|
||||||
|
import CustomSelect from "../Helper/CustomSelect.vue";
|
||||||
import formatter from "@/mixins/formatter";
|
import formatter from "@/mixins/formatter";
|
||||||
import { estimatedSoc, energyOptions, optionStep, fmtEnergy } from "@/utils/energyOptions.ts";
|
import { estimatedSoc, energyOptions, optionStep, fmtEnergy } from "@/utils/energyOptions.ts";
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "LimitEnergySelect",
|
name: "LimitEnergySelect",
|
||||||
components: { LabelAndValue, AnimatedNumber },
|
components: { LabelAndValue, AnimatedNumber, CustomSelect },
|
||||||
mixins: [formatter],
|
mixins: [formatter],
|
||||||
props: {
|
props: {
|
||||||
limitEnergy: { type: Number, default: 0 },
|
limitEnergy: { type: Number, default: 0 },
|
||||||
|
|
@ -62,6 +53,13 @@ export default defineComponent({
|
||||||
this.socPerKwh
|
this.socPerKwh
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
selectOptions() {
|
||||||
|
return this.options.map(({ energy, text, disabled }) => ({
|
||||||
|
value: energy,
|
||||||
|
name: text,
|
||||||
|
disabled,
|
||||||
|
}));
|
||||||
|
},
|
||||||
step() {
|
step() {
|
||||||
return optionStep(this.capacity || 100);
|
return optionStep(this.capacity || 100);
|
||||||
},
|
},
|
||||||
|
|
@ -96,13 +94,4 @@ export default defineComponent({
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
.custom-select {
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
position: absolute;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<LabelAndValue class="flex-grow-1" :label="title" align="end" data-testid="limit-soc">
|
<LabelAndValue class="flex-grow-1" :label="title" align="end" data-testid="limit-soc">
|
||||||
<h3 class="value m-0">
|
<h3 class="value m-0">
|
||||||
<label class="position-relative" role="button">
|
<CustomSelect inline :options="options" :selected="limitSoc" @change="change">
|
||||||
<select :value="limitSoc" class="custom-select" @change="change">
|
|
||||||
<option v-for="{ soc, text } in options" :key="soc" :value="soc">
|
|
||||||
{{ text }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<span class="text-decoration-underline" data-testid="limit-soc-value">
|
<span class="text-decoration-underline" data-testid="limit-soc-value">
|
||||||
<AnimatedNumber :to="limitSoc" :format="formatSoc" />
|
<AnimatedNumber :to="limitSoc" :format="formatSoc" />
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</CustomSelect>
|
||||||
|
|
||||||
<div v-if="estimatedTargetRange" class="extraValue text-nowrap">
|
<div v-if="estimatedTargetRange" class="extraValue text-nowrap">
|
||||||
<AnimatedNumber :to="estimatedTargetRange" :format="formatKm" />
|
<AnimatedNumber :to="estimatedTargetRange" :format="formatKm" />
|
||||||
|
|
@ -23,12 +18,13 @@
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import LabelAndValue from "../Helper/LabelAndValue.vue";
|
import LabelAndValue from "../Helper/LabelAndValue.vue";
|
||||||
import AnimatedNumber from "../Helper/AnimatedNumber.vue";
|
import AnimatedNumber from "../Helper/AnimatedNumber.vue";
|
||||||
|
import CustomSelect from "../Helper/CustomSelect.vue";
|
||||||
import { distanceUnit } from "@/units";
|
import { distanceUnit } from "@/units";
|
||||||
import formatter from "@/mixins/formatter";
|
import formatter from "@/mixins/formatter";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "LimitSocSelect",
|
name: "LimitSocSelect",
|
||||||
components: { LabelAndValue, AnimatedNumber },
|
components: { LabelAndValue, AnimatedNumber, CustomSelect },
|
||||||
mixins: [formatter],
|
mixins: [formatter],
|
||||||
props: {
|
props: {
|
||||||
limitSoc: { type: Number, default: 0 },
|
limitSoc: { type: Number, default: 0 },
|
||||||
|
|
@ -47,8 +43,8 @@ export default defineComponent({
|
||||||
const start = this.rangeActive ? this.minTemp : 20;
|
const start = this.rangeActive ? this.minTemp : 20;
|
||||||
const end = this.rangeActive ? this.maxTemp : 100;
|
const end = this.rangeActive ? this.maxTemp : 100;
|
||||||
for (let soc = start; soc <= end; soc += this.step) {
|
for (let soc = start; soc <= end; soc += this.step) {
|
||||||
const text = this.fmtSocOption(soc, this.rangePerSoc, distanceUnit(), this.heating);
|
const name = this.fmtSocOption(soc, this.rangePerSoc, distanceUnit(), this.heating);
|
||||||
result.push({ soc, text });
|
result.push({ value: soc, name });
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
@ -90,7 +86,6 @@ export default defineComponent({
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.value {
|
.value {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
.extraValue {
|
.extraValue {
|
||||||
margin-top: 0.1rem;
|
margin-top: 0.1rem;
|
||||||
|
|
@ -98,14 +93,4 @@ export default defineComponent({
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
.custom-select {
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
position: absolute;
|
|
||||||
opacity: 0;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,13 @@
|
||||||
role="button"
|
role="button"
|
||||||
data-testid="change-vehicle"
|
data-testid="change-vehicle"
|
||||||
>
|
>
|
||||||
<select :id="dropdownId" :value="selected" class="custom-select" @change="change">
|
<select
|
||||||
|
:id="dropdownId"
|
||||||
|
:value="selected"
|
||||||
|
:aria-label="$t('main.vehicle.changeVehicle')"
|
||||||
|
class="custom-select"
|
||||||
|
@change="change"
|
||||||
|
>
|
||||||
<option
|
<option
|
||||||
v-for="{ name, value } in vehicleOptions"
|
v-for="{ name, value } in vehicleOptions"
|
||||||
:key="name"
|
:key="name"
|
||||||
|
|
|
||||||
207
assets/js/components/Vehicles/SettingsModal.vue
Normal file
207
assets/js/components/Vehicles/SettingsModal.vue
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
<template>
|
||||||
|
<GenericModal
|
||||||
|
id="vehicleSettingsModal"
|
||||||
|
ref="modal"
|
||||||
|
size="lg"
|
||||||
|
:title="$t('main.vehicleSettings.title')"
|
||||||
|
data-testid="vehicle-settings-modal"
|
||||||
|
@open="modalVisible"
|
||||||
|
@closed="modalInvisible"
|
||||||
|
>
|
||||||
|
<div v-if="isModalVisible">
|
||||||
|
<p class="text-gray mt-0 mb-4">
|
||||||
|
{{ $t("main.vehicleSettings.description") }}
|
||||||
|
<a :href="docsUrl" target="_blank" rel="noopener">
|
||||||
|
{{ $t("main.vehicleSettings.learnMore") }}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
v-for="(vehicle, index) in vehicles"
|
||||||
|
:key="vehicle.name"
|
||||||
|
role="group"
|
||||||
|
:aria-label="vehicle.title"
|
||||||
|
:class="{ 'border-top pt-4': index > 0 }"
|
||||||
|
class="mb-4"
|
||||||
|
>
|
||||||
|
<div class="d-flex flex-wrap align-items-center column-gap-2 row-gap-1 mb-3">
|
||||||
|
<VehicleIcon :name="vehicle.icon" class="flex-shrink-0" />
|
||||||
|
<strong class="text-truncate">{{ vehicle.title }}</strong>
|
||||||
|
<Badge v-if="connectedLoadpoint(vehicle)" class="flex-shrink-0">
|
||||||
|
{{
|
||||||
|
$t("main.vehicleSettings.connectedTo", [
|
||||||
|
connectedLoadpoint(vehicle)?.title ||
|
||||||
|
$t("main.loadpoint.fallbackName"),
|
||||||
|
])
|
||||||
|
}}
|
||||||
|
</Badge>
|
||||||
|
<Badge v-else variant="muted" class="flex-shrink-0">
|
||||||
|
{{ $t("main.vehicleSettings.notConnected") }}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<SettingsFormRow
|
||||||
|
:id="fieldId(vehicle, 'mode')"
|
||||||
|
:label="$t('main.vehicleSettings.mode')"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
:id="fieldId(vehicle, 'mode')"
|
||||||
|
class="form-select form-select-sm"
|
||||||
|
:value="vehicle.mode ?? ''"
|
||||||
|
@change="changeMode(vehicle, $event)"
|
||||||
|
>
|
||||||
|
<option v-for="opt in modeOptions" :key="opt.value" :value="opt.value">
|
||||||
|
{{ opt.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</SettingsFormRow>
|
||||||
|
<template v-if="socSupported(vehicle)">
|
||||||
|
<SettingsFormRow
|
||||||
|
:id="fieldId(vehicle, 'limitSoc')"
|
||||||
|
:label="$t('main.vehicleSettings.limitSoc')"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
:id="fieldId(vehicle, 'limitSoc')"
|
||||||
|
class="form-select form-select-sm"
|
||||||
|
:value="vehicle.limitSoc ?? 0"
|
||||||
|
@change="changeLimitSoc(vehicle, $event)"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="opt in socOptions(vehicle)"
|
||||||
|
:key="opt.value"
|
||||||
|
:value="opt.value"
|
||||||
|
>
|
||||||
|
{{ opt.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</SettingsFormRow>
|
||||||
|
<SettingsFormRow
|
||||||
|
:id="fieldId(vehicle, 'minSoc')"
|
||||||
|
:label="$t('main.vehicleSettings.minSoc')"
|
||||||
|
:description="$t('main.vehicleSettings.minSocDescription')"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
:id="fieldId(vehicle, 'minSoc')"
|
||||||
|
class="form-select form-select-sm"
|
||||||
|
:value="vehicle.minSoc ?? 0"
|
||||||
|
@change="changeMinSoc(vehicle, $event)"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="opt in socOptions(vehicle)"
|
||||||
|
:key="opt.value"
|
||||||
|
:value="opt.value"
|
||||||
|
>
|
||||||
|
{{ opt.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</SettingsFormRow>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<p class="mb-0 border-top pt-4">
|
||||||
|
<i18n-t keypath="main.vehicleSettings.editHint" tag="span" scope="global">
|
||||||
|
<router-link to="/config#vehicles" @click="closeModal">
|
||||||
|
{{ $t("config.main.title") }}
|
||||||
|
</router-link>
|
||||||
|
</i18n-t>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</GenericModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Badge from "../Helper/Badge.vue";
|
||||||
|
import GenericModal from "../Helper/GenericModal.vue";
|
||||||
|
import SettingsFormRow from "../Helper/SettingsFormRow.vue";
|
||||||
|
import VehicleIcon from "../VehicleIcon";
|
||||||
|
import api from "@/api";
|
||||||
|
import formatter from "@/mixins/formatter";
|
||||||
|
import { docsPrefix } from "@/i18n";
|
||||||
|
import { distanceUnit } from "@/units";
|
||||||
|
import { vehicleHasSoc, vehicleNotReachable } from "@/uiLoadpoints";
|
||||||
|
import { CHARGE_MODE, type SelectOption, type UiLoadpoint, type Vehicle } from "@/types/evcc";
|
||||||
|
import { defineComponent, type PropType } from "vue";
|
||||||
|
|
||||||
|
const { OFF, PV, MINPV, NOW } = CHARGE_MODE;
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "VehicleSettingsModal",
|
||||||
|
components: { Badge, GenericModal, SettingsFormRow, VehicleIcon },
|
||||||
|
mixins: [formatter],
|
||||||
|
props: {
|
||||||
|
vehicles: { type: Array as PropType<Vehicle[]>, default: () => [] },
|
||||||
|
loadpoints: { type: Array as PropType<UiLoadpoint[]>, default: () => [] },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isModalVisible: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
docsUrl(): string {
|
||||||
|
return `${docsPrefix()}/features/limits`;
|
||||||
|
},
|
||||||
|
modeOptions(): SelectOption<string>[] {
|
||||||
|
return [
|
||||||
|
{ value: "", name: this.$t("main.vehicleSettings.keepAsIs") },
|
||||||
|
...[OFF, PV, MINPV, NOW].map((mode) => ({
|
||||||
|
value: mode,
|
||||||
|
name: this.$t(`main.mode.${mode}`),
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
modalVisible(): void {
|
||||||
|
this.isModalVisible = true;
|
||||||
|
},
|
||||||
|
modalInvisible(): void {
|
||||||
|
this.isModalVisible = false;
|
||||||
|
},
|
||||||
|
closeModal(): void {
|
||||||
|
(this.$refs["modal"] as InstanceType<typeof GenericModal> | undefined)?.close();
|
||||||
|
},
|
||||||
|
fieldId(vehicle: Vehicle, field: string): string {
|
||||||
|
return `vehicleSettings-${vehicle.name}-${field}`;
|
||||||
|
},
|
||||||
|
connectedLoadpoint(vehicle: Vehicle): UiLoadpoint | undefined {
|
||||||
|
return this.loadpoints.find((lp) => lp.vehicleName === vehicle.name && lp.connected);
|
||||||
|
},
|
||||||
|
socSupported(vehicle: Vehicle): boolean {
|
||||||
|
const loadpoint = this.connectedLoadpoint(vehicle);
|
||||||
|
if (loadpoint) {
|
||||||
|
return loadpoint.socBasedCharging || loadpoint.vehicleNotReachable;
|
||||||
|
}
|
||||||
|
return vehicleHasSoc(vehicle) || vehicleNotReachable(vehicle);
|
||||||
|
},
|
||||||
|
socOptions(vehicle: Vehicle): SelectOption<number>[] {
|
||||||
|
// 0 = none, then 5-100 in steps of 5
|
||||||
|
const rangePerSoc = this.connectedLoadpoint(vehicle)?.rangePerSoc;
|
||||||
|
return Array.from(Array(21).keys()).map((i) => {
|
||||||
|
const soc = i * 5;
|
||||||
|
return {
|
||||||
|
value: soc,
|
||||||
|
name:
|
||||||
|
soc === 0
|
||||||
|
? this.$t("general.none")
|
||||||
|
: this.fmtSocOption(soc, rangePerSoc, distanceUnit()),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
selectValue(event: Event): string {
|
||||||
|
return (event.target as HTMLSelectElement).value;
|
||||||
|
},
|
||||||
|
changeMode(vehicle: Vehicle, event: Event): void {
|
||||||
|
const mode = this.selectValue(event);
|
||||||
|
if (mode === "") {
|
||||||
|
api.delete(`vehicles/${vehicle.name}/mode`);
|
||||||
|
} else {
|
||||||
|
api.post(`vehicles/${vehicle.name}/mode/${mode}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changeMinSoc(vehicle: Vehicle, event: Event): void {
|
||||||
|
api.post(`vehicles/${vehicle.name}/minsoc/${this.selectValue(event)}`);
|
||||||
|
},
|
||||||
|
changeLimitSoc(vehicle: Vehicle, event: Event): void {
|
||||||
|
api.post(`vehicles/${vehicle.name}/limitsoc/${this.selectValue(event)}`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="d-flex justify-content-between mb-3 align-items-center" data-testid="vehicle-title">
|
<div class="d-flex justify-content-between mb-3 align-items-center" data-testid="vehicle-title">
|
||||||
<h4 class="d-flex align-items-center m-0 flex-grow-1 overflow-hidden">
|
<h4 class="d-flex align-items-center flex-grow-1 overflow-hidden ring-space">
|
||||||
<div
|
<div
|
||||||
v-if="iconType === 'refresh'"
|
v-if="iconType === 'refresh'"
|
||||||
ref="refresh"
|
ref="refresh"
|
||||||
|
|
@ -158,6 +158,11 @@ export default defineComponent({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
/* overflow-hidden would clip the vehicle select focus ring */
|
||||||
|
.ring-space {
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin: -0.5rem;
|
||||||
|
}
|
||||||
.vehicle-name {
|
.vehicle-name {
|
||||||
text-decoration-color: var(--evcc-gray);
|
text-decoration-color: var(--evcc-gray);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@
|
||||||
v-bind="vehicleStatus"
|
v-bind="vehicleStatus"
|
||||||
class="mb-2"
|
class="mb-2"
|
||||||
@open-loadpoint-settings="$emit('open-loadpoint-settings')"
|
@open-loadpoint-settings="$emit('open-loadpoint-settings')"
|
||||||
@open-minsoc-settings="openPlanModal(true)"
|
@open-minsoc-settings="openVehicleSettings"
|
||||||
@open-plan-modal="openPlanModal"
|
@open-plan-modal="$emit('open-modal')"
|
||||||
/>
|
/>
|
||||||
<div class="mt-2 mb-4 d-flex gap-2">
|
<div class="mt-2 mb-4 d-flex gap-2">
|
||||||
<BatteryBoostButton
|
<BatteryBoostButton
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
v-bind="vehicleSocProps"
|
v-bind="vehicleSocProps"
|
||||||
@limit-soc-updated="limitSocUpdated"
|
@limit-soc-updated="limitSocUpdated"
|
||||||
@limit-soc-drag="limitSocDrag"
|
@limit-soc-drag="limitSocDrag"
|
||||||
@plan-clicked="openPlanModal"
|
@plan-clicked="$emit('open-modal')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="details d-flex flex-wrap justify-content-between">
|
<div class="details d-flex flex-wrap justify-content-between">
|
||||||
|
|
@ -80,6 +80,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import Modal from "bootstrap/js/dist/modal";
|
||||||
import collector from "@/mixins/collector.ts";
|
import collector from "@/mixins/collector.ts";
|
||||||
import formatter, { POWER_UNIT } from "@/mixins/formatter";
|
import formatter, { POWER_UNIT } from "@/mixins/formatter";
|
||||||
import LabelAndValue from "../Helper/LabelAndValue.vue";
|
import LabelAndValue from "../Helper/LabelAndValue.vue";
|
||||||
|
|
@ -287,8 +288,10 @@ export default defineComponent({
|
||||||
fmtEnergy(value: number) {
|
fmtEnergy(value: number) {
|
||||||
return this.fmtWh(value, value == 0 ? POWER_UNIT.KW : POWER_UNIT.AUTO);
|
return this.fmtWh(value, value == 0 ? POWER_UNIT.KW : POWER_UNIT.AUTO);
|
||||||
},
|
},
|
||||||
openPlanModal(openArrivalTab = false) {
|
openVehicleSettings() {
|
||||||
this.$emit("open-modal", openArrivalTab);
|
Modal.getOrCreateInstance(
|
||||||
|
document.getElementById("vehicleSettingsModal") as HTMLElement
|
||||||
|
).show();
|
||||||
},
|
},
|
||||||
handleBoostStatus(status: VehicleStatus) {
|
handleBoostStatus(status: VehicleStatus) {
|
||||||
this.statusOverride = status;
|
this.statusOverride = status;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,15 @@ const get = (id: string) => {
|
||||||
return settings.loadpoints[id];
|
return settings.loadpoints[id];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const vehicleHasSoc = (vehicle?: Vehicle): boolean => {
|
||||||
|
return !vehicle?.features?.includes("Offline");
|
||||||
|
};
|
||||||
|
|
||||||
|
export const vehicleNotReachable = (vehicle?: Vehicle): boolean => {
|
||||||
|
const features = vehicle?.features || [];
|
||||||
|
return features.includes("Offline") && features.includes("Retryable");
|
||||||
|
};
|
||||||
|
|
||||||
export const convertToUiLoadpoints = (
|
export const convertToUiLoadpoints = (
|
||||||
loadpoints: Loadpoint[],
|
loadpoints: Loadpoint[],
|
||||||
vehicles: Record<string, Vehicle>
|
vehicles: Record<string, Vehicle>
|
||||||
|
|
@ -24,8 +33,8 @@ export const convertToUiLoadpoints = (
|
||||||
const capacity = vehicle?.capacity || 0;
|
const capacity = vehicle?.capacity || 0;
|
||||||
const range = distanceValue(vehicleRange);
|
const range = distanceValue(vehicleRange);
|
||||||
const vehicleKnown = !!lp.vehicleName;
|
const vehicleKnown = !!lp.vehicleName;
|
||||||
const vehicleHasSoc = vehicleKnown && !vehicle?.features?.includes("Offline");
|
const hasSoc = vehicleKnown && vehicleHasSoc(vehicle);
|
||||||
const socBasedCharging = vehicleHasSoc || lp.vehicleSoc > 0;
|
const socBasedCharging = hasSoc || lp.vehicleSoc > 0;
|
||||||
const socBasedPlanning = !!(socBasedCharging && capacity > 0);
|
const socBasedPlanning = !!(socBasedCharging && capacity > 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -36,7 +45,7 @@ export const convertToUiLoadpoints = (
|
||||||
vehicleSoc,
|
vehicleSoc,
|
||||||
capacity,
|
capacity,
|
||||||
vehicleKnown,
|
vehicleKnown,
|
||||||
vehicleHasSoc,
|
vehicleHasSoc: hasSoc,
|
||||||
socBasedCharging,
|
socBasedCharging,
|
||||||
socBasedPlanning,
|
socBasedPlanning,
|
||||||
displayTitle: vehicle?.title || lp.title || "Charging point",
|
displayTitle: vehicle?.title || lp.title || "Charging point",
|
||||||
|
|
@ -49,9 +58,7 @@ export const convertToUiLoadpoints = (
|
||||||
rangePerSoc:
|
rangePerSoc:
|
||||||
vehicleSoc > 10 && range ? Math.round((range / vehicleSoc) * 1e2) / 1e2 : undefined,
|
vehicleSoc > 10 && range ? Math.round((range / vehicleSoc) * 1e2) / 1e2 : undefined,
|
||||||
socPerKwh: capacity > 0 ? 100 / capacity : 0,
|
socPerKwh: capacity > 0 ? 100 / capacity : 0,
|
||||||
vehicleNotReachable:
|
vehicleNotReachable: vehicleNotReachable(vehicle),
|
||||||
(vehicle?.features || []).includes("Offline") &&
|
|
||||||
(vehicle?.features || []).includes("Retryable"),
|
|
||||||
} satisfies UiLoadpoint;
|
} satisfies UiLoadpoint;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
6
assets/js/utils/vehicleList.ts
Normal file
6
assets/js/utils/vehicleList.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import type { Vehicle } from "@/types/evcc";
|
||||||
|
|
||||||
|
// convert the vehicles state record into a list, keys become vehicle names
|
||||||
|
export default function vehicleList(vehicles?: Record<string, Vehicle>): Vehicle[] {
|
||||||
|
return Object.entries(vehicles || {}).map(([name, vehicle]) => ({ ...vehicle, name }));
|
||||||
|
}
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
<BottomTabBar v-bind="bottomTabBarProps" />
|
<BottomTabBar v-bind="bottomTabBarProps" />
|
||||||
|
|
||||||
<GlobalSettingsModal v-bind="globalSettingsProps" />
|
<GlobalSettingsModal v-bind="globalSettingsProps" />
|
||||||
|
<VehicleSettingsModal :vehicles="vehicleList" :loadpoints="state.uiLoadpoints" />
|
||||||
<AboutModal v-bind="aboutModalProps" />
|
<AboutModal v-bind="aboutModalProps" />
|
||||||
<HelpModal />
|
<HelpModal />
|
||||||
<PasswordModal />
|
<PasswordModal />
|
||||||
|
|
@ -21,12 +22,14 @@
|
||||||
import store from "../store";
|
import store from "../store";
|
||||||
import BottomTabBar from "../components/BottomTabs/Bar.vue";
|
import BottomTabBar from "../components/BottomTabs/Bar.vue";
|
||||||
import GlobalSettingsModal from "../components/GlobalSettings/GlobalSettingsModal.vue";
|
import GlobalSettingsModal from "../components/GlobalSettings/GlobalSettingsModal.vue";
|
||||||
|
import VehicleSettingsModal from "../components/Vehicles/SettingsModal.vue";
|
||||||
import OfflineIndicator from "../components/Footer/OfflineIndicator.vue";
|
import OfflineIndicator from "../components/Footer/OfflineIndicator.vue";
|
||||||
import PasswordModal from "../components/Auth/PasswordModal.vue";
|
import PasswordModal from "../components/Auth/PasswordModal.vue";
|
||||||
import LoginModal from "../components/Auth/LoginModal.vue";
|
import LoginModal from "../components/Auth/LoginModal.vue";
|
||||||
import AboutModal from "../components/AboutModal.vue";
|
import AboutModal from "../components/AboutModal.vue";
|
||||||
import HelpModal from "../components/HelpModal.vue";
|
import HelpModal from "../components/HelpModal.vue";
|
||||||
import collector from "../mixins/collector";
|
import collector from "../mixins/collector";
|
||||||
|
import vehicleList from "@/utils/vehicleList";
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
// assume offline if not data received for 5 minutes
|
// assume offline if not data received for 5 minutes
|
||||||
|
|
@ -45,6 +48,7 @@ export default defineComponent({
|
||||||
AboutModal,
|
AboutModal,
|
||||||
BottomTabBar,
|
BottomTabBar,
|
||||||
GlobalSettingsModal,
|
GlobalSettingsModal,
|
||||||
|
VehicleSettingsModal,
|
||||||
HelpModal,
|
HelpModal,
|
||||||
PasswordModal,
|
PasswordModal,
|
||||||
LoginModal,
|
LoginModal,
|
||||||
|
|
@ -77,6 +81,9 @@ export default defineComponent({
|
||||||
const { state, uiLoadpoints } = store;
|
const { state, uiLoadpoints } = store;
|
||||||
return { ...state, uiLoadpoints: uiLoadpoints.value };
|
return { ...state, uiLoadpoints: uiLoadpoints.value };
|
||||||
},
|
},
|
||||||
|
vehicleList() {
|
||||||
|
return vehicleList(this.state.vehicles);
|
||||||
|
},
|
||||||
globalSettingsProps() {
|
globalSettingsProps() {
|
||||||
return this.collectProps(GlobalSettingsModal, this.state);
|
return this.collectProps(GlobalSettingsModal, this.state);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="my-4">{{ $t("config.section.vehicles") }}</h2>
|
<h2 id="vehicles" class="my-4">{{ $t("config.section.vehicles") }}</h2>
|
||||||
<div class="p-0 config-list box-pull-out">
|
<div class="p-0 config-list box-pull-out">
|
||||||
<DeviceCard
|
<DeviceCard
|
||||||
v-for="vehicle in vehicles"
|
v-for="vehicle in vehicles"
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,7 @@ import DynamicPriceIcon from "../components/MaterialIcon/DynamicPrice.vue";
|
||||||
import { TYPES, GROUPS, PERIODS, type Session } from "../components/Sessions/types";
|
import { TYPES, GROUPS, PERIODS, type Session } from "../components/Sessions/types";
|
||||||
import { defineComponent, type PropType } from "vue";
|
import { defineComponent, type PropType } from "vue";
|
||||||
import { CURRENCY, type Notification } from "@/types/evcc";
|
import { CURRENCY, type Notification } from "@/types/evcc";
|
||||||
|
import vehicleList from "@/utils/vehicleList";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Sessions",
|
name: "Sessions",
|
||||||
|
|
@ -468,8 +469,7 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
vehicleList() {
|
vehicleList() {
|
||||||
const vehicles = store.state.vehicles || {};
|
return vehicleList(store.state.vehicles);
|
||||||
return Object.entries(vehicles).map(([name, vehicle]) => ({ ...vehicle, name }));
|
|
||||||
},
|
},
|
||||||
loadpointList() {
|
loadpointList() {
|
||||||
const loadpoints = store.state.loadpoints || [];
|
const loadpoints = store.state.loadpoints || [];
|
||||||
|
|
|
||||||
12
i18n/bg.json
12
i18n/bg.json
|
|
@ -854,9 +854,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Активен",
|
"active": "Активен",
|
||||||
"addRepeatingPlan": "Добавяне на повтарящ се план",
|
"addRepeatingPlan": "Добавяне на повтарящ се план",
|
||||||
"arrivalTab": "Пристигане",
|
|
||||||
"day": "Ден",
|
"day": "Ден",
|
||||||
"departureTab": "Заминаване",
|
|
||||||
"goal": "Цел на зареждане",
|
"goal": "Цел на зареждане",
|
||||||
"modalTitle": "План за зареждане",
|
"modalTitle": "План за зареждане",
|
||||||
"none": "няма",
|
"none": "няма",
|
||||||
|
|
@ -880,8 +878,6 @@
|
||||||
"strategySettings": "Настройки на стратегията",
|
"strategySettings": "Настройки на стратегията",
|
||||||
"time": "Време",
|
"time": "Време",
|
||||||
"title": "План",
|
"title": "План",
|
||||||
"titleMinSoc": "Минимално зареждане",
|
|
||||||
"titleTargetCharge": "Заминаване",
|
|
||||||
"unsavedChanges": "Има незаписани промени. Приложи сега?",
|
"unsavedChanges": "Има незаписани промени. Приложи сега?",
|
||||||
"update": "Приложи",
|
"update": "Приложи",
|
||||||
"weekdays": "Дни"
|
"weekdays": "Дни"
|
||||||
|
|
@ -939,20 +935,12 @@
|
||||||
"currents": "Заряден ток",
|
"currents": "Заряден ток",
|
||||||
"default": "по подразбиране",
|
"default": "по подразбиране",
|
||||||
"disclaimerHint": "Забележка:",
|
"disclaimerHint": "Забележка:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Ограничение на зареждането, което се използва, когато този автомобил е свързан.",
|
|
||||||
"label": "Лимит по подразбиране"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Макс. ток"
|
"label": "Макс. ток"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Мин. ток"
|
"label": "Мин. ток"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Превозното средство се зарежда „бързо“ до {0} в соларен режим. След това продължава със соларен излишък. Полезно за осигуряване на минимален пробег дори в по-тъмни дни.",
|
|
||||||
"label": "Мин. заряд %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Тези опции са налични само за превозни средства с известен заряд.",
|
"onlyForSocBasedCharging": "Тези опции са налични само за превозни средства с известен заряд.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Фази",
|
"label": "Фази",
|
||||||
|
|
|
||||||
|
|
@ -393,9 +393,6 @@
|
||||||
"remoteDisabledSoft": "{source}: isključeno prilagodljivo solarno punjenje"
|
"remoteDisabledSoft": "{source}: isključeno prilagodljivo solarno punjenje"
|
||||||
},
|
},
|
||||||
"loadpointSettings": {
|
"loadpointSettings": {
|
||||||
"minSoc": {
|
|
||||||
"description": "Vozilo se brzo puni do {0} u solarnom načinu rada. Zatim nastavlja punjenjem viškom solarne energije. Korisno za osiguranje minimalnog dometa čak i za tmurnije dane."
|
|
||||||
},
|
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"phases_1_hint": "(od {min} do {max})",
|
"phases_1_hint": "(od {min} do {max})",
|
||||||
"phases_3_hint": "(od {min} do {max})"
|
"phases_3_hint": "(od {min} do {max})"
|
||||||
|
|
|
||||||
10
i18n/ca.json
10
i18n/ca.json
|
|
@ -116,13 +116,9 @@
|
||||||
},
|
},
|
||||||
"main": {
|
"main": {
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"arrivalTab": "Arribades",
|
|
||||||
"departureTab": "Sortides",
|
|
||||||
"modalTitle": "Plà de càrrega",
|
"modalTitle": "Plà de càrrega",
|
||||||
"none": "no definit",
|
"none": "no definit",
|
||||||
"title": "Plà",
|
"title": "Plà"
|
||||||
"titleMinSoc": "Càrrega mínima",
|
|
||||||
"titleTargetCharge": "Sortides"
|
|
||||||
},
|
},
|
||||||
"energyflow": {
|
"energyflow": {
|
||||||
"battery": "Bateria",
|
"battery": "Bateria",
|
||||||
|
|
@ -156,10 +152,6 @@
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Corriente de carrega mínima"
|
"label": "Corriente de carrega mínima"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Marge per a emergències. El vehicle es carrega 'ràpidament' a {0} en mode solar. Després continua amb l'excedent fotovoltaic.",
|
|
||||||
"label": "Càrrega de min. %"
|
|
||||||
},
|
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fases",
|
"label": "Fases",
|
||||||
"phases_0": "Canvi automàtic",
|
"phases_0": "Canvi automàtic",
|
||||||
|
|
|
||||||
12
i18n/cs.json
12
i18n/cs.json
|
|
@ -1157,9 +1157,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktivní",
|
"active": "Aktivní",
|
||||||
"addRepeatingPlan": "Přidat opakující se plán",
|
"addRepeatingPlan": "Přidat opakující se plán",
|
||||||
"arrivalTab": "Příchod",
|
|
||||||
"day": "Den",
|
"day": "Den",
|
||||||
"departureTab": "Odchod",
|
|
||||||
"goal": "Cílový stav nabíjení",
|
"goal": "Cílový stav nabíjení",
|
||||||
"modalTitle": "Plán nabíjení",
|
"modalTitle": "Plán nabíjení",
|
||||||
"none": "Žádný",
|
"none": "Žádný",
|
||||||
|
|
@ -1183,8 +1181,6 @@
|
||||||
"strategySettings": "Nastavení strategie",
|
"strategySettings": "Nastavení strategie",
|
||||||
"time": "Čas",
|
"time": "Čas",
|
||||||
"title": "Plán",
|
"title": "Plán",
|
||||||
"titleMinSoc": "Min. nabíjení",
|
|
||||||
"titleTargetCharge": "Odjezd",
|
|
||||||
"unsavedChanges": "Jsou zde neuložené změny. Použít nyní?",
|
"unsavedChanges": "Jsou zde neuložené změny. Použít nyní?",
|
||||||
"update": "Nastavit",
|
"update": "Nastavit",
|
||||||
"weekdays": "Dny"
|
"weekdays": "Dny"
|
||||||
|
|
@ -1282,20 +1278,12 @@
|
||||||
"currents": "Nabíjecí proud",
|
"currents": "Nabíjecí proud",
|
||||||
"default": "výchozí",
|
"default": "výchozí",
|
||||||
"disclaimerHint": "Poznámka:",
|
"disclaimerHint": "Poznámka:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Nabíjecí limit, který je použit, když je připojeno toto vozidlo.",
|
|
||||||
"label": "Výchozí limit nabití"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Max. Proud"
|
"label": "Max. Proud"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. Proud"
|
"label": "Min. Proud"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Vozidlo bude rychle nabito na {0} v solárním režimu. Poté bude pokračovat nabíjení z přebytku solární energie. Užitečné pro zajištění minimálního dojezdu i během zatažených dnů.",
|
|
||||||
"label": "Minimální úroveň nabití"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Tyto volby jsou povolené pouze pro vozidla se známou nabíjecí úrovní.",
|
"onlyForSocBasedCharging": "Tyto volby jsou povolené pouze pro vozidla se známou nabíjecí úrovní.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Připojení fází",
|
"label": "Připojení fází",
|
||||||
|
|
|
||||||
12
i18n/da.json
12
i18n/da.json
|
|
@ -1194,9 +1194,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"addRepeatingPlan": "Tilføj plan for gentagelse",
|
"addRepeatingPlan": "Tilføj plan for gentagelse",
|
||||||
"arrivalTab": "Ankomst",
|
|
||||||
"day": "Dag",
|
"day": "Dag",
|
||||||
"departureTab": "Afgang",
|
|
||||||
"goal": "Opladnings mål",
|
"goal": "Opladnings mål",
|
||||||
"modalTitle": "Lade plan",
|
"modalTitle": "Lade plan",
|
||||||
"none": "ingen",
|
"none": "ingen",
|
||||||
|
|
@ -1220,8 +1218,6 @@
|
||||||
"strategySettings": "Indstillinger for strategi",
|
"strategySettings": "Indstillinger for strategi",
|
||||||
"time": "Tid",
|
"time": "Tid",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Min. ladning",
|
|
||||||
"titleTargetCharge": "Afgang",
|
|
||||||
"unsavedChanges": "Der er ændringer som ikke er gemt. Skal de benyttes nu?",
|
"unsavedChanges": "Der er ændringer som ikke er gemt. Skal de benyttes nu?",
|
||||||
"update": "Anvend",
|
"update": "Anvend",
|
||||||
"weekdays": "Dage"
|
"weekdays": "Dage"
|
||||||
|
|
@ -1320,20 +1316,12 @@
|
||||||
"currents": "Ladestrøm",
|
"currents": "Ladestrøm",
|
||||||
"default": "standard",
|
"default": "standard",
|
||||||
"disclaimerHint": "Bemærk:",
|
"disclaimerHint": "Bemærk:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Opladningsgrænse som benyttes når dette køretøj er forbundet.",
|
|
||||||
"label": "standard opladningsgrænse"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Max. Nuværende"
|
"label": "Max. Nuværende"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. Nuværende"
|
"label": "Min. Nuværende"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Køretøjet bliver „hurtigt” opladet til {0} i solar mode, og fortsætter derefter med solenergioverskuddet. Nyttig til at sikre en minimum rækkevidde selv på mørke dage.",
|
|
||||||
"label": "Min. opladning %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Disse indstillinger er kun tilgængelig for køretøjer med kendt opladningsniveau.",
|
"onlyForSocBasedCharging": "Disse indstillinger er kun tilgængelig for køretøjer med kendt opladningsniveau.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Faser",
|
"label": "Faser",
|
||||||
|
|
|
||||||
30
i18n/de.json
30
i18n/de.json
|
|
@ -1146,6 +1146,7 @@
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
|
"none": "keine",
|
||||||
"note": "Hinweis:"
|
"note": "Hinweis:"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
|
|
@ -1259,9 +1260,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"addRepeatingPlan": "Wiederholenden Plan hinzufügen",
|
"addRepeatingPlan": "Wiederholenden Plan hinzufügen",
|
||||||
"arrivalTab": "Ankunft",
|
|
||||||
"day": "Tag",
|
"day": "Tag",
|
||||||
"departureTab": "Abfahrt",
|
|
||||||
"goal": "Ladeziel",
|
"goal": "Ladeziel",
|
||||||
"modalTitle": "Ladeplanung",
|
"modalTitle": "Ladeplanung",
|
||||||
"none": "keiner",
|
"none": "keiner",
|
||||||
|
|
@ -1285,8 +1284,6 @@
|
||||||
"strategySettings": "Strategie-Einstellungen",
|
"strategySettings": "Strategie-Einstellungen",
|
||||||
"time": "Zeit",
|
"time": "Zeit",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Min. Ladung",
|
|
||||||
"titleTargetCharge": "Abfahrt",
|
|
||||||
"unsavedChanges": "Ungespeicherte Änderungen vorhanden. Jetzt anwenden?",
|
"unsavedChanges": "Ungespeicherte Änderungen vorhanden. Jetzt anwenden?",
|
||||||
"update": "Anwenden",
|
"update": "Anwenden",
|
||||||
"weekdays": "Tage"
|
"weekdays": "Tage"
|
||||||
|
|
@ -1315,7 +1312,8 @@
|
||||||
"pv": "Solaranlage",
|
"pv": "Solaranlage",
|
||||||
"pvExport": "Einspeisung",
|
"pvExport": "Einspeisung",
|
||||||
"pvProduction": "Erzeugung",
|
"pvProduction": "Erzeugung",
|
||||||
"selfConsumption": "Eigenverbrauch"
|
"selfConsumption": "Eigenverbrauch",
|
||||||
|
"toggleDetails": "Energiefluss-Details"
|
||||||
},
|
},
|
||||||
"heatingStatus": {
|
"heatingStatus": {
|
||||||
"charging": "Heize …",
|
"charging": "Heize …",
|
||||||
|
|
@ -1395,20 +1393,12 @@
|
||||||
"currents": "Ladestrom",
|
"currents": "Ladestrom",
|
||||||
"default": "default",
|
"default": "default",
|
||||||
"heating": "Heizen",
|
"heating": "Heizen",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Dieses Ladelimit wird verwendet, wenn das Fahrzeug angeschlossen wird.",
|
|
||||||
"label": "Standard Ladelimit"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Max. Ladestrom"
|
"label": "Max. Ladestrom"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. Ladestrom"
|
"label": "Min. Ladestrom"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Fahrzeug wird im PV-Modus „Schnell“ auf {0} geladen. Danach weiter mit PV-Überschuss. Nützlich, um auch an dunklen Tagen eine Mindestreichweite zu gewährleisten.",
|
|
||||||
"label": "Min. Ladung %"
|
|
||||||
},
|
|
||||||
"minTemp": {
|
"minTemp": {
|
||||||
"description": "Unter {0} wird im PV-Modus auch mit Batterie- und Netzstrom geheizt, um diese Temperatur zu halten.",
|
"description": "Unter {0} wird im PV-Modus auch mit Batterie- und Netzstrom geheizt, um diese Temperatur zu halten.",
|
||||||
"label": "Min. Temperatur"
|
"label": "Min. Temperatur"
|
||||||
|
|
@ -1495,6 +1485,20 @@
|
||||||
"unknown": "Gastfahrzeug",
|
"unknown": "Gastfahrzeug",
|
||||||
"vehicleSoc": "Ladestand"
|
"vehicleSoc": "Ladestand"
|
||||||
},
|
},
|
||||||
|
"vehicleSettings": {
|
||||||
|
"connectedTo": "verbunden mit {0}",
|
||||||
|
"description": "Diese Standardwerte werden angewendet, wenn das Fahrzeug an einem Ladepunkt angeschlossen wird.",
|
||||||
|
"editHint": "Fahrzeuge unter {0} hinzufügen oder bearbeiten.",
|
||||||
|
"keepAsIs": "Beibehalten",
|
||||||
|
"learnMore": "Mehr erfahren.",
|
||||||
|
"limitSoc": "Standardlimit",
|
||||||
|
"menu": "Fahrzeuge",
|
||||||
|
"minSoc": "Minimale Ladung",
|
||||||
|
"minSocDescription": "Wird im PV-Modus schnell bis zu diesem Wert geladen.",
|
||||||
|
"mode": "Standardmodus",
|
||||||
|
"notConnected": "nicht verbunden",
|
||||||
|
"title": "Fahrzeugeinstellungen"
|
||||||
|
},
|
||||||
"vehicleStatus": {
|
"vehicleStatus": {
|
||||||
"awaitingAuthorization": "Warte auf Autorisierung.",
|
"awaitingAuthorization": "Warte auf Autorisierung.",
|
||||||
"batteryBoost": "Batterie Boost aktiv.",
|
"batteryBoost": "Batterie Boost aktiv.",
|
||||||
|
|
|
||||||
12
i18n/el.json
12
i18n/el.json
|
|
@ -859,9 +859,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Ενεργό",
|
"active": "Ενεργό",
|
||||||
"addRepeatingPlan": "Προσθήκη επαναλαμβανόμενου προγράμματος",
|
"addRepeatingPlan": "Προσθήκη επαναλαμβανόμενου προγράμματος",
|
||||||
"arrivalTab": "Άφιξη",
|
|
||||||
"day": "Ημέρα",
|
"day": "Ημέρα",
|
||||||
"departureTab": "Αναχώρηση",
|
|
||||||
"goal": "Επιθυμητή φόρτιση",
|
"goal": "Επιθυμητή φόρτιση",
|
||||||
"modalTitle": "Πρόγραμμα Φόρτισης",
|
"modalTitle": "Πρόγραμμα Φόρτισης",
|
||||||
"none": "κανένα",
|
"none": "κανένα",
|
||||||
|
|
@ -885,8 +883,6 @@
|
||||||
"strategySettings": "Ρυθμίσεις στρατηγικής",
|
"strategySettings": "Ρυθμίσεις στρατηγικής",
|
||||||
"time": "Ώρα",
|
"time": "Ώρα",
|
||||||
"title": "Πρόγραμμα",
|
"title": "Πρόγραμμα",
|
||||||
"titleMinSoc": "Ελάχιστη φόρτιση",
|
|
||||||
"titleTargetCharge": "Αναχώρηση",
|
|
||||||
"unsavedChanges": "Υπάρχουν μη αποθηκευμένες αλλαγές. Υποβολή τώρα;",
|
"unsavedChanges": "Υπάρχουν μη αποθηκευμένες αλλαγές. Υποβολή τώρα;",
|
||||||
"update": "Υποβολή",
|
"update": "Υποβολή",
|
||||||
"weekdays": "Ημέρες"
|
"weekdays": "Ημέρες"
|
||||||
|
|
@ -944,20 +940,12 @@
|
||||||
"currents": "Ένταση φόρτισης",
|
"currents": "Ένταση φόρτισης",
|
||||||
"default": "προεπιλογή",
|
"default": "προεπιλογή",
|
||||||
"disclaimerHint": "Σημείωση:",
|
"disclaimerHint": "Σημείωση:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Όριο φόρτισης που χρησιμοποιείται όταν αυτό το όχημα είναι συνδεδεμένο.",
|
|
||||||
"label": "Προεπιλεγμένο όριο"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Μέγιστη Ένταση"
|
"label": "Μέγιστη Ένταση"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Ελάχιστη Ένταση"
|
"label": "Ελάχιστη Ένταση"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Το όχημα φορτίζεται (γρήγορα) μέχρι {0} σε λειτουργία ηλιακής Φ/Β ενέργειας. Μετά συνεχίζει μόνο με το πλεόνασμα Φ/Β ενέργειας. Χρήσιμο για να εξασφαλίσει μια ελάχιστη εμβέλεια ακόμη και για πιο συννεφιασμένες ημέρες.",
|
|
||||||
"label": "Ελ. % φόρτισης"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Αυτές οι επιλογές είναι διαθέσιμες μόνο για οχήματα με γνωστό επίπεδο φόρτισης.",
|
"onlyForSocBasedCharging": "Αυτές οι επιλογές είναι διαθέσιμες μόνο για οχήματα με γνωστό επίπεδο φόρτισης.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Φάσεις",
|
"label": "Φάσεις",
|
||||||
|
|
|
||||||
30
i18n/en.json
30
i18n/en.json
|
|
@ -1146,6 +1146,7 @@
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
|
"none": "none",
|
||||||
"note": "Note:"
|
"note": "Note:"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
|
|
@ -1259,9 +1260,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Active",
|
"active": "Active",
|
||||||
"addRepeatingPlan": "Add repeating plan",
|
"addRepeatingPlan": "Add repeating plan",
|
||||||
"arrivalTab": "Arrival",
|
|
||||||
"day": "Day",
|
"day": "Day",
|
||||||
"departureTab": "Departure",
|
|
||||||
"goal": "Charging goal",
|
"goal": "Charging goal",
|
||||||
"modalTitle": "Charging Plan",
|
"modalTitle": "Charging Plan",
|
||||||
"none": "none",
|
"none": "none",
|
||||||
|
|
@ -1285,8 +1284,6 @@
|
||||||
"strategySettings": "Strategy settings",
|
"strategySettings": "Strategy settings",
|
||||||
"time": "Time",
|
"time": "Time",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Min charge",
|
|
||||||
"titleTargetCharge": "Departure",
|
|
||||||
"unsavedChanges": "There are unsaved changes. Apply now?",
|
"unsavedChanges": "There are unsaved changes. Apply now?",
|
||||||
"update": "Apply",
|
"update": "Apply",
|
||||||
"weekdays": "Days"
|
"weekdays": "Days"
|
||||||
|
|
@ -1315,7 +1312,8 @@
|
||||||
"pv": "Solar system",
|
"pv": "Solar system",
|
||||||
"pvExport": "Grid export",
|
"pvExport": "Grid export",
|
||||||
"pvProduction": "Production",
|
"pvProduction": "Production",
|
||||||
"selfConsumption": "Self-consumption"
|
"selfConsumption": "Self-consumption",
|
||||||
|
"toggleDetails": "Energy flow details"
|
||||||
},
|
},
|
||||||
"heatingStatus": {
|
"heatingStatus": {
|
||||||
"charging": "Heating…",
|
"charging": "Heating…",
|
||||||
|
|
@ -1395,20 +1393,12 @@
|
||||||
"currents": "Charging Current",
|
"currents": "Charging Current",
|
||||||
"default": "default",
|
"default": "default",
|
||||||
"heating": "Heating",
|
"heating": "Heating",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Charging limit that is used when this vehicle is connected.",
|
|
||||||
"label": "Default limit"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Max. Current"
|
"label": "Max. Current"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. Current"
|
"label": "Min. Current"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "The vehicle gets „fast” charged to {0} in solar mode. Then continues with solar surplus. Useful to ensure a minimum range even for darker days.",
|
|
||||||
"label": "Min. charge %"
|
|
||||||
},
|
|
||||||
"minTemp": {
|
"minTemp": {
|
||||||
"description": "Below {0} battery and grid power are also used in solar mode to maintain this temperature.",
|
"description": "Below {0} battery and grid power are also used in solar mode to maintain this temperature.",
|
||||||
"label": "Min. temperature"
|
"label": "Min. temperature"
|
||||||
|
|
@ -1495,6 +1485,20 @@
|
||||||
"unknown": "Guest vehicle",
|
"unknown": "Guest vehicle",
|
||||||
"vehicleSoc": "Charge"
|
"vehicleSoc": "Charge"
|
||||||
},
|
},
|
||||||
|
"vehicleSettings": {
|
||||||
|
"connectedTo": "connected to {0}",
|
||||||
|
"description": "These defaults are applied when the vehicle connects to a charging point.",
|
||||||
|
"editHint": "Add or edit vehicles in {0}.",
|
||||||
|
"keepAsIs": "Keep as is",
|
||||||
|
"learnMore": "Learn more.",
|
||||||
|
"limitSoc": "Default limit",
|
||||||
|
"menu": "Vehicles",
|
||||||
|
"minSoc": "Minimum charge",
|
||||||
|
"minSocDescription": "Fast charge to this level in solar mode.",
|
||||||
|
"mode": "Default mode",
|
||||||
|
"notConnected": "not connected",
|
||||||
|
"title": "Vehicle Settings"
|
||||||
|
},
|
||||||
"vehicleStatus": {
|
"vehicleStatus": {
|
||||||
"awaitingAuthorization": "Waiting for authorization.",
|
"awaitingAuthorization": "Waiting for authorization.",
|
||||||
"batteryBoost": "Battery boost active.",
|
"batteryBoost": "Battery boost active.",
|
||||||
|
|
|
||||||
12
i18n/es.json
12
i18n/es.json
|
|
@ -988,9 +988,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Activo",
|
"active": "Activo",
|
||||||
"addRepeatingPlan": "Añadir plan recurrente",
|
"addRepeatingPlan": "Añadir plan recurrente",
|
||||||
"arrivalTab": "Llegadas",
|
|
||||||
"day": "Día",
|
"day": "Día",
|
||||||
"departureTab": "Salidas",
|
|
||||||
"goal": "Objetivo de la carga",
|
"goal": "Objetivo de la carga",
|
||||||
"modalTitle": "Plan de carga",
|
"modalTitle": "Plan de carga",
|
||||||
"none": "ninguno",
|
"none": "ninguno",
|
||||||
|
|
@ -1014,8 +1012,6 @@
|
||||||
"strategySettings": "Configuración de la estrategia",
|
"strategySettings": "Configuración de la estrategia",
|
||||||
"time": "Tiempo",
|
"time": "Tiempo",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Carga mínima",
|
|
||||||
"titleTargetCharge": "Partida",
|
|
||||||
"unsavedChanges": "Hay cambios sin guardar. ¿Aplicar ahora?",
|
"unsavedChanges": "Hay cambios sin guardar. ¿Aplicar ahora?",
|
||||||
"update": "Aplicar",
|
"update": "Aplicar",
|
||||||
"weekdays": "Días"
|
"weekdays": "Días"
|
||||||
|
|
@ -1073,20 +1069,12 @@
|
||||||
"currents": "Corriente de carga",
|
"currents": "Corriente de carga",
|
||||||
"default": "defecto",
|
"default": "defecto",
|
||||||
"disclaimerHint": "Nota:",
|
"disclaimerHint": "Nota:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Límite de carga que se utiliza cuando este vehículo está conectado.",
|
|
||||||
"label": "Límite predeterminado"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Corriente de carga máxima"
|
"label": "Corriente de carga máxima"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Corriente de carga mínima"
|
"label": "Corriente de carga mínima"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "El vehículo se carga «rápidamente» hasta {0} en modo solar. A continuación, continúa con el excedente solar. Útil para garantizar una autonomía mínima incluso en días más oscuros.",
|
|
||||||
"label": "Carga de min. %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Estas opciones solo están disponibles para vehículos con un nivel de carga conocido.",
|
"onlyForSocBasedCharging": "Estas opciones solo están disponibles para vehículos con un nivel de carga conocido.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fases",
|
"label": "Fases",
|
||||||
|
|
|
||||||
12
i18n/fi.json
12
i18n/fi.json
|
|
@ -1192,9 +1192,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktiivinen",
|
"active": "Aktiivinen",
|
||||||
"addRepeatingPlan": "Lisää toistuva suunnitelma",
|
"addRepeatingPlan": "Lisää toistuva suunnitelma",
|
||||||
"arrivalTab": "Saapuminen",
|
|
||||||
"day": "Päivä",
|
"day": "Päivä",
|
||||||
"departureTab": "Lähtö",
|
|
||||||
"goal": "Lataus tavoite",
|
"goal": "Lataus tavoite",
|
||||||
"modalTitle": "Lataussuunnitelma",
|
"modalTitle": "Lataussuunnitelma",
|
||||||
"none": "ei mitään",
|
"none": "ei mitään",
|
||||||
|
|
@ -1218,8 +1216,6 @@
|
||||||
"strategySettings": "Strategiamääritykset",
|
"strategySettings": "Strategiamääritykset",
|
||||||
"time": "Aika",
|
"time": "Aika",
|
||||||
"title": "Suunnitelma",
|
"title": "Suunnitelma",
|
||||||
"titleMinSoc": "Minimi lataus",
|
|
||||||
"titleTargetCharge": "Lähtö",
|
|
||||||
"unsavedChanges": "Tallentamattomia muutoksia. Asetetaanko nyt?",
|
"unsavedChanges": "Tallentamattomia muutoksia. Asetetaanko nyt?",
|
||||||
"update": "Aseta",
|
"update": "Aseta",
|
||||||
"weekdays": "Päivät"
|
"weekdays": "Päivät"
|
||||||
|
|
@ -1317,20 +1313,12 @@
|
||||||
"currents": "Latausvirta",
|
"currents": "Latausvirta",
|
||||||
"default": "oletus",
|
"default": "oletus",
|
||||||
"disclaimerHint": "Huomautus:",
|
"disclaimerHint": "Huomautus:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Latausraja mitä käytetään kun ajoneuvo yhdistetty.",
|
|
||||||
"label": "Oletusraja"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Maksimivirta"
|
"label": "Maksimivirta"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Minimivirta"
|
"label": "Minimivirta"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Ajoneuvo ladataan välittömästi {0} asti huolimatta aurinkoenergian ylijäämästä, tämän jälkeen vain ylijäämäenergialla. Tämä on hyödyllinen takaamaan minimi toimintamatka myös pimeinä päivinä.",
|
|
||||||
"label": "Minimi lataustaso"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Nämä vaihtoehdot ovat käytettävissä vain ajoneuvoille, joiden lataustaso on tiedossa.",
|
"onlyForSocBasedCharging": "Nämä vaihtoehdot ovat käytettävissä vain ajoneuvoille, joiden lataustaso on tiedossa.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Vaihetila",
|
"label": "Vaihetila",
|
||||||
|
|
|
||||||
12
i18n/fr.json
12
i18n/fr.json
|
|
@ -1196,9 +1196,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Actif",
|
"active": "Actif",
|
||||||
"addRepeatingPlan": "Ajouter un plan récurrent",
|
"addRepeatingPlan": "Ajouter un plan récurrent",
|
||||||
"arrivalTab": "Arrivée",
|
|
||||||
"day": "Jour",
|
"day": "Jour",
|
||||||
"departureTab": "Départ",
|
|
||||||
"goal": "Objectif de charge",
|
"goal": "Objectif de charge",
|
||||||
"modalTitle": "Planification de la charge",
|
"modalTitle": "Planification de la charge",
|
||||||
"none": "aucune",
|
"none": "aucune",
|
||||||
|
|
@ -1222,8 +1220,6 @@
|
||||||
"strategySettings": "Paramètres de stratégie",
|
"strategySettings": "Paramètres de stratégie",
|
||||||
"time": "Heure",
|
"time": "Heure",
|
||||||
"title": "Planification",
|
"title": "Planification",
|
||||||
"titleMinSoc": "Charge min",
|
|
||||||
"titleTargetCharge": "Départ",
|
|
||||||
"unsavedChanges": "Il y a des modifications non sauvegardées. Appliquer ?",
|
"unsavedChanges": "Il y a des modifications non sauvegardées. Appliquer ?",
|
||||||
"update": "Appliquer",
|
"update": "Appliquer",
|
||||||
"weekdays": "Jours"
|
"weekdays": "Jours"
|
||||||
|
|
@ -1320,20 +1316,12 @@
|
||||||
"currents": "Courant de charge",
|
"currents": "Courant de charge",
|
||||||
"default": "défaut",
|
"default": "défaut",
|
||||||
"disclaimerHint": "Remarque :",
|
"disclaimerHint": "Remarque :",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Limite de charge à utiliser quand ce véhicule est connecté.",
|
|
||||||
"label": "Limite par défaut"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Courant max."
|
"label": "Courant max."
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Courant min."
|
"label": "Courant min."
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Le véhicule est chargé en mode „Rapide” à {0} en mode solaire, puis avec le surplus solaire. Utile pour s'assurer d'un minimum d'autonomie, même pour les jours plus sombres.",
|
|
||||||
"label": "Charge min. %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Ces options sont disponibles uniquement pour les véhicules avec un niveau de charge connu.",
|
"onlyForSocBasedCharging": "Ces options sont disponibles uniquement pour les véhicules avec un niveau de charge connu.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Phases",
|
"label": "Phases",
|
||||||
|
|
|
||||||
12
i18n/hr.json
12
i18n/hr.json
|
|
@ -860,9 +860,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktivno",
|
"active": "Aktivno",
|
||||||
"addRepeatingPlan": "Dodaj ponavljajući plan",
|
"addRepeatingPlan": "Dodaj ponavljajući plan",
|
||||||
"arrivalTab": "Dolazak",
|
|
||||||
"day": "Dan",
|
"day": "Dan",
|
||||||
"departureTab": "Odlazak",
|
|
||||||
"goal": "Cilj punjenja",
|
"goal": "Cilj punjenja",
|
||||||
"modalTitle": "Plan punjenja",
|
"modalTitle": "Plan punjenja",
|
||||||
"none": "nema, dodaj",
|
"none": "nema, dodaj",
|
||||||
|
|
@ -886,8 +884,6 @@
|
||||||
"strategySettings": "Postavke strategije",
|
"strategySettings": "Postavke strategije",
|
||||||
"time": "Vrijeme",
|
"time": "Vrijeme",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Min. punjenje",
|
|
||||||
"titleTargetCharge": "Odlazak",
|
|
||||||
"unsavedChanges": "Postoje promjene koje nisu spremljene. Spremiti odmah?",
|
"unsavedChanges": "Postoje promjene koje nisu spremljene. Spremiti odmah?",
|
||||||
"update": "Primijeni",
|
"update": "Primijeni",
|
||||||
"weekdays": "Dani"
|
"weekdays": "Dani"
|
||||||
|
|
@ -945,20 +941,12 @@
|
||||||
"currents": "Struja punjenja",
|
"currents": "Struja punjenja",
|
||||||
"default": "zadano",
|
"default": "zadano",
|
||||||
"disclaimerHint": "Napomena:",
|
"disclaimerHint": "Napomena:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Ograničenje punjenja koje se koristi kada je ovo vozilo spojeno.",
|
|
||||||
"label": "Zadano ograničenje"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Maksimalna struja punjenja"
|
"label": "Maksimalna struja punjenja"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Minimalna struja punjenja"
|
"label": "Minimalna struja punjenja"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Vozilo se puni „brzo” na {0} u solarnom modusu. Zatim se nastavlja puniti sa solarnim viškom. Korisno za osiguravanje minimalnog raspona čak i u danima s manje sunca.",
|
|
||||||
"label": "Min. % punjenja"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Navedene opcije dostupne samo za vozila s poznatom razinom napunjenosti baterije.",
|
"onlyForSocBasedCharging": "Navedene opcije dostupne samo za vozila s poznatom razinom napunjenosti baterije.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Faze",
|
"label": "Faze",
|
||||||
|
|
|
||||||
12
i18n/hu.json
12
i18n/hu.json
|
|
@ -870,9 +870,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktív",
|
"active": "Aktív",
|
||||||
"addRepeatingPlan": "Ismétlődő terv hozzáadása",
|
"addRepeatingPlan": "Ismétlődő terv hozzáadása",
|
||||||
"arrivalTab": "Érkezés",
|
|
||||||
"day": "Nap",
|
"day": "Nap",
|
||||||
"departureTab": "Indulás",
|
|
||||||
"goal": "Töltési cél",
|
"goal": "Töltési cél",
|
||||||
"modalTitle": "Töltési Tervezet",
|
"modalTitle": "Töltési Tervezet",
|
||||||
"none": "nincs",
|
"none": "nincs",
|
||||||
|
|
@ -896,8 +894,6 @@
|
||||||
"strategySettings": "Stratégiai beállítások",
|
"strategySettings": "Stratégiai beállítások",
|
||||||
"time": "Idő",
|
"time": "Idő",
|
||||||
"title": "Terv",
|
"title": "Terv",
|
||||||
"titleMinSoc": "Min töltés",
|
|
||||||
"titleTargetCharge": "Indulás",
|
|
||||||
"unsavedChanges": "Vannak nem mentett módosítások. Alkalmazza most?",
|
"unsavedChanges": "Vannak nem mentett módosítások. Alkalmazza most?",
|
||||||
"update": "Alkalmazás",
|
"update": "Alkalmazás",
|
||||||
"weekdays": "Napok"
|
"weekdays": "Napok"
|
||||||
|
|
@ -955,20 +951,12 @@
|
||||||
"currents": "Töltőáram",
|
"currents": "Töltőáram",
|
||||||
"default": "alapértelmezett",
|
"default": "alapértelmezett",
|
||||||
"disclaimerHint": "Megjegyzés:",
|
"disclaimerHint": "Megjegyzés:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Töltési korlát, amikor a jármű csatlakoztatva van.",
|
|
||||||
"label": "Alapértelmezett limit"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Max. Áram"
|
"label": "Max. Áram"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. Áram"
|
"label": "Min. Áram"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "A jármű gyorstöltve lesz {0}-ra szolár üzemmódban. Ezután folytatódik a töltés a napelemes többletenergiával. Hasznos egy minimum tartományt megadni a felhősebb napokra.",
|
|
||||||
"label": "Min. töltés %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Ezek a beállítások csak olyan járművekre elérhetőek, amiknek ismert a töltési szintje.",
|
"onlyForSocBasedCharging": "Ezek a beállítások csak olyan járművekre elérhetőek, amiknek ismert a töltési szintje.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fázis",
|
"label": "Fázis",
|
||||||
|
|
|
||||||
12
i18n/it.json
12
i18n/it.json
|
|
@ -1098,9 +1098,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Attivo",
|
"active": "Attivo",
|
||||||
"addRepeatingPlan": "Aggiungi piano ricorrente",
|
"addRepeatingPlan": "Aggiungi piano ricorrente",
|
||||||
"arrivalTab": "Arrivo",
|
|
||||||
"day": "Giorno",
|
"day": "Giorno",
|
||||||
"departureTab": "Partenza",
|
|
||||||
"goal": "Obiettivo di ricarica",
|
"goal": "Obiettivo di ricarica",
|
||||||
"modalTitle": "Piano di ricarica",
|
"modalTitle": "Piano di ricarica",
|
||||||
"none": "nessuno",
|
"none": "nessuno",
|
||||||
|
|
@ -1124,8 +1122,6 @@
|
||||||
"strategySettings": "Impostazioni strategia",
|
"strategySettings": "Impostazioni strategia",
|
||||||
"time": "Ora",
|
"time": "Ora",
|
||||||
"title": "Piano",
|
"title": "Piano",
|
||||||
"titleMinSoc": "Carica minima",
|
|
||||||
"titleTargetCharge": "Partenza",
|
|
||||||
"unsavedChanges": "Ci sono modifiche non salvate. Vuoi salvarle adesso?",
|
"unsavedChanges": "Ci sono modifiche non salvate. Vuoi salvarle adesso?",
|
||||||
"update": "Applica",
|
"update": "Applica",
|
||||||
"weekdays": "Giorni"
|
"weekdays": "Giorni"
|
||||||
|
|
@ -1191,20 +1187,12 @@
|
||||||
"currents": "Corrente di carica",
|
"currents": "Corrente di carica",
|
||||||
"default": "default",
|
"default": "default",
|
||||||
"disclaimerHint": "Nota:",
|
"disclaimerHint": "Nota:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Limite di carica applicato quando il veicolo è connesso.",
|
|
||||||
"label": "Limite di default"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Corrente massima"
|
"label": "Corrente massima"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Corrente min."
|
"label": "Corrente min."
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Per le emergenze. Il veicolo viene caricato 'velocemente' al {0} da tutto il solare disponibile, e poi continua con solo il surplus solare.",
|
|
||||||
"label": "Carica min. %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Questa opzione è solo per i veicoli dei quali si sa lo stato di carica.",
|
"onlyForSocBasedCharging": "Questa opzione è solo per i veicoli dei quali si sa lo stato di carica.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fasi",
|
"label": "Fasi",
|
||||||
|
|
|
||||||
12
i18n/ja.json
12
i18n/ja.json
|
|
@ -1121,9 +1121,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "アクティブ",
|
"active": "アクティブ",
|
||||||
"addRepeatingPlan": "繰り返しプランを追加",
|
"addRepeatingPlan": "繰り返しプランを追加",
|
||||||
"arrivalTab": "到着",
|
|
||||||
"day": "日",
|
"day": "日",
|
||||||
"departureTab": "出発",
|
|
||||||
"goal": "充電目標",
|
"goal": "充電目標",
|
||||||
"modalTitle": "充電プラン",
|
"modalTitle": "充電プラン",
|
||||||
"none": "なし",
|
"none": "なし",
|
||||||
|
|
@ -1147,8 +1145,6 @@
|
||||||
"strategySettings": "戦略設定",
|
"strategySettings": "戦略設定",
|
||||||
"time": "時間",
|
"time": "時間",
|
||||||
"title": "プラン",
|
"title": "プラン",
|
||||||
"titleMinSoc": "最小充電",
|
|
||||||
"titleTargetCharge": "出発",
|
|
||||||
"unsavedChanges": "保存されていない変更があります。今すぐ適用しますか?",
|
"unsavedChanges": "保存されていない変更があります。今すぐ適用しますか?",
|
||||||
"update": "適用",
|
"update": "適用",
|
||||||
"weekdays": "日"
|
"weekdays": "日"
|
||||||
|
|
@ -1243,20 +1239,12 @@
|
||||||
"currents": "充電電流",
|
"currents": "充電電流",
|
||||||
"default": "デフォルト",
|
"default": "デフォルト",
|
||||||
"disclaimerHint": "注:",
|
"disclaimerHint": "注:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "この車両が接続されたときに使用される充電制限。",
|
|
||||||
"label": "デフォルト制限"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "最大電流"
|
"label": "最大電流"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "最小電流"
|
"label": "最小電流"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "太陽光モード時、車両はまず „高速” で {0} まで充電されます。その後は太陽光の余剰電力で充電を継続します。日照の少ない日でも最低限の航続距離を確保するのに役立ちます。",
|
|
||||||
"label": "最小充電 %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "これらのオプションは、バッテリー残量が取得できている車両でのみ利用可能です。",
|
"onlyForSocBasedCharging": "これらのオプションは、バッテリー残量が取得できている車両でのみ利用可能です。",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "相数",
|
"label": "相数",
|
||||||
|
|
|
||||||
12
i18n/lb.json
12
i18n/lb.json
|
|
@ -1119,9 +1119,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"addRepeatingPlan": "Widderhuelte Planifikatioun derbäi fügen",
|
"addRepeatingPlan": "Widderhuelte Planifikatioun derbäi fügen",
|
||||||
"arrivalTab": "Arrivée",
|
|
||||||
"day": "Dag",
|
"day": "Dag",
|
||||||
"departureTab": "Depart",
|
|
||||||
"goal": "Luedzil",
|
"goal": "Luedzil",
|
||||||
"modalTitle": "Luedplanifikatioun",
|
"modalTitle": "Luedplanifikatioun",
|
||||||
"none": "keng",
|
"none": "keng",
|
||||||
|
|
@ -1145,8 +1143,6 @@
|
||||||
"strategySettings": "Strategie-Astellungen",
|
"strategySettings": "Strategie-Astellungen",
|
||||||
"time": "Zäit",
|
"time": "Zäit",
|
||||||
"title": "Planifikatioun",
|
"title": "Planifikatioun",
|
||||||
"titleMinSoc": "Min. Oplueden",
|
|
||||||
"titleTargetCharge": "Depart",
|
|
||||||
"unsavedChanges": "Net gespäichert Ännerungen leie vir. Elo uwennen?",
|
"unsavedChanges": "Net gespäichert Ännerungen leie vir. Elo uwennen?",
|
||||||
"update": "Uwennen",
|
"update": "Uwennen",
|
||||||
"weekdays": "Deeg"
|
"weekdays": "Deeg"
|
||||||
|
|
@ -1241,20 +1237,12 @@
|
||||||
"currents": "Luedstroum",
|
"currents": "Luedstroum",
|
||||||
"default": "Standard",
|
"default": "Standard",
|
||||||
"disclaimerHint": "Notiz:",
|
"disclaimerHint": "Notiz:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Luedzil dat benotzt gëtt, wann dëst Gefier verbonnen ass.",
|
|
||||||
"label": "Standard Luedzil"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Max. Stroum"
|
"label": "Max. Stroum"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. Stroum"
|
"label": "Min. Stroum"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "D'Gefier gëtt \"séier\" op {0} am Solarmodus opgelueden. Da geet et weider mat Solariwwerschëss. Dëst ass nëtzlech fir eng Minimum-Reechwäit och wärend méi däischter Deeg ze garantéieren.",
|
|
||||||
"label": "Min. oplueden %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Dës Optioune sinn nëmme fir Gefierer mat bekannte Luedstatioune verfügbar.",
|
"onlyForSocBasedCharging": "Dës Optioune sinn nëmme fir Gefierer mat bekannte Luedstatioune verfügbar.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Phasen",
|
"label": "Phasen",
|
||||||
|
|
|
||||||
12
i18n/lt.json
12
i18n/lt.json
|
|
@ -1198,9 +1198,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktyvus",
|
"active": "Aktyvus",
|
||||||
"addRepeatingPlan": "Pridėti pasikartojantį įkrovimo planą",
|
"addRepeatingPlan": "Pridėti pasikartojantį įkrovimo planą",
|
||||||
"arrivalTab": "Atvykimas",
|
|
||||||
"day": "Diena",
|
"day": "Diena",
|
||||||
"departureTab": "Išvykimas",
|
|
||||||
"goal": "Įkrovimo tikslas",
|
"goal": "Įkrovimo tikslas",
|
||||||
"modalTitle": "Įkrovimo planas",
|
"modalTitle": "Įkrovimo planas",
|
||||||
"none": "nėra",
|
"none": "nėra",
|
||||||
|
|
@ -1224,8 +1222,6 @@
|
||||||
"strategySettings": "Strategijos pasirinkimai",
|
"strategySettings": "Strategijos pasirinkimai",
|
||||||
"time": "Laikas",
|
"time": "Laikas",
|
||||||
"title": "Planas",
|
"title": "Planas",
|
||||||
"titleMinSoc": "Minimali įkrova",
|
|
||||||
"titleTargetCharge": "Išvykimas",
|
|
||||||
"unsavedChanges": "Yra neišsaugotų pakeitimų. Išsaugoti dabar?",
|
"unsavedChanges": "Yra neišsaugotų pakeitimų. Išsaugoti dabar?",
|
||||||
"update": "Patvirtinti",
|
"update": "Patvirtinti",
|
||||||
"weekdays": "Dienos"
|
"weekdays": "Dienos"
|
||||||
|
|
@ -1324,20 +1320,12 @@
|
||||||
"currents": "Įkrovimo Srovė",
|
"currents": "Įkrovimo Srovė",
|
||||||
"default": "standartiškai",
|
"default": "standartiškai",
|
||||||
"disclaimerHint": "Pastaba:",
|
"disclaimerHint": "Pastaba:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Įkrovimo limitas, naudojamas, prijungus šį automobilį.",
|
|
||||||
"label": "Standartinis limitas"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Max. Srovė"
|
"label": "Max. Srovė"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. Srovė"
|
"label": "Min. Srovė"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Automobilis įkraunamas „Greitai” iki {0} nustatyme „Saulė”, toliau įkraunamas tik saulės energijos pertekliumi. Padeda užtikrinti minimalią įkrovą dienomis, kai mažai saulės.",
|
|
||||||
"label": "Minimali įkrova %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Šie pasirinkimai galimi tik automobiliams su žinomu įkrovos lygiu.",
|
"onlyForSocBasedCharging": "Šie pasirinkimai galimi tik automobiliams su žinomu įkrovos lygiu.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fazės",
|
"label": "Fazės",
|
||||||
|
|
|
||||||
12
i18n/lv.json
12
i18n/lv.json
|
|
@ -1171,9 +1171,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktīvs",
|
"active": "Aktīvs",
|
||||||
"addRepeatingPlan": "Pievienot atkārtojošu plānu",
|
"addRepeatingPlan": "Pievienot atkārtojošu plānu",
|
||||||
"arrivalTab": "Ierašanās",
|
|
||||||
"day": "Diena",
|
"day": "Diena",
|
||||||
"departureTab": "Izbraukšana",
|
|
||||||
"goal": "Uzlādes mērķis",
|
"goal": "Uzlādes mērķis",
|
||||||
"modalTitle": "Uzlādes plāns",
|
"modalTitle": "Uzlādes plāns",
|
||||||
"none": "nav",
|
"none": "nav",
|
||||||
|
|
@ -1197,8 +1195,6 @@
|
||||||
"strategySettings": "Stratēģijas iestatījumi",
|
"strategySettings": "Stratēģijas iestatījumi",
|
||||||
"time": "Laiks",
|
"time": "Laiks",
|
||||||
"title": "Plāns",
|
"title": "Plāns",
|
||||||
"titleMinSoc": "Min. uzlāde",
|
|
||||||
"titleTargetCharge": "Izbraukšana",
|
|
||||||
"unsavedChanges": "Ir nesaglabātas izmaiņas. Piemērot tagad?",
|
"unsavedChanges": "Ir nesaglabātas izmaiņas. Piemērot tagad?",
|
||||||
"update": "Piemērot",
|
"update": "Piemērot",
|
||||||
"weekdays": "Dienas"
|
"weekdays": "Dienas"
|
||||||
|
|
@ -1297,20 +1293,12 @@
|
||||||
"currents": "Uzlādes strāva",
|
"currents": "Uzlādes strāva",
|
||||||
"default": "noklusējuma",
|
"default": "noklusējuma",
|
||||||
"disclaimerHint": "Piezīme:",
|
"disclaimerHint": "Piezīme:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Uzlādes ierobežojums, kas tiek izmantots, kad šis transportlīdzeklis ir pievienots.",
|
|
||||||
"label": "Noklusējuma ierobežojums"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Maks. strāva"
|
"label": "Maks. strāva"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. strāva"
|
"label": "Min. strāva"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Transportlīdzeklis tiek „ātri” uzlādēts līdz {0} saules režīmā. Pēc tam turpina ar saules enerģijas pārpalikumu. Noderīgi, lai nodrošinātu minimālu nobraukumu pat tumšākām dienām.",
|
|
||||||
"label": "Min. uzlāde %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Šīs iespējas ir pieejamas tikai transportlīdzekļiem ar zināmu uzlādes līmeni.",
|
"onlyForSocBasedCharging": "Šīs iespējas ir pieejamas tikai transportlīdzekļiem ar zināmu uzlādes līmeni.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fāzes",
|
"label": "Fāzes",
|
||||||
|
|
|
||||||
12
i18n/nl.json
12
i18n/nl.json
|
|
@ -1177,9 +1177,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Actief",
|
"active": "Actief",
|
||||||
"addRepeatingPlan": "Herhalend schema toevoegen",
|
"addRepeatingPlan": "Herhalend schema toevoegen",
|
||||||
"arrivalTab": "Aankomst",
|
|
||||||
"day": "Dag",
|
"day": "Dag",
|
||||||
"departureTab": "Vertrek",
|
|
||||||
"goal": "Laaddoel",
|
"goal": "Laaddoel",
|
||||||
"modalTitle": "Laad Plan",
|
"modalTitle": "Laad Plan",
|
||||||
"none": "geen",
|
"none": "geen",
|
||||||
|
|
@ -1203,8 +1201,6 @@
|
||||||
"strategySettings": "Strategie-instellingen",
|
"strategySettings": "Strategie-instellingen",
|
||||||
"time": "Tijd",
|
"time": "Tijd",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Min lading",
|
|
||||||
"titleTargetCharge": "Vertrek",
|
|
||||||
"unsavedChanges": "Wijzigingen nog niet opgeslagen. Nu toepassen?",
|
"unsavedChanges": "Wijzigingen nog niet opgeslagen. Nu toepassen?",
|
||||||
"update": "Toepassen",
|
"update": "Toepassen",
|
||||||
"weekdays": "Dagen"
|
"weekdays": "Dagen"
|
||||||
|
|
@ -1302,20 +1298,12 @@
|
||||||
"currents": "Laadstroom",
|
"currents": "Laadstroom",
|
||||||
"default": "standaard",
|
"default": "standaard",
|
||||||
"disclaimerHint": "Let op:",
|
"disclaimerHint": "Let op:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Standaard laadlimiet wanneer dit voertuig aangesloten wordt.",
|
|
||||||
"label": "Standaard limiet"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Max. Stroomsterkte"
|
"label": "Max. Stroomsterkte"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. Stroomsterkte"
|
"label": "Min. Stroomsterkte"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Het voertuig wordt „snel” opgeladen tot {0} in zonne-modus. Het laden gaat daarna verder met zonneoverschot. Nuttig om een bepaald rijbereik te garanderen, ook gedurende periodes met weinig of geen zonnestroom.",
|
|
||||||
"label": "Min. batterij %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Deze instellingen zijn alleen beschikbaar bij voertuigen waar het batterijpercentage bekend is.",
|
"onlyForSocBasedCharging": "Deze instellingen zijn alleen beschikbaar bij voertuigen waar het batterijpercentage bekend is.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fasen",
|
"label": "Fasen",
|
||||||
|
|
|
||||||
12
i18n/no.json
12
i18n/no.json
|
|
@ -900,9 +900,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"addRepeatingPlan": "Legg til gjentakende plan",
|
"addRepeatingPlan": "Legg til gjentakende plan",
|
||||||
"arrivalTab": "Ankomst",
|
|
||||||
"day": "Dag",
|
"day": "Dag",
|
||||||
"departureTab": "Avgang",
|
|
||||||
"goal": "Ladingsmål",
|
"goal": "Ladingsmål",
|
||||||
"modalTitle": "Ladeplan",
|
"modalTitle": "Ladeplan",
|
||||||
"none": "ingen",
|
"none": "ingen",
|
||||||
|
|
@ -926,8 +924,6 @@
|
||||||
"strategySettings": "Strategiinnstillinger",
|
"strategySettings": "Strategiinnstillinger",
|
||||||
"time": "Tid",
|
"time": "Tid",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Min.-lading",
|
|
||||||
"titleTargetCharge": "Avgang",
|
|
||||||
"unsavedChanges": "Det er ubehandlede endringer. Vil du bruke dem nå?",
|
"unsavedChanges": "Det er ubehandlede endringer. Vil du bruke dem nå?",
|
||||||
"update": "Søk",
|
"update": "Søk",
|
||||||
"weekdays": "Dager"
|
"weekdays": "Dager"
|
||||||
|
|
@ -985,20 +981,12 @@
|
||||||
"currents": "Ladestrøm",
|
"currents": "Ladestrøm",
|
||||||
"default": "forvalg",
|
"default": "forvalg",
|
||||||
"disclaimerHint": "Merknad:",
|
"disclaimerHint": "Merknad:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Ladegrense som brukes når dette kjøretøyet er tilkoblet.",
|
|
||||||
"label": "Standardgrense"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Maks. ladestrøm"
|
"label": "Maks. ladestrøm"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. ladestrøm"
|
"label": "Min. ladestrøm"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "For nødstilfeller. Kjøretøyet blir „raskt” ladet til {0} fra all tilgjengelig solenergi, og fortsetter deretter med bare solenergioverskuddet.",
|
|
||||||
"label": "Min. lading%"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Disse alternativene er kun tilgjengelige for kjøretøy med kjent ladenivå.",
|
"onlyForSocBasedCharging": "Disse alternativene er kun tilgjengelige for kjøretøy med kjent ladenivå.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Faser",
|
"label": "Faser",
|
||||||
|
|
|
||||||
12
i18n/pl.json
12
i18n/pl.json
|
|
@ -1041,9 +1041,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktywny",
|
"active": "Aktywny",
|
||||||
"addRepeatingPlan": "Dodaj plan powtarzalny",
|
"addRepeatingPlan": "Dodaj plan powtarzalny",
|
||||||
"arrivalTab": "Przyjazd",
|
|
||||||
"day": "Dzień",
|
"day": "Dzień",
|
||||||
"departureTab": "Wyjazd",
|
|
||||||
"goal": "Cel ładowania",
|
"goal": "Cel ładowania",
|
||||||
"modalTitle": "Plan ładowania",
|
"modalTitle": "Plan ładowania",
|
||||||
"none": "brak",
|
"none": "brak",
|
||||||
|
|
@ -1067,8 +1065,6 @@
|
||||||
"strategySettings": "Ustawienia strategii",
|
"strategySettings": "Ustawienia strategii",
|
||||||
"time": "Czas",
|
"time": "Czas",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Minimalne ładowanie",
|
|
||||||
"titleTargetCharge": "Wyjazd",
|
|
||||||
"unsavedChanges": "Są niezapisane zmiany. Zastosować teraz?",
|
"unsavedChanges": "Są niezapisane zmiany. Zastosować teraz?",
|
||||||
"update": "Zastosuj",
|
"update": "Zastosuj",
|
||||||
"weekdays": "Dni"
|
"weekdays": "Dni"
|
||||||
|
|
@ -1160,20 +1156,12 @@
|
||||||
"currents": "Prąd ładowania",
|
"currents": "Prąd ładowania",
|
||||||
"default": "domyślny",
|
"default": "domyślny",
|
||||||
"disclaimerHint": "Uwaga:",
|
"disclaimerHint": "Uwaga:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Limit ładowania stosowany, gdy ten pojazd jest podłączony.",
|
|
||||||
"label": "Domyślny limit"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Maks. prąd"
|
"label": "Maks. prąd"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. Prąd"
|
"label": "Min. Prąd"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Pojazd będzie „szybko” naładowany do {0} w trybie „Słońce”. Następnie kontynuuje tylko z nadwyżką fotowoltaiczną. Przydatne, aby zapewnić minimalny zasięg nawet w pochmurne dni.",
|
|
||||||
"label": "Minimalne naładowanie %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Opcje te są dostępne tylko dla pojazdów ze znanym poziomem naładowania.",
|
"onlyForSocBasedCharging": "Opcje te są dostępne tylko dla pojazdów ze znanym poziomem naładowania.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fazy",
|
"label": "Fazy",
|
||||||
|
|
|
||||||
12
i18n/pt.json
12
i18n/pt.json
|
|
@ -1110,9 +1110,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Ativo",
|
"active": "Ativo",
|
||||||
"addRepeatingPlan": "Adicionar planos iguais",
|
"addRepeatingPlan": "Adicionar planos iguais",
|
||||||
"arrivalTab": "Fim",
|
|
||||||
"day": "Dia",
|
"day": "Dia",
|
||||||
"departureTab": "Inicio",
|
|
||||||
"goal": "Carga pretendida",
|
"goal": "Carga pretendida",
|
||||||
"modalTitle": "Plano de carga",
|
"modalTitle": "Plano de carga",
|
||||||
"none": "nenhum",
|
"none": "nenhum",
|
||||||
|
|
@ -1136,8 +1134,6 @@
|
||||||
"strategySettings": "Definições da estratégia",
|
"strategySettings": "Definições da estratégia",
|
||||||
"time": "Hora",
|
"time": "Hora",
|
||||||
"title": "Plano",
|
"title": "Plano",
|
||||||
"titleMinSoc": "Carga mínima",
|
|
||||||
"titleTargetCharge": "Inicio",
|
|
||||||
"unsavedChanges": "Há alterações não salvas. Aplicar agora?",
|
"unsavedChanges": "Há alterações não salvas. Aplicar agora?",
|
||||||
"update": "Aplicar",
|
"update": "Aplicar",
|
||||||
"weekdays": "Dias"
|
"weekdays": "Dias"
|
||||||
|
|
@ -1203,20 +1199,12 @@
|
||||||
"currents": "Corrente de carga",
|
"currents": "Corrente de carga",
|
||||||
"default": "predefinido",
|
"default": "predefinido",
|
||||||
"disclaimerHint": "Aviso:",
|
"disclaimerHint": "Aviso:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "limite de partilha que é usado quando este veículo está conectado.",
|
|
||||||
"label": "Limite padrão"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Corrente de carga máxima"
|
"label": "Corrente de carga máxima"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Corrente de carga mínima"
|
"label": "Corrente de carga mínima"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "O veículo é carregado “rápido” até {0} no modo solar. A seguir, continua com excedente solar. Útil para garantir um alcance mínimo mesmo em dias com pouco sol.",
|
|
||||||
"label": "Min. de carga %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Estas opções só estão disponíveis para veículos com nível de carregamento conhecido.",
|
"onlyForSocBasedCharging": "Estas opções só estão disponíveis para veículos com nível de carregamento conhecido.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fases elétricas",
|
"label": "Fases elétricas",
|
||||||
|
|
|
||||||
12
i18n/ro.json
12
i18n/ro.json
|
|
@ -1017,9 +1017,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Activ",
|
"active": "Activ",
|
||||||
"addRepeatingPlan": "Adăugați plan repetitiv",
|
"addRepeatingPlan": "Adăugați plan repetitiv",
|
||||||
"arrivalTab": "Ajungere",
|
|
||||||
"day": "Zi",
|
"day": "Zi",
|
||||||
"departureTab": "Plecare",
|
|
||||||
"goal": "Scopul incarcarii",
|
"goal": "Scopul incarcarii",
|
||||||
"modalTitle": "Plan de incarcare",
|
"modalTitle": "Plan de incarcare",
|
||||||
"none": "nimic",
|
"none": "nimic",
|
||||||
|
|
@ -1043,8 +1041,6 @@
|
||||||
"strategySettings": "Setări strategie",
|
"strategySettings": "Setări strategie",
|
||||||
"time": "Timp",
|
"time": "Timp",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Incarcare minima",
|
|
||||||
"titleTargetCharge": "Plecare",
|
|
||||||
"unsavedChanges": "Există modificări nesalvate. Doriți să le aplicați acum?",
|
"unsavedChanges": "Există modificări nesalvate. Doriți să le aplicați acum?",
|
||||||
"update": "Aplica",
|
"update": "Aplica",
|
||||||
"weekdays": "Zile"
|
"weekdays": "Zile"
|
||||||
|
|
@ -1109,20 +1105,12 @@
|
||||||
"currents": "Curent încărcare",
|
"currents": "Curent încărcare",
|
||||||
"default": "default",
|
"default": "default",
|
||||||
"disclaimerHint": "Nota:",
|
"disclaimerHint": "Nota:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Limita de incarcare care e folosita cand e conectat a aceasta masina.",
|
|
||||||
"label": "Limita default"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Amperaj maxim"
|
"label": "Amperaj maxim"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Amperaj minim"
|
"label": "Amperaj minim"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Vehiculul primește încărcare rapida {0} din toata energia solara disponibilă, apoi continua încărcarea cu surplusul solar.",
|
|
||||||
"label": "Min. încărcare %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Aceste optiuni sunt active doar pentru masini carora le cunoaste gradul de incarcare.",
|
"onlyForSocBasedCharging": "Aceste optiuni sunt active doar pentru masini carora le cunoaste gradul de incarcare.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Faze",
|
"label": "Faze",
|
||||||
|
|
|
||||||
12
i18n/ru.json
12
i18n/ru.json
|
|
@ -850,9 +850,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Активный",
|
"active": "Активный",
|
||||||
"addRepeatingPlan": "Добавить повторяющийся план",
|
"addRepeatingPlan": "Добавить повторяющийся план",
|
||||||
"arrivalTab": "Прибытие",
|
|
||||||
"day": "День",
|
"day": "День",
|
||||||
"departureTab": "Отправление",
|
|
||||||
"goal": "Цель зарядки",
|
"goal": "Цель зарядки",
|
||||||
"modalTitle": "План тарификации",
|
"modalTitle": "План тарификации",
|
||||||
"none": "нет",
|
"none": "нет",
|
||||||
|
|
@ -876,8 +874,6 @@
|
||||||
"strategySettings": "Настройки стратегии",
|
"strategySettings": "Настройки стратегии",
|
||||||
"time": "Время",
|
"time": "Время",
|
||||||
"title": "План",
|
"title": "План",
|
||||||
"titleMinSoc": "Минимальная плата",
|
|
||||||
"titleTargetCharge": "Отправление",
|
|
||||||
"unsavedChanges": "Есть несохраненные изменения. Применить сейчас?",
|
"unsavedChanges": "Есть несохраненные изменения. Применить сейчас?",
|
||||||
"update": "Применить",
|
"update": "Применить",
|
||||||
"weekdays": "Дни"
|
"weekdays": "Дни"
|
||||||
|
|
@ -935,20 +931,12 @@
|
||||||
"currents": "Ток зарядки",
|
"currents": "Ток зарядки",
|
||||||
"default": "по умолчанию",
|
"default": "по умолчанию",
|
||||||
"disclaimerHint": "Заметка:",
|
"disclaimerHint": "Заметка:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Предел зарядки, который используется при подключении этого транспортного средства.",
|
|
||||||
"label": "Предельное значение по умолчанию"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Макс. ток"
|
"label": "Макс. ток"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Мин. ток"
|
"label": "Мин. ток"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Автомобиль «быстро» заряжается до {0} в солнечном режиме. Затем продолжает работу за счет избытка солнечной энергии. Полезно для обеспечения минимального запаса хода даже в пасмурные дни.",
|
|
||||||
"label": "Мин. заряд %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Эти опции доступны только для автомобилей с известным уровнем заряда.",
|
"onlyForSocBasedCharging": "Эти опции доступны только для автомобилей с известным уровнем заряда.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Фазы",
|
"label": "Фазы",
|
||||||
|
|
|
||||||
12
i18n/sl.json
12
i18n/sl.json
|
|
@ -876,9 +876,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktivno",
|
"active": "Aktivno",
|
||||||
"addRepeatingPlan": "Dodaj ponavljajoči načrt",
|
"addRepeatingPlan": "Dodaj ponavljajoči načrt",
|
||||||
"arrivalTab": "Prihod",
|
|
||||||
"day": "Dan",
|
"day": "Dan",
|
||||||
"departureTab": "Odhod",
|
|
||||||
"goal": "Cilj polnjenja",
|
"goal": "Cilj polnjenja",
|
||||||
"modalTitle": "Načrt polnjenja",
|
"modalTitle": "Načrt polnjenja",
|
||||||
"none": "brez",
|
"none": "brez",
|
||||||
|
|
@ -907,8 +905,6 @@
|
||||||
"strategySettings": "Nastavitve strategije",
|
"strategySettings": "Nastavitve strategije",
|
||||||
"time": "Čas",
|
"time": "Čas",
|
||||||
"title": "Načrt",
|
"title": "Načrt",
|
||||||
"titleMinSoc": "Min. polnjenje",
|
|
||||||
"titleTargetCharge": "Odhod",
|
|
||||||
"unsavedChanges": "Obstajajo neshranjene spremembe. Želite uporabiti zdaj?",
|
"unsavedChanges": "Obstajajo neshranjene spremembe. Želite uporabiti zdaj?",
|
||||||
"update": "Uporabi",
|
"update": "Uporabi",
|
||||||
"weekdays": "Dnevi"
|
"weekdays": "Dnevi"
|
||||||
|
|
@ -966,20 +962,12 @@
|
||||||
"currents": "Polnilni tok",
|
"currents": "Polnilni tok",
|
||||||
"default": "privzeto",
|
"default": "privzeto",
|
||||||
"disclaimerHint": "Opomba:",
|
"disclaimerHint": "Opomba:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Omejitev polnjenja, ki se uporablja, ko je to vozilo povezano.",
|
|
||||||
"label": "Privzeta omejitev"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Maks. tok"
|
"label": "Maks. tok"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. tok"
|
"label": "Min. tok"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Za nujne primere. Vozilo se »hitro« napolni na {0} od vse razpoložljive solarne energije, nato pa nadaljuje samo s solarnim presežkom.",
|
|
||||||
"label": "Min. polnjenje %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Te možnosti so na voljo samo za vozila z znano stopnjo napolnjenosti.",
|
"onlyForSocBasedCharging": "Te možnosti so na voljo samo za vozila z znano stopnjo napolnjenosti.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Faze",
|
"label": "Faze",
|
||||||
|
|
|
||||||
12
i18n/sv.json
12
i18n/sv.json
|
|
@ -1169,9 +1169,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"addRepeatingPlan": "Lägg till en återkommande laddplan",
|
"addRepeatingPlan": "Lägg till en återkommande laddplan",
|
||||||
"arrivalTab": "Ankomst",
|
|
||||||
"day": "Dag",
|
"day": "Dag",
|
||||||
"departureTab": "Avfärd",
|
|
||||||
"goal": "Laddmål",
|
"goal": "Laddmål",
|
||||||
"modalTitle": "Laddplan",
|
"modalTitle": "Laddplan",
|
||||||
"none": "ingen",
|
"none": "ingen",
|
||||||
|
|
@ -1195,8 +1193,6 @@
|
||||||
"strategySettings": "Strategiinställningar",
|
"strategySettings": "Strategiinställningar",
|
||||||
"time": "Tid",
|
"time": "Tid",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Min. laddning",
|
|
||||||
"titleTargetCharge": "Avfärd",
|
|
||||||
"unsavedChanges": "Det finns ej sparade ändringar. Spara nu?",
|
"unsavedChanges": "Det finns ej sparade ändringar. Spara nu?",
|
||||||
"update": "Verkställ",
|
"update": "Verkställ",
|
||||||
"weekdays": "Dagar"
|
"weekdays": "Dagar"
|
||||||
|
|
@ -1295,20 +1291,12 @@
|
||||||
"currents": "Laddström",
|
"currents": "Laddström",
|
||||||
"default": "förvald",
|
"default": "förvald",
|
||||||
"disclaimerHint": "Anmärkning:",
|
"disclaimerHint": "Anmärkning:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Laddbegränsning när detta fordon är anslutet.",
|
|
||||||
"label": "Förvald laddgräns"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Max. ström"
|
"label": "Max. ström"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Min. ström"
|
"label": "Min. ström"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Fordonet laddas i sol-läge „snabbt” till {0} och sedan med endast solel. Användbart för att alltid ha en minsta räckvidd tillgänglig .",
|
|
||||||
"label": "Min. laddning %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Dessa inställningar är endast tillgängliga för fordon med känd laddnivå.",
|
"onlyForSocBasedCharging": "Dessa inställningar är endast tillgängliga för fordon med känd laddnivå.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Faser",
|
"label": "Faser",
|
||||||
|
|
|
||||||
12
i18n/ta.json
12
i18n/ta.json
|
|
@ -935,9 +935,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "செயலில்",
|
"active": "செயலில்",
|
||||||
"addRepeatingPlan": "மறுநிகழ்வு திட்டத்தைச் சேர்",
|
"addRepeatingPlan": "மறுநிகழ்வு திட்டத்தைச் சேர்",
|
||||||
"arrivalTab": "வருகை",
|
|
||||||
"day": "நாள்",
|
"day": "நாள்",
|
||||||
"departureTab": "புறப்படுதல்",
|
|
||||||
"goal": "மின்சேர்வி இலக்கு",
|
"goal": "மின்சேர்வி இலக்கு",
|
||||||
"modalTitle": "மின்சேர்வி திட்டம்",
|
"modalTitle": "மின்சேர்வி திட்டம்",
|
||||||
"none": "எதுவுமில்லை",
|
"none": "எதுவுமில்லை",
|
||||||
|
|
@ -961,8 +959,6 @@
|
||||||
"strategySettings": "மூலோபாய அமைப்புகள்",
|
"strategySettings": "மூலோபாய அமைப்புகள்",
|
||||||
"time": "நேரம்",
|
"time": "நேரம்",
|
||||||
"title": "திட்டம்",
|
"title": "திட்டம்",
|
||||||
"titleMinSoc": "\"குறை. மின்னூட்டு\"",
|
|
||||||
"titleTargetCharge": "புறப்படுதல்",
|
|
||||||
"unsavedChanges": "There அரே unsaved changes. இடு now?",
|
"unsavedChanges": "There அரே unsaved changes. இடு now?",
|
||||||
"update": "இடு",
|
"update": "இடு",
|
||||||
"weekdays": "நாட்கள்"
|
"weekdays": "நாட்கள்"
|
||||||
|
|
@ -1027,20 +1023,12 @@
|
||||||
"currents": "மின்சேர்வி மின்னோட்டம்",
|
"currents": "மின்சேர்வி மின்னோட்டம்",
|
||||||
"default": "இயல்புநிலை",
|
"default": "இயல்புநிலை",
|
||||||
"disclaimerHint": "குறிப்பு:",
|
"disclaimerHint": "குறிப்பு:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "இந்த வாகனம் இணைக்கப்படும்போது பயன்படுத்தப்படும் மின்சேர்வி வரம்பு.",
|
|
||||||
"label": "இயல்புநிலை வரம்பு"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "அதிக. மின்னோட்டம்"
|
"label": "அதிக. மின்னோட்டம்"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "குறை. மின்னோட்டம்"
|
"label": "குறை. மின்னோட்டம்"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "The vehicle gets „fast” charged பெறுநர் {0} in solar mode. Then continues with solar surplus. Useful பெறுநர் ensure a சிறுமம் வீச்சு இரட்டை க்கு darker days.",
|
|
||||||
"label": "Min. மின்னூட்டு %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "These விருப்பங்கள் அரே only available க்கு vehicles with known charging level.",
|
"onlyForSocBasedCharging": "These விருப்பங்கள் அரே only available க்கு vehicles with known charging level.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "கட்டங்கள்",
|
"label": "கட்டங்கள்",
|
||||||
|
|
|
||||||
12
i18n/tr.json
12
i18n/tr.json
|
|
@ -1143,9 +1143,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Aktif",
|
"active": "Aktif",
|
||||||
"addRepeatingPlan": "“Tekrar eden plan ekle”",
|
"addRepeatingPlan": "“Tekrar eden plan ekle”",
|
||||||
"arrivalTab": "Varış",
|
|
||||||
"day": "Gün",
|
"day": "Gün",
|
||||||
"departureTab": "Ayrılış",
|
|
||||||
"goal": "Doldurma hedefi",
|
"goal": "Doldurma hedefi",
|
||||||
"modalTitle": "Doldurma Planı",
|
"modalTitle": "Doldurma Planı",
|
||||||
"none": "yok",
|
"none": "yok",
|
||||||
|
|
@ -1169,8 +1167,6 @@
|
||||||
"strategySettings": "Strateji ayarları",
|
"strategySettings": "Strateji ayarları",
|
||||||
"time": "Zaman",
|
"time": "Zaman",
|
||||||
"title": "Plan",
|
"title": "Plan",
|
||||||
"titleMinSoc": "Asgari doldurma",
|
|
||||||
"titleTargetCharge": "Ayrılış",
|
|
||||||
"unsavedChanges": "Kaydedilmemiş değişiklikler var. Şimdi uygulansın mı?",
|
"unsavedChanges": "Kaydedilmemiş değişiklikler var. Şimdi uygulansın mı?",
|
||||||
"update": "Uygula",
|
"update": "Uygula",
|
||||||
"weekdays": "Günler"
|
"weekdays": "Günler"
|
||||||
|
|
@ -1265,20 +1261,12 @@
|
||||||
"currents": "Doldurma Akımı",
|
"currents": "Doldurma Akımı",
|
||||||
"default": "varsayılan",
|
"default": "varsayılan",
|
||||||
"disclaimerHint": "Not:",
|
"disclaimerHint": "Not:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Araç bağlandığında kullanılan dolum sınırı.",
|
|
||||||
"label": "Varsayılan dolum sınır"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Azami Akım"
|
"label": "Azami Akım"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Asgari Akım"
|
"label": "Asgari Akım"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Araç, güneş enerjisi modunda {0} seviyesine hızlı doldurulur. Ardından güneş enerjisi fazlalığıyla devam eder. Karanlık havalarda dahi asgari bir menzil sağlamak için kullanışlıdır.",
|
|
||||||
"label": "Asgari dolum oranı"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Bu seçenekler, sadece doluluk seviyesi bilinen araçlar için açık.",
|
"onlyForSocBasedCharging": "Bu seçenekler, sadece doluluk seviyesi bilinen araçlar için açık.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Fazlar",
|
"label": "Fazlar",
|
||||||
|
|
|
||||||
12
i18n/uk.json
12
i18n/uk.json
|
|
@ -863,9 +863,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "Активний",
|
"active": "Активний",
|
||||||
"addRepeatingPlan": "Додати повторюваний план",
|
"addRepeatingPlan": "Додати повторюваний план",
|
||||||
"arrivalTab": "Прибуття",
|
|
||||||
"day": "День",
|
"day": "День",
|
||||||
"departureTab": "Від'їзд",
|
|
||||||
"goal": "Зарядка гол",
|
"goal": "Зарядка гол",
|
||||||
"modalTitle": "Тарифний план",
|
"modalTitle": "Тарифний план",
|
||||||
"none": "немає",
|
"none": "немає",
|
||||||
|
|
@ -889,8 +887,6 @@
|
||||||
"strategySettings": "Налаштування стратегії",
|
"strategySettings": "Налаштування стратегії",
|
||||||
"time": "Час",
|
"time": "Час",
|
||||||
"title": "План",
|
"title": "План",
|
||||||
"titleMinSoc": "Мінімальна плата",
|
|
||||||
"titleTargetCharge": "Від'їзд",
|
|
||||||
"unsavedChanges": "Є незбережені зміни. Застосувати зараз?",
|
"unsavedChanges": "Є незбережені зміни. Застосувати зараз?",
|
||||||
"update": "Застосувати",
|
"update": "Застосувати",
|
||||||
"weekdays": "Днів"
|
"weekdays": "Днів"
|
||||||
|
|
@ -948,20 +944,12 @@
|
||||||
"currents": "Струм Зарядки",
|
"currents": "Струм Зарядки",
|
||||||
"default": "за замовчуванням",
|
"default": "за замовчуванням",
|
||||||
"disclaimerHint": "Примітка:",
|
"disclaimerHint": "Примітка:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "Ліміт заряджання, який використовується, коли цей автомобіль під’єднано.",
|
|
||||||
"label": "Ліміт за замовчуванням"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "Макс. струм"
|
"label": "Макс. струм"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "Мін. струм"
|
"label": "Мін. струм"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "Для надзвичайних ситуацій. Транспортний засіб «швидко» заряджається до {0} від усіх доступних сонячних батарей, а потім продовжує працювати лише з сонячним надлишком.",
|
|
||||||
"label": "Мін. заряд %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "Ці параметри доступні лише для автомобілів із відомим рівнем заряду.",
|
"onlyForSocBasedCharging": "Ці параметри доступні лише для автомобілів із відомим рівнем заряду.",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "Фази",
|
"label": "Фази",
|
||||||
|
|
|
||||||
|
|
@ -614,9 +614,7 @@
|
||||||
"chargingPlan": {
|
"chargingPlan": {
|
||||||
"active": "启用",
|
"active": "启用",
|
||||||
"addRepeatingPlan": "添加重复计划",
|
"addRepeatingPlan": "添加重复计划",
|
||||||
"arrivalTab": "抵达",
|
|
||||||
"day": "日期",
|
"day": "日期",
|
||||||
"departureTab": "离开",
|
|
||||||
"goal": "充电目标",
|
"goal": "充电目标",
|
||||||
"modalTitle": "充电计划",
|
"modalTitle": "充电计划",
|
||||||
"none": "无",
|
"none": "无",
|
||||||
|
|
@ -633,8 +631,6 @@
|
||||||
"selectAll": "全选",
|
"selectAll": "全选",
|
||||||
"time": "时间",
|
"time": "时间",
|
||||||
"title": "计划",
|
"title": "计划",
|
||||||
"titleMinSoc": "最小充电量",
|
|
||||||
"titleTargetCharge": "出发时间",
|
|
||||||
"unsavedChanges": "有未保存的更改。是否立即应用?",
|
"unsavedChanges": "有未保存的更改。是否立即应用?",
|
||||||
"update": "应用",
|
"update": "应用",
|
||||||
"weekdays": "天数"
|
"weekdays": "天数"
|
||||||
|
|
@ -688,20 +684,12 @@
|
||||||
"currents": "充电电流",
|
"currents": "充电电流",
|
||||||
"default": "默认",
|
"default": "默认",
|
||||||
"disclaimerHint": "注意:",
|
"disclaimerHint": "注意:",
|
||||||
"limitSoc": {
|
|
||||||
"description": "连接此车辆时使用的充电上限。",
|
|
||||||
"label": "默认上限"
|
|
||||||
},
|
|
||||||
"maxCurrent": {
|
"maxCurrent": {
|
||||||
"label": "最大电流"
|
"label": "最大电流"
|
||||||
},
|
},
|
||||||
"minCurrent": {
|
"minCurrent": {
|
||||||
"label": "最小电流"
|
"label": "最小电流"
|
||||||
},
|
},
|
||||||
"minSoc": {
|
|
||||||
"description": "在太阳能模式下,车辆将“快速”充电至 {0},然后继续使用太阳能余电充电。这有助于确保即使在光照不足的日子也能达到最低续航里程。",
|
|
||||||
"label": "最小电量 %"
|
|
||||||
},
|
|
||||||
"onlyForSocBasedCharging": "这些选项仅适用于已知充电量的车辆。",
|
"onlyForSocBasedCharging": "这些选项仅适用于已知充电量的车辆。",
|
||||||
"phasesConfigured": {
|
"phasesConfigured": {
|
||||||
"label": "相数",
|
"label": "相数",
|
||||||
|
|
|
||||||
|
|
@ -181,11 +181,14 @@ test.describe("vehicles", async () => {
|
||||||
/active/
|
/active/
|
||||||
);
|
);
|
||||||
|
|
||||||
await lp.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
const moreTab = page.getByTestId("tab-more");
|
||||||
const modal = page.getByTestId("charging-plan-modal");
|
await moreTab.click();
|
||||||
|
await moreTab.getByRole("button", { name: "Vehicles" }).click();
|
||||||
|
const modal = page.getByTestId("vehicle-settings-modal");
|
||||||
await expectModalVisible(modal);
|
await expectModalVisible(modal);
|
||||||
await modal.getByRole("link", { name: "Arrival" }).click();
|
await expect(
|
||||||
await expect(modal.getByRole("combobox", { name: "Default mode" })).toHaveValue("now");
|
modal.getByRole("group", { name: "Grey Car" }).getByRole("combobox", { name: "Default mode" })
|
||||||
|
).toHaveValue("now");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("save and restore rfid identifiers", async ({ page }) => {
|
test("save and restore rfid identifiers", async ({ page }) => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { test, expect } from "@playwright/test";
|
import { test, expect } from "@playwright/test";
|
||||||
import { start, stop, baseUrl } from "./evcc";
|
import { start, stop, baseUrl } from "./evcc";
|
||||||
|
import { expectModalVisible } from "./utils";
|
||||||
|
|
||||||
test.use({ baseURL: baseUrl() });
|
test.use({ baseURL: baseUrl() });
|
||||||
|
|
||||||
|
|
@ -20,16 +21,18 @@ test.describe("vehicle startup error (using failing Tesla API)", async () => {
|
||||||
await expect(page.getByTestId("vehicle-name")).toHaveText("Broken Tesla");
|
await expect(page.getByTestId("vehicle-name")).toHaveText("Broken Tesla");
|
||||||
await expect(page.getByTestId("vehicle-not-reachable-icon")).toBeVisible();
|
await expect(page.getByTestId("vehicle-not-reachable-icon")).toBeVisible();
|
||||||
|
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
const moreTab = page.getByTestId("tab-more");
|
||||||
const modal = page.getByTestId("charging-plan-modal");
|
await moreTab.click();
|
||||||
await modal.getByRole("link", { name: "Arrival" }).click();
|
await moreTab.getByRole("button", { name: "Vehicles" }).click();
|
||||||
await expect(modal.getByRole("combobox", { name: "Min. charge %" })).toBeEnabled();
|
const modal = page.getByTestId("vehicle-settings-modal");
|
||||||
|
await expectModalVisible(modal);
|
||||||
|
await expect(modal.getByRole("combobox", { name: "Minimum charge" })).toBeEnabled();
|
||||||
await expect(modal.getByRole("combobox", { name: "Default limit" })).toBeEnabled();
|
await expect(modal.getByRole("combobox", { name: "Default limit" })).toBeEnabled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("guest vehicle: normal title and no icon", async ({ page }) => {
|
test("guest vehicle: normal title and no icon", async ({ page }) => {
|
||||||
// switch to offline vehicle
|
// switch to offline vehicle
|
||||||
await page.getByTestId("change-vehicle").locator("select").selectOption("Guest vehicle");
|
await page.getByRole("combobox", { name: "Change vehicle" }).selectOption("Guest vehicle");
|
||||||
|
|
||||||
await expect(page.getByTestId("vehicle-name")).toHaveText("Guest vehicle");
|
await expect(page.getByTestId("vehicle-name")).toHaveText("Guest vehicle");
|
||||||
await expect(page.getByTestId("vehicle-not-reachable-icon")).not.toBeVisible();
|
await expect(page.getByTestId("vehicle-not-reachable-icon")).not.toBeVisible();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { test, expect, type Page } from "@playwright/test";
|
import { test, expect, type Locator, type Page } from "@playwright/test";
|
||||||
import { start, stop, restart, baseUrl } from "./evcc";
|
import { start, stop, restart, baseUrl } from "./evcc";
|
||||||
import { expectModalVisible, expectModalHidden } from "./utils";
|
import { expectModalVisible, expectModalHidden } from "./utils";
|
||||||
import {
|
import {
|
||||||
|
|
@ -32,45 +32,109 @@ test.afterEach(async () => {
|
||||||
await stop();
|
await stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function switchVehicle(page: Page, title: string) {
|
||||||
|
await page.getByRole("combobox", { name: "Change vehicle" }).selectOption(title);
|
||||||
|
await expect(page.getByTestId("vehicle-name")).toHaveText(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openVehicleSettings(page: Page) {
|
||||||
|
const moreTab = page.getByTestId("tab-more");
|
||||||
|
await moreTab.click();
|
||||||
|
await moreTab.getByRole("button", { name: "Vehicles" }).click();
|
||||||
|
const modal = page.getByTestId("vehicle-settings-modal");
|
||||||
|
await expectModalVisible(modal);
|
||||||
|
return modal;
|
||||||
|
}
|
||||||
|
|
||||||
|
function vehicleRow(modal: Locator, title: string) {
|
||||||
|
return modal.getByRole("group", { name: title });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function closeModal(page: Page) {
|
||||||
|
const modal = page.getByTestId("vehicle-settings-modal");
|
||||||
|
await modal.getByRole("button", { name: "Close" }).click();
|
||||||
|
await expectModalHidden(modal);
|
||||||
|
}
|
||||||
|
|
||||||
|
test.describe("overview", async () => {
|
||||||
|
test("all configured vehicles listed", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
|
||||||
|
const modal = await openVehicleSettings(page);
|
||||||
|
await expect(modal.getByRole("group")).toHaveCount(2);
|
||||||
|
await expect(vehicleRow(modal, "blauer e-Golf")).toBeVisible();
|
||||||
|
await expect(vehicleRow(modal, "grüner Honda e")).toBeVisible();
|
||||||
|
await expect(modal).not.toContainText("Guest vehicle");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("connected indicator only on connected vehicle", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
|
||||||
|
const modal = await openVehicleSettings(page);
|
||||||
|
await expect(
|
||||||
|
vehicleRow(modal, "blauer e-Golf").getByText("connected to Carport")
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(vehicleRow(modal, "grüner Honda e").getByText("not connected")).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("per-vehicle values are independent", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
|
||||||
|
const modal = await openVehicleSettings(page);
|
||||||
|
const golfMode = vehicleRow(modal, "blauer e-Golf").getByRole("combobox", {
|
||||||
|
name: "Default mode",
|
||||||
|
});
|
||||||
|
const hondaMode = vehicleRow(modal, "grüner Honda e").getByRole("combobox", {
|
||||||
|
name: "Default mode",
|
||||||
|
});
|
||||||
|
|
||||||
|
await hondaMode.selectOption("Fast");
|
||||||
|
await expect(hondaMode).toHaveValue("now");
|
||||||
|
await expect(golfMode).toHaveValue("");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test.describe("minSoc", async () => {
|
test.describe("minSoc", async () => {
|
||||||
test("apply and restart", async ({ page }) => {
|
test("apply and restart", async ({ page }) => {
|
||||||
await page.goto("/");
|
await page.goto("/");
|
||||||
|
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
const modal = await openVehicleSettings(page);
|
||||||
const modal = page.getByTestId("charging-plan-modal");
|
const minSoc = vehicleRow(modal, "blauer e-Golf").getByRole("combobox", {
|
||||||
await expectModalVisible(modal);
|
name: "Minimum charge",
|
||||||
await modal.getByRole("link", { name: "Arrival" }).click();
|
});
|
||||||
|
await minSoc.selectOption("20");
|
||||||
await expect(modal).toContainText("charged to x in solar mode");
|
await expect(minSoc).toHaveValue("20");
|
||||||
await modal.getByRole("combobox", { name: "Min. charge %" }).selectOption("20%");
|
await closeModal(page);
|
||||||
await expect(modal).toContainText("charged to 20% in solar mode");
|
|
||||||
await modal.getByRole("button", { name: "Close" }).click();
|
|
||||||
await expectModalHidden(modal);
|
|
||||||
await page.waitForLoadState("networkidle");
|
await page.waitForLoadState("networkidle");
|
||||||
|
|
||||||
await restart(simulatorConfig());
|
await restart(simulatorConfig());
|
||||||
await page.reload();
|
await page.reload();
|
||||||
|
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
const modalAfterRestart = await openVehicleSettings(page);
|
||||||
await page.getByRole("link", { name: "Arrival" }).click();
|
await expect(
|
||||||
await expect(page.getByText("charged to 20% in solar mode")).toBeVisible();
|
vehicleRow(modalAfterRestart, "blauer e-Golf").getByRole("combobox", {
|
||||||
|
name: "Minimum charge",
|
||||||
|
})
|
||||||
|
).toHaveValue("20");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("show minsoc indicator when minsoc is active", async ({ page }) => {
|
test("show minsoc indicator when minsoc is active", async ({ page }) => {
|
||||||
await page.goto("/");
|
await page.goto("/");
|
||||||
|
|
||||||
await expect(page.getByTestId("charging-plan")).toContainText("Plan");
|
const modal = await openVehicleSettings(page);
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
const minSoc = vehicleRow(modal, "blauer e-Golf").getByRole("combobox", {
|
||||||
await page.getByRole("link", { name: "Arrival" }).click();
|
name: "Minimum charge",
|
||||||
await page.getByRole("combobox", { name: "Min. charge %" }).selectOption("50%");
|
});
|
||||||
await page.getByRole("button", { name: "Close" }).click();
|
await minSoc.selectOption("50");
|
||||||
|
await closeModal(page);
|
||||||
|
|
||||||
await expect(page.getByTestId("vehicle-status-minsoc")).toBeVisible();
|
await expect(page.getByTestId("vehicle-status-minsoc")).toBeVisible();
|
||||||
await expect(page.getByTestId("vehicle-status-minsoc")).toHaveText("50%");
|
await expect(page.getByTestId("vehicle-status-minsoc")).toHaveText("50%");
|
||||||
|
|
||||||
await page.getByTestId("vehicle-status-minsoc").click();
|
await page.getByTestId("vehicle-status-minsoc").click();
|
||||||
await page.getByRole("combobox", { name: "Min. charge %" }).selectOption("---");
|
await expectModalVisible(modal);
|
||||||
await page.getByRole("button", { name: "Close" }).click();
|
await minSoc.selectOption("0");
|
||||||
|
await closeModal(page);
|
||||||
|
|
||||||
await expect(page.getByTestId("vehicle-status-minsoc")).not.toBeVisible();
|
await expect(page.getByTestId("vehicle-status-minsoc")).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
@ -80,26 +144,25 @@ test.describe("limitSoc", async () => {
|
||||||
test("apply and restart", async ({ page }) => {
|
test("apply and restart", async ({ page }) => {
|
||||||
await page.goto("/");
|
await page.goto("/");
|
||||||
|
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
const modal = await openVehicleSettings(page);
|
||||||
const modal = page.getByTestId("charging-plan-modal");
|
await vehicleRow(modal, "blauer e-Golf")
|
||||||
await expectModalVisible(modal);
|
.getByRole("combobox", { name: "Default limit" })
|
||||||
await modal.getByRole("link", { name: "Arrival" }).click();
|
.selectOption("80");
|
||||||
|
await closeModal(page);
|
||||||
await modal.getByRole("combobox", { name: "Default limit" }).selectOption("80%");
|
|
||||||
await modal.getByRole("button", { name: "Close" }).click();
|
|
||||||
await expectModalHidden(modal);
|
|
||||||
await expect(page.getByTestId("limit-soc-value")).toContainText("80%");
|
await expect(page.getByTestId("limit-soc-value")).toContainText("80%");
|
||||||
await page.waitForLoadState("networkidle");
|
await page.waitForLoadState("networkidle");
|
||||||
await page.waitForTimeout(500); // bad practice but may help here :/
|
|
||||||
|
|
||||||
await restart(simulatorConfig());
|
await restart(simulatorConfig());
|
||||||
await page.reload();
|
await page.reload();
|
||||||
|
|
||||||
await expect(page.getByTestId("limit-soc-value")).toContainText("80%");
|
await expect(page.getByTestId("limit-soc-value")).toContainText("80%");
|
||||||
|
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
const modalAfterRestart = await openVehicleSettings(page);
|
||||||
await page.getByRole("link", { name: "Arrival" }).click();
|
await expect(
|
||||||
await expect(page.getByRole("combobox", { name: "Default limit" })).toHaveValue("80");
|
vehicleRow(modalAfterRestart, "blauer e-Golf").getByRole("combobox", {
|
||||||
|
name: "Default limit",
|
||||||
|
})
|
||||||
|
).toHaveValue("80");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -107,69 +170,64 @@ test.describe("minSoc and limitSoc", async () => {
|
||||||
test("hidden for offline vehicles", async ({ page }) => {
|
test("hidden for offline vehicles", async ({ page }) => {
|
||||||
await page.goto("/");
|
await page.goto("/");
|
||||||
|
|
||||||
// switch to offline vehicle
|
const modal = await openVehicleSettings(page);
|
||||||
await page.getByTestId("change-vehicle").locator("select").selectOption("grüner Honda e");
|
const honda = vehicleRow(modal, "grüner Honda e");
|
||||||
|
await expect(honda.getByRole("combobox", { name: "Default mode" })).toBeVisible();
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
await expect(honda.getByRole("combobox", { name: "Minimum charge" })).not.toBeVisible();
|
||||||
await page.getByRole("link", { name: "Arrival" }).click();
|
await expect(honda.getByRole("combobox", { name: "Default limit" })).not.toBeVisible();
|
||||||
await expect(page.getByRole("combobox", { name: "Min. charge %" })).not.toBeVisible();
|
|
||||||
await expect(page.getByRole("combobox", { name: "Default limit" })).not.toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("no tabs for guest vehicles", async ({ page }) => {
|
|
||||||
await page.goto("/");
|
|
||||||
|
|
||||||
// switch to guest vehicle (no known vehicle)
|
|
||||||
await page.getByTestId("change-vehicle").locator("select").selectOption("Guest vehicle");
|
|
||||||
|
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
|
||||||
const modal = page.getByTestId("charging-plan-modal");
|
|
||||||
await expectModalVisible(modal);
|
|
||||||
await expect(modal.getByRole("link", { name: "Departure" })).toHaveCount(0);
|
|
||||||
await expect(modal.getByRole("link", { name: "Arrival" })).toHaveCount(0);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe("default mode", async () => {
|
test.describe("default mode", async () => {
|
||||||
async function setDefaultMode(page: Page, option: string) {
|
async function setDefaultMode(page: Page, title: string, option: string) {
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
const modal = await openVehicleSettings(page);
|
||||||
const modal = page.getByTestId("charging-plan-modal");
|
await vehicleRow(modal, title)
|
||||||
await expectModalVisible(modal);
|
.getByRole("combobox", { name: "Default mode" })
|
||||||
await modal.getByRole("link", { name: "Arrival" }).click();
|
.selectOption(option);
|
||||||
await modal.getByRole("combobox", { name: "Default mode" }).selectOption(option);
|
await closeModal(page);
|
||||||
await modal.getByRole("button", { name: "Close" }).click();
|
|
||||||
await expectModalHidden(modal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("apply and restart", async ({ page }) => {
|
test("apply and restart", async ({ page }) => {
|
||||||
await page.goto("/");
|
await page.goto("/");
|
||||||
|
|
||||||
await setDefaultMode(page, "Fast");
|
await setDefaultMode(page, "blauer e-Golf", "Fast");
|
||||||
await page.waitForLoadState("networkidle");
|
await page.waitForLoadState("networkidle");
|
||||||
|
|
||||||
await restart(simulatorConfig());
|
await restart(simulatorConfig());
|
||||||
await page.reload();
|
await page.reload();
|
||||||
|
|
||||||
await page.getByTestId("charging-plan").getByRole("button", { name: "none" }).click();
|
const modal = await openVehicleSettings(page);
|
||||||
await page.getByRole("link", { name: "Arrival" }).click();
|
await expect(
|
||||||
await expect(page.getByRole("combobox", { name: "Default mode" })).toHaveValue("now");
|
vehicleRow(modal, "blauer e-Golf").getByRole("combobox", { name: "Default mode" })
|
||||||
|
).toHaveValue("now");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("applied on vehicle switch", async ({ page }) => {
|
test("applied on vehicle switch", async ({ page }) => {
|
||||||
await page.goto("/");
|
await page.goto("/");
|
||||||
const mode = page.getByTestId("loadpoint").first().getByTestId("mode");
|
const mode = page.getByTestId("loadpoint").first().getByTestId("mode");
|
||||||
const changeVehicle = page.getByTestId("change-vehicle").locator("select");
|
|
||||||
|
|
||||||
// per-vehicle default modes
|
// per-vehicle default modes
|
||||||
await setDefaultMode(page, "Solar");
|
await setDefaultMode(page, "blauer e-Golf", "Solar");
|
||||||
await changeVehicle.selectOption("grüner Honda e");
|
await setDefaultMode(page, "grüner Honda e", "Fast");
|
||||||
await setDefaultMode(page, "Fast");
|
|
||||||
|
|
||||||
// switching vehicles applies the vehicle's default mode
|
// switching vehicles applies the vehicle's default mode
|
||||||
await changeVehicle.selectOption("blauer e-Golf");
|
await switchVehicle(page, "grüner Honda e");
|
||||||
await expect(mode.getByRole("button", { name: "Solar", exact: true })).toHaveClass(/active/);
|
|
||||||
|
|
||||||
await changeVehicle.selectOption("grüner Honda e");
|
|
||||||
await expect(mode.getByRole("button", { name: "Fast" })).toHaveClass(/active/);
|
await expect(mode.getByRole("button", { name: "Fast" })).toHaveClass(/active/);
|
||||||
|
|
||||||
|
await switchVehicle(page, "blauer e-Golf");
|
||||||
|
await expect(mode.getByRole("button", { name: "Solar", exact: true })).toHaveClass(/active/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe("menu entry", async () => {
|
||||||
|
test("hidden when no vehicles are configured", async ({ page }) => {
|
||||||
|
await stop();
|
||||||
|
await start("basics.evcc.yaml");
|
||||||
|
|
||||||
|
await page.goto("/");
|
||||||
|
const moreTab = page.getByTestId("tab-more");
|
||||||
|
await moreTab.click();
|
||||||
|
await expect(moreTab.getByRole("button", { name: "User Interface" })).toBeVisible();
|
||||||
|
await expect(moreTab.getByRole("button", { name: "Vehicles" })).not.toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue