Fakultas Ilmu Komputer UI
Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
PMPL
Class Project
DIGIPUS
Commits
f96ddea6
Commit
f96ddea6
authored
Oct 03, 2020
by
Jonathan Christopher Jakub
Browse files
[
#75
] Group comments per post on User Comments page
parent
b8088dc9
Changes
6
Hide whitespace changes
Inline
Side-by-side
app/static/app/css/user_uploaded_posts.css
0 → 100644
View file @
f96ddea6
.posts-vertically-centered
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
font-size
:
1rem
;
}
.posts-space-between-container
{
display
:
flex
;
flex-direction
:
row
;
justify-content
:
space-between
;
}
#posts-profile-picture
{
border-radius
:
50%
;
}
#posts-user-profile
{
display
:
flex
;
flex-direction
:
row
;
}
#posts-user-name
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
margin-left
:
1rem
;
font-size
:
1.5rem
;
}
#posts-img
{
width
:
100px
;
height
:
auto
;
height
:
inherit
!important
;
margin-right
:
1rem
;
}
#posts-info
{
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
}
#posts-comment-info
{
display
:
flex
;
flex-direction
:
row
;
margin
:
0.5rem
6rem
0.5rem
6rem
;
padding
:
0.5rem
;
}
app/templates/app/includes/sidebar.html
View file @
f96ddea6
...
...
@@ -29,8 +29,8 @@
</a>
</li>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"{% url '
comments' user.id
%}"
>
<span>
Komentar
</span></a>
<a
class=
"nav-link"
href=
"{% url '
posts'
%}"
>
<span>
Materi Diunggah
</span></a>
</li>
</ul>
\ No newline at end of file
</ul>
app/templates/user_uploaded_posts.html
0 → 100644
View file @
f96ddea6
{% extends 'app/base_dashboard.html' %}
{% load static %}
{% block title %}
<title>
Materi Diunggah | Digipus
</title>
{% endblock %}
{% block stylesheets %}
<link
rel=
"stylesheet"
type=
"text/css"
href=
"{% static 'app/css/user_uploaded_posts.css' %}"
/>
{% endblock %}
{% block content %}
<div
class=
"posts-space-between-container bg-white rounded shadow bd-highlight"
style=
"padding: 1rem 1.5rem; margin-bottom: 1.5rem;"
>
<div
id=
"posts-user-profile"
>
<img
id=
"posts-profile-picture"
src=
"{{ user.profile_picture.url }}"
alt=
"profile-picture"
width=
"100px"
height=
"100px"
/>
<div
id=
"posts-user-name"
>
Materi oleh
<strong>
&
nbsp{{ user.name }}
</strong>
</div>
</div>
<div
class=
"posts-vertically-centered"
>
<span>
{{ posts|length }}
</span>
<span>
Materi
</span>
</div>
</div>
<div
style=
"padding: 1rem 0"
id=
"posts"
>
{% if posts %}
{% for _, post in posts.items %}
<div
id=
"post-{{ post.data.id }}"
>
<div
class=
"posts-space-between-container bg-white rounded shadow"
style=
"margin: 0.5rem 2rem; padding: 1rem;"
>
<div
id=
"posts-user-profile"
>
{% if post.data.cover %}
<img
id=
"posts-img"
src=
"{{ post.data.cover.url }}"
alt=
"profile-picture"
/>
{% else %}
</div
style="background-color:
grey;
width:
100px;
height:
100px;"
>
{% endif %}
<div
id=
"posts-info"
>
<span><a
class=
"ml-auto p-1 link"
style=
"text-align: left; font-size: 2rem;"
href=
"{% url 'detail-materi' post.data.id %}"
>
{{ post.data.title }}
</a></span>
<span
style=
"font-size: 0.75rem; padding-left: 0.3rem;"
>
{{ post.data.date_created }}
</span>
</div>
</div>
<div
class=
"posts-vertically-centered"
>
<span>
{{ post.comments|length }}
</span>
<span>
Komentar
</span>
</div>
</div>
{% for comment in post.comments %}
<div
id=
"post-{{ post.data.id }}-comment-{{ comment.id }}"
>
<div
id=
"posts-comment-info"
class=
"bg-white rounded shadow"
>
<img
id=
"posts-profile-picture"
src=
"{{ comment.user.profile_picture.url }}"
alt=
"profile-picture"
width=
"40px"
height=
"40px"
style=
"margin: 18px"
/>
<div
style=
"display: flex; align-items: center;"
>
<div
style=
"display: flex; flex-direction: column;"
>
<span
style=
"font-size: 0.9rem;"
><strong>
{{ comment.user.name }}
</strong>
- {{ comment.timestamp }}
</span>
{{ comment.comment }}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
{% else %}
<div
class=
"text-center h5"
>
Anda belum memiliki materi yang telah diunggah / disetujui
</div>
{% endif %}
</div>
{% endblock %}
app/tests.py
View file @
f96ddea6
...
...
@@ -2,7 +2,7 @@ import json
from
io
import
StringIO
from
django.contrib.auth
import
get_user_model
from
django.core.exceptions
import
ValidationError
from
django.core.exceptions
import
PermissionDenied
,
ValidationError
from
django.core.files.uploadedfile
import
SimpleUploadedFile
from
django.core.management
import
call_command
from
django.test
import
Client
,
RequestFactory
,
TestCase
...
...
@@ -17,7 +17,7 @@ from .models import Category, Comment, Materi, Like, Rating
from
.views
import
(
DaftarKatalog
,
DashboardKontributorView
,
DetailMateri
,
ProfilKontributorView
,
SuksesLoginAdminView
,
SuksesLoginKontributorView
,
SuntingProfilView
,
ProfilAdminView
,
Commen
tsView
,
SuntingProfilAdminView
,
RevisiMateriView
)
ProfilAdminView
,
Pos
tsView
,
SuntingProfilAdminView
,
RevisiMateriView
)
from
app.forms
import
SuntingProfilForm
...
...
@@ -160,69 +160,108 @@ class DetailMateriTest(TestCase):
self
.
assertEqual
(
Comment
.
objects
.
all
().
filter
(
comment
=
"This is new comment by Anonymous"
).
count
(),
0
)
class
ViewCommentsTest
(
TestCase
):
def
setUp
(
self
):
self
.
client
=
Client
()
self
.
contributor_credential
=
{
"email"
:
"kontributor@gov.id"
,
"password"
:
"passwordtest"
}
self
.
matt_damon_credential
=
{
"email"
:
"mattdamon@gov.id"
,
"password"
:
"passwordtest"
class
PostsViewTest
(
TestCase
):
@
classmethod
def
generate_posts_data
(
cls
,
user
):
POST_COUNT
=
3
COMMENTS_COUNT_PER_POST
=
[
1
,
0
,
3
]
assert
POST_COUNT
==
len
(
COMMENTS_COUNT_PER_POST
)
sample_file
=
SimpleUploadedFile
(
"Test.jpg"
,
b
"Test file"
)
sample_category
=
Category
.
objects
.
create
(
name
=
"Test Category"
)
post_comment_group_dict
=
{}
for
_
in
range
(
POST_COUNT
):
post
=
Materi
.
objects
.
create
(
uploader
=
user
,
cover
=
sample_file
,
content
=
sample_file
,
)
post
.
categories
.
add
(
sample_category
)
post_comment_group_dict
[
post
.
id
]
=
{
"data"
:
post
,
"comments"
:
[],
}
for
i
,
post_id
in
enumerate
(
post_comment_group_dict
):
post
=
post_comment_group_dict
[
post_id
][
"data"
]
for
_
in
range
(
COMMENTS_COUNT_PER_POST
[
i
]):
comment
=
Comment
.
objects
.
create
(
materi
=
post
)
post_comment_group_dict
[
post_id
][
"comments"
].
append
(
comment
)
# order by latest (-timestamp)
post_comment_group_dict
[
post_id
][
"comments"
].
reverse
()
return
post_comment_group_dict
@
classmethod
def
setUpTestData
(
cls
):
cls
.
url
=
'/posts/'
cls
.
user_credentials
=
{
"email"
:
"user@email.com"
,
"password"
:
"justpass"
}
self
.
contributor
=
get_user_model
().
objects
.
create_user
(
**
self
.
contributor_credential
,
name
=
"Kontributor"
,
is_contributor
=
True
)
self
.
mattDamon
=
get_user_model
().
objects
.
create_user
(
**
self
.
matt_damon_credential
,
name
=
"Matt Damon"
,
is_contributor
=
True
)
self
.
cover
=
SimpleUploadedFile
(
"Cherprang_Areekul40_nJM9dGt.jpg"
,
b
"Test file"
)
self
.
content
=
SimpleUploadedFile
(
"Bahan_PA_RKK.pdf"
,
b
"Test file"
)
Materi
(
title
=
"Materi 1"
,
author
=
"Agas"
,
uploader
=
self
.
contributor
,
publisher
=
"Kelas SC"
,
descriptions
=
"Deskripsi Materi 1"
,
status
=
"APPROVE"
,
cover
=
self
.
cover
,
content
=
self
.
content
).
save
()
Materi
(
title
=
"Materi 2"
,
author
=
"Matt"
,
uploader
=
self
.
mattDamon
,
publisher
=
"Kelas SC"
,
descriptions
=
"Deskripsi Materi 2"
,
status
=
"APPROVE"
,
cover
=
self
.
cover
,
content
=
self
.
content
).
save
()
self
.
materi1
=
Materi
.
objects
.
first
()
self
.
materi2
=
Materi
.
objects
.
get
(
uploader
=
self
.
mattDamon
)
self
.
commentByKontributor
=
Comment
.
objects
.
create
(
username
=
'saul'
,
comment
=
"this is contributor comment"
,
materi
=
self
.
materi1
,
user
=
self
.
contributor
)
self
.
commentByMatt
=
Comment
.
objects
.
create
(
username
=
'saul'
,
comment
=
"this is Matt Damon"
,
materi
=
self
.
materi2
,
user
=
self
.
mattDamon
)
self
.
url
=
'/kontributor/'
+
str
(
self
.
contributor
.
id
)
+
'/comments/'
cls
.
user
=
User
.
objects
.
create_user
(
**
cls
.
user_credentials
,
is_contributor
=
True
)
cls
.
data
=
cls
.
generate_posts_data
(
cls
.
user
)
def
test_comments_url_exist
(
self
):
self
.
client
.
login
(
**
self
.
contributor_credential
)
response
=
self
.
client
.
get
(
self
.
url
)
def
_request_as_user
(
self
):
self
.
client
.
login
(
**
self
.
user_credentials
)
return
self
.
client
.
get
(
self
.
url
)
def
test_url_resolves_to_posts_view
(
self
):
found
=
resolve
(
self
.
url
)
self
.
assertEqual
(
found
.
func
.
__name__
,
PostsView
.
as_view
().
__name__
)
def
test_returns_200_on_authenticated_access
(
self
):
response
=
self
.
_request_as_user
()
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertNotEqual
(
response
.
status_code
,
404
)
def
test_comments_using_comments_template
(
self
):
self
.
client
.
login
(
**
self
.
contributor_credential
)
def
test_returns_403_on_unauthenticated_access
(
self
):
response
=
self
.
client
.
get
(
self
.
url
)
self
.
assertTemplateUsed
(
response
,
'comments.html'
)
self
.
assertRaises
(
PermissionDenied
)
self
.
assertEqual
(
response
.
status_code
,
403
)
def
test_comments_using_comments_func
(
self
):
self
.
client
.
login
(
**
self
.
contributor_credential
)
found
=
resolve
(
self
.
url
)
self
.
assertEqual
(
found
.
func
.
__name__
,
CommentsView
.
as_view
().
__name__
)
def
test_returns_correct_template
(
self
):
response
=
self
.
_request_as_user
()
self
.
assertTemplateUsed
(
response
,
"user_uploaded_posts.html"
)
def
test_comments_page_render_comments
(
self
):
self
.
client
.
login
(
**
self
.
contributor_credential
)
response
=
self
.
client
.
get
(
self
.
url
)
self
.
assertContains
(
response
,
"this is contributor comment"
)
self
.
assertNotContains
(
response
,
'bukan comment'
)
def
test_success_returns_correct_comment_post_groupings_by_context
(
self
):
post_comment_group_dict
=
self
.
data
def
test_comments_page_only_render_specific_user_comments
(
self
):
self
.
client
.
login
(
**
self
.
contributor_credential
)
response
=
self
.
client
.
get
(
self
.
url
)
self
.
assertContains
(
response
,
"this is contributor comment"
)
self
.
assertNotContains
(
response
,
"this is Matt Damon"
)
response
=
self
.
_request_as_user
()
response_user
=
response
.
context_data
[
"user"
]
self
.
assertEqual
(
response_user
,
self
.
user
)
response_data
=
response
.
context_data
[
"posts"
]
actual_data
=
post_comment_group_dict
self
.
assertDictEqual
(
response_data
,
actual_data
)
def
test_html_contains_grouped_posts_and_comments
(
self
):
response
=
self
.
_request_as_user
()
posts
=
list
(
self
.
data
.
keys
())
comments
=
{
i
:
[
comment
.
id
for
comment
in
self
.
data
[
post_id
][
"comments"
]]
for
i
,
post_id
in
enumerate
(
posts
)
}
self
.
assertRegex
(
str
(
response
.
content
),
rf
'.*(<div id="post-
{
posts
[
2
]
}
">)'
+
\
rf
'.*(<div id="post-
{
posts
[
2
]
}
-comment-
{
comments
[
2
][
0
]
}
">)'
+
\
rf
'.*(<div id="post-
{
posts
[
2
]
}
-comment-
{
comments
[
2
][
1
]
}
">)'
+
\
rf
'.*(<div id="post-
{
posts
[
2
]
}
-comment-
{
comments
[
2
][
2
]
}
">)'
+
\
rf
'.*(<div id="post-
{
posts
[
1
]
}
">)'
+
\
rf
'.*(<div id="post-
{
posts
[
0
]
}
">)'
+
\
rf
'.*(<div id="post-
{
posts
[
0
]
}
-comment-
{
comments
[
0
][
0
]
}
">)'
)
def
test_comments_page_only_for_specific_contributor
(
self
):
self
.
client
.
login
(
**
self
.
matt_damon_credential
)
response
=
self
.
client
.
get
(
self
.
url
)
self
.
assertEqual
(
response
.
status_code
,
403
)
self
.
assertNotEqual
(
response
.
status_code
,
200
)
class
TemplateLoaderTest
(
TestCase
):
def
test_template_loader_url_exist
(
self
):
...
...
app/urls.py
View file @
f96ddea6
...
...
@@ -4,7 +4,7 @@ from app import views
from
app.views
import
(
DashboardKontributorView
,
ProfilKontributorView
,
SuksesLoginAdminView
,
SuksesLoginKontributorView
,
SuntingProfilView
,
UploadMateriHTML
,
UploadMateriView
,
ProfilAdminView
,
Commen
tsView
,
SuntingProfilAdminView
,
ReqMateriView
)
ProfilAdminView
,
Pos
tsView
,
SuntingProfilAdminView
,
ReqMateriView
)
urlpatterns
=
[
path
(
""
,
views
.
DaftarKatalog
.
as_view
(),
name
=
"daftar_katalog"
),
...
...
@@ -24,7 +24,7 @@ urlpatterns = [
path
(
"sukses-admin/"
,
SuksesLoginAdminView
.
as_view
(),
name
=
"sukses-admin"
),
re_path
(
r
"^.*\.html"
,
views
.
pages
,
name
=
"pages"
),
path
(
"profil-admin/"
,
ProfilAdminView
.
as_view
(),
name
=
"profil-admin"
),
path
(
'kontributor/<int:pk_user>/commen
ts/
'
,
Commen
tsView
.
as_view
(),
name
=
'
commen
ts'
),
path
(
"pos
ts/
"
,
Pos
tsView
.
as_view
(),
name
=
'
pos
ts'
),
path
(
"sunting-admin/"
,
SuntingProfilAdminView
.
as_view
(),
name
=
"sunting-admin"
),
path
(
"req-materi/"
,
ReqMateriView
.
as_view
(),
name
=
"req-materi"
),
path
(
"post-req-materi/"
,
views
.
post_req_materi
,
name
=
"post-req-materi"
),
...
...
app/views.py
View file @
f96ddea6
...
...
@@ -486,33 +486,35 @@ class SuksesLoginAdminView(TemplateView):
return
self
.
render_to_response
(
context
)
class
CommentsView
(
TemplateView
):
template_name
=
"comments.html"
class
PostsView
(
TemplateView
):
template_name
=
"user_uploaded_posts.html"
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
if
not
request
.
user
.
pk
==
kwargs
[
"pk_user"
]
:
if
not
request
.
user
.
is_authenticated
:
raise
PermissionDenied
(
request
)
return
super
(
CommentsView
,
self
).
dispatch
(
request
,
*
args
,
**
kwargs
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
(
CommentsView
,
self
).
get_context_data
(
**
kwargs
)
user
=
get_object_or_404
(
User
,
pk
=
kwargs
[
"pk_user"
])
users_materi
=
Materi
.
objects
.
filter
(
uploader
=
user
)
numb_of_comments
=
0
qset_comments
=
Comment
.
objects
.
none
()
for
materi
in
users_materi
:
materi_comments
=
Comment
.
objects
.
filter
(
materi
=
materi
).
count
()
numb_of_comments
+=
materi_comments
qset_comments
|=
Comment
.
objects
.
filter
(
materi
=
materi
)
context
[
'comments'
]
=
qset_comments
.
order_by
(
'-timestamp'
)
context
[
"numb_of_comments"
]
=
numb_of_comments
context
[
"numb_of_materi"
]
=
users_materi
.
count
()
return
context
return
super
(
PostsView
,
self
).
dispatch
(
request
,
*
args
,
**
kwargs
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
context
=
self
.
get_context_data
(
**
kwargs
)
context
=
super
().
get_context_data
(
**
kwargs
)
user
=
self
.
request
.
user
posts
=
Materi
.
objects
.
filter
(
uploader
=
user
).
order_by
(
"-date_created"
)
posts_data
=
{
post
.
id
:
{
"data"
:
post
,
"comments"
:
[]
}
for
post
in
posts
}
comments
=
Comment
.
objects
\
.
filter
(
materi__id__in
=
posts_data
.
keys
())
\
.
order_by
(
"-timestamp"
)
for
comment
in
comments
:
posts_data
[
comment
.
materi
.
id
][
"comments"
].
append
(
comment
)
context
[
"user"
]
=
user
context
[
"posts"
]
=
posts_data
return
self
.
render_to_response
(
context
=
context
)
class
RevisiMateriView
(
TemplateView
):
template_name
=
"revisi.html"
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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