mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 20:36:35 +00:00
Sensor Card Fill feature (#4745)
This commit is contained in:
parent
7758ddba56
commit
107f428dd3
@ -27,6 +27,17 @@ import { SensorCardConfig } from "./types";
|
|||||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
|
|
||||||
|
const average = (items): number => {
|
||||||
|
return (
|
||||||
|
items.reduce((sum, entry) => sum + parseFloat(entry.state), 0) /
|
||||||
|
items.length
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const lastValue = (items): number => {
|
||||||
|
return parseFloat(items[items.length - 1].state) || 0;
|
||||||
|
};
|
||||||
|
|
||||||
const midPoint = (
|
const midPoint = (
|
||||||
_Ax: number,
|
_Ax: number,
|
||||||
_Ay: number,
|
_Ay: number,
|
||||||
@ -69,34 +80,40 @@ const calcPoints = (
|
|||||||
max: number
|
max: number
|
||||||
): number[][] => {
|
): number[][] => {
|
||||||
const coords = [] as number[][];
|
const coords = [] as number[][];
|
||||||
const margin = 5;
|
|
||||||
const height = 80;
|
const height = 80;
|
||||||
width -= 10;
|
|
||||||
let yRatio = (max - min) / height;
|
let yRatio = (max - min) / height;
|
||||||
yRatio = yRatio !== 0 ? yRatio : height;
|
yRatio = yRatio !== 0 ? yRatio : height;
|
||||||
let xRatio = width / (hours - (detail === 1 ? 1 : 0));
|
let xRatio = width / (hours - (detail === 1 ? 1 : 0));
|
||||||
xRatio = isFinite(xRatio) ? xRatio : width;
|
xRatio = isFinite(xRatio) ? xRatio : width;
|
||||||
|
|
||||||
|
const first = history.filter(Boolean)[0];
|
||||||
|
let last = [average(first), lastValue(first)];
|
||||||
|
|
||||||
const getCoords = (item, i, offset = 0, depth = 1) => {
|
const getCoords = (item, i, offset = 0, depth = 1) => {
|
||||||
if (depth > 1) {
|
if (depth > 1) {
|
||||||
return item.forEach((subItem, index) =>
|
return item.forEach((subItem, index) =>
|
||||||
getCoords(subItem, i, index, depth - 1)
|
getCoords(subItem, i, index, depth - 1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const average =
|
|
||||||
item.reduce((sum, entry) => sum + parseFloat(entry.state), 0) /
|
|
||||||
item.length;
|
|
||||||
|
|
||||||
const x = xRatio * (i + offset / 6) + margin;
|
const x = xRatio * (i + offset / 6);
|
||||||
const y = height - (average - min) / yRatio + margin * 2;
|
|
||||||
|
if (item) {
|
||||||
|
last = [average(item), lastValue(item)];
|
||||||
|
}
|
||||||
|
const y = height - ((item ? last[0] : last[1]) - min) / yRatio;
|
||||||
return coords.push([x, y]);
|
return coords.push([x, y]);
|
||||||
};
|
};
|
||||||
|
|
||||||
history.forEach((item, i) => getCoords(item, i, 0, detail));
|
for (let i = 0; i < history.length; i += 1) {
|
||||||
if (coords.length === 1) {
|
getCoords(history[i], i, 0, detail);
|
||||||
coords[1] = [width + margin, coords[0][1]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coords.push([width + margin, coords[coords.length - 1][1]]);
|
if (coords.length === 1) {
|
||||||
|
coords[1] = [width, coords[0][1]];
|
||||||
|
}
|
||||||
|
|
||||||
|
coords.push([width, coords[coords.length - 1][1]]);
|
||||||
return coords;
|
return coords;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -227,14 +244,27 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
} else {
|
} else {
|
||||||
graph = svg`
|
graph = svg`
|
||||||
<svg width="100%" height="100%" viewBox="0 0 500 100">
|
<svg width="100%" height="100%" viewBox="0 0 500 100">
|
||||||
|
<g>
|
||||||
|
<mask id="fill">
|
||||||
|
<path
|
||||||
|
class='fill'
|
||||||
|
fill='white'
|
||||||
|
d="${this._history} L 500, 100 L 0, 100 z"
|
||||||
|
/>
|
||||||
|
</mask>
|
||||||
|
<rect height="100%" width="100%" id="fill-rect" fill="var(--accent-color)" mask="url(#fill)"></rect>
|
||||||
|
<mask id="line">
|
||||||
<path
|
<path
|
||||||
d="${this._history}"
|
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="var(--accent-color)"
|
stroke="var(--accent-color)"
|
||||||
stroke-width="5"
|
stroke-width="5"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
/>
|
d=${this._history}
|
||||||
|
></path>
|
||||||
|
</mask>
|
||||||
|
<rect height="100%" width="100%" id="rect" fill="var(--accent-color)" mask="url(#line)"></rect>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -247,17 +277,15 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
.actionHandler=${actionHandler()}
|
.actionHandler=${actionHandler()}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<div class="flex">
|
<div class="flex header">
|
||||||
|
<div class="name">
|
||||||
|
<span>${this._config.name || computeStateName(stateObj)}</span>
|
||||||
|
</div>
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<ha-icon
|
<ha-icon
|
||||||
.icon="${this._config.icon || stateIcon(stateObj)}"
|
.icon="${this._config.icon || stateIcon(stateObj)}"
|
||||||
></ha-icon>
|
></ha-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="header">
|
|
||||||
<span class="name"
|
|
||||||
>${this._config.name || computeStateName(stateObj)}</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex info">
|
<div class="flex info">
|
||||||
<span id="value">${stateObj.state}</span>
|
<span id="value">${stateObj.state}</span>
|
||||||
@ -355,9 +383,9 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 16px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-card:focus {
|
ha-card:focus {
|
||||||
@ -370,6 +398,11 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
margin: 16px 16px 0;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@ -377,13 +410,13 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name > span {
|
||||||
display: block;
|
display: block;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
max-height: 1.4rem;
|
max-height: 1.4rem;
|
||||||
margin-top: 2px;
|
top: 2px;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@ -405,7 +438,7 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
.info {
|
.info {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin: 16px 0 16px 8px;
|
margin: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#value {
|
#value {
|
||||||
@ -432,11 +465,17 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.graph > div {
|
.graph > div {
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
margin: auto 8px;
|
margin: auto 0px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fill {
|
||||||
|
opacity: 0.1;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user