diff --git a/dashboard/decorators.py b/dashboard/decorators.py
index 467fcda82..87244a6f4 100644
--- a/dashboard/decorators.py
+++ b/dashboard/decorators.py
@@ -397,7 +397,14 @@ def jsonify(root='data'):
def decorator(func):
@functools.wraps(func)
def jsonify_decorated_function(*args, **kwargs):
- return json.dumps({root: func(*args, **kwargs)})
+ value = func(*args, **kwargs)
+ if isinstance(value, tuple):
+ result = dict([(root[i], value[i])
+ for i in six.moves.range(min(len(value),
+ len(root)))])
+ else:
+ result = {root: value}
+ return json.dumps(result)
return jsonify_decorated_function
diff --git a/dashboard/static/css/style.css b/dashboard/static/css/style.css
index 0e5f531f2..4d17e4951 100644
--- a/dashboard/static/css/style.css
+++ b/dashboard/static/css/style.css
@@ -470,3 +470,13 @@ div.stackamenu li.current-menu-item a span {
color: white;
/*text-shadow: 0 -1px 0 #436281;*/
}
+
+.select2-loading {
+ font-style: italic;
+ color: dimgray;
+ background: url('../images/select2-spinner.gif') no-repeat 100% !important;
+}
+
+.ui-widget-overlay {
+ opacity: 0.6;
+}
diff --git a/dashboard/static/js/driverlog-ui.js b/dashboard/static/js/driverlog-ui.js
index 0302258b7..28344b66c 100644
--- a/dashboard/static/js/driverlog-ui.js
+++ b/dashboard/static/js/driverlog-ui.js
@@ -36,132 +36,66 @@ function make_uri(uri, options) {
return (str == "") ? uri : uri + "?" + str;
}
-function make_std_options() {
- var options = {};
- options['project_id'] = $('#project_selector').val();
- options['vendor'] = $('#vendor_selector').val();
- options['release_id'] = $('#release_selector').val();
-
- return options;
+function getPageState() {
+ return {
+ project_id: $('#project_id').val(),
+ vendor: $('#vendor').val(),
+ release_id: $('#release_id').val()
+ };
}
-function reload() {
- var ops = {};
- $.extend(ops, getUrlVars());
- $.extend(ops, make_std_options());
- window.location.search = $.map(ops,function (val, index) {
- return index + "=" + encodeURIComponent(val);
+function reload(extra) {
+ window.location.search = $.map($.extend(getPageState(), extra), function (val, index) {
+ return val? (index + "=" + encodeURIComponent(val)) : null;
}).join("&")
}
-function init_selectors(base_url) {
- $(document).tooltip();
+function initSelectors(base_url) {
- var project_id = getUrlVars()["project_id"];
+ function initSingleSelector(name, data_container, api_url, select2_extra_options, change_handler) {
+ $("#" + name).val(0).select2({
+ data: [{id: 0, text: "Loading..." }],
+ formatSelection: function(item) { return "
+
+
{% endblock %}
diff --git a/dashboard/templates/reports/open_reviews.html b/dashboard/templates/reports/open_reviews.html
index 25ab645d8..752f9e5ff 100644
--- a/dashboard/templates/reports/open_reviews.html
+++ b/dashboard/templates/reports/open_reviews.html
@@ -7,8 +7,8 @@ Open reviews report for {{ module }}
{% block scripts %}
{% endblock %}
diff --git a/dashboard/templates/reports/user_activity.html b/dashboard/templates/reports/user_activity.html
index cb6b60e6a..3343602fd 100644
--- a/dashboard/templates/reports/user_activity.html
+++ b/dashboard/templates/reports/user_activity.html
@@ -10,7 +10,7 @@
{% block scripts %}
{% endblock %}
diff --git a/dashboard/templates/widget.html b/dashboard/templates/widget.html
index e9a178999..f9b9e7c74 100644
--- a/dashboard/templates/widget.html
+++ b/dashboard/templates/widget.html
@@ -42,7 +42,7 @@
var base_url = "http://stackalytics.com";
$(document).ready(function () {
- init_selectors(base_url);
+ initSelectors(base_url);
renderTableAndChart(base_url + "/api/1.0/stats/companies", null, null, "company_chart", null);
});
diff --git a/dashboard/vault.py b/dashboard/vault.py
index 4bdb986a2..e8732dbd4 100644
--- a/dashboard/vault.py
+++ b/dashboard/vault.py
@@ -118,21 +118,7 @@ def _init_project_types(vault):
runtime_storage_inst = vault['runtime_storage']
project_types = runtime_storage_inst.get_by_key('project_types') or {}
- result = []
- parent = None
- for pt in project_types:
- is_child = pt.get('child', False)
- if parent and is_child:
- item = {'id': pt['id'], 'text': pt['title']}
- if 'items' in parent:
- parent['items'].append(item)
- else:
- parent['items'] = [item]
- else:
- parent = pt
- result.append(parent)
-
- vault['project_types'] = result
+ vault['project_types'] = project_types
vault['project_types_index'] = dict([(pt['id'], pt)
for pt in project_types])
diff --git a/dashboard/web.py b/dashboard/web.py
index 42ce3655e..2991df015 100644
--- a/dashboard/web.py
+++ b/dashboard/web.py
@@ -275,12 +275,14 @@ def get_contribution_json(records, **kwargs):
@decorators.exception_handler()
@decorators.response()
@decorators.cached(ignore=['company'])
-@decorators.jsonify('companies')
+@decorators.jsonify()
@decorators.record_filter(ignore=['company'])
def get_companies_json(record_ids, **kwargs):
memory_storage = vault.get_memory_storage()
companies = memory_storage.get_index_keys_by_record_ids(
'company_name', record_ids)
+ if kwargs['_params']['company']:
+ companies.add(kwargs['_params']['company'][0])
result = [memory_storage.get_original_company_name(company)
for company in companies]
@@ -293,7 +295,7 @@ def get_companies_json(record_ids, **kwargs):
@decorators.exception_handler()
@decorators.response()
@decorators.cached(ignore=['module'])
-@decorators.jsonify('modules')
+@decorators.jsonify()
@decorators.record_filter(ignore=['module'])
def get_modules_json(record_ids, **kwargs):
module_id_index = vault.get_vault()['module_id_index']
@@ -313,7 +315,8 @@ def get_modules_json(record_ids, **kwargs):
# keep only modules with specified tags
if tags:
module_ids = set(module_id for module_id in module_ids
- if module_id_index[module_id].get('tag') in tags)
+ if ((module_id in module_id_index) and
+ (module_id_index[module_id].get('tag') in tags)))
result = []
for module_id in module_ids:
@@ -327,8 +330,9 @@ def get_modules_json(record_ids, **kwargs):
@app.route('/api/1.0/companies/
')
@decorators.response()
+@decorators.cached()
@decorators.jsonify('company')
-def get_company(company_name):
+def get_company(company_name, **kwargs):
memory_storage_inst = vault.get_memory_storage()
for company in memory_storage_inst.get_companies():
if company.lower() == company_name.lower():
@@ -342,8 +346,9 @@ def get_company(company_name):
@app.route('/api/1.0/modules/')
@decorators.response()
+@decorators.cached()
@decorators.jsonify('module')
-def get_module(module):
+def get_module(module, **kwargs):
module_id_index = vault.get_vault()['module_id_index']
module = module.lower()
if module in module_id_index:
@@ -410,11 +415,13 @@ def get_bpd(records, **kwargs):
@decorators.exception_handler()
@decorators.response()
@decorators.cached(ignore=['user_id'])
-@decorators.jsonify('users')
+@decorators.jsonify()
@decorators.record_filter(ignore=['user_id'])
def get_users_json(record_ids, **kwargs):
user_ids = vault.get_memory_storage().get_index_keys_by_record_ids(
'user_id', record_ids)
+ if kwargs['_params']['user_id']:
+ user_ids.add(kwargs['_params']['user_id'][0])
result = [{'id': user_id,
'text': (vault.get_user_from_runtime_storage(user_id)
@@ -440,64 +447,35 @@ def get_user(user_id):
@decorators.exception_handler()
@decorators.response()
@decorators.cached(ignore=parameters.FILTER_PARAMETERS)
-@decorators.jsonify('releases')
+@decorators.jsonify(root=('data', 'default'))
def get_releases_json(**kwargs):
- return [{'id': r['release_name'], 'text': r['release_name'].capitalize()}
- for r in vault.get_release_options()]
-
-
-@app.route('/api/1.0/releases/')
-@decorators.response()
-@decorators.jsonify('release')
-def get_release_json(release):
- if release != 'all':
- if release not in vault.get_vault()['releases']:
- release = parameters.get_default('release')
-
- return {'id': release, 'text': release.capitalize()}
+ return ([{'id': r['release_name'], 'text': r['release_name'].capitalize()}
+ for r in vault.get_release_options()],
+ parameters.get_default('release'))
@app.route('/api/1.0/metrics')
@decorators.exception_handler()
@decorators.response()
@decorators.cached(ignore=parameters.FILTER_PARAMETERS)
-@decorators.jsonify('metrics')
+@decorators.jsonify(root=('data', 'default'))
def get_metrics_json(**kwargs):
- return sorted([{'id': m, 'text': t}
- for m, t in six.iteritems(parameters.METRIC_LABELS)],
- key=operator.itemgetter('text'))
-
-
-@app.route('/api/1.0/metrics/')
-@decorators.response()
-@decorators.jsonify('metric')
-@decorators.exception_handler()
-def get_metric_json(metric):
- if metric not in parameters.METRIC_LABELS:
- metric = parameters.get_default('metric')
- return {'id': metric, 'text': parameters.METRIC_LABELS[metric]}
+ return (sorted([{'id': m, 'text': t} for m, t in
+ six.iteritems(parameters.METRIC_LABELS)],
+ key=operator.itemgetter('text')),
+ parameters.get_default('metric'))
@app.route('/api/1.0/project_types')
@decorators.response()
@decorators.exception_handler()
@decorators.cached(ignore=parameters.FILTER_PARAMETERS)
-@decorators.jsonify('project_types')
+@decorators.jsonify(root=('data', 'default'))
def get_project_types_json(**kwargs):
- return [{'id': pt['id'], 'text': pt['title'], 'items': pt.get('items', [])}
- for pt in vault.get_project_types()]
-
-
-@app.route('/api/1.0/project_types/')
-@decorators.response()
-@decorators.jsonify('project_type')
-@decorators.exception_handler()
-def get_project_type_json(project_type):
- if not vault.is_project_type_valid(project_type):
- project_type = parameters.get_default('project_type')
-
- pt = vault.get_project_type(project_type)
- return {'id': pt['id'], 'text': pt['title']}
+ return ([{'id': pt['id'], 'text': pt['title'],
+ 'child': pt.get('child', False)}
+ for pt in vault.get_project_types()],
+ parameters.get_default('project_type'))
def _get_week(kwargs, param_name):
diff --git a/tests/api/test_companies.py b/tests/api/test_companies.py
index 79b5ee205..b359434e9 100644
--- a/tests/api/test_companies.py
+++ b/tests/api/test_companies.py
@@ -59,14 +59,14 @@ class TestAPICompanies(test_api.TestAPI):
response = self.app.get('/api/1.0/companies?metric=commits&'
'module=glance')
- companies = json.loads(response.data)['companies']
+ companies = json.loads(response.data)['data']
self.assertEqual([{'id': 'ibm', 'text': 'IBM'},
{'id': 'nec', 'text': 'NEC'},
{'id': 'ntt', 'text': 'NTT'}], companies)
response = self.app.get('/api/1.0/companies?metric=marks&'
'module=glance')
- companies = json.loads(response.data)['companies']
+ companies = json.loads(response.data)['data']
self.assertEqual([{'id': 'ibm', 'text': 'IBM'},
{'id': 'nec', 'text': 'NEC'}], companies)
diff --git a/tests/api/test_modules.py b/tests/api/test_modules.py
index f832b55a3..906ae6a05 100644
--- a/tests/api/test_modules.py
+++ b/tests/api/test_modules.py
@@ -45,7 +45,7 @@ class TestAPIModules(test_api.TestAPI):
response = self.app.get('/api/1.0/modules?'
'project_type=all&metric=commits')
- modules = json.loads(response.data)['modules']
+ modules = json.loads(response.data)['data']
self.assertEqual(
[{'id': 'glance', 'text': 'glance', 'tag': 'module'},
{'id': 'nova', 'text': 'nova', 'tag': 'module'},
@@ -58,7 +58,7 @@ class TestAPIModules(test_api.TestAPI):
response = self.app.get('/api/1.0/modules?module=nova-group&'
'project_type=integrated&metric=commits')
- modules = json.loads(response.data)['modules']
+ modules = json.loads(response.data)['data']
self.assertEqual(
[{'id': 'glance', 'text': 'glance', 'tag': 'module'},
{'id': 'nova', 'text': 'nova', 'tag': 'module'},
diff --git a/tests/api/test_releases.py b/tests/api/test_releases.py
index a4d76a48d..d3c303a94 100644
--- a/tests/api/test_releases.py
+++ b/tests/api/test_releases.py
@@ -28,17 +28,7 @@ class TestAPIReleases(test_api.TestAPI):
{'release_name': 'icehouse', 'end_date': 1397692800}]},
test_api.make_records(record_type=['commit'])):
response = self.app.get('/api/1.0/releases')
- releases = json.loads(response.data)['releases']
+ releases = json.loads(response.data)['data']
self.assertEqual(3, len(releases))
self.assertIn({'id': 'all', 'text': 'All'}, releases)
self.assertIn({'id': 'icehouse', 'text': 'Icehouse'}, releases)
-
- def test_release_details(self):
- with test_api.make_runtime_storage(
- {'releases': [
- {'release_name': 'prehistory', 'end_date': 1365033600},
- {'release_name': 'icehouse', 'end_date': 1397692800}]},
- test_api.make_records(record_type=['commit'])):
- response = self.app.get('/api/1.0/releases/icehouse')
- release = json.loads(response.data)['release']
- self.assertEqual({'id': 'icehouse', 'text': 'Icehouse'}, release)
diff --git a/tests/api/test_users.py b/tests/api/test_users.py
index ca135b723..3adc9b51f 100644
--- a/tests/api/test_users.py
+++ b/tests/api/test_users.py
@@ -36,7 +36,7 @@ class TestAPIUsers(test_api.TestAPI):
user_id=['john_doe', 'bill_smith'])):
response = self.app.get('/api/1.0/users?'
'module=nova&metric=commits')
- users = json.loads(response.data)['users']
+ users = json.loads(response.data)['data']
self.assertEqual(2, len(users))
self.assertIn({'id': 'john_doe', 'text': 'John Doe'}, users)
self.assertIn({'id': 'bill_smith', 'text': 'Bill Smith'}, users)