diff --git a/completion_aggregator/templates/chapter_completion_progress_bar.html b/completion_aggregator/templates/chapter_completion_progress_bar.html
new file mode 100644
index 00000000..748c50ac
--- /dev/null
+++ b/completion_aggregator/templates/chapter_completion_progress_bar.html
@@ -0,0 +1,13 @@
+{% load i18n %}
+
+
+
0%
+
+
+ {{completion_percentage}}%
+
+
+
100%
+
diff --git a/completion_aggregator/templates/completion_progress_bar.html b/completion_aggregator/templates/completion_progress_bar.html
new file mode 100644
index 00000000..300ec883
--- /dev/null
+++ b/completion_aggregator/templates/completion_progress_bar.html
@@ -0,0 +1,15 @@
+{% load i18n %}
+
+
+
+
0%
+
+
+ {{completion_percentage}}%
+
+
+
100%
+
+
diff --git a/completion_aggregator/urls.py b/completion_aggregator/urls.py
index d36755cc..63a5923b 100644
--- a/completion_aggregator/urls.py
+++ b/completion_aggregator/urls.py
@@ -5,10 +5,11 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from django.conf.urls import include, url
-from django.views.generic import TemplateView
+from . import views
urlpatterns = [
url(r'^v1/', include('completion_aggregator.api.v1.urls', namespace='completion_api_v1')),
url(r'^v0/', include('completion_aggregator.api.v0.urls', namespace='completion_api_v0')),
- url(r'^$', TemplateView.as_view(template_name="completion_aggregator/base.html")),
+ url(r'^progress_bar/(?P[\w.@+:-]+)/$', views.CompletionProgressBarView.as_view(), name="completion-progress-bar"),
+ url(r'^progress_bar/(?P[\w.@+:-]+)/(?P.+)/$', views.CompletionProgressBarView.as_view(), name="completion-progress-bar"),
]
diff --git a/completion_aggregator/views.py b/completion_aggregator/views.py
new file mode 100644
index 00000000..0f8b2afe
--- /dev/null
+++ b/completion_aggregator/views.py
@@ -0,0 +1,71 @@
+"""
+completion_aggregator App progress bar view
+"""
+from __future__ import absolute_import, unicode_literals
+
+from django.conf import settings
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.shortcuts import render
+from django.views.decorators.clickjacking import xframe_options_exempt
+from django.views.generic import TemplateView
+from xblockutils.resources import ResourceLoader
+
+from .api.v1.views import CompletionDetailView
+
+loader = ResourceLoader(__name__)
+
+
+class CompletionProgressBarView(LoginRequiredMixin, TemplateView):
+ """
+ View to display the progress bar of a student in a course
+ """
+ @xframe_options_exempt
+ def get(self, request, course_key, chapter_id=None):
+ """
+ Fetch progress and render the template.
+ """
+ completion_percentage = 0
+ new_req = request.GET.copy()
+ new_req['username'] = request.user.username
+ if chapter_id is not None:
+ new_req['requested_fields'] = "chapter"
+ request.GET = new_req
+ completion_resp = CompletionDetailView.as_view()(request, course_key).data
+ if completion_resp:
+ results = completion_resp.get('results')
+ user_completion_percentage = self._get_user_completion(chapter_id, results)
+
+ if user_completion_percentage:
+ completion_percentage = user_completion_percentage
+
+ template = 'chapter_completion_progress_bar.html' if chapter_id is not None else 'completion_progress_bar.html'
+ return render(request, template, {
+ 'completion_percentage': completion_percentage,
+ })
+
+ def _get_user_completion(self, chapter_id, results):
+ """
+ Return the user completion percentage, using the completion response.
+ In case the user completion cannot be returned as a result of missing user completion, we return None,
+ indicating its absence.
+ """
+ if not results:
+ return None
+
+ user_completion = next(filter(lambda r: r, results), None)
+
+ # No completion returned, hence we cannot get the percentage either
+ # Indicate no user completion by returning None
+ if not user_completion:
+ return None
+
+ if chapter_id:
+ chapters = user_completion['chapter']
+ chapter = next(filter(lambda c: c['block_key'].split('@')[-1] == chapter_id, chapters), None)
+
+ completion_kind = chapter if chapter_id else user_completion
+
+ if not completion_kind:
+ return None
+
+ return round(float(completion_kind['completion']['percent']) * 100)