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
|
|
|
|
2015-03-10 09:58:12 +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-10 09:58:12 +00:00
|
|
|
};
|
2015-03-07 14:13:47 +00:00
|
|
|
|
2015-03-10 09:58:12 +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() {
|
2015-03-10 09:58:12 +00:00
|
|
|
return {
|
|
|
|
orgs: [],
|
|
|
|
org: null,
|
|
|
|
teams: [],
|
|
|
|
team: null
|
|
|
|
};
|
2015-03-07 08:34:35 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
componentDidMount: function() {
|
2015-03-10 09:58:12 +00:00
|
|
|
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
|
|
|
},
|
|
|
|
|
2015-03-10 09:58:12 +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() {
|
2015-03-10 09:58:12 +00:00
|
|
|
$.get(this.teamsURL + this.getParams().org, function(res){
|
2015-03-14 17:34:37 +00:00
|
|
|
this.setState({teams: res});
|
2015-03-10 09:58:12 +00:00
|
|
|
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));
|
|
|
|
},
|
|
|
|
|
2015-03-10 09:58:12 +00:00
|
|
|
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>
|
2015-03-14 15:54:27 +00:00
|
|
|
<WeekIntervalSelector />
|
2015-03-15 10:39:33 +00:00
|
|
|
</div>
|
2015-03-10 09:58:12 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var Menu = React.createClass({
|
|
|
|
mixins: [Router.State],
|
|
|
|
|
2015-03-07 08:34:35 +00:00
|
|
|
render: function() {
|
2015-03-10 09:58:12 +00:00
|
|
|
var renderOrg = function(org) {
|
|
|
|
return (
|
|
|
|
<li key={'org-'+ org.login} className="nav org">
|
|
|
|
<Link to="org" params={{org: org.login}}>{org.login}</Link>
|
|
|
|
</li>
|
|
|
|
)
|
|
|
|
};
|
2015-03-07 08:34:35 +00:00
|
|
|
var renderTeam = function(team) {
|
|
|
|
return (
|
2015-03-10 09:58:12 +00:00
|
|
|
<li key={'team-'+ team.name} className="nav team">
|
2015-03-08 10:02:14 +00:00
|
|
|
<Link to="team" params={{org: team.owner, team: team.name}}>{team.name}</Link>
|
2015-03-07 14:13:47 +00:00
|
|
|
</li>
|
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-11 12:10:11 +00:00
|
|
|
<li key="empact">
|
|
|
|
<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-10 09:58:12 +00:00
|
|
|
<li key="orgs-header" className="nav header">Organizations:</li>
|
|
|
|
{this.props.orgs.map(renderOrg)}
|
2015-03-07 14:13:47 +00:00
|
|
|
<li key="teams-header" className="nav header">Teams:</li>
|
2015-03-10 09:58:12 +00:00
|
|
|
{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 (
|
2015-03-10 09:58:12 +00:00
|
|
|
<Router.RouteHandler />
|
2015-03-07 14:13:47 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-03-11 20:18:14 +00:00
|
|
|
var Dashboard = React.createClass({
|
2015-03-10 08:24:19 +00:00
|
|
|
mixins: [Router.State],
|
2015-03-10 09:58:12 +00:00
|
|
|
|
2015-03-07 14:13:47 +00:00
|
|
|
render: function(){
|
2015-03-11 20:18:14 +00:00
|
|
|
var p = this.getParams(),
|
2015-03-14 17:41:32 +00:00
|
|
|
infoImage, infoTitle,
|
2015-03-11 20:18:14 +00:00
|
|
|
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;
|
2015-03-11 20:18:14 +00:00
|
|
|
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-10 09:58:12 +00:00
|
|
|
|
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} />
|
2015-03-11 20:18:14 +00:00
|
|
|
<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
|
|
|
|
2015-03-10 09:58:12 +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 09:58:12 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-03-10 08:24:19 +00:00
|
|
|
var InfoBlock = React.createClass({
|
|
|
|
render: function() {
|
|
|
|
return (
|
|
|
|
<div className="info-block">
|
2015-03-14 15:53:12 +00:00
|
|
|
<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({
|
|
|
|
monthNames: [
|
|
|
|
'Jan', 'Feb', 'Mar',
|
|
|
|
'Apr', 'May', 'Jun',
|
|
|
|
'Jul', 'Aug', 'Sep',
|
|
|
|
'Oct', 'Nov', 'Dec'
|
|
|
|
],
|
|
|
|
|
2015-03-15 10:39:33 +00:00
|
|
|
getInitialState: function() {
|
|
|
|
return {
|
|
|
|
from: 0,
|
|
|
|
to: 0
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
2015-03-14 15:54:27 +00:00
|
|
|
componentDidMount: function() {
|
2015-03-15 10:39:33 +00:00
|
|
|
// window.addEventListener('resize', this.resize);
|
2015-03-14 15:54:27 +00:00
|
|
|
},
|
|
|
|
|
2015-03-15 10:39:33 +00:00
|
|
|
showSelector: function() {
|
|
|
|
|
2015-03-14 15:54:27 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
render: function() {
|
|
|
|
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);
|
|
|
|
};
|
|
|
|
|
|
|
|
var renderWeek = function(week, i) {
|
|
|
|
var d = new Date(week*ms),
|
|
|
|
month = this.monthNames[d.getMonth()],
|
2015-03-15 10:39:33 +00:00
|
|
|
season = this.seasons[d.getMonth()],
|
2015-03-14 15:54:27 +00:00
|
|
|
day = d.getDate();
|
|
|
|
|
|
|
|
return (
|
2015-03-15 10:39:33 +00:00
|
|
|
<div key={'week-'+ i} ref="blocks" className="week">
|
2015-03-14 15:54:27 +00:00
|
|
|
<div key={''+ i +'-week'} className="square">{day}</div>
|
2015-03-15 10:39:33 +00:00
|
|
|
<div key={''+ i +'-month'} className={'square '+ season}>{month}</div>
|
2015-03-14 15:54:27 +00:00
|
|
|
<div key={''+ i +'-day'} className="square">{day}</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}.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">
|
|
|
|
<div className="week">
|
|
|
|
Mar 9
|
|
|
|
</div>
|
|
|
|
—
|
|
|
|
<div className="week">
|
|
|
|
Apr 27
|
|
|
|
</div>
|
|
|
|
</div>
|
2015-03-14 15:54:27 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-03-07 14:13:47 +00:00
|
|
|
var routes = [
|
2015-03-10 09:58:12 +00:00
|
|
|
<Router.Route name="root" path="/app/" handler={App}>
|
|
|
|
<Router.DefaultRoute handler={SelectOrg} />
|
|
|
|
<Router.NotFoundRoute handler={NotFound} />
|
|
|
|
<Router.Route name="org" path=":org" handler={Org}>
|
2015-03-11 20:18:14 +00:00
|
|
|
<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>
|
2015-03-10 09:58:12 +00:00
|
|
|
</Router.Route>
|
|
|
|
];
|
2015-03-07 14:13:47 +00:00
|
|
|
Router.run(routes, Router.HistoryLocation, function(Handler) {
|
2015-03-10 09:58:12 +00:00
|
|
|
React.render(<Handler />, document.body);
|
2015-03-07 14:13:47 +00:00
|
|
|
});
|