Fakultas Ilmu Komputer UI

views.py 33 KB
Newer Older
1
2
import mimetypes
import os
3
from io import BytesIO
4

5
import django
6
from decouple import config
7
import pandas as pd
8
from django.conf import settings
9
from django.contrib import messages
10
11
12
from django.contrib.auth.views import PasswordChangeForm
from django.contrib.auth.views import PasswordChangeView
from django.core.exceptions import PermissionDenied, FieldError
13
from django.core.mail import send_mail
14
from django.core.paginator import Paginator
15
from django.db.models import Q, Avg, Count
16
17
from django.http import (Http404, HttpResponse, HttpResponseRedirect,
                         JsonResponse)
18
19
from django.shortcuts import get_object_or_404, redirect
from django.shortcuts import render
20
from django.template import loader
21
from django.urls import reverse
22
from django.urls import reverse_lazy
23
from django.views import defaults
24
from django.views.generic import TemplateView
25

26
from app.forms import SuntingProfilForm, UploadMateriForm, RatingContributorForm
27
28
29
from app.models import (
    Category,
    Comment,
30
    Review,
31
32
    Materi,
    ReqMaterial,
33
    Rating, RatingContributor,
Anthony Dewa Priyasembada's avatar
Anthony Dewa Priyasembada committed
34
35
    SubmitVisitor,
    ReadLater
36
)
37
from authentication.models import User
38
39
from .services import DafterKatalogService, DetailMateriService, LikeDislikeService, MateriFieldValidationHelperService, \
    DownloadViewMateriHelperService, UploadMateriService, EditProfileService, RevisiMateriService, \
Anthony Dewa Priyasembada's avatar
Anthony Dewa Priyasembada committed
40
    DownloadHistoryService, GoogleDriveUploadService, ReadLaterService
41

42
43
44
45
46
47
48
MISSING_PARAMETER_MESSAGE = "Missing parameter"
UNSUPPORTED_MESSAGE = "Unsuported method"
FILE_NOT_FOUND_MESSAGE = "File tidak dapat ditemukan."
UNGGAH_HTML = "unggah.html"
UNGGAH_URL = "/unggah/"
UNGGAH_EXCEL_URL = "/unggah_excel/"
LOGIN_URL = "/login/"
49

50
def permission_denied(request, exception, template_name="error_403.html"):
51
52
    return defaults.permission_denied(request, exception, template_name)

53

54
class DaftarKatalog(TemplateView):
igor lestin sianipar's avatar
igor lestin sianipar committed
55
    paginate_by = 2
56
57
58
59
60
61
62
    template_name = "app/katalog_materi.html"

    def get_context_data(self, **kwargs):
        return super().get_context_data(**kwargs)

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
63
        context["kategori_list"] = Category.objects.all()
64

65
        lst_materi = Materi.objects.filter(status="APPROVE").order_by("date_modified")
Mika dabelza abi's avatar
Mika dabelza abi committed
66
67
        url = ""

68
        lst_materi, url = DafterKatalogService.apply_options(lst_materi, request, url)
Saul Andre's avatar
Saul Andre committed
69

70

71
        context["materi_list"] = lst_materi
Mika dabelza abi's avatar
Mika dabelza abi committed
72
        paginator = Paginator(context["materi_list"], 15)
73
        page_number = request.GET.get("page")
Mika dabelza abi's avatar
Mika dabelza abi committed
74
75
76
77
        page_obj = paginator.get_page(page_number)
        context["materi_list"] = page_obj

        context["url"] = url
78
79
        return self.render_to_response(context=context)

80

81
82
class KatalogPerKontributorView(TemplateView):
    template_name = "app/katalog_kontri.html"
83

84
85
86
87
88
89
90
91
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        contributor = get_object_or_404(User, email=kwargs["email"])
        context["contributor"] = contributor
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
92
93
94
95
96

        materi_list = Materi.objects.filter(status="APPROVE", uploader=context["contributor"]).order_by(
            "date_modified"
        )

97
        paginator = Paginator(materi_list, 15)
98
        page_number = request.GET.get("page")
99
100
        materi_list_by_page = paginator.get_page(page_number)
        context["materi_list"] = materi_list_by_page
101
102
103
104
105
        contributor = context["contributor"]
        context["form_rating"] = RatingContributorForm(initial={
            "contributor": contributor,
            "user":request.user
        })
106
        context["avg_rating"] = User.objects.filter(email=kwargs["email"]) \
