parent
b8bbfc7cd3
commit
1954a62c4b
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,21 @@
|
|||||||
|
circle {
|
||||||
|
r:5;
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
circle.highlighted {
|
||||||
|
fill:red;
|
||||||
|
}
|
||||||
|
#container {
|
||||||
|
overflow: visible;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 20px 40px;
|
||||||
|
}
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding:10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
@ -0,0 +1,99 @@
|
|||||||
|
const WIDTH = 800;
|
||||||
|
const HEIGHT = 600;
|
||||||
|
|
||||||
|
let instances;
|
||||||
|
const selectedInstances = [];
|
||||||
|
let xScale, yScale;
|
||||||
|
const parseTime = d3.timeParse("%B %e, %Y");
|
||||||
|
const formatTime = d3.timeFormat("%B %e, %Y");
|
||||||
|
|
||||||
|
|
||||||
|
const renderPoints = () => {
|
||||||
|
d3.select('#points').html('');
|
||||||
|
const circles = d3.select('#points')
|
||||||
|
.selectAll('circle')
|
||||||
|
.data(instances, (datum) => {
|
||||||
|
return datum.id
|
||||||
|
});
|
||||||
|
circles.enter().append('circle');
|
||||||
|
|
||||||
|
d3.selectAll('circle')
|
||||||
|
.attr('cy', (datum, index) => {
|
||||||
|
return yScale(datum.ninety_day_outcomes);
|
||||||
|
});
|
||||||
|
|
||||||
|
d3.selectAll('circle')
|
||||||
|
.attr('cx', (datum, index) => {
|
||||||
|
return xScale(parseTime(datum.graduation_date));
|
||||||
|
});
|
||||||
|
|
||||||
|
d3.selectAll('circle')
|
||||||
|
.classed('highlighted', (datum, index)=>{
|
||||||
|
return datum.highlighted
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const setupGraph = ()=>{
|
||||||
|
d3.select('svg');
|
||||||
|
d3.select('svg')
|
||||||
|
.style('width', WIDTH)
|
||||||
|
.style('height', HEIGHT);
|
||||||
|
|
||||||
|
xScale = d3.scaleTime();
|
||||||
|
xScale.range([0,WIDTH]);
|
||||||
|
const xDomain = d3.extent(instances, (datum, index) => {
|
||||||
|
return parseTime(datum.graduation_date);
|
||||||
|
});
|
||||||
|
xScale.domain(xDomain);
|
||||||
|
|
||||||
|
yScale = d3.scaleLinear();
|
||||||
|
yScale.range([HEIGHT, 0]);
|
||||||
|
const yDomain = d3.extent(instances, (datum, index) => {
|
||||||
|
return datum.ninety_day_outcomes;
|
||||||
|
})
|
||||||
|
yScale.domain(yDomain);
|
||||||
|
}
|
||||||
|
|
||||||
|
const createAxes = () => {
|
||||||
|
const bottomAxis = d3.axisBottom(xScale);
|
||||||
|
d3.select('#container')
|
||||||
|
.append('g')
|
||||||
|
.attr('id', 'x-axis')
|
||||||
|
.call(bottomAxis)
|
||||||
|
.attr('transform', 'translate(0,'+HEIGHT+')');
|
||||||
|
|
||||||
|
const leftAxis = d3.axisLeft(yScale);
|
||||||
|
d3.select('#container')
|
||||||
|
.append('g')
|
||||||
|
.attr('id', 'y-axis')
|
||||||
|
.call(leftAxis);
|
||||||
|
}
|
||||||
|
|
||||||
|
const createFormSubmissionHandler = () => {
|
||||||
|
d3.select('form').on('submit', (event)=>{
|
||||||
|
event.preventDefault();
|
||||||
|
const instanceID = parseInt(d3.select('input[type="text"]').property('value'))
|
||||||
|
selectedInstances.push(instanceID);
|
||||||
|
const list = d3.select('ul');
|
||||||
|
list.html('');
|
||||||
|
for(instance of selectedInstances){
|
||||||
|
list.append('li').html(instance)
|
||||||
|
}
|
||||||
|
for(instance of instances){
|
||||||
|
if(instance.instance_id == instanceID){
|
||||||
|
instance.highlighted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderPoints()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = async ()=>{
|
||||||
|
instances = await d3.json('/instances');
|
||||||
|
instances.forEach(instance => instance.highlighted = false)
|
||||||
|
setupGraph();
|
||||||
|
createAxes();
|
||||||
|
renderPoints();
|
||||||
|
createFormSubmissionHandler();
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title></title>
|
||||||
|
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/app.js"></script>
|
||||||
|
<link rel="stylesheet" href="app.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Outcomes Tracker</h1>
|
||||||
|
<p>See how instances did in comparisson to others</p>
|
||||||
|
<section>
|
||||||
|
<h2>The Graph</h2>
|
||||||
|
<dl>
|
||||||
|
<dt>X-Axis:</dt>
|
||||||
|
<dd>Graduation Date</dd>
|
||||||
|
<dt>Y-Axis:</dt>
|
||||||
|
<dd>Percentage of graduates that got a job within 90 days of graduation.</dd>
|
||||||
|
</dl>
|
||||||
|
<svg id="container">
|
||||||
|
<svg>
|
||||||
|
<g id="points"></g>
|
||||||
|
</svg>
|
||||||
|
</svg>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2>Choose Instances To Highlight</h2>
|
||||||
|
<form>
|
||||||
|
<input type="text" placeholder="Insance ID"/>
|
||||||
|
<input type="submit"/>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2>Highlighted Instances</h2>
|
||||||
|
<ul></ul>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const app = express();
|
||||||
|
const pg = require('pg');
|
||||||
|
const client = new pg.Client({
|
||||||
|
database:"outcomes_tracker"
|
||||||
|
})
|
||||||
|
|
||||||
|
app.use(express.static('public'))
|
||||||
|
|
||||||
|
app.get('/instances', async (req, res)=>{
|
||||||
|
const instances = await client.query("SELECT * FROM instances WHERE course = 'ONL-SEIR-21215'");
|
||||||
|
res.json(instances.rows);
|
||||||
|
})
|
||||||
|
|
||||||
|
client.connect();
|
||||||
|
app.listen(3000, ()=>{
|
||||||
|
console.log('listening');
|
||||||
|
})
|
||||||
Loading…
Reference in new issue