Fakultas Ilmu Komputer UI

Commit 59d87955 authored by Samuel Dimas Partogi's avatar Samuel Dimas Partogi
Browse files

Merge branch 'PBI-9-Statistik_Akses_Materi' into 'staging'

Pbi 9 statistik akses materi

See merge request ppl-fasilkom-ui/2020/ppl-c/diskominfo-depok-digipus/marjinal-digipus!69
parents 84bb7a6b 32ef74e1
...@@ -7,6 +7,7 @@ LONG_MONTH = ['', 'Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', ...@@ -7,6 +7,7 @@ LONG_MONTH = ['', 'Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni',
BASE_PERIODE = [ BASE_PERIODE = [
("", "Pilih"),
('-----', ( ('-----', (
("LAST_WEEK", "7 Hari Terakhir"), ("LAST_WEEK", "7 Hari Terakhir"),
("LAST_MONTH", "30 Hari Terakhir"), ("LAST_MONTH", "30 Hari Terakhir"),
......
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit from crispy_forms.layout import Layout, Submit, Row, Column, Reset, ButtonHolder, Button
from crispy_forms.bootstrap import InlineCheckboxes
from django import forms from django import forms
from administration.choices import genereatePeriodeChoices from administration.choices import genereatePeriodeChoices
...@@ -9,6 +9,12 @@ from app.models import Category ...@@ -9,6 +9,12 @@ from app.models import Category
from authentication.models import User from authentication.models import User
def generate_category_choices():
categories = Category.objects.all()
category_choices = [(i.id, i.name) for i in categories]
return category_choices
class DateInput(forms.DateInput): class DateInput(forms.DateInput):
input_type = 'date' input_type = 'date'
...@@ -87,6 +93,8 @@ class PeriodForm(forms.Form): ...@@ -87,6 +93,8 @@ class PeriodForm(forms.Form):
widget=DateInput, label="Waktu mulai", required=False) widget=DateInput, label="Waktu mulai", required=False)
end_date = forms.DateField( end_date = forms.DateField(
widget=DateInput, label="Waktu selesai", required=False) widget=DateInput, label="Waktu selesai", required=False)
categories = forms.MultipleChoiceField(
label="Kategori", required=False, choices=generate_category_choices)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
...@@ -95,7 +103,34 @@ class PeriodForm(forms.Form): ...@@ -95,7 +103,34 @@ class PeriodForm(forms.Form):
field.widget.attrs['class'] = 'form-control' field.widget.attrs['class'] = 'form-control'
self.helper = FormHelper() self.helper = FormHelper()
self.helper.attrs["name"] = "filter-form"
self.helper.form_method = 'get' self.helper.form_method = 'get'
self.helper.add_input(Submit('submit', 'Filter')) self.helper.layout = Layout(
Row(
# def get_date(self): 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'),
css_class='form-row'
),
InlineCheckboxes('categories'),
Row(
ButtonHolder(Submit('submit', 'Filter')),
ButtonHolder(Button('reset_form', 'Hapus filter'), css_class ="btn-warning")
)
)
def clean(self):
cleaned_data = super().clean()
start_date = cleaned_data.get('start_date')
end_date = cleaned_data.get('end_date')
if start_date is not None and end_date is None:
self.add_error("end_date",
"masukan waktu selesai")
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")
...@@ -2,48 +2,4 @@ ...@@ -2,48 +2,4 @@
// var canvas = document.getElementById("chart1"); // var canvas = document.getElementById("chart1");
// var heightRatio = 1.5; // var heightRatio = 1.5;
// canvas.height = canvas.width * heightRatio; // canvas.height = canvas.width * heightRatio;
// }); // });
var ctx = document.getElementById("chart1").getContext("2d"); \ No newline at end of file
var myChart = new Chart(ctx, {
type: "bar",
responsive: true,
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
label: "# of Votes",
data: [12, 19, 3, 5, 2, 3],
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,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
},
});
from django.urls import path from django.urls import path
from administration.views import (VerificationView, DetailVerificationView, 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
VerificationSettingView, CategorySettingView, KelolaKontributorView,
ProfileContributorAdminView, ProfileAdminAdministrationView,
KelolaAdminView, RegistrasiAdminView, EditVerificationView, EditCategoryView, StatisticsView, StatisticApiView,
delete_admin, delete_contributor, delete_verification, delete_category)
app_name = "administration" app_name = "administration"
......
import random import random
import string import string
from django.utils import timezone, lorem_ipsum
from dateutil.relativedelta import relativedelta
def id_generator(size=6, chars=string.ascii_uppercase + string.digits): # pragma: no cover
def generate_time_step(s, e, step="DAILY"):
result = []
time = s.replace(hour=0, minute=0, second=0, microsecond=0)
while time < e:
result.append(time)
if step == "DAILY":
time = time + relativedelta(days=1)
result.append(e)
return result
def id_generator(size=6, chars=string.ascii_uppercase + string.digits): # pragma: no cover
return ''.join(random.choice(chars) for _ in range(size)) return ''.join(random.choice(chars) for _ in range(size))
import json import json
from datetime import datetime, date
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.contrib.auth.hashers import make_password from django.contrib.auth.hashers import make_password
...@@ -6,14 +7,64 @@ from django.http import HttpResponseRedirect, JsonResponse ...@@ -6,14 +7,64 @@ from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
from django.views.generic import TemplateView, View from django.views.generic import TemplateView, View
from django.contrib import messages 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.models import VerificationReport, VerificationSetting, DeletionHistory
from administration.forms import CategoryForm, VerificationSettingForm, RegistrasiAdminForm, PeriodForm from administration.forms import CategoryForm, VerificationSettingForm, RegistrasiAdminForm, PeriodForm
from app.models import Category, Materi from app.models import Category, Materi, ViewStatistics, DownloadStatistics, Comment, Like, getRandomColor
from authentication.models import User from authentication.models import User
from datetime import datetime from datetime import datetime
from administration.utils import generate_time_step
def get_start_end_date(period):
if period == 'ALL_TIME':
return (None, None)
elif period.split("_")[0] == "LAST":
end = timezone.now()
delta = 7
if period.split("_")[1] == "WEEK":
delta = 7
if period.split("_")[1] == "MONTH":
delta = 30
if period.split("_")[1] == "QUARTER":
delta = 90
if period.split("_")[1] == "YEAR":
delta = 365
start = end - relativedelta(days=delta)
return (start, end)
elif period.split("_")[0] == "CURRENT":
start = timezone.now()
if period.split("_")[1] == "MONTH":
start = start.replace(day=1, hour=0, minute=0,
second=0, microsecond=0)
end = start + relativedelta(months=1)
return (start, end)
elif period.split("_")[1] == "YEAR":
start = start.replace(month=1, day=1, hour=0,
minute=0, second=0, microsecond=0)
end = start + relativedelta(years=1)
return (start, end)
elif period.split("_")[0] == "MINUS":
start = timezone.now()
delta = int(period.split("_")[1])
if period.split("_")[2] == "MONTH":
start = start.replace(day=1, hour=0, minute=0,
second=0, microsecond=0)
start = start - relativedelta(months=delta)
end = start + relativedelta(months=1)
return (start, end)
elif period.split("_")[2] == "YEAR":
start = start.replace(month=1, day=1, hour=0,
minute=0, second=0, microsecond=0)
start = start - relativedelta(years=delta)
end = start + relativedelta(years=1)
return (start, end)
else:
return (None, None)
# Create your views here.
class VerificationView(TemplateView): class VerificationView(TemplateView):
template_name = "verif.html" template_name = "verif.html"
...@@ -223,15 +274,120 @@ class ProfileContributorAdminView(TemplateView): ...@@ -223,15 +274,120 @@ class ProfileContributorAdminView(TemplateView):
class StatisticsView(TemplateView): class StatisticsView(TemplateView):
template_name = "administration/data_statistik.html" template_name = "administration/data_statistik.html"
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
raise PermissionDenied(request)
return super(StatisticsView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(StatisticsView, self).get_context_data(**kwargs) context = super(StatisticsView, self).get_context_data(**kwargs)
context["page_title"] = "Statistik" context["page_title"] = "Statistik"
context["periodForm"] = PeriodForm(self.request.GET) context["periodForm"] = PeriodForm(self.request.GET)
return context return context
def get_filter_set(self, **kwargs):
filter_set = {}
form = PeriodForm(self.request.GET)
DEFAULT_PERIOD = "LAST_MONTH"
if form.is_valid():
form_data = form.cleaned_data
if len(form_data["categories"]) == 0:
form_data["categories"] = None
if form_data["period"] == "":
form_data["period"] = DEFAULT_PERIOD
# check if using custom date range
if form_data["start_date"] is not None and form_data["end_date"] is not None:
start = timezone.make_aware(datetime.combine(
form_data["start_date"], datetime.min.time()))
end = timezone.make_aware(datetime.combine(
form_data["end_date"], datetime.min.time()))
elif form_data["period"] is not None:
start, end = get_start_end_date(form_data["period"])
else:
start, end = get_start_end_date(DEFAULT_PERIOD)
filter_set["start"] = start
filter_set["end"] = end
filter_set["categories"] = form_data["categories"]
return filter_set
def get_query_set(self, object_statistic, **kwargs):
if self.request.user.is_admin:
return object_statistic.objects.filter(materi__status="APPROVE")
else:
return object_statistic.objects.filter(materi__status="APPROVE", materi__uploader=self.request.user.id)
def filter_qs(self, qs, filter_set):
if filter_set.get("categories", None) is not None:
qs = qs.filter(materi__categories__in=filter_set.get("categories"))
if filter_set.get("start") is not None and filter_set.get("end") is not None:
s = filter_set.get("start")
e = filter_set.get("end")
qs = qs.filter(timestamp__gte=s, timestamp__lt=e)
return qs.distinct()
# def generate_table_data(self, data_sets):
# table_data = {}
# counter = 1
# row_materi_table = []
# for item in data_sets:
# # return res
def generate_chart_data(self, start, end, data_sets):
chart_data = {
"charts": [],
"total": [],
"label": []
}
label = ["Dilihat", "Diunduh", "Komentar", "Disukai"]
colors = ["#4e73df", "#e74a3b", "#1cc88a", "#f6c23e"]
time_step = generate_time_step(start, end)
for i in time_step:
chart_data["label"].append(i.strftime("%d/%m/%Y"))
# generate view stat
for label, color, dataset in zip(label, colors, data_sets):
result = {
"label": label,
"backgroundColor": color,
"borderColor": color,
"borderWidth": 1
}
data = []
total = 0
s = 0
e = 1
while e < len(time_step):
todays = dataset.filter(
timestamp__gte=time_step[s], timestamp__lt=time_step[e]).count()
data.append(todays)
total += todays
s += 1
e += 1
result["data"] = data
chart_data["charts"].append(result)
chart_data["total"].append(total)
return chart_data
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs) context = self.get_context_data(**kwargs)
form = context["periodForm"] filter_set = self.get_filter_set(**kwargs)
view_set = self.get_query_set(ViewStatistics, **kwargs)
view_set = self.filter_qs(view_set, filter_set)
download_set = self.get_query_set(DownloadStatistics, **kwargs)
download_set = self.filter_qs(download_set, filter_set)
like_set = self.get_query_set(Like, **kwargs)
like_set = self.filter_qs(like_set, filter_set)
comment_set = self.get_query_set(Comment, **kwargs)
comment_set = self.filter_qs(comment_set, filter_set)
data_sets = [view_set, download_set, like_set, comment_set]
chart_data = self.generate_chart_data(
filter_set["start"], filter_set["end"], data_sets)
context["chart_data"] = chart_data
return self.render_to_response(context=context) return self.render_to_response(context=context)
......
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