forked from grittisemper/frk-waze-card
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.js
178 lines (151 loc) · 4.89 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import { LitElement, html } from 'lit-element';
import style from './style';
class WazeCard extends LitElement {
static get properties() {
return {
hass: Object,
config: Object,
};
}
constructor() {
super();
this.wazeBaseUrl = 'https://www.waze.com/ul?navigate=yes&ll=';
}
setConfig(config) {
if (!config.entities) {
throw new Error('Entities list required.');
}
if (config.columns && !Array.isArray(config.columns)) {
throw new Error('columns config needs to be a list');
}
if (config.custom_distance && !['km', 'mi'].includes(config.custom_distance)) {
throw new Error('custom_distance config needs to be either `km` or `mi`');
}
this.config = {
title: 'Waze Routes',
header: true,
columns: ['name', 'distance', 'duration', 'route'],
custom_distance: '',
custom_distance_units: '',
...config,
};
}
/**
* get the current size of the card
* @return {Number}
*/
getCardSize() {
const headerHeight = (this.config && this.config.header) ? 1 : 0;
const tableHeight = (this.config && this.config.entities) ? this.config.entities.length * 1 : 0;
return headerHeight + tableHeight;
}
static get styles() {
return style;
}
/**
* generates the card HTML
* @return {TemplateResult}
*/
render() {
const wazeStates = this.getAllStates(this.config.entities);
return this.createCard(wazeStates);
}
/**
* @param {Array<Object>} wazeStates
* @return {TemplateResult}
*/
createCard(wazeStates) {
const header = this.config.header ? html`<div class='header'>${this.config.title}</div>` : html``;
return html`
<ha-card>
${header}
<div class='waze-card-wrapper'>
<table>
<thead>
${this.config.columns.map(column => html`<th align="left">${column}</th>`)}
</thead>
<tbody>
${this.createCardBody(wazeStates)}
</tbody>
</table>
</div>
</ha-card>
`;
}
/**
*
* @param {Array<Object>} wazeStates
* @return {Array<TemplateResult>}
*/
createCardBody(wazeStates) {
return wazeStates.map((state) => {
// create the routes columns based on config array
const routeColumns = this.config.columns.map(column => html`
<td @click=${() => state.location && window.open(`${this.wazeBaseUrl}${state.location.lat}%2C${state.location.long}`)}>
${(state[column] || '')}
</td>
`);
return html`
<tr class='${state.location ? 'waze-card-pointer' : ''}'>
${routeColumns}
</tr>
`;
});
}
/**
* formats all states for this card to use for the HTML
* @param {Array<Object>} entities
* @return {Array<Object>}
*/
getAllStates(entities) {
return entities
.map((entity) => {
const state = this.hass.states[entity.entity || ''];
if (!state) return;
state.name = entity.name || state.attributes.friendly_name;
// if given a zone then att lat/long for clicking to open waze
if (entity.zone) {
const zone = this.hass.states[entity.zone || ''];
if (!zone) throw new Error(`Could not find config for zone entity ${entity.zone}`);
state.location = { lat: zone.attributes.latitude, long: zone.attributes.longitude };
state.name = state.name ? state.name : zone.attributes.friendly_name;
}
return state;
})
.filter(Boolean)
.map(state => ({
location: state.location || '',
name: state.name || state.entity || '',
distance: this.computeDistance(state),
duration: this.computeDuration(state),
route: state.attributes && state.attributes.route || '',
}));
}
/**
* generates the duration for a route
* @param {Object} state the card state
* @return {string} the formatted duration for a ruote
*/
computeDuration(state) {
const duration = state.attributes && state.attributes.duration || 0;
const unit_of_measurement = state.attributes && state.attributes.unit_of_measurement || '';
return `${parseInt(duration, 0)} ${unit_of_measurement}`;
}
/**
* computes the distance for a route for metric/imperial system
* @param {Object} state the card state
* @return {string} the formatted distance
*/
computeDistance(state) {
let distance = state.attributes && state.attributes.distance || 0;
distance = parseInt(Math.round(distance), 0);
let distance_units = this.hass.config.unit_system.length;
if (this.config.custom_distance) {
distance_units = this.config.custom_distance;
distance = distance *= this.config.custom_distance === 'km' ? 1.60934 : 0.62137;
}
distance = distance.toFixed(1);
return `${distance}${this.config.custom_distance_units || distance_units}`;
}
}
customElements.define('waze-card', WazeCard);