Improved Charge Progress UI (#798)

This commit is contained in:
Michael Geers 2021-03-26 08:32:27 +01:00 • committed by GitHub
parent 9d2d314b8a
commit df19f23ec2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 362 additions and 116 deletions

View file

@ -56,7 +56,7 @@
/>
<fa-icon
icon="clock"
v-bind:class="{ fas: socTimerActive, far: !socTimerActive }"
v-bind:class="{ fas: timerActive, far: !timerActive }"
></fa-icon>
</label>
</div> -->
@ -164,11 +164,13 @@ export default {
// vehicle
connected: Boolean,
// charging: Boolean,
enabled: Boolean,
socTitle: String,
socCharge: Number,
minSoC: Number,
socTimerSet: Boolean,
socTimerActive: Boolean,
timerSet: Boolean,
timerActive: Boolean,
targetTime: String,
// details
chargePower: Number,

View file

@ -62,6 +62,6 @@ VehicleTimer.args = {
hasVehicle: true,
range: 240.123,
chargeEstimate: 5 * 3600,
socTimerSet: true,
socTimerActive: true,
timerSet: true,
timerActive: true,
};

View file

@ -3,9 +3,6 @@
<div class="col-6 col-md-3 mt-3">
<div class="mb-2 value">
Leistung
<fa-icon class="text-primary ml-1" icon="clock" v-if="socTimerActive"></fa-icon>
<fa-icon class="text-secondary ml-1" icon="clock" v-else-if="socTimerSet"></fa-icon>
<fa-icon
class="text-primary ml-1"
icon="temperature-low"
@ -75,8 +72,6 @@ export default {
climater: String,
hasVehicle: Boolean,
range: Number,
socTimerActive: Boolean,
socTimerSet: Boolean,
},
mixins: [formatter],
};

View file

@ -14,24 +14,128 @@ const Template = (args, { argTypes }) => ({
export const Base = Template.bind({});
Base.args = {
soc: false,
socTitle: "Mein Auto",
enabled: true,
connected: true,
hasVehicle: true,
socCharge: 42,
};
export const Car = Template.bind({});
Car.args = {
soc: true,
export const Connected = Template.bind({});
Connected.args = {
socTitle: "Mein Auto",
enabled: false,
connected: true,
socCharge: 15,
hasVehicle: true,
charging: false,
socCharge: 66,
};
export const CarWithMin = Template.bind({});
CarWithMin.args = {
soc: true,
export const ReadyToCharge = Template.bind({});
ReadyToCharge.args = {
socTitle: "Mein Auto",
enabled: true,
connected: true,
socCharge: 15,
hasVehicle: true,
charging: false,
socCharge: 66,
};
export const Charging = Template.bind({});
Charging.args = {
socTitle: "Mein Auto",
enabled: true,
connected: true,
hasVehicle: true,
charging: true,
socCharge: 66,
};
const hoursFromNow = function (hours) {
const now = new Date();
now.setHours(now.getHours() + hours);
return now.toISOString();
};
export const TargetChargePlanned = Template.bind({});
TargetChargePlanned.args = {
socTitle: "Mein Auto",
enabled: false,
connected: true,
hasVehicle: true,
socCharge: 31,
minSoC: 20,
charging: false,
timerSet: true,
timerActive: false,
targetSoC: 45,
targetTime: hoursFromNow(14),
};
export const TargetChargeActive = Template.bind({});
TargetChargeActive.args = {
socTitle: "Mein Auto",
enabled: true,
connected: true,
hasVehicle: true,
socCharge: 66,
minSoC: 30,
charging: true,
timerSet: true,
timerActive: true,
targetSoC: 80,
targetTime: hoursFromNow(2),
};
export const MinCharge = Template.bind({});
MinCharge.args = {
socTitle: "Mein Auto",
enabled: true,
connected: true,
hasVehicle: true,
socCharge: 17,
minSoC: 20,
charging: true,
};
export const UnknownVehicleConnected = Template.bind({});
UnknownVehicleConnected.args = {
socTitle: "Mein Auto",
enabled: false,
connected: true,
hasVehicle: false,
};
export const UnknownVehicleReadyToCharge = Template.bind({});
UnknownVehicleReadyToCharge.args = {
socTitle: "Mein Auto",
enabled: true,
connected: true,
hasVehicle: false,
charging: false,
};
export const UnknownVehicleCharging = Template.bind({});
UnknownVehicleCharging.args = {
socTitle: "Mein Auto",
enabled: true,
connected: true,
hasVehicle: false,
charging: true,
};
export const Disconnected = Template.bind({});
Disconnected.args = {
socTitle: "Mein Auto",
connected: false,
hasVehicle: false,
};
export const DisconnectedKnownSoc = Template.bind({});
DisconnectedKnownSoc.args = {
socTitle: "Mein Auto",
connected: false,
enabled: false,
hasVehicle: true,
socCharge: 17,
};

View file

@ -1,47 +1,63 @@
<template>
<div>
<div class="mb-2">{{ socTitle || "Fahrzeug" }}</div>
<div class="progress" style="height: 24px; font-size: 100%; margin-top: 16px">
<div class="mb-3">
{{ socTitle || "Fahrzeug" }}
</div>
<div class="progress" style="height: 28px; font-size: 100%">
<div
class="progress-bar"
role="progressbar"
:class="{
'progress-bar-striped': charging,
'progress-bar-animated': charging,
'bg-light': !connected,
'text-secondary': !connected,
'bg-warning': connected && minSoCActive,
[progressColor]: true,
}"
:style="{ width: socChargeDisplayWidth + '%' }"
>
{{ socChargeDisplayValue }}
</div>
<div
v-if="remainingSoCWidth"
class="progress-bar"
role="progressbar"
:class="{
'progress-bar-striped': charging,
'progress-bar-animated': charging,
'bg-warning': true,
[progressColor]: true,
'bg-muted': true,
}"
:style="{ width: minSoCRemainingDisplayWidth + '%' }"
v-if="minSoCActive && socChargeDisplayWidth < 100"
:style="{ width: remainingSoCWidth + '%' }"
></div>
</div>
<small v-if="markerLabel()" class="subline my-2 text-secondary">
<fa-icon
v-if="minSoCActive"
class="text-muted mr-1"
icon="exclamation-circle"
></fa-icon>
<fa-icon v-else-if="targetChargeEnabled" class="text-muted mr-1" icon="clock"></fa-icon>
{{ markerLabel() }}
</small>
</div>
</template>
<script>
import formatter from "../mixins/formatter";
export default {
name: "Vehicle",
props: {
socTitle: String,
connected: Boolean,
charging: Boolean,
hasVehicle: Boolean,
socCharge: Number,
enabled: Boolean,
charging: Boolean,
minSoC: Number,
timerActive: Boolean,
timerSet: Boolean,
targetTime: String,
targetSoC: Number,
},
computed: {
socChargeDisplayWidth: function () {
@ -52,10 +68,12 @@ export default {
},
socChargeDisplayValue: function () {
// no soc or no soc value
if (!this.hasVehicle || this.socCharge < 0) {
if (!this.hasVehicle || !this.socCharge || this.socCharge < 0) {
let chargeStatus = "getrennt";
if (this.charging) {
chargeStatus = "laden";
chargeStatus = "lädt";
} else if (this.enabled) {
chargeStatus = "bereit";
} else if (this.connected) {
chargeStatus = "verbunden";
}
@ -69,12 +87,98 @@ export default {
}
return socCharge;
},
socMarker: function () {
if (!this.connected || !this.hasVehicle) {
return null;
}
if (this.minSoCActive) {
return this.minSoC;
}
if (this.targetChargeEnabled) {
return this.targetSoC;
}
return null;
},
progressColor: function () {
if (!this.connected) {
return "bg-light border";
}
if (this.minSoCActive) {
return "bg-danger";
}
if (this.enabled) {
return "bg-primary";
}
return "bg-secondary";
},
minSoCActive: function () {
return this.minSoC > 0 && this.socCharge < this.minSoC;
},
minSoCRemainingDisplayWidth: function () {
return this.minSoC - this.socCharge;
targetChargeEnabled: function () {
return this.targetTime && this.timerSet;
},
remainingSoCWidth: function () {
if (!this.connected || this.socCharge === 100) {
return null;
}
if (this.minSoCActive) {
return this.minSoC - this.socCharge;
}
if (this.targetChargeEnabled) {
return this.targetSoC - this.socCharge;
}
return null;
},
},
methods: {
// not computed because it needs to update over time
markerLabel: function () {
if (!this.connected) {
return null;
}
if (this.minSoCActive) {
return `Mindestladung bis ${this.socMarker}%`;
}
if (this.targetChargeEnabled) {
const targetDate = Date.parse(this.targetTime);
if (this.timerActive) {
return `Lädt ${this.fmtRelativeTime(targetDate)} bis ${this.socMarker}%`;
} else {
return `Geplant bis ${this.fmtAbsoluteDate(targetDate)} bis ${this.socMarker}%`;
}
}
return null;
},
},
mixins: [formatter],
};
</script>
<style scoped>
.subline {
display: flex;
align-items: center;
}
.progress {
overflow: visible;
}
.progress-bar.bg-muted {
position: relative;
overflow: visible;
color: var(--white);
}
.progress-bar.bg-muted::after {
position: absolute;
right: 0;
top: -5px;
height: calc(100% + 10px);
width: 2px;
background: var(--dark);
content: "";
}
.bg-disabled {
background-color: var(--gray);
}
.bg-light {
color: var(--dark);
}
</style>

View file

@ -11,7 +11,7 @@ import { faBatteryQuarter } from "@fortawesome/free-solid-svg-icons/faBatteryQua
import { faBatteryThreeQuarters } from "@fortawesome/free-solid-svg-icons/faBatteryThreeQuarters";
import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
import { faChevronUp } from "@fortawesome/free-solid-svg-icons/faChevronUp";
import { faClock } from "@fortawesome/free-solid-svg-icons";
import { faClock } from "@fortawesome/free-solid-svg-icons/faClock";
import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons/faExclamationTriangle";
import { faLeaf } from "@fortawesome/free-solid-svg-icons/faLeaf";
import { faSun } from "@fortawesome/free-solid-svg-icons/faSun";
@ -21,6 +21,7 @@ import { faThermometerHalf } from "@fortawesome/free-solid-svg-icons/faThermomet
import { faHeart } from "@fortawesome/free-solid-svg-icons/faHeart";
import { faGift } from "@fortawesome/free-solid-svg-icons/faGift";
import { faBox } from "@fortawesome/free-solid-svg-icons/faBox";
import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle";
library.add(
faArrowDown,
@ -41,7 +42,8 @@ library.add(
faThermometerHalf,
faHeart,
faGift,
faBox
faBox,
faExclamationCircle
);
Vue.component("fa-icon", FontAwesomeIcon);

View file

@ -58,5 +58,34 @@ export default {
}
return "m";
},
fmtAbsoluteDate: function (date) {
return new Intl.DateTimeFormat("de-DE", {
weekday: "short",
hour: "numeric",
minute: "numeric",
}).format(date);
},
fmtRelativeTime: function (date) {
var units = {
year: 24 * 60 * 60 * 1000 * 365,
month: (24 * 60 * 60 * 1000 * 365) / 12,
day: 24 * 60 * 60 * 1000,
hour: 60 * 60 * 1000,
minute: 60 * 1000,
second: 1000,
};
var rtf = new Intl.RelativeTimeFormat("de", { numeric: "auto", style: "narrow" });
var getRelativeTime = (d1, d2 = new Date()) => {
var elapsed = d1 - d2;
// "Math.abs" accounts for both "past" & "future" scenarios
for (var u in units)
if (Math.abs(elapsed) > units[u] || u == "second")
return rtf.format(Math.round(elapsed / units[u]), u);
};
return getRelativeTime(date);
},
},
};

View file

@ -119,6 +119,9 @@ func (lp *LoadPoint) SetTargetCharge(finishAt time.Time, targetSoC int) {
lp.publish("targetTime", finishAt)
lp.publish("targetSoC", targetSoC)
lp.socTimer.Time = finishAt
lp.socTimer.SoC = targetSoC
lp.requestUpdate()
}

View file

@ -1 +1 @@
.progress-bar-animated{animation-direction:reverse}.btn.caption{opacity:1}.btn.first{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}.value,input[type=radio],label.btn{white-space:nowrap!important}.text-muted a,.text-muted a:hover{color:#6c757d!important;text-decoration:none}.bg-muted{opacity:.25}.fade-enter-active[data-v-a6ded36e],.fade-leave-active[data-v-a6ded36e]{transition:opacity .25s ease-in}.fade-enter[data-v-a6ded36e],.fade-leave-to[data-v-a6ded36e]{opacity:0}.dialog[data-v-a6ded36e]{position:fixed;top:0;left:0;z-index:1050;width:100%;height:100%;overflow:hidden;outline:0}.icon[data-v-a6ded36e]{color:#0fdd42}.text-black a[data-v-a6ded36e]{color:#18191a}.icon[data-v-5f0f38d1]{color:#0fdd42}.text-black a[data-v-5f0f38d1]{color:#18191a}.logo[data-v-459f11b2]{width:85px}.app[data-v-459f11b2]{min-height:100vh}
.progress-bar-animated{animation-direction:reverse}.btn.caption{opacity:1}.btn.first{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}.value,input[type=radio],label.btn{white-space:nowrap!important}.text-muted a,.text-muted a:hover{color:#6c757d!important;text-decoration:none}.bg-muted{opacity:.25}.fade-enter-active[data-v-a6ded36e],.fade-leave-active[data-v-a6ded36e]{transition:opacity .25s ease-in}.fade-enter[data-v-a6ded36e],.fade-leave-to[data-v-a6ded36e]{opacity:0}.dialog[data-v-a6ded36e]{position:fixed;top:0;left:0;z-index:1050;width:100%;height:100%;overflow:hidden;outline:0}.icon[data-v-a6ded36e]{color:#0fdd42}.text-black a[data-v-a6ded36e]{color:#18191a}.icon[data-v-5f0f38d1]{color:#0fdd42}.text-black a[data-v-5f0f38d1]{color:#18191a}.logo[data-v-459f11b2]{width:85px}.app[data-v-459f11b2]{min-height:100vh}.subline[data-v-6c9c1346]{display:flex;align-items:center}.progress[data-v-6c9c1346]{overflow:visible}.progress-bar.bg-muted[data-v-6c9c1346]{position:relative;overflow:visible;color:var(--white)}.progress-bar.bg-muted[data-v-6c9c1346]:after{position:absolute;right:0;top:-5px;height:calc(100% + 10px);width:2px;background:var(--dark);content:""}.bg-disabled[data-v-6c9c1346]{background-color:var(--gray)}.bg-light[data-v-6c9c1346]{color:var(--dark)}

4
dist/index.html vendored
View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="EV Charge Controller"><meta name="author" content="andig"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="apple-touch-icon" sizes="180x180" href="ico/apple-touch-icon.png?[[.Version]]"><link rel="icon" type="image/png" sizes="32x32" href="ico/favicon-32x32.png?[[.Version]]"><link rel="icon" type="image/png" sizes="16x16" href="ico/favicon-16x16.png?[[.Version]]"><link rel="manifest" href="ico/site.webmanifest"><link rel="mask-icon" href="ico/safari-pinned-tab.svg?[[.Version]]" color="#18191a"><link rel="shortcut icon" href="ico/favicon.ico?[[.Version]]"><meta name="apple-mobile-web-app-title" content="evcc"><meta name="application-name" content="evcc"><meta name="msapplication-TileColor" content="#18191a"><meta name="msapplication-config" content="ico/browserconfig.xml"><meta name="theme-color" content="#18191a"><title>evcc</title><link href="css/chunk-vendors.52eaf30c.css" rel="preload" as="style"><link href="css/index.6dc6b1ad.css" rel="preload" as="style"><link href="js/chunk-vendors.af4765ba.js" rel="preload" as="script"><link href="js/index.59100a52.js" rel="preload" as="script"><link href="css/chunk-vendors.52eaf30c.css" rel="stylesheet"><link href="css/index.6dc6b1ad.css" rel="stylesheet"></head><body><script>window.evcc = {
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="EV Charge Controller"><meta name="author" content="andig"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="apple-touch-icon" sizes="180x180" href="ico/apple-touch-icon.png?[[.Version]]"><link rel="icon" type="image/png" sizes="32x32" href="ico/favicon-32x32.png?[[.Version]]"><link rel="icon" type="image/png" sizes="16x16" href="ico/favicon-16x16.png?[[.Version]]"><link rel="manifest" href="ico/site.webmanifest"><link rel="mask-icon" href="ico/safari-pinned-tab.svg?[[.Version]]" color="#18191a"><link rel="shortcut icon" href="ico/favicon.ico?[[.Version]]"><meta name="apple-mobile-web-app-title" content="evcc"><meta name="application-name" content="evcc"><meta name="msapplication-TileColor" content="#18191a"><meta name="msapplication-config" content="ico/browserconfig.xml"><meta name="theme-color" content="#18191a"><title>evcc</title><link href="css/chunk-vendors.52eaf30c.css" rel="preload" as="style"><link href="css/index.82bccd36.css" rel="preload" as="style"><link href="js/chunk-vendors.35669cb4.js" rel="preload" as="script"><link href="js/index.b9c3ae72.js" rel="preload" as="script"><link href="css/chunk-vendors.52eaf30c.css" rel="stylesheet"><link href="css/index.82bccd36.css" rel="stylesheet"></head><body><script>window.evcc = {
version: "[[.Version]]",
configured: "[[.Configured]]",
};</script><div id="app"></div><div id="toasts"></div><script src="js/chunk-vendors.af4765ba.js"></script><script src="js/index.59100a52.js"></script></body></html>
};</script><div id="app"></div><div id="toasts"></div><script src="js/chunk-vendors.35669cb4.js"></script><script src="js/index.b9c3ae72.js"></script></body></html>

File diff suppressed because one or more lines are too long

1
dist/js/chunk-vendors.35669cb4.js.map vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/index.b9c3ae72.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/index.b9c3ae72.js.map vendored Normal file

File diff suppressed because one or more lines are too long

134
package-lock.json generated
View file

@ -1389,24 +1389,24 @@
}
},
"@fortawesome/fontawesome-common-types": {
"version": "0.2.34",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.34.tgz",
"integrity": "sha512-XcIn3iYbTEzGIxD0/dY5+4f019jIcEIWBiHc3KrmK/ROahwxmZ/s+tdj97p/5K0klz4zZUiMfUlYP0ajhSJjmA=="
"version": "0.2.35",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.35.tgz",
"integrity": "sha512-IHUfxSEDS9dDGqYwIW7wTN6tn/O8E0n5PcAHz9cAaBoZw6UpG20IG/YM3NNLaGPwPqgjBAFjIURzqoQs3rrtuw=="
},
"@fortawesome/fontawesome-svg-core": {
"version": "1.2.34",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.34.tgz",
"integrity": "sha512-0KNN0nc5eIzaJxlv43QcDmTkDY1CqeN6J7OCGSs+fwGPdtv0yOQqRjieopBCmw+yd7uD3N2HeNL3Zm5isDleLg==",
"version": "1.2.35",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.35.tgz",
"integrity": "sha512-uLEXifXIL7hnh2sNZQrIJWNol7cTVIzwI+4qcBIq9QWaZqUblm0IDrtSqbNg+3SQf8SMGHkiSigD++rHmCHjBg==",
"requires": {
"@fortawesome/fontawesome-common-types": "^0.2.34"
"@fortawesome/fontawesome-common-types": "^0.2.35"
}
},
"@fortawesome/free-solid-svg-icons": {
"version": "5.15.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.2.tgz",
"integrity": "sha512-ZfCU+QjaFsdNZmOGmfqEWhzI3JOe37x5dF4kz9GeXvKn/sTxhqMtZ7mh3lBf76SvcYY5/GKFuyG7p1r4iWMQqw==",
"version": "5.15.3",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz",
"integrity": "sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q==",
"requires": {
"@fortawesome/fontawesome-common-types": "^0.2.34"
"@fortawesome/fontawesome-common-types": "^0.2.35"
}
},
"@fortawesome/vue-fontawesome": {
@ -2620,9 +2620,9 @@
}
},
"@types/connect-history-api-fallback": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.3.tgz",
"integrity": "sha512-7SxFCd+FLlxCfwVwbyPxbR4khL9aNikJhrorw8nUIOqeuooc9gifBuDQOJw5kzN7i6i3vLn9G8Wde/4QDihpYw==",
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.4.tgz",
"integrity": "sha512-Kf8v0wljR5GSCOCF/VQWdV3ZhKOVA73drXtY3geMTQgHy9dgqQ0dLrf31M0hcuWkhFzK5sP0kkS3mJzcKVtZbw==",
"dev": true,
"requires": {
"@types/express-serve-static-core": "*",
@ -2642,9 +2642,9 @@
}
},
"@types/express-serve-static-core": {
"version": "4.17.18",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz",
"integrity": "sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA==",
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.19.tgz",
"integrity": "sha512-DJOSHzX7pCiSElWaGR8kCprwibCB/3yW6vcT8VG3P0SJjnv19gnWG/AZMfM60Xj/YJIp/YCaDHyvzsFVeniARA==",
"dev": true,
"requires": {
"@types/node": "*",
@ -3033,30 +3033,30 @@
"dev": true
},
"@vue/cli-overlay": {
"version": "4.5.11",
"resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-4.5.11.tgz",
"integrity": "sha512-aDQNw+oGk5+KR0vL9TocjfzyYHTJxR2lS8iPbcL4lRglCs2dudOE7QWXypj5dM4rQus0jJ5fxJTS55o9uy9fcQ==",
"version": "4.5.12",
"resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-4.5.12.tgz",
"integrity": "sha512-dCN0RzVpA8fp+MfjuVBROgM483MPObAb/je+APE/JhpCJyPQORYQEvNpmaorpN+9Cp6mrESVSzhh0qD4SFrlzg==",
"dev": true
},
"@vue/cli-plugin-router": {
"version": "4.5.11",
"resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-4.5.11.tgz",
"integrity": "sha512-09tzw3faOs48IUPwLutYaNC7eoyyL140fKruTwdFdXuBLDdSQVida57Brx0zj2UKXc5qF8hk4GoGrOshN0KfNg==",
"version": "4.5.12",
"resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-4.5.12.tgz",
"integrity": "sha512-DYNz5AA3W7Ewt3aaiOLGdYFt4MX4w/HTEtep+kPzP9S9tAknzyoIJXkaYzhwu8ArpEYwhWgtuCcDZ8hR6++DbA==",
"dev": true,
"requires": {
"@vue/cli-shared-utils": "^4.5.11"
"@vue/cli-shared-utils": "^4.5.12"
}
},
"@vue/cli-plugin-vuex": {
"version": "4.5.11",
"resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.11.tgz",
"integrity": "sha512-JBPeZLubiSHbRkEKDj0tnLiU43AJ3vt6JULn4IKWH1XWZ6MFC8vElaP5/AA4O3Zko5caamDDBq3TRyxdA2ncUQ==",
"version": "4.5.12",
"resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.12.tgz",
"integrity": "sha512-STgbvNv/3iHAKArc18b/qjN7RX1FTrfxPeHH26GOr/A8lJes7+CSluZZ8E5R7Zr/vL0zOqOkUVDAjFXVf4zWQA==",
"dev": true
},
"@vue/cli-service": {
"version": "4.5.11",
"resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-4.5.11.tgz",
"integrity": "sha512-FXeJh2o6B8q/njv2Ebhe9EsLXt9sPMXGDY5zVvcV5jgj9wkoej9yLfnmwWCau5kegNClP6bcM+BEHuMYxJ+ubQ==",
"version": "4.5.12",
"resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-4.5.12.tgz",
"integrity": "sha512-Di/dFw72HIvUrpTgnnPQkPq07mdd7z3GPeCH/o+6fv4bxOD+gwK9z7P6RkG4lGv2QdLz+qjim9f7xw5w+9ENkg==",
"dev": true,
"requires": {
"@intervolga/optimize-cssnano-plugin": "^1.0.5",
@ -3065,10 +3065,10 @@
"@types/minimist": "^1.2.0",
"@types/webpack": "^4.0.0",
"@types/webpack-dev-server": "^3.11.0",
"@vue/cli-overlay": "^4.5.11",
"@vue/cli-plugin-router": "^4.5.11",
"@vue/cli-plugin-vuex": "^4.5.11",
"@vue/cli-shared-utils": "^4.5.11",
"@vue/cli-overlay": "^4.5.12",
"@vue/cli-plugin-router": "^4.5.12",
"@vue/cli-plugin-vuex": "^4.5.12",
"@vue/cli-shared-utils": "^4.5.12",
"@vue/component-compiler-utils": "^3.1.2",
"@vue/preload-webpack-plugin": "^1.1.0",
"@vue/web-component-wrapper": "^1.2.0",
@ -3392,9 +3392,9 @@
}
},
"@vue/cli-shared-utils": {
"version": "4.5.11",
"resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-4.5.11.tgz",
"integrity": "sha512-+aaQ+ThQG3+WMexfSWNl0y6f43edqVqRNbguE53F3TIH81I7saS5S750ayqXhZs2r6STJJyqorQnKtAWfHo29A==",
"version": "4.5.12",
"resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-4.5.12.tgz",
"integrity": "sha512-qnIQPJ4XckMoqYh9fJ0Y91QKMIb4Hiibrm9+k4E15QHpk5RaokuOpf10SsOr2NLPCXSWsHOLo3hduZSwHPGY/Q==",
"dev": true,
"requires": {
"@hapi/joi": "^15.0.1",
@ -5843,9 +5843,9 @@
}
},
"cli-spinners": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz",
"integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ==",
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz",
"integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==",
"dev": true
},
"cli-table3": {
@ -7277,9 +7277,9 @@
}
},
"detect-node": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.5.tgz",
"integrity": "sha512-qi86tE6hRcFHy8jI1m2VG+LaPUR1LhqDa5G8tVjuUXmOrpuAgqsA1pN0+ldgr3aKUH+QLI9hCY/OcRYisERejw==",
"dev": true
},
"detect-port": {
@ -7866,9 +7866,9 @@
}
},
"eslint": {
"version": "7.21.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.21.0.tgz",
"integrity": "sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==",
"version": "7.22.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.22.0.tgz",
"integrity": "sha512-3VawOtjSJUQiiqac8MQc+w457iGLfuNGLFn8JmF051tTKbh5/x/0vlcEj8OgDCaw7Ysa2Jn8paGshV7x2abKXg==",
"dev": true,
"requires": {
"@babel/code-frame": "7.12.11",
@ -7888,7 +7888,7 @@
"file-entry-cache": "^6.0.1",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^5.0.0",
"globals": "^12.1.0",
"globals": "^13.6.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
@ -7896,7 +7896,7 @@
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash": "^4.17.20",
"lodash": "^4.17.21",
"minimatch": "^3.0.4",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
@ -7990,12 +7990,12 @@
}
},
"globals": {
"version": "12.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz",
"integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==",
"dev": true,
"requires": {
"type-fest": "^0.8.1"
"type-fest": "^0.20.2"
}
},
"has-flag": {
@ -8014,6 +8014,12 @@
"type-check": "~0.4.0"
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"optionator": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@ -8091,6 +8097,12 @@
"prelude-ls": "^1.2.1"
}
},
"type-fest": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -8386,9 +8398,9 @@
}
},
"eslint-plugin-prettier": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz",
"integrity": "sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ==",
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz",
"integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==",
"dev": true,
"requires": {
"prettier-linter-helpers": "^1.0.0"
@ -8564,9 +8576,9 @@
"dev": true
},
"eventsource": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
"integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz",
"integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==",
"dev": true,
"requires": {
"original": "^1.0.0"
@ -20813,9 +20825,9 @@
}
},
"yargs-parser": {
"version": "20.2.6",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.6.tgz",
"integrity": "sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA==",
"version": "20.2.7",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz",
"integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==",
"dev": true
},
"yocto-queue": {

View file

@ -17,14 +17,14 @@
"@storybook/addon-essentials": "^6.1.21",
"@storybook/addon-links": "^6.1.21",
"@storybook/vue": "^6.1.21",
"@vue/cli-service": "^4.5.11",
"@vue/cli-service": "^4.5.12",
"@vue/component-compiler-utils": "^3.2.0",
"@vue/eslint-config-standard": "^5.1.2",
"eslint": "^7.21.0",
"eslint": "^7.22.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-promise": "^4.3.1",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-vue": "^7.7.0",
@ -40,8 +40,8 @@
},
"repository": "github:andig/evcc",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.34",
"@fortawesome/free-solid-svg-icons": "^5.15.2",
"@fortawesome/fontawesome-svg-core": "^1.2.35",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/vue-fontawesome": "^2.0.0",
"axios": "^0.21.0",
"bootstrap": "^4.6.0",