react github timeline

by Victor Melnik

HTML

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="timeline">
</div>

CSS

body {
  font-family: Helvetica, Verdana, Arial, sans-serif;
  font-size: 16px;
  font-weight: 300;
}

#timeline h1 {
  text-align: center;
}

.progress {
  position: relative;
  display: block;
  height: 2px;
  margin: 0 auto;
  width: 70%;
}
.progress div {
  position: absolute;
  top: 0;
  display: block;
  height: 2px;
}
.progress .background {
  background-color: #c7c7c7;
  width: 100%;
}
.progress .line {
  background-color: #5282d2;
  z-index: 999;
}

#timeline {
  width: 90%;
  margin: 0 auto;
}

#timeline ul {
  list-style: none;
  margin: 10px 0;
  padding: 0;
}

#timeline li {
  display: block;
  position: relative;
  background-color: #FEFEFE;
  border: 2px solid #FEFEFE;
  margin: 0 auto 10px;
  padding: 6px;
  padding-bottom: 5px;
  box-shadow: 0px 1px 2px rgba(34, 25, 25, 0.4);
}

.avatar {
  float: left;
  max-width: 48px;
  max-height: 48px;
  margin-bottom: 5px;
}

.headline {
  float: left;
  margin-left: 8px;
}

.user {
  color: #000;
  font-size: 120%;
  font-weight: bold;
}

.small,
.time {
  font-size: 80%;
  color: #777;
}

.time {
  margin-bottom: 5px;
  font-size: small;
}

.clearfix {
  clear: both;
}

Babel + JSX

// Hack for jsfiddle, in normal app you would write it as follows:
// import React, { Component } from 'react';
const { Component } = React;

class App extends Component {
  state = {
    time: 0,
    timeMax: 6,
    events: []
  }
  
  componentWillMount() {
    this.onUpdate();
  }
  
  onUpdate = () => {
  	var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://api.github.com/events');
    xhr.onload = () => {
      const events = JSON.parse(xhr.responseText);
      const timeMax = xhr.getResponseHeader("X-Poll-Interval");
      this.setState({ time: 0, timeMax, events })
      this.startTimer();
    };
    xhr.send();
  };
  
  startTimer = () => {    
    this.timerID = setInterval(this.tick, 1000);
  };
  
  tick = () => {
    const {time, timeMax} = this.state
    if (time >= timeMax) {
      clearInterval(this.timerID);
      this.setState({ time: 0, timeMax: 10 })
      this.onUpdate()
    } else {
      this.setState({ time: time + 1, timeMax })
    }
  };
  
  render() {
    return (
      <div>
        <h1>GitHub Timeline</h1>
        <Timeline time={this.state.time} timeMax={this.state.timeMax} />
        <Events events={this.state.events} />
      </div>
    )
  }
}

class Timeline extends Component {
  render() {
    const { time, timeMax } = this.props;
    const width = (Math.floor(time * 100 / timeMax) + '%')
    return (
    	<div className="progress">
        <div className="line" style={{ width }}></div>
        <div className="background"></div>
      </div>
    )
  }
}

class Events extends Component {
	render() {
  	return (
    	<ul>
      {
        this.props.events.map(e => <Event key={e.id} event={e} />)
      }
      </ul>
    )
  }
}

class Event extends Component {
	formatDate = (v) => v.replace(/T|Z/g, ' ');
  
  renderEvent(event) {
  	switch (event.type) {
    	case 'CommitCommentEvent':
      	return <CommitComment event={event}/>
      case 'CreateEvent':
      	return <Create event={event}/>
      case 'DeleteEvent':
   ...