diff --git a/dashboard/templates/kpi/kpi.html b/dashboard/templates/kpi/kpi.html
index 045c15ac1..2a5ee63ef 100644
--- a/dashboard/templates/kpi/kpi.html
+++ b/dashboard/templates/kpi/kpi.html
@@ -7,63 +7,110 @@
{% block scripts %}
{% endblock %}
-{% macro goal_position_in_top(record_filter, item_type, item_id, target_position, title) -%}
+{% macro marker_block(id, title) %}
+
+{%- endmacro %}
- {% set id = title.replace(' ', '_') %}
+{% macro goal_position_in_top(record_filter, item_type, item_id, target_position, title) -%}
+ {% set id = title|remove_ctrl_chars %}
{% set uri = '/api/1.0/stats/' + item_type %}
-
-
+ {{ marker_block(id, title) }}
{%- endmacro %}
+{% macro goal_percentage_in_top_less_than(record_filter, item_type, item_id, target_percentage, title) -%}
+ {% set id = title|remove_ctrl_chars %}
+ {% set uri = '/api/1.0/stats/' + item_type %}
+
+
+
+ {{ marker_block(id, title) }}
+{%- endmacro %}
+
+
{% block content %}
Metrics
@@ -72,4 +119,7 @@
{{ goal_position_in_top({'release': 'icehouse', 'project_type': 'openstack', 'metric': 'marks', 'module': 'glance', 'exclude': 'core'},
'engineers', 'boris-42', 3, 'Top-3 in non-core top reviewers') }}
+ {{ goal_percentage_in_top_less_than({'release': 'all', 'project_type': 'stackforge', 'metric': 'commits', 'module': 'stackalytics'},
+ 'companies', 'Mirantis', 0.8, 'Internal contribution is less than 80%') }}
+
{% endblock %}
diff --git a/dashboard/web.py b/dashboard/web.py
index 984e6d8a0..46dbc35c3 100644
--- a/dashboard/web.py
+++ b/dashboard/web.py
@@ -20,6 +20,7 @@ import time
import flask
from flask.ext import gravatar as gravatar_ext
from oslo.config import cfg
+import re
from dashboard import decorators
from dashboard import helpers
@@ -472,6 +473,11 @@ def to_url_params(dict_params, base_url):
['%s=%s' % (k, v) for k, v in dict_params.iteritems()])
+@app.template_filter('remove_ctrl_chars')
+def remove_ctrl_chars(text):
+ return re.sub(r'[\W]', '_', text)
+
+
def main():
app.run(cfg.CONF.listen_host, cfg.CONF.listen_port)