Fakultas Ilmu Komputer UI

Commit d3f89948 authored by Michael Christopher Manullang's avatar Michael Christopher Manullang
Browse files

Pulled new changes from master

parents 56ddf270 0a815a6d
Pipeline #58072 failed with stages
in 42 seconds
......@@ -205,4 +205,10 @@ __pycache__/
db.sqlite3
.coverage
htmlcov/
flowchart/
\ No newline at end of file
flowchart/
# Pycharm IDE
.idea
# MacOS
.DS_Store
......@@ -134,3 +134,15 @@ class PeriodForm(forms.Form):
if start_date > end_date:
self.add_error("end_date",
"waktu selesai sebelum waktu mulai")
class EditAdminStatusForm(forms.ModelForm):
is_active = forms.BooleanField(required=False)
class Meta:
model = User
fields = ["is_active"]
def __init__(self, *args, **kwargs):
super(EditAdminStatusForm, self).__init__(*args, **kwargs)
# Generated by Django 3.1 on 2020-09-29 05:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('administration', '0006_merge_20200604_0718'),
]
operations = [
migrations.AlterField(
model_name='verificationreport',
name='report',
field=models.JSONField(),
),
]
from django.contrib.postgres.fields import JSONField
from django.db.models import JSONField
from django.db import models
from django.utils import timezone
......@@ -25,4 +25,4 @@ class DeletionHistory(models.Model):
deleted_user_name = models.CharField(max_length=150)
deleted_user_role = models.CharField(max_length=150)
timestamp = models.DateTimeField(default=timezone.now)
deletor_admin = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
\ No newline at end of file
deletor_admin = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
......@@ -50,4 +50,17 @@
<!-- Divider -->
<hr class="sidebar-divider my-0">
<li class="nav-item">
<a class="nav-link" href="/administration/kelola-materi">
<span>Kelola Materi</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/administration/news/list">
<span>Kelola Berita</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider my-0">
</ul>
\ No newline at end of file
{% extends 'administration/base_administrasi.html' %}
{% load static %}
{% block content %}
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
Edit {{ page_title }}
</h6>
</div>
<div class="card-body">
<form method="POST">
{% csrf_token %}
{{ item.name }}
<div class="status d-flex align-items-baseline">
{{ form.is_active }} <br> Active
</div>
<div class="">
<button class="btn-sm btn-primary rounded p-12" type="submit">
<i class="far fa-save" aria-hidden="true"></i>
Simpan
</button>
</div>
</form>
</div>
</div>
{% endblock %}
\ No newline at end of file
......@@ -27,30 +27,39 @@
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Nama</th>
<th>NIK</th>
<th>Instansi</th>
<th>Pilihan</th>
<th scope="col">Nama</th>
<th scope="col">NIK</th>
<th scope="col">Instansi</th>
<th scope="col">Status</th>
<th scope="col">Pilihan</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Nama</th>
<th>NIK</th>
<th>Instansi</th>
<th>Pilihan</th>
<th scope="col">Nama</th>
<th scope="col">NIK</th>
<th scope="col">Instansi</th>
<th scope="col">Status</th>
<th scope="col">Pilihan</th>
</tr>
</tr>
</tfoot>
<tbody>
{% for current in users_list %}
<tr>
<td>{{ current.name }}</td>
<td>{% if current.name %} {{ current.name }} {% else %} Superadmin {% endif %}</td>
<td>{{ current.nik }}</td>
<td>{{ current.instansi }}</td>
<td>{% if current.is_active %} Active {% else %} Inactive {% endif %}</td>
<td class="verif-buttons">
<span>
{% if user.is_superuser %}
{% if not current.is_superuser %}
<a href="/administration/setting/admin/{{ current.id }}/edit" class="accept-button button-decoration" role="button">Edit</a>
{% endif %}
{% endif %}
<a href="/administration/profil-admin/{{ current.id }}/" class="accept-button button-decoration">Detail</a>
{% if not current.is_superuser %}
<button type="button" class="reject-button button-decoration" data-toggle="modal" data-target="#confirmModal{{ current.id }}">Hapus</button>
<div class="modal fade" id="confirmModal{{ current.id }}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
......@@ -62,15 +71,25 @@
</button>
</div>
<div class="modal-body">
<p>Sila konfirmasi penghapusan akun dengan tekan tombol hapus di bawah</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
<a href="/administration/hapus-admin/{{current.id}}/" type="button" class="btn btn-danger">Hapus</a>
<p>Anda akan menghapus akun admin dengan email
<span class="bg-danger pr-1 pl-1 text-white" style="text-transform: lowercase">{{current.email}}</span>
. Lakukan konfirmasi penghapusan dengan mengetik: </p>
<p class="bg-danger text-white p-1"> {{current.email}} </p>
</div>
<form/>
{% csrf_token %}
<div class="form-group pl-3 pr-3">
<input name="{{ current.email }}" class="form-control" id="{{ current.id }}"required pattern="{{current.email}}" oninput="checkValue(this)">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
<a href="/administration/hapus-admin/{{current.id}}/" id="btn-hapus-{{current.id}}" type="button" class="btn btn-danger disabled">Hapus</a>
</div>
</form>
</div>
</div>
</div>
{% endif %}
</span>
</td>
</tr>
......@@ -118,4 +137,14 @@
</div>
</div>
</div>
<script type="text/javascript">
function checkValue(element){
buttonElement = document.getElementById("btn-hapus-" + element.id)
if(element.value != element.name) {
buttonElement.classList.add("disabled");
} else {
buttonElement.classList.remove("disabled");
}
}
</script>
{% endblock %}
\ No newline at end of file
{% extends 'administration/base_administrasi2.html' %}
{% load static %}
{% block title %}
<title>Kelola Admin | Digipus</title>
{% endblock %}
{% block content %}
<!-- Page Heading -->
<h1 class="h3 mb-2 text-gray-800">Kelola Admin</h1>
<p class="mb-4">Tekan tombol detail untuk informasi lebih lanjut tentang admin</ehp>
<!-- DataTales Example -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<div class="d-flex">
<div class="mr-auto p-2">
<h6 id="table-description" class="m-0 font-weight-bold text-primary">Tabel Daftar Approved Material</h6>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table aria-describedby="table-description" class="table table-bordered" id="dataTable">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Cover</th>
<th scope="col">Content</th>
<th scope="col">Kontributor</th>
<th scope="col">Status</th>
<th scope="col">Jumlah Like</th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="col">Title</th>
<th scope="col">Cover</th>
<th scope="col">Content</th>
<th scope="col">Kontributor</th>
<th scope="col">Status</th>
<th scope="col">Jumlah Like</th>
</tr>
</tr>
</tfoot>
<tbody>
{% for materi in materi_list %}
<tr>
<td>{{ materi.title }}</td>
<td>
{% if materi.cover %}
<img id="posts-img" src="{{ materi.cover.url }}" alt="cover-picture" style="max-width: 400px;"/>
{% endif %}
</td>
<td>
<a href="/materi/{{materi.id}}/view">Lihat konten</a></td>
<td>{{ materi.uploader }}</td>
<td>{{ materi.status }}</td>
<td>{{ materi.like_count }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}
This diff is collapsed.
from django.urls import path
from administration.views import VerificationView, DetailVerificationView, VerificationSettingView, CategorySettingView, KelolaKontributorView, ProfileContributorAdminView, ProfileAdminAdministrationView, KelolaAdminView, RegistrasiAdminView, EditVerificationView, delete_admin, delete_contributor, delete_verification, StatisticsView, StatisticApiView, EditCategoryView, delete_category, generatedummy
from administration.views import VerificationView, DetailVerificationView, \
VerificationSettingView, CategorySettingView, \
KelolaKontributorView, ProfileContributorAdminView, \
ProfileAdminAdministrationView, KelolaAdminView, \
RegistrasiAdminView, EditVerificationView, \
delete_admin, delete_contributor, \
delete_verification, StatisticsView, \
StatisticApiView, EditCategoryView, \
EditAdminStatusView, delete_category, \
generatedummy, KelolaMateriView
app_name = "administration"
......@@ -22,7 +31,10 @@ urlpatterns = [
path("profil-admin/<int:pk>/", ProfileAdminAdministrationView.as_view()),
path("kelola-admin/", KelolaAdminView.as_view()),
path("kelola-admin/tambah/", RegistrasiAdminView.as_view()),
path("setting/admin/<int:pk>/edit",
EditAdminStatusView.as_view(), name="edit-admin-status"),
path("hapus-admin/<int:pk>/", delete_admin),
path("hapus-kontributor/<int:pk>/", delete_contributor),
path("kelola-materi/", KelolaMateriView.as_view()),
path("generate-dummy", generatedummy),
]
......@@ -10,8 +10,9 @@ from django.contrib import messages
from django.utils import timezone, lorem_ipsum
from dateutil.relativedelta import relativedelta
from administration.models import VerificationReport, VerificationSetting, DeletionHistory
from administration.forms import CategoryForm, VerificationSettingForm, RegistrasiAdminForm, PeriodForm
from administration.forms import CategoryForm, VerificationSettingForm, RegistrasiAdminForm, PeriodForm, EditAdminStatusForm
from app.models import Category, Materi, ViewStatistics, DownloadStatistics, Comment, Like, getRandomColor
from app.views import permission_denied
from authentication.models import User
from datetime import datetime
......@@ -19,6 +20,7 @@ from administration.utils import generate_time_step
from django.core import management
ADMINISTRATION_MANAGEMENT = "/administration/kelola-admin/"
def get_start_end_date(period):
if period == 'ALL_TIME':
......@@ -450,7 +452,7 @@ class RegistrasiAdminView(TemplateView):
new_user.password = make_password(data["password"])
new_user.is_admin = True
new_user.save()
return HttpResponseRedirect("/administration/kelola-admin/")
return HttpResponseRedirect(ADMINISTRATION_MANAGEMENT)
else:
context = self.get_context_data(**kwargs)
context["form"] = form
......@@ -520,12 +522,42 @@ class EditCategoryView(TemplateView):
context["form"] = form
return self.render_to_response(context)
class EditAdminStatusView(TemplateView):
template_name = "edit_admin.html"
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_superuser:
raise PermissionDenied(request)
return super(EditAdminStatusView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(EditAdminStatusView, self).get_context_data(**kwargs)
context["page_title"] = "Admin Status"
context["item"] = User.objects.get(id=kwargs["pk"])
context["form"] = EditAdminStatusForm(instance=context["item"])
return context
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
return self.render_to_response(context=context)
def post(self, request, *args, **kwargs):
user_object = self.get_context_data(**kwargs)["item"]
if user_object.is_superuser:
raise PermissionDenied(request)
form = EditAdminStatusForm(
request.POST, instance=user_object)
form.save()
return HttpResponseRedirect(ADMINISTRATION_MANAGEMENT)
def delete_admin(request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_admin:
raise PermissionDenied(request)
user_to_be_deleted = User.objects.get(pk=kwargs["pk"])
if (user_to_be_deleted.is_superuser):
raise PermissionDenied(request)
DeletionHistory.objects.create(
deleted_user_name=user_to_be_deleted.name,
deleted_user_role="Admin",
......@@ -533,7 +565,7 @@ def delete_admin(request, *args, **kwargs):
)
User.objects.filter(pk=kwargs["pk"]).delete()
return HttpResponseRedirect("/administration/kelola-admin/")
return HttpResponseRedirect(ADMINISTRATION_MANAGEMENT)
def delete_contributor(request, *args, **kwargs):
......@@ -593,4 +625,22 @@ def generatedummy(request):
# RUn management command
management.call_command('generatedummy', materi)
management.call_command('generatetraffic', visitor)
return JsonResponse({"success":True,"materi":materi,"visitor":visitor})
\ No newline at end of file
return JsonResponse({"success":True,"materi":materi,"visitor":visitor})
class KelolaMateriView(TemplateView):
template_name = "kelola_materi.html"
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_admin:
raise PermissionDenied(request)
return super(KelolaMateriView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(KelolaMateriView, self).get_context_data(**kwargs)
context['materi_list'] = Materi.objects.all()
return context
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
from django import forms
from app.models import Materi,Category
from app.models import Materi, Category, RatingContributor
from authentication.models import User
......@@ -27,10 +27,37 @@ class UploadMateriForm(forms.ModelForm):
class SuntingProfilForm(forms.ModelForm):
class Meta:
model = User
fields = ["profile_picture", "linkedin",
fields = ["email","name","instansi", "nik", "alamat", "nomor_telpon",
"profile_picture", "linkedin",
"facebook", "twitter", "instagram", "biography"]
def __init__(self, *args, **kwargs):
super(SuntingProfilForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs["class"] = "form-control"
if any(self.errors):
key = list(self.errors)[0]
self.fields[key].widget.attrs["autofocus"] = ""
self.fields["email"].widget.attrs["readonly"] = True
class RatingContributorForm(forms.ModelForm):
class Meta:
model = RatingContributor
fields = ['score', 'user']
SCORE_CHOICE = (
('', 'Select score'),
('1', '1'), # First one is the value of select option and second is the displayed value in option
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5'),
)
widgets = {
'score': forms.Select(choices=SCORE_CHOICE, attrs={'class': 'form-control'},),
'user': forms.HiddenInput()
}
# Generated by Django 3.0.3 on 2020-09-29 11:30
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('app', '0013_auto_20200919_2055'),
]
operations = [
migrations.CreateModel(
name='Rating',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
('score', models.IntegerField()),
('materi', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.Materi')),
('user', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'unique_together': {('materi', 'user')},
},
),
]
# Generated by Django 3.0.4 on 2020-09-30 04:50
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', '0014_rating'),
]
operations = [
migrations.AddField(
model_name='downloadstatistics',
name='downloader',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='riwayat_unduh', to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 3.0.3 on 2020-10-01 04:23
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('app', '0014_rating'),
]
operations = [
migrations.CreateModel(
name='ReqMaterial',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=100)),
('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
],
),
]
# Generated by Django 3.1.1 on 2020-10-05 14:41
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', '0015_reqmaterial'),
]
operations = [
migrations.CreateModel(
name='RatingContributor',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timestamp', models.DateTimeField(auto_now=True)),
('score', models.IntegerField()),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
# Generated by Django 3.1.1 on 2020-10-05 14:45
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0016_ratingcontributor'),
]
operations = [
migrations.AlterField(
model_name='ratingcontributor',
name='score',
field=models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(5)]),
),
]
# Generated by Django 3.1 on 2020-10-09 00:00
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('app', '0017_auto_20201005_2145'),
('app', '0015_downloadstatistics_downloader'),
]
operations = [
]
import random
from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models
from django.utils import timezone
......@@ -12,6 +14,7 @@ VERIFICATION_STATUS = [
("REVISION", "Perbaikan"),