Convert battery icon to vue component (#2726)
* feat: use vue battery icon * Add battery icon stories * feat: use battery state if available10.9-maintenance
parent
1301f97a4f
commit
e0209c6b59
|
@ -50,7 +50,7 @@ export const decorators = [
|
||||||
template: `
|
template: `
|
||||||
<div style="margin: 1rem;">
|
<div style="margin: 1rem;">
|
||||||
<link rel="stylesheet" href="/css/opensans_webfontkit/fonts.css" />
|
<link rel="stylesheet" href="/css/opensans_webfontkit/fonts.css" />
|
||||||
<link rel="stylesheet" href="/css/main.css" />
|
<link rel="stylesheet" href="/css/theme.css" />
|
||||||
<story />
|
<story />
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import vueI18n from "./vueI18n.js";
|
||||||
import BatteryLegend from "./quad-status/BatteryLegend.vue";
|
import BatteryLegend from "./quad-status/BatteryLegend.vue";
|
||||||
import BetaflightLogo from "./betaflight-logo/BetaflightLogo.vue";
|
import BetaflightLogo from "./betaflight-logo/BetaflightLogo.vue";
|
||||||
import StatusBar from "./status-bar/StatusBar.vue";
|
import StatusBar from "./status-bar/StatusBar.vue";
|
||||||
|
import BatteryIcon from "./quad-status/BatteryIcon.vue";
|
||||||
|
|
||||||
// Most of the global objects can go here at first.
|
// Most of the global objects can go here at first.
|
||||||
// It's a bit of overkill for simple components,
|
// It's a bit of overkill for simple components,
|
||||||
|
@ -38,6 +39,7 @@ i18next.on('initialized', function() {
|
||||||
BatteryLegend,
|
BatteryLegend,
|
||||||
BetaflightLogo,
|
BetaflightLogo,
|
||||||
StatusBar,
|
StatusBar,
|
||||||
|
BatteryIcon,
|
||||||
},
|
},
|
||||||
data: betaflightModel,
|
data: betaflightModel,
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import BatteryIcon from "./BatteryIcon.vue";
|
||||||
|
|
||||||
|
// More on default export: https://storybook.js.org/docs/vue/writing-stories/introduction#default-export
|
||||||
|
export default {
|
||||||
|
title: "Battery Icon",
|
||||||
|
component: BatteryIcon,
|
||||||
|
};
|
||||||
|
|
||||||
|
// More on component templates: https://storybook.js.org/docs/vue/writing-stories/introduction#using-args
|
||||||
|
const Template = (_args, { argTypes }) => ({
|
||||||
|
props: Object.keys(argTypes),
|
||||||
|
components: { BatteryIcon },
|
||||||
|
template: '<battery-icon v-bind="$props" />',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const OK = Template.bind({});
|
||||||
|
OK.args = {
|
||||||
|
voltage: 16,
|
||||||
|
vbatmincellvoltage: 3.7,
|
||||||
|
vbatmaxcellvoltage: 4.2,
|
||||||
|
vbatwarningcellvoltage: 3.8,
|
||||||
|
};
|
||||||
|
export const Warning = Template.bind({});
|
||||||
|
Warning.args = {
|
||||||
|
...OK.args,
|
||||||
|
voltage: 15.1,
|
||||||
|
};
|
||||||
|
export const Empty = Template.bind({});
|
||||||
|
Empty.args = {
|
||||||
|
...OK.args,
|
||||||
|
voltage: 14,
|
||||||
|
};
|
|
@ -0,0 +1,136 @@
|
||||||
|
<template>
|
||||||
|
<div class="battery-icon">
|
||||||
|
<div class="quad-status-contents">
|
||||||
|
<div
|
||||||
|
class="battery-status"
|
||||||
|
:class="classes"
|
||||||
|
:style="{ width: batteryWidth + '%' }"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
const NO_BATTERY_VOLTAGE_MAXIMUM = 1.8; // Maybe is better to add a call to MSP_BATTERY_STATE but is not available for all versions
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
voltage: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
vbatmincellvoltage: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
vbatmaxcellvoltage: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
vbatwarningcellvoltage: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
nbCells() {
|
||||||
|
let nbCells = Math.floor(this.voltage / this.vbatmaxcellvoltage) + 1;
|
||||||
|
if (this.voltage === 0) {
|
||||||
|
nbCells = 1;
|
||||||
|
}
|
||||||
|
return nbCells;
|
||||||
|
},
|
||||||
|
min() {
|
||||||
|
return this.vbatmincellvoltage * this.nbCells;
|
||||||
|
},
|
||||||
|
max() {
|
||||||
|
return this.vbatmaxcellvoltage * this.nbCells;
|
||||||
|
},
|
||||||
|
warn() {
|
||||||
|
return this.vbatwarningcellvoltage * this.nbCells;
|
||||||
|
},
|
||||||
|
isEmpty() {
|
||||||
|
return (
|
||||||
|
this.voltage < this.min && this.voltage > NO_BATTERY_VOLTAGE_MAXIMUM
|
||||||
|
);
|
||||||
|
},
|
||||||
|
classes() {
|
||||||
|
if (this.batteryState) {
|
||||||
|
return {
|
||||||
|
"state-ok": this.batteryState === 0,
|
||||||
|
"state-warning": this.batteryState === 1,
|
||||||
|
"state-empty": this.batteryState === 2,
|
||||||
|
// TODO: BATTERY_NOT_PRESENT
|
||||||
|
// TODO: BATTERY_INIT
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const isWarning = this.voltage < this.warn;
|
||||||
|
return {
|
||||||
|
"state-empty": this.isEmpty,
|
||||||
|
"state-warning": isWarning,
|
||||||
|
"state-ok": !this.isEmpty && !isWarning,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
batteryWidth() {
|
||||||
|
return this.isEmpty
|
||||||
|
? 100
|
||||||
|
: ((this.voltage - this.min) / (this.max - this.min)) * 100;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.quad-status-contents {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 14px;
|
||||||
|
height: 10px;
|
||||||
|
width: 31px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quad-status-contents progress::-webkit-progress-bar {
|
||||||
|
height: 12px;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quad-status-contents progress::-webkit-progress-value {
|
||||||
|
background-color: #bcf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.battery-icon {
|
||||||
|
background-image: url(../../images/icons/cf_icon_bat_grey.svg);
|
||||||
|
background-size: contain;
|
||||||
|
background-position: center;
|
||||||
|
display: inline-block;
|
||||||
|
height: 30px;
|
||||||
|
width: 60px;
|
||||||
|
transition: none;
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-left: -4px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.battery-status {
|
||||||
|
height: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes error-blinker {
|
||||||
|
0% {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-color: var(--error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.battery-status.state-ok {
|
||||||
|
background-color: #59aa29;
|
||||||
|
}
|
||||||
|
.battery-status.state-warning {
|
||||||
|
background-color: var(--error);
|
||||||
|
}
|
||||||
|
|
||||||
|
.battery-status.state-empty {
|
||||||
|
animation: error-blinker 1s linear infinite;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,8 +1,8 @@
|
||||||
import BatteryLegend from './BatteryLegend.vue';
|
import BatteryLegend from "./BatteryLegend.vue";
|
||||||
|
|
||||||
// More on default export: https://storybook.js.org/docs/vue/writing-stories/introduction#default-export
|
// More on default export: https://storybook.js.org/docs/vue/writing-stories/introduction#default-export
|
||||||
export default {
|
export default {
|
||||||
title: 'Battery Legend',
|
title: "Battery Legend",
|
||||||
component: BatteryLegend,
|
component: BatteryLegend,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,3 @@
|
||||||
|
|
||||||
@keyframes error-blinker {
|
|
||||||
0% {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
background-color: var(--error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:root {
|
|
||||||
--accent: #ffbb00;
|
|
||||||
--error: red;
|
|
||||||
--subtleAccent: silver;
|
|
||||||
--quietText: #ffffff;
|
|
||||||
--quietHeader: #828885;
|
|
||||||
--defaultText: #000000;
|
|
||||||
--subtleText: #c0c0c0;
|
|
||||||
--mutedText: #616161;
|
|
||||||
--linkText: #2e2ebb;
|
|
||||||
--boxBackground: #ffffff;
|
|
||||||
--alternativeBackground: #f9f9f9;
|
|
||||||
--sideBackground: #ffffff;
|
|
||||||
--ledAccent: #adadad;
|
|
||||||
--ledBackground: #e9e9e9;
|
|
||||||
--gimbalBackground: #eee;
|
|
||||||
--gimbalCrosshair: var(--subtleAccent);
|
|
||||||
--switcherysecond: #c4c4c4;
|
|
||||||
--pushedButton-background: #c4c4c4;
|
|
||||||
--pushedButton-fontColor: #000000;
|
|
||||||
--hoverButton-background: #ffcc3e;
|
|
||||||
--superSubtleAccent: #CCCCCC;
|
|
||||||
--accentBorder: #ffbb00;
|
|
||||||
}
|
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -621,46 +587,7 @@ input[type="number"] {
|
||||||
text-shadow: 0 1px rgba(0, 0, 0, 1.0);
|
text-shadow: 0 1px rgba(0, 0, 0, 1.0);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.quad-status-contents {
|
|
||||||
display: none;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-left: 14px;
|
|
||||||
height: 10px;
|
|
||||||
width: 31px;
|
|
||||||
progress {
|
|
||||||
&::-webkit-progress-bar {
|
|
||||||
height: 12px;
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
&::-webkit-progress-value {
|
|
||||||
background-color: #bcf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.battery-status {
|
|
||||||
height: 11px;
|
|
||||||
}
|
|
||||||
.battery-status.state-ok {
|
|
||||||
background-color: #59AA29;
|
|
||||||
}
|
|
||||||
.battery-status.state-warning {
|
|
||||||
background-color: var(--error);
|
|
||||||
}
|
|
||||||
.battery-status.state-empty {
|
|
||||||
animation: error-blinker 1s linear infinite;
|
|
||||||
}
|
|
||||||
.battery-icon {
|
|
||||||
background-image: url(../images/icons/cf_icon_bat_grey.svg);
|
|
||||||
background-size: contain;
|
|
||||||
background-position: center;
|
|
||||||
display: inline-block;
|
|
||||||
height: 30px;
|
|
||||||
width: 60px;
|
|
||||||
transition: none;
|
|
||||||
margin-top: 4px;
|
|
||||||
margin-left: -4px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.armedicon {
|
.armedicon {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
* Main theme colors
|
||||||
|
* This file is left as css on purpose to make it easier to work without
|
||||||
|
* the need to compile the less files and still can be use in storybook
|
||||||
|
*/
|
||||||
|
:root {
|
||||||
|
--accent: #ffbb00;
|
||||||
|
--error: red;
|
||||||
|
--subtleAccent: silver;
|
||||||
|
--quietText: #ffffff;
|
||||||
|
--quietHeader: #828885;
|
||||||
|
--defaultText: #000000;
|
||||||
|
--subtleText: #c0c0c0;
|
||||||
|
--mutedText: #616161;
|
||||||
|
--linkText: #2e2ebb;
|
||||||
|
--boxBackground: #ffffff;
|
||||||
|
--alternativeBackground: #f9f9f9;
|
||||||
|
--sideBackground: #ffffff;
|
||||||
|
--ledAccent: #adadad;
|
||||||
|
--ledBackground: #e9e9e9;
|
||||||
|
--gimbalBackground: #eee;
|
||||||
|
--gimbalCrosshair: var(--subtleAccent);
|
||||||
|
--switcherysecond: #c4c4c4;
|
||||||
|
--pushedButton-background: #c4c4c4;
|
||||||
|
--pushedButton-fontColor: #000000;
|
||||||
|
--hoverButton-background: #ffcc3e;
|
||||||
|
--superSubtleAccent: #cccccc;
|
||||||
|
--accentBorder: #ffbb00;
|
||||||
|
}
|
|
@ -659,10 +659,6 @@ async function getStatus() {
|
||||||
async function update_live_status() {
|
async function update_live_status() {
|
||||||
const statuswrapper = $('#quad-status_wrapper');
|
const statuswrapper = $('#quad-status_wrapper');
|
||||||
|
|
||||||
$(".quad-status-contents").css({
|
|
||||||
display: 'inline-block',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (GUI.active_tab !== 'cli' && GUI.active_tab !== 'presets') {
|
if (GUI.active_tab !== 'cli' && GUI.active_tab !== 'presets') {
|
||||||
await MSP.promise(MSPCodes.MSP_BOXNAMES);
|
await MSP.promise(MSPCodes.MSP_BOXNAMES);
|
||||||
await getStatus();
|
await getStatus();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<link type="text/css" rel="stylesheet" href="./js/libraries/jquery.nouislider.min.css"/>
|
<link type="text/css" rel="stylesheet" href="./js/libraries/jquery.nouislider.min.css"/>
|
||||||
<link type="text/css" rel="stylesheet" href="./js/libraries/jquery.nouislider.pips.min.css"/>
|
<link type="text/css" rel="stylesheet" href="./js/libraries/jquery.nouislider.pips.min.css"/>
|
||||||
<link type="text/css" rel="stylesheet" href="./js/libraries/flightindicators.css"/>
|
<link type="text/css" rel="stylesheet" href="./js/libraries/flightindicators.css"/>
|
||||||
|
<link type="text/css" rel="stylesheet" href="./css/theme.css" media="all"/>
|
||||||
<link type="text/css" rel="stylesheet" href="./css/main.css" media="all"/>
|
<link type="text/css" rel="stylesheet" href="./css/main.css" media="all"/>
|
||||||
<link type="text/css" rel="stylesheet" href="./css/tabs/static_tab.css" media="all"/>
|
<link type="text/css" rel="stylesheet" href="./css/tabs/static_tab.css" media="all"/>
|
||||||
<link type="text/css" rel="stylesheet" href="./css/tabs/landing.css" media="all"/>
|
<link type="text/css" rel="stylesheet" href="./css/tabs/landing.css" media="all"/>
|
||||||
|
@ -184,12 +185,15 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="header-wrapper">
|
<div class="header-wrapper">
|
||||||
<div id="quad-status_wrapper">
|
<div id="quad-status_wrapper">
|
||||||
<div class="battery-icon">
|
<battery-icon
|
||||||
<div class="quad-status-contents">
|
:voltage="FC.ANALOG.voltage"
|
||||||
<div class="battery-status"></div>
|
:vbatmincellvoltage="FC.BATTERY_CONFIG.vbatmincellvoltage"
|
||||||
</div>
|
:vbatmaxcellvoltage="FC.BATTERY_CONFIG.vbatmaxcellvoltage"
|
||||||
</div>
|
:vbatwarningcellvoltage="FC.BATTERY_CONFIG.vbatwarningcellvoltage"
|
||||||
<battery-legend
|
:batteryState="FC.BATTERY_STATE?.batteryState"
|
||||||
|
>
|
||||||
|
</battery-icon>
|
||||||
|
<battery-legend
|
||||||
:voltage="FC.ANALOG.voltage"
|
:voltage="FC.ANALOG.voltage"
|
||||||
:vbatmaxcellvoltage="FC.BATTERY_CONFIG.vbatmaxcellvoltage"
|
:vbatmaxcellvoltage="FC.BATTERY_CONFIG.vbatmaxcellvoltage"
|
||||||
></battery-legend>
|
></battery-legend>
|
||||||
|
|
Loading…
Reference in New Issue