Implemented base for KPI reports

Added report that checks position in the top

Change-Id: Id9e8a81518f71de75937be1d1ab3c2aa4ab37377
This commit is contained in:
Ilya Shakhat 2013-11-29 19:21:45 +04:00
parent d95f2d560a
commit 9a39255091
5 changed files with 198 additions and 0 deletions

28
dashboard/kpi.py Normal file
View File

@ -0,0 +1,28 @@
# Copyright (c) 2013 Mirantis Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import flask
from dashboard import decorators
blueprint = flask.Blueprint('kpi', __name__, url_prefix='/kpi')
@blueprint.route('/group')
@decorators.templated()
@decorators.exception_handler()
def kpi():
return

View File

@ -336,6 +336,41 @@ a[href^="https://launchpad"]:after {
color: #999999;
}
.kpi_block {
padding-bottom: 1em;
}
.kpi_title_block {
margin-left: 50px;
}
.kpi_title {
font-size: 16pt;
font-weight: bold;
}
.kpi_marker {
font-size: 19pt;
font-weight: bold;
text-align: center; vertical-align: middle;
background-color: lightgray; color: white;
float: left; width: 32px; height: 32px;
}
.kpi_good {
background-color: #008000;
}
.kpi_bad {
background-color: red;
}
.kpi_note {
font-size: 11pt;
color: #606060;
display: none;
}
.select2-results {
max-height: 300px;
}

View File

@ -0,0 +1,55 @@
{% extends "base.html" %}
{% block head %}
<title>{% block title %}{% endblock %}</title>
<meta name="keywords" content="openstack, contribution, statistics, community, review, commit, report, havana, grizzly, icehouse"/>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/style.css') }}">
<link href='http://fonts.googleapis.com/css?family=PT+Sans:400,700,400italic&subset=latin,cyrillic' rel='stylesheet' type='text/css' />
<link href='http://fonts.googleapis.com/css?family=PT+Sans+Caption&subset=latin,cyrillic' rel='stylesheet' type='text/css' />
<link href='http://fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700&subset=latin,cyrillic' rel='stylesheet' type='text/css' />
<link rel="icon" href="{{ url_for('static', filename='images/favicon.png') }}" type="image/png"/>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/jquery.jqplot.min.css') }}">
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/jquery.dataTables.css') }}">
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/select2.css') }}">
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/style.css') }}">
<script type="text/javascript" src="{{ url_for('static', filename='js/jquery-1.9.1.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jquery.dataTables.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jquery.jqplot.min.js') }}"></script>
<!--[if lt IE 9]><script type="text/javascript" src="{{ url_for('static', filename='js/excanvas.min.js') }}"></script><![endif]-->
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.json2.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.pieRenderer.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.barRenderer.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.bubbleRenderer.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.categoryAxisRenderer.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.dateAxisRenderer.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.canvasTextRenderer.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.canvasAxisLabelRenderer.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.canvasAxisTickRenderer.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.cursor.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jqplot.highlighter.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/select2.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jquery.tmpl.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/stackalytics-ui.js') }}"></script>
{% block scripts %}{% endblock %}
{% endblock %}
{% block body %}
<div style="margin: 2em;">
<div id="analytics_header" style="padding-bottom: 1em; border-bottom: 1px solid darkgrey;">
<span id="logo"><a href="/">Stackalytics</a></span>
<span id="slogan">| community heartbeat</span>
</div>
{% block content %}
{% endblock %}
</div>
{% endblock %}

View File

@ -0,0 +1,72 @@
{% extends "kpi/base_kpi.html" %}
{% block title %}
Group KPI
{% endblock %}
{% block scripts %}
<script type="text/javascript">
function load_position_target_data(id, url, target_id, target_value) {
$.ajax({
url: make_uri(url),
dataType: "jsonp",
success: function (data) {
data = data["stats"];
var position = -1;
for (var i = 0; i < data.length; i++) {
if (data[i].id == target_id) {
position = i;
break;
}
}
var isOk = false;
var message = "";
if (position >= 0) {
if (position <= target_value) {
isOk = true;
message = "Target position is " + target_value;
} else {
message = "Position " + position + " is worse than target " + target_value;
}
} else {
message = "Target " + target_id + " is not found";
}
$("#position_target_marker_" + id).addClass(isOk? "kpi_good": "kpi_bad").text(i);
$("#position_target_note_" + id).show().text(message);
}
});
}
</script>
{% endblock %}
{% macro position_target(record_filter, target_id, target_value, title) -%}
{% set id=title.replace(' ', '_') %}
<script type="application/javascript">
$(document).ready(function () {
load_position_target_data("{{ id }}", "{{ record_filter|make_url('/api/1.0/stats/companies')|safe }}", "{{ target_id }}", "{{ target_value }}");
});
</script>
<div id="position_target" class="kpi_block">
<div id="position_target_marker_{{ id }}" class="kpi_marker"></div>
<div class="kpi_title_block">
<div class="kpi_title">{{ title }}</div>
<div class="kpi_note" id="position_target_note_{{ id }}"></div>
</div>
</div>
{%- endmacro %}
{% block content %}
<h1>Metrics</h1>
{{ position_target({'release': 'icehouse', 'project_type': 'openstack', 'metric': 'commits'}, 'Mirantis', 5, 'Position by commits') }}
{{ position_target({'release': 'icehouse', 'project_type': 'openstack', 'metric': 'marks'}, 'Mirantis', 5, 'Position by reviews') }}
{% endblock %}

View File

@ -23,6 +23,7 @@ from oslo.config import cfg
from dashboard import decorators
from dashboard import helpers
from dashboard import kpi
from dashboard import parameters
from dashboard import reports
from dashboard import vault
@ -37,6 +38,7 @@ app = flask.Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('DASHBOARD_CONF', silent=True)
app.register_blueprint(reports.blueprint)
app.register_blueprint(kpi.blueprint)
LOG = logging.getLogger(__name__)
@ -434,6 +436,12 @@ def timeline(records, **kwargs):
gravatar = gravatar_ext.Gravatar(app, size=64, rating='g', default='wavatar')
@app.template_filter('make_url')
def to_url_params(dict_params, base_url):
return base_url + '?' + '&'.join(
['%s=%s' % (k, v) for k, v in dict_params.iteritems()])
def main():
app.run(cfg.CONF.listen_host, cfg.CONF.listen_port)