diff --git a/stackalytics/dashboard/decorators.py b/stackalytics/dashboard/decorators.py index 1322219ee..ad5706f52 100644 --- a/stackalytics/dashboard/decorators.py +++ b/stackalytics/dashboard/decorators.py @@ -404,15 +404,17 @@ def templated(template=None, return_code=200): module = parameters.get_single_parameter(kwargs, 'module') ctx['module'] = module + module_name = None if module and module in vault_inst['module_id_index']: ctx['module_inst'] = vault_inst['module_id_index'][module] + module_name = ctx['module_inst']['module_group_name'] ctx['user_id'] = parameters.get_single_parameter(kwargs, 'user_id') if ctx['user_id']: ctx['user_inst'] = vault.get_user_from_runtime_storage( ctx['user_id']) ctx['page_title'] = helpers.make_page_title( - ctx['company'], ctx['user_id'], ctx['module'], ctx['release']) + ctx['company'], ctx['user_id'], module_name, ctx['release']) ctx['stackalytics_version'] = ( stackalytics_version.version_info.version_string()) ctx['stackalytics_release'] = ( diff --git a/stackalytics/dashboard/helpers.py b/stackalytics/dashboard/helpers.py index 6c0dc0951..568512fa4 100644 --- a/stackalytics/dashboard/helpers.py +++ b/stackalytics/dashboard/helpers.py @@ -111,6 +111,35 @@ def extend_user(user): return user +def extend_module(module_id): + module_id_index = vault.get_vault()['module_id_index'] + module_id = module_id.lower() + + if module_id not in module_id_index: + return None + + repos_index = vault.get_vault()['repos_index'] + + module = module_id_index[module_id] + name = module['module_group_name'] + if name[0].islower(): + name = name.capitalize() + + child_modules = [] + for m in module['modules']: + child = {'module_name': m} + if m in repos_index: + child['repo_uri'] = repos_index[m]['uri'] + child_modules.append(child) + + return { + 'id': module_id, + 'name': name, + 'tag': module['tag'], + 'modules': child_modules, + } + + def get_activity(records, start_record, page_size, query_message=None): if query_message: # note that all records are now dicts! diff --git a/stackalytics/dashboard/templates/_macros/module_details.html b/stackalytics/dashboard/templates/_macros/module_details.html new file mode 100644 index 000000000..dcf76c6a4 --- /dev/null +++ b/stackalytics/dashboard/templates/_macros/module_details.html @@ -0,0 +1,54 @@ +{% macro show_module_details(module) -%} + + + + + +
+ +{%- endmacro %} diff --git a/stackalytics/dashboard/templates/overview.html b/stackalytics/dashboard/templates/overview.html index 91a358232..ad12189e6 100644 --- a/stackalytics/dashboard/templates/overview.html +++ b/stackalytics/dashboard/templates/overview.html @@ -2,6 +2,7 @@ {% import '_macros/activity_log.html' as activity_log %} {% import '_macros/contribution_summary.html' as contribution_summary %} {% import '_macros/user_profile.html' as user_profile %} +{% import '_macros/module_details.html' as module_details %} {% set show_company_breakdown = (not company) and (not user_id) %} {% set show_engineer_breakdown = (not user_id) %} @@ -13,6 +14,7 @@ {% set show_contribution_on_left = (not user_id) and (module) %} {% set show_contribution_on_right = (user_id) or (company and not module) %} {% set show_user_profile = (user_id) %} +{% set show_module_details = (module) %} {% set show_top_mentors_options = (metric == 'tm_marks') %} {% set show_review_ratio = (metric in ['marks', 'tm_marks']) %} @@ -184,6 +186,10 @@ {% endif %} + {% if show_module_details %} + {{ module_details.show_module_details(module=module) }} + {% endif %} + {% if show_bp_breakdown %}

Blueprint popularity

diff --git a/stackalytics/dashboard/vault.py b/stackalytics/dashboard/vault.py index 8eabc1570..5f0383fba 100644 --- a/stackalytics/dashboard/vault.py +++ b/stackalytics/dashboard/vault.py @@ -89,6 +89,7 @@ def get_vault(): _init_releases(vault) _init_module_groups(vault) _init_project_types(vault) + _init_repos(vault) _init_user_index(vault) return vault @@ -128,8 +129,14 @@ def _init_project_types(vault): project_types = runtime_storage_inst.get_by_key('project_types') or {} vault['project_types'] = project_types - vault['project_types_index'] = dict([(pt['id'], pt) - for pt in project_types]) + vault['project_types_index'] = dict((pt['id'], pt) for pt in project_types) + + +def _init_repos(vault): + runtime_storage_inst = vault['runtime_storage'] + repos = runtime_storage_inst.get_by_key('repos') or {} + + vault['repos_index'] = dict((r['module'], r) for r in repos) def _init_user_index(vault): @@ -173,7 +180,7 @@ def get_user_from_runtime_storage(user_id): return user_index[user_id] -def resolve_modules_for_releases(module_ids, releases): +def _resolve_modules_for_releases(module_ids, releases): module_id_index = get_vault().get('module_id_index') or {} for module_id in module_ids: @@ -201,7 +208,7 @@ def resolve_modules_for_releases(module_ids, releases): def resolve_modules(module_ids, releases): all_releases = get_vault()['releases'].keys() - for module, release in resolve_modules_for_releases(module_ids, releases): + for module, release in _resolve_modules_for_releases(module_ids, releases): if release is None: for r in all_releases: yield (module, r) diff --git a/stackalytics/dashboard/web.py b/stackalytics/dashboard/web.py index 6bad82c65..2ce824cd2 100644 --- a/stackalytics/dashboard/web.py +++ b/stackalytics/dashboard/web.py @@ -343,18 +343,15 @@ def get_company(company_name, **kwargs): flask.abort(404) -@app.route('/api/1.0/modules/') +@app.route('/api/1.0/modules/') @decorators.response() @decorators.cached() @decorators.jsonify('module') -def get_module(module, **kwargs): - module_id_index = vault.get_vault()['module_id_index'] - module = module.lower() - if module in module_id_index: - return {'id': module_id_index[module]['id'], - 'text': module_id_index[module]['module_group_name'], - 'tag': module_id_index[module]['tag']} - flask.abort(404) +def get_module(module_id, **kwargs): + module = helpers.extend_module(module_id) + if not module: + flask.abort(404) + return module @app.route('/api/1.0/members') diff --git a/tests/api/test_modules.py b/tests/api/test_modules.py index 6d747ede7..a47c68637 100644 --- a/tests/api/test_modules.py +++ b/tests/api/test_modules.py @@ -79,7 +79,7 @@ class TestAPIModules(test_api.TestAPI): 'module_groups': { 'nova-group': {'id': 'nova-group', 'module_group_name': 'nova-group', - 'modules': ['nova', 'nova-cli'], + 'modules': ['nova-cli', 'nova'], 'tag': 'group'}, 'nova': test_api.make_module('nova'), 'nova-cli': test_api.make_module('nova-cli'), @@ -89,10 +89,20 @@ class TestAPIModules(test_api.TestAPI): response = self.app.get('/api/1.0/modules/nova') module = test_api.load_json(response)['module'] self.assertEqual( - {'id': 'nova', 'text': 'nova', 'tag': 'module'}, module) + {'id': 'nova', + 'modules': [ + {'module_name': 'nova', + 'repo_uri': 'git://git.openstack.org/openstack/nova.git'} + ], + 'name': 'Nova', 'tag': 'module'}, module) response = self.app.get('/api/1.0/modules/nova-group') module = test_api.load_json(response)['module'] self.assertEqual( - {'tag': 'group', 'id': 'nova-group', 'text': 'nova-group'}, - module) + {'id': 'nova-group', + 'modules': [ + {'module_name': 'nova-cli'}, + {'module_name': 'nova', + 'repo_uri': 'git://git.openstack.org/openstack/nova.git'} + ], + 'name': 'Nova-group', 'tag': 'group'}, module)