1
0
Fork 0
empact/app/scripts/src/app.jsx

339 lines
10 KiB
React
Raw Normal View History

2015-03-07 14:13:47 +00:00
var Router = ReactRouter,
2015-03-08 08:42:40 +00:00
Link = Router.Link;
2015-03-07 14:13:47 +00:00
var Storage = {
set: function(category, key, value) {
window.localStorage.setItem(category +'-'+ key, JSON.stringify(value));
},
get: function(category, key) {
var val = window.localStorage.getItem(category +'-'+ key);
return val === null ? null : JSON.parse(val);
2015-03-07 14:13:47 +00:00
}
};
2015-03-07 14:13:47 +00:00
var App = React.createClass({
mixins: [Router.Navigation, Router.State],
2015-03-14 17:34:37 +00:00
orgsURL: '/api/orgs',
teamsURL: '/api/teams?org=',
usersURL: '/api/users?org=',
2015-03-07 14:13:47 +00:00
2015-03-07 08:34:35 +00:00
getInitialState: function() {
return {
orgs: [],
org: null,
teams: [],
team: null
};
2015-03-07 08:34:35 +00:00
},
componentDidMount: function() {
this.loadOrgs();
2015-03-07 08:34:35 +00:00
this.loadTeams();
2015-03-14 17:34:37 +00:00
this.loadUsers();
2015-03-07 08:34:35 +00:00
},
loadOrgs: function() {
$.get(this.orgsURL, function(res){
this.setState({orgs: res});
if (res !== null) {
for (var i = 0; i < res.length; i++) {
var org = res[i];
Storage.set('org', org.login, org);
}
}
}.bind(this));
},
2015-03-07 08:34:35 +00:00
loadTeams: function() {
$.get(this.teamsURL + this.getParams().org, function(res){
2015-03-14 17:34:37 +00:00
this.setState({teams: res});
if (res !== null) {
for (var i = 0; i < res.length; i++) {
var team = res[i];
Storage.set('team', team.name, team);
}
}
2015-03-07 08:34:35 +00:00
}.bind(this));
},
2015-03-14 17:34:37 +00:00
loadUsers: function() {
$.get(this.usersURL + this.getParams().org, function(res){
this.setState({users: res});
if (res !== null) {
for (var i = 0; i < res.length; i++) {
var user = res[i];
Storage.set('user', user.login, user);
}
}
}.bind(this));
},
render: function(){
return (
2015-03-15 10:39:33 +00:00
<div className="master">
<div className="app" id="app">
<Menu orgs={this.state.orgs} teams={this.state.teams} />
<Router.RouteHandler />
</div>
</div>
);
}
});
var Menu = React.createClass({
mixins: [Router.State],
2015-03-07 08:34:35 +00:00
render: function() {
var renderOrg = function(org) {
return (
<li key={'org-'+ org.login} className="nav org">
2015-03-15 12:10:02 +00:00
<Link to="org"
params={{org: org.login}}
query={this.getQuery()}>
{org.login}
</Link>
</li>
)
2015-03-15 12:10:02 +00:00
}.bind(this);
2015-03-07 08:34:35 +00:00
var renderTeam = function(team) {
return (
<li key={'team-'+ team.name} className="nav team">
2015-03-15 12:10:02 +00:00
<Link to="team"
params={{org: team.owner, team: team.name}}
query={this.getQuery()}>
{team.name}
</Link>
2015-03-07 14:13:47 +00:00
</li>
2015-03-07 08:34:35 +00:00
)
2015-03-15 12:10:02 +00:00
}.bind(this);
2015-03-07 08:34:35 +00:00
return (
2015-03-15 10:39:33 +00:00
<div className="menu">
2015-03-07 14:13:47 +00:00
<ul>
2015-03-16 10:46:18 +00:00
<li className="empact">
2015-03-11 12:10:11 +00:00
<Link to="org" params={this.getParams()} className="logo-button">
2015-03-10 12:48:57 +00:00
<div className="logo e">e</div>
2015-03-11 12:10:11 +00:00
<div className="logo m">m</div>
<div className="logo p">p</div>
<div className="logo a">a</div>
<div className="logo c">c</div>
<div className="logo t">t</div>
2015-03-10 12:48:57 +00:00
</Link>
2015-03-07 14:13:47 +00:00
</li>
2015-03-16 10:46:18 +00:00
<li className="nav header">Organizations:</li>
{this.props.orgs.map(renderOrg)}
2015-03-16 10:46:18 +00:00
<li className="nav header">Teams:</li>
{this.props.teams.map(renderTeam)}
2015-03-07 14:13:47 +00:00
</ul>
2015-03-15 10:39:33 +00:00
</div>
2015-03-07 14:13:47 +00:00
);
}
});
2015-03-10 08:04:59 +00:00
var Org = React.createClass({
2015-03-07 14:13:47 +00:00
render: function(){
return (
<Router.RouteHandler />
2015-03-07 14:13:47 +00:00
);
}
});
var Dashboard = React.createClass({
2015-03-10 08:24:19 +00:00
mixins: [Router.State],
2015-03-07 14:13:47 +00:00
render: function(){
var p = this.getParams(),
2015-03-14 17:41:32 +00:00
infoImage, infoTitle,
bcApi, bcItems,
sacApi, sacItems;
if (p.team) {
infoTitle = p.team;
bcApi = '/api/stat/teams/top';
bcItems = ['repo', 'user'],
sacApi = '/api/stat/teams/activity';
sacItems = ['user', 'repo'];
} else if (p.user) {
2015-03-14 17:34:37 +00:00
var info = Storage.get('user', p.user);
infoImage = info ? info.avatar_url : null;
infoTitle = info && info.name ? info.name : p.user;
bcApi = '/api/stat/users/top';
bcItems = ['repo'],
sacApi = '/api/stat/users/activity';
sacItems = ['repo'];
} else if (p.repo) {
infoTitle = p.repo;
bcApi = '/api/stat/repos/top';
bcItems = ['user', 'team'],
sacApi = '/api/stat/repos/activity';
sacItems = ['user', 'team'];
} else {
var info = Storage.get('org', p.org);
infoImage = info.avatar_url;
infoTitle = info.login;
bcApi = '/api/stat/orgs/top';
bcItems = ['repo', 'team', 'user'],
sacApi = '/api/stat/orgs/activity';
sacItems = ['team', 'user', 'repo'];
}
2015-03-07 14:13:47 +00:00
return (
2015-03-15 10:39:33 +00:00
<div className="content">
2015-03-14 17:41:32 +00:00
<InfoBlock image={infoImage} title={infoTitle} />
<BarChart api={bcApi} params={this.getParams()} items={bcItems} />
<StackedAreaChart api={sacApi} params={this.getParams()} items={sacItems} />
2015-03-15 10:39:33 +00:00
</div>
2015-03-07 14:13:47 +00:00
);
}
});
var NotFound = React.createClass({
render: function(){
return (
2015-03-15 10:39:33 +00:00
<div className="content">NOT FOUND :(</div>
2015-03-07 08:34:35 +00:00
);
}
});
2015-03-07 14:13:47 +00:00
var SelectOrg = React.createClass({
render: function(){
return (
2015-03-15 10:39:33 +00:00
<div className="content">Please select organization from the menu!</div>
);
}
});
2015-03-10 08:24:19 +00:00
var InfoBlock = React.createClass({
render: function() {
return (
<div className="info-block">
<div className={'img'+ (this.props.image ? '' : ' empty')}
style={{backgroundImage: "url("+ (this.props.image || '') +")"}} />
2015-03-10 08:24:19 +00:00
<h1>{this.props.title}</h1>
</div>
)
}
});
2015-03-14 15:54:27 +00:00
var WeekIntervalSelector = React.createClass({
2015-03-15 12:10:02 +00:00
mixins: [ReactRouter.Navigation, ReactRouter.State],
2015-03-14 15:54:27 +00:00
monthNames: [
'Jan', 'Feb', 'Mar',
'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'
],
2015-03-15 10:39:33 +00:00
getInitialState: function() {
2015-03-14 15:54:27 +00:00
var ms = 1000,
daySeconds = 86400,
weekSeconds = daySeconds*7,
today = new Date(),
sunday = new Date(today - daySeconds*ms*today.getDay()),
perfectSunday = new Date(Date.UTC(sunday.getFullYear(), sunday.getMonth(), sunday.getDate())),
lastWeek = perfectSunday.setHours(0)/ms,
firstWeek = lastWeek - 51*weekSeconds;
var weeks = [];
for (var i = lastWeek; i >= firstWeek; i -= weekSeconds) {
weeks.push(i);
};
2015-03-15 12:10:02 +00:00
var from = (this.getQuery().f ? parseInt(this.getQuery().f, 10)*100 : lastWeek - 7*weekSeconds),
to = (this.getQuery().t ? parseInt(this.getQuery().t, 10)*100 : lastWeek);
2015-03-14 15:54:27 +00:00
2015-03-15 12:10:02 +00:00
return {
from: from,
to: to,
weeks: weeks
};
},
componentDidMount: function() {
this.updateLocation();
},
handleChange: function(thing, e) {
var patch = {};
patch[thing] = e.target.value;
this.setState(patch, this.updateLocation);
},
updateLocation: function() {
this.transitionTo(document.location.pathname, null, {
f: this.state.from/100,
t: this.state.to/100
});
},
formatDate: function(ts, showYear) {
var d = new Date(ts*1000),
day = d.getDate(),
month = this.monthNames[d.getMonth()],
year = (''+ d.getFullYear()).slice(2);
if (showYear) {
return month +' '+ day +" '"+ year;
} else {
return month +' '+ day;
}
},
render: function() {
var weeksBefore = _(this.state.weeks)
.filter(function(week) {
return week <= this.state.to;
}.bind(this))
.sort()
.reverse()
.value();
var weeksAfter = _(this.state.weeks)
.filter(function(week) {
return week >= this.state.from;
}.bind(this))
.sort()
.value();
var renderOption = function(ts) {
2015-03-14 15:54:27 +00:00
return (
2015-03-15 12:10:02 +00:00
<option key={ts} value={ts}>{this.formatDate(ts, true)}</option>
);
2015-03-14 15:54:27 +00:00
}.bind(this);
2015-03-15 10:39:33 +00:00
2015-03-14 15:54:27 +00:00
return (
2015-03-15 10:39:33 +00:00
<div className="week-selector">
2015-03-15 12:10:02 +00:00
<div ref="from" className="week">
<span ref="label" className="label">{this.formatDate(this.state.from)}</span>
<select ref="select" value={this.state.from} onChange={this.handleChange.bind(this, 'from')}>
{weeksBefore.map(renderOption)}
</select>
2015-03-15 10:39:33 +00:00
</div>
&mdash;
2015-03-15 12:10:02 +00:00
<div ref="to" className="week">
<span ref="label" className="label">{this.formatDate(this.state.to)}</span>
<select ref="select" value={this.state.to} onChange={this.handleChange.bind(this, 'to')}>
{weeksAfter.map(renderOption)}
</select>
2015-03-15 10:39:33 +00:00
</div>
</div>
2015-03-14 15:54:27 +00:00
);
}
});
2015-03-07 14:13:47 +00:00
var routes = [
<Router.Route name="root" path="/app/" handler={App}>
<Router.DefaultRoute handler={SelectOrg} />
<Router.NotFoundRoute handler={NotFound} />
<Router.Route name="org" path=":org" handler={Org}>
<Router.DefaultRoute handler={Dashboard} />
<Router.Route name="team" path="teams/:team" handler={Dashboard} />
<Router.Route name="user" path="users/:user" handler={Dashboard} />
<Router.Route name="repo" path="repos/:repo" handler={Dashboard} />
2015-03-08 08:42:40 +00:00
</Router.Route>
</Router.Route>
];
2015-03-07 14:13:47 +00:00
Router.run(routes, Router.HistoryLocation, function(Handler) {
React.render(<Handler />, document.body);
2015-03-07 14:13:47 +00:00
});