More configuration
This commit is contained in:
parent
94d2549fca
commit
6e867a0fae
|
|
@ -20,7 +20,7 @@ function load() {
|
|||
fetch("/api/sensors")
|
||||
.then((r) => r.json())
|
||||
.then((sensors) => {
|
||||
$sensorsContainer.innerHTML = ''
|
||||
$sensorsContainer.innerHTML = "";
|
||||
|
||||
sensorComponents = sensors.map((sensor) => createSensor(sensor));
|
||||
sensorComponents.forEach((component) =>
|
||||
|
|
@ -74,10 +74,28 @@ function renderConfig({ sensor, onSave, shown }) {
|
|||
<label>Name</label>
|
||||
<input name="name" value="${config.name}" />
|
||||
</div>
|
||||
<div class="input">
|
||||
<label>Type</label>
|
||||
<select name="graphType" value="${config.graphType || 'line'}">
|
||||
<option value="line">Line</option>
|
||||
<option value="points">Points</option>
|
||||
<option value="lineAndPoints">Line + Points</option>
|
||||
<option value="bar">Bar</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<label>Unit</label>
|
||||
<input name="unit" value="${config.unit}" />
|
||||
</div>
|
||||
<div class="input">
|
||||
<label>Min value</label>
|
||||
<input name="min" value="${config.min}" />
|
||||
</div>
|
||||
<div class="input">
|
||||
<label>Max value</label>
|
||||
<input name="max" value="${config.max}" />
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button onclick=${hideConfig} type="button">Cancel</button>
|
||||
|
|
@ -91,27 +109,58 @@ function renderConfig({ sensor, onSave, shown }) {
|
|||
);
|
||||
}
|
||||
|
||||
const CURRENT_FILTERS = {
|
||||
interval: "week",
|
||||
refresh: "1s",
|
||||
customFrom: new Date().toISOString(),
|
||||
customTo: new Date().toISOString(),
|
||||
};
|
||||
const CURRENT_FILTERS = loadFilters();
|
||||
|
||||
function refreshAll() {
|
||||
sensorComponents.forEach(c => c.refreshValues())
|
||||
function loadFilters() {
|
||||
const params = new URLSearchParams(location.search.replace(/^\?/, ""));
|
||||
|
||||
return {
|
||||
interval: params.get("interval") || "week",
|
||||
refresh: "1s",
|
||||
customFrom: params.get("from") || new Date().toISOString(),
|
||||
customTo: params.get("to") || new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
let isCustomSelected = false
|
||||
let lastIntervalSelected = 'week'
|
||||
function saveFilters() {
|
||||
const values = {
|
||||
interval: CURRENT_FILTERS.interval,
|
||||
};
|
||||
|
||||
if (CURRENT_FILTERS.interval === "custom") {
|
||||
values.from = CURRENT_FILTERS.customFrom.toISOString();
|
||||
values.to = CURRENT_FILTERS.customTo.toISOString();
|
||||
}
|
||||
|
||||
const url = new URL(location.href);
|
||||
const params = new URLSearchParams(values);
|
||||
|
||||
url.search = params.toString();
|
||||
|
||||
history.replaceState(null, null, url.toString());
|
||||
}
|
||||
|
||||
function refreshAll() {
|
||||
sensorComponents.forEach((c) => c.refreshValues());
|
||||
}
|
||||
|
||||
let lastIntervalSelected = CURRENT_FILTERS.interval;
|
||||
|
||||
function splitDateTime(v) {
|
||||
const d = new Date(v)
|
||||
const d = new Date(v);
|
||||
|
||||
const date = d.getFullYear() + '-' + (d.getMonth() + 1).toString().padStart(2, '0') + '-' + d.getDate().toString().padStart(2, '0')
|
||||
const time = d.getHours().toString().padStart(2, '0') + ':' + d.getMinutes().toString().padStart(2, '0')
|
||||
const date =
|
||||
d.getFullYear() +
|
||||
"-" +
|
||||
(d.getMonth() + 1).toString().padStart(2, "0") +
|
||||
"-" +
|
||||
d.getDate().toString().padStart(2, "0");
|
||||
const time =
|
||||
d.getHours().toString().padStart(2, "0") +
|
||||
":" +
|
||||
d.getMinutes().toString().padStart(2, "0");
|
||||
|
||||
return [date, time]
|
||||
return [date, time];
|
||||
}
|
||||
|
||||
function renderFilters() {
|
||||
|
|
@ -128,23 +177,26 @@ function renderFilters() {
|
|||
CURRENT_FILTERS.customFrom = from.toISOString();
|
||||
CURRENT_FILTERS.customTo = to.toISOString();
|
||||
} else {
|
||||
CURRENT_FILTERS.customFrom = new Date(`${data.fromDate} ${data.fromTime}`)
|
||||
CURRENT_FILTERS.customTo = new Date(`${data.toDate} ${data.toTime}`)
|
||||
CURRENT_FILTERS.customFrom = new Date(
|
||||
`${data.fromDate} ${data.fromTime}`
|
||||
);
|
||||
CURRENT_FILTERS.customTo = new Date(`${data.toDate} ${data.toTime}`);
|
||||
}
|
||||
|
||||
refreshAll()
|
||||
renderFilters()
|
||||
refreshAll();
|
||||
renderFilters();
|
||||
saveFilters();
|
||||
};
|
||||
|
||||
const handleIntervalChange = (e) => {
|
||||
lastIntervalSelected = e.target.value
|
||||
lastIntervalSelected = e.target.value;
|
||||
|
||||
renderFilters()
|
||||
}
|
||||
renderFilters();
|
||||
};
|
||||
|
||||
const customFrom = splitDateTime(CURRENT_FILTERS.customFrom)
|
||||
const customTo = splitDateTime(CURRENT_FILTERS.customTo)
|
||||
const isCustomSelected = lastIntervalSelected === 'custom'
|
||||
const customFrom = splitDateTime(CURRENT_FILTERS.customFrom);
|
||||
const customTo = splitDateTime(CURRENT_FILTERS.customTo);
|
||||
const isCustomSelected = lastIntervalSelected === "custom";
|
||||
|
||||
render(
|
||||
$filters,
|
||||
|
|
@ -153,7 +205,11 @@ function renderFilters() {
|
|||
<form class="horizontal" onsubmit=${handleApply}>
|
||||
<div class="input">
|
||||
<label>Interval</label>
|
||||
<select name="interval" value="${lastIntervalSelected}" onchange=${handleIntervalChange}>
|
||||
<select
|
||||
name="interval"
|
||||
value="${lastIntervalSelected}"
|
||||
onchange=${handleIntervalChange}
|
||||
>
|
||||
<option value="hour">Hour</option>
|
||||
<option value="day">Day</option>
|
||||
<option value="week">Week</option>
|
||||
|
|
@ -162,12 +218,21 @@ function renderFilters() {
|
|||
</select>
|
||||
</div>
|
||||
|
||||
${isCustomSelected ? html`
|
||||
${isCustomSelected
|
||||
? html`
|
||||
<div class="input date-time">
|
||||
<label>From</label>
|
||||
<div>
|
||||
<input type="date" value="${customFrom[0]}" name="fromDate" />
|
||||
<input type="time" value="${customFrom[1]}" name="fromTime" />
|
||||
<input
|
||||
type="date"
|
||||
value="${customFrom[0]}"
|
||||
name="fromDate"
|
||||
/>
|
||||
<input
|
||||
type="time"
|
||||
value="${customFrom[1]}"
|
||||
name="fromTime"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input date-time">
|
||||
|
|
@ -177,7 +242,8 @@ function renderFilters() {
|
|||
<input type="time" value="${customTo[1]}" name="toTime" />
|
||||
</div>
|
||||
</div>
|
||||
` : undefined}
|
||||
`
|
||||
: undefined}
|
||||
|
||||
<button>Apply</button>
|
||||
</form>
|
||||
|
|
@ -246,20 +312,30 @@ function createSensor(sensor) {
|
|||
|
||||
const renderBody = (range, values) => {
|
||||
const { from, to } = range;
|
||||
const minValue = parseFloat(sensor.config.min);
|
||||
const maxValue = parseFloat(sensor.config.max);
|
||||
const customRange = !isNaN(minValue) && !isNaN(maxValue);
|
||||
|
||||
Plotly.newPlot(
|
||||
body,
|
||||
[
|
||||
{
|
||||
type: "lines",
|
||||
...(sensor.config.graphType === 'line' && { type: 'scatter', mode: 'lines' }),
|
||||
...(sensor.config.graphType === 'points' && { type: 'scatter', mode: 'markers' }),
|
||||
...(sensor.config.graphType === 'lineAndPoints' && { type: 'scatter', mode: 'lines+markers' }),
|
||||
...(sensor.config.graphType === 'bar' && { type: 'bar' }),
|
||||
x: values.map((v) => new Date(v.timestamp * 1000)),
|
||||
y: values.map((v) => v.value),
|
||||
},
|
||||
],
|
||||
{
|
||||
xaxis: { range: [from, to], type: "date" },
|
||||
yaxis: {
|
||||
...(customRange && { range: [minValue, maxValue] }),
|
||||
...(sensor.config.unit && { ticksuffix: ` ${sensor.config.unit}` }),
|
||||
},
|
||||
margin: {
|
||||
l: 50,
|
||||
l: 70,
|
||||
r: 20,
|
||||
b: 60,
|
||||
t: 20,
|
||||
|
|
@ -302,7 +378,7 @@ function createSensor(sensor) {
|
|||
|
||||
return {
|
||||
container,
|
||||
refreshValues
|
||||
refreshValues,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue