Skip to content

Commit

Permalink
Render top contributors in detaild stats via react
Browse files Browse the repository at this point in the history
Fix #4699
  • Loading branch information
ta2-1 committed Jul 28, 2016
1 parent c66a1dc commit 831fe8b
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 39 deletions.
16 changes: 12 additions & 4 deletions pootle/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
from .http import JsonResponse, JsonResponseBadRequest
from .url_helpers import get_path_parts, get_previous_url
from .utils.json import PootleJSONEncoder
from .utils.stats import get_translation_states
from .utils.stats import (get_top_scorers_data, get_translation_states,
TOP_CONTRIBUTORS_CHUNK_SIZE)


def check_directory_permission(permission_codename, request, directory):
Expand Down Expand Up @@ -685,6 +686,11 @@ def get_context_data(self, *args, **kwargs):
super(PootleBrowseView, self).get_context_data(*args, **kwargs))

language_code, project_code = split_pootle_path(self.pootle_path)[:2]
top_scorers = User.top_scorers(
project=project_code,
language=language_code,
limit=TOP_CONTRIBUTORS_CHUNK_SIZE + 1,
)

ctx.update(
{'page': 'browse',
Expand All @@ -701,10 +707,12 @@ def get_context_data(self, *args, **kwargs):
'url_action_view_all': url_action_view_all,
'table': self.table,
'is_store': self.is_store,
'top_scorers': User.top_scorers(project=project_code,
language=language_code,
limit=10),
'top_scorers': top_scorers,
'top_scorers_data': get_top_scorers_data(
top_scorers,
TOP_CONTRIBUTORS_CHUNK_SIZE),
'browser_extends': self.template_extends})

return ctx


Expand Down
11 changes: 9 additions & 2 deletions pootle/static/css/scores.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ html[dir="rtl"] .path-summary-more .top-scorers .top-scorer
{
font-size: 1em;
width: 100%;
table-layout: fixed;
}

.path-summary-more .top-scorers-table tr td.number:last-child
Expand All @@ -139,7 +138,15 @@ html[dir="rtl"] .path-summary-more .top-scorers-table tr td.number:last-child
.path-summary-more .top-scorers-table tr td.number:first-child
{
text-align: left;
width: 2em;
width: 1em;
padding-right: 1em;
}

html[dir="rtl"] .path-summary-more .top-scorers-table tr td.number:first-child
{
text-align: right;
padding-left: 1em;
padding-right: auto;
}

.top-scorer a
Expand Down
5 changes: 5 additions & 0 deletions pootle/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,11 @@ html[dir="rtl"] .check-count
display: inherit;
}

.more-top-contributors
{
padding: 9px 0;
}