107
108
109
110
111
112
113
            .annotate(avg_rating=Avg("contributor__score"))[0]
        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

114
        return self.render_to_response(context=context)
115

116
    def post(self, request, *args, **kwargs):
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
        context = self.get_context_data(**kwargs)
        if not request.user.is_authenticated:
            raise PermissionDenied(request)

        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()
                
145
146
        return redirect("katalog-per-kontributor", email=kwargs["email"])

147
148
149
150
class DetailMateri(TemplateView):
    template_name = "app/detail_materi.html"

    def get_context_data(self, **kwargs):
151
152
153
154
        context = super(DetailMateri, self).get_context_data(**kwargs)
        if not self.request.session or not self.request.session.session_key:
            self.request.session.save()
        materi = get_object_or_404(Materi, pk=kwargs["pk"])
155
156
157
        DetailMateriService.init_context_data(context, materi, self.request.session)
        published_date = DetailMateriService.set_published_date(materi)
        DetailMateriService.init_citation_and_materi_rating(context, materi, published_date, self.request)
158
        DetailMateriService.init_materi_download_count(context, materi)
159
160
161
162

        if self.request.user.is_authenticated:
            materi_rating = Rating.objects.filter(materi=materi, user=self.request.user).first()
            if materi_rating is not None:
163
                context['materi_rating_score'] = materi_rating.score
164

Anthony Dewa Priyasembada's avatar
Anthony Dewa Priyasembada committed
165
166
167
168
169
170
            materi_read_later = ReadLater.objects.filter(materi=materi, user=self.request.user).first()
            if materi_read_later is not None:
                context['is_in_read_later_list'] = True
            else:
                context['is_in_read_later_list'] = False

171
        context['is_authenticated'] = self.request.user.is_authenticated
172

173
        return context
174

175

176
177
    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
178
        query_set_for_comment = Comment.objects.filter(materi=context["materi_data"])
179
        query_set_for_review = Review.objects.filter(materi=context["materi_data"])
180
        has_disliked, has_liked = DetailMateriService.find_comment_like_dislike(query_set_for_comment, self.request.session)
181
        context["comment_data"] = query_set_for_comment
182
        context["review_data"] = query_set_for_review
183
184
        context["has_liked_comment"] = has_liked
        context["has_disliked_comment"] = has_disliked
185
186
        return self.render_to_response(context=context)

187

188

189
    def post(self, request, *args, **kwargs):
190
191
192
        comment_text = request.POST.get("comment", None)
        review_text  = request.POST.get("review", None)
        if ((comment_text == None or comment_text == "" )and (review_text == None or review_text == "")):
193
194
            context = self.get_context_data(*args, **kwargs)
            context["error_message"] = "Anda belum menuliskan komentar"
195
            context["materi_data"] = get_object_or_404(Materi, pk=kwargs["pk"])
196
            query_set_for_comment = Comment.objects.filter(materi=context["materi_data"])
197
            context["comment_data"] = query_set_for_comment
198
199
            query_set_for_review = Review.objects.filter(materi=context["materi_data"])
            context["review_data"] = query_set_for_review
200
            return self.render_to_response(context=context)
201

202
        materi = get_object_or_404(Materi, pk=kwargs["pk"])
203
        user_obj = request.user if request.user.is_authenticated else None
204
        if user_obj:
205
            if (comment_text != None ):
206
                comment = Comment.objects.create(
207
                    comment=comment_text, username=DetailMateriService.get_user_name(request), materi=materi, user=user_obj
208
209
                )
                comment.save()
210
211
212
213
214
215
216
217
218
219
220
221
                materi_uploader = materi.uploader
                if materi_uploader.is_subscribing_to_material_comments and user_obj.email != materi_uploader.email:
                    email_content =  f'User dengan email {user_obj.email} ' + \
                        f'menambahkan komentar pada materi Anda dengan judul "{materi.title}".' + \
                        f'\nKomentar: "{comment.comment}".\n' + \
                        f'Silahkan akses halaman detail materi untuk berinteraksi lebih lanjut.'
                    send_mail(
                        subject = 'DIGIPUS: Komentar Baru pada Materi Anda',
                        message = email_content,
                        from_email = getattr(settings, 'EMAIL_HOST_USER'),
                        recipient_list = [materi_uploader.email,],
                        fail_silently = False,
222
                    ) 
223
            elif (review_text != None):
