Fakultas Ilmu Komputer UI

Commit 8608bb88 authored by Kevin Raikhan Zain's avatar Kevin Raikhan Zain
Browse files

[#44] Material: List of Rated Materials (User View)

parent 5a6450a0
.text-sort {
margin-right: 1em;
margin-left: 1em;
}
#table-given-rating {
margin-top: 1em;
}
#form-sort-by {
margin-bottom: 0;
}
\ No newline at end of file
......@@ -22,4 +22,9 @@
<a class="nav-link" href="/change-password/">
<span>Change Password</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/given-rating/">
<span>Rating Diberikan</span></a>
</li>
</ul>
\ No newline at end of file
{% extends 'app/base_profile.html' %}
{% load static %}
{% block title %}
<title>Sunting Profil | Digipus</title>
{% endblock %}
{% block stylesheets %}
<link rel="stylesheet" type="text/css" href="{% static 'app/css/given-rating.css' %}">
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
<script>
const order = '{{ order_by }}';
const order_by_key = '{{ order_by_key }}';
$(function () {
if (order === 'asc') {
$('#sort-ascending-option').attr('selected', true);
} else {
$('#sort-descending-option').attr('selected', true);
}
if (order_by_key === 'materi__title') {
$('#sort-by-title-option').attr('selected', true);
} else if (order_by_key === 'score') {
$('#sort-by-rating-option').attr('selected', true);
} else {
$('#sort-by-date-option').attr('selected', true);
}
});
function onSortChange(evt) {
window.location.href = `/given-rating/?order_by_key=${order_by_key}&order=${evt.target.value}`;
}
function onSortKeyChange(evt) {
window.location.href = `/given-rating/?order_by_key=${evt.target.value}&order=${order}`;
}
</script>
{% endblock %}
{% block content %}
<div class="container">
<div class="col-20">
<h1 class="mt-2">Rating Yang Anda Berikan Ke Materi</h1>
<hr class="mt-0 mb-4">
{% if rating_list %}
<div class="justify-content-end d-flex align-items-center">
<span class="text-sort">Urutkan Berdasarkan : </span>
<div class="form-group" id="form-sort-by">
<select class="form-control" onchange="onSortKeyChange(event)">
<option value="timestamp" id="sort-by-date-option">Tanggal</option>
<option value="materi__title" id="sort-by-title-option">Judul</option>
<option value="score" id="sort-by-rating-option">Rating</option>
</select>
</div>
<span class="text-sort">Dari : </span>
<div class="form-group" id="form-sort-by">
<select class="form-control" onchange="onSortChange(event)">
<option value="dsc" id="sort-descending-option">Besar ke Kecil
</option>
<option value="asc" id="sort-ascending-option">Kecil ke Besar
</option>
</select>
</div>
</div>
<table class="table table-bordered table-striped" id="table-given-rating"
aria-describedby="Your Given Rating List">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Judul Materi</th>
<th scope="col">Tanggal</th>
<th scope="col">Rating</th>
</tr>
</thead>
<tbody>
{% for i in rating_list %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td><a href="/materi/1/">{{ i.materi.title }}</a></td>
<td>{{ i.timestamp }}</td>
<td>{{ i.score }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<h3>Anda belum pernah memberikan rating ke materi</h3>
{% endif %}
</div>
</div>
{% endblock %}
......@@ -2613,3 +2613,168 @@ class ChangePasswordTest(TestCase):
self.client.logout()
class SeeRatedMateriByUser(TestCase):
def setUp(self):
self.client = Client()
self.contributor_credential = {
"email": "kontributor@gov.id",
"password": id_generator()
}
self.admin_credential = {
"email": "admin@gov.id",
"password": id_generator()
}
self.kontributor = User.objects.create_contributor(**self.contributor_credential)
self.admin = User.objects.create_admin(**self.admin_credential)
self.given_rating_url = "/given-rating/"
self.cover = SimpleUploadedFile(
"cover.jpg",
b"Test file"
)
self.content = SimpleUploadedFile(
"content.txt",
b"Test file"
)
Materi(title="Materi 2", author="Agas", uploader=self.kontributor,
publisher="Kelas SC", descriptions="Deskripsi Materi 1",
status="PENDING", cover=self.cover, content=self.content).save()
Materi(title="Materi 3", author="Agas", uploader=self.kontributor,
publisher="Kelas SC", descriptions="Deskripsi Materi 1",
status="PENDING", cover=self.cover, content=self.content).save()
Materi(title="Materi 1", author="Agas", uploader=self.kontributor,
publisher="Kelas SC", descriptions="Deskripsi Materi 1",
status="PENDING", cover=self.cover, content=self.content).save()
self.materi1 = Materi.objects.all()[0]
self.materi2 = Materi.objects.all()[1]
self.materi3 = Materi.objects.all()[2]
time.sleep(0.5)
self.rating_test_1 = Rating(materi=self.materi1, user=self.kontributor, score=5)
time.sleep(0.5)
self.rating_test_2 = Rating(materi=self.materi2, user=self.kontributor, score=4)
time.sleep(0.5)
self.rating_test_3 = Rating(materi=self.materi3, user=self.kontributor, score=3)
time.sleep(0.5)
self.rating_test_4 = Rating(materi=self.materi3, user=self.admin, score=3)
self.rating_test_1.save()
self.rating_test_2.save()
self.rating_test_3.save()
self.rating_test_4.save()
def test_authorize_template_used(self):
self.client.login(**self.contributor_credential)
response = self.client.get(self.given_rating_url)
self.assertTemplateUsed(response, "given-rating.html")
def test_unauthorized_user_shouldnt_be_able_to_access_see_rating_page(self):
response = self.client.get(self.given_rating_url)
self.assertEqual(response.status_code, 403)
self.assertTemplateUsed(response, "error_403.html")
def test_authorized_should_be_able_to_access_given_rating_page(self):
self.client.login(**self.contributor_credential)
response = self.client.get(self.given_rating_url)
self.assertEqual(response.status_code, 200)
self.client.login(**self.admin_credential)
response = self.client.get(self.given_rating_url)
self.assertEqual(response.status_code, 200)
def test_given_rating_page_should_show_correct_rating(self):
self.client.login(**self.contributor_credential)
response = self.client.get(self.given_rating_url)
self.assertIn(self.rating_test_1, response.context['rating_list'])
self.assertIn(self.rating_test_2, response.context['rating_list'])
self.assertIn(self.rating_test_3, response.context['rating_list'])
def test_given_rating_page_should_not_show_others_rating(self):
self.client.login(**self.contributor_credential)
response = self.client.get(self.given_rating_url)
self.assertNotIn(self.rating_test_4, response.context['rating_list'])
def test_given_rating_page_no_rating_should_display_message(self):
user_credential = {"email": "user@mail.com", "password": id_generator()}
User.objects.create_contributor(**user_credential)
self.client.login(**user_credential)
response = self.client.get(self.given_rating_url)
self.assertEqual(len(response.context['rating_list']), 0)
self.assertIn("Anda belum pernah memberikan rating ke materi", response.content.decode("utf-8"))
self.assertNotIn(self.materi1.title, response.content.decode("utf-8"))
def test_given_rating_page_order_should_give_default_parameter(self):
# No parameters order_by_key = timestamp and order_by : ascending
self.client.login(**self.contributor_credential)
response = self.client.get(self.given_rating_url)
self.assertEqual(response.context['order_by'], 'dsc')
self.assertEqual(response.context['order_by_key'], 'timestamp')
# No order_by_key parameter, should default to timestamp
response = self.client.get(self.given_rating_url + '?order=asc')
self.assertEqual(response.context['order_by'], 'asc')
self.assertEqual(response.context['order_by_key'], 'timestamp')
# No order_by parameter, should default to asc
response = self.client.get(self.given_rating_url + '?order_by_key=score')
self.assertEqual(response.context['order_by'], 'dsc')
self.assertEqual(response.context['order_by_key'], 'score')
# INVALID PARAMETERS
# Starts with negative
response = self.client.get(self.given_rating_url + '?order_by_key=-score')
self.assertEqual(response.context['order_by'], 'dsc')
self.assertEqual(response.context['order_by_key'], 'score')
# Invalid params
response = self.client.get(self.given_rating_url + '?order_by_key=halohalohalo&order=haihaihaihai')
self.assertEqual(response.context['order_by'], 'dsc')
self.assertEqual(response.context['order_by_key'], 'timestamp')
def test_given_rating_page_order_ascending_should_be_correct(self):
self.client.login(**self.contributor_credential)
response = self.client.get(self.given_rating_url + '?order_by_key=score&order=asc')
# From Low to High
# order key score
self.assertEqual(response.context['order_by'], 'asc')
self.assertEqual(response.context['order_by_key'], 'score')
self.assertEqual(list(response.context['rating_list']),
[self.rating_test_3, self.rating_test_2, self.rating_test_1])
# order key timestamp
response = self.client.get(self.given_rating_url + '?order_by_key=timestamp&order=asc')
self.assertEqual(response.context['order_by'], 'asc')
self.assertEqual(response.context['order_by_key'], 'timestamp')
self.assertEqual(list(response.context['rating_list']),
[self.rating_test_1, self.rating_test_2, self.rating_test_3])
# order key materi title
response = self.client.get(self.given_rating_url + '?order_by_key=materi__title&order=asc')
self.assertEqual(response.context['order_by'], 'asc')
self.assertEqual(response.context['order_by_key'], 'materi__title')
self.assertEqual(list(response.context['rating_list']),
[self.rating_test_3, self.rating_test_1, self.rating_test_2])
def test_given_rating_page_order_descending_should_be_correct(self):
self.client.login(**self.contributor_credential)
# From High to Low
# order key score
response = self.client.get(self.given_rating_url + '?order_by_key=score&order=dsc')
self.assertEqual(response.context['order_by'], 'dsc')
self.assertEqual(response.context['order_by_key'], 'score')
self.assertEqual(list(response.context['rating_list']),
[self.rating_test_1, self.rating_test_2, self.rating_test_3])
# order key timestamp
response = self.client.get(self.given_rating_url + '?order_by_key=timestamp&order=dsc')
self.assertEqual(response.context['order_by'], 'dsc')
self.assertEqual(response.context['order_by_key'], 'timestamp')
self.assertEqual(list(response.context['rating_list']),
[self.rating_test_3, self.rating_test_2, self.rating_test_1])
# order key materi title
response = self.client.get(self.given_rating_url + '?order_by_key=materi__title&order=dsc')
self.assertEqual(response.context['order_by'], 'dsc')
self.assertEqual(response.context['order_by_key'], 'materi__title')
self.assertEqual(list(response.context['rating_list']),
[self.rating_test_2, self.rating_test_1, self.rating_test_3])
......@@ -39,4 +39,5 @@ urlpatterns = [
path("favorite/", MateriFavorite.as_view(), name="favorite"),
path("change-password/", PasswordChangeViews.as_view(template_name='change-password.html')),
path("password_success/", views.password_success, name="password_success"),
path("given-rating/", views.see_given_rating, name="see_given_rating"),
]
......@@ -6,14 +6,18 @@ import django
import pandas as pd
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.contrib.auth.views import PasswordChangeForm
from django.contrib.auth.views import PasswordChangeView
from django.core.exceptions import PermissionDenied, FieldError
from django.core.paginator import Paginator
from django.db.models import Q, Avg
from django.http import (Http404, HttpResponse, HttpResponseRedirect,
JsonResponse)
from django.shortcuts import get_object_or_404, redirect
from django.shortcuts import render
from django.template import loader
from django.urls import reverse
from django.urls import reverse_lazy
from django.views import defaults
from django.views.generic import TemplateView
......@@ -29,10 +33,6 @@ from authentication.models import User
from .services import DafterKatalogService, DetailMateriService, LikeDislikeService, MateriFieldValidationHelperService, \
DownloadViewMateriHelperService, UploadMateriService, EditProfileService, RevisiMateriService, \
DownloadHistoryService, GoogleDriveUploadService
from django.contrib.auth.views import PasswordChangeForm
from django.urls import reverse_lazy
from django.contrib.auth.views import PasswordChangeView
from django.shortcuts import render
def permission_denied(request, exception, template_name="error_403.html"):
......@@ -116,7 +116,7 @@ class DetailMateri(TemplateView):
materi_rating = Rating.objects.filter(materi=materi, user=self.request.user).first()
if materi_rating is not None:
context['materi_rating_score'] = materi_rating.score
context['is_authenticated'] = self.request.user.is_authenticated
return context
......@@ -663,9 +663,33 @@ class MateriFavorite(TemplateView):
return self.render_to_response(context=context)
class PasswordChangeViews(PasswordChangeView):
from_class = PasswordChangeForm
success_url = reverse_lazy('password_success')
def password_success(request):
return render(request, 'password_success.html', {})
def see_given_rating(request):
if request.user.is_authenticated:
order_by_key = request.GET.get('order_by_key', 'timestamp')
if request.GET.get('order', '').lower() == 'asc':
order_by = 'asc'
query_order = ''
else:
order_by = 'dsc'
query_order = '-'
try:
if order_by_key[0] == '-':
order_by_key = order_by_key[1:]
rating_list = Rating.objects.filter(user=request.user).order_by(query_order + order_by_key)
except FieldError:
order_by_key = 'timestamp'
rating_list = Rating.objects.filter(user=request.user).order_by(query_order + order_by_key)
return render(request, 'given-rating.html',
context={'rating_list': rating_list, 'order_by_key': order_by_key, 'order_by': order_by})
return permission_denied(request, exception=None)
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