div.small
{
font-size: 1em;
Expand Down
60 changes: 60 additions & 0 deletions pootle/static/js/browser/components/Stats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (C) Pootle contributors.
*
* This file is a part of the Pootle project. It is distributed under the GPL3
* or later license. See the LICENSE file for a copy of the license and the
* AUTHORS file for copyright and authorship information.
*/

import React from 'react';

import StatsAPI from 'api/StatsAPI';
import TopContributors from './TopContributors';


const Stats = React.createClass({

propTypes: {
topContributors: React.PropTypes.array.isRequired,
hasMoreContributors: React.PropTypes.bool.isRequired,
pootlePath: React.PropTypes.string.isRequired,
},

getInitialState() {
return {
topContributors: this.props.topContributors,
hasMoreContributors: this.props.hasMoreContributors,
};
},

onLoadMoreTopContributors(data) {
const topContributors = this.state.topContributors.concat(data.items);
this.setState({
topContributors,
hasMoreContributors: data.has_more_items,
});
},

loadMoreTopContributors() {
if (!this.state.hasMoreContributors) {
return false;
}
const params = { offset: this.state.topContributors.length };
return StatsAPI.getTopContributors(this.props.pootlePath, params)
.done(this.onLoadMoreTopContributors);
},

render() {
return (
<TopContributors
items={this.state.topContributors}
hasMoreItems={this.state.hasMoreContributors}
loadMore={this.loadMoreTopContributors}
/>
);
},

});


export default Stats;
82 changes: 82 additions & 0 deletions pootle/static/js/browser/components/TopContributors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (C) Pootle contributors.
*
* This file is a part of the Pootle project. It is distributed under the GPL3
* or later license. See the LICENSE file for a copy of the license and the
* AUTHORS file for copyright and authorship information.
*/

import React from 'react';

import Avatar from 'components/Avatar';
import { t } from 'utils/i18n';


function getScoreText(score) {
if (score > 0) {
return t('+%(score)s', { score });
}
return score;
}


const TopContributors = React.createClass({

propTypes: {
items: React.PropTypes.array.isRequired,
hasMoreItems: React.PropTypes.bool.isRequired,
loadMore: React.PropTypes.func.isRequired,
},

createRow(item, index) {
const title = (`
<span class="value">${item.suggested}</span> suggested<br/>
<span class="value">${item.translated}</span> translated<br/>
<span class="value">${item.reviewed}</span> reviewed<br/>
`);
return (
<tr key={`top-contibutor-${index}`}>
<td className="number">{t('#%(position)s', { position: index + 1 })}</td>
<td className="user top-scorer">
<Avatar
email={item.email}
label={item.display_name}
size={20}
username={item.username}
/>
</td>
<td className="number">
<span title={title}>{getScoreText(item.public_total_score)}</span>
</td>
</tr>
);
},

render() {
let loadMore;

if (this.props.hasMoreItems) {
loadMore = (
<div className="more-top-contributors">
<a onClick={this.props.loadMore}>
<span className="show-more">{gettext('More...')}</span>
</a>
</div>
);
}
return (
<div>
<table className="top-scorers-table">
<tbody>
{this.props.items.map(this.createRow)}
</tbody>
</table>
{loadMore}
</div>
);
},

});


export default TopContributors;
2 changes: 1 addition & 1 deletion pootle/static/js/shared/api/StatsAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const StatsAPI = {
const body = { path, offset };

return fetch({
body: body,
body,
url: `${this.apiRoot}contributors/`,
});
},
Expand Down
11 changes: 10 additions & 1 deletion pootle/static/js/stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import TimeSince from 'components/TimeSince';
import UserEvent from 'components/UserEvent';
import cookie from 'utils/cookie';

import Stats from './browser/components/Stats';
import VisibilityToggle from './browser/components/VisibilityToggle';
import msg from './msg';

Expand Down Expand Up @@ -62,7 +63,6 @@ const stats = {
}

this.retries = 0;

const isExpanded = (options.isInitiallyExpanded ||
window.location.search.indexOf('?details') !== -1);
this.state = {
Expand Down Expand Up @@ -119,6 +119,15 @@ const stats = {
document.querySelector('.js-mnt-visibility-toggle'));
}

ReactDOM.render(
<Stats
hasMoreContributors={options.topContributorsData.has_more_items}
topContributors={options.topContributorsData.items}
pootlePath={this.pootlePath}
/>,
document.querySelector('#js-mnt-top-contributors')
);

// Retrieve async data if needed
if (isExpanded) {
this.loadChecks();
Expand Down
5 changes: 2 additions & 3 deletions pootle/templates/browser/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ <h3>{% trans "Failing Checks" %}</h3>
{% if top_scorers %}
<div class="summary-2-col">
<h3 class="top">{% trans "Top Contributors for the Last 30 Days" %}</h3>
<div class="bd">
{% include 'core/_top_scorers_as_table.html' %}
</div>
<div id="js-mnt-top-contributors" class="bd"></div>
</div>
{% endif %}
<div class="summary-3-col">
Expand Down Expand Up @@ -190,6 +188,7 @@ <h3>{% trans "Translations" %}</h3>
isAdmin: {{ has_admin_access|yesno:"true,false" }},
isInitiallyExpanded: {{ is_store|yesno:"true,false" }},
initialData: {{ stats|to_js }},
topContributorsData: {{ top_scorers_data|to_js }},
statsRefreshAttemptsCount: {{ stats_refresh_attempts_count }},
uiLocaleDir: '{{ LANGUAGE_BIDI|yesno:"rtl,ltr" }}',
});
Expand Down
28 changes: 0 additions & 28 deletions pootle/templates/core/_top_scorers_as_table.html

This file was deleted.

0 comments on commit 831fe8b

Please sign in to comment.