Implemented summary report on reviews per engineer
Partially implements blueprint review-stats Change-Id: I011d81a10ad63746a9246a62379c0f6b4c814812
This commit is contained in:
parent
6779de9dc2
commit
7fcf69efdf
@ -86,7 +86,7 @@
|
||||
|
||||
{% endif %}
|
||||
|
||||
<h4>Marks</h4>
|
||||
<h3>Reviews</h3>
|
||||
{% for mark in [-2, -1, 0, 1, 2] %}
|
||||
<div>{{ mark }}: {{ marks[mark] }}</div>
|
||||
{% endfor %}
|
||||
|
@ -114,6 +114,7 @@
|
||||
var aggregate = 0;
|
||||
var index = 1;
|
||||
var i;
|
||||
var hasComment = false;
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
if (i < limit - 1) {
|
||||
@ -133,7 +134,12 @@
|
||||
} else {
|
||||
var link = data[i].name
|
||||
}
|
||||
tableData.push({"index": index_label, "link": link, "metric": data[i].metric});
|
||||
var rec = {"index": index_label, "link": link, "metric": data[i].metric};
|
||||
if (data[i].comment) {
|
||||
rec["comment"] = data[i].comment;
|
||||
hasComment = true;
|
||||
}
|
||||
tableData.push(rec);
|
||||
}
|
||||
|
||||
if (i == limit) {
|
||||
@ -142,6 +148,15 @@
|
||||
chartData.push(["others", aggregate]);
|
||||
}
|
||||
|
||||
var tableColumns = [
|
||||
{ "mData": "index" },
|
||||
{ "mData": "link" },
|
||||
{ "mData": "metric" }
|
||||
];
|
||||
if (hasComment) {
|
||||
tableColumns.push({ "mData": "comment"})
|
||||
}
|
||||
|
||||
$("#" + table_id).dataTable({
|
||||
"aLengthMenu": [
|
||||
[25, 50, -1],
|
||||
@ -153,11 +168,7 @@
|
||||
"sPaginationType": "full_numbers",
|
||||
"iDisplayLength": 25,
|
||||
"aaData": tableData,
|
||||
"aoColumns": [
|
||||
{ "mData": "index" },
|
||||
{ "mData": "link" },
|
||||
{ "mData": "metric" }
|
||||
]
|
||||
"aoColumns": tableColumns
|
||||
});
|
||||
|
||||
var plot = $.jqplot(chart_id, [chartData], {
|
||||
|
@ -7,6 +7,7 @@
|
||||
{% block scripts %}
|
||||
<script type="text/javascript">
|
||||
chartAndTableRenderer("/data/companies", "left_list", "left_chart", "/companies/", {module: "{{ module }}" });
|
||||
chartAndTableRenderer("/data/engineers", "right_list", "right_chart", "/engineers/", {module: "{{ module }}" });
|
||||
timelineRenderer({module: "{{ module }}" })
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -34,37 +35,24 @@
|
||||
|
||||
{% block right_frame %}
|
||||
|
||||
<h2>Recent activity</h2>
|
||||
<h2>Contribution by engineers</h2>
|
||||
|
||||
{% for rec in commits %}
|
||||
<div style="padding-bottom: 1em;">
|
||||
<div style='float: left; '>
|
||||
<img src="{{ rec.author_email|gravatar(size=32) }}">
|
||||
</div>
|
||||
<div style="margin-left: 4em;">
|
||||
<div>
|
||||
{% if rec.launchpad_id %}
|
||||
{{ rec.author_name|link('/engineers/' + rec.launchpad_id)|safe }}
|
||||
{% else %}
|
||||
{{ rec.author_name }}
|
||||
{% endif %}
|
||||
{% if rec.company_name %}
|
||||
(
|
||||
{{ rec.company_name|link('/companies/' + rec.company_name)|safe }}
|
||||
)
|
||||
{% endif %}
|
||||
<em>{{ rec.date|datetimeformat }}</em>
|
||||
</div>
|
||||
<div id="right_chart" style="width: 100%; height: 350px;"></div>
|
||||
|
||||
{% if rec.correction_comment %}
|
||||
<div style='font-weight: bold; color: red; padding-left: 2em;'>Commit corrected: {{ rec.correction_comment }}</div>
|
||||
<table id="right_list" class="display">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Engineer</th>
|
||||
<th>{{ metric_label }}</th>
|
||||
{% if metric == 'marks' %}
|
||||
<th>-2|-1|+1|+2 (+/- ratio)</th>
|
||||
{% endif %}
|
||||
<div><b>{{ rec.subject }}</b></div>
|
||||
<div style="white-space: pre-wrap;">{{ rec|commit_message|safe }}</div>
|
||||
<div><span style="color: green">+ {{ rec.lines_added }}</span>
|
||||
<span style="color: red">- {{ rec.lines_deleted }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="spacer"></div>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -44,8 +44,7 @@ DEFAULTS = {
|
||||
METRIC_LABELS = {
|
||||
'loc': 'Lines of code',
|
||||
'commits': 'Commits',
|
||||
'reviews': 'Reviews',
|
||||
'marks': 'Marks',
|
||||
'marks': 'Reviews',
|
||||
}
|
||||
|
||||
DEFAULT_RECORDS_LIMIT = 10
|
||||
@ -277,17 +276,59 @@ def aggregate_filter():
|
||||
@functools.wraps(f)
|
||||
def aggregate_filter_decorated_function(*args, **kwargs):
|
||||
|
||||
def commit_filter(result, record, param_id):
|
||||
result[record[param_id]]['metric'] += 1
|
||||
|
||||
def loc_filter(result, record, param_id):
|
||||
result[record[param_id]]['metric'] += record['loc']
|
||||
|
||||
def mark_filter(result, record, param_id):
|
||||
value = record['value']
|
||||
result_by_param = result[record[param_id]]
|
||||
result_by_param['metric'] += 1
|
||||
|
||||
if value in result_by_param:
|
||||
result_by_param[value] += 1
|
||||
else:
|
||||
result_by_param[value] = 1
|
||||
|
||||
def mark_finalize(record):
|
||||
new_record = {}
|
||||
for key in ['id', 'metric', 'name']:
|
||||
new_record[key] = record[key]
|
||||
|
||||
positive = 0
|
||||
mark_distribution = []
|
||||
for key in ['-2', '-1', '1', '2']:
|
||||
if key in record:
|
||||
if key in ['1', '2']:
|
||||
positive += record[key]
|
||||
mark_distribution.append(str(record[key]))
|
||||
else:
|
||||
mark_distribution.append('0')
|
||||
|
||||
new_record['comment'] = (
|
||||
'|'.join(mark_distribution) +
|
||||
' (%.1f%%)' % ((positive * 100.0) / record['metric']))
|
||||
return new_record
|
||||
|
||||
metric_param = (flask.request.args.get('metric') or
|
||||
get_default('metric'))
|
||||
metric = metric_param.lower()
|
||||
if metric in ['commits', 'reviews', 'marks']:
|
||||
metric_filter = lambda r: 1
|
||||
aggregate_filter = None
|
||||
|
||||
if metric == 'commits':
|
||||
metric_filter = commit_filter
|
||||
elif metric == 'loc':
|
||||
metric_filter = lambda r: r['loc']
|
||||
metric_filter = loc_filter
|
||||
elif metric == 'marks':
|
||||
metric_filter = mark_filter
|
||||
aggregate_filter = mark_finalize
|
||||
else:
|
||||
raise Exception('Invalid metric %s' % metric)
|
||||
|
||||
kwargs['metric_filter'] = metric_filter
|
||||
kwargs['finalize_handler'] = aggregate_filter
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return aggregate_filter_decorated_function
|
||||
@ -471,16 +512,18 @@ def engineer_details(user_id, records):
|
||||
# AJAX Handlers ---------
|
||||
|
||||
def _get_aggregated_stats(records, metric_filter, keys, param_id,
|
||||
param_title=None):
|
||||
param_title=None, finalize_handler=None):
|
||||
param_title = param_title or param_id
|
||||
result = dict((c, 0) for c in keys)
|
||||
titles = {}
|
||||
result = dict((c, {'metric': 0, 'id': c}) for c in keys)
|
||||
for record in records:
|
||||
result[record[param_id]] += metric_filter(record)
|
||||
titles[record[param_id]] = record[param_title]
|
||||
metric_filter(result, record, param_id)
|
||||
result[record[param_id]]['name'] = record[param_title]
|
||||
|
||||
response = [{'id': r, 'metric': result[r], 'name': titles[r]}
|
||||
for r in result if result[r]]
|
||||
if not finalize_handler:
|
||||
finalize_handler = lambda x: x
|
||||
|
||||
response = [finalize_handler(result[r]) for r in result
|
||||
if result[r]['metric']]
|
||||
response.sort(key=lambda x: x['metric'], reverse=True)
|
||||
return response
|
||||
|
||||
@ -489,7 +532,7 @@ def _get_aggregated_stats(records, metric_filter, keys, param_id,
|
||||
@exception_handler()
|
||||
@record_filter()
|
||||
@aggregate_filter()
|
||||
def get_companies(records, metric_filter):
|
||||
def get_companies(records, metric_filter, finalize_handler):
|
||||
response = _get_aggregated_stats(records, metric_filter,
|
||||
get_memory_storage().get_companies(),
|
||||
'company_name')
|
||||
@ -500,7 +543,7 @@ def get_companies(records, metric_filter):
|
||||
@exception_handler()
|
||||
@record_filter()
|
||||
@aggregate_filter()
|
||||
def get_modules(records, metric_filter):
|
||||
def get_modules(records, metric_filter, finalize_handler):
|
||||
response = _get_aggregated_stats(records, metric_filter,
|
||||
get_memory_storage().get_modules(),
|
||||
'module')
|
||||
@ -511,10 +554,11 @@ def get_modules(records, metric_filter):
|
||||
@exception_handler()
|
||||
@record_filter()
|
||||
@aggregate_filter()
|
||||
def get_engineers(records, metric_filter):
|
||||
def get_engineers(records, metric_filter, finalize_handler):
|
||||
response = _get_aggregated_stats(records, metric_filter,
|
||||
get_memory_storage().get_user_ids(),
|
||||
'user_id', 'author_name')
|
||||
'user_id', 'author_name',
|
||||
finalize_handler=finalize_handler)
|
||||
return json.dumps(response)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user