Published
Edited
Apr 26, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof context = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, heightcontext]);
const clipId2 = DOM.uid("clip");

svg.append("clipPath")
.attr("id", clipId2.id)
.append("rect")
.attr("x", margin2.left)
.attr("y", 0)
.attr("width", width - margin2.left - margin2.right)
.attr("height", heightcontext - margin2.bottom);
const brush = d3.brushX()
.extent([[margin2.left, 0], [width - margin2.right, heightcontext - margin2.bottom]])
.on("brush", brushed)
.on("end", brushended);
const defaultSelection = dayRange.map(xt);
svg.selectAll(".ttip")
.data(data)
.join("rect")
.attr("x", d => xt(d.start_time))
.attr("y", d => yt2(d.may_id))
.attr("width", d => xt(d.end_time) - xt(d.start_time))
.attr("height", yt2.bandwidth())
.attr("fill", d => colorScale(d.new_value))
.attr("clip-path", clipId2);


svg.append("g")
.attr("transform", `translate(0,${heightcontext - margin2.bottom})`)
.call(xAxis);

const gb = svg.append("g")
.call(brush)
.call(brush.move, defaultSelection);

function brushed({selection}) {
if (selection) {
svg.property("value", selection.map(xt.invert, xt));
svg.dispatch("input");
}
}

function brushended(event) {
const selection = event.selection;
if (!selection) { gb.call(brush.move, defaultSelection) };
if (!event.sourceEvent || !selection) return;
let dayRange = selection.map(d => d3.timeDay.round(xt.invert(d)));
dayRange[1] = d3.timeSecond.offset(dayRange[1],-1)
d3.select(this).transition().call(brush.move, dayRange.map(xt));
}
function updateBrush(daterange) {
d3.select(this).transition().call(brush.move, daterange)
}

return svg.node();
}
Insert cell
dayRange = [d3.timeDay.offset(d3.timeDay(new Date), -14), d3.timeDay(new Date)]
Insert cell
xt = d3.scaleTime()
.domain([new Date(2021, 2, 15), d3.timeDay(new Date)])
.range([margin.left, width - margin.right])
Insert cell
xAxis = d3.axisBottom(xt).tickSizeOuter(0)
Insert cell
yt = d3.scaleBand()
.domain(mayID)
.range([margin.top, height - margin.bottom])
.padding(0.2)
Insert cell
yAxis = d3.axisRight(yt)
.tickSizeOuter(0)
Insert cell
yt2 = d3.scaleBand()
.domain(mayID)
.range([margin2.top, heightcontext - margin2.bottom])
.padding(0.2)
Insert cell
yAxis2 = d3.axisRight(yt2)
.tickSizeOuter(0)
Insert cell
colorScale = d3.scaleOrdinal()
.domain(["autonomy", "manual-only", "grounded-prod"])
.range(["#369040", "orange", "red"])
.unknown("#fff");
Insert cell
Insert cell
parseDate = d3.timeParse('%Y-%m-%d %H:%M:%S');
Insert cell
formatDate = d3.timeFormat('%b %e - %H%:%M');
Insert cell
height = 250
Insert cell
heightcontext = 60
Insert cell
margin = ({top: 0, right: 60, bottom: 30, left: 20})
Insert cell
margin2 = ({top: 0, right: 60, bottom: 30, left: 20})
Insert cell
update = {
const [day1, day2] = context
reliabilityChart.update(xt.copy().domain(context))
};
Insert cell
style = html`<style>
.tippy-box[data-theme ~= 'may'] {
background-color: white;
opacity: 0.9;
color: black;
}
</style>`
Insert cell
tooltip = {
reliabilityChart;
return tippy(".ttip", {
followCursor: true,
allowHTML: true,
theme: 'may'
})
}
Insert cell
formatDuration = d => {
const formatFloat = d3.format('.0f');
return d < 7200 ? `${formatFloat(d / 60)} minutes`
: d < 86400*2 ? `${formatFloat(d / 3600)} hrs`
: `${formatFloat(d / 86400)} days`
}
Insert cell
createTableTooltip = (d) => {
return `<table cellpadding="4">
<tr><th></th><th>${d.new_value}</th></tr>
<tr><td>Start Time</td><td align="right">${formatDate(d.start_time)}</td></tr>
<tr><td>End Time</td><td align="right">${formatDate(d.end_time)}</td></tr>
<tr><td>Duration</td><td align="right">${formatDuration(d.duration)}</td></tr>
</table>`
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more