224
                review = Review.objects.create(
225
                    review=review_text, username=DetailMateriService.get_user_name(request), materi=materi, user=user_obj
226
227
                )
                review.save()
228
229
        return HttpResponseRedirect(request.path)

230

231
def toggle_like(request):
232
233
234
    if request.method == "POST":
        materi_id = request.POST.get("materi_id", None)
        session_id = request.POST.get("session_id", None)
235
        if materi_id is None or session_id is None:
236
            return JsonResponse({"success": False, "msg": MISSING_PARAMETER_MESSAGE})
237
        return JsonResponse(LikeDislikeService.apply_like_materi(materi_id, session_id))
238
    else:
239
        return JsonResponse({"success": False, "msg": UNSUPPORTED_MESSAGE})
240
241


242
def delete_comment(request, pk_materi, pk_comment):
243
244
    if not request.user.is_authenticated or not request.user.is_admin:
        raise PermissionDenied(request)
245
    comment = get_object_or_404(Comment, pk=pk_comment)
246
    url = "/materi/" + str(pk_materi) + "/"
247
248
249
    comment.delete()
    return HttpResponseRedirect(url)

250
def toggle_like_comment(request):
251
    comment_id = 0
252
253
254
255
    if request.method == "POST":
        comment_id = request.POST.get("comment_id", None)
        session_id = request.POST.get("session_id", None)
        if comment_id is None or session_id is None:
256
            return JsonResponse({"success": False, "msg": MISSING_PARAMETER_MESSAGE, "comment_id": comment_id})
257
        return JsonResponse(LikeDislikeService.apply_comment_like(comment_id, session_id))
258
    else:
259
        return JsonResponse({"success": False, "msg": UNSUPPORTED_MESSAGE, "comment_id": comment_id})
260

261

262
def toggle_dislike_comment(request):
263
    comment_id = 0
264
265
266
267
    if request.method == "POST":
        comment_id = request.POST.get("comment_id", None)
        session_id = request.POST.get("session_id", None)
        if comment_id is None or session_id is None:
268
            return JsonResponse({"success": False, "msg": MISSING_PARAMETER_MESSAGE, "comment_id": comment_id})
269
        return JsonResponse(LikeDislikeService.apply_comment_dislike(comment_id, session_id))
270
    else:
271
        return JsonResponse({"success": False, "msg": UNSUPPORTED_MESSAGE, "comment_id": comment_id})
272
273


274
def add_rating_materi(request):
275
    if request.method == "POST" and request.user.is_authenticated:
276

277
278
        materi_id = request.POST.get("materi_id", None)
        rating_score = request.POST.get("rating_score", None)
279
280


281
282
283
284
        is_valid_params, materi_id, \
        rating_score, response, \
        status_code = MateriFieldValidationHelperService.\
            validate_materi_rating_params(materi_id,rating_score)
285

286
287
        if not is_valid_params:
            return JsonResponse(response, status=status_code)
288

289
290
291
        is_valid_rating, materi, \
        response, status_code = MateriFieldValidationHelperService.\
            validate_materi_rating(materi_id, request.user)
292

293
294
        if not is_valid_rating:
            return JsonResponse(response, status=status_code)
295
296

        Rating(materi=materi, user=request.user, score=rating_score).save()
297
298
299
        return JsonResponse(
            {"success": True, "msg": "Rating successfully created", "rating_score": rating_score}, status=201
        )
300
301
302
    return JsonResponse({"success": False, "msg": "Forbidden"}, status=403)


303

304
305
306
307
308
def download_materi(request, pk):
    materi = get_object_or_404(Materi, pk=pk)
    path = materi.content.path
    file_path = os.path.join(settings.MEDIA_ROOT, path)
    if os.path.exists(file_path):
309
310
311
        try:
            mimetype = mimetypes.guess_type(file_path)
            with open(file_path, "rb") as fh:
312
313
314
                return DownloadViewMateriHelperService.build_materi_response(fh, file_path,
                                                                             materi, mimetype, request,
                                                                             HttpResponse(fh.read(), content_type=mimetype[0]))
315
316
        except Exception:
            raise Http404(FILE_NOT_FOUND_MESSAGE)
317
    else:
318
        raise Http404(FILE_NOT_FOUND_MESSAGE)
319

igor lestin sianipar's avatar
igor lestin sianipar committed
320

