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: `
|
||||
<div style="margin: 1rem;">
|
||||
<link rel="stylesheet" href="/css/opensans_webfontkit/fonts.css" />
|
||||
<link rel="stylesheet" href="/css/main.css" />
|
||||
<link rel="stylesheet" href="/css/theme.css" />
|
||||
<story />
|
||||
</div>
|
||||
`,
|
||||
|
|
|
@ -10,6 +10,7 @@ import vueI18n from "./vueI18n.js";
|
|||
import BatteryLegend from "./quad-status/BatteryLegend.vue";
|
||||
import BetaflightLogo from "./betaflight-logo/BetaflightLogo.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.
|
||||
// It's a bit of overkill for simple components,
|
||||
|
@ -38,6 +39,7 @@ i18next.on('initialized', function() {
|
|||
BatteryLegend,
|
||||
BetaflightLogo,
|
||||
StatusBar,
|
||||
BatteryIcon,
|
||||
},
|
||||
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
|
||||
export default {
|
||||
title: 'Battery Legend',
|
||||
title: "Battery Legend",
|
||||
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;
|
||||
padding: 0;
|
||||
|
@ -621,46 +587,7 @@ input[type="number"] {
|
|||
text-shadow: 0 1px rgba(0, 0, 0, 1.0);
|
||||
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 {
|
||||
margin-left: 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() {
|
||||
const statuswrapper = $('#quad-status_wrapper');
|
||||
|
||||
$(".quad-status-contents").css({
|
||||
display: 'inline-block',
|
||||
});
|
||||
|
||||
if (GUI.active_tab !== 'cli' && GUI.active_tab !== 'presets') {
|
||||
await MSP.promise(MSPCodes.MSP_BOXNAMES);
|
||||
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.pips.min.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/tabs/static_tab.css" media="all"/>
|
||||
<link type="text/css" rel="stylesheet" href="./css/tabs/landing.css" media="all"/>
|
||||
|
@ -184,11 +185,14 @@
|
|||
</div>
|
||||
<div class="header-wrapper">
|
||||
<div id="quad-status_wrapper">
|
||||
<div class="battery-icon">
|
||||
<div class="quad-status-contents">
|
||||
<div class="battery-status"></div>
|
||||
</div>
|
||||
</div>
|
||||
<battery-icon
|
||||
:voltage="FC.ANALOG.voltage"
|
||||
:vbatmincellvoltage="FC.BATTERY_CONFIG.vbatmincellvoltage"
|
||||
:vbatmaxcellvoltage="FC.BATTERY_CONFIG.vbatmaxcellvoltage"
|
||||
:vbatwarningcellvoltage="FC.BATTERY_CONFIG.vbatwarningcellvoltage"
|
||||
:batteryState="FC.BATTERY_STATE?.batteryState"
|
||||
>
|
||||
</battery-icon>
|
||||
<battery-legend
|
||||
:voltage="FC.ANALOG.voltage"
|
||||
:vbatmaxcellvoltage="FC.BATTERY_CONFIG.vbatmaxcellvoltage"
|
||||
|
|
Loading…
Reference in New Issue