Hello,
I have made a dashboard using one example as a base. However my client asked to also be able to put the dates manually. So we still have the example like plots using html:
Summary
<div class="grid grid-cols-2-3" style="margin-top: 2rem;">
<div class="card grid-colspan-2 grid-rowspan-2" style="display: flex; flex-direction: column;">
<h2>
${getVariableTitle(selected_sensor)}, ${getVariableTitle(selected_sensor2)} from
${startEnd === defaultStartEnd
? `${new Date(form[0]).toLocaleString('en-GB', { hour12: false })} to ${new Date(form[1]).toLocaleString('en-GB', { hour12: false })}`
: startEnd.map((d) => new Date(d).toISOString().replace('T', ' ').slice(0, 21)).join(" to ")}
</h2>
<div class="plot-container">
${resize((width, height) =>
Plot.plot({
width,
height: 275,
y: { grid: true, label: "value" },
color: { domain: [ targetLabelDevice+" "+selected_sensor, targetLabelDevice2+" "+selected_sensor2], legend: true },
marks: [
Plot.dotY(tidyData2.filter((d) => startEnd[0] <= d.timestamp && d.timestamp <= startEnd[1]), { x: "timestamp", y: "value", stroke: "type", tip: true })
],
})
)}
</div>
</div>
</div>
<div class="grid">
<div class="card">
<h2>${getVariableTitle(selected_sensor)}, ${getVariableTitle(selected_sensor2)} over all time</h2>
<h3>Click or drag to zoom</h3>
<div class="plot-container">
${resize((width) =>
Plot.plot({
width,
y: {grid: true, label: "value" },
color: {
domain: [targetLabelDevice + " " + selected_sensor, targetLabelDevice2 + " " + selected_sensor2],
legend: true,
},
marks: [
Plot.dotY(tidyData2, { x: "timestamp", y: "value", stroke: "type", tip: true }),
(index, scales, channels, dimensions, context) => {
const x1 = dimensions.marginLeft;
const y1 = 0;
const x2 = dimensions.width - dimensions.marginRight;
const y2 = dimensions.height;
const brushed = (event) => {
if (!event.sourceEvent) return;
let {selection} = event;
if (!selection) {
const r = 10; // radius of point-based selection
let [px] = d3.pointer(event, context.ownerSVGElement);
px = Math.max(x1 + r, Math.min(x2 - r, px));
selection = [px - r, px + r];
g.call(brush.move, selection);
}
setStartEnd(selection.map(scales.x.invert));
};
const pointerdowned = (event) => {
const pointerleave = new PointerEvent("pointerleave", {bubbles: true, pointerType: "mouse"});
event.target.dispatchEvent(pointerleave);
};
const brush = d3.brushX().extent([[x1, y1], [x2, y2]]).on("brush end", brushed);
const g = d3.create("svg:g").call(brush);
g.call(brush.move, getStartEnd().map(scales.x));
g.on("pointerdown", pointerdowned);
return g.node();
}
]
})
)}
</div>
</div>
</div>
But i also have this date input using JS
Summary
const form = view(Inputs.form(
[
Inputs.datetime({ label: "From", value: "2024-12-10T13:13Z"}),
Inputs.datetime({ label: "to", value: "2024-12-10T13:14Z"}),
],
{
template: (inputs) => htl.html`<div style="display: flex; gap: 1em">
${inputs}
</div>`
}
));
While i put the input as the default using JS,
Summary
const defaultStartEnd = [form[0],form[1]];
const startEnd = Mutable(defaultStartEnd);
const setStartEnd = (se) => startEnd.value = (se ?? defaultStartEnd);
const getStartEnd = () => startEnd.value;
When changing radio and dropdown inputs, the brush stops working with the date inputs. It still works as standalone. But i want the inputs to affect the brush too (ideally the other way too, but i don’t really care much about that).
Any help would be appreciated,
Albert