321
322
323
324
325
326
def view_materi(request, pk):
    materi = get_object_or_404(Materi, pk=pk)
    path = materi.content.path
    file_path = os.path.join(settings.MEDIA_ROOT, path)
    if os.path.exists(file_path):
        mimetype = mimetypes.guess_type(file_path)
327
328
329
        try:
            with open(file_path, "rb") as fh:
                response = HttpResponse(fh.read(), content_type=mimetype[0])
330
                DownloadViewMateriHelperService.build_view_materi_response(file_path, materi, response)
331
                return response
332
333
        except Exception:
            raise Http404(FILE_NOT_FOUND_MESSAGE)
334
    else:
335
        raise Http404(FILE_NOT_FOUND_MESSAGE)
igor lestin sianipar's avatar
igor lestin sianipar committed
336

igor lestin sianipar's avatar
igor lestin sianipar committed
337

Selvy Fitriani's avatar
Selvy Fitriani committed
338
339
def delete_materi(request, pk):
    materi = get_object_or_404(Materi, pk=pk)
340
341
342
    if request.user.is_superuser or request.user.is_admin:
        materi.soft_delete()
        return HttpResponseRedirect("/administration/")
Selvy Fitriani's avatar
Selvy Fitriani committed
343
344
345
    materi.delete()
    return HttpResponseRedirect("/dashboard/")

igor lestin sianipar's avatar
igor lestin sianipar committed
346
class UploadMateriView(TemplateView):
347
    template_name = UNGGAH_HTML
igor lestin sianipar's avatar
igor lestin sianipar committed
348
    context = {}
349
    redirect_path = "/unggah/"
igor lestin sianipar's avatar
igor lestin sianipar committed
350
351
352
353
354

    def get_context_data(self, **kwargs):
        context = super(UploadMateriView, self).get_context_data(**kwargs)
        return context

Saul Andre's avatar
Saul Andre committed
355
    def post(self, request, *args, **kwargs):
Steven Kusuman's avatar
Steven Kusuman committed
356
        if request.user.is_authenticated == False or not request.user.is_contributor:
igor lestin sianipar's avatar
igor lestin sianipar committed
357
            raise PermissionDenied(request)
358
        form = UploadMateriForm(request.POST, request.FILES)
igor lestin sianipar's avatar
igor lestin sianipar committed
359
360
361
        if form.is_valid():
            materi = form.save(commit=False)
            materi.uploader = request.user
362
            konten = form.cleaned_data["content"]
363
364
            yt_url_id = form.cleaned_data['yt_video_id']
            if not UploadMateriService.validate_file_extension(konten, request, yt_url_id):
365
                return HttpResponseRedirect(UNGGAH_URL)
366
            UploadMateriService.upload_materi(form, materi)
367
            messages.success(request, "Materi berhasil diunggah, periksa riwayat unggah anda")
368
            return HttpResponseRedirect(UNGGAH_URL)
Saul Andre's avatar
Saul Andre committed
369
        else:
igor lestin sianipar's avatar
igor lestin sianipar committed
370
            context = self.get_context_data(**kwargs)
371
            context["form"] = form
372
            messages.error(request, "Terjadi kesalahan pada pengisian data")
igor lestin sianipar's avatar
igor lestin sianipar committed
373
374
            return self.render_to_response(context)

375
376


igor lestin sianipar's avatar
igor lestin sianipar committed
377
    def get(self, request, *args, **kwargs):
Steven Kusuman's avatar
Steven Kusuman committed
378
        if request.user.is_authenticated == False or not request.user.is_contributor:
igor lestin sianipar's avatar
igor lestin sianipar committed
379
            raise PermissionDenied(request)
380

igor lestin sianipar's avatar
igor lestin sianipar committed
381
        context = self.get_context_data(**kwargs)
382
        context["form"] = UploadMateriForm
igor lestin sianipar's avatar
igor lestin sianipar committed
383
        return self.render_to_response(context)
384

385

386
class UploadMateriHTML(TemplateView):
387
    template_name = UNGGAH_HTML
388
    context = {}
igor lestin sianipar's avatar
igor lestin sianipar committed
389

390
    def get_template_names(self):
391
392
        if self.request.path == UNGGAH_URL:
            template_name = UNGGAH_HTML
393
394
395
        return template_name


396
397
398
399
400
class UploadMateriExcelView(TemplateView):
    template_name = "unggah_excel.html"
    context = {}

    def get_template_names(self):
401
        if self.request.path == UNGGAH_EXCEL_URL:
