...
 
Commits (2)
......@@ -47,7 +47,7 @@ docker-production:
docker-compose --project-directory . -f docker_scripts/docker-production.yml -p adega up
docker-remove-all:
docker rm adega_web_1 adega_db_1
docker rm adega_web adega_db_1
docker rmi adega_web
......@@ -68,6 +68,6 @@ args = `arg="$(filter-out $@,$(MAKECMDGOALS))" && echo $${arg:-${1}}`
docker-manage:
@echo $(call args,"")
docker exec -it adega_web_1 bash -c "cd src; python3 manage.py $(call args,'')"
docker exec -it adega_web bash -c "cd src; python3 manage.py $(call args,'')"
......@@ -44,6 +44,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'django_extensions',
'widget_tweaks',
'guardian',
'adega',
'public',
......@@ -104,8 +105,13 @@ DATABASES = {
}
}
AUTHENTICATION_BACKENDS = ['public.auth.EmailBackend']
AUTHENTICATION_BACKENDS = [
'public.auth.EmailBackend',
'guardian.backends.ObjectPermissionBackend',
]
ANONYMOUS_USER_NAME = "Público"
LOGIN_URL = 'public:index'
......
......@@ -7,23 +7,23 @@ from . import views
from django.views.generic import RedirectView
urlpatterns = [
url(r'^$', RedirectView.as_view(url='/adega/')),
#url(r'^$', RedirectView.as_view(url='/')),
url(r'^adega/$', views.dashboard, name='dashboard'),
url(r'^$', views.dashboard, name='dashboard'),
url(r'^adega/admission/(?P<submission_id>\w*)/', include('admission.urls', namespace='admission')),
url(r'^admission/(?P<submission_id>\w*)/', include('admission.urls', namespace='admission')),
url(r'^adega/course/(?P<submission_id>\w*)/', include('course.urls', namespace='course')),
url(r'^course/(?P<submission_id>\w*)/', include('course.urls', namespace='course')),
url(r'^adega/submission/', include('submission.urls', namespace='submission')),
url(r'^submission/', include('submission.urls', namespace='submission')),
url(r'^adega/student/(?P<submission_id>\w*)/', include('student.urls', namespace='student')),
url(r'^student/(?P<submission_id>\w*)/', include('student.urls', namespace='student')),
url(r'^adega/degree/(?P<submission_id>\w*)/', include('degree.urls', namespace='degree')),
url(r'^degree/(?P<submission_id>\w*)/', include('degree.urls', namespace='degree')),
url(r'^adega/public/', include('public.urls', namespace='public')),
url(r'^public/', include('public.urls', namespace='public')),
url(r'^adega/logout/$', views.logout, name='logout'),
url(r'^logout/$', views.logout, name='logout'),
url(r'^adega/admin/', admin.site.urls),
]
......@@ -6,15 +6,15 @@ from django.contrib import messages
from degree.models import Degree
from report_api.views import get_list_admission, get_admission_detail
from submission.models import Submission
from guardian.decorators import permission_required_or_403
@permission_required_or_403('view_admission', (Submission, 'id', 'submission_id'))
def detail(request, submission_id, ano, semestre):
submission_id = int(submission_id)
submission = Submission.objects.get(id=submission_id)
degree = submission.degree
if not (degree in request.user.educator.degree.all()):
return redirect("adega:dashboard")
for admission in get_list_admission(request.session, degree, submission_id):
......@@ -43,13 +43,12 @@ def detail(request, submission_id, ano, semestre):
})
@permission_required_or_403('view_admission', (Submission, 'id', 'submission_id'))
def index(request, submission_id):
submission_id = int(submission_id)
submission = Submission.objects.get(id=submission_id)
degree = submission.degree
if not (degree in request.user.educator.degree.all()):
return redirect("adega:dashboard")
return render(request, 'admission/index.html', {
"listage_admissions": get_list_admission(
......
......@@ -6,14 +6,14 @@ from django.contrib import messages
from degree.models import Degree
from report_api.views import get_list_courses, get_course_detail
from submission.models import Submission
from guardian.decorators import permission_required_or_403
@permission_required_or_403('view_course', (Submission, 'id', 'submission_id'))
def detail(request, submission_id, codigo_disciplina):
submission_id = int(submission_id)
submission = Submission.objects.get(id=submission_id)
degree = submission.degree
if not (degree in request.user.educator.degree.all()):
return redirect("adega:dashboard")
course_detail = get_course_detail(
request.session,
......@@ -31,13 +31,12 @@ def detail(request, submission_id, codigo_disciplina):
})
@permission_required_or_403('view_course', (Submission, 'id', 'submission_id'))
def index(request, submission_id):
submission_id = int(submission_id)
submission = Submission.objects.get(id=submission_id)
degree = submission.degree
if not (degree in request.user.educator.degree.all()):
return redirect("adega:dashboard")
analysis_result = get_list_courses(request.session, degree, submission_id)
courses_list = analysis_result["cache"]
......
from django.db import models
from django.contrib.auth.models import User
class Degree(models.Model):
name = models.CharField(max_length=40)
code = models.CharField(max_length=40)
manager = models.ForeignKey(User)
def __str__(self):
return self.name
def clean_code(self):
if '/' in self.code:
raise ValidationError('Valor inválido: O código não pode conter "/"')
from django.shortcuts import render, redirect
from django.views.generic import View
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout as process_logout
from report_api.views import get_degree_information
from degree.models import Degree
from submission.models import Submission
import json
from guardian.decorators import permission_required_or_403
@login_required
@permission_required_or_403('view_degree', (Submission, 'id', 'submission_id'))
def index(request, submission_id):
submission_id = int(submission_id)
......@@ -17,28 +17,10 @@ def index(request, submission_id):
degree = submission.degree
if not (degree in request.user.educator.degree.all()):
return redirect("dashboard")
degree_data = get_degree_information(request.session,degree, submission_id=submission_id)
return render(request,"degree/index.html",{
"submission":submission,
degree_data = get_degree_information(request.session, degree, submission_id=submission_id)
return render(request, "degree/index.html", {
"submission": submission,
"degree": degree,
"degree_data":degree_data
"degree_data": degree_data
})
#class Views(View):
# template_name = "index.html"
# @login_required
# def setDegree(self,request,degree_id):
# request.session["degree"] = degree_id
# return redirect('degree:index' )
# def index(self,request):
# if("degree" in request.session):
# degree = Degree.objects.get(code = request.session["degree"])
# else:
# return redirect("adega:dashboard")
# submission = degree.submission
# return render(request,"degree/index",{"degree":degree})
#
#
......@@ -6,15 +6,11 @@
<section class="col-md-8 content">
<h2>O projeto adega</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Integer auctor pellentesque lacus eget tincidunt.
Nam eu blandit est, sed vestibulum arcu. Phasellus ut tempus sapien.
Nunc vitae justo quis elit mattis ullamcorper eu ut lorem.
Sed ut interdum enim. Maecenas orci lectus, euismod sed
gravida fermentum, pretium non dui. Mauris vehicula nisl in
suscipit lacinia.</p>
<p>
O A.D.E.G.A. (Análise de Dados Estatísticos da Grade Acadêmica) tem como objetivo de desenvolver estudos sobre os cursos de graduacão por meio de técnicas de análise de dados como forma de obter informações sobre os cursos de graduação.
</p>
<p>Sed a risus eu sapien dictum faucibus a sed massa.
<!-- <p>Sed a risus eu sapien dictum faucibus a sed massa.
Curabitur non sapien non ipsum tincidunt sodales sed eu libero.
Vestibulum ac libero laoreet, fermentum dui id, maximus ex.
Ut sit amet turpis nulla. Sed ac sapien tortor.
......@@ -27,7 +23,7 @@
mattis venenatis. Pellentesque sed ligula commodo augue lobortis
accumsan ac tempor velit. Duis pharetra mattis orci, commodo
bibendum ex luctus at. Nullam nisl est, mattis id augue dignissim,
varius maximus quam.</p>
varius maximus quam.</p> -->
</section>
<section id="content" class="col-md-4 content">
......
......@@ -9,14 +9,14 @@ from report_api.views import get_list_students, get_student_detail
import json
from submission.models import Submission
from guardian.decorators import permission_required_or_403
@permission_required_or_403('view_student', (Submission, 'id', 'submission_id'))
def detail(request, submission_id, grr):
submission_id = int(submission_id)
submission = Submission.objects.get(id=submission_id)
degree = submission.degree
if not (degree in request.user.educator.degree.all()):
return redirect("adega:dashboard")
cache_j = get_student_detail(
request.session,
......@@ -46,13 +46,12 @@ def detail(request, submission_id, grr):
@permission_required_or_403('view_student', (Submission, 'id', 'submission_id'))
def index(request, submission_id):
submission_id = int(submission_id)
submission = Submission.objects.get(id=submission_id)
degree = submission.degree
if not (degree in request.user.educator.degree.all()):
return redirect("adega:dashboard")
sem_evasao = get_list_students(
......
......@@ -37,29 +37,30 @@ class Submission(models.Model):
historico = models.FileField(upload_to=get_path)
matricula = models.FileField(upload_to=get_path)
degree = models.ForeignKey(Degree)
timestamp = models.DateTimeField(default=timezone.now)
last = models.BooleanField(default=True)
processed = models.BooleanField(default=False)
process_time = models.IntegerField(null=True)
analysis_status = models.IntegerField(default=0, choices=ANALYSIS_STATUS_CHOICES)
analysis_status = models.IntegerField(
default=0,
choices=ANALYSIS_STATUS_CHOICES
)
last_error = models.CharField(default="", max_length=4096)
relative_year = models.IntegerField(null=True)
relative_semester = models.IntegerField(null=True)
semester_status = models.IntegerField(null=True, choices=STATUS_CHOICES)
done_in = models.DateTimeField(null=True)
class Meta:
permissions = (
# ('view_submission', 'Visualizar Relatórios'),
('view_course', 'Visualizar disciplinas'),
('view_student', 'Visualizar alunos'),
('view_degree', 'Visualizar curso'),
('view_admission', 'Visualizar turma ingresso'),
)
def save(self, *args, **kwargs):
"""
Sobrescrita do metodo save.
......@@ -101,10 +102,3 @@ class Submission(models.Model):
self.analysis_status = 2
self.last_error = error_message
self.save()
# @receiver(models.signals.post_save, sender=Submission)
# def execute_after_save(sender, instance, created, *args, **kwargs):
# if created:
# print(sender,instance,created)
# # submission_analysis.analyze(instance, debug=False)
# submission_analysis.analyze(sender)
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="alert alert-warning" role="alert">
......@@ -33,36 +35,124 @@
</div>
<div class="formBox form-group">
<form method="post" enctype="multipart/form-data" >
<div class="formBox form-group ">
<form id="form_sub" method="post" accept-charset="utf-8" enctype="multipart/form-data">
{% csrf_token %}
<!-- Uploads files -->
<div class="form-row">
<div class="col-lg-5 col-md-5 col-sm-4">
<label for="historico" type="file"
class="custom-file-label">Histórico</label>
<input type="file" name="historico"
class="custom-file-input" id="historico"/>
</div>
<div class="col-lg-5 col-md-5 col-sm-4 offset-lg-1 offset-md-1">
<label for="matricula" class="custom-file-label">Matrícula</label>
<input type="file" name="matricula" id="matricula"
class="custom-file-input"/>
</div>
</div>
<!-- Integer field -->
<div class="form-row">
<div class="col-lg-5 col-md-5">
<label for="relative_year">Ano do relatório</label>
<input type="number" class="form-control" name="relative_year" id="relative_year"
value="{{form.relative_year.field.initial}}" />
</div>
<div class="col-lg-5 col-md-5 offset-lg-1 offset-md-1">
<label for="relative_semester">Semestre do relatório</label>
<input type="number" class="form-control" name="relative_semester" id="relative_semester"
value="{{form.relative_semester.field.initial}}" />
</div>
</div>
<!-- Select field -->
<div class="form-row">
<div class="col-lg-5 col-md-5">
<label>Selecione o status do semestre</label>
<select name="semester_status" class="browser-default custom-select" id="semester_status">
{% for choice in form.semester_status.field.choices %}
<option value="{{choice.0}}">{{choice.1}}</option>
{% endfor %}
</select>
</div>
<div class="col-lg-5 col-md-5 offset-lg-1 offset-md-1">
<label>Selecione o curso de graduação</label>
<select name="degree" class="browser-default custom-select" id="degree">
{% for choice in form.degree.field.choices %}
<option value="{{choice.0}}">{{choice.1}}</option>
{% endfor %}
</select>
</div>
</div>
<!-- Permissions -->
<div class="row">
<table class="table table-striped" id="ptable" >
<thead >
<tr>
<th rowspan="3">Usuário</th>
<th colspan="5">Permissões</th>
</tr>
<tr>
{% for permission in permissions %}
<th scope="col"> {{permission}}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<th>{{user}}</th>
{% for permission in perms %}
<td>
<div class="form-check">
<input class="form-check-input position-static"
type="checkbox"
id="perm-{{user}}-{{permission}}"
name="perm-{{user}}-{{permission}}"
value=1 aria-label="...">
</div>
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-4">
{{ form.as_p }}
</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-4">
<div class="col-lg-3 col-md-4 col-sm-4 offset-lg-2">
<button class="btn btn-success btn-block" type="submit">Enviar relatório</button>
</div>
<div class="col-lg-3 col-md-4 col-sm-4">
<button class="btn btn-danger btn-block" type="submit">Cancelar</button>
</div>
</div>
</form>
</form>
</div>
<script charset="utf-8">
$("input[type=file]").change(function () {
var fieldVal = $(this).val();
// Change the node's value by removing the fake path (Chrome)
fieldVal = fieldVal.replace("C:\\fakepath\\", "");
if (fieldVal != undefined || fieldVal != "") {
$(this).next(".custom-file-label").attr('data-content', fieldVal);
$(this).next(".custom-file-label").text(fieldVal);
}
});
</script>
{% endblock content %}
{% block js-foot %}
<script src="{% static 'datatables/jquery.dataTables.min.js' %}">
$('#ptable').dataTable({
"bPaginate": true,
"bInfo": false,
"aaSorting": [[ 1, "desc" ]],
"responsive": true
});
</script>
{% endblock js-foot %}
......@@ -6,7 +6,16 @@ from submission.models import Submission
from submission.forms import SubmissionForm
from degree.models import Degree
from submission.analysis import main as submission_analysis
from educator.models import Educator
from django.contrib.auth.models import User
from guardian.shortcuts import assign_perm
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.db.models import Q
@method_decorator(login_required, name='dispatch')
class SubmissionCreate(SuccessMessageMixin, CreateView):
model = Submission
form_class = SubmissionForm
......@@ -16,6 +25,9 @@ class SubmissionCreate(SuccessMessageMixin, CreateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["users"] = User.objects.filter(~Q(username=self.request.user.username))
context["permissions"] = [x[1] for x in Submission._meta.permissions]
context["perms"] = [x[0] for x in Submission._meta.permissions]
context["hide_navbar"] = True
return context
......@@ -30,11 +42,31 @@ class SubmissionCreate(SuccessMessageMixin, CreateView):
response = super(SubmissionCreate, self).form_valid(form)
# trata permissoes
data = self.request.POST.copy()
users = {}
for i in data.keys():
# gets only permission data
if i.startswith("perm-"):
perm_str = i.split('-')
# cache user
if perm_str[1] not in users:
users[perm_str[1]] = User.objects.get(username=perm_str[1])
# assing permission perm_str[2] to user perm_str[1] for
# submission self.object
assign_perm(perm_str[2], users[perm_str[1]], self.object)
# assing all permission for self user
for perm in Submission._meta.permissions:
assign_perm(perm[0], self.request.user, self.object)
submission_analysis.analyze(self.object, debug=False)
return response
@method_decorator(login_required, name='dispatch')
class SubmissionUpdate(UpdateView):
model = Submission
template_name = 'submission_update.html'
......@@ -52,6 +84,8 @@ class SubmissionUpdate(UpdateView):
context["hide_navbar"] = True
return context
@method_decorator(login_required, name='dispatch')
class SubmissionDelete(DeleteView):
model = Submission
template_name = 'submission_delete.html'
......@@ -62,6 +96,8 @@ class SubmissionDelete(DeleteView):
context["hide_navbar"] = True
return context
@method_decorator(login_required, name='dispatch')
class SubmissionList(ListView):
model = Submission
template_name = 'submission_list.html'
......@@ -80,6 +116,7 @@ class SubmissionList(ListView):
return self.model.objects.filter(author=educator)
@method_decorator(login_required, name='dispatch')
class SubmissionDetail(DetailView):
model = Submission
template_name = 'submission_detail.html'
......