Fakultas Ilmu Komputer UI

Commit 1ad4f8c6 authored by Yusuf T Ardho's avatar Yusuf T Ardho
Browse files

Merge branch 'master' of...

Merge branch 'master' of https://gitlab.cs.ui.ac.id/pmpl/class-project/marjinal-digipus into 1706074985-103
parents 8c29431e 651e62c7
Pipeline #60144 passed with stages
in 26 minutes and 53 seconds
......@@ -100,8 +100,11 @@ Dev Docker Image:
- .docker-image
- .development
allow_failure: true
when: manual
Prod Docker Image:
extends:
- .docker-image
- .production
\ No newline at end of file
- .production
when: manual
allow_failure: true
\ No newline at end of file
......@@ -18,7 +18,7 @@ BASE_PERIODE = [
]
def genereatePeriodeChoices():
def generate_periode_choices():
periode = BASE_PERIODE
now = timezone.now()
# Month
......
......@@ -3,7 +3,7 @@ from crispy_forms.layout import Layout, Submit, Row, Column, Reset, ButtonHolder
from crispy_forms.bootstrap import InlineCheckboxes
from django import forms
from administration.choices import genereatePeriodeChoices
from administration.choices import generate_periode_choices
from administration.models import VerificationSetting
from app.models import Category
from authentication.models import User
......@@ -88,7 +88,7 @@ class RegistrasiAdminForm(forms.ModelForm):
class PeriodForm(forms.Form):
period = forms.ChoiceField(
choices=genereatePeriodeChoices(), label="Periode", required=False)
choices=generate_periode_choices(), label="Periode", required=False)
start_date = forms.DateField(
widget=DateInput, label="Waktu mulai", required=False)
end_date = forms.DateField(
......@@ -102,14 +102,16 @@ class PeriodForm(forms.Form):
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control'
period_css_class = 'form-group col-md-4 mb-0'
self.helper = FormHelper()
self.helper.attrs["name"] = "filter-form"
self.helper.form_method = 'get'
self.helper.layout = Layout(
Row(
Column('period', css_class='form-group col-md-4 mb-0'),
Column('start_date', css_class='form-group col-md-4 mb-0'),
Column('end_date', css_class='form-group col-md-4 mb-0'),
Column('period', css_class=period_css_class),
Column('start_date', css_class=period_css_class),
Column('end_date', css_class=period_css_class),
css_class='form-row'
),
InlineCheckboxes('categories'),
......@@ -130,10 +132,9 @@ class PeriodForm(forms.Form):
if start_date is None and end_date is not None:
self.add_error("start_date",
"masukan waktu mulai")
if start_date is not None and end_date is not None:
if start_date > end_date:
self.add_error("end_date",
"waktu selesai sebelum waktu mulai")
if start_date is not None and end_date is not None and start_date > end_date:
self.add_error("end_date",
"waktu selesai sebelum waktu mulai")
class EditAdminStatusForm(forms.ModelForm):
......
......@@ -97,20 +97,6 @@
<!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Statistik</h6>
<!-- <div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<em class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></em>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Dropdown Header:</div>
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div> -->
</div>
<!-- Card Body -->
<div class="card-body" style="overflow:auto!important; display:inline-block!important; height: 750px;">
......@@ -128,7 +114,7 @@
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTableRiwayat" width="100%" cellspacing="0"
<table class="table table-bordered" id="dataTableRiwayat"
aria-describedby="titleTabelRiwayat">
<thead>
<tr>
......
{% extends 'administration/base_administrasi2.html' %}
{% load static %}
{% extends 'detail_kontri_admin_base.html' %}
{% block title %}
<title>Kelola Admin | Digipus</title>
{% endblock %}
{% block content %}
<div class="profile-content white-text">
<div>
{% if not user.default_profile_picture %}
<img class="img-profile rounded-circle" src="https://i.ibb.co/9wgPzyZ/default-image.png" alt="Photo" class="img-thumbnail"></img>
{% else %}
<img class="img-profile rounded-circle" src="{{ user.profile_picture.url }}" alt="Photo" class="img-thumbnail"></img>
{% endif %}
<div class="profile-margin"></div>
<h2>{{ user.name }}</h2>
<h4>{{ user.email }}</h4>
<h4>{{ user.biography }}</h4>
<div class="profile-margin"></div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
instansi
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
{{user.instansi}}
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
LinkedIn
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://linkedin.com">{{ user.linkedin }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Facebook
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://facebook.com">{{ user.facebook }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Twitter
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://twitter.com">{{ user.twitter }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Instagram
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://instagram.com">{{ user.instagram }}</a>
</div>
</div>
<a class="btn btn-primary btn-admin" href="/administration/kelola-admin/">Kembali ke Kelola Admin</a>
</div>
</div>
{% endblock%}
\ No newline at end of file
{% block return_link %}
<a class="btn btn-primary btn-admin" href="/administration/kelola-admin/">Kembali ke Kelola Admin</a>
{% endblock %}
{% extends 'administration/base_administrasi2.html' %}
{% load static %}
{% extends 'detail_kontri_admin_base.html' %}
{% block title %}
<title>Kelola Kontributor | Digipus</title>
{% endblock %}
{% block content %}
<div class="profile-content white-text">
<div>
{% if not user.default_profile_picture %}
<img class="img-profile rounded-circle" src="https://i.ibb.co/9wgPzyZ/default-image.png" alt="Photo" class="img-thumbnail"></img>
{% else %}
<img class="img-profile rounded-circle" src="{{ user.profile_picture.url }}" alt="Photo" class="img-thumbnail"></img>
{% endif %}
<div class="profile-margin"></div>
<h2>{{ user.name }}</h2>
<h4>{{ user.email }}</h4>
<h4>{{ user.biography }}</h4>
<div class="profile-margin"></div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
instansi
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
{{user.instansi}}
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
LinkedIn
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://linkedin.com">{{ user.linkedin }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Facebook
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://facebook.com">{{ user.facebook }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Twitter
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://twitter.com">{{ user.twitter }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Instagram
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://instagram.com">{{ user.instagram }}</a>
</div>
</div>
<a class="btn btn-primary btn-admin" href="/administration/kelola-kontributor/">Kembali ke Kelola Kontributor</a>
</div>
</div>
{% endblock %}
\ No newline at end of file
{% block return_link %}
<a class="btn btn-primary btn-admin" href="/administration/kelola-kontributor/">Kembali ke Kelola Kontributor</a>
{% endblock %}
{% extends 'administration/base_administrasi2.html' %}
{% block content %}
<div class="profile-content white-text">
<div>
{% if not user.default_profile_picture %}
<img class="img-profile rounded-circle" src="https://i.ibb.co/9wgPzyZ/default-image.png" alt="Photo" class="img-thumbnail"></img>
{% else %}
<img class="img-profile rounded-circle" src="{{ user.profile_picture.url }}" alt="Photo" class="img-thumbnail"></img>
{% endif %}
<div class="profile-margin"></div>
<h2>{{ user.name }}</h2>
<h4>{{ user.email }}</h4>
<h4>{{ user.biography }}</h4>
<div class="profile-margin"></div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
instansi
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
{{user.instansi}}
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
LinkedIn
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://linkedin.com">{{ user.linkedin }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Facebook
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://facebook.com">{{ user.facebook }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Twitter
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://twitter.com">{{ user.twitter }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Instagram
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://instagram.com">{{ user.instagram }}</a>
</div>
</div>
{% block return_link %}
{% endblock %}
</div>
</div>
{% endblock %}
\ No newline at end of file
......@@ -52,25 +52,31 @@ Pratinjau Materi
{% if riwayat %}
<div class="info-wrapper">
<div class="info" id="1">
<dt class="col col-4">
<p class="info-name"><strong>Verifikatur</strong></p>
</dt>
<dl>
<dt class="col col-4">
<p class="info-name"><strong>Verifikatur</strong></p>
</dt>
</dl>
<dd>
<p class="info-content">{{verification_report.user.name}}</p>
</dd>
</div>
<div class="info" id="1">
<dt class="col col-4">
<p class="info-name"><strong>Waktu Verifikasi</strong></p>
</dt>
<dl>
<dt class="col col-4">
<p class="info-name"><strong>Waktu Verifikasi</strong></p>
</dt>
</dl>
<dd>
<p class="info-content">{{verification_report.timestamp}}</p>
</dd>
</div>
<div class="info" id="1">
<dt class="col col-4">
<p class="info-name"><strong>Status Materi</strong></p>
</dt>
<dl>
<dt class="col col-4">
<p class="info-name"><strong>Status Materi</strong></p>
</dt>
</dl>
<dd>
<p class="info-content">{{verification_report.status}}</p>
</dd>
......
......@@ -17,7 +17,7 @@
</div>
<div class="card-body">
<div class="table-responsive">
<table aria-describedby="table-description" class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<table aria-describedby="table-description" class="table table-bordered" id="dataTable">
<thead>
<tr>
<th scope="col">Nama</th>
......
......@@ -21,7 +21,8 @@
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<table class="table table-bordered" id="dataTable">
<caption>Materi yang Dilaporkan</caption>
<thead>
<tr>
<th scope="col">Judul</th>
......
......@@ -186,7 +186,7 @@
</div>
<div class="card-body">
<div class="table-responsive">
<table aria-describedby="table-description" class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<table aria-describedby="table-description" class="table table-bordered" id="dataTable">
<thead>
<tr>
<th scope="col">Judul Verifikasi</th>
......@@ -235,29 +235,6 @@
<em class="fas fa-angle-up"></em>
</a>
<!-- <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
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 src="https://code.jquery.com/jquery-3.5.0.min.js"
integrity="sha256-xNzN2a4ltkB44Mc/Jz3pT4iU1cmeR0FkXs4pru/JxaQ=" crossorigin="anonymous"></script>
<script src="{% static 'js/sb-admin-2.min.js' %}"></script>
<script src="{% static 'vendor/datatables/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'vendor/datatables/dataTables.bootstrap4.min.js' %}"></script>
<script src="{% static 'js/demo/datatables-demo.js' %}"></script> -->
</body>
</html>
\ No newline at end of file
......@@ -61,7 +61,7 @@
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTableRiwayat" width="100%" cellspacing="0" aria-describedby="titleTabelRiwayat">
<table class="table table-bordered" id="dataTableRiwayat" aria-describedby="titleTabelRiwayat">
<thead>
<tr>
<th scope="col">Judul Materi</th>
......
......@@ -10,7 +10,9 @@ from app.models import Category, Materi, LaporanMateri
from authentication.models import User
from bs4 import BeautifulSoup
from datetime import datetime
from datetime import datetime, timedelta
from .forms import PeriodForm
EDIT_ENDPOINT = "/edit"
ERROR_403_MESSAGE = 'Kamu harus login untuk mengakses halaman ini'
......@@ -1659,3 +1661,50 @@ class EditKontributorStatusTests(TestCase):
self.assertEqual(response.status_code, 403)
class PeriodFormTests(TestCase):
def test_validation_error_when_start_date_is_none(self):
data = {
'start_date': None,
'end_date': datetime.now(),
}
form = PeriodForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(
form["start_date"].errors,
['masukan waktu mulai']
)
def test_validation_error_when_end_date_is_none(self):
data = {
'start_date': datetime.now(),
'end_date': None,
}
form = PeriodForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(
form["end_date"].errors,
['masukan waktu selesai']
)
def test_validation_error_when_start_date_greater_than_end_date(self):
current_time = datetime.now()
data = {
'start_date': current_time + timedelta(days = 1),
'end_date': current_time,
}
form = PeriodForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(
form["end_date"].errors,
['waktu selesai sebelum waktu mulai']
)
def test_form_valid_when_data_valid(self):
current_time = datetime.now()
data = {
'start_date': current_time - timedelta(days = 1),
'end_date': current_time,
}
form = PeriodForm(data)
self.assertTrue(form.is_valid())
......@@ -19,6 +19,8 @@ from django.core import management
ADMINISTRATION_MANAGEMENT = "/administration/kelola-admin/"
ADMINISTRATION_REPORT = "/administration/laporan-materi/"
ADMINISTRATION_VERIFICATION_SETTING = "/administration/setting/verification/"
ADMINISTRATION_CATEGORY_SETTING = "/administration/setting/category/"
class VerificationView(TemplateView):
......@@ -115,7 +117,7 @@ class VerificationSettingView(TemplateView):
form = VerificationSettingForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect("/administration/setting/verification/")
return HttpResponseRedirect(ADMINISTRATION_VERIFICATION_SETTING)
else:
context = self.get_context_data(**kwargs)
context["form"] = form
......@@ -146,7 +148,7 @@ class CategorySettingView(TemplateView):
form = CategoryForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect("/administration/setting/category/")
return HttpResponseRedirect(ADMINISTRATION_CATEGORY_SETTING)
else:
context = self.get_context_data(**kwargs)
context["form"] = form
......@@ -351,7 +353,7 @@ class EditVerificationView(TemplateView):
request.POST, instance=verification_object)
if form.is_valid():
form.save()
return HttpResponseRedirect("/administration/setting/verification/")
return HttpResponseRedirect(ADMINISTRATION_VERIFICATION_SETTING)
else:
context = self.get_context_data(**kwargs)
context["form"] = form
......@@ -383,7 +385,7 @@ class EditCategoryView(TemplateView):
request.POST, instance=category_object)
if form.is_valid():
form.save()
return HttpResponseRedirect("/administration/setting/category/")
return HttpResponseRedirect(ADMINISTRATION_CATEGORY_SETTING)
else:
context = self.get_context_data(**kwargs)
context["form"] = form
......@@ -483,15 +485,15 @@ def delete_contributor(request, *args, **kwargs):
def delete_verification(request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_admin:
raise PermissionDenied(request)
queryObject = get_object_or_404(VerificationSetting,
query_object = get_object_or_404(VerificationSetting,
pk=kwargs["pk_verification"])
queryObject.archived = True
queryObject.description = "Telah dihapus pada " + \
query_object.archived = True
query_object.description = "Telah dihapus pada " + \
str(timezone.now().strftime("%m/%d/%Y, %H:%M:%S")) + " WIB"
queryObject.archived_by = request.user
queryObject.save()
query_object.archived_by = request.user
query_object.save()
messages.success(request, "Point verifikasi berhasil dihapus")
return HttpResponseRedirect("/administration/setting/verification/")
return HttpResponseRedirect(ADMINISTRATION_VERIFICATION_SETTING)
def delete_category(request, *args, **kwargs):
......@@ -499,16 +501,16 @@ def delete_category(request, *args, **kwargs):
raise PermissionDenied(request)
category_name = get_object_or_404(Category,
pk=kwargs["pk_category"]).name
queryObject = get_object_or_404(Category,
query_object = get_object_or_404(Category,
pk=kwargs["pk_category"])
queryObject.archived = True
queryObject.description = "Telah dihapus pada " + \
query_object.archived = True
query_object.description = "Telah dihapus pada " + \
str(timezone.now().strftime("%m/%d/%Y, %H:%M:%S")) + " WIB"
queryObject.archived_by = request.user
queryObject.save()
query_object.archived_by = request.user
query_object.save()
messages.success(request, "Kategori " +
category_name + " berhasil dihapus")
return HttpResponseRedirect("/administration/setting/category/")
return HttpResponseRedirect(ADMINISTRATION_CATEGORY_SETTING)
def generatedummy(request):
if request.user.is_authenticated is False or request.user.is_admin is False:
......
......@@ -10,7 +10,6 @@ def year_choices():
class UploadMateriForm(forms.ModelForm):
categories = forms.ModelMultipleChoiceField(queryset=Category.objects.all(),widget=forms.CheckboxSelectMultiple(attrs={'style' : 'column-count:2'}),required=True)
#categories.widget.attrs["style"] = "column-count:2"
release_year = forms.TypedChoiceField(coerce=int, choices=year_choices, initial=datetime.date.today().year)
yt_video_id = forms.CharField(label="Youtube Video Id", \
help_text="This is not required.<br>\
......
......@@ -24,7 +24,7 @@ class Command(BaseCommand):
counter = 0
category_name = f"Kategori dummy {counter}"
dummy_category = []
for i in range(num_of_category):
for _ in range(num_of_category):
while (Category.objects.filter(name=category_name).exists()):
counter += 1
category_name = f"Kategori dummy {counter}"
......@@ -38,7 +38,7 @@ class Command(BaseCommand):
counter = 0
criterion_name = f"Kriteria dummy {counter}"
dummy_criteria = []
for i in range(num_of_criteria):
for _ in range(num_of_criteria):
while (VerificationSetting.objects.filter(title=criterion_name).exists()):
counter += 1
criterion_name = f"Kriteria dummy {counter}"
......@@ -67,8 +67,7 @@ class Command(BaseCommand):
counter = 0
dummy_user = []
email = f"admin-dummy-{counter}@email.com"
end_date = timezone.now()
for i in range(num_of_user):
for _ in range(num_of_user):