mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-15 05:16:34 +00:00
Improve chart loading behaviour and some other chart fixes (#1042)
* show is loading and animate chart display * let tooltip overflow in more-info * graph chart tooltip overflow * style toopltip a bit more like material design guidelines * smoother tooltip appearing * timeline transition time * max-widht -> width
This commit is contained in:
parent
fb8fb09c73
commit
0790cd1ac9
@ -11,8 +11,14 @@
|
|||||||
paper-card:not([dialog]) .content {
|
paper-card:not([dialog]) .content {
|
||||||
padding: 0 16px 16px;
|
padding: 0 16px 16px;
|
||||||
}
|
}
|
||||||
|
paper-card[dialog] {
|
||||||
|
padding-top: 16px;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
paper-card {
|
paper-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
/* prevent new stacking context, chart tooltip needs to overflow */
|
||||||
|
position: static;
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
@apply --paper-font-headline;
|
@apply --paper-font-headline;
|
||||||
|
@ -5,10 +5,14 @@
|
|||||||
<dom-module id="ha-chart-base">
|
<dom-module id="ha-chart-base">
|
||||||
<template>
|
<template>
|
||||||
<style>
|
<style>
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
.chartHeader {
|
.chartHeader {
|
||||||
display: flex;
|
|
||||||
padding: 6px 0 0 0;
|
padding: 6px 0 0 0;
|
||||||
width: 100%
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
.chartHeader > div {
|
.chartHeader > div {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
@ -16,9 +20,12 @@
|
|||||||
}
|
}
|
||||||
.chartHeader > div.chartTitle {
|
.chartHeader > div.chartTitle {
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
|
flex: 0 0 0;
|
||||||
|
max-width: 30%;
|
||||||
}
|
}
|
||||||
.chartHeader > div.chartLegend {
|
.chartHeader > div.chartLegend {
|
||||||
flex: auto;
|
flex: 1 1 1;
|
||||||
|
min-width: 70%;
|
||||||
}
|
}
|
||||||
:root{
|
:root{
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -27,15 +34,17 @@
|
|||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
}
|
}
|
||||||
.chartTooltip {
|
.chartTooltip {
|
||||||
|
font-size: 90%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: rgba(0, 0, 0, .7);
|
background: rgba(80, 80, 80, .9);
|
||||||
color: white;
|
color: white;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 5px);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
|
transition: opacity 0.15s ease-in-out;
|
||||||
}
|
}
|
||||||
.chartLegend ul,
|
.chartLegend ul,
|
||||||
.chartTooltip ul {
|
.chartTooltip ul {
|
||||||
@ -54,17 +63,17 @@
|
|||||||
.chartLegend li {
|
.chartLegend li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
max-width: 49%;
|
width: 49%;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.chartLegend li:nth-child(odd):last-of-type {
|
.chartLegend li:nth-child(odd):last-of-type {
|
||||||
/* Make last item take full width if it is add-numbered. */
|
/* Make last item take full width if it is odd-numbered. */
|
||||||
max-width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.chartLegend li.hidden {
|
.chartLegend li[data-hidden] {
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
}
|
}
|
||||||
.chartLegend em,
|
.chartLegend em,
|
||||||
@ -85,7 +94,7 @@
|
|||||||
<div class="chartLegend">
|
<div class="chartLegend">
|
||||||
<ul>
|
<ul>
|
||||||
<template is="dom-repeat" items="[[metas]]">
|
<template is="dom-repeat" items="[[metas]]">
|
||||||
<li on-click="_legendClick" class$="[[item.hidden]]">
|
<li on-click="_legendClick" data-hidden$="[[item.hidden]]">
|
||||||
<em style$="background-color:[[item.bgColor]]"></em>
|
<em style$="background-color:[[item.bgColor]]"></em>
|
||||||
[[item.label]]
|
[[item.label]]
|
||||||
</li>
|
</li>
|
||||||
@ -136,6 +145,12 @@
|
|||||||
data: Object,
|
data: Object,
|
||||||
identifier: String,
|
identifier: String,
|
||||||
isZoomable: Boolean,
|
isZoomable: Boolean,
|
||||||
|
rendered: {
|
||||||
|
type: Boolean,
|
||||||
|
notify: true,
|
||||||
|
value: false,
|
||||||
|
readOnly: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,9 +168,7 @@
|
|||||||
xPadding: '0',
|
xPadding: '0',
|
||||||
yPadding: '0'
|
yPadding: '0'
|
||||||
});
|
});
|
||||||
if (!this._chart) {
|
this.onPropsChange();
|
||||||
requestAnimationFrame(() => requestAnimationFrame(() => this.onPropsChange()));
|
|
||||||
}
|
|
||||||
this._resizeListener = () => {
|
this._resizeListener = () => {
|
||||||
this._debouncer = Polymer.Debouncer.debounce(
|
this._debouncer = Polymer.Debouncer.debounce(
|
||||||
this._debouncer,
|
this._debouncer,
|
||||||
@ -271,8 +284,9 @@
|
|||||||
|
|
||||||
_legendClick(event) {
|
_legendClick(event) {
|
||||||
event = event || window.event;
|
event = event || window.event;
|
||||||
|
event.stopPropagation();
|
||||||
let target = event.target || event.srcElement;
|
let target = event.target || event.srcElement;
|
||||||
while (target.nodeName !== 'LI') {
|
while (target.nodeName !== 'LI') { // user clicked child, find parent LI
|
||||||
target = target.parentElement;
|
target = target.parentElement;
|
||||||
}
|
}
|
||||||
const index = event.model.itemsIndex;
|
const index = event.model.itemsIndex;
|
||||||
@ -345,6 +359,9 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._customTooltips({ opacity: 0 });
|
this._customTooltips({ opacity: 0 });
|
||||||
|
const plugins = [
|
||||||
|
{ afterRender: () => this._setRendered(true) }
|
||||||
|
];
|
||||||
let options = {
|
let options = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
@ -419,7 +436,8 @@
|
|||||||
const chartData = {
|
const chartData = {
|
||||||
type: this.data.type,
|
type: this.data.type,
|
||||||
data: this.data.data,
|
data: this.data.data,
|
||||||
options: options
|
options: options,
|
||||||
|
plugins: plugins,
|
||||||
};
|
};
|
||||||
// Async resize after dom update
|
// Async resize after dom update
|
||||||
this._chart = new Chart(ctx, chartData);
|
this._chart = new Chart(ctx, chartData);
|
||||||
|
@ -4,11 +4,21 @@
|
|||||||
|
|
||||||
<dom-module id='state-history-chart-line'>
|
<dom-module id='state-history-chart-line'>
|
||||||
<template>
|
<template>
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 0;
|
||||||
|
transition: height 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<ha-chart-base
|
<ha-chart-base
|
||||||
|
id='chart'
|
||||||
data="[[chartData]]"
|
data="[[chartData]]"
|
||||||
is-zoomable="[[isZoomable]]"
|
is-zoomable="[[isZoomable]]"
|
||||||
identifier="[[identifier]]">
|
identifier="[[identifier]]"
|
||||||
</ha-chart-base>
|
rendered="{{rendered}}"
|
||||||
|
></ha-chart-base>
|
||||||
</template>
|
</template>
|
||||||
</dom-module>
|
</dom-module>
|
||||||
<script>
|
<script>
|
||||||
@ -27,6 +37,11 @@ class StateHistoryChartLine extends Polymer.Element {
|
|||||||
},
|
},
|
||||||
|
|
||||||
endTime: Object,
|
endTime: Object,
|
||||||
|
rendered: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
observer: '_onRenderedChanged'
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
static get observers() {
|
static get observers() {
|
||||||
@ -43,6 +58,16 @@ class StateHistoryChartLine extends Polymer.Element {
|
|||||||
this.drawChart();
|
this.drawChart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onRenderedChanged(rendered) {
|
||||||
|
if (rendered) this.animateHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
animateHeight() {
|
||||||
|
requestAnimationFrame(() => requestAnimationFrame(() => {
|
||||||
|
this.style.height = this.$.chart.scrollHeight + 'px';
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
drawChart() {
|
drawChart() {
|
||||||
const unit = this.unit;
|
const unit = this.unit;
|
||||||
const deviceStates = this.data;
|
const deviceStates = this.data;
|
||||||
|
@ -4,7 +4,21 @@
|
|||||||
|
|
||||||
<dom-module id='state-history-chart-timeline'>
|
<dom-module id='state-history-chart-timeline'>
|
||||||
<template>
|
<template>
|
||||||
<ha-chart-base data="[[chartData]]"></ha-chart-base>
|
<style>
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
:host([rendered]) {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<ha-chart-base
|
||||||
|
data="[[chartData]]"
|
||||||
|
rendered="{{rendered}}"
|
||||||
|
></ha-chart-base>
|
||||||
</template>
|
</template>
|
||||||
</dom-module>
|
</dom-module>
|
||||||
<script>
|
<script>
|
||||||
@ -23,6 +37,11 @@ class StateHistoryChartTimeline extends Polymer.Element {
|
|||||||
},
|
},
|
||||||
noSingle: Boolean,
|
noSingle: Boolean,
|
||||||
endTime: Date,
|
endTime: Date,
|
||||||
|
rendered: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
reflectToAttribute: true,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,21 @@
|
|||||||
<style>
|
<style>
|
||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
|
/* height of single timeline chart = 58px */
|
||||||
|
min-height: 58px;
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 58px;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<template is='dom-if' class='info' if='[[_computeIsLoading(isLoadingData)]]'>
|
||||||
|
<div class='info'>Loading state history...</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template is='dom-if' if='[[_computeIsEmpty(historyData)]]'>
|
<template is='dom-if' class='info' if='[[_computeIsEmpty(isLoadingData, historyData)]]'>
|
||||||
No state history found.
|
<div class='info'>No state history found.</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template is='dom-if' if='[[historyData.timeline.length]]'>
|
<template is='dom-if' if='[[historyData.timeline.length]]'>
|
||||||
@ -48,10 +58,7 @@ class StateHistoryCharts extends Polymer.Element {
|
|||||||
value: null,
|
value: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
isLoadingData: {
|
isLoading: Boolean,
|
||||||
type: Boolean,
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
endTime: {
|
endTime: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -67,12 +74,18 @@ class StateHistoryCharts extends Polymer.Element {
|
|||||||
return !noSingle && data && data.length === 1;
|
return !noSingle && data && data.length === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeIsEmpty(historyData) {
|
_computeIsEmpty(isLoadingData, historyData) {
|
||||||
return !historyData || !historyData.timeline || !historyData.line ||
|
const historyDataEmpty = (!historyData || !historyData.timeline || !historyData.line ||
|
||||||
(historyData.timeline.length === 0 &&
|
(historyData.timeline.length === 0 &&
|
||||||
historyData.line.length === 0);
|
historyData.line.length === 0));
|
||||||
|
return !isLoadingData && historyDataEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_computeIsLoading(isLoading) {
|
||||||
|
return isLoading && !this.historyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_computeEndTime(endTime, upToNow) {
|
_computeEndTime(endTime, upToNow) {
|
||||||
// We don't really care about the value of historyData, but if it change we want to update
|
// We don't really care about the value of historyData, but if it change we want to update
|
||||||
// endTime.
|
// endTime.
|
||||||
|
@ -27,8 +27,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
state-history-charts {
|
state-history-charts {
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user