Report company-affiliation-changes

Implemented report company-affiliation-changes.
The report shows affiliation changes of users given in default_data.json.
The report shows affiliation changes between certain start-date and end-date.
The result are given in table.

Change-Id: I6ed448448672b5dda9c58d8fe20f1cf04cb0d669
Implements: blueprint company-affiliation-changes
This commit is contained in:
pkholkin 2014-11-26 14:44:05 +04:00
parent 5a4096af11
commit 26302fa9fa
7 changed files with 238 additions and 5 deletions

View File

@ -551,7 +551,7 @@
"launchpad_id": "anteaya",
"companies": [
{
"company_name": "independent",
"company_name": "*independent",
"end_date": "2013-Apr-02"
},
{

View File

@ -69,7 +69,7 @@ def get_default(param_name):
if 'release' not in DEFAULTS:
release = cfg.CONF.default_release
if not release:
runtime_storage_inst = vault.get_vault()['runtime_storage']
runtime_storage_inst = vault.get_runtime_storage()
releases = runtime_storage_inst.get_by_key('releases')
if releases:
release = releases[-1]['release_name']

View File

@ -159,6 +159,22 @@ def members():
}
@blueprint.route('/affiliation_changes')
@decorators.exception_handler()
@decorators.templated()
def affiliation_changes():
start_days = str(flask.request.args.get('start_days') or
utils.timestamp_to_date(int(time.time()) -
365 * 24 * 60 * 60))
end_days = str(flask.request.args.get('end_days') or
utils.timestamp_to_date(int(time.time())))
return {
'start_days': start_days,
'end_days': end_days,
}
@blueprint.route('/cores')
@decorators.exception_handler()
@decorators.templated()

View File

@ -0,0 +1,162 @@
{% extends "reports/base_report.html" %}
{% block title %}
Company Affiliation Changes
{% endblock %}
{% block scripts %}
<script type="text/javascript">
function show_users_table(options) {
var table_column_names = ["from", "to", "count", "users"];
var table_id = "users_table";
$.ajax({
url: makeURI("/api/1.0/affiliation_changes", options),
dataType: "json",
success: function (data) {
var Data = data["affiliation_changes"];
var tableColumns = [];
var sort_by_column = 2;
for (var i = 0; i < table_column_names.length; i++) {
tableColumns.push({"mData": table_column_names[i]});
}
result = {};
for (i = 0; i < Data.length; i++) {
var user_id = Data[i].user_id;
var user_name = Data[i].user_name;
var old_company_name = Data[i].old_company_name;
var new_company_name = Data[i].new_company_name;
if (!result[old_company_name])
result[old_company_name] = {};
if (!result[old_company_name][new_company_name])
result[old_company_name][new_company_name] = [];
result[old_company_name][new_company_name].push({
'name': user_name,
'id': user_id
});
}
var tableData = [];
var index = 0;
for (old_company_name in result)
for (new_company_name in result[old_company_name]) {
tableData.push({});
tableData[index].from = "<a href=\".." + "?company=" + old_company_name + "\">" + old_company_name + "</a>";
tableData[index].to = "<a href=\".." + "?company=" + new_company_name + "\">" + new_company_name + "</a>";
var users = result[old_company_name][new_company_name];
tableData[index].count = users.length;
var user_links = [];
for (var j = 0; j < users.length; j++)
user_links.push("<a href=\"" + "users/" + users[j].id + "\">" + users[j].name + "</a>");
user_links.sort();
tableData[index].users = user_links.join(", ");
index++;
}
if (table_id) {
$("#" + table_id).dataTable({
"aaSorting": [
[ sort_by_column, "desc" ]
],
"bFilter": true,
"bInfo": true,
"bAutoWidth": true,
"aaData": tableData,
"aoColumns": tableColumns,
"bDestroy": true,
'bPaginate': true,
"sPaginationType": "full_numbers",
"aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
"iDisplayLength": -1
});
}
}
});
}
function make_options() {
var options = {};
options['start_days'] = $('#start_days_selector').val();
options['end_days'] = $('#end_days_selector').val();
return options;
}
function reload() {
window.location.search = $.map(make_options(),function (val, index) {
return index + "=" + val;
}).join("&")
}
function show_page() {
show_users_table(make_options());
}
$(document).ready(function () {
$("#start_days_selector").val("{{ start_days }}").on('change', function (evt) {
reload();
});
$("#end_days_selector").val("{{ end_days }}").on('change', function (evt) {
reload();
});
show_page();
});
$(function() {
$( "#start_days_selector" ).datepicker({
dateFormat: 'yy-M-d',
changeMonth: true,
changeYear: true
});
});
$(function() {
$( "#end_days_selector" ).datepicker({
dateFormat: 'yy-M-d',
changeMonth: true,
changeYear: true
});
});
$(document).ready(function () {
$('#start_days_selector').val("{{ start_days }}");
$('#end_days_selector').val("{{ end_days }}");
show_page();
});
</script>
{% endblock %}
{% block content %}
<h1>Company Affiliation Changes</h1>
<p>Start of the period: <input type="text" id="start_days_selector"/> &nbsp; End of the period: <input type="text" id="end_days_selector"/></p>
<div class="body" style="margin-right: 1em;">
<table id="users_table" style="width: 100%">
<thead>
<tr>
<th>From</th>
<th>To</th>
<th>Count</th>
<th>Users</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
{% endblock %}

View File

@ -68,7 +68,7 @@ def compact_records(records):
def extend_record(record):
runtime_storage_inst = get_vault()['runtime_storage']
runtime_storage_inst = get_runtime_storage()
return runtime_storage_inst.get_by_key(
runtime_storage_inst._get_record_name(record.record_id))
@ -121,6 +121,10 @@ def get_memory_storage():
return get_vault()['memory_storage']
def get_runtime_storage():
return get_vault()['runtime_storage']
def _init_releases(vault):
runtime_storage_inst = vault['runtime_storage']
releases = runtime_storage_inst.get_by_key('releases')
@ -170,7 +174,7 @@ def get_project_types():
def get_release_options():
runtime_storage_inst = get_vault()['runtime_storage']
runtime_storage_inst = get_runtime_storage()
releases = (runtime_storage_inst.get_by_key('releases') or [None])[1:]
releases.append({'release_name': 'all'})
releases.reverse()
@ -195,7 +199,7 @@ def get_project_type(project_type_id):
def get_user_from_runtime_storage(user_id):
runtime_storage_inst = get_vault()['runtime_storage']
runtime_storage_inst = get_runtime_storage()
user_index = get_vault()['user_index']
if user_id not in user_index:
user_index[user_id] = user_processor.load_user(

View File

@ -490,6 +490,52 @@ def get_project_types_json(**kwargs):
parameters.get_default('project_type'))
@app.route('/api/1.0/affiliation_changes')
@decorators.exception_handler()
@decorators.response()
@decorators.jsonify('affiliation_changes')
def get_company_changes(**kwargs):
start_days = str(flask.request.args.get('start_days') or
utils.timestamp_to_date(int(time.time()) -
365 * 24 * 60 * 60))
end_days = str(flask.request.args.get('end_days') or
utils.timestamp_to_date(int(time.time())))
start_date = utils.date_to_timestamp_ext(start_days)
end_date = utils.date_to_timestamp_ext(end_days)
runtime_storage = vault.get_runtime_storage()
result = []
for user in runtime_storage.get_all_users():
companies = user.get('companies') or []
if len(companies) < 2:
continue
companies_iter = iter(companies)
company = companies_iter.next()
old_company_name = company['company_name']
date = company['end_date']
for company in companies_iter:
new_company_name = company['company_name']
if start_date <= date <= end_date:
result.append({
'user_id': user['user_id'],
'user_name': user['user_name'],
'old_company_name': old_company_name,
'new_company_name': new_company_name,
'date': date,
})
old_company_name = new_company_name
date = company['end_date']
return result
def _get_week(kwargs, param_name):
date_param = parameters.get_single_parameter(kwargs, param_name)
if date_param:

View File

@ -57,6 +57,11 @@ def iso8601_to_timestamp(s):
return int(time.mktime(iso8601.parse_date(s).timetuple()))
def timestamp_to_date(timestamp):
return (datetime.datetime.fromtimestamp(timestamp).
strftime('%Y-%b-%d'))
def timestamp_to_week(timestamp):
# Jan 4th 1970 is the first Sunday in the Epoch
return (timestamp - 3 * 24 * 3600) // (7 * 24 * 3600)