diff --git a/components/404.jsx b/components/404.jsx
new file mode 100644
index 0000000..c005254
--- /dev/null
+++ b/components/404.jsx
@@ -0,0 +1,16 @@
+var React = require('react');
+
+
+var PageNotFound = React.createClass({
+ render: function() {
+ return (
+
+
+
404: Page not found
+
+
+ )
+ }
+});
+
+module.exports = PageNotFound;
diff --git a/components/contact.jsx b/components/contact.jsx
new file mode 100644
index 0000000..734136c
--- /dev/null
+++ b/components/contact.jsx
@@ -0,0 +1,143 @@
+var React = require('react');
+var Formsy = require('formsy-react');
+var Textarea = require('react-textarea-autosize');
+
+var Nav = require('./nav');
+var Footer = require('./footer');
+
+
+var ContactPage = React.createClass({
+ getInitialState: function() {
+ return {
+ canSubmit: false
+ };
+ },
+
+ enableButton: function () {
+ this.setState({
+ canSubmit: true
+ });
+ },
+
+ disableButton: function () {
+ this.setState({
+ canSubmit: false
+ });
+ },
+
+ resetForm: function() {
+ this.refs.form.reset();
+ this.refs.form.inputs.emailContent.setValue('');
+ },
+
+ handleSubmit: function(data) {
+ var data = JSON.stringify({
+ name: data.fullName,
+ email: data.email,
+ content: data.emailContent
+ });
+
+ $.ajaxSetup({
+ beforeSend: function(xhr, settings) {
+ xhr.setRequestHeader("X-CSRFToken", Django.csrf_token());
+ xhr.setRequestHeader("Content-Type", 'application/json');
+ }
+ });
+
+ $.ajax({
+ type: 'POST',
+ url: '/api/public/contact/',
+ data: data,
+ success: function(data) { this.resetForm() }.bind(this),
+ error: function(error) { }
+ });
+
+ },
+
+ render: function() {
+ return (
+
+
+
+ Get in touch with us
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+});
+
+var FullNameInput = React.createClass({
+ mixins: [Formsy.Mixin],
+
+ changeValue: function (event) {
+ this.setValue(event.currentTarget.value);
+ },
+
+ render: function () {
+ var className = this.showRequired() ? 'required' : this.showError() ? 'error' : null;
+
+ var errorMessage = this.getErrorMessage();
+
+ return (
+
+
+ {errorMessage}
+
+ );
+ }
+});
+
+var EmailInput = React.createClass({
+ mixins: [Formsy.Mixin],
+
+ changeValue: function (event) {
+ this.setValue(event.currentTarget.value);
+ },
+
+ render: function () {
+ var className = this.showRequired() ? 'required' : this.showError() ? 'error' : null;
+
+ var errorMessage = this.getErrorMessage();
+
+ return (
+
+
+ {errorMessage}
+
+ );
+ }
+});
+
+var ContentTextarea = React.createClass({
+ mixins: [Formsy.Mixin],
+
+ changeValue: function (event) {
+ this.setValue(event.currentTarget.value);
+ },
+
+ render: function () {
+ var className = this.showRequired() ? 'required' : this.showError() ? 'error' : null;
+
+ var errorMessage = this.getErrorMessage();
+
+ return (
+
+
+ {errorMessage}
+
+ );
+ }
+});
+
+module.exports = ContactPage;
diff --git a/components/cub.jsx b/components/cub.jsx
index 00ff9ff..5c31198 100644
--- a/components/cub.jsx
+++ b/components/cub.jsx
@@ -1,650 +1,25 @@
var React = require('react');
-var ReactDOM = require('react-dom');
-
-var Formsy = require('formsy-react');
var History = require('history');
-var Link = require('react-router').Link;
+var ReactDOM = require('react-dom');
var Router = require('react-router').Router;
var Route = require('react-router').Route;
-var Redirect = require('react-router').Redirect;
-var ReactPaginate = require('react-paginate');
-var Textarea = require('react-textarea-autosize');
-
-const history = History.createHistory();
-const per_page = 10;
-
-
-const MAX_PROGRESS = 1000
-
-
-var Repo = React.createClass({
- render: function() {
- var repo_score = this.props.repo.watchers_count * PointsList.watch;
- repo_score += this.props.repo.stargazers_count * PointsList.star;
-
- return (
-
-
-
{repo_score}
-
Points
-
-
-
{this.props.repo.description}
-
- Forked: {this.props.repo.fork}
- Forks: {this.props.repo.forks_count}
- Stars: {this.props.repo.stargazers_count}
- Watchers: {this.props.repo.watchers_count}
-
-
- )
- }
-})
-
-
-var RepoList = React.createClass({
- getInitialState: function() {
- return {
- repos: [],
- offset: 0,
- pageNum: 1,
- nextOffset: per_page,
- previousOffset: 0
- }
- },
-
- getRepoList: function() {
- var offset = this.state.offset;
- var nextOffset = offset + per_page;
- var previousOffset = (offset - per_page < 1) ? 0 : offset - per_page;
- var url = '/api/v1/repository/?offset=' + offset + '&limit=' + per_page;
-
- $.get(url, function(res) {
- this.setState({
- repos: res.objects,
- nextOffset: nextOffset,
- previousOffset: previousOffset,
- pageNum: Math.ceil(res.meta.total_count / per_page )})
- }.bind(this));
- },
-
- componentDidMount: function() {
- if (this.props.username !== 'undefined' && this.isMounted()) {
- this.getRepoList();
-
- } else {
- // Load demo page
- this.setState({
- repos : {},
- offset : null,
- pageNum : null
- });
- }
- },
-
- handleClick: function(event) {
- var pageSelected = event.selected;
-
- this.setState({
- offset: pageSelected * per_page
- }, () => {
- this.getRepoList();
- });
- },
-
- render: function() {
- return (
-
-
Your score
-
-
Your contributions
- { this.state.repos.map(function(repo, i) {
- return (
)
- }, this)}
-
-
... }
- pageNum={this.state.pageNum}
- marginPagesDisplayed={2}
- pageRangeDisplayed={5}
- clickCallback={this.handleClick}
- containerClassName={"pagination"}
- subContainerClassName={"pagination-pages"}
- activeClassName={"active"} />
-
- );
- }
-});
-
-
-var PointsList = React.createClass({
- statics: {
- watch : 10,
- star : 20
- },
-
- render: function() {
- return (
-
-
Points:
-
- Watcher: {PointsList.watch}p
- Star: {PointsList.star}p
-
-
- );
- }
-});
-
-
-var ProfileStats = React.createClass({
- getInitialState: function() {
- return {
- repos_count: null,
- repos_score: null,
- repos_top_name: null,
- repos_top_score: null,
- progress: 0,
- login_message: null
- }
- },
-
- componentDidMount: function() {
- if (typeof username === 'undefined') {
- if (typeof this.props.username === 'undefined') {
- // User not authenticated, looking at default page
- // Show demo data
- this.setState({
- repos_count: '###',
- repos_score: '###',
- repos_top_name: '###',
- repos_top_score: '__',
- progress: 15,
- login_message: 'You need to login to see your own metrics.'
- });
-
- } else {
- // User is not authenticated, looking at someone
- // Show some real data
- this.setState({
- repos_count: '###',
- repos_score: '###',
- repos_top_name: '###',
- repos_top_score: '__',
- progress: 0,
- login_message: 'You need to login to see more metrics.'
- });
- }
-
- } else {
- if (typeof this.props.username === 'undefined') {
- // User is authenticated, looking at default page
- this.setState(this.state);
-
- } else if (this.props.username == username) {
- // User is authenticated, looking at own profile
- var offset = 0;
- var per_page = 999;
- var url = '/api/v1/repository/?offset=' + offset + '&limit=' + per_page;
-
- $.get(url, function(res) {
- if (this.isMounted()) {
-
- // Compute total repo score and max repo
- var total_score = 0;
- var max_score = 0;
- var max_repo = '';
- for (var i in res.objects) {
- var score = 0;
- score += res.objects[i].watchers_count * PointsList.watch;
- score += res.objects[i].stargazers_count * PointsList.star;
-
- if (score > max_score) { max_score = score; max_repo = res.objects[i].name }
- total_score += score;
- }
-
- this.setState({
- repos_count: res.objects.length,
- repos_score: total_score,
- repos_top_name: max_repo,
- repos_top_score: max_score,
- progress: 100 * total_score / MAX_PROGRESS
- });
- }
- }.bind(this));
-
- } else {
- // User is authenticated, looking at someone
- this.setState({
- repos_count: null,
- repos_score: null,
- repos_top_name: null,
- repos_top_score: null,
- progress: 0
- });
- }
- }
- },
-
- render: function() {
- return(
-
-
-
Noob
-
Master
-
-
- {this.state.progress + '%'}
-
-
-
Rockstar
-
-
-
-
Most important repo
-
{this.state.repos_top_name}
-
{this.state.repos_top_score + " points"}
-
-
-
Total score
-
{this.state.repos_score}
-
for all repos
-
-
-
Own contributions count
-
{this.state.repos_count}
-
repositories
-
-
- { this.state.login_message ?
-
: ''}
-
- );
- }
-});
-
-var Profile = React.createClass({
- getInitialState: function() {
- return {
- avatar_url : null,
- name : null,
- username : null,
- email : null,
- progress : 70,
- }
- },
-
- componentDidMount: function() {
- if (typeof username === 'undefined') {
- if (typeof this.props.username === 'undefined') {
- // User not authenticated, looking at default page
- // Show demo data
- this.setState({
- avatar_url : 'http://bestmarketinfo.com/images/blank-avatar.png',
- name : 'Your name',
- username : 'username',
- email : 'username@cub.com',
- });
-
- } else {
- // User is not authenticated, looking at someone
- // Show some real data
- var url = '/api/public/account/?username=' + this.props.username;
-
- $.get(url, function(res) {
- if (this.isMounted()) {
- this.setState({
- avatar_url : res.objects[0].avatar_url,
- name : res.objects[0].name,
- username : res.objects[0].username
- });
- }
- }
- .bind(this))
- .fail(function(err) {
- if (err.status == 400 ) {
- // User not found, redirect to 404 page
- window.location.href = "/404/";
- }
- });
- }
-
- } else {
- if (typeof this.props.username === 'undefined') {
- // User is authenticated, looking at default page
- // Redirect to own profile
- window.location.href = '/profile/' + username;
-
- } else if (this.props.username == username) {
- // User is authenticated, looking at own profile
- $.get('/api/v1/account/', function(res) {
- if (this.isMounted()) {
- this.setState({
- avatar_url : res.objects[0].avatar_url,
- name : res.objects[0].name,
- username : res.objects[0].username,
- email : res.objects[0].email
- });
- }
- }.bind(this));
-
- } else {
- // User is authenticated, looking at someone
- $.get('/api/v1/account/?username=' + this.props.username, function(res) {
- if (this.isMounted()) {
- this.setState({
- avatar_url : res.objects[0].avatar_url,
- name : res.objects[0].name,
- username : res.objects[0].username,
- email : res.objects[0].email
- });
- }
- }
- .bind(this))
- .fail(function(err) {
- if (err.status == 400 ) {
- // User not found, redirect to 404 page
- window.location.href = "/404/";
- }
- });
- }
- }
- },
-
- render: function() {
- if (this.state.avatar_url) {
- return (
-
-
-
-
-
-
{this.state.name}
-
-
{this.state.email}
-
-
- );
- } else {
- return(
);
- }
- }
-})
-
-
-var Nav = React.createClass({
- render: function() {
- var user = ''
- if (typeof username !== 'undefined')
- user = username
-
- return (
-
-
-
- CUB
-
-
- Profile
- Repos
- Contact
- { this.render_links() }
-
-
-
- )
- },
-
- render_links: function() {
- if (typeof user !== 'undefined') {
- return (Logout )
- } else {
- return (Login )
- }
- }
-})
-
-
-var RepoPage = React.createClass({
- render: function() {
- return (
-
-
-
-
- )
- }
-})
-
-
-var FullNameInput = React.createClass({
- mixins: [Formsy.Mixin],
-
- changeValue: function (event) {
- this.setValue(event.currentTarget.value);
- },
- render: function () {
- var className = this.showRequired() ? 'required' : this.showError() ? 'error' : null;
-
- var errorMessage = this.getErrorMessage();
-
- return (
-
-
- {errorMessage}
-
- );
- }
- })
-
- var EmailInput = React.createClass({
- mixins: [Formsy.Mixin],
-
- changeValue: function (event) {
- this.setValue(event.currentTarget.value);
- },
- render: function () {
- var className = this.showRequired() ? 'required' : this.showError() ? 'error' : null;
-
- var errorMessage = this.getErrorMessage();
-
- return (
-
-
- {errorMessage}
-
- );
- }
- })
-
- var ContentTextarea = React.createClass({
- mixins: [Formsy.Mixin],
-
- changeValue: function (event) {
- this.setValue(event.currentTarget.value);
- },
- render: function () {
- var className = this.showRequired() ? 'required' : this.showError() ? 'error' : null;
-
- var errorMessage = this.getErrorMessage();
-
- return (
-
-
- {errorMessage}
-
- );
- }
- })
-
-var ContactPage = React.createClass({
-
- getInitialState: function() {
- return {
- canSubmit: false
- };
- },
-
- enableButton: function () {
- this.setState({
- canSubmit: true
- });
- },
-
- disableButton: function () {
- this.setState({
- canSubmit: false
- });
- },
-
- resetForm: function() {
- this.refs.form.reset();
- this.refs.form.inputs.emailContent.setValue('');
- },
-
- handleSubmit: function(data) {
- var data = JSON.stringify({
- name: data.fullName,
- email: data.email,
- content: data.emailContent
- });
-
- $.ajaxSetup({
- beforeSend: function(xhr, settings) {
- xhr.setRequestHeader("X-CSRFToken", Django.csrf_token());
- xhr.setRequestHeader("Content-Type", 'application/json');
- }
- });
-
- $.ajax({
- type: 'POST',
- url: '/api/public/contact/',
- data: data,
- success: function(data) { this.resetForm() }.bind(this),
- error: function(error) { }
- });
-
- },
-
- render: function() {
- return (
-
-
-
- Get in touch with us
-
-
-
-
-
-
-
-
-
-
-
- )
- }
-})
-
-
-var ProfilePage = React.createClass({
- render: function() {
- return (
-
- )
- }
-})
-
-
-var IndexPage = React.createClass({
- statics: {
- onEnter(next, transition) {
- // Redirect to profile if user is logged in
- if (typeof username !== 'undefined') {
- return transition(null, '/profile/' + username);
- }
- },
- },
-
- render: function() {
- return (
-
-
-
-
Open Source Connect Hub
-
CUB
-
- { this.render_links() }
-
-
-
- )
- },
-
- render_links: function() {
- // OBSOLETE, will be removed
- // User will be redirected to profile page if he is logged in, so we don't
- // need to show /profile link anymore
- if (typeof user !== 'undefined')
- return (Profile )
- else
- return (Login )
- }
-})
-
-
-var NotFoundPage = React.createClass({
- render: function() {
- return (
-
-
-
404: Page not found
-
-
- )
- }
-})
-
-
-var Footer = React.createClass({
- render: function() {
- return (
-
- )
- }
-})
+var IndexPage = require('./index');
+var ProfilePage = require('./profile');
+var RepoPage = require('./repos');
+var ContactPage = require('./contact');
+var PointsList = require('./settings');
+var PageNotFound = require('./404');
ReactDOM.render((
-
+
-
+
), document.getElementById("main"))
diff --git a/components/footer.jsx b/components/footer.jsx
new file mode 100644
index 0000000..189ce7b
--- /dev/null
+++ b/components/footer.jsx
@@ -0,0 +1,18 @@
+var React = require('react');
+
+
+var Footer = React.createClass({
+ render: function() {
+ return (
+
+ )
+ }
+});
+
+module.exports = Footer;
diff --git a/components/index.jsx b/components/index.jsx
new file mode 100644
index 0000000..ad45592
--- /dev/null
+++ b/components/index.jsx
@@ -0,0 +1,40 @@
+var React = require('react');
+
+
+var IndexPage = React.createClass({
+ statics: {
+ onEnter(next, transition) {
+ // Redirect to profile if user is logged in
+ if (typeof username !== 'undefined') {
+ return transition(null, '/profile/' + username);
+ }
+ },
+ },
+
+ render: function() {
+ return (
+
+
+
+
Open Source Connect Hub
+
CUB
+
+ { this.render_links() }
+
+
+
+ )
+ },
+
+ render_links: function() {
+ // OBSOLETE, will be removed
+ // User will be redirected to profile page if he is logged in, so we don't
+ // need to show /profile link anymore
+ if (typeof user !== 'undefined')
+ return (Profile )
+ else
+ return (Login )
+ }
+});
+
+module.exports = IndexPage;
diff --git a/components/nav.jsx b/components/nav.jsx
new file mode 100644
index 0000000..2d30e36
--- /dev/null
+++ b/components/nav.jsx
@@ -0,0 +1,36 @@
+var React = require('react');
+var Link = require('react-router').Link;
+
+var Nav = React.createClass({
+ render: function() {
+ var user = ''
+ if (typeof username !== 'undefined')
+ user = username
+
+ return (
+
+
+
+ CUB
+
+
+ Profile
+ Repos
+ Contact
+ { this.render_links() }
+
+
+
+ )
+ },
+
+ render_links: function() {
+ if (typeof user !== 'undefined') {
+ return (Logout )
+ } else {
+ return (Login )
+ }
+ }
+})
+
+module.exports = Nav;
diff --git a/components/profile.jsx b/components/profile.jsx
new file mode 100644
index 0000000..5102f61
--- /dev/null
+++ b/components/profile.jsx
@@ -0,0 +1,262 @@
+var React = require('react');
+
+var Nav = require('./nav');
+var PointsList = require('./settings');
+var Footer = require('./footer');
+
+const MAX_PROGRESS = 1000;
+
+
+var ProfilePage = React.createClass({
+ render: function() {
+ return (
+
+ )
+ }
+});
+
+var ProfileStats = React.createClass({
+ getInitialState: function() {
+ return {
+ repos_count: null,
+ repos_score: null,
+ repos_top_name: null,
+ repos_top_score: null,
+ progress: 0,
+ login_message: null
+ }
+ },
+
+ componentDidMount: function() {
+ if (typeof username === 'undefined') {
+ if (typeof this.props.username === 'undefined') {
+ // User not authenticated, looking at default page
+ // Show demo data
+ this.setState({
+ repos_count: '###',
+ repos_score: '###',
+ repos_top_name: '###',
+ repos_top_score: '__',
+ progress: 15,
+ login_message: 'You need to login to see your own metrics.'
+ });
+
+ } else {
+ // User is not authenticated, looking at someone
+ // Show some real data
+ this.setState({
+ repos_count: '###',
+ repos_score: '###',
+ repos_top_name: '###',
+ repos_top_score: '__',
+ progress: 0,
+ login_message: 'You need to login to see more metrics.'
+ });
+ }
+
+ } else {
+ if (typeof this.props.username === 'undefined') {
+ // User is authenticated, looking at default page
+ this.setState(this.state);
+
+ } else if (this.props.username == username) {
+ // User is authenticated, looking at own profile
+ var offset = 0;
+ var per_page = 999;
+ var url = '/api/v1/repository/?offset=' + offset + '&limit=' + per_page;
+
+ $.get(url, function(res) {
+ if (this.isMounted()) {
+
+ // Compute total repo score and max repo
+ var total_score = 0;
+ var max_score = 0;
+ var max_repo = '';
+ for (var i in res.objects) {
+ var score = 0;
+ score += res.objects[i].watchers_count * PointsList.watch;
+ score += res.objects[i].stargazers_count * PointsList.star;
+
+ if (score > max_score) { max_score = score; max_repo = res.objects[i].name }
+ total_score += score;
+ }
+
+ this.setState({
+ repos_count: res.objects.length,
+ repos_score: total_score,
+ repos_top_name: max_repo,
+ repos_top_score: max_score,
+ progress: 100 * total_score / MAX_PROGRESS
+ });
+ }
+ }.bind(this));
+
+ } else {
+ // User is authenticated, looking at someone
+ this.setState({
+ repos_count: null,
+ repos_score: null,
+ repos_top_name: null,
+ repos_top_score: null,
+ progress: 0
+ });
+ }
+ }
+ },
+
+ render: function() {
+ return(
+
+
+
Noob
+
Master
+
+
+ {this.state.progress + '%'}
+
+
+
Rockstar
+
+
+
+
Most important repo
+
{this.state.repos_top_name}
+
{this.state.repos_top_score + " points"}
+
+
+
Total score
+
{this.state.repos_score}
+
for all repos
+
+
+
Own contributions count
+
{this.state.repos_count}
+
repositories
+
+
+ { this.state.login_message ?
+
: ''}
+
+ );
+ }
+});
+
+var Profile = React.createClass({
+ getInitialState: function() {
+ return {
+ avatar_url : null,
+ name : null,
+ username : null,
+ email : null,
+ progress : 70,
+ }
+ },
+
+ componentDidMount: function() {
+ if (typeof username === 'undefined') {
+ if (typeof this.props.username === 'undefined') {
+ // User not authenticated, looking at default page
+ // Show demo data
+ this.setState({
+ avatar_url : '/static/images/generic_avatar.png',
+ name : 'Your name',
+ username : 'username',
+ email : 'username@cub.com',
+ });
+
+ } else {
+ // User is not authenticated, looking at someone
+ // Show some real data
+ var url = '/api/public/account/?username=' + this.props.username;
+
+ $.get(url, function(res) {
+ if (this.isMounted()) {
+ this.setState({
+ avatar_url : res.objects[0].avatar_url,
+ name : res.objects[0].name,
+ username : res.objects[0].username
+ });
+ }
+ }
+ .bind(this))
+ .fail(function(err) {
+ if (err.status == 400 ) {
+ // User not found, redirect to 404 page
+ window.location.href = "/404/";
+ }
+ });
+ }
+
+ } else {
+ if (typeof this.props.username === 'undefined') {
+ // User is authenticated, looking at default page
+ // Redirect to own profile
+ window.location.href = '/profile/' + username;
+
+ } else if (this.props.username == username) {
+ // User is authenticated, looking at own profile
+ $.get('/api/v1/myaccount/', function(res) {
+ if (this.isMounted()) {
+ this.setState({
+ avatar_url : res.objects[0].avatar_url,
+ name : res.objects[0].name,
+ username : res.objects[0].username,
+ email : res.objects[0].email
+ });
+ }
+ }.bind(this));
+
+ } else {
+ // User is authenticated, looking at someone
+ $.get('/api/v1/account/?username=' + this.props.username, function(res) {
+ if (this.isMounted()) {
+ this.setState({
+ avatar_url : res.objects[0].avatar_url,
+ name : res.objects[0].name,
+ username : res.objects[0].username,
+ email : res.objects[0].email
+ });
+ }
+ }
+ .bind(this))
+ .fail(function(err) {
+ if (err.status == 400 ) {
+ // User not found, redirect to 404 page
+ window.location.href = "/404/";
+ }
+ });
+ }
+ }
+ },
+
+ render: function() {
+ if (this.state.avatar_url) {
+ return (
+
+
+
+
+
+
{this.state.name}
+
+
{this.state.email}
+
+
+ );
+ } else {
+ return(
);
+ }
+ }
+});
+
+module.exports = ProfilePage;
diff --git a/components/repos.jsx b/components/repos.jsx
new file mode 100644
index 0000000..e499365
--- /dev/null
+++ b/components/repos.jsx
@@ -0,0 +1,124 @@
+var React = require('react');
+var ReactPaginate = require('react-paginate');
+
+var Nav = require('./nav');
+var PointsList = require('./settings');
+var Footer = require('./footer');
+
+const per_page = 10;
+
+
+var RepoPage = React.createClass({
+ render: function() {
+ return (
+
+
+
+
+
+ )
+ }
+});
+
+var RepoList = React.createClass({
+ getInitialState: function() {
+ return {
+ repos: [],
+ offset: 0,
+ pageNum: 1,
+ nextOffset: per_page,
+ previousOffset: 0
+ }
+ },
+
+ getRepoList: function() {
+ var offset = this.state.offset;
+ var nextOffset = offset + per_page;
+ var previousOffset = (offset - per_page < 1) ? 0 : offset - per_page;
+ var url = '/api/v1/repository/?offset=' + offset + '&limit=' + per_page;
+
+ $.get(url, function(res) {
+ this.setState({
+ repos: res.objects,
+ nextOffset: nextOffset,
+ previousOffset: previousOffset,
+ pageNum: Math.ceil(res.meta.total_count / per_page )})
+ }.bind(this));
+ },
+
+ componentDidMount: function() {
+ if (this.props.username !== 'undefined' && this.isMounted()) {
+ this.getRepoList();
+
+ } else {
+ // Load demo page
+ this.setState({
+ repos : {},
+ offset : null,
+ pageNum : null
+ });
+ }
+ },
+
+ handleClick: function(event) {
+ var pageSelected = event.selected;
+
+ this.setState({
+ offset: pageSelected * per_page
+ }, () => {
+ this.getRepoList();
+ });
+ },
+
+ render: function() {
+ return (
+
+
Your score
+
+
Your contributions
+ { this.state.repos.map(function(repo, i) {
+ return (
)
+ }, this)}
+
+
... }
+ pageNum={this.state.pageNum}
+ marginPagesDisplayed={2}
+ pageRangeDisplayed={5}
+ clickCallback={this.handleClick}
+ containerClassName={"pagination"}
+ subContainerClassName={"pagination-pages"}
+ activeClassName={"active"} />
+
+ );
+ }
+});
+
+var Repo = React.createClass({
+ render: function() {
+ var repo_score = this.props.repo.watchers_count * PointsList.watch;
+ repo_score += this.props.repo.stargazers_count * PointsList.star;
+
+ return (
+
+
+
{repo_score}
+
Points
+
+
+
{this.props.repo.description}
+
+ Forked: {this.props.repo.fork}
+ Forks: {this.props.repo.forks_count}
+ Stars: {this.props.repo.stargazers_count}
+ Watchers: {this.props.repo.watchers_count}
+
+
+ )
+ }
+})
+
+module.exports = RepoPage;
diff --git a/components/settings.jsx b/components/settings.jsx
new file mode 100644
index 0000000..bdc81df
--- /dev/null
+++ b/components/settings.jsx
@@ -0,0 +1,22 @@
+var React = require('react');
+
+var PointsList = React.createClass({
+ statics: {
+ watch : 10,
+ star : 20
+ },
+
+ render: function() {
+ return (
+
+
Points:
+
+ Watcher: {PointsList.watch}p
+ Star: {PointsList.star}p
+
+
+ );
+ }
+});
+
+module.exports = PointsList;
diff --git a/static/images/generic_avatar.png b/static/images/generic_avatar.png
new file mode 100644
index 0000000..e41ec14
Binary files /dev/null and b/static/images/generic_avatar.png differ