402
403
404
405
406
            template_name = "unggah_excel.html"
        return template_name

    def get(self, request, *args, **kwargs):

407
        if "template" in self.request.GET:
408

409
410
411
            data_frame = pd.DataFrame(
                {"Title": [], "Author": [], "Publisher": [], "Categories": [], "Description": [],}
            )
412
413

            with BytesIO() as b:
414
                writer = pd.ExcelWriter(b, engine="xlsxwriter")  # pylint: disable=abstract-class-instantiated
415
416
417
                data_frame.to_excel(writer, index=0)
                writer.save()
                response = HttpResponse(
418
419
                    b.getvalue(), content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                )
420
421
422
423
424
425
426
427
428
429

                response["Content-Disposition"] = "attachment; filename=template.xlsx"

                return response

        else:
            context = self.get_context_data(**kwargs)
            return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
430
431
        excel_file = request.FILES["excel"]
        excel = pd.read_excel(excel_file)
432

433
        row, lines = excel.shape
434
        categories = Category.objects.all()
435

436
        field_length = {
437
438
439
            "title": 50,
            "author": 30,
            "publisher": 30,
440
441
442
443
444
445
        }

        message = None

        # First pass, validate input
        for i in range(row):
446

447
            # Validate Categories
448
            message = UploadMateriService.validate_excel_categories(categories, excel, i, message)
449

450
            message = UploadMateriService.validate_excel_field_length(excel, field_length, i, message)
451
452
453

            if message != None:
                break
454

455
456
        if message != None:
            messages.error(request, message)
457
            return HttpResponseRedirect(UNGGAH_EXCEL_URL)
458
459
460

        # Second pass, save data
        with django.db.transaction.atomic():
461
            UploadMateriService.upload_materi_excel(categories, excel, request, row)
462

463
        messages.success(request, "Materi berhasil diunggah")
464

465
        return HttpResponseRedirect(UNGGAH_EXCEL_URL)
466
467


468
469


470
class DashboardKontributorView(TemplateView):
471
    template_name = "dashboard.html"
472
473
474
475
476
477
478

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated or not request.user.is_contributor:
            raise PermissionDenied(request)
        return super(DashboardKontributorView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
479
        context = super(DashboardKontributorView, self).get_context_data(**kwargs)
480
481
482
483
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
484
485
486
        current_user = self.request.user
        materi_list = current_user.materi_set.all()
        context["materi_list"] = materi_list
487
        return self.render_to_response(context)
488

489

490
class ProfilView(TemplateView):
491
492
493
    template_name = "profil.html"

    def dispatch(self, request, *args, **kwargs):
494
        if not request.user.is_authenticated:
495
            raise PermissionDenied(request)
496
        return super(ProfilView, self).dispatch(request, *args, **kwargs)
497
498
499

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
500
        current_user = request.user
501
502
503
        context["user"] = current_user
        return self.render_to_response(context)

504

505
506
507
508
class SuntingProfilView(TemplateView):
    template_name = "sunting.html"

    def dispatch(self, request, *args, **kwargs):
509
        if not request.user.is_authenticated:
510
511
512
513
            raise PermissionDenied(request)
        return super(SuntingProfilView, self).dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
Samuel Dimas Partogi's avatar
Samuel Dimas Partogi committed
514
        current_user = self.request.user
515
516
517
518
519
520
521
522
523
524
        context = self.get_context_data(**kwargs)
        context["user"] = current_user
        context["form"] = SuntingProfilForm(instance=current_user)
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
        if request.user.is_authenticated == False:
            raise PermissionDenied(request)

        current_user = self.request.user
525

526
        form = SuntingProfilForm(request.POST, request.FILES, instance=current_user)
527
528
        if form.is_valid():
            current_user.default_profile_picture = True
529
530
531

            # Removing exifdata from profile picture on upload
            if request.FILES:
532
                EditProfileService.update_profile_picture(current_user, request)
533
            else:
534
                form.save()
535
            return HttpResponseRedirect("/profil/")
536
537
        else:
            context = self.get_context_data(**kwargs)
538
539
            context["form"] = form
            return self.render_to_response(context)
540

541

542
543
544
545
546
class ReqMateriView(TemplateView):
    template_name = "req_materi.html"

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated == False:
547
            return HttpResponseRedirect(LOGIN_URL)
548
549
550
        return super(ReqMateriView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
551
        context = super(ReqMateriView, self).get_context_data(**kwargs)
552
553
554
555
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
556
        context['requested_material'] = ReqMaterial.objects.all()
557
558
559
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
560
        title = request.POST.get("title", None)
561
        if title is None:
562
            return JsonResponse({"success": False, "msg": MISSING_PARAMETER_MESSAGE})
563
564
565
        ReqMaterial(title=title).save()
        return JsonResponse({"success": True, "msg": "Permintaan materi berhasil dikirimkan"})

566

567
568
569
570
571
572
573
class SuksesLoginKontributorView(TemplateView):
    template_name = "sukses_kontri.html"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_contributor:
            raise PermissionDenied(request)
        return super(SuksesLoginKontributorView, self).dispatch(request, *args, **kwargs)
574

575
    def get_context_data(self, **kwargs):
576
        context = super(SuksesLoginKontributorView, self).get_context_data(**kwargs)
577
578
579
580
581
582
583
584
585
586
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)

        current_user = self.request.user
        context["user"] = current_user

        return self.render_to_response(context)

587

588
589
590
591
592
593
594
class SuksesLoginAdminView(TemplateView):
    template_name = "sukses_admin.html"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_admin:
            raise PermissionDenied(request)
        return super(SuksesLoginAdminView, self).dispatch(request, *args, **kwargs)
595

596
597
598
599
600
601
602
603
604
605
606
607
    def get_context_data(self, **kwargs):
        context = super(SuksesLoginAdminView, self).get_context_data(**kwargs)
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)

        current_user = self.request.user
        context["user"] = current_user

        return self.render_to_response(context)

