diff --git a/.eslintrc.yaml b/.eslintrc.yaml old mode 100755 new mode 100644 index 6020c9cb..889d79b0 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -14,3 +14,4 @@ globals: window: true Event: true customElements: true + document: true diff --git a/src/main.js b/src/main.js index 5ce587b1..2b0e779b 100644 --- a/src/main.js +++ b/src/main.js @@ -48,6 +48,9 @@ class MiniGraphCard extends LitElement { this.stateChanged = false; this.initial = true; this._md5Config = undefined; + this.sections = false; + this.graphHeight = 100; + this.graphWidth = 500; } static get styles() { @@ -105,12 +108,14 @@ class MiniGraphCard extends LitElement { this._md5Config = SparkMD5.hash(JSON.stringify(this.config)); const entitiesChanged = !compareArray(this.config.entities || [], config.entities); + this.graphHeight = this.config.height; + if (!this.Graph || entitiesChanged) { if (this._hass) this.hass = this._hass; this.Graph = this.config.entities.map( entity => new Graph( - 500, - this.config.height, + this.graphWidth, + this.graphHeight, [this.config.show.fill ? 0 : this.config.line_width, this.config.line_width], this.config.hours_to_show, this.config.points_per_hour, @@ -127,6 +132,31 @@ class MiniGraphCard extends LitElement { } } + checkSections() { + return this.layout === 'grid'; + } + + getCurrentLayout() { + const layout = this.getLayoutOptions(); + const layoutConfigured = this.config.layout_options !== undefined; + const columns = Math.max(layoutConfigured + ? this.config.layout_options.grid_columns : layout.grid_columns, layout.grid_min_columns); + const rows = Math.max(layoutConfigured + ? this.config.layout_options.grid_rows : layout.grid_rows, layout.grid_min_rows); + return { grid_columns: columns, grid_rows: rows }; + } + + getLayoutSize(layout) { + return this.sections && layout.grid_rows <= 3 ? 'small' : ''; + } + + getGraphHeightSections() { + const layout = this.getCurrentLayout(); + const headerRows = this.getHeaderRows() + (this.getLayoutSize(layout) === '' ? 1 : 0); + + return Math.max(layout.grid_rows - headerRows, 1); + } + connectedCallback() { super.connectedCallback(); if (this.config.update_interval) { @@ -181,9 +211,11 @@ class MiniGraphCard extends LitElement { if (this.config.entities.some((_, index) => this.entity[index] === undefined)) { return this.renderWarnings(); } + const layout = this.getCurrentLayout(); + this.sections = this.checkSections(); return html` this.setTooltip(i, point[3], point[V])} + @mouseout=${() => (this.tooltip = {})} + > + + this.setTooltip(i, point[3], point[V])} - @mouseout=${() => (this.tooltip = {})} + style="stroke: var(--primary-background-color, white);" + x1=${point[X]} y1=${point[Y]} x2=${point[X]} y2=${point[Y]} + stroke-linecap="round" stroke-width=${this.config.line_width} + vector-effect="non-scaling-stroke" /> + `; } @@ -534,7 +577,9 @@ class MiniGraphCard extends LitElement { renderSvg() { const { height } = this.config; return svg` - e.stopPropagation()}> @@ -1039,6 +1084,22 @@ class MiniGraphCard extends LitElement { } } + getHeaderRows() { + return 0 + + ((this.config.show.name || this.config.show.icon) ? 1 : 0) + + ((this.config.show.state) ? 1 : 0) + + ((this.config.show.extrema || this.config.show.average) ? 1 : 0); + } + + getLayoutOptions() { + return { + grid_rows: 1 + this.getHeaderRows(), + grid_columns: 2, + grid_min_rows: 1 + this.getHeaderRows(), + grid_min_columns: 2, + }; + } + getCardSize() { return 3; } diff --git a/src/style.js b/src/style.js index 01395872..45757dd6 100644 --- a/src/style.js +++ b/src/style.js @@ -1,16 +1,15 @@ import { css } from 'lit-element'; const style = css` - :host { - display: flex; - flex-direction: column; - } ha-card { flex-direction: column; flex: 1; padding: 16px 0; position: relative; overflow: hidden; + height: 100%; + } + ha-card.sections { } ha-card > div { padding: 0px 16px 16px 16px; @@ -123,6 +122,12 @@ const style = css` justify-content: space-between; flex-wrap: nowrap; } + .sections.small .states { + padding: 0px 16px 0px 16px; + } + .sections.small .header { + padding: 0px 16px 0px 16px; + } .states .icon { align-self: center; margin-left: 0; @@ -233,7 +238,11 @@ const style = css` left: initial; right: 0; } + .sections.small .state__time { + display: none; + } .graph { + flex: auto; align-self: flex-end; box-sizing: border-box; display: flex; @@ -245,10 +254,14 @@ const style = css` display: flex; flex-direction: row; position: relative; + height: 100%; } .graph__container__svg { cursor: default; - flex: 1; + position: relative; + width: 100%; + height: 100%; + z-index: 0; } svg { overflow: hidden; @@ -264,6 +277,15 @@ const style = css` .fill[anim="false"][type="fade"] { animation: reveal-2 .25s cubic-bezier(0.215, 0.61, 0.355, 1) forwards; } + .line { + vector-effect: non-scaling-stroke; + } + .line--point--group:hover .line--point { + visibility: hidden; + } + .line--point--group { + cursor: pointer; + } .line--points[anim="false"], .line[anim="false"] { animation: pop .25s cubic-bezier(0.215, 0.61, 0.355, 1) forwards; @@ -275,13 +297,11 @@ const style = css` animation: none !important; transition: all .15s !important; } - .line--points[tooltip] .line--point[inactive] { + .line--points[tooltip] .line--point--group[inactive] { opacity: 0; } .line--point { - cursor: pointer; fill: var(--primary-background-color, white); - stroke-width: inherit; } .line--point:hover { fill: var(--mcg-hover, inherit) !important; @@ -336,6 +356,7 @@ const style = css` pointer-events: none; top: 0; bottom: 0; opacity: .75; + z-index: 1; } .graph__labels > span { cursor: pointer; @@ -351,6 +372,9 @@ const style = css` padding-top: 16px; flex-wrap: wrap; } + .sections .graph__legend { + padding-top: 8px; + } .graph__legend__item { cursor: pointer; display: flex; @@ -358,6 +382,9 @@ const style = css` margin: .4em; align-items: center } + .sections .graph__legend__item { + margin: .4em .4em 0px .4em; + } .graph__legend__item span { opacity: .75; margin-left: .4em;