Replace storybook with histoire (#5154)

This commit is contained in:
Michael Geers 2022-11-14 17:24:32 +01:00 • committed by GitHub
parent 7883c7f15c
commit ea2c3d53fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 3278 additions and 48475 deletions

View file

@ -9,8 +9,8 @@ module.exports = {
"plugin:vue/vue3-recommended",
"plugin:prettier/recommended",
"prettier",
"plugin:storybook/recommended",
],
parser: "vue-eslint-parser",
rules: {
"vue/require-default-prop": "off",
"vue/attribute-hyphenation": "off",

View file

@ -96,7 +96,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: "16"
node-version: "18"
- name: Get NPM cache dir
id: npm-cache-dir

View file

@ -1,16 +0,0 @@
module.exports = {
stories: ["../assets/js/**/*.stories.js"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
],
framework: "@storybook/vue3",
core: {
builder: "@storybook/builder-vite",
},
staticDirs: ["../assets"],
features: {
storyStoreV7: true,
},
};

View file

@ -1,4 +0,0 @@
<script>
window.global = window;
</script>
<meta name="theme-color" content="#020318" />

View file

@ -1,37 +0,0 @@
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap";
import smoothscroll from "smoothscroll-polyfill";
import { app } from "@storybook/vue3";
import VueNumber from "vue-number-animation";
import i18n from "../assets/js/i18n";
import "../assets/css/app.css";
import { watchThemeChanges } from "../assets/js/theme";
smoothscroll.polyfill();
app.use(i18n);
app.use(VueNumber);
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
backgrounds: {
default: "background",
values: [
{
name: "background",
value: "var(--evcc-background)",
},
{
name: "box",
value: "var(--evcc-box)",
},
],
},
};
watchThemeChanges();

View file

@ -5,6 +5,7 @@
[![Open in Visual Studio Code](https://img.shields.io/static/v1?logo=visualstudiocode&label=&message=Open%20in%20VS%20Code&labelColor=2c2c32&color=007acc&logoColor=007acc)](https://open.vscode.dev/evcc-io/evcc)
[![OSS hosting by cloudsmith](https://img.shields.io/badge/OSS%20hosting%20by-cloudsmith-blue?logo=cloudsmith)](https://cloudsmith.io/~evcc/packages/)
[![Latest Version](https://img.shields.io/github/release/evcc-io/evcc.svg)](https://github.com/evcc-io/evcc/releases)
<!-- [![Pulls from Docker Hub](https://img.shields.io/docker/pulls/andig/evcc.svg)](https://hub.docker.com/r/andig/evcc) -->
<!-- [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=48YVXXA7BDNC2) -->
@ -44,7 +45,7 @@ You'll find everything you need in our [documentation](https://docs.evcc.io/) (G
## Contribute
To build evcc from source, [Go][2] 1.18 and [Node][3] 16 are required.
To build evcc from source, [Go][2] 1.18 and [Node][3] 18 are required.
Build and run go backend. The UI becomes available at http://127.0.0.1:7070/

16
assets/histoire.setup.js Normal file
View file

@ -0,0 +1,16 @@
import { defineSetupVue3 } from "@histoire/plugin-vue";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap";
import smoothscroll from "smoothscroll-polyfill";
import VueNumber from "vue-number-animation";
import i18n from "./js/i18n";
import "./css/app.css";
import { watchThemeChanges } from "./js/theme";
smoothscroll.polyfill();
watchThemeChanges();
export const setupVue3 = defineSetupVue3(({ app }) => {
app.use(i18n);
app.use(VueNumber);
});

View file

@ -0,0 +1,13 @@
<script setup>
import BatteryIcon from "./BatteryIcon.vue";
</script>
<template>
<Story :layout="{ type: 'grid', width: 150 }">
<Variant title="empty"> <BatteryIcon :soc="10" /> </Variant>
<Variant title="quarter"> <BatteryIcon :soc="30" /> </Variant>
<Variant title="half"> <BatteryIcon :soc="50" /> </Variant>
<Variant title="three quarter"> <BatteryIcon :soc="70" /> </Variant>
<Variant title="full"> <BatteryIcon :soc="90" /> </Variant>
</Story>
</template>

View file

@ -1,134 +0,0 @@
import Energyflow from "./";
export default {
title: "Main/Energyflow",
component: Energyflow,
argTypes: {
pvPower: { control: { type: "range", min: 0, max: 10000, step: 100 } },
gridPower: { control: { type: "range", min: -5000, max: 20000, step: 100 } },
homePower: { control: { type: "range", min: 0, max: 30000, step: 100 } },
loadpointsPower: { control: { type: "range", min: 0, max: 20000, step: 100 } },
activeLoadpointsCount: { control: { type: "range", min: 0, max: 5, step: 1 } },
batteryPower: { control: { type: "range", min: -4000, max: 4000, step: 100 } },
batterySoC: { control: { type: "range", min: 0, max: 100, step: 1 } },
},
};
const Template = (args) => ({
setup() {
return { args };
},
components: { Energyflow },
template: '<Energyflow v-bind="args"></Energyflow>',
});
export const GridAndPV = Template.bind({});
GridAndPV.args = {
gridConfigured: true,
pvConfigured: true,
pvPower: 7300,
gridPower: -2300,
homePower: 800,
loadpointsPower: 4200,
activeLoadpointsCount: 3,
batteryConfigured: false,
siteTitle: "Home",
};
export const BatteryAndGrid = Template.bind({});
BatteryAndGrid.args = {
gridConfigured: true,
pvConfigured: true,
batteryConfigured: true,
pvPower: 0,
gridPower: 1200,
homePower: 2000,
batteryPower: 800,
batterySoC: 77,
siteTitle: "Home",
};
export const BatteryCharging = Template.bind({});
BatteryCharging.args = {
gridConfigured: true,
pvConfigured: true,
batteryConfigured: true,
pvPower: 5000,
gridPower: -1300,
homePower: 800,
loadpointsPower: 1400,
activeLoadpointsCount: 1,
batteryPower: -1500,
batterySoC: 75,
siteTitle: "Home",
};
export const GridPVAndBattery = Template.bind({});
GridPVAndBattery.args = {
gridConfigured: true,
pvConfigured: true,
batteryConfigured: true,
pvPower: 1000,
gridPower: 700,
homePower: 3300,
batteryPower: 1500,
batterySoC: 30,
siteTitle: "Home",
};
export const BatteryThresholds = Template.bind({});
BatteryThresholds.args = {
gridConfigured: true,
pvConfigured: true,
batteryConfigured: true,
activeLoadpointsCount: 1,
pvPower: 8700,
gridPower: -500,
loadpointsPower: 7500,
batteryPower: -700,
batterySoC: 95,
siteTitle: "Home",
};
export const PVThresholds = Template.bind({});
PVThresholds.args = {
gridConfigured: true,
pvConfigured: true,
batteryConfigured: true,
activeLoadpointsCount: 2,
pvPower: 300,
gridPower: 5500,
homePower: 1000,
loadpointsPower: 5600,
batteryPower: 800,
batterySoC: 76,
siteTitle: "Home",
};
export const GridOnly = Template.bind({});
GridOnly.args = {
gridConfigured: true,
pvConfigured: false,
batteryConfigured: false,
activeLoadpointsCount: 1,
pvPower: 0,
gridPower: -6200,
homePower: 1000,
loadpointsPower: 4200,
batteryPower: 0,
batterySoC: 0,
siteTitle: "Home",
};
export const LowEnergy = Template.bind({});
LowEnergy.args = {
gridConfigured: true,
pvConfigured: true,
batteryConfigured: true,
pvPower: 700,
gridPower: -300,
homePower: 300,
batteryPower: -100,
batterySoC: 55,
siteTitle: "Home",
};

View file

@ -0,0 +1,118 @@
<script setup>
import Energyflow from "./Energyflow.vue";
</script>
<template>
<Story :layout="{ type: 'grid', width: 800 }">
<Variant title="grid and pv">
<Energyflow
gridConfigured
pvConfigured
:pvPower="7300"
:gridPower="-2300"
:homePower="800"
:loadpointsPower="4200"
:activeLoadpointsCount="3"
siteTitle="Home"
/>
</Variant>
<Variant title="battery and grid">
<Energyflow
gridConfigured
pvConfigured
batteryConfigured
:pvPower="0"
:gridPower="1200"
:homePower="2000"
:batteryPower="800"
:batterySoC="77"
siteTitle="Home"
/>
</Variant>
<Variant title="battery charging">
<Energyflow
gridConfigured
pvConfigured
batteryConfigured
:pvPower="5000"
:gridPower="-1300"
:homePower="800"
:loadpointsPower="1400"
:activeLoadpointsCount="1"
:batteryPower="-1500"
:batterySoC="75"
siteTitle="Home"
/>
</Variant>
<Variant title="grid, pv and battery">
<Energyflow
gridConfigured
pvConfigured
batteryConfigured
:pvPower="1000"
:gridPower="700"
:homePower="3300"
:batteryPower="1500"
:batterySoC="30"
siteTitle="Home"
/>
</Variant>
<Variant title="battery thresholds">
<Energyflow
gridConfigured
pvConfigured
batteryConfigured
:pvPower="8700"
:gridPower="-500"
:loadpointsPower="7500"
:activeLoadpointsCount="2"
:batteryPower="-700"
:batterySoC="95"
siteTitle="Home"
/>
</Variant>
<Variant title="pv thresholds">
<Energyflow
gridConfigured
pvConfigured
batteryConfigured
:pvPower="300"
:gridPower="5500"
:homePower="1000"
:loadpointsPower="5600"
:activeLoadpointsCount="2"
:batteryPower="800"
:batterySoC="76"
siteTitle="Home"
/>
</Variant>
<Variant title="grid only">
<Energyflow
gridConfigured
pvConfigured
batteryConfigured
:pvPower="0"
:gridPower="6500"
:homePower="1000"
:loadpointsPower="5500"
:activeLoadpointsCount="1"
:batteryPower="0"
:batterySoC="0"
siteTitle="Home"
/>
</Variant>
<Variant title="low power">
<Energyflow
gridConfigured
pvConfigured
batteryConfigured
:pvPower="700"
:gridPower="-300"
:homePower="300"
:batteryPower="-100"
:batterySoC="55"
siteTitle="Home"
/>
</Variant>
</Story>
</template>

View file

@ -1,86 +0,0 @@
import Footer from "./Footer.vue";
export default {
title: "Main/Footer",
component: Footer,
argTypes: {},
};
const Template = (args) => ({
setup() {
return { args };
},
components: { Footer },
template: '<Footer v-bind="args"></Footer>',
});
export const KeinUpdate = Template.bind({});
KeinUpdate.args = {
version: { installed: "0.40" },
savings: {
since: 82800,
totalCharged: 15.231,
selfConsumptionCharged: 12.231,
selfConsumptionPercent: 80.3,
},
};
export const Sponsor = Template.bind({});
Sponsor.args = {
version: {
installed: "0.36",
},
savings: {
since: 82.8,
totalCharged: 21.0,
selfConsumptionCharged: 12.0,
selfConsumptionPercent: 54,
},
sponsor: "naltatis",
};
export const UpdateVerfuegbar = Template.bind({});
UpdateVerfuegbar.args = {
version: {
installed: "0.36",
available: "0.40",
releaseNotes: "Lorem ipsum dolor sit amet consectetur",
},
savings: {
since: 82.8,
totalCharged: 15.231,
selfConsumptionCharged: 15.0,
selfConsumptionPercent: 74,
},
};
export const Updater = Template.bind({});
Updater.args = {
version: {
installed: "0.36",
available: "0.40",
releaseNotes: "Lorem ipsum dolor sit amet consectetur",
hasUpdater: true,
},
savings: {
since: 82.8,
totalCharged: 0,
selfConsumptionCharged: 0,
selfConsumptionPercent: 0,
},
};
export const Upgrade = Template.bind({});
Upgrade.args = {
version: {
installed: "0.36",
available: "0.40",
hasUpdater: true,
},
savings: {
since: 82.8,
totalCharged: 0,
selfConsumptionCharged: 0,
selfConsumptionPercent: 0,
},
};

View file

@ -0,0 +1,23 @@
<script setup>
import { reactive } from "vue";
import Footer from "./Footer.vue";
const state = reactive({
version: {
installed: "0.401",
available: "0.401",
commit: "5ce7be4",
},
savings: {
selfConsumptionPercent: 88,
},
});
</script>
<template>
<Story>
<Variant title="default">
<Footer v-bind="state" />
</Variant>
</Story>
</template>

View file

@ -0,0 +1,9 @@
<script setup>
import LiveCommunity from "./LiveCommunity.vue";
</script>
<template>
<Story>
<LiveCommunity />
</Story>
</template>

View file

@ -1,97 +0,0 @@
import Loadpoint from "./Loadpoint.vue";
export default {
title: "Main/Loadpoint",
component: Loadpoint,
argTypes: {
mode: { control: { type: "inline-radio", options: ["off", "now", "minpv", "pv"] } },
remoteDisabled: { control: { type: "radio", options: ["", "soft", "hard"] } },
climater: { control: { type: "inline-radio", options: ["on", "heating", "cooling"] } },
},
};
const Template = (args) => ({
setup() {
return { args };
},
components: { Loadpoint },
template: '<Loadpoint v-bind="args"></Loadpoint>',
});
export const Base = Template.bind({});
Base.args = {
id: 0,
pvConfigured: true,
chargePower: 2800,
chargedEnergy: 11e3,
chargeDuration: 95 * 60,
vehiclePresent: true,
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
mode: "pv",
charging: true,
vehicleSoC: 66,
targetSoC: 90,
chargeCurrent: 7,
minCurrent: 6,
maxCurrent: 16,
activePhases: 2,
};
export const WithoutSoc = Template.bind({});
WithoutSoc.args = {
id: 0,
pvConfigured: true,
chargePower: 2800,
chargedEnergy: 7123,
chargeDuration: 95 * 60,
vehiclePresent: false,
enabled: true,
connected: true,
mode: "pv",
charging: true,
vehicleSoC: 66,
targetSoC: 90,
chargeCurrent: 7,
minCurrent: 6,
maxCurrent: 16,
activePhases: 2,
};
export const Idle = Template.bind({});
Idle.args = {
id: 0,
chargePower: 0,
vehiclePresent: false,
enabled: false,
connected: false,
mode: "off",
charging: false,
chargeCurrent: 0,
minCurrent: 6,
maxCurrent: 16,
activePhases: 0,
};
export const Disabled = Template.bind({});
Disabled.args = {
id: 0,
pvConfigured: true,
remoteDisabled: "soft",
remoteDisabledSource: "Sunny Home Manager",
vehiclePresent: true,
vehicleTitle: "Mein Auto",
chargedEnergy: 31211,
enabled: true,
mode: "now",
connected: true,
charging: false,
chargePower: 8112,
vehicleSoC: 66,
targetSoC: 100,
chargeCurrent: 7,
minCurrent: 6,
maxCurrent: 16,
activePhases: 3,
};

View file

@ -0,0 +1,57 @@
<script setup>
import Loadpoint from "./Loadpoint.vue";
import { reactive } from "vue";
const state = reactive({
id: 0,
pvConfigured: true,
chargePower: 2800,
chargedEnergy: 11e3,
chargeDuration: 95 * 60,
vehiclePresent: true,
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
mode: "pv",
charging: true,
vehicleSoC: 66,
targetSoC: 90,
chargeCurrent: 7,
minCurrent: 6,
maxCurrent: 16,
activePhases: 2,
});
</script>
<template>
<Story>
<Variant title="standard">
<Loadpoint v-bind="state" />
</Variant>
<Variant title="without soc">
<Loadpoint v-bind="state" vehicleTitle="" :vehiclePresent="false" />
</Variant>
<Variant title="idle">
<Loadpoint
v-bind="state"
:enabled="false"
:connected="false"
:vehiclePresent="false"
mode="off"
:charging="false"
:chargeCurrent="0"
/>
</Variant>
<Variant title="disabled">
<Loadpoint
v-bind="state"
remoteDisabled="soft"
remoteDisabledSource="Sunny Home Manager"
mode="now"
:enabled="false"
:charging="false"
:chargePower="0"
/>
</Variant>
</Story>
</template>

View file

@ -1,117 +0,0 @@
import LoadpointDetails from "./LoadpointDetails.vue";
import i18n from "../i18n";
export default {
title: "Main/LoadpointDetails",
component: LoadpointDetails,
argTypes: {
climater: { control: { type: "inline-radio", options: ["on", "heating", "cooling"] } },
},
};
const Template = (args, { argTypes }) => ({
i18n,
props: Object.keys(argTypes),
components: { LoadpointDetails },
template: '<LoadpointDetails v-bind="$props"></LoadpointDetails>',
});
export const Base = Template.bind({});
Base.args = {};
export const Charging = Template.bind({});
Charging.args = {
chargePower: 2800,
chargedEnergy: 11e3,
chargeDuration: 95 * 60,
};
export const Vehicle = Template.bind({});
Vehicle.args = {
chargePower: 2800,
chargedEnergy: 11e3,
chargeDuration: 95 * 60,
vehiclePresent: true,
chargeRemainingDuration: 5 * 3600,
};
export const VehicleRange = Template.bind({});
VehicleRange.args = {
chargePower: 2800,
chargedEnergy: 11e3,
chargeDuration: 95 * 60,
vehiclePresent: true,
vehicleRange: 240.123,
chargeRemainingDuration: 5 * 3600,
};
export const VehicleClimater = Template.bind({});
VehicleClimater.args = {
chargePower: 2800,
chargedEnergy: 11e3,
chargeDuration: 95 * 60,
vehiclePresent: true,
vehicleRange: 240.123,
chargeRemainingDuration: 5 * 3600,
climater: "on",
};
export const TimerPhaseScaleDown = Template.bind({});
TimerPhaseScaleDown.args = {
chargePower: 4400,
chargedEnergy: 11e3,
chargeDuration: 95 * 60,
vehiclePresent: true,
vehicleRange: 240.123,
chargeRemainingDuration: 5 * 3600,
activePhases: 3,
phaseAction: "scale1p",
phaseRemaining: 80,
pvAction: "enable",
pvRemaining: 90,
};
export const TimerPhaseScaleUp = Template.bind({});
TimerPhaseScaleUp.args = {
chargePower: 3900,
chargedEnergy: 11e3,
chargeDuration: 95 * 60,
vehiclePresent: true,
vehicleRange: 240.123,
chargeRemainingDuration: 5 * 3600,
activePhases: 1,
phaseAction: "scale3p",
phaseRemaining: 25,
pvAction: "inactive",
pvRemaining: 0,
};
export const TimerPvDisable = Template.bind({});
TimerPvDisable.args = {
chargePower: 1300,
chargedEnergy: 4e3,
chargeDuration: 95 * 60,
vehiclePresent: true,
vehicleRange: 240.123,
chargeRemainingDuration: 5 * 3600,
activePhases: 1,
phaseAction: "inactive",
phaseRemaining: 0,
pvAction: "disable",
pvRemaining: 55,
};
export const TimerPvEnable = Template.bind({});
TimerPvEnable.args = {
chargePower: 0,
chargedEnergy: 0,
chargeDuration: 0,
vehiclePresent: true,
vehicleRange: 240.123,
chargeRemainingDuration: 0,
activePhases: 1,
phaseAction: "inactive",
phaseRemaining: 0,
pvAction: "enable",
pvRemaining: 55,
};

View file

@ -1,21 +0,0 @@
import Mode from "./Mode.vue";
export default {
title: "Main/Mode",
component: Mode,
argTypes: {
mode: { control: { type: "inline-radio" }, options: ["off", "now", "minpv", "pv"] },
},
parameters: { backgrounds: { default: "box" } },
};
const Template = (args) => ({
setup() {
return { args };
},
components: { Mode },
template: '<Mode v-bind="args"></Mode>',
});
export const Base = Template.bind({});
Base.args = { mode: "pv" };

View file

@ -0,0 +1,28 @@
<script setup>
import { reactive } from "vue";
import Mode from "./Mode.vue";
const state = reactive({
mode: "pv",
});
</script>
<template>
<Story auto-props-disabled>
<Variant title="standard">
<Mode :mode="state.mode" />
<template #controls>
<HstSelect
v-model="state.mode"
title="mode"
:options="{
off: 'off',
now: 'now',
minpv: 'minpv',
pv: 'pv',
}"
/>
</template>
</Variant>
</Story>
</template>

View file

@ -1,73 +0,0 @@
import Notifications from "./Notifications.vue";
export default {
title: "Main/Notifications",
component: Notifications,
argTypes: {},
};
const Template = (args) => ({
setup() {
return { args };
},
components: { Notifications },
template: '<Notifications v-bind="args"></Notifications>',
});
function timeAgo(hours = 0, minutes = 0, seconds = 0) {
const date = new Date();
date.setHours(date.getHours() - hours);
date.setMinutes(date.getMinutes() - minutes);
date.setSeconds(date.getSeconds() - seconds);
return date;
}
export const Base = Template.bind({});
Base.args = {
notifications: [
{
message: "Server unavailable",
type: "error",
time: timeAgo(),
count: 1,
},
{
message: "charger out of sync: expected disabled, got enabled",
type: "warn",
count: 4,
time: timeAgo(0, 0, 42),
},
{
message: "Sponsortoken: x509: certificate has expired",
type: "error",
count: 1,
time: timeAgo(1, 12, 44),
},
{
message:
"Block device full: can not write to /tmp/evcc/foobarloremawefhwuiehfwuiehfwiauhefjkajowaeigjwalvmoweivwail",
type: "error",
count: 1,
time: timeAgo(1, 12, 44),
},
{
message: "charger out of sync: expected disabled, got enabled",
type: "warn",
count: 4,
time: timeAgo(1, 22, 0),
},
{
message: "vehicle remote charge start: invalid character '<' looking for beginning of value",
type: "warn",
count: 3,
time: timeAgo(4, 2, 0),
},
{
message:
"Amet irure quis incididunt voluptate esse. Commodo ea sunt est ipsum tempor nisi laboris voluptate labore elit laborum. Ex irure commodo reprehenderit consequat consequat do ad tempor aliquip deserunt eu. Laboris minim nostrud quis nisi. Dolor occaecat reprehenderit velit dolore exercitation cupidatat et voluptate. Nulla pariatur deserunt esse minim nisi nisi nulla. Sit eiusmod do incididunt sint minim pariatur aute.",
type: "warn",
count: 1,
time: timeAgo(5, 2, 44),
},
],
};

View file

@ -0,0 +1,70 @@
<script setup>
import { reactive } from "vue";
import Notifications from "./Notifications.vue";
const timeAgo = (hours = 0, minutes = 0, seconds = 0) => {
const date = new Date();
date.setHours(date.getHours() - hours);
date.setMinutes(date.getMinutes() - minutes);
date.setSeconds(date.getSeconds() - seconds);
return date;
};
const state = reactive({
notifications: [
{
message: "Server unavailable",
type: "error",
time: timeAgo(),
count: 1,
},
{
message: "charger out of sync: expected disabled, got enabled",
type: "warn",
count: 4,
time: timeAgo(0, 0, 42),
},
{
message: "Sponsortoken: x509: certificate has expired",
type: "error",
count: 1,
time: timeAgo(1, 12, 44),
},
{
message:
"Block device full: can not write to /tmp/evcc/foobarloremawefhwuiehfwuiehfwiauhefjkajowaeigjwalvmoweivwail",
type: "error",
count: 1,
time: timeAgo(1, 12, 44),
},
{
message: "charger out of sync: expected disabled, got enabled",
type: "warn",
count: 4,
time: timeAgo(1, 22, 0),
},
{
message:
"vehicle remote charge start: invalid character '<' looking for beginning of value",
type: "warn",
count: 3,
time: timeAgo(4, 2, 0),
},
{
message:
"Amet irure quis incididunt voluptate esse. Commodo ea sunt est ipsum tempor nisi laboris voluptate labore elit laborum. Ex irure commodo reprehenderit consequat consequat do ad tempor aliquip deserunt eu. Laboris minim nostrud quis nisi. Dolor occaecat reprehenderit velit dolore exercitation cupidatat et voluptate. Nulla pariatur deserunt esse minim nisi nisi nulla. Sit eiusmod do incididunt sint minim pariatur aute.",
type: "warn",
count: 1,
time: timeAgo(5, 2, 44),
},
],
});
</script>
<template>
<Story>
<Variant title="default">
<Notifications v-bind="state" />
</Variant>
</Story>
</template>

View file

@ -0,0 +1,9 @@
<script setup>
import OfflineIndicator from "./OfflineIndicator.vue";
</script>
<template>
<Story>
<OfflineIndicator />
</Story>
</template>

View file

@ -1,55 +0,0 @@
import Phases from "./Phases.vue";
export default {
title: "Main/Phases",
component: Phases,
argTypes: {},
parameters: { backgrounds: { default: "box" } },
};
const Template = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components: { Phases },
template: '<Phases v-bind="$props"></Phases>',
});
export const Base = Template.bind({});
Base.args = {
activePhases: 1,
minCurrent: 6,
maxCurrent: 32,
chargeCurrent: 10,
};
export const OnePhase = Template.bind({});
OnePhase.args = {
activePhases: 1,
minCurrent: 6,
maxCurrent: 16,
chargeCurrent: 6,
};
export const TwoPhase = Template.bind({});
TwoPhase.args = {
activePhases: 2,
minCurrent: 6,
maxCurrent: 16,
chargeCurrent: 8,
};
export const ThreePhases = Template.bind({});
ThreePhases.args = {
activePhases: 3,
minCurrent: 6,
maxCurrent: 16,
chargeCurrent: 12,
};
export const RealCurrents = Template.bind({});
RealCurrents.args = {
activePhases: 3,
minCurrent: 6,
maxCurrent: 32,
chargeCurrent: 16.5,
chargeCurrents: [15.2, 15.76, 14.5],
};

View file

@ -0,0 +1,37 @@
<script setup>
import Phases from "./Phases.vue";
import { reactive } from "vue";
const state = reactive({
phasesActive: 1,
minCurrent: 6,
maxCurrent: 16,
chargeCurrent: 8,
chargeCurrents: null,
});
</script>
<template>
<Story :layout="{ type: 'grid', width: 300 }">
<Variant title="one phase">
<Phases v-bind="state" />
</Variant>
<Variant title="two phase">
<Phases v-bind="state" :phasesActive="2" />
</Variant>
<Variant title="three phase">
<Phases v-bind="state" :phasesActive="3" />
</Variant>
<Variant title="real currents">
<Phases
v-bind="state"
:phasesActive="3"
:chargeCurrent="13"
:chargeCurrents="[11, 9, 12]"
/>
</Variant>
<Variant title="more available">
<Phases v-bind="state" :chargeCurrent="12" :chargeCurrents="[6, 0, 0]" />
</Variant>
</Story>
</template>

View file

@ -1,29 +0,0 @@
import Savings from "./Savings.vue";
export default {
title: "Main/Footer/Savings",
component: Savings,
argTypes: {},
};
const Template = (args) => ({
setup() {
return { args };
},
components: { Savings },
template: '<div class="d-flex justify-content-end"><Savings v-bind="args"></Savings></div>',
});
export const Default = Template.bind({});
Default.args = {
since: 82800,
totalCharged: 15231,
selfConsumptionCharged: 12231,
selfConsumptionPercent: 80.3,
};
export const NoCharge = Template.bind({});
NoCharge.args = {
since: 82800,
totalCharged: 0,
};

View file

@ -0,0 +1,31 @@
<script setup>
import { reactive } from "vue";
import Savings from "./Savings.vue";
const state = reactive({
totalCharged: 408.88948736396026,
selfConsumptionPercent: 80.3,
since: 1666776003,
amount: 11.924127889686181,
effectivePrice: 0.22583777338821223,
gridCharged: 313.4964642464708,
selfConsumptionCharged: 95.39302311748945,
gridPrice: 0.34,
feedInPrice: 0.13,
currency: "EUR",
});
</script>
<template>
<Story>
<Variant title="no sponsor">
<Savings v-bind="state" />
</Variant>
<Variant title="sponsor">
<Savings v-bind="state" sponsor="naltatis" />
</Variant>
<Variant title="no data">
<Savings />
</Variant>
</Story>
</template>

View file

@ -0,0 +1,16 @@
<script setup>
import SavingsTile from "./SavingsTile.vue";
</script>
<template>
<Story>
<SavingsTile
icon="coinjar"
title="Ersparnis"
value="14,2"
unit="€"
sub1="gegenüber Netzbezug"
sub2="seit Dezember 2022"
/>
</Story>
</template>

View file

@ -1,105 +0,0 @@
import Site from "./Site.vue";
export default {
title: "Main/Site",
component: Site,
argTypes: {},
};
const Template = (args) => ({
setup() {
return { args };
},
components: { Site },
template: '<Site v-bind="args"></Site>',
});
export const Base = Template.bind({});
Base.args = {
gridConfigured: true,
pvConfigured: true,
gridPower: 1340,
pvPower: 6420,
batteryConfigured: true,
batteryPower: 800,
batterySoC: 66,
loadpoints: [],
};
export const Single = Template.bind({});
Single.args = {
gridConfigured: true,
pvConfigured: true,
gridPower: -2300,
pvPower: 7000,
batteryConfigured: true,
batteryPower: -2000,
batterySoC: 24,
loadpoints: [
{
title: "Ladepunkt 1",
mode: "now",
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: true,
charging: true,
vehicleSoC: 66,
vehicleRange: 344,
targetSoC: 90,
chargeRemainingDuration: 999,
chargePower: 11232,
chargeDuration: 123982,
chargedEnergy: 23213,
},
],
};
export const Multi = Template.bind({});
Multi.args = {
gridConfigured: true,
pvConfigured: true,
gridPower: 4000,
pvPower: 11500,
batteryConfigured: false,
batteryPower: 0,
batterySoC: 0,
loadpoints: [
{
title: "Ladepunkt 1",
mode: "now",
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: true,
charging: true,
vehicleSoC: 66,
vehicleRange: 344,
targetSoC: 90,
chargeRemainingDuration: 999,
chargePower: 11232,
chargeDuration: 123982,
chargedEnergy: 23213,
},
{
title: "Ladepunkt 2",
mode: "pv",
vehicleTitle: "Mein anderes Auto",
},
{
title: "Ladepunkt 3",
mode: "now",
vehicleTitle: "Mein drittes Auto",
enabled: true,
connected: true,
charging: true,
vehicleSoC: 22,
vehicleRange: 34,
targetSoC: 100,
chargeRemainingDuration: 22,
chargePower: 1423,
chargeDuration: 243,
chargedEnergy: 235,
},
],
};

View file

@ -0,0 +1,14 @@
<script setup>
import Sponsor from "./Sponsor.vue";
</script>
<template>
<Story :layout="{ type: 'grid', width: 600 }">
<Variant title="no sponsor">
<Sponsor />
</Variant>
<Variant title="sponsor">
<Sponsor sponsor="naltatis" />
</Variant>
</Story>
</template>

View file

@ -1,53 +0,0 @@
import "bootstrap";
import TopNavigation from "./TopNavigation.vue";
export default {
title: "Main/TopNavigation",
component: TopNavigation,
parameters: {
backgrounds: {
default: "light",
},
},
};
const Template = (args) => ({
setup() {
return { args };
},
components: { TopNavigation },
template: `<div class="d-flex justify-content-end" style="padding-bottom: 18rem">
<TopNavigation v-bind="args"></TopNavigation>
</div>`,
});
export const Default = Template.bind({});
Default.args = {};
export const VehicleLogins = Template.bind({});
VehicleLogins.args = {
vehicleLogins: {
["Mercedes EQS"]: {
authenticated: true,
uri: "https://login-provider-a.test/",
},
["Nissan Leaf Pro"]: {
authenticated: false,
uri: "https://login-provider-b.test/",
},
},
};
export const PendingVehicleLogins = Template.bind({});
PendingVehicleLogins.args = {
vehicleLogins: {
["Mercedes EQS"]: {
authenticated: true,
uri: "https://login-provider-a.test/",
},
["Nissan Leaf Pro"]: {
authenticated: true,
uri: "https://login-provider-b.test/",
},
},
};

View file

@ -0,0 +1,39 @@
<script setup>
import TopNavigation from "./TopNavigation.vue";
</script>
<template>
<Story title="Top Navigation">
<Variant title="standard">
<TopNavigation />
</Variant>
<Variant title="vehicle logins">
<TopNavigation
:vehicleLogins="{
['Mercedes EQS']: {
authenticated: true,
uri: 'https://login-provider-a.test/',
},
['Nissan Leaf Pro']: {
authenticated: true,
uri: 'https://login-provider-b.test/',
},
}"
/>
</Variant>
<Variant title="pending vehicle logins">
<TopNavigation
:vehicleLogins="{
['Mercedes EQS']: {
authenticated: true,
uri: 'https://login-provider-a.test/',
},
['Nissan Leaf Pro']: {
authenticated: false,
uri: 'https://login-provider-b.test/',
},
}"
/>
</Variant>
</Story>
</template>

View file

@ -1,265 +0,0 @@
import Vehicle from "./Vehicle.vue";
export default {
title: "Main/Vehicle",
component: Vehicle,
parameters: { backgrounds: { default: "box" } },
};
const Template = (args) => ({
setup() {
return { args };
},
components: { Vehicle },
template: '<Vehicle v-bind="args"></Vehicle>',
parameters: { backgrounds: { default: "box" } },
});
export const Base = Template.bind({});
Base.args = {
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: true,
vehicleSoC: 42,
vehicleRange: 231,
targetSoC: 90,
socBasedCharging: true,
id: 0,
};
export const Connected = Template.bind({});
Connected.args = {
vehicleTitle: "Mein Auto",
enabled: false,
connected: true,
vehiclePresent: true,
charging: false,
vehicleSoC: 66,
targetSoC: 90,
socBasedCharging: true,
id: 0,
};
export const ReadyToCharge = Template.bind({});
ReadyToCharge.args = {
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: true,
charging: false,
vehicleSoC: 66,
targetSoC: 90,
socBasedCharging: true,
id: 0,
};
export const Charging = Template.bind({});
Charging.args = {
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: true,
charging: true,
vehicleSoC: 66,
targetSoC: 90,
socBasedCharging: true,
id: 0,
};
const hoursFromNow = function (hours) {
const now = new Date();
now.setHours(now.getHours() + hours);
return now.toISOString();
};
export const TargetChargePlanned = Template.bind({});
TargetChargePlanned.args = {
vehicleTitle: "Mein Auto",
enabled: false,
connected: true,
vehiclePresent: true,
vehicleSoC: 31,
minSoC: 20,
charging: false,
targetTimeActive: false,
targetSoC: 45,
targetTime: hoursFromNow(14),
socBasedCharging: true,
id: 0,
};
export const TargetChargeActive = Template.bind({});
TargetChargeActive.args = {
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: true,
vehicleSoC: 66,
minSoC: 30,
charging: true,
targetTimeActive: true,
targetSoC: 80,
targetTime: hoursFromNow(2),
socBasedCharging: true,
id: 0,
};
export const MinCharge = Template.bind({});
MinCharge.args = {
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: true,
vehicleSoC: 17,
minSoC: 20,
charging: true,
targetSoC: 90,
socBasedCharging: true,
id: 0,
};
export const VehicleTargetSoc = Template.bind({});
VehicleTargetSoc.args = {
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: true,
vehicleTargetSoC: 80,
vehicleSoC: 66,
charging: true,
targetSoC: 90,
socBasedCharging: true,
id: 0,
};
export const TimerPvEnable = Template.bind({});
TimerPvEnable.args = {
vehicleTitle: "Mein Auto",
enabled: false,
connected: true,
vehiclePresent: true,
vehicleSoC: 17,
charging: false,
targetSoC: 90,
phaseAction: "inactive",
phaseRemainingInterpolated: 0,
pvAction: "enable",
pvRemainingInterpolated: 32,
socBasedCharging: true,
id: 0,
};
export const TimerPvDisable = Template.bind({});
TimerPvDisable.args = {
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: true,
vehicleSoC: 17,
charging: true,
targetSoC: 90,
phaseAction: "inactive",
phaseRemainingInterpolated: 0,
pvAction: "disable",
pvRemainingInterpolated: 155,
socBasedCharging: true,
id: 0,
};
export const UnknownVehicleConnected = Template.bind({});
UnknownVehicleConnected.args = {
enabled: false,
connected: true,
vehiclePresent: false,
targetSoC: 90,
socBasedCharging: false,
id: 0,
};
export const UnknownVehicleReadyToCharge = Template.bind({});
UnknownVehicleReadyToCharge.args = {
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: false,
charging: false,
targetSoC: 100,
socBasedCharging: false,
id: 0,
};
export const UnknownVehicleCharging = Template.bind({});
UnknownVehicleCharging.args = {
vehicleTitle: "Mein Auto",
enabled: true,
connected: true,
vehiclePresent: false,
charging: true,
targetSoC: 90,
socBasedCharging: false,
id: 0,
};
export const OfflineVehicleCharging = Template.bind({});
OfflineVehicleCharging.args = {
vehicleTitle: "Polestar 2",
enabled: true,
connected: true,
vehiclePresent: true,
vehicleFeatureOffline: true,
vehicleCapacity: 72,
chargedEnergy: 14123,
charging: true,
targetSoC: 90,
socBasedCharging: false,
id: 0,
};
export const OfflineVehicleTargetEnergy = Template.bind({});
OfflineVehicleTargetEnergy.args = {
vehicleTitle: "Polestar 2",
enabled: true,
connected: true,
vehiclePresent: true,
vehicleFeatureOffline: true,
vehicleCapacity: 72,
chargedEnergy: 14123,
targetEnergy: 30,
charging: true,
socBasedCharging: false,
id: 0,
};
export const Disconnected = Template.bind({});
Disconnected.args = {
vehicleTitle: "Mein Auto",
connected: false,
vehiclePresent: false,
targetSoC: 75,
id: 0,
};
export const DisconnectedKnownSoc = Template.bind({});
DisconnectedKnownSoc.args = {
vehicleTitle: "Mein Auto",
connected: false,
enabled: false,
vehiclePresent: true,
vehicleSoC: 17,
targetSoC: 60,
id: 0,
};
export const SwitchBetweenVehicles = Template.bind({});
SwitchBetweenVehicles.args = {
vehicleTitle: "Weißes Model 3",
vehicles: ["Blauer e-Golf", "Weißes Model 3"],
enabled: true,
connected: true,
vehiclePresent: true,
vehicleSoC: 42,
vehicleRange: 231,
targetSoC: 90,
id: 0,
};

View file

@ -0,0 +1,111 @@
<script setup>
import { reactive } from "vue";
import Vehicle from "./Vehicle.vue";
const state = reactive({
vehicleTitle: "Mein Auto",
enabled: false,
connected: true,
vehiclePresent: true,
vehicleSoC: 42,
vehicleRange: 231,
targetSoC: 90,
vehicleCapacity: 72,
chargedEnergy: 14123,
socBasedCharging: true,
id: 0,
});
const hoursFromNow = function (hours) {
const now = new Date();
now.setHours(now.getHours() + hours);
return now.toISOString();
};
</script>
<template>
<Story>
<Variant title="disconnected">
<Vehicle v-bind="state" :connected="false" />
</Variant>
<Variant title="connected">
<Vehicle v-bind="state" />
</Variant>
<Variant title="ready">
<Vehicle v-bind="state" enabled />
</Variant>
<Variant title="charging">
<Vehicle v-bind="state" enabled charging />
</Variant>
<Variant title="charging">
<Vehicle v-bind="state" enabled charging />
</Variant>
<Variant title="unknown vehicle">
<Vehicle
v-bind="state"
enabled
charging
:vehiclePresent="false"
:socBasedCharging="false"
:vehicleCapacity="null"
mode="pv"
/>
</Variant>
<Variant title="offline vehicle">
<Vehicle
v-bind="state"
enabled
charging
vehicleTitle="Opel Corsa-e"
:socBasedCharging="false"
:vehicleCapacity="72"
vehicleFeatureOffline
mode="pv"
/>
</Variant>
<Variant title="offline vehicle with target">
<Vehicle
v-bind="state"
enabled
charging
vehicleTitle="Opel Corsa-e"
:socBasedCharging="false"
:vehicleCapacity="72"
:targetEnergy="30"
vehicleFeatureOffline
mode="pv"
/>
</Variant>
<Variant title="vehicle limit">
<Vehicle v-bind="state" enabled charging :vehicleTargetSoC="80" />
</Variant>
<Variant title="vehicle limit reached">
<Vehicle v-bind="state" enabled :vehicleTargetSoC="80" :vehicleSoC="80" />
</Variant>
<Variant title="target charge planned">
<Vehicle v-bind="state" :targetTime="hoursFromNow(14)" mode="pv" />
</Variant>
<Variant title="target charge active">
<Vehicle v-bind="state" enabled charging :targetTime="hoursFromNow(14)" mode="pv" />
</Variant>
<Variant title="pv enable timer">
<Vehicle v-bind="state" pvAction="enable" :pvRemainingInterpolated="32" />
</Variant>
<Variant title="pv disable timer">
<Vehicle
v-bind="state"
enabled
charging
pvAction="disable"
:pvRemainingInterpolated="155"
/>
</Variant>
<Variant title="vehicle switch">
<Vehicle
v-bind="state"
vehicleTitle="Blauer e-Golf"
:vehicles="['Blauer e-Golf', 'Weißes Model 3']"
/>
</Variant>
</Story>
</template>

View file

@ -1,53 +1,32 @@
<script setup>
import { reactive } from "vue";
import Version from "./Version.vue";
export default {
title: "Main/Footer/Version",
component: Version,
argTypes: {},
};
const Template = (args) => ({
setup() {
return { args };
},
components: { Version },
template: '<Version v-bind="args"></Version>',
const state = reactive({
installed: "0.141",
available: "0.141",
});
const releaseNotes =
'<h1>0.48</h1><p>Bug fixes:</p><ul><li>Withdraw Kia and Hyundai apis (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="817450535" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/699" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/699/hovercard" href="https://github.com/evcc-io/evcc/pull/699">#699</a>)</li><li>Simplify Tesla integration and fix upstream changes (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="817525274" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/700" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/700/hovercard" href="https://github.com/evcc-io/evcc/pull/700">#700</a>)</li><li>SHM: Check connected status (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="811567860" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/673" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/673/hovercard" href="https://github.com/evcc-io/evcc/pull/673">#673</a>)</li></ul><p>Enhancements:</p><ul><li>Add Seat api (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="812885392" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/681" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/681/hovercard" href="https://github.com/evcc-io/evcc/pull/681">#681</a>)</li><li>Add Skoda api (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="812883796" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/680" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/680/hovercard" href="https://github.com/evcc-io/evcc/pull/680">#680</a>)</li><li>Add Peugeot/Opel/Citroen api (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="815612446" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/692" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/692/hovercard" href="https://github.com/evcc-io/evcc/pull/692">#692</a>)</li><li>KEBA: Support mA current resolution adjustments (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="801358501" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/646" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/646/hovercard" href="https://github.com/evcc-io/evcc/pull/646">#646</a>)</li></ul>';
'<h1>0.141</h1><p>Bug fixes:</p><ul><li>Withdraw Kia and Hyundai apis (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="817450535" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/699" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/699/hovercard" href="https://github.com/evcc-io/evcc/pull/699">#699</a>)</li><li>Simplify Tesla integration and fix upstream changes (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="817525274" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/700" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/700/hovercard" href="https://github.com/evcc-io/evcc/pull/700">#700</a>)</li><li>SHM: Check connected status (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="811567860" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/673" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/673/hovercard" href="https://github.com/evcc-io/evcc/pull/673">#673</a>)</li></ul><p>Enhancements:</p><ul><li>Add Seat api (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="812885392" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/681" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/681/hovercard" href="https://github.com/evcc-io/evcc/pull/681">#681</a>)</li><li>Add Skoda api (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="812883796" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/680" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/680/hovercard" href="https://github.com/evcc-io/evcc/pull/680">#680</a>)</li><li>Add Peugeot/Opel/Citroen api (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="815612446" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/692" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/692/hovercard" href="https://github.com/evcc-io/evcc/pull/692">#692</a>)</li><li>KEBA: Support mA current resolution adjustments (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="801358501" data-permission-text="Title is private" data-url="https://github.com/evcc-io/evcc/issues/646" data-hovercard-type="pull_request" data-hovercard-url="/evcc-io/evcc/pull/646/hovercard" href="https://github.com/evcc-io/evcc/pull/646">#646</a>)</li></ul>';
</script>
export const AktuelleVersion = Template.bind({});
AktuelleVersion.args = {
installed: "0.48",
available: "0.48",
};
export const Download = Template.bind({});
Download.args = {
installed: "0.47",
available: "0.48",
releaseNotes,
};
export const Updater = Template.bind({});
Updater.args = {
installed: "0.47",
available: "0.48",
releaseNotes,
hasUpdater: true,
};
export const KeineReleaseNotes = Template.bind({});
KeineReleaseNotes.args = {
installed: "0.36",
available: "0.40",
hasUpdater: true,
};
export const Nightly = Template.bind({});
Nightly.args = {
installed: "0.40",
available: "0.40",
commit: "5ce7be4",
};
<template>
<Story :layout="{ type: 'grid', width: 600 }">
<Variant title="latest">
<Version v-bind="state" />
</Variant>
<Variant title="nightly">
<Version v-bind="state" commit="5ce7be4" />
</Variant>
<Variant title="update available">
<Version v-bind="state" available="0.142" :releaseNotes="releaseNotes" />
</Variant>
<Variant title="auto updater">
<Version v-bind="state" available="0.142" :releaseNotes="releaseNotes" hasUpdater />
</Variant>
<Variant title="no release notes">
<Version v-bind="state" available="0.142" />
</Variant>
</Story>
</template>

View file

@ -40,10 +40,13 @@ function updateTheme() {
// update iOS title bar color
const themeColors = { light: "#f3f3f7", dark: "#020318" };
document.querySelector("meta[name=theme-color]").setAttribute("content", themeColors[theme]);
const $metaThemeColor = document.querySelector("meta[name=theme-color]");
if ($metaThemeColor) {
$metaThemeColor.setAttribute("content", themeColors[theme]);
}
// toggle the class on html root
const $html = document.querySelector(":root");
const $html = document.querySelector("html");
$html.classList.add("no-transitions");
$html.classList.toggle("dark", theme === THEME_DARK);
window.requestAnimationFrame(function () {

70
dist/assets/index.2a941499.js 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

2
dist/index.html vendored
View file

@ -20,7 +20,7 @@
<meta name="theme-color" content="#020318" />
<title>evcc</title>
<script type="module" crossorigin src="./assets/index.9a0a4bb1.js"></script>
<script type="module" crossorigin src="./assets/index.2a941499.js"></script>
<link rel="stylesheet" href="./assets/index.f6aa52fd.css">
</head>

8
histoire.config.js Normal file
View file

@ -0,0 +1,8 @@
import { defineConfig } from "histoire";
import { HstVue } from "@histoire/plugin-vue";
export default defineConfig({
plugins: [HstVue()],
setupFile: "./histoire.setup.js",
viteNodeInlineDeps: [/!axios/],
});

49814
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,8 +7,7 @@
"test": "",
"lint": "prettier assets './**/*.{yml,yaml,toml}' --write && eslint assets/**/*.js assets/**/*.vue --fix",
"dev": "vite",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
"histoire": "histoire dev"
},
"main": "index.js",
"dependencies": {
@ -28,35 +27,29 @@
},
"devDependencies": {
"@babel/core": "^7.17.2",
"@storybook/addon-actions": "^6.5.9",
"@storybook/addon-essentials": "^6.5.9",
"@storybook/addon-interactions": "^6.5.9",
"@storybook/addon-links": "^6.5.9",
"@storybook/builder-vite": "^0.2.2",
"@storybook/testing-library": "^0.0.13",
"@storybook/vue3": "^6.5.9",
"@histoire/plugin-vue": "^0.11.6",
"@vue/compiler-sfc": "^3.2.30",
"babel-loader": "^8.2.3",
"eslint": "^8.21.0",
"eslint": "^8.27.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-standard": "^5.0.0",
"eslint-plugin-storybook": "^0.6.1",
"eslint-plugin-vue": "^9.3.0",
"histoire": "^0.11.6",
"html-webpack-plugin": "^5.5.0",
"postcss-custom-media": "^8.0.2",
"prettier": "^2.5.1",
"prettier-plugin-toml": "^0.3.1",
"vite": "^3.0.4",
"vite-plugin-toml": "^0.4.0",
"vue-eslint-parser": "^9.1.0",
"vue-loader": "^17.0.0"
},
"engines": {
"npm": ">=8.0.0",
"node": ">=16.0.0"
"node": ">=18.0.0"
},
"license": "MIT",
"repository": "github:evcc-io/evcc"