Skip to content

Commit

Permalink
Merge pull request #8 from frlequ/circle-not-updating
Browse files Browse the repository at this point in the history
Fix circles not updating
  • Loading branch information
frlequ authored Oct 16, 2024
2 parents 73e42d3 + da228d8 commit 054f5f3
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 175 deletions.
9 changes: 8 additions & 1 deletion dist/network-tariff-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class NetworkTariffCard extends LitElement {
return false; // Default to true if offsetHours is not present
})(), outerRadius: config.outerRadius || 40, innerRadius: config.innerRadius || 32, name: config.name || '', colorMap: Object.assign({}, config.colorMap // User-defined colors will overwrite defaults
) }, config);
//this.attachShadow({ mode: 'open' });
}
// The createSegment function now calculates each path segment of the donut chart
createSegment(i, totalSegments, outerRadius, innerRadius, strokeColor, strokeWidth, textColor, offsetHours, showHours) {
Expand Down Expand Up @@ -81,6 +80,13 @@ class NetworkTariffCard extends LitElement {
${showHours ? `<text x="${labelX}" y="${labelY}" fill="${textColor}" font-size="5" text-anchor="middle" alignment-baseline="middle">${i + 1}</text>` : ''}
`;
}
// Check if 'hass' has changed
updated(changedProperties) {
if (changedProperties.has('hass')) {
this.firstUpdated(); // Call update whenever 'hass' changes
}
}
// Draw SVG
firstUpdated() {
const svg = this.shadowRoot.querySelector(".circle-clock");
// Access the entity from Home Assistant's hass object
Expand Down Expand Up @@ -177,3 +183,4 @@ NetworkTariffCard.styles = css `
}
`;
customElements.define('network-tariff-card', NetworkTariffCard);
console.info("%c NETWORK-TARIFF-CARD %c Version: " + "v1.0.4".padEnd(7, " "), "color: orange; font-weight: bold; background: black", "color: white; font-weight: bold; background: dimgray");
312 changes: 138 additions & 174 deletions src/network-tariff-card.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,141 @@
import {
LitElement,
html,
css,
} from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module";

import { LitElement, html, css, } from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module";
class NetworkTariffCard extends LitElement {
static get properties() {
return {
hass: { type: Object },
config: { type: Object },
};
}

static styles = css`
constructor() {
super(...arguments);
// Declare variables globally
this.entity = null;
this.blocksArray = [];
this.defaultColorMap = {
1: '#03045e',
2: '#0077b6',
3: '#00b4d8',
4: '#90e0ef',
5: '#caf0f8'
};
this.colorMap = null;
}
static get properties() {
return {
hass: { type: Object },
config: { type: Object },
};
}
setConfig(config) {
if (!config.entity) {
throw new Error('You need to define an entity');
}
this.config = Object.assign({ showHours: (() => {
if (config.showHours !== undefined) { // Check if showHours is present
if (typeof config.showHours === 'boolean') {
return config.showHours; // Return the valid boolean value
}
else {
throw new Error(`Invalid value for showHours: ${config.showHours}. It must be a boolean. True or False.`);
}
}
return true; // Default to true if showHours is not present
})(), offsetHours: (() => {
if (config.offsetHours !== undefined) { // Check if offsetHours is present
if (typeof config.offsetHours === 'boolean') {
return config.offsetHours; // Return the valid boolean value
}
else {
throw new Error(`Invalid value for offsetHours: ${config.offsetHours}. It must be a boolean. True or False.`);
}
}
return false; // Default to true if offsetHours is not present
})(), outerRadius: config.outerRadius || 40, innerRadius: config.innerRadius || 32, name: config.name || '', colorMap: Object.assign({}, config.colorMap // User-defined colors will overwrite defaults
) }, config);

}
// The createSegment function now calculates each path segment of the donut chart
createSegment(i, totalSegments, outerRadius, innerRadius, strokeColor, strokeWidth, textColor, offsetHours, showHours) {
const angle = (2 * Math.PI) / totalSegments; // Angle per segment
const offset = showHours ? 0 : 5;
const offsetAngle = offsetHours ? 0.132 : 0;
// Calculate coordinates for the outer arc
const x1 = 50 + (outerRadius + offset) * Math.cos(i * angle - Math.PI / 2);
const y1 = 50 + (outerRadius + offset) * Math.sin(i * angle - Math.PI / 2);
const x2 = 50 + (outerRadius + offset) * Math.cos((i + 1) * angle - Math.PI / 2);
const y2 = 50 + (outerRadius + offset) * Math.sin((i + 1) * angle - Math.PI / 2);
// Calculate coordinates for the inner arc (the hole)
const x3 = 50 + (innerRadius + offset) * Math.cos((i + 1) * angle - Math.PI / 2);
const y3 = 50 + (innerRadius + offset) * Math.sin((i + 1) * angle - Math.PI / 2);
const x4 = 50 + (innerRadius + offset) * Math.cos(i * angle - Math.PI / 2);
const y4 = 50 + (innerRadius + offset) * Math.sin(i * angle - Math.PI / 2);
const segmentValue = this.blocksArray[i];
// Determine the segment color
const segmentColor = (this.colorMap[segmentValue] !== undefined ? this.colorMap[segmentValue] : this.defaultColorMap[segmentValue]) || '#000'; // Default to black if no match
// Calculate the position for the number label
const labelRadius = outerRadius + 5; // Slightly outside the outer radius
const labelX = 50 + labelRadius * Math.cos((i + 0.5) * angle - Math.PI / 2 + offsetAngle);
const labelY = 50 + labelRadius * Math.sin((i + 0.5) * angle - Math.PI / 2 + offsetAngle);
// Create the donut segment path and number label
return `
<path
d="M${x1},${y1} A${outerRadius},${outerRadius} 0 0,1 ${x2},${y2}
L${x3},${y3} A${innerRadius},${innerRadius} 0 0,0 ${x4},${y4} Z"
fill="${segmentColor}"
stroke="${strokeColor}" stroke-width="${strokeWidth}"
/>
${showHours ? `<text x="${labelX}" y="${labelY}" fill="${textColor}" font-size="5" text-anchor="middle" alignment-baseline="middle">${i + 1}</text>` : ''}
`;
}

// Check if 'hass' has changed
updated(changedProperties) {
if (changedProperties.has('hass')) {
this.firstUpdated(); // Call update whenever 'hass' changes
}
}

// Draw SVG
firstUpdated() {
const svg = this.shadowRoot.querySelector(".circle-clock");
// Access the entity from Home Assistant's hass object
this.entity = this.hass.states[this.config.entity];
if (!this.entity)
return; // Exit if the entity is not available
const state = this.entity ? this.entity.state : 'Unavailable';
this.blocks = this.entity.attributes.blocks || Array(24).fill(1);
this.blocksArray = Array.isArray(this.blocks) ? this.blocks : this.blocks.split(',').map(Number);

const now = new Date();
const currentHour = now.getHours();
//const colorMap = this.config.colorMap;
this.colorMap = this.config.colorMap;
const totalSegments = 24;
const outerRadius = this.config.outerRadius !== undefined ? this.config.outerRadius : 40;
const innerRadius = this.config.innerRadius !== undefined ? this.config.innerRadius : 32;
const offsetHours = this.config.offsetHours !== undefined ? this.config.offsetHours : false;
const showHours = this.config.showHours !== undefined ? this.config.showHours : true;
const strokeColor = "rgba(0, 0, 0, 1)"; // Line separating each segment
const strokeWidth = 0.3;
const textColor = "rgba(150, 150, 150, 1)";
// Create daily blocks
const segments = Array.from({ length: totalSegments }, (_, i) => this.createSegment(i, totalSegments, outerRadius, innerRadius, strokeColor, strokeWidth, textColor, offsetHours, showHours)).join('');
// Create current hour section
const currentHourSegment = this.createSegment(currentHour, totalSegments, innerRadius - 1, innerRadius - 5, 'black', 0.3, 'rgba(0, 0, 0, 0)', offsetHours, showHours);
// Render out
svg.innerHTML = segments + currentHourSegment;
}
render() {
const entity = this.hass.states[this.config.entity];
const state = entity ? entity.state : 'Unavailable';
return html `
<ha-card>
<div class="tariffcard">
<div class="name">${this.config.name || 'Entity'}</div>
<div class="circle-container">
<div class="state">${state}</div>
<svg class="circle-clock" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"></svg>
</div>
</div>
</ha-card>
`;
}
}
NetworkTariffCard.styles = css `
.tariffcard {
display: flex;
justify-content: center;
Expand Down Expand Up @@ -63,164 +186,5 @@ class NetworkTariffCard extends LitElement {
z-index: 1;
}
`;

