Created
April 12, 2016 18:12
-
-
Save grayrest/371c36e882abc20dacf9d0d6925570fe to your computer and use it in GitHub Desktop.
Mobx Uptime Boxes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component} from 'react'; | |
import ReactDOM from 'react-dom'; | |
import {observable, computed} from 'mobx'; | |
import {observer} from 'mobx-react'; | |
// import DevTools from 'mobx-react-devtools'; | |
class Server { | |
@observable days = []; | |
@observable name = ""; | |
@computed get upDays() { | |
return this.days.reduce((acc, day) => acc + (day.up ? 1 : 0), 0); | |
} | |
@computed get maxStreak() { | |
let out = this.days.reduce((acc, day) => { | |
if (day.up) { | |
acc.streak += 1; | |
if (acc.streak > acc.maxStreak) { acc.maxStreak = acc.streak; } | |
} else { | |
acc.streak = 0; | |
} | |
return acc; | |
}, {streak: 0, maxStreak: 0}); | |
return out.maxStreak; | |
} | |
constructor(name) { | |
this.name = name; | |
for(let i = 0; i < 365; i++) { | |
let up = Math.random() > 0.2; | |
this.days.push({number: i, up: up}); | |
} | |
} | |
update() { | |
for(let i = 0; i < 365; i++) { | |
let up = Math.random() > 0.2; | |
if (this.days[i].up != up) { | |
this.days[i].up = up; | |
} | |
} | |
} | |
} | |
class State { | |
@observable fps = 0; | |
servers = []; | |
} | |
@observer | |
class UptimeDay extends Component { | |
render() { | |
let day = this.props.day; | |
return <div className="uptime-day" > | |
<span className="uptime-day-status" style={{backgroundColor: day.up ? '#8cc665' : '#ccc'}} /> | |
<span className="hover">{day.number}: {day.up ? 'Servers operational!' : 'Red alert!'}</span> | |
</div> | |
} | |
} | |
@observer | |
class ServerUptime extends Component { | |
render() { | |
let server = this.props.server; | |
return <div className="server-uptime"> | |
<h1>{server.name}</h1> | |
<h2>{server.upDays}</h2> | |
<h2>Biggest Streak: {server.maxStreak}</h2> | |
<div className="days">{server.days.map(day => <UptimeDay day={day} key={day.number} />)}</div> | |
</div> | |
} | |
} | |
@observer | |
class Shell extends Component { | |
render() { | |
return <div id="uptime-boxes"> | |
<div id="fps">{this.props.fps} FPS</div> | |
{this.props.servers.map((server, i) => <ServerUptime server={server} key={i} />)} | |
</div> | |
} | |
} | |
let state = new State(); | |
state.servers = ["Stefan"].map(name => new Server(`${name}'s Server`)); | |
// begin hacky benchmarking stuff | |
function exponentialMovingAverage(alpha) { | |
return (val, next) => val ? val + alpha * (next - val) : next; | |
} | |
let clear = null; | |
let lastFrame = 0; | |
let started = false; | |
let fps = 0; | |
let ema = exponentialMovingAverage(2/121); | |
function rafCallback() { | |
let thisFrame = performance.now(); | |
if (lastFrame) { | |
fps = ema(fps, (1000 / (thisFrame - lastFrame))) | |
} | |
state.fps = fps; | |
state.servers.forEach(server => server.update()); | |
lastFrame = thisFrame; | |
clear = requestAnimationFrame(rafCallback); | |
} | |
window.togglePlay = function () { | |
if (started) { | |
window['playpause'].innerHTML = "Play"; | |
cancelAnimationFrame(clear); | |
clear = null; | |
fps = 0; | |
lastFrame = 0; | |
started = false; | |
} else { | |
window['playpause'].innerHTML = "Pause"; | |
started = true; | |
lastFrame = 0; | |
fps = 0; | |
clear = requestAnimationFrame(rafCallback); | |
} | |
} | |
ReactDOM.render(<Shell fps={state.fps} servers={state.servers} />, document.getElementById('output')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<title>Uptime Boxes</title> | |
<style type="text/css"> | |
html, body { | |
margin: 0; | |
padding: 0; | |
font-family: sans-serif; | |
} | |
#fps { | |
position: fixed; | |
top: 0px; | |
right: 0px; | |
padding: 32px; | |
font-size: 32px; | |
text-align: right; | |
} | |
* { | |
box-sizing: border-box; | |
} | |
.server-uptime { | |
display: block; | |
overflow: hidden; | |
margin: 0 auto; | |
width: 50%; | |
} | |
.server-uptime + .server-uptime { | |
margin: 20px auto 0 auto; | |
border-top: 1px solid #999; | |
} | |
.days { | |
display: flex; | |
flex-direction: row; | |
flex-flow: wrap; | |
} | |
.uptime-day { | |
display: flex; | |
} | |
span.uptime-day-status { | |
width: 10px; | |
height: 10px; | |
margin: 1px; | |
} | |
.hover { | |
display: none; | |
} | |
.uptime-day-status:hover + .hover { | |
display: flex; | |
position: absolute; | |
margin-top: -35px; | |
margin-left: -30px; | |
border-radius: 4px; | |
color: #eee; | |
background-color: #333; | |
padding: 10px; | |
font-size: 11px; | |
} | |
</style> | |
</head> | |
<body> | |
<button id="playpause" onclick='togglePlay()'>Play</button> | |
<div id="output"></div> | |
<script src="/static/bundle.js"></script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment