Skip to content

Instantly share code, notes, and snippets.

@grayrest
Created April 12, 2016 18:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grayrest/371c36e882abc20dacf9d0d6925570fe to your computer and use it in GitHub Desktop.
Save grayrest/371c36e882abc20dacf9d0d6925570fe to your computer and use it in GitHub Desktop.
Mobx Uptime Boxes
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'));
<!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