setConfig(config) {

if (!config.entity) {
throw new Error('You need to define an entity');
}

this.config = {
showHours: (() => {
if (config.showHours !== undefined) { // Check if showHours is present
if (typeof config.showHours === 'boolean') {
return config.showHours; // Return the valid boolean value
} else {
throw new Error(`Invalid value for showHours: ${config.showHours}. It must be a boolean. True or False.`);
}
}
return true; // Default to true if showHours is not present
})(),
offsetHours: (() => {
if (config.offsetHours !== undefined) { // Check if offsetHours is present
if (typeof config.offsetHours === 'boolean') {
return config.offsetHours; // Return the valid boolean value
} else {
throw new Error(`Invalid value for offsetHours: ${config.offsetHours}. It must be a boolean. True or False.`);
}
}
return false; // Default to true if offsetHours is not present
})(),
outerRadius: config.outerRadius || 40, // Default hole size, can be adjusted
innerRadius: config.innerRadius || 32, // Default hole size, can be adjusted
name: config.name || '',
colorMap: {

...config.colorMap // User-defined colors will overwrite defaults
},
...config
};

//this.attachShadow({ mode: 'open' });
}

// Declare variables globally
entity = null;
blocks;
blocksArray = [];
defaultColorMap = {
1: '#03045e',
2: '#0077b6',
3: '#00b4d8',
4: '#90e0ef',
5: '#caf0f8'
};
colorMap = null;

// The createSegment function now calculates each path segment of the donut chart
createSegment(i, totalSegments, outerRadius, innerRadius, strokeColor, strokeWidth, textColor, offsetHours, showHours) {
const angle = (2 * Math.PI) / totalSegments; // Angle per segment
const offset = showHours ? 0 : 5;
const offsetAngle = offsetHours ? 0.132 : 0;


// Calculate coordinates for the outer arc
const x1 = 50 + (outerRadius + offset) * Math.cos(i * angle - Math.PI / 2);
const y1 = 50 + (outerRadius + offset) * Math.sin(i * angle - Math.PI / 2);
const x2 = 50 + (outerRadius + offset) * Math.cos((i + 1) * angle - Math.PI / 2);
const y2 = 50 + (outerRadius + offset) * Math.sin((i + 1) * angle - Math.PI / 2);

// Calculate coordinates for the inner arc (the hole)
const x3 = 50 + (innerRadius + offset) * Math.cos((i + 1) * angle - Math.PI / 2);
const y3 = 50 + (innerRadius + offset) * Math.sin((i + 1) * angle - Math.PI / 2);
const x4 = 50 + (innerRadius + offset) * Math.cos(i * angle - Math.PI / 2);
const y4 = 50 + (innerRadius + offset) * Math.sin(i * angle - Math.PI / 2);

const segmentValue = this.blocksArray[i];

// Determine the segment color
const segmentColor = (this.colorMap[segmentValue] !== undefined ? this.colorMap[segmentValue] : this.defaultColorMap[segmentValue]) || '#000'; // Default to black if no match

// Calculate the position for the number label
const labelRadius = outerRadius + 5; // Slightly outside the outer radius
const labelX = 50 + labelRadius * Math.cos((i + 0.5) * angle - Math.PI / 2 + offsetAngle);
const labelY = 50 + labelRadius * Math.sin((i + 0.5) * angle - Math.PI / 2 + offsetAngle);

// Create the donut segment path and number label
return `
<path
d="M${x1},${y1} A${outerRadius},${outerRadius} 0 0,1 ${x2},${y2}
L${x3},${y3} A${innerRadius},${innerRadius} 0 0,0 ${x4},${y4} Z"
fill="${segmentColor}"
stroke="${strokeColor}" stroke-width="${strokeWidth}"
/>
${showHours ? `<text x="${labelX}" y="${labelY}" fill="${textColor}" font-size="5" text-anchor="middle" alignment-baseline="middle">${i + 1}</text>` : ''}
`;
}

firstUpdated() {
const svg = this.shadowRoot.querySelector(".circle-clock");

// Access the entity from Home Assistant's hass object
this.entity = this.hass.states[this.config.entity];
if (!this.entity) return; // Exit if the entity is not available

const state = this.entity ? this.entity.state : 'Unavailable';
this.blocks = this.entity.attributes.blocks || Array(24).fill(1);
this.blocksArray = Array.isArray(this.blocks) ? this.blocks : this.blocks.split(',').map(Number);

const now = new Date();
const currentHour = now.getHours();


//const colorMap = this.config.colorMap;
this.colorMap = this.config.colorMap;


const totalSegments = 24;

const outerRadius = this.config.outerRadius !== undefined ? this.config.outerRadius : 40;
const innerRadius = this.config.innerRadius !== undefined ? this.config.innerRadius : 32;
const offsetHours = this.config.offsetHours !== undefined ? this.config.offsetHours : false;
const showHours = this.config.showHours !== undefined ? this.config.showHours : true;


const strokeColor = "rgba(0, 0, 0, 1)"; // Line separating each segment
const strokeWidth = 0.3;
const textColor = "rgba(150, 150, 150, 1)";


// Create daily blocks
const segments = Array.from({ length: totalSegments }, (_, i) =>
this.createSegment(i, totalSegments, outerRadius, innerRadius, strokeColor, strokeWidth, textColor, offsetHours, showHours)
).join('');


// Create current hour section
const currentHourSegment = this.createSegment(currentHour, totalSegments, innerRadius - 1, innerRadius - 5, 'black', 0.3, 'rgba(0, 0, 0, 0)', offsetHours, showHours);


// Render out
svg.innerHTML = segments + currentHourSegment;

}

render() {
const entity = this.hass.states[this.config.entity];
const state = entity ? entity.state : 'Unavailable';

return html`
<ha-card>
<div class="tariffcard">
<div class="name">${this.config.name || 'Entity'}</div>
<div class="circle-container">
<div class="state">${state}</div>
<svg class="circle-clock" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"></svg>
</div>
</div>
</ha-card>
`;
}
}

customElements.define('network-tariff-card', NetworkTariffCard);
console.info("%c NETWORK-TARIFF-CARD %c Version: " + "v1.0.4".padEnd(7, " "), "color: orange; font-weight: bold; background: black", "color: white; font-weight: bold; background: dimgray");

0 comments on commit 054f5f3

Please sign in to comment.