Permalink
Browse files

[bug 920166] Add product picker to question metrics dashboard.

  • Loading branch information...
1 parent 10f7eb8 commit c4d61ed566214898c1d5b4a553e8ec4012fe2eee @rlr rlr committed Jan 28, 2014
View
@@ -110,6 +110,7 @@ class QuestionsMetricList(CachedAPIView):
def get_objects(self, request):
# Set up the queries for the data we need
locale = request.GET.get('locale')
+ product = request.GET.get('product')
# Set up the query for the data we need.
qs = _daily_qs_for(Question)
@@ -120,6 +121,9 @@ def get_objects(self, request):
if locale:
qs = qs.filter(locale=locale)
+ if product:
+ qs = qs.filter(products__slug=product)
+
# All answers that were created within 3 days of the question.
aq_72 = Answer.objects.filter(
created__lt=F('question__created') + timedelta(days=3))
@@ -13,6 +13,7 @@
SUPPORT_FORUM_CONTRIBUTORS_METRIC_CODE, VISITORS_METRIC_CODE,
EXIT_SURVEY_YES_CODE, EXIT_SURVEY_NO_CODE, EXIT_SURVEY_DONT_KNOW_CODE)
from kitsune.kpi.tests import metric, metric_kind
+from kitsune.products.tests import product
from kitsune.sumo.helpers import urlparams
from kitsune.sumo.tests import TestCase
from kitsune.sumo.urlresolvers import reverse
@@ -99,6 +100,52 @@ def test_questions_by_locale(self):
assert 'responded_24' not in r['objects'][0]
assert 'responded_72' not in r['objects'][0]
+ def test_questions_by_product(self):
+ """Test product filtering of questions API call."""
+ firefox_os = product(slug='firefox-os', save=True)
+ firefox = product(slug='firefox', save=True)
+
+ # A Firefox OS question with a solution:
+ q = question(save=True)
+ q.products.add(firefox_os)
+ a = answer(question=q, save=True)
+ q.solution = a
+ q.save()
+
+ # A Firefox OS question with an answer:
+ q = question(save=True)
+ q.products.add(firefox_os)
+ answer(question=q, save=True)
+
+ # A Firefox OS question without answers:
+ q = question(save=True)
+ q.products.add(firefox_os)
+
+ # A Firefox question without answers:
+ q = question(locale='pt-BR', save=True)
+ q.products.add(firefox)
+
+ # Verify no product filtering:
+ r = self._get_api_result('api.kpi.questions')
+ eq_(r['objects'][0]['solved'], 1)
+ eq_(r['objects'][0]['responded_24'], 2)
+ eq_(r['objects'][0]['responded_72'], 2)
+ eq_(r['objects'][0]['questions'], 4)
+
+ # Verify product=firefox-os
+ r = self._get_api_result('api.kpi.questions', product='firefox-os')
+ eq_(r['objects'][0]['solved'], 1)
+ eq_(r['objects'][0]['responded_24'], 2)
+ eq_(r['objects'][0]['responded_72'], 2)
+ eq_(r['objects'][0]['questions'], 3)
+
+ # Verify product=firefox
+ r = self._get_api_result('api.kpi.questions', product='firefox')
+ eq_(r['objects'][0]['questions'], 1)
+ assert 'solved' not in r['objects'][0]
+ assert 'responded_24' not in r['objects'][0]
+ assert 'responded_72' not in r['objects'][0]
+
def test_questions_inactive_user(self):
"""Verify questions from inactive users aren't counted."""
# Two questions for an inactive user.
@@ -149,6 +196,13 @@ def test_kb_vote(self):
helpful_vote(revision=r, save=True)
helpful_vote(revision=r, helpful=True, save=True)
+ # Assign 2 documents to Firefox OS and 1 to Firefox
+ firefox_os = product(slug='firefox-os', save=True)
+ firefox = product(slug='firefox', save=True)
+ r1.document.products.add(firefox_os)
+ r2.document.products.add(firefox_os)
+ r3.document.products.add(firefox)
+
# All votes should be counted if we don't specify a locale
r = self._get_api_result('api.kpi.kb-votes')
eq_(r['objects'][0]['kb_helpful'], 3)
@@ -164,6 +218,22 @@ def test_kb_vote(self):
eq_(r['objects'][0]['kb_helpful'], 2)
eq_(r['objects'][0]['kb_votes'], 6)
+ # Only Firefox OS votes:
+ r = self._get_api_result('api.kpi.kb-votes', product='firefox-os')
+ eq_(r['objects'][0]['kb_helpful'], 2)
+ eq_(r['objects'][0]['kb_votes'], 6)
+
+ # Only Firefox votes:
+ r = self._get_api_result('api.kpi.kb-votes', product='firefox')
+ eq_(r['objects'][0]['kb_helpful'], 1)
+ eq_(r['objects'][0]['kb_votes'], 3)
+
+ # Only Firefox OS + es votes:
+ r = self._get_api_result(
+ 'api.kpi.kb-votes', product='firefox-os', locale='es')
+ eq_(r['objects'][0]['kb_helpful'], 1)
+ eq_(r['objects'][0]['kb_votes'], 3)
+
def test_active_contributors(self):
"""Test active contributors API call."""
# 2 en-US revisions by 2 contributors:
@@ -1,4 +1,5 @@
{% extends "questions/base.html" %}
+{% from "dashboards/includes/macros.html" import product_choice_list %}
{% set title = _('Support Forum Metrics') %}
{% set crumbs = [(url('questions.questions'), _('Support Forum')),
(None, _('Metrics'))] %}
@@ -8,26 +9,42 @@
{% block content %}
<h1>{{ _('Support Forum Metrics') }}</h1>
- <section id="locale-picker">
- <span>{{ _('Locale:') }}</span>
- {% if not current_locale %}
- <strong>{{ _('All') }}</strong>
- {% else %}
- <a href="{{ url('questions.metrics') }}">{{ _('All') }}</a>
- {% endif %}
- {% for locale in settings.AAQ_LANGUAGES %}
- {% if current_locale == locale %}
- <strong>{{ locale }}</strong>
- {% else %}
- <a href="{{ url('questions.locale_metrics', locale) }}">{{ locale }}</a>
- {% endif %}
- {% endfor %}
- </section>
+ {% if not current_locale %}
+ {% set base_url = url('questions.metrics')|urlparams(None, request.GET)|urlparams(product=None) %}
+ {% else %}
+ {% set base_url = url('questions.locale_metrics', current_locale)|urlparams(None, request.GET)|urlparams(product=None) %}
+ {% endif %}
+ {{ product_choice_list(products, product, base_url) }}
+
+ <div class="choice-list">
+ <label>{{ _('Locale:') }}</label>
+ <ul>
+ <li>
+ {% if not current_locale %}
+ {{ _('All') }}
+ {% else %}
+ <a href="{{ url('questions.metrics') }}">{{ _('All') }}</a>
+ {% endif %}
+ </li>
+ {% for locale in settings.AAQ_LANGUAGES %}
+ <li>
+ {% if current_locale == locale %}
+ {{ locale }}
+ {% else %}
+ <a href="{{ url('questions.locale_metrics', locale)|urlparams(None, request.GET) }}">{{ locale }}</a>
+ {% endif %}
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
{% set api_url = url('api.kpi.questions') %}
{% if current_locale %}
{% set api_url = api_url|urlparams(locale=current_locale) %}
{% endif %}
+ {% if product %}
+ {% set api_url = api_url|urlparams(product=product.slug) %}
+ {% endif %}
<section id="questions-metrics" data-url="{{ api_url }}">
<div class="rickshaw">
<div class="inline-controls"></div>
@@ -56,13 +73,16 @@ <h2 class="grid_12">{{ _('Topics') }}</h2>
{{ form.as_ul() }}
<li><input type="submit" /></li>
</ul>
+ {% if product %}
+ <input type="hidden" name="product" value="{{ product.slug }}" />
+ {% endif %}
</form>
</div>
</div>
</div>
{% else %}
<p>
- {{ _('Data is temporarily unavailable, please try again in a few minutes.') }}
+ {{ _('There is no topic data available for the current selections.') }}
</p>
{% endif %}
{% endblock %}
View
@@ -1382,7 +1382,7 @@ def marketplace_success(request, template=None):
return render(request, template)
-def stats_topic_data(bucket_days, start, end, locale=None):
+def stats_topic_data(bucket_days, start, end, locale=None, product=None):
"""Gets a zero filled histogram for each question topic.
Uses elastic search.
@@ -1404,6 +1404,9 @@ def stats_topic_data(bucket_days, start, end, locale=None):
if locale:
f &= F(question_locale=locale)
+ if product:
+ f &= F(product=product.slug)
+
topics = Topic.objects.values('slug', 'title')
facets = {}
# TODO: If we change to using datetimes in ES, 'histogram' below
@@ -1480,6 +1483,10 @@ def metrics(request, locale_code=None):
"""The Support Forum metrics dashboard."""
template = 'questions/metrics.html'
+ product = request.GET.get('product')
+ if product:
+ product = get_object_or_404(Product, slug=product)
+
form = StatsForm(request.GET)
if form.is_valid():
bucket_days = form.cleaned_data['bucket']
@@ -1491,9 +1498,12 @@ def metrics(request, locale_code=None):
end = date.today()
data = {
- 'graph': stats_topic_data(bucket_days, start, end, locale_code),
+ 'graph': stats_topic_data(
+ bucket_days, start, end, locale_code, product),
'form': form,
'current_locale': locale_code,
+ 'product': product,
+ 'products': Product.objects.filter(visible=True),
}
return render(request, template, data)
@@ -440,25 +440,6 @@
}
}
-.choice-list {
- margin: 2em 0;
-
- ul {
- display: inline;
- }
-
- li {
- display: inline-block;
- font-weight: bold;
- list-style: none;
- padding: 0 8px;
-
- a {
- font-weight: normal;
- }
- }
-}
-
#kb-helpfulness-chart {
min-height: 400px;
@@ -1542,3 +1542,22 @@ input[type=button],
}
}
}
+
+.choice-list {
+ margin: 2em 0;
+
+ ul {
+ display: inline;
+ }
+
+ li {
+ display: inline-block;
+ font-weight: bold;
+ list-style: none;
+ padding: 0 8px;
+
+ a {
+ font-weight: normal;
+ }
+ }
+}
@@ -3,7 +3,3 @@
border-radius: 5px;
padding: 20px 10px;
}
-
-#locale-picker {
- margin: 20px 0;
-}

0 comments on commit c4d61ed

Please sign in to comment.