From e42d1f661f8b67f925f3afa0e92867e71b7b18e4 Mon Sep 17 00:00:00 2001 From: Ilya Shakhat Date: Mon, 2 Sep 2013 19:28:30 +0400 Subject: [PATCH] Implemented module groupping Implements blueprint modules-grouping Change-Id: I272fe3c9c36dd3d446f32304084ee5869ec8d5bb --- dashboard/static/css/style.css | 5 ++ dashboard/templates/layout.html | 9 +- dashboard/web.py | 86 +++++++++++++++++-- etc/default_data.json | 34 ++++++++ etc/default_data.schema.json | 19 ++++ etc/test_default_data.json | 14 +++ .../processor/default_data_processor.py | 1 + 7 files changed, 160 insertions(+), 8 deletions(-) diff --git a/dashboard/static/css/style.css b/dashboard/static/css/style.css index 9715dcf2b..657fe4247 100644 --- a/dashboard/static/css/style.css +++ b/dashboard/static/css/style.css @@ -208,6 +208,11 @@ a[href^="https://launchpad"]:after { font-size: 9pt; } +.select_group { + font-weight: bold; + color: #4bb2c5; +} + .review_mark { font-weight: bold; } diff --git a/dashboard/templates/layout.html b/dashboard/templates/layout.html index 6fa974a49..6140e8991 100644 --- a/dashboard/templates/layout.html +++ b/dashboard/templates/layout.html @@ -276,7 +276,14 @@ callback(data["module"]); }); } - } }); + }, + formatResultCssClass: function (item) { + if (item.group) { + return "select_group" + } + return ""; + } + }); $('#module') .on("change", function(e) { reload(); }); diff --git a/dashboard/web.py b/dashboard/web.py index 28ae084fe..cf10e4473 100644 --- a/dashboard/web.py +++ b/dashboard/web.py @@ -17,6 +17,7 @@ import cgi import datetime import functools import json +import operator import os import re import urllib @@ -101,6 +102,7 @@ def get_vault(): if have_updates: init_project_types(vault) init_releases(vault) + init_module_groups(vault) return vault @@ -162,6 +164,43 @@ def init_project_types(vault): vault['project_type_group_index'] = project_type_group_index +def init_module_groups(vault): + runtime_storage_inst = vault['runtime_storage'] + module_index = {} + module_id_index = {} + module_groups = runtime_storage_inst.get_by_key('module_groups') or [] + + for module_group in module_groups: + module_group_name = module_group['module_group_name'] + module_group_id = module_group_name.lower() + + module_id_index[module_group_name] = { + 'group': True, + 'id': module_group_id, + 'text': module_group_name, + 'modules': [m.lower() for m in module_group['modules']], + } + + modules = module_group['modules'] + for module in modules: + if module in module_index: + module_index[module].add(module_group_id) + else: + module_index[module] = set([module_group_id]) + + memory_storage_inst = vault['memory_storage'] + for module in memory_storage_inst.get_modules(): + module_id_index[module] = { + 'id': module.lower(), + 'text': module, + 'modules': [module.lower()], + } + + vault['module_group_index'] = module_index + vault['module_id_index'] = module_id_index + vault['module_groups'] = module_groups + + def get_project_type_options(): return get_vault()['project_type_options'] @@ -226,6 +265,15 @@ def get_single_parameter(kwargs, singular_name, use_default=True): return '' +def resolve_modules(module_ids): + module_id_index = get_vault()['module_id_index'] + modules = set() + for module_id in module_ids: + if module_id in module_id_index: + modules |= set(module_id_index[module_id]['modules']) + return modules + + # Decorators --------- def record_filter(ignore=None, use_default=True): @@ -243,8 +291,8 @@ def record_filter(ignore=None, use_default=True): if 'module' not in ignore: param = get_parameter(kwargs, 'module', 'modules', use_default) if param: - record_ids &= ( - memory_storage.get_record_ids_by_modules(param)) + record_ids &= (memory_storage.get_record_ids_by_modules( + resolve_modules(param))) if 'project_type' not in ignore: param = get_parameter(kwargs, 'project_type', 'project_types', @@ -667,7 +715,31 @@ def get_companies_json(records): @exception_handler() @record_filter(ignore='module') def get_modules_json(records): - return _get_collection(records, 'modules', 'module', 'module_name') + module_group_index = get_vault()['module_group_index'] + module_id_index = get_vault()['module_id_index'] + + modules_set = set() + for record in records: + module = record['module'] + if module not in modules_set: + modules_set.add(module) + + modules_groups_set = set() + for module in modules_set: + if module in module_group_index: + modules_groups_set |= module_group_index[module] + + modules_set |= modules_groups_set + + query = (flask.request.args.get('module_name') or '').lower() + options = [] + + for module in modules_set: + if module.find(query) >= 0: + options.append(module_id_index[module]) + + result = sorted(options, key=operator.itemgetter('text')) + return json.dumps({'modules': result}) @app.route('/data/companies/.json') @@ -686,10 +758,10 @@ def get_company(company_name): @app.route('/data/modules/.json') def get_module(module): - memory_storage = get_vault()['memory_storage'] - for m in memory_storage.get_modules(): - if m.lower() == module.lower(): - return json.dumps({'module': {'id': module, 'text': m}}) + module_id_index = get_vault()['module_id_index'] + module = module.lower() + if module in module_id_index: + return json.dumps({'module': module_id_index[module]}) return json.dumps({}) diff --git a/etc/default_data.json b/etc/default_data.json index 5ac07e0eb..d84fb26dd 100644 --- a/etc/default_data.json +++ b/etc/default_data.json @@ -4275,6 +4275,40 @@ "project_group": null } ], + "module_groups": [ + { + "module_group_name": "nova-group", + "modules": ["nova", "python-novaclient"] + }, + { + "module_group_name": "neutron-group", + "modules": ["neutron", "python-neutronclient"] + }, + { + "module_group_name": "keystone-group", + "modules": ["keystone", "python-keystoneclient"] + }, + { + "module_group_name": "cinder-group", + "modules": ["cinder", "python-cinderclient"] + }, + { + "module_group_name": "glance-group", + "modules": ["glance", "python-glanceclient"] + }, + { + "module_group_name": "swift-group", + "modules": ["swift", "python-swiftclient"] + }, + { + "module_group_name": "savanna-group", + "modules": ["savanna", "python-savannaclient", "savanna-dashboard", "savanna-extra"] + }, + { + "module_group_name": "murano-group", + "modules": ["murano-agent", "python-muranoclient", "murano-api", "murano-common", "murano-conductor", "murano-dashboard", "murano-deployment", "murano-docs", "murano-tests"] + } + ], "releases": [ { "release_name": "prehistory", diff --git a/etc/default_data.schema.json b/etc/default_data.schema.json index e0bf92c95..8e3d24580 100644 --- a/etc/default_data.schema.json +++ b/etc/default_data.schema.json @@ -143,6 +143,25 @@ "required": ["organization", "project_type"], "additionalProperties": false } + }, + "module_groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "module_group_name": { + "type": "string" + }, + "modules": { + "type": ["array"], + "items": { + "type": "string" + } + } + }, + "required": ["module_group_name", "modules"], + "additionalProperties": false + } } } } \ No newline at end of file diff --git a/etc/test_default_data.json b/etc/test_default_data.json index 164ab9e78..a6160345c 100644 --- a/etc/test_default_data.json +++ b/etc/test_default_data.json @@ -83,6 +83,13 @@ "module": "glance", "project_type": "openstack" }, + { + "branches": ["master"], + "module": "python-glanceclient", + "project_group": "core", + "project_type": "openstack", + "uri": "git://github.com/openstack/python-glanceclient.git" + }, { "branches": ["master"], "module": "stackalytics", @@ -99,6 +106,13 @@ } ], + "module_groups": [ + { + "module_group_name": "glance-group", + "modules": ["glance", "python-glanceclient"] + } + ], + "releases": [ { "release_name": "prehistory", diff --git a/stackalytics/processor/default_data_processor.py b/stackalytics/processor/default_data_processor.py index f3e2637ed..3e5d8157f 100644 --- a/stackalytics/processor/default_data_processor.py +++ b/stackalytics/processor/default_data_processor.py @@ -108,6 +108,7 @@ KEYS = { 'repos': None, 'releases': None, 'companies': _process_companies, + 'module_groups': None, }