Add filtering by languages

Translation records can be filtered by language, this allows
to find top contributors within a language.

Language selector is moved above module selector to pay more
attention to it.

Change-Id: I52b61e5cf509bfef9375431bf558314def81772c
This commit is contained in:
Ilya Shakhat
2018-11-16 00:18:40 +04:00
parent 1650fb1c9a
commit 34386f4e6e
5 changed files with 67 additions and 23 deletions

View File

@@ -247,6 +247,13 @@ def record_filter(ignore=None):
record_ids, _filter_records_by_days(start_date, end_date,
memory_storage_inst))
# filtering by non-indexed attributes goes last
language = params['language']
if language:
record_ids = (
set(memory_storage_inst.get_record_ids_by_languages(
record_ids, language)))
kwargs['record_ids'] = record_ids
kwargs['records'] = memory_storage_inst.get_records(record_ids)
@@ -454,6 +461,9 @@ def templated(template=None, return_code=200):
ctx['user_inst'] = vault.get_user_from_runtime_storage(
ctx['user_id'])
ctx['language'] = parameters.get_single_parameter(
kwargs, 'language')
ctx['page_title'] = helpers.make_page_title(
ctx['project_type_inst'],
ctx.get('release'), ctx.get('module_inst'),

View File

@@ -188,6 +188,14 @@ class CachedMemoryStorage(MemoryStorage):
def get_first_record_day(self):
return min(self.day_index.keys())
def get_record_ids_by_languages(self, record_ids, languages):
# special case: filter by attribute not covered by index
for record in self.get_records(record_ids):
lng = record.value
if lng:
if lng.lower() in languages:
yield record.record_id
def get_memory_storage(memory_storage_type):
if memory_storage_type == MEMORY_STORAGE_CACHED:

View File

@@ -58,7 +58,7 @@ METRIC_TO_RECORD_TYPE = {
FILTER_PARAMETERS = ['release', 'project_type', 'module', 'company', 'user_id',
'metric', 'start_date', 'end_date', 'blueprint_id',
'core_in']
'core_in', 'language']
DEFAULT_RECORDS_LIMIT = 10
DEFAULT_STATIC_ACTIVITY_SIZE = 100

View File

@@ -127,6 +127,39 @@
{% block right_frame %}
{% if show_languages_breakdown %}
<div id="language_container">
{% if language %}
<div class="drop" style="margin-top: 16px;">
<label for="language_selector" title="One of available languages">Language</label>
<input type="hidden" id="language_selector" style="width: 200px" data-placeholder="Select language"/>
</div>
<script>
$(document).ready(function () {
initSingleSelector("language", makeURI("/api/1.0/languages"), {allowClear: true});
});
</script>
{% else %}
<h2>Languages</h2>
<div id="language_chart" style="width: 100%; height: 350px; margin-bottom: 1em;"></div>
<table id="language_table" class="display">
<thead>
<tr>
<th>#</th>
<th>Language</th>
<th>Translations</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endif %}
<div class="spacer"></div>
</div>
{% endif %}
{% if show_module_breakdown %}
<div id="module_container">
<h2>Contribution by modules</h2>
@@ -179,27 +212,6 @@
</div>
{% endif %}
{% if show_languages_breakdown %}
<div id="language_container">
<h2>Languages</h2>
<div id="language_chart" style="width: 100%; height: 350px; margin-bottom: 1em;"></div>
<table id="language_table" class="display">
<thead>
<tr>
<th>#</th>
<th>Language</th>
<th>Translations</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<div class="spacer"></div>
</div>
{% endif %}
{% if show_contribution_on_right %}
{{ contribution_summary.show_contribution_summary(show_all=False) }}
{{ show_report_links(module, company, user_id) }}

View File

@@ -403,12 +403,26 @@ def get_bpd(records, **kwargs):
return result
@app.route('/api/1.0/languages')
@decorators.exception_handler()
@decorators.response()
@decorators.cached(ignore=['language'])
@decorators.jsonify()
@decorators.record_filter(ignore=['language'])
def get_languages_json(record_ids, **kwargs):
memory_storage = vault.get_memory_storage()
languages = set(r.value for r in memory_storage.get_records(record_ids))
return [{'id': c.lower().replace('&', ''), 'text': c}
for c in sorted(languages)]
@app.route('/api/1.0/stats/languages')
@decorators.exception_handler()
@decorators.response()
@decorators.cached()
@decorators.jsonify('stats')
@decorators.record_filter()
@decorators.record_filter(ignore=['language'])
def get_languages(records, **kwargs):
result = []
languages = collections.defaultdict(int)