Fakultas Ilmu Komputer UI
Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
PMPL
Class Project
DIGIPUS
Commits
8608bb88
Commit
8608bb88
authored
Oct 27, 2020
by
Kevin Raikhan Zain
Browse files
[
#44
] Material: List of Rated Materials (User View)
parent
5a6450a0
Changes
6
Hide whitespace changes
Inline
Side-by-side
app/static/app/css/given-rating.css
0 → 100644
View file @
8608bb88
.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
app/templates/app/includes/sidebar_profile.html
View file @
8608bb88
...
...
@@ -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
app/templates/given-rating.html
0 → 100644
View file @
8608bb88
{% 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 %}
app/tests.py
View file @
8608bb88
...
...
@@ -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
])
app/urls.py
View file @
8608bb88
...
...
@@ -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"
),
]
app/views.py
View file @
8608bb88
...
...
@@ -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
)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment