Fakultas Ilmu Komputer UI

Commit 2ab1dcf0 authored by Azhar Rais's avatar Azhar Rais
Browse files

Merge branch '1706074865-24' into 'master'

[#24] Discussion Forum

Closes #24

See merge request !22
parents 4a7c10fe f2e6d6fa
Pipeline #58024 passed with stages
in 34 minutes and 6 seconds
......@@ -209,3 +209,6 @@ flowchart/
# Pycharm IDE
.idea
# MacOS
.DS_Store
......@@ -58,15 +58,17 @@
<form class="searchBar" action=''>
<div class="col-6 form-group">
<input type="text" name='search' class="form-control" placeholder="Tulis di sini"
value='{{request.GET.search}}'>
value='{{ request.GET.search }}'>
</div>
<button type="submit" class="btn btn-cari">Cari</button>
</form>
<p class="pageTitle">Tidak menemukan materi yang kamu cari ? ajukan permintaan materi kami <a
href="/req-materi">disini</a></p>
<p class="pageTitle">Ingin diskusi lebih mendalam? Silahkan kunjungi <a
href="{% url 'forum_home' %}">forum kami</a></p>
</div>
</div>
</div>
</div>
</header>
<a href="/download-history/" class="btn-history">Riwayat Unduh</a><br><br>
......
......@@ -51,16 +51,17 @@
<a class="btn btn-primary main-content" href="/sunting/">Sunting Profil</a>
<a class="btn btn-primary main-content" href="/profil/">Profil</a>
<a class="btn btn-primary main-content" href="/dashboard/">Dasbor</a>
<a class="btn btn-primary main-content" href="{% url 'forum_home' %}">Forum</a>
</span>
</div>
</div>
</div>
<!-- /.container-fluid -->
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- End of Main Content -->
<!-- Footer -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
......
......@@ -151,6 +151,12 @@ class LoginPageContributorTest(TestCase):
self.assertEqual(302, response.status_code)
self.assertEqual(response.url, expected_redirect_url)
def test_login_has_next_query_string(self):
next_querystring = "?next=/forum/discussion/create"
response = self.client.post(self.url + next_querystring, self.login_credential)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/forum/discussion/create")
def test_kontributor_visit_login_after_auth(self):
# 302 meaning successful login and redirected
expected_redirect_url = "/sukses-kontributor/"
......
from django.contrib.auth import authenticate, login
from django.http import HttpResponseRedirect
from django.http import HttpResponseRedirect, QueryDict
from django.views.generic import TemplateView
......@@ -42,10 +42,13 @@ class Login(TemplateView):
if user is not None:
login(request, user)
redirect_to = "/"
querystring = QueryDict(request.META['QUERY_STRING'])
if request.user.is_admin:
redirect_to = "/sukses-admin/"
elif request.user.is_contributor:
redirect_to = "/sukses-kontributor/"
if 'next' in querystring:
redirect_to = querystring['next']
return HttpResponseRedirect(redirect_to)
else:
context = self.get_context_data(*args, **kwargs)
......
......@@ -48,6 +48,7 @@ INSTALLED_APPS = [
'crispy_forms',
"news.apps.NewsConfig",
"traffic_statistics",
"forum",
]
MIDDLEWARE = [
......
......@@ -26,4 +26,5 @@ urlpatterns = [
path("administration/", include("administration.urls")),
path("", include("news.urls"), name="news"),
path("statistics/", include("traffic_statistics.urls")),
path("forum/", include("forum.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class ForumConfig(AppConfig):
name = 'forum'
from django.forms import ModelForm, TextInput, Textarea, ModelMultipleChoiceField, SelectMultiple
from app.models import Materi
from forum.models import Discussion, DiscussionComment
class MateriChoiceField(ModelMultipleChoiceField):
widget = SelectMultiple(attrs={'class': 'selectpicker form-control', 'data-live-search': "true"})
def label_from_instance(self, obj):
return obj.title
class DiscussionForm(ModelForm):
class Meta:
model = Discussion
fields = ['title', 'description']
widgets = {
'title': TextInput(attrs={'class': 'form-control'}),
'description': Textarea(attrs={'class': 'form-control'}),
}
materi = MateriChoiceField(queryset=Materi.objects.filter(status="APPROVE"), to_field_name='pk', required=False)
class DiscussionCommentForm(ModelForm):
class Meta:
model = DiscussionComment
fields = ['description']
widgets = {
'description': Textarea(attrs={'class': 'form-control', 'rows': 3})
}
materi = MateriChoiceField(queryset=Materi.objects.filter(status="APPROVE"), to_field_name='pk', required=False)
# Generated by Django 3.1 on 2020-10-06 14:39
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Discussion',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.TextField()),
('description', models.TextField(default='')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='DiscussionComment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('description', models.TextField(default='')),
('discussion', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.discussion')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
# Generated by Django 3.1 on 2020-10-07 12:03
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('forum', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='discussion',
name='created_at',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='discussion',
name='updated_at',
field=models.DateTimeField(auto_now=True),
),
]
# Generated by Django 3.1 on 2020-10-08 13:56
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('forum', '0002_auto_20201007_1903'),
]
operations = [
migrations.AddField(
model_name='discussioncomment',
name='created_at',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='discussioncomment',
name='updated_at',
field=models.DateTimeField(auto_now=True),
),
]
# Generated by Django 3.1 on 2020-10-08 18:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0015_reqmaterial'),
('forum', '0003_auto_20201008_2056'),
]
operations = [
migrations.AddField(
model_name='discussion',
name='materi',
field=models.ManyToManyField(blank=True, null=True, to='app.Materi'),
),
]
# Generated by Django 3.1 on 2020-10-08 18:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0015_reqmaterial'),
('forum', '0004_discussion_materi'),
]
operations = [
migrations.AlterField(
model_name='discussion',
name='materi',
field=models.ManyToManyField(blank=True, to='app.Materi'),
),
]
# Generated by Django 3.1 on 2020-10-08 23:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0015_reqmaterial'),
('forum', '0005_auto_20201009_0138'),
]
operations = [
migrations.AddField(
model_name='discussioncomment',
name='materi',
field=models.ManyToManyField(blank=True, to='app.Materi'),
),
migrations.AlterField(
model_name='discussion',
name='description',
field=models.TextField(blank=True, default=''),
),
]
from django.db import models
from app.models import Materi
from authentication.models import User
class Discussion(models.Model):
title = models.TextField(blank=False)
description = models.TextField(default='', blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=False)
materi = models.ManyToManyField(Materi, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class DiscussionComment(models.Model):
description = models.TextField(default='')
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=False)
discussion = models.ForeignKey(Discussion, on_delete=models.CASCADE, blank=False)
materi = models.ManyToManyField(Materi, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
/*!
* Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select)
*
* Copyright 2012-2020 SnapAppointments, LLC
* Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
*/@-webkit-keyframes bs-notify-fadeOut{0%{opacity:.9}100%{opacity:0}}@-o-keyframes bs-notify-fadeOut{0%{opacity:.9}100%{opacity:0}}@keyframes bs-notify-fadeOut{0%{opacity:.9}100%{opacity:0}}.bootstrap-select>select.bs-select-hidden,select.bs-select-hidden,select.selectpicker{display:none!important}.bootstrap-select{width:220px\0;vertical-align:middle}.bootstrap-select>.dropdown-toggle{position:relative;width:100%;text-align:right;white-space:nowrap;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.bootstrap-select>.dropdown-toggle:after{margin-top:-1px}.bootstrap-select>.dropdown-toggle.bs-placeholder,.bootstrap-select>.dropdown-toggle.bs-placeholder:active,.bootstrap-select>.dropdown-toggle.bs-placeholder:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder:hover{color:#999}.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success:hover{color:rgba(255,255,255,.5)}.bootstrap-select>select{position:absolute!important;bottom:0;left:50%;display:block!important;width:.5px!important;height:100%!important;padding:0!important;opacity:0!important;border:none;z-index:0!important}.bootstrap-select>select.mobile-device{top:0;left:0;display:block!important;width:100%!important;z-index:2!important}.bootstrap-select.is-invalid .dropdown-toggle,.error .bootstrap-select .dropdown-toggle,.has-error .bootstrap-select .dropdown-toggle,.was-validated .bootstrap-select select:invalid+.dropdown-toggle{border-color:#b94a48}.bootstrap-select.is-valid .dropdown-toggle,.was-validated .bootstrap-select select:valid+.dropdown-toggle{border-color:#28a745}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus,.bootstrap-select>select.mobile-device:focus+.dropdown-toggle{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none;height:auto}:not(.input-group)>.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{float:none;z-index:auto}.form-inline .bootstrap-select,.form-inline .bootstrap-select.form-control:not([class*=col-]){width:auto}.bootstrap-select:not(.input-group-btn),.bootstrap-select[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.dropdown-menu-right,.bootstrap-select[class*=col-].dropdown-menu-right,.row .bootstrap-select[class*=col-].dropdown-menu-right{float:right}.form-group .bootstrap-select,.form-horizontal .bootstrap-select,.form-inline .bootstrap-select{margin-bottom:0}.form-group-lg .bootstrap-select.form-control,.form-group-sm .bootstrap-select.form-control{padding:0}.form-group-lg .bootstrap-select.form-control .dropdown-toggle,.form-group-sm .bootstrap-select.form-control .dropdown-toggle{height:100%;font-size:inherit;line-height:inherit;border-radius:inherit}.bootstrap-select.form-control-lg .dropdown-toggle,.bootstrap-select.form-control-sm .dropdown-toggle{font-size:inherit;line-height:inherit;border-radius:inherit}.bootstrap-select.form-control-sm .dropdown-toggle{padding:.25rem .5rem}.bootstrap-select.form-control-lg .dropdown-toggle{padding:.5rem 1rem}.form-inline .bootstrap-select .form-control{width:100%}.bootstrap-select.disabled,.bootstrap-select>.disabled{cursor:not-allowed}.bootstrap-select.disabled:focus,.bootstrap-select>.disabled:focus{outline:0!important}.bootstrap-select.bs-container{position:absolute;top:0;left:0;height:0!important;padding:0!important}.bootstrap-select.bs-container .dropdown-menu{z-index:1060}.bootstrap-select .dropdown-toggle .filter-option{position:static;top:0;left:0;float:left;height:100%;width:100%;text-align:left;overflow:hidden;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.bs3.bootstrap-select .dropdown-toggle .filter-option{padding-right:inherit}.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option{position:absolute;padding-top:inherit;padding-bottom:inherit;padding-left:inherit;float:none}.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner{padding-right:inherit}.bootstrap-select .dropdown-toggle .filter-option-inner-inner{overflow:hidden}.bootstrap-select .dropdown-toggle .filter-expand{width:0!important;float:left;opacity:0!important;overflow:hidden}.bootstrap-select .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.input-group .bootstrap-select.form-control .dropdown-toggle{border-radius:inherit}.bootstrap-select[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select .dropdown-menu{min-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select .dropdown-menu>.inner:focus{outline:0!important}.bootstrap-select .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select .dropdown-menu li{position:relative}.bootstrap-select .dropdown-menu li.active small{color:rgba(255,255,255,.5)!important}.bootstrap-select .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select .dropdown-menu li a{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bootstrap-select .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select .dropdown-menu li a span.check-mark{display:none}.bootstrap-select .dropdown-menu li a span.text{display:inline-block}.bootstrap-select .dropdown-menu li small{padding-left:.5em}.bootstrap-select .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select .dropdown-menu .notify.fadeOut{-webkit-animation:.3s linear 750ms forwards bs-notify-fadeOut;-o-animation:.3s linear 750ms forwards bs-notify-fadeOut;animation:.3s linear 750ms forwards bs-notify-fadeOut}.bootstrap-select .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.fit-width .dropdown-toggle .filter-option{position:static;display:inline;padding:0}.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner,.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner{display:inline}.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before{content:'\00a0'}.bootstrap-select.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark{position:absolute;display:inline-block;right:15px;top:5px}.bootstrap-select.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select .bs-ok-default:after{content:'';display:block;width:.5em;height:1em;border-style:solid;border-width:0 .26em .26em 0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle,.bootstrap-select.show-menu-arrow.show>.dropdown-toggle{z-index:1061}.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before{bottom:auto;top:-4px;border-top:7px solid rgba(204,204,204,.2);border-bottom:0}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after{bottom:auto;top:-4px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle .filter-option:after,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle .filter-option:before,.bootstrap-select.show-menu-arrow.show>.dropdown-toggle .filter-option:after,.bootstrap-select.show-menu-arrow.show>.dropdown-toggle .filter-option:before{display:block}.bs-actionsbox,.bs-donebutton,.bs-searchbox{padding:4px 8px}.bs-actionsbox{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-donebutton{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-donebutton .btn-group button{width:100%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox .form-control{margin-bottom:0;width:100%;float:none}
\ No newline at end of file
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