igor lestin sianipar's avatar
igor lestin sianipar committed
608

609
610
611
class PostsView(TemplateView):

    template_name = "user_uploaded_posts.html"
612
613

    def dispatch(self, request, *args, **kwargs):
614
        if not request.user.is_authenticated:
615
            raise PermissionDenied(request)
616
        return super(PostsView, self).dispatch(request, *args, **kwargs)
617
618

    def get(self, request, *args, **kwargs):
619
620
621
622
        context = super().get_context_data(**kwargs)
        user = self.request.user

        posts = Materi.objects.filter(uploader=user).order_by("-date_created")
623
        posts_data = {post.id: {"data": post, "comments": []} for post in posts}
624

625
        comments = Comment.objects.filter(materi__id__in=posts_data.keys()).order_by("-timestamp")
626
627
628
629
630
631
632

        for comment in comments:
            posts_data[comment.materi.id]["comments"].append(comment)

        context["user"] = user
        context["posts"] = posts_data

633
        return self.render_to_response(context=context)
634

635

636
637
638
class RevisiMateriView(TemplateView):
    template_name = "revisi.html"

639
    def dispatch(self, request, *args, **kwargs):
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
        if not request.user.is_contributor:
            raise PermissionDenied(request)
        return super(RevisiMateriView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(RevisiMateriView, self).get_context_data(**kwargs)
        current_materi = get_object_or_404(Materi, pk=kwargs["pk"])
        context["materi"] = current_materi
        context["revisi_form"] = UploadMateriForm(instance=current_materi)
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

655
    def post(self, request, *args, **kwargs):
656
657
658
659
        if request.user.is_authenticated == False:
            raise PermissionDenied(request)

        current_materi = get_object_or_404(Materi, pk=kwargs["pk"])
660
        form = UploadMateriForm(request.POST, request.FILES, instance=current_materi)
661
        if form.is_valid():
662
            RevisiMateriService.revisi_materi(form, request)
663
664
665
666
667
668
            return HttpResponseRedirect("/dashboard/")
        else:
            context = self.get_context_data(**kwargs)
            context["form_revisi"] = form
            return self.render_to_response(context)

669

Samuel Dimas's avatar
Samuel Dimas committed
670
671
672
673
674
675
def pages(request):
    context = {}
    # All resource paths end in .html.
    # Pick out the html file name from the url. And load that template.
    try:

676
        load_template = request.path.split("/")[-1]
Samuel Dimas's avatar
Samuel Dimas committed
677
678
679
        template = loader.get_template(load_template)
        return HttpResponse(template.render(context, request))

680
    except Exception:
Samuel Dimas's avatar
Samuel Dimas committed
681

682
        template = loader.get_template("error-404.html")
Samuel Dimas's avatar
Samuel Dimas committed
683
        return HttpResponse(template.render(context, request))
684
685


686
687
688
689
class DownloadHistoryView(TemplateView):
    template_name = "download_history.html"

    def get_context_data(self, **kwargs):
690
        context = super(DownloadHistoryView, self).get_context_data(**kwargs)
691
692
693
694
695
696
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        if request.user.is_authenticated:
            current_user = self.request.user
697
            DownloadHistoryService.init_data_authenticated_user(context, current_user)
698
        else:
699
            DownloadHistoryService.init_data_guest_user(context, request)
700
        return self.render_to_response(context)
701

702

703
704
705
706
707
def save_to_gdrive(request, pk):
    materi = get_object_or_404(Materi, pk=pk)
    path = materi.content.path
    file_path = os.path.join(settings.MEDIA_ROOT, path)
    if os.path.exists(file_path):
708
        GoogleDriveUploadService.upload_to_gdrive(file_path, materi.title)
709
    else:
710
        raise Http404(FILE_NOT_FOUND_MESSAGE)
711

Yaumi's avatar
Yaumi committed
712
713
    return HttpResponseRedirect(reverse('detail-materi', kwargs={'pk': pk}))

714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
class MateriFavorite(TemplateView):

    template_name = "user_favorite_materi.html"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            raise PermissionDenied(request)
        return super(MateriFavorite, self).dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        context = super().get_context_data(**kwargs)
        user = self.request.user

        materi = Materi.objects.filter(like=True)
        likes_data = { mat.id: { "data": mat, "comments": [] } for mat in materi }

        comments = Comment.objects \
            .filter(materi__id__in=likes_data.keys()) \
            .order_by("-timestamp")

        for comment in comments:
            likes_data[comment.materi.id]["comments"].append(comment)

        context["user"] = user
        context["likes"] = likes_data

        return self.render_to_response(context=context)

Yaumi's avatar
Yaumi committed
742
class PasswordChangeViews(PasswordChangeView):
743

Yaumi's avatar
Yaumi committed
744
745
    from_class = PasswordChangeForm
    success_url = reverse_lazy('password_success')
Yaumi's avatar
Yaumi committed
746

Yaumi's avatar
Yaumi committed
747
def password_success(request):
748
    return render(request, 'password_success.html', {})
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772


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)
insan ramadhan's avatar
insan ramadhan committed
773
774
775
776
777
778

