diff --git a/bulletin/__init__.py b/bulletin/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bulletin/__init__.py
diff --git a/bulletin/admin.py b/bulletin/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/bulletin/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/bulletin/apps.py b/bulletin/apps.py
new file mode 100644
index 0000000..b027b77
--- /dev/null
+++ b/bulletin/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class BulletinConfig(AppConfig):
+ name = 'bulletin'
diff --git a/bulletin/forms.py b/bulletin/forms.py
new file mode 100644
index 0000000..5af7684
--- /dev/null
+++ b/bulletin/forms.py
@@ -0,0 +1,128 @@
+# coding=utf-8
+from django import forms
+from django.utils.translation import ugettext_lazy as _
+from django.utils.html import strip_tags
+
+from subjects.models import Tag
+
+from .models import Bulletin
+
+from resubmit.widgets import ResubmitFileWidget
+
+class BulletinForm(forms.ModelForm):
+ subject = None
+
+ def __init__(self, *args, **kwargs):
+ super(BulletinForm, self).__init__(*args, **kwargs)
+
+ self.subject = kwargs['initial'].get('subject', None)
+
+ if self.instance.id:
+ self.subject = self.instance.topic.subject
+ self.initial['tags'] = ", ".join(self.instance.tags.all().values_list("name", flat = True))
+
+ self.fields['students'].queryset = self.subject.students.all()
+ self.fields['groups'].queryset = self.subject.group_subject.all()
+
+ tags = forms.CharField(label = _('Tags'), required = False)
+
+ class Meta:
+ model = Bulletin
+ fields = ['name', 'content', 'brief_description', 'all_students', 'students', 'groups', 'show_window', 'visible']
+ labels = {
+ 'name': _('Bulletin name'),
+ 'content': _('Bulletin content'),
+ }
+ widgets = {
+ 'content': forms.Textarea,
+ 'brief_description': forms.Textarea,
+ 'students': forms.SelectMultiple,
+ 'groups': forms.SelectMultiple,
+ }
+
+ def clean_name(self):
+ name = self.cleaned_data.get('name', '')
+
+ topics = self.subject.topic_subject.all()
+
+ for topic in topics:
+ if self.instance.id:
+ same_name = topic.resource_topic.filter(name__unaccent__iexact = name).exclude(id = self.instance.id).count()
+ else:
+ same_name = topic.resource_topic.filter(name__unaccent__iexact = name).count()
+
+ if same_name > 0:
+ self._errors['name'] = [_('This subject already has a bulletin with this name')]
+
+ return ValueError
+
+ return name
+
+ def clean_content(self):
+ content = self.cleaned_data.get('content', '')
+ cleaned_content = strip_tags(content)
+
+ if cleaned_content == '':
+ self._errors['content'] = [_('This field is required.')]
+
+ return ValueError
+
+ return content
+
+ def save(self, commit = True):
+ super(BulletinForm, self).save(commit = True)
+
+ self.instance.save()
+
+ previous_tags = self.instance.tags.all()
+
+ tags = self.cleaned_data['tags'].split(",")
+
+ #Excluding unwanted tags
+ for prev in previous_tags:
+ if not prev.name in tags:
+ self.instance.tags.remove(prev)
+
+ for tag in tags:
+ tag = tag.strip()
+
+ exist = Tag.objects.filter(name = tag).exists()
+
+ if exist:
+ new_tag = Tag.objects.get(name = tag)
+ else:
+ new_tag = Tag.objects.create(name = tag)
+
+ if not new_tag in self.instance.tags.all():
+ self.instance.tags.add(new_tag)
+
+ return self.instance
+
+class FormModalMessage(forms.Form):
+ MAX_UPLOAD_SIZE = 5*1024*1024
+
+ comment = forms.CharField(widget=forms.Textarea,label=_("Message"))
+ image = forms.FileField(widget=ResubmitFileWidget(attrs={'accept':'image/*'}),required=False)
+
+ def clean_comment(self):
+ comment = self.cleaned_data.get('comment', '')
+ cleaned_comment = strip_tags(comment)
+
+ if cleaned_comment == '':
+ self._errors['comment'] = [_('This field is required.')]
+
+ return ValueError
+
+ return comment
+
+ def clean_image(self):
+ image = self.cleaned_data.get('image', False)
+
+ if image:
+ if hasattr(image, '_size'):
+ if image._size > self.MAX_UPLOAD_SIZE:
+ self._errors['image'] = [_("The image is too large. It should have less than 5MB.")]
+
+ return ValueError
+
+ return image
diff --git a/bulletin/migrations/__init__.py b/bulletin/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bulletin/migrations/__init__.py
diff --git a/bulletin/models.py b/bulletin/models.py
new file mode 100644
index 0000000..43c5732
--- /dev/null
+++ b/bulletin/models.py
@@ -0,0 +1,49 @@
+import os
+from django.db import models
+from django.core.exceptions import ValidationError
+from django.utils.translation import ugettext_lazy as _
+from django.core.urlresolvers import reverse_lazy
+
+from topics.models import Resource
+
+def validate_file_extension(value):
+ valid_formats = [
+ 'image/jpeg','image/x-citrix-jpeg','image/png','image/x-citrix-png','image/x-png',
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'application/vnd.ms-excel','text/html','application/msword','application/vnd.oasis.opendocument.presentation',
+ 'application/vnd.oasis.opendocument.spreadsheet','application/vnd.oasis.opendocument.text',
+ 'application/pdf'
+ ]
+
+ if hasattr(value.file, 'content_type'):
+ if not value.file.content_type in valid_formats:
+ raise ValidationError(_('Please select a valid file. The uploaded file must have one of the following extensions: .doc, .docx, .html, .jpg, .odp, .ods, .odt, .pdf, .png, .ppt, .pptx, .xlx e .xlsx'))
+
+class Bulletin(Resource):
+ content = models.TextField(_('Bulletin Content'), blank = True)
+ file_content = models.FileField(_('File'), blank = True, upload_to = 'files/', validators = [validate_file_extension])
+
+ class Meta:
+ verbose_name = _('Bulletin')
+ verbose_name_plural = _('Bulletins')
+
+ def __str__(self):
+ return self.name
+
+ def access_link(self):
+ if self.show_window:
+ return reverse_lazy('bulletin:window_view', args = (), kwargs = {'slug': self.slug})
+
+ return reverse_lazy('bulletin:view', args = (), kwargs = {'slug': self.slug})
+
+ def update_link(self):
+ return 'bulletin:update'
+
+ def delete_link(self):
+ return 'bulletin:delete'
+
+ def delete_message(self):
+ return _('Are you sure you want delete the bulletin')
diff --git a/bulletin/templates/bulletin/_form.html b/bulletin/templates/bulletin/_form.html
new file mode 100644
index 0000000..72d2a72
--- /dev/null
+++ b/bulletin/templates/bulletin/_form.html
@@ -0,0 +1,347 @@
+{% load static i18n %}
+{% load widget_tweaks %}
+
+
+
+
diff --git a/bulletin/templates/bulletin/create.html b/bulletin/templates/bulletin/create.html
new file mode 100644
index 0000000..33c4698
--- /dev/null
+++ b/bulletin/templates/bulletin/create.html
@@ -0,0 +1,34 @@
+{% extends 'subjects/view.html' %}
+
+{% load static i18n django_bootstrap_breadcrumbs %}
+
+{% block style %}
+ {{block.super}}
+
+{% endblock %}
+
+{% block javascript %}
+ {{block.super}}
+
+{% endblock %}
+
+{% block breadcrumbs %}
+ {{ block.super }}
+
+ {% breadcrumb topic 'subjects:topic_view' topic.subject.slug topic.slug %}
+
+ {% trans 'Create Bulletin' as bread %}
+ {% breadcrumb bread 'bulletin:create' topic.slug %}
+{% endblock %}
+
+{% block content %}
+
+
+
+ {% include 'bulletin/_form.html' %}
+
+
+
+
+
+{% endblock %}
diff --git a/bulletin/templates/bulletin/relatorios.html b/bulletin/templates/bulletin/relatorios.html
new file mode 100644
index 0000000..de505e5
--- /dev/null
+++ b/bulletin/templates/bulletin/relatorios.html
@@ -0,0 +1,435 @@
+{% extends "bulletin/view.html" %}
+
+{% load static i18n pagination permissions_tags subject_counter %}
+{% load django_bootstrap_breadcrumbs %}
+
+{% block javascript%}
+ {{ block.super }}
+
+
+
+
+
+{% endblock%}
+
+{% block breadcrumbs %}
+ {{ block.super }}
+ {% trans 'Reports' as bread %}
+ {% breadcrumb bread bulletin%}
+{% endblock %}
+
+{% block content %}
+
+ {% if messages %}
+ {% for message in messages %}
+
+ {% endfor %}
+ {% endif %}
+
+
+
+
+
+
{% trans "Report of the resource " %}{{bulletin}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/bulletin/templates/bulletin/send_message.html b/bulletin/templates/bulletin/send_message.html
new file mode 100644
index 0000000..8c48540
--- /dev/null
+++ b/bulletin/templates/bulletin/send_message.html
@@ -0,0 +1,112 @@
+
+ {% load widget_tweaks i18n %}
+
+
+
+
\ No newline at end of file
diff --git a/bulletin/templates/bulletin/update.html b/bulletin/templates/bulletin/update.html
new file mode 100644
index 0000000..186939a
--- /dev/null
+++ b/bulletin/templates/bulletin/update.html
@@ -0,0 +1,36 @@
+{% extends 'subjects/view.html' %}
+
+{% load static i18n django_bootstrap_breadcrumbs %}
+
+{% block style %}
+ {{block.super}}
+
+{% endblock %}
+
+{% block javascript %}
+ {{block.super}}
+
+{% endblock %}
+
+{% block breadcrumbs %}
+ {{ block.super }}
+
+ {% breadcrumb topic 'subjects:topic_view' topic.subject.slug topic.slug %}
+
+ {% trans 'Edit: ' as bread %}
+ {% with bread|add:bulletin.name as bread_slug %}
+ {% breadcrumb bread_slug 'bulletin:update' topic.slug bulletin.slug %}
+ {% endwith %}
+{% endblock %}
+
+{% block content %}
+
+
+
+ {% include 'bulletin/_form.html' %}
+
+
+
+
+
+{% endblock %}
diff --git a/bulletin/templates/bulletin/view.html b/bulletin/templates/bulletin/view.html
new file mode 100644
index 0000000..03b900e
--- /dev/null
+++ b/bulletin/templates/bulletin/view.html
@@ -0,0 +1,58 @@
+{% extends 'subjects/view.html' %}
+
+{% load static i18n pagination permissions_tags subject_counter %}
+{% load django_bootstrap_breadcrumbs %}
+
+{% block javascript%}
+ {{ block.super }}
+{% endblock%}
+
+{% block breadcrumbs %}
+ {{ block.super }}
+ {% breadcrumb topic 'subjects:topic_view' subject.slug topic.slug %}
+ {% breadcrumb bulletin 'bulletin:view' bulletin.slug %}
+{% endblock %}
+
+{% block content %}
+ {% if messages %}
+ {% for message in messages %}
+
+ {% endfor %}
+ {% endif %}
+
+ {% resource_permissions request.user bulletin as has_resource_permissions %}
+
+ {% if bulletin.visible %}
+
+
+ {% elif has_resource_permissions %}
+
+
+
+ {% autoescape off %}
+ {{ bulletin.content }}
+ {% endautoescape %}
+
+
+{% endblock %}
diff --git a/bulletin/templates/bulletin/window_view.html b/bulletin/templates/bulletin/window_view.html
new file mode 100644
index 0000000..fa09684
--- /dev/null
+++ b/bulletin/templates/bulletin/window_view.html
@@ -0,0 +1 @@
+{{ bulletin.content|safe }}
diff --git a/bulletin/tests.py b/bulletin/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/bulletin/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/bulletin/urls.py b/bulletin/urls.py
new file mode 100644
index 0000000..4b84991
--- /dev/null
+++ b/bulletin/urls.py
@@ -0,0 +1,14 @@
+from django.conf.urls import url
+from django.contrib.auth import views as auth_views
+
+from . import views
+
+urlpatterns = [
+ url(r'^create/(?P
[\w_-]+)/$', views.CreateView.as_view(), name = 'create'),
+ url(r'^update/(?P[\w_-]+)/(?P[\w_-]+)/$', views.UpdateView.as_view(), name = 'update'),
+ url(r'^delete/(?P[\w_-]+)/$', views.DeleteView.as_view(), name = 'delete'),
+ url(r'^window_view/(?P[\w_-]+)/$', views.NewWindowView.as_view(), name = 'window_view'),
+ url(r'^view/(?P[\w_-]+)/$', views.InsideView.as_view(), name = 'view'),
+ url(r'^chart/(?P[\w_-]+)/$', views.StatisticsView.as_view(), name = 'get_chart'),
+ url(r'^send-message/(?P[\w_-]+)/$', views.SendMessage.as_view(), name = 'send_message'),
+]
diff --git a/bulletin/views.py b/bulletin/views.py
new file mode 100644
index 0000000..786bd76
--- /dev/null
+++ b/bulletin/views.py
@@ -0,0 +1,590 @@
+from django.shortcuts import get_object_or_404, redirect, render
+from django.views import generic
+from django.contrib import messages
+from django.core.urlresolvers import reverse, reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.http import JsonResponse
+
+from amadeus.permissions import has_subject_permissions, has_resource_permissions
+
+import time
+import datetime
+from log.mixins import LogMixin
+
+from topics.models import Topic
+
+from pendencies.forms import PendenciesForm
+
+from .forms import BulletinForm
+from .models import Bulletin
+
+from log.models import Log
+from chat.models import Conversation, TalkMessages, ChatVisualizations
+from users.models import User
+from subjects.models import Subject
+
+from .forms import FormModalMessage
+
+from django.template.loader import render_to_string
+from django.utils import formats
+import textwrap
+from django.utils.html import strip_tags
+import json
+from channels import Group
+
+class NewWindowView(LoginRequiredMixin, LogMixin, generic.DetailView):
+ log_component = 'resources'
+ log_action = 'view'
+ log_resource = 'bulletin'
+ log_context = {}
+
+ login_url = reverse_lazy("users:login")
+ redirect_field_name = 'next'
+
+ template_name = 'bulletin/window_view.html'
+ model = Bulletin
+ context_object_name = 'bulletin'
+
+ def dispatch(self, request, *args, **kwargs):
+ slug = self.kwargs.get('slug', '')
+ bulletin = get_object_or_404(Bulletin, slug=slug)
+
+ if not has_resource_permissions(request.user, bulletin):
+ return redirect(reverse_lazy('subjects:home'))
+
+ return super(NewWindowView, self).dispatch(request, *args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(NewWindowView, self).get_context_data(**kwargs)
+
+ self.log_context['category_id'] = self.object.topic.subject.category.id
+ self.log_context['category_name'] = self.object.topic.subject.category.name
+ self.log_context['category_slug'] = self.object.topic.subject.category.slug
+ self.log_context['subject_id'] = self.object.topic.subject.id
+ self.log_context['subject_name'] = self.object.topic.subject.name
+ self.log_context['subject_slug'] = self.object.topic.subject.slug
+ self.log_context['topic_id'] = self.object.topic.id
+ self.log_context['topic_name'] = self.object.topic.name
+ self.log_context['topic_slug'] = self.object.topic.slug
+ self.log_context['bulletin_id'] = self.object.id
+ self.log_context['bulletin_name'] = self.object.name
+ self.log_context['bulletin_slug'] = self.object.slug
+ self.log_context['timestamp_start'] = str(int(time.time()))
+
+ super(NewWindowView, self).createLog(self.request.user, self.log_component, self.log_action,
+ self.log_resource, self.log_context)
+
+ self.request.session['log_id'] = Log.objects.latest('id').id
+
+ return context
+
+class InsideView(LoginRequiredMixin, LogMixin, generic.DetailView):
+ log_component = 'resources'
+ log_action = 'view'
+ log_resource = 'bulletin'
+ log_context = {}
+
+ login_url = reverse_lazy("users:login")
+ redirect_field_name = 'next'
+
+ template_name = 'bulletins/view.html'
+ model = Bulletin
+ context_object_name = 'bulletin'
+
+ def dispatch(self, request, *args, **kwargs):
+ slug = self.kwargs.get('slug', '')
+ bulletin = get_object_or_404(Bulletin, slug=slug)
+
+ if not has_resource_permissions(request.user, bulletin):
+ return redirect(reverse_lazy('subjects:home'))
+
+ return super(InsideView, self).dispatch(request, *args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(InsideView, self).get_context_data(**kwargs)
+
+ context['title'] = self.object.name
+
+ context['topic'] = self.object.topic
+ context['subject'] = self.object.topic.subject
+
+ self.log_context['category_id'] = self.object.topic.subject.category.id
+ self.log_context['category_name'] = self.object.topic.subject.category.name
+ self.log_context['category_slug'] = self.object.topic.subject.category.slug
+ self.log_context['subject_id'] = self.object.topic.subject.id
+ self.log_context['subject_name'] = self.object.topic.subject.name
+ self.log_context['subject_slug'] = self.object.topic.subject.slug
+ self.log_context['topic_id'] = self.object.topic.id
+ self.log_context['topic_name'] = self.object.topic.name
+ self.log_context['topic_slug'] = self.object.topic.slug
+ self.log_context['bulletin_id'] = self.object.id
+ self.log_context['bulletin_name'] = self.object.name
+ self.log_context['bulletin_slug'] = self.object.slug
+ self.log_context['timestamp_start'] = str(int(time.time()))
+
+ super(InsideView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
+
+ self.request.session['log_id'] = Log.objects.latest('id').id
+
+ return context
+
+class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
+ log_component = 'resources'
+ log_action = 'create'
+ log_resource = 'bulletin'
+ log_context = {}
+
+ login_url = reverse_lazy("users:login")
+ redirect_field_name = 'next'
+
+ template_name = 'bulletin/create.html'
+ form_class = BulletinForm
+
+ def dispatch(self, request, *args, **kwargs):
+ slug = self.kwargs.get('slug', '')
+ topic = get_object_or_404(Topic, slug = slug)
+
+ if not has_subject_permissions(request.user, topic.subject):
+ return redirect(reverse_lazy('subjects:home'))
+
+ return super(CreateView, self).dispatch(request, *args, **kwargs)
+
+ def get(self, request, *args, **kwargs):
+ self.object = None
+
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+
+ slug = self.kwargs.get('slug', '')
+ topic = get_object_or_404(Topic, slug = slug)
+
+ pendencies_form = PendenciesForm(initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
+
+ return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form))
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+
+ slug = self.kwargs.get('slug', '')
+ topic = get_object_or_404(Topic, slug = slug)
+
+ pendencies_form = PendenciesForm(self.request.POST, initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
+
+ if (form.is_valid() and pendencies_form.is_valid()):
+ return self.form_valid(form, pendencies_form)
+ else:
+ return self.form_invalid(form, pendencies_form)
+
+ def get_initial(self):
+ initial = super(CreateView, self).get_initial()
+
+ slug = self.kwargs.get('slug', '')
+
+ topic = get_object_or_404(Topic, slug = slug)
+ initial['subject'] = topic.subject
+
+ return initial
+
+ def form_invalid(self, form, pendencies_form):
+ return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form))
+
+ def form_valid(self, form, pendencies_form):
+ self.object = form.save(commit = False)
+ slug = self.kwargs.get('slug', '')
+ topic = get_object_or_404(Topic, slug = slug)
+
+ self.object.topic = topic
+ self.object.order = topic.resource_topic.count() + 1
+
+ if not self.object.topic.visible and not self.object.topic.repository:
+ self.object.visible = False
+
+ self.object.save()
+
+ pend_form = pendencies_form.save(commit = False)
+ pend_form.resource = self.object
+
+ if not pend_form.action == "":
+ pend_form.save()
+
+ self.log_context['category_id'] = self.object.topic.subject.category.id
+ self.log_context['category_name'] = self.object.topic.subject.category.name
+ self.log_context['category_slug'] = self.object.topic.subject.category.slug
+ self.log_context['subject_id'] = self.object.topic.subject.id
+ self.log_context['subject_name'] = self.object.topic.subject.name
+ self.log_context['subject_slug'] = self.object.topic.subject.slug
+ self.log_context['topic_id'] = self.object.topic.id
+ self.log_context['topic_name'] = self.object.topic.name
+ self.log_context['topic_slug'] = self.object.topic.slug
+ self.log_context['bulletin_id'] = self.object.id
+ self.log_context['bulletin_name'] = self.object.name
+ self.log_context['bulletin_slug'] = self.object.slug
+
+ super(CreateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
+
+ return redirect(self.get_success_url())
+
+ def get_context_data(self, **kwargs):
+ context = super(CreateView, self).get_context_data(**kwargs)
+
+ context['title'] = _('Create Bulletin')
+
+ slug = self.kwargs.get('slug', '')
+ topic = get_object_or_404(Topic, slug = slug)
+
+ context['topic'] = topic
+ context['subject'] = topic.subject
+
+ return context
+
+ def get_success_url(self):
+ messages.success(self.request, _('The Bulletin "%s" was added to the Topic "%s" of the virtual environment "%s" successfully!')%(self.object.name, self.object.topic.name, self.object.topic.subject.name))
+
+ success_url = reverse_lazy('bulletin:view', kwargs = {'slug': self.object.slug})
+
+ if self.object.show_window:
+ self.request.session['resources'] = {}
+ self.request.session['resources']['new_page'] = True
+ self.request.session['resources']['new_page_url'] = reverse('bulletin:window_view', kwargs = {'slug': self.object.slug})
+
+ success_url = reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
+
+ return success_url
+
+class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
+ log_component = 'resources'
+ log_action = 'update'
+ log_resource = 'bulletin'
+ log_context = {}
+
+ login_url = reverse_lazy("users:login")
+ redirect_field_name = 'next'
+
+ template_name = 'bulletin/update.html'
+ model = Bulletin
+ form_class = BulletinForm
+
+ def dispatch(self, request, *args, **kwargs):
+ slug = self.kwargs.get('topic_slug', '')
+ topic = get_object_or_404(Topic, slug = slug)
+
+ if not has_subject_permissions(request.user, topic.subject):
+ return redirect(reverse_lazy('subjects:home'))
+
+ return super(UpdateView, self).dispatch(request, *args, **kwargs)
+
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object()
+
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+
+ slug = self.kwargs.get('topic_slug', '')
+ topic = get_object_or_404(Topic, slug = slug)
+
+ pend_form = self.object.pendencies_resource.all()
+
+ if len(pend_form) > 0:
+ pendencies_form = PendenciesForm(instance = pend_form[0], initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
+ else:
+ pendencies_form = PendenciesForm(initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
+
+ return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form))
+
+ def post(self, request, *args, **kwargs):
+ self.object = self.get_object()
+
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+
+ slug = self.kwargs.get('topic_slug', '')
+ topic = get_object_or_404(Topic, slug = slug)
+
+ pend_form = self.object.pendencies_resource.all()
+
+ if len(pend_form) > 0:
+ pendencies_form = PendenciesForm(self.request.POST, instance = pend_form[0], initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
+ else:
+ pendencies_form = PendenciesForm(self.request.POST, initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
+
+ if (form.is_valid() and pendencies_form.is_valid()):
+ return self.form_valid(form, pendencies_form)
+ else:
+ return self.form_invalid(form, pendencies_form)
+
+ def form_invalid(self, form, pendencies_form):
+ return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form))
+
+ def form_valid(self, form, pendencies_form):
+ self.object = form.save(commit = False)
+
+ if not self.object.topic.visible and not self.object.topic.repository:
+ self.object.visible = False
+
+ self.object.save()
+
+ pend_form = pendencies_form.save(commit = False)
+ pend_form.resource = self.object
+
+ if not pend_form.action == "":
+ pend_form.save()
+
+ self.log_context['category_id'] = self.object.topic.subject.category.id
+ self.log_context['category_name'] = self.object.topic.subject.category.name
+ self.log_context['category_slug'] = self.object.topic.subject.category.slug
+ self.log_context['subject_id'] = self.object.topic.subject.id
+ self.log_context['subject_name'] = self.object.topic.subject.name
+ self.log_context['subject_slug'] = self.object.topic.subject.slug
+ self.log_context['topic_id'] = self.object.topic.id
+ self.log_context['topic_name'] = self.object.topic.name
+ self.log_context['topic_slug'] = self.object.topic.slug
+ self.log_context['bulletin_id'] = self.object.id
+ self.log_context['bulletin_name'] = self.object.name
+ self.log_context['bulletin_slug'] = self.object.slug
+
+ super(UpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
+
+ return redirect(self.get_success_url())
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateView, self).get_context_data(**kwargs)
+
+ context['title'] = _('Update Bulletin')
+
+ slug = self.kwargs.get('topic_slug', '')
+ topic = get_object_or_404(Topic, slug = slug)
+
+ context['topic'] = topic
+ context['subject'] = topic.subject
+
+ return context
+
+ def get_success_url(self):
+ messages.success(self.request, _('The Bulletin "%s" was updated successfully!')%(self.object.name))
+
+ success_url = reverse_lazy('bulletin:view', kwargs = {'slug': self.object.slug})
+
+ if self.object.show_window:
+ self.request.session['resources'] = {}
+ self.request.session['resources']['new_page'] = True
+ self.request.session['resources']['new_page_url'] = reverse('bulletin:window_view', kwargs = {'slug': self.object.slug})
+
+ success_url = reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
+
+ return success_url
+
+class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
+ log_component = 'resources'
+ log_action = 'delete'
+ log_resource = 'bulletin'
+ log_context = {}
+
+ login_url = reverse_lazy("users:login")
+ redirect_field_name = 'next'
+
+ template_name = 'resources/delete.html'
+ model = Bulletin
+ context_object_name = 'resource'
+
+ def dispatch(self, request, *args, **kwargs):
+ slug = self.kwargs.get('slug', '')
+ bulletin = get_object_or_404(Bulletin, slug = slug)
+
+ if not has_subject_permissions(request.user, bulletin.topic.subject):
+ return redirect(reverse_lazy('subjects:home'))
+
+ return super(DeleteView, self).dispatch(request, *args, **kwargs)
+
+ def get_success_url(self):
+ messages.success(self.request, _('The bulletin "%s" was removed successfully from virtual environment "%s"!')%(self.object.name, self.object.topic.subject.name))
+
+ self.log_context['category_id'] = self.object.topic.subject.category.id
+ self.log_context['category_name'] = self.object.topic.subject.category.name
+ self.log_context['category_slug'] = self.object.topic.subject.category.slug
+ self.log_context['subject_id'] = self.object.topic.subject.id
+ self.log_context['subject_name'] = self.object.topic.subject.name
+ self.log_context['subject_slug'] = self.object.topic.subject.slug
+ self.log_context['topic_id'] = self.object.topic.id
+ self.log_context['topic_name'] = self.object.topic.name
+ self.log_context['topic_slug'] = self.object.topic.slug
+ self.log_context['bulletin_id'] = self.object.id
+ self.log_context['bulletin_name'] = self.object.name
+ self.log_context['bulletin_slug'] = self.object.slug
+
+ super(DeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
+
+ return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
+
+
+class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView):
+ log_component = 'resources'
+ log_action = 'view_statistics'
+ log_resource = 'bulletin'
+ log_context = {}
+
+ login_url = reverse_lazy("users:login")
+ redirect_field_name = 'next'
+ model = Bulletin
+ template_name = 'bulletin/relatorios.html'
+
+ def dispatch(self, request, *args, **kwargs):
+ slug = self.kwargs.get('slug', '')
+ bulletin = get_object_or_404(Bulletin, slug = slug)
+
+ if not has_subject_permissions(request.user, bulletin.topic.subject):
+ return redirect(reverse_lazy('subjects:home'))
+
+ return super(StatisticsView, self).dispatch(request, *args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(StatisticsView, self).get_context_data(**kwargs)
+
+ self.log_context['category_id'] = self.object.topic.subject.category.id
+ self.log_context['category_name'] = self.object.topic.subject.category.name
+ self.log_context['category_slug'] = self.object.topic.subject.category.slug
+ self.log_context['subject_id'] = self.object.topic.subject.id
+ self.log_context['subject_name'] = self.object.topic.subject.name
+ self.log_context['subject_slug'] = self.object.topic.subject.slug
+ self.log_context['topic_id'] = self.object.topic.id
+ self.log_context['topic_name'] = self.object.topic.name
+ self.log_context['topic_slug'] = self.object.topic.slug
+ self.log_context['bulletin_id'] = self.object.id
+ self.log_context['bulletin_name'] = self.object.name
+ self.log_context['bulletin_slug'] = self.object.slug
+
+ super(StatisticsView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
+
+
+ context['title'] = _('Bulletin Reports')
+
+ slug = self.kwargs.get('slug')
+ bulletin = get_object_or_404(Bulletin, slug = slug)
+
+ date_format = "%d/%m/%Y %H:%M" if self.request.GET.get('language','') == 'pt-br' else "%m/%d/%Y %I:%M %p"
+ if self.request.GET.get('language','') == "":
+ start_date = datetime.datetime.now() - datetime.timedelta(30)
+ end_date = datetime.datetime.now()
+ else :
+ start_date = datetime.datetime.strptime(self.request.GET.get('init_date',''),date_format)
+ end_date = datetime.datetime.strptime(self.request.GET.get('end_date',''),date_format)
+ context["init_date"] = start_date
+ context["end_date"] = end_date
+ alunos = bulletin.students.all()
+ if bulletin.all_students :
+ alunos = bulletin.topic.subject.students.all()
+
+ vis_ou = Log.objects.filter(context__contains={'bulletin_id':bulletin.id},resource="bulletin",action="view",user_email__in=(aluno.email for aluno in alunos), datetime__range=(start_date,end_date + datetime.timedelta(minutes = 1)))
+ did,n_did,history = str(_("Realized")),str(_("Unrealized")),str(_("Historic"))
+ re = []
+ data_n_did,data_history = [],[]
+ json_n_did, json_history = {},{}
+
+ for log_al in vis_ou.order_by("datetime"):
+ data_history.append([str(alunos.get(email=log_al.user_email)),
+ ", ".join([str(x) for x in bulletin.topic.subject.group_subject.filter(participants__email=log_al.user_email)]),
+ log_al.action,log_al.datetime])
+
+ json_history["data"] = data_history
+
+ not_view = alunos.exclude(email__in=[log.user_email for log in vis_ou.distinct("user_email")])
+ index = 0
+ for alun in not_view:
+ data_n_did.append([index,str(alun),", ".join([str(x) for x in bulletin.topic.subject.group_subject.filter(participants__email=alun.email)]),str(_('View')), str(alun.email)])
+ index += 1
+ json_n_did["data"] = data_n_did
+
+
+ context["json_n_did"] = json_n_did
+ context["json_history"] = json_history
+ c_visualizou = vis_ou.distinct("user_email").count()
+ column_view = str(_('View'))
+ re.append([str(_('Bulletin')),did,n_did])
+ re.append([column_view,c_visualizou, alunos.count() - c_visualizou])
+ context['topic'] = bulletin.topic
+ context['subject'] = bulletin.topic.subject
+ context['db_data'] = re
+ context['title_chart'] = _('Actions about resource')
+ context['title_vAxis'] = _('Quantity')
+ context['view'] = column_view
+ context["n_did_table"] = n_did
+ context["did_table"] = did
+ context["history_table"] = history
+ return context
+
+
+
+from django.http import HttpResponse #used to send HTTP 404 error to ajax
+
+class SendMessage(LoginRequiredMixin, LogMixin, generic.edit.FormView):
+ log_component = 'resources'
+ log_action = 'send'
+ log_resource = 'bulletin'
+ log_context = {}
+
+ login_url = reverse_lazy("users:login")
+ redirect_field_name = 'next'
+
+ template_name = 'bulletin/send_message.html'
+ form_class = FormModalMessage
+
+ def dispatch(self, request, *args, **kwargs):
+ slug = self.kwargs.get('slug', '')
+ bulletin = get_object_or_404(Bulletin, slug = slug)
+ self.bulletin = bulletin
+
+ if not has_subject_permissions(request.user, bulletin.topic.subject):
+ return redirect(reverse_lazy('subjects:home'))
+
+ return super(SendMessage, self).dispatch(request, *args, **kwargs)
+
+ def form_valid(self, form):
+ message = form.cleaned_data.get('comment')
+ image = form.cleaned_data.get("image")
+ users = (self.request.POST.get('users[]','')).split(",")
+ user = self.request.user
+ subject = self.bulletin.topic.subject
+
+ if (users[0] is not ''):
+ for u in users:
+ to_user = User.objects.get(email=u)
+ talk, create = Conversation.objects.get_or_create(user_one=user,user_two=to_user)
+ created = TalkMessages.objects.create(text=message,talk=talk,user=user,subject=subject,image=image)
+
+ simple_notify = textwrap.shorten(strip_tags(message), width = 30, placeholder = "...")
+
+ if image is not '':
+ simple_notify += " ".join(_("[Photo]"))
+
+ notification = {
+ "type": "chat",
+ "subtype": "subject",
+ "space": subject.slug,
+ "user_icon": created.user.image_url,
+ "notify_title": str(created.user),
+ "simple_notify": simple_notify,
+ "view_url": reverse("chat:view_message", args = (created.id, ), kwargs = {}),
+ "complete": render_to_string("chat/_message.html", {"talk_msg": created}, self.request),
+ "container": "chat-" + str(created.user.id),
+ "last_date": _("Last message in %s")%(formats.date_format(created.create_date, "SHORT_DATETIME_FORMAT"))
+ }
+
+ notification = json.dumps(notification)
+
+ Group("user-%s" % to_user.id).send({'text': notification})
+
+ ChatVisualizations.objects.create(viewed = False, message = created, user = to_user)
+
+ success = str(_('The message was successfull sent!'))
+ return JsonResponse({"message":success})
+ erro = HttpResponse(str(_("No user selected!")))
+ erro.status_code = 404
+ return erro
+
+ def get_context_data(self, **kwargs):
+ context = super(SendMessage,self).get_context_data()
+ context["bulletin"] = get_object_or_404(Bulletin, slug=self.kwargs.get('slug', ''))
+ return context
--
libgit2 0.21.2