Fakultas Ilmu Komputer UI

Commit ff4ce3df authored by MUHAMMAD EZRA RIZKIATAMA PUTRA's avatar MUHAMMAD EZRA RIZKIATAMA PUTRA
Browse files

Merge branch '1606896041-72' into 'master'

[#72] Profile: Rating for Contributor (Delete Rating)

See merge request !83
parents b8f2b16e f9afd12b
Pipeline #60039 passed with stages
in 27 minutes and 11 seconds
...@@ -59,7 +59,7 @@ class SuntingProfilForm(forms.ModelForm): ...@@ -59,7 +59,7 @@ class SuntingProfilForm(forms.ModelForm):
class RatingContributorForm(forms.ModelForm): class RatingContributorForm(forms.ModelForm):
class Meta: class Meta:
model = RatingContributor model = RatingContributor
fields = ['score', 'user'] fields = ['score', 'user', 'contributor']
SCORE_CHOICE = ( SCORE_CHOICE = (
('', 'Select score'), ('', 'Select score'),
('1', '1'), # First one is the value of select option and second is the displayed value in option ('1', '1'), # First one is the value of select option and second is the displayed value in option
...@@ -69,6 +69,7 @@ class RatingContributorForm(forms.ModelForm): ...@@ -69,6 +69,7 @@ class RatingContributorForm(forms.ModelForm):
('5', '5'), ('5', '5'),
) )
widgets = { widgets = {
'score': forms.Select(choices=SCORE_CHOICE, attrs={'class': 'form-control'},), 'score': forms.Select(choices=SCORE_CHOICE, attrs={'class': 'form-control', 'id':'form-rating'},),
'user': forms.HiddenInput() 'user': forms.HiddenInput(),
'contributor': forms.HiddenInput()
} }
# Generated by Django 3.1 on 2020-10-30 09:48
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('app', '0026_submitvisitor'),
]
operations = [
migrations.AddField(
model_name='ratingcontributor',
name='contributor',
field=models.ForeignKey(default='', on_delete=django.db.models.deletion.CASCADE, related_name='contributor', to='authentication.user'),
preserve_default=False,
),
migrations.AlterField(
model_name='ratingcontributor',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user', to=settings.AUTH_USER_MODEL),
),
migrations.AlterUniqueTogether(
name='ratingcontributor',
unique_together={('contributor', 'user')},
),
]
...@@ -253,13 +253,17 @@ class Rating(models.Model): ...@@ -253,13 +253,17 @@ class Rating(models.Model):
class RatingContributor(models.Model): class RatingContributor(models.Model):
timestamp = models.DateTimeField(auto_now=True) timestamp = models.DateTimeField(auto_now=True)
score = models.PositiveIntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)]) score = models.PositiveIntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)])
user = models.ForeignKey(User, on_delete=models.CASCADE) contributor = models.ForeignKey(User, on_delete=models.CASCADE, related_name='contributor')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user')
def save(self, force_insert=False, force_update=False, using=None, update_fields=None): def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
if 1 <= self.score <= 5: if 1 <= self.score <= 5:
super().save(force_insert, force_update, using, update_fields) super().save(force_insert, force_update, using, update_fields)
else: else:
raise ValidationError("Rating score must be integer between 1-5") raise ValidationError("Rating score must be integer between 1-5")
class Meta:
unique_together = ["contributor", "user"]
class LaporanMateri(models.Model): class LaporanMateri(models.Model):
......
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load humanize %} {% load humanize %}
{% block title %}Digipus - {% endblock %} {% block title %}Digipus - {{ contributor.name }}'s' Profile{% endblock %}
{% block header %} {% block header %}
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!DOCTYPE html> <link href="../../static/app/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<html lang="en"> <link href="../../static/app/css/heroic-features.css" rel="stylesheet">
<head> <link rel="stylesheet" type="text/css" href="{% static 'app/css/katalog_materi.css' %}">
<title>Digipus Home</title> <link rel="stylesheet" type="text/css" href="{% static 'app/css/katalog_kontri.css' %}">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="../../static/app/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" type="text/css" href="{% static 'css/main.css' %}">
<link href="../../static/app/css/heroic-features.css" rel="stylesheet"> <link rel="stylesheet" type="text/css" href="{% static 'css/util.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/styles.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'app/css/katalog_materi.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'fonts/font-awesome-4.7.0/css/font-awesome.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'app/css/katalog_kontri.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'vendor/animsition/css/animsition.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'vendor/daterangepicker/daterangepicker.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'vendor/css-hamburgers/hamburgers.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'vendor/select2/select2.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'vendor/animate/animate.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/main.css' %}"> <link rel="icon" type="image/png" href="{% static 'images/icons/logo.ico' %}" />
<link rel="stylesheet" type="text/css" href="{% static 'css/util.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/styles.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'fonts/font-awesome-4.7.0/css/font-awesome.min.css' %}"> {% endblock header %}
<link rel="stylesheet" type="text/css" href="{% static 'vendor/animsition/css/animsition.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'vendor/daterangepicker/daterangepicker.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'vendor/css-hamburgers/hamburgers.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'vendor/select2/select2.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'vendor/animate/animate.css' %}">
<link rel="icon" type="image/png" href="{% static 'images/icons/logo.ico' %}" /> {% block content %}
{% endblock header %}
{% block content %}
</head>
<body style="background-color: #f8f8f8;"> <body style="background-color: #f8f8f8;">
<div class="container main"> <div class="container main">
...@@ -87,10 +79,28 @@ ...@@ -87,10 +79,28 @@
</table> </table>
</div> </div>
</div> </div>
<h4 id="rating">Rating: {% if avg_rating.avg_rating %}{{ avg_rating.avg_rating|floatformat:"2"|intcomma }}{% else %}0{% endif %}</h4> <div class="row mx-5 mt-3">
<h6>oleh: {{ count_rating }} orang</h6> <h4 id="rating">Rating: {% if avg_rating.avg_rating %}{{ avg_rating.avg_rating|floatformat:"2"|intcomma }}{% else %}0{% endif %}
<div class="row"><form method="post">{{ form_rating }} {% csrf_token %} </h4>
<button type="submit" class="form-control" style="margin-top: 1rem">Submit</button></form> </div> </div>
<div class="row mx-5 mt-2">
<h6>oleh: {{ count_rating }} orang</h6>
</div>
<div class="row mx-5 mt-3">
{% if not user.is_authenticated %}
<h4><a href="{% url 'login' %}">Kamu harus login untuk memberi rating</a></h4>
{% else %}
<form method="post" class="form-inline">{{ form_rating }} {% csrf_token %}
{% if has_rated %}
<button class="form-control mx-3" id="updateButton">Update</button>
<button class="btn btn-danger" id="deleteButton">Delete Rating</button>
{% else %}
<button type="submit" class="form-control mx-3">Submit</button>
{% endif %}
</form>
{% endif %}
</div>
</div> </div>
</header> </header>
...@@ -134,7 +144,73 @@ ...@@ -134,7 +144,73 @@
</div> </div>
</div> </div>
</body> </body>
{% endblock %}
</html> {% block extra_scripts %}
<script type="text/javascript">
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function reload () {
window.location = ''
};
$('#deleteButton').click(function () {
console.log("anjing")
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$.ajax({
type: 'POST',
url: "{% url 'katalog-per-kontributor' contributor.email%}",
data: {
'delete': true
},
success: reload,
dataType: 'html'
});
});
$('#updateButton').click(function () {
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$.ajax({
type: 'POST',
url: "{% url 'katalog-per-kontributor' contributor.email%}",
data: {
'update': true,
'score': $('#form-rating').val()
},
success: reload,
dataType: 'html'
});
});
</script>
{% endblock %} {% endblock %}
\ No newline at end of file
This diff is collapsed.
...@@ -90,19 +90,51 @@ class KatalogPerKontributorView(TemplateView): ...@@ -90,19 +90,51 @@ class KatalogPerKontributorView(TemplateView):
page_number = request.GET.get("page") page_number = request.GET.get("page")
materi_list_by_page = paginator.get_page(page_number) materi_list_by_page = paginator.get_page(page_number)
context["materi_list"] = materi_list_by_page context["materi_list"] = materi_list_by_page
contributor = get_object_or_404(User, email=kwargs["email"]) contributor = context["contributor"]
context["form_rating"] = RatingContributorForm(initial={"user": contributor}) context["form_rating"] = RatingContributorForm(initial={
"contributor": contributor,
"user":request.user
})
context["avg_rating"] = User.objects.filter(email=kwargs["email"]) \ context["avg_rating"] = User.objects.filter(email=kwargs["email"]) \
.annotate(avg_rating=Avg("ratingcontributor__score"))[0] .annotate(avg_rating=Avg("contributor__score"))[0]
context["count_rating"] = RatingContributor.objects.filter(user=contributor).count() context["count_rating"] = RatingContributor.objects.filter(contributor=contributor).count()
if request.user.is_authenticated:
has_rated = RatingContributor.objects.filter(user=request.user, contributor=contributor).exists()
context["has_rated"] = has_rated
return self.render_to_response(context=context) return self.render_to_response(context=context)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
data = RatingContributorForm(request.POST) context = self.get_context_data(**kwargs)
if data.is_valid(): if not request.user.is_authenticated:
data.save() raise PermissionDenied(request)
return redirect("katalog-per-kontributor", email=kwargs["email"])
is_delete = request.POST.get('delete', None)
is_update = request.POST.get('update', None)
if is_delete:
rating_contributor = get_object_or_404(
RatingContributor,
user=request.user,
contributor=context["contributor"]
)
rating_contributor.delete()
elif is_update:
score = request.POST.get('score', None)
rating = RatingContributor.objects.filter(
user=request.user,
contributor=context["contributor"]
).first()
if rating and score:
rating.score = int(score)
rating.save()
else:
data = RatingContributorForm(request.POST)
if data.is_valid():
data.save()
return redirect("katalog-per-kontributor", email=kwargs["email"])
class DetailMateri(TemplateView): class DetailMateri(TemplateView):
template_name = "app/detail_materi.html" template_name = "app/detail_materi.html"
......
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