class SubmitVisitorView(TemplateView):
    template_name = "submit_visitor.html"

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated == False:
779
            return HttpResponseRedirect(LOGIN_URL)
insan ramadhan's avatar
insan ramadhan committed
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
        return super(SubmitVisitorView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(SubmitVisitorView, self).get_context_data(**kwargs)
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
        title = request.POST.get("title", None)
        email = request.POST.get("email", None)
        user_id = request.POST.get("user_id", None)
        if title is None:
795
            return JsonResponse({"success": False, "msg": MISSING_PARAMETER_MESSAGE})
insan ramadhan's avatar
insan ramadhan committed
796
797
        SubmitVisitor(msg=title, user_id=user_id, email=email).save()
        return JsonResponse({"success": True, "msg": "Buku tamu berhasil ditambahkan"})
798

Anthony Dewa Priyasembada's avatar
Anthony Dewa Priyasembada committed
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
class ReadLaterView(TemplateView):
    template_name = 'baca-nanti.html'

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            raise PermissionDenied(request)
        return super(ReadLaterView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(ReadLaterView, self).get_context_data(**kwargs)
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        user = self.request.user
        context["read_later_list"] = ReadLater.objects.filter(user=user).order_by('-timestamp')
        return self.render_to_response(context)

def toggle_readlater(request):
    if request.method == "POST":
        materi_id = request.POST.get("materi_id", None)
        if materi_id is None:
821
            return JsonResponse({"success": False, "msg": MISSING_PARAMETER_MESSAGE})
Anthony Dewa Priyasembada's avatar
Anthony Dewa Priyasembada committed
822
823
824
        
        return JsonResponse(ReadLaterService.toggle_read_later(materi_id, request.user))
    else:
825
        return JsonResponse({"success": False, "msg": UNSUPPORTED_MESSAGE})
Anthony Dewa Priyasembada's avatar
Anthony Dewa Priyasembada committed
826

827
828
829
830
831
class StatisticsView(TemplateView):
    template_name = "statistik.html"

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated == False:
832
            return HttpResponseRedirect(LOGIN_URL)
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
        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)