Fakultas Ilmu Komputer UI

Commit 36a096b1 authored by Arief Pratama's avatar Arief Pratama
Browse files

Add Statistics by category using ChartJs

parent 2221a24c
Pipeline #60071 passed with stages
in 27 minutes and 50 seconds
......@@ -27,7 +27,7 @@
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<a class="nav-link" href="{% url 'stats' %}">
<span>Statisik Materi</span>
</a>
</li>
......
{% extends 'app/base_dashboard.html' %}
{% load static %}
{% block title %}
<title>Unggah Materi dari Excel | Digipus</title>
{% endblock %}
{% block stylesheets %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"
integrity="sha512-d9xgZrVZpmmQlfonhQUvTR7lMPtO7NkZMkA0ABN3PHCbKA5nqylQ/yWlFAyY6hYgdF1Qh6nYiuADWwKB4C2WSw=="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.css"
integrity="sha512-/zs32ZEJh+/EO2N1b0PEdoA10JkdC3zJ8L5FTiQu82LR9S/rOQNfQN7U59U9BC12swNeRAz3HSzIL2vpp4fv3w=="
crossorigin="anonymous" />
{% endblock %}
{% block content %}
<div class="container">
<h1 class="h3 mb-2 text-gray-800">Summary Materi per Kategori</h1>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<th>Kategori</th>
<th>Jumlah Materi</th>
</thead>
<tbody>
{% for s in stats %}
<tr>
<td>{{s.name}}</td>
<td>{{s.num}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="col-lg-6 mx-auto">
<canvas id="myChart" width="400" height="400"></canvas>
</div>
</div>
<script type="text/javascript">
function displayChart(data) {
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: data
});
}
document.addEventListener("DOMContentLoaded", function(){
fetch('/stats?data=json')
.then(function(response) {
return response.json()
})
.then(function(json) {
displayChart(json)
})
});
</script>
{% endblock %}
\ No newline at end of file
......@@ -3,6 +3,7 @@ import pandas as pd
from io import StringIO
import re
import time
import random
from django.test import override_settings
from bs4 import BeautifulSoup
......@@ -3443,3 +3444,53 @@ class MateriRecommendationTest(TestCase):
list = [int(id) for id in re.findall(r"Materi\s(\d+)[^\d]", response.content.decode())]
self.assertEqual(list, [1, 2])
class MateriStatsTest(TestCase):
def setUp(self):
self.credential = {
'email':"kontributor@gov.id",
'password':"P@ssw0rd",
}
self.path = '/stats/'
self.path_json = '/stats/?data=json'
self.header = 'Summary Materi per Kategori'
self.contributor = User.objects.create_contributor(**self.credential, name="kontributor")
self.client = Client()
categories = []
for i in range(10):
cat = Category(name=f'Cat{i}', description=f'Cat{i} description')
cat.save()
categories.append(cat)
for i in range(10):
for j in range(random.randint(1, 10)):
m = Materi(title=f'Title{i}-{j}')
m.save()
m.categories.add(categories[i])
m.save()
def test_stats_has_correct_template(self):
self.client.login(**self.credential)
response = self.client.get(self.path)
self.assertTemplateUsed(response, 'statistik.html')
def test_stats_as_authenticated(self):
self.client.login(**self.credential)
response = self.client.get(self.path)
self.assertContains(response, self.header)
def test_stats_as_anonymous(self):
response = self.client.get(self.path)
self.assertEqual(response.status_code, 302) #redirect
response = self.client.get(self.path_json)
self.assertEqual(response.status_code, 302) #redirect
def test_stats_api_correct_data(self):
self.client.login(**self.credential)
response = self.client.get(self.path_json)
jobj = json.loads(response.content)
self.assertEqual(len(jobj['labels']), 6)
......@@ -2,7 +2,7 @@ from django.contrib.auth import views as auth_views
from django.urls import path, re_path
from app import views
from app.views import (DashboardKontributorView, ProfilView,
from app.views import (DashboardKontributorView, ProfilView, StatisticsView,
SuksesLoginAdminView, SuksesLoginKontributorView, DownloadHistoryView,
SuntingProfilView, UploadMateriHTML, UploadMateriView, UploadMateriExcelView, PostsView,
ReqMateriView, KatalogPerKontributorView, MateriFavorite, PasswordChangeViews, password_success, SubmitVisitorView)
......@@ -41,4 +41,5 @@ urlpatterns = [
path("password_success/", views.password_success, name="password_success"),
path("given-rating/", views.see_given_rating, name="see_given_rating"),
path("submit-visitor/", SubmitVisitorView.as_view(), name="submit-visitor"),
path("stats/", StatisticsView.as_view(), name="stats"),
]
......@@ -12,7 +12,7 @@ from django.contrib.auth.views import PasswordChangeView
from django.core.exceptions import PermissionDenied, FieldError
from django.core.mail import send_mail
from django.core.paginator import Paginator
from django.db.models import Q, Avg
from django.db.models import Q, Avg, Count
from django.http import (Http404, HttpResponse, HttpResponseRedirect,
JsonResponse)
from django.shortcuts import get_object_or_404, redirect
......@@ -780,3 +780,60 @@ class SubmitVisitorView(TemplateView):
return JsonResponse({"success": False, "msg": "Missing parameter"})
SubmitVisitor(msg=title, user_id=user_id, email=email).save()
return JsonResponse({"success": True, "msg": "Buku tamu berhasil ditambahkan"})
class StatisticsView(TemplateView):
template_name = "statistik.html"
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated == False:
return HttpResponseRedirect("/login/")
return super(StatisticsView, self).dispatch(request, *args, **kwargs)
def get_stat_json(self):
query = Category.objects.annotate(num=Count('materi')).order_by('-num')
# Take maximum 10 Category
result = []
for e in query:
if len(result) >= 6:
break
else:
result.append(e)
chart_data = {
'labels': [e.name for e in result],
'datasets': [{
'label': 'Jumlah Materi per Kategori',
'data': [e.num for e in result],
'backgroundColor': [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
'borderColor': [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
'borderWidth': 1
}]
}
return chart_data
def get(self, request, *args, **kwargs):
if request.GET.get('data') == 'json':
return JsonResponse(self.get_stat_json())
else:
context = self.get_context_data(**kwargs)
query = Category.objects.annotate(num=Count('materi'))
context['stats'] = query
return self.render_to_response(context)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment