Commit 58603d7cf7d4bcbf70b04d103cfda1930145b3ed

Authored by Jailson Dias
2 parents 7483f021 228b3f41

Merge branch 'refactoring' of https://github.com/amadeusproject/amadeuslms into refactoring

amadeus/settings.py
... ... @@ -68,6 +68,7 @@ INSTALLED_APPS = [
68 68 'topics',
69 69 'pendencies',
70 70 'mural',
  71 + 'chat',
71 72 'file_link',
72 73 'goals',
73 74 'pdf_file',
... ...
amadeus/static/css/.sass-cache/a7f87b90919294b62ab4f8079e31dcda8f485534/green.sassc
No preview for this file type
amadeus/static/css/base/amadeus.css
... ... @@ -1227,4 +1227,70 @@ div.dataTables_wrapper div.dataTables_paginate {
1227 1227 display: inline;
1228 1228 margin-right: 30px;
1229 1229 }
1230   -/* End Reports */
1231 1230 \ No newline at end of file
  1231 +
  1232 +.delete-row{
  1233 + float: right;
  1234 + background-color: gray;
  1235 + color: white;
  1236 + padding: 5px 20px;
  1237 + font-size: 12px;
  1238 + text-decoration: none;
  1239 + border: none;
  1240 + border-radius: 2px;
  1241 + position: relative;
  1242 + margin: 10px 20px;
  1243 + font-weight: 700;
  1244 + text-transform: uppercase;
  1245 + letter-spacing: 0;
  1246 +}
  1247 +/* End Reports */
  1248 +
  1249 +/* Chat */
  1250 +.participants-group {
  1251 + margin-left: 40px;
  1252 +}
  1253 +
  1254 +.participant {
  1255 + margin-bottom: 10px;
  1256 + border-width: 1px;
  1257 + border-style: solid;
  1258 + padding-right: 10px;
  1259 + height: 70px;
  1260 +}
  1261 +
  1262 +.participant .user-img {
  1263 + height: 70px;
  1264 + padding: 3px 0px 5px 0px;
  1265 + text-align: center;
  1266 +}
  1267 +
  1268 +.participant .user-img img {
  1269 + height: 100%;
  1270 + margin: 0 auto;
  1271 +}
  1272 +
  1273 +.participant .user-info {
  1274 + padding: 7px 15px;
  1275 +}
  1276 +.participant .user-info .status {
  1277 + width: 20px;
  1278 + height: 20px;
  1279 + border-width: 1px;
  1280 + border-style: solid;
  1281 + border-radius: 10px;
  1282 + margin-right: 10px;
  1283 + position: relative;
  1284 + top: 3px;
  1285 + display: inline-block;
  1286 + border-spacing: 0;
  1287 + border-collapse: collapse;
  1288 +}
  1289 +.participant .user-info h4 {
  1290 + font-weight: 700;
  1291 + line-height: 2.0;
  1292 +}
  1293 +
  1294 +.participant .buttons {
  1295 + padding: 7px 0px;
  1296 +}
  1297 +/* End Chat */
1232 1298 \ No newline at end of file
... ...
amadeus/static/css/themes/green.css
... ... @@ -471,6 +471,19 @@ a.add-row {
471 471 .goal_divider {
472 472 border-top-color: #888; }
473 473  
  474 +.participant {
  475 + border-color: #888; }
  476 +
  477 +.participant .user-info h4 {
  478 + color: #59b75c; }
  479 +
  480 +.participant .user-info .status {
  481 + border-color: #888;
  482 + background-color: #F5F5F5; }
  483 +
  484 +.participant .user-info .status.active {
  485 + background-color: #59b75c; }
  486 +
474 487 @media(max-width: 768px) {
475 488 .navbar .navbar-nav .dropdown .dropdown-menu li > a {
476 489 color: #333333 !important; }
... ...
amadeus/static/css/themes/green.css.map
1 1 {
2 2 "version": 3,
3   -"mappings": "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",
  3 +"mappings": "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",
4 4 "sources": ["green.sass"],
5 5 "names": [],
6 6 "file": "green.css"
... ...
amadeus/static/css/themes/green.sass
... ... @@ -642,6 +642,19 @@ a.add-row
642 642 .goal_divider
643 643 border-top-color: #888
644 644  
  645 +.participant
  646 + border-color: #888
  647 +
  648 +.participant .user-info h4
  649 + color: #59b75c
  650 +
  651 +.participant .user-info .status
  652 + border-color: #888
  653 + background-color: $default-white
  654 +
  655 +.participant .user-info .status.active
  656 + background-color: #59b75c
  657 +
645 658 @media(max-width: 768px)
646 659 .navbar .navbar-nav .dropdown .dropdown-menu li > a
647 660 color: #333333 !important
... ...
amadeus/templates/base.html
... ... @@ -206,10 +206,12 @@
206 206 <span class="badge notify_badge mural_badge" {% if mural_notifications_count == 0 %} style="display:none" {% endif %}>{% if mural_notifications_count > 99 %} +99 {% else %} {{ mural_notifications_count }} {% endif %}</span>
207 207 </a>
208 208 </li>
209   - <li class="item" data-toggle="tooltip" data-placement="right" title="{% trans "Messages" %}">
210   - <i class="fa fa-envelope-o" aria-hidden="true"></i>
  209 + <li class="item {{ chat_menu_active }} action_icon" data-toggle="tooltip" data-placement="right" title="{% trans "Messages" %}">
  210 + <a href="{% url 'chat:manage_general' %}">
  211 + <i class="fa fa-envelope-o" aria-hidden="true"></i>
  212 + </a>
211 213 </li>
212   - <li class="item {{ pendencies_menu_active }} action_icon" data-toggle="tooltip" data-placement="right" title="{% trans "Pendencias" %}">
  214 + <li class="item {{ pendencies_menu_active }} action_icon" data-toggle="tooltip" data-placement="right" title="{% trans "Pendencies" %}">
213 215 <a href="{% url 'notifications:manage' %}">
214 216 <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
215 217 {% if notifications_count > 0 %}
... ... @@ -253,15 +255,17 @@
253 255 </a>
254 256 </li>
255 257 <li class="item {{ mural_menu_active }} action_icon" data-toggle="tooltip" data-placement="top" title="{% trans "Mural" %}">
256   - <a href="{% url 'mural:manage_general' %}"
  258 + <a href="{% url 'mural:manage_general' %}">
257 259 <i class="fa fa-list" aria-hidden="true" ></i>
258 260 <span class="badge notify_badge mural_badge" {% if mural_notifications_count == 0 %} style="display:none" {% endif %}>{% if mural_notifications_count > 99 %} +99 {% else %} {{ mural_notifications_count }} {% endif %}</span>
259 261 </a>
260 262 </li>
261   - <li class="item" data-toggle="tooltip" data-placement="top" title="{% trans "Messages" %}">
262   - <i class="fa fa-envelope-o" aria-hidden="true"></i>
  263 + <li class="item {{ chat_menu_active }} action_icon" data-toggle="tooltip" data-placement="top" title="{% trans "Messages" %}">
  264 + <a href="{% url 'chat:manage_general' %}">
  265 + <i class="fa fa-envelope-o" aria-hidden="true"></i>
  266 + </a>
263 267 </li>
264   - <li class="item {{ pendencies_menu_active }} action_icon" data-toggle="tooltip" data-placement="top" title="{% trans "Pendencias" %}">
  268 + <li class="item {{ pendencies_menu_active }} action_icon" data-toggle="tooltip" data-placement="top" title="{% trans "Pendencies" %}">
265 269 <a href="{% url 'notifications:manage' %}">
266 270 <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
267 271 {% if notifications_count > 0 %}
... ...
amadeus/urls.py
... ... @@ -30,6 +30,7 @@ urlpatterns = [
30 30 url(r'^subjects/', include('subjects.urls', namespace = 'subjects')),
31 31 url(r'^groups/', include('students_group.urls', namespace = 'groups')),
32 32 url(r'^topics/', include('topics.urls', namespace = 'topics')),
  33 + url(r'^chat/', include('chat.urls', namespace = 'chat')),
33 34 url(r'^mural/', include('mural.urls', namespace = 'mural')),
34 35 url(r'^webpages/', include('webpage.urls', namespace = 'webpages')),
35 36 url(r'^ytvideo/', include('youtube_video.urls', namespace = 'youtube')),
... ...
chat/__init__.py 0 → 100644
chat/admin.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.contrib import admin
  2 +
  3 +# Register your models here.
... ...
chat/apps.py 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +from django.apps import AppConfig
  2 +
  3 +
  4 +class ChatConfig(AppConfig):
  5 + name = 'chat'
... ...
chat/migrations/0001_initial.py 0 → 100644
... ... @@ -0,0 +1,128 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-03-10 22:13
  3 +from __future__ import unicode_literals
  4 +
  5 +import chat.models
  6 +from django.conf import settings
  7 +from django.db import migrations, models
  8 +import django.db.models.deletion
  9 +
  10 +
  11 +class Migration(migrations.Migration):
  12 +
  13 + initial = True
  14 +
  15 + dependencies = [
  16 + ('subjects', '0014_auto_20170130_1828'),
  17 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  18 + ('categories', '0014_auto_20170224_0023'),
  19 + ]
  20 +
  21 + operations = [
  22 + migrations.CreateModel(
  23 + name='ChatFavorites',
  24 + fields=[
  25 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  26 + ],
  27 + ),
  28 + migrations.CreateModel(
  29 + name='ChatVisualizations',
  30 + fields=[
  31 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  32 + ('viewed', models.BooleanField(default=False, verbose_name='Viewed')),
  33 + ('date_viewed', models.DateTimeField(blank=True, null=True, verbose_name='Date/Time Viewed')),
  34 + ],
  35 + ),
  36 + migrations.CreateModel(
  37 + name='Conversation',
  38 + fields=[
  39 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  40 + ('_my_subclass', models.CharField(max_length=200)),
  41 + ],
  42 + options={
  43 + 'abstract': False,
  44 + },
  45 + ),
  46 + migrations.CreateModel(
  47 + name='TalkMessages',
  48 + fields=[
  49 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  50 + ('text', models.TextField(blank=True, verbose_name='Comment')),
  51 + ('image', models.ImageField(blank=True, null=True, upload_to=chat.models.upload_filename, validators=[chat.models.validate_img_extension], verbose_name='Image')),
  52 + ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Create Date')),
  53 + ],
  54 + ),
  55 + migrations.CreateModel(
  56 + name='CategoryTalk',
  57 + fields=[
  58 + ('conversation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='chat.Conversation')),
  59 + ('space', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='talk_category', to='categories.Category', verbose_name='Category')),
  60 + ],
  61 + options={
  62 + 'abstract': False,
  63 + },
  64 + bases=('chat.conversation',),
  65 + ),
  66 + migrations.CreateModel(
  67 + name='GeneralTalk',
  68 + fields=[
  69 + ('conversation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='chat.Conversation')),
  70 + ('space', models.IntegerField(blank=True, default=0, verbose_name='Space')),
  71 + ],
  72 + options={
  73 + 'abstract': False,
  74 + },
  75 + bases=('chat.conversation',),
  76 + ),
  77 + migrations.CreateModel(
  78 + name='SubjectTalk',
  79 + fields=[
  80 + ('conversation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='chat.Conversation')),
  81 + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='talk_subject', to='subjects.Subject', verbose_name='Subject')),
  82 + ],
  83 + options={
  84 + 'abstract': False,
  85 + },
  86 + bases=('chat.conversation',),
  87 + ),
  88 + migrations.AddField(
  89 + model_name='talkmessages',
  90 + name='talk',
  91 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='message_talk', to='chat.Conversation', verbose_name='Conversation'),
  92 + ),
  93 + migrations.AddField(
  94 + model_name='talkmessages',
  95 + name='user',
  96 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='message_user', to=settings.AUTH_USER_MODEL, verbose_name='User'),
  97 + ),
  98 + migrations.AddField(
  99 + model_name='conversation',
  100 + name='user_one',
  101 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='talk_user_start', to=settings.AUTH_USER_MODEL, verbose_name='User One'),
  102 + ),
  103 + migrations.AddField(
  104 + model_name='conversation',
  105 + name='user_two',
  106 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='talk_user_end', to=settings.AUTH_USER_MODEL, verbose_name='User Two'),
  107 + ),
  108 + migrations.AddField(
  109 + model_name='chatvisualizations',
  110 + name='message',
  111 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chat_visualization_message', to='chat.TalkMessages', verbose_name='Message'),
  112 + ),
  113 + migrations.AddField(
  114 + model_name='chatvisualizations',
  115 + name='user',
  116 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chat_visualization_user', to=settings.AUTH_USER_MODEL, verbose_name='User'),
  117 + ),
  118 + migrations.AddField(
  119 + model_name='chatfavorites',
  120 + name='message',
  121 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chat_favorites_message', to='chat.TalkMessages', verbose_name='Message'),
  122 + ),
  123 + migrations.AddField(
  124 + model_name='chatfavorites',
  125 + name='user',
  126 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chat_favorites_user', to=settings.AUTH_USER_MODEL, verbose_name='User'),
  127 + ),
  128 + ]
... ...
chat/migrations/__init__.py 0 → 100644
chat/models.py 0 → 100644
... ... @@ -0,0 +1,56 @@
  1 +import os
  2 +import time
  3 +from django.db import models
  4 +from django.core import validators
  5 +from django.core.exceptions import ValidationError
  6 +from django.utils.translation import ugettext_lazy as _
  7 +
  8 +from topics.decorators import always_as_child
  9 +
  10 +from categories.models import Category
  11 +from subjects.models import Subject
  12 +from topics.models import KnowsChild
  13 +from users.models import User
  14 +
  15 +def validate_img_extension(value):
  16 + valid_formats = ['image/jpeg','image/x-citrix-jpeg','image/png','image/x-citrix-png','image/x-png','image/gif']
  17 +
  18 + if hasattr(value.file, 'content_type'):
  19 + if not value.file.content_type in valid_formats:
  20 + raise ValidationError(_('File not supported.'))
  21 +
  22 +def upload_filename(instance, filename):
  23 + path = "chat/"
  24 + filename = str(int(time.time())) + "_" + filename
  25 +
  26 + return os.path.join(path, filename)
  27 +
  28 +class Conversation(KnowsChild):
  29 + user_one = models.ForeignKey(User, verbose_name = _('User One'), related_name = 'talk_user_start')
  30 + user_two = models.ForeignKey(User, verbose_name = _('User Two'), related_name = 'talk_user_end')
  31 +
  32 +class GeneralTalk(Conversation):
  33 + space = models.IntegerField(_('Space'), default = 0, blank = True)
  34 +
  35 +class CategoryTalk(Conversation):
  36 + space = models.ForeignKey(Category, verbose_name = ('Category'), related_name = 'talk_category', null = True)
  37 +
  38 +class SubjectTalk(Conversation):
  39 + space = models.ForeignKey(Subject, verbose_name = _('Subject'), related_name = 'talk_subject')
  40 +
  41 +class TalkMessages(models.Model):
  42 + text = models.TextField(_('Comment'), blank = True)
  43 + image = models.ImageField(verbose_name = _('Image'), null=True, blank = True, upload_to = upload_filename, validators = [validate_img_extension])
  44 + talk = models.ForeignKey(Conversation, verbose_name = _('Conversation'), related_name = 'message_talk')
  45 + user = models.ForeignKey(User, verbose_name = _('User'), related_name = 'message_user')
  46 + create_date = models.DateTimeField(_('Create Date'), auto_now_add = True)
  47 +
  48 +class ChatVisualizations(models.Model):
  49 + viewed = models.BooleanField(_('Viewed'), default = False)
  50 + message = models.ForeignKey(TalkMessages, verbose_name = _('Message'), related_name = 'chat_visualization_message', null = True)
  51 + user = models.ForeignKey(User, verbose_name = _('User'), related_name = "chat_visualization_user", null = True)
  52 + date_viewed = models.DateTimeField(_('Date/Time Viewed'), null = True, blank = True)
  53 +
  54 +class ChatFavorites(models.Model):
  55 + message = models.ForeignKey(TalkMessages, verbose_name = _('Message'), related_name = 'chat_favorites_message', null = True)
  56 + user = models.ForeignKey(User, verbose_name = _('User'), related_name = "chat_favorites_user", null = True)
0 57 \ No newline at end of file
... ...
chat/templates/chat/_view_participant.html 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +{% load i18n chat_tags %}
  2 +
  3 +<div class="col-md-12 participant panel">
  4 + <div class="col-md-1 user-img">
  5 + <img src="{{ participant.image_url }}" class="img-responsive" />
  6 + </div>
  7 + <div class="col-md-6 user-info">
  8 + <h4><div class="status {{ participant|is_online:online_users }}"></div> {{ participant }}</h4>
  9 + </div>
  10 + <div class="col-md-4 buttons pull-right text-center">
  11 + <a href="" class="btn btn-raised btn-default">{% trans 'See Profile' %}</a>
  12 + <a href="" class="btn btn-raised btn-success">{% trans 'Send Message' %}</a>
  13 + </div>
  14 +</div>
... ...
chat/templates/chat/list.html 0 → 100644
... ... @@ -0,0 +1,67 @@
  1 +{% extends 'base.html' %}
  2 +
  3 +{% load static i18n pagination %}
  4 +{% load django_bootstrap_breadcrumbs %}
  5 +
  6 +{% block breadcrumbs %}
  7 + {{ block.super }}
  8 +
  9 + {% trans 'Messages General' as general %}
  10 +
  11 + {% breadcrumb general 'chat:manage_general' %}
  12 +{% endblock %}
  13 +
  14 +{% block content %}
  15 + <div id="core-subjects-options-div">
  16 + <ul class="core-subjects-options mural-tabs">
  17 + <a href="{% url 'chat:manage_general' %}"><li data-chat="general" class="active">{% trans "General" %} (<span>{{ totals.general }}</span>)</li></a>
  18 + <a href=""><li data-chat="categories">{% trans "Per Category" %} (<span>{{ totals.category }}</span>)</li></a>
  19 + <a href=""><li data-chat="subjects">{% trans "Per Subject" %} (<span>{{ totals.subject }}</span>)</li></a>
  20 + </ul>
  21 + </div>
  22 +
  23 + <div class="col-md-12 cards-content">
  24 + <div class="row">
  25 + <div class="col-md-12 col-sm-12 col-xs-12">
  26 + <div class="panel panel-default">
  27 + <div class="panel-body">
  28 + <div class="col-md-8">
  29 + <form action="" method="GET" class="form-horizontal">
  30 + <div class="form-group">
  31 + <div class="col-md-11 col-sm-11 col-xs-11">
  32 + <input type="text" class="form-control" name="search" placeholder="{% trans 'Search...' %}" />
  33 + </div>
  34 + <div class="col-md-1 col-sm-1 col-xs-1">
  35 + <button type="submit" class="btn btn-fab btn-fab-mini">
  36 + <i class="fa fa-search"></i>
  37 + </button>
  38 + </div>
  39 + </div>
  40 + </form>
  41 + </div>
  42 + <div class="col-md-4">
  43 + <a href="{% url 'chat:participants_general' %}" class="pull-right btn btn-default btn-raised btn-md">{% trans 'List all participants' %}</a>
  44 + </div>
  45 + </div>
  46 + </div>
  47 +
  48 + {% if conversations.count > 0 %}
  49 + <div class="panel panel-info panel-body">
  50 + <h2 class="my-subjects-title"><b>{% trans 'Conversations' %}</b></h2>
  51 +
  52 + {% for chat in conversations %}
  53 + {% include 'chat/_view.html' %}
  54 + {% endfor %}
  55 + </div>
  56 + {% else %}
  57 + <div class="text-center no-subjects">
  58 + <i class="fa fa-envelope-o"></i>
  59 + <h4>{% trans 'You do not posses messages in this space yet.' %}</h4>
  60 + </div>
  61 + {% endif %}
  62 + </div>
  63 + </div>
  64 + </div>
  65 +
  66 + <div class="modal fade" id="post-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
  67 + {% endblock %}
0 68 \ No newline at end of file
... ...
chat/templates/chat/list_participants.html 0 → 100644
... ... @@ -0,0 +1,75 @@
  1 +{% extends 'base.html' %}
  2 +
  3 +{% load static i18n pagination chat_tags %}
  4 +{% load django_bootstrap_breadcrumbs %}
  5 +
  6 +{% block breadcrumbs %}
  7 + {{ block.super }}
  8 +
  9 + {% trans 'Messages General' as general %}
  10 + {% trans 'Participants' as participants_bread %}
  11 +
  12 + {% breadcrumb general 'chat:manage_general' %}
  13 + {% breadcrumb participants_bread 'chat:participants_general' %}
  14 +{% endblock %}
  15 +
  16 +{% block content %}
  17 + {% users_online as online_users %}
  18 +
  19 + <div id="core-subjects-options-div">
  20 + <ul class="core-subjects-options mural-tabs">
  21 + <a href="{% url 'chat:manage_general' %}"><li data-chat="general" class="active">{% trans "General" %} (<span>{{ totals.general }}</span>)</li></a>
  22 + <a href=""><li data-chat="categories">{% trans "Per Category" %} (<span>{{ totals.category }}</span>)</li></a>
  23 + <a href=""><li data-chat="subjects">{% trans "Per Subject" %} (<span>{{ totals.subject }}</span>)</li></a>
  24 + </ul>
  25 + </div>
  26 +
  27 + <div class="col-md-12 cards-content">
  28 + <div class="row">
  29 + <div class="col-md-12 col-sm-12 col-xs-12">
  30 + <div class="panel panel-default">
  31 + <div class="panel-body">
  32 + <div class="col-md-8">
  33 + <form action="" method="GET" class="form-horizontal">
  34 + <div class="form-group">
  35 + <div class="col-md-11 col-sm-11 col-xs-11">
  36 + <input type="text" class="form-control" name="search" placeholder="{% trans 'Search...' %}" />
  37 + </div>
  38 + <div class="col-md-1 col-sm-1 col-xs-1">
  39 + <button type="submit" class="btn btn-fab btn-fab-mini">
  40 + <i class="fa fa-search"></i>
  41 + </button>
  42 + </div>
  43 + </div>
  44 + </form>
  45 + </div>
  46 + <div class="col-md-4">
  47 + <a href="{% url 'chat:participants_general' %}" class="pull-right btn btn-default btn-raised btn-md">{% trans 'List all participants' %}</a>
  48 + </div>
  49 + </div>
  50 + </div>
  51 +
  52 + {% if participants.count > 0 %}
  53 + <div class="panel category-panel-content panel-body">
  54 + <h2 class="my-subjects-title"><b>{% trans 'Participants' %}</b></h2>
  55 +
  56 + <div class="participants-group">
  57 + {% for participant in participants %}
  58 + {% include 'chat/_view_participant.html' %}
  59 + {% endfor %}
  60 + </div>
  61 +
  62 + {% pagination request paginator page_obj %}
  63 + </div>
  64 + {% else %}
  65 + <div class="text-center no-subjects">
  66 + <i class="fa fa-envelope-o"></i>
  67 + <h4>{% trans 'There is no other participants in this space yet.' %}</h4>
  68 + </div>
  69 + {% endif %}
  70 + </div>
  71 + </div>
  72 + </div>
  73 +
  74 + <div class="modal fade" id="post-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
  75 + {% endblock %}
0 76 \ No newline at end of file
... ...
chat/templatetags/__init__.py 0 → 100644
chat/templatetags/chat_tags.py 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +from django import template
  2 +from django.utils import timezone
  3 +from django.contrib.sessions.models import Session
  4 +
  5 +register = template.Library()
  6 +
  7 +@register.assignment_tag
  8 +def users_online():
  9 + sessions = Session.objects.filter(expire_date__gte = timezone.now())
  10 +
  11 + uid_list = []
  12 +
  13 + # Build a list of user ids from that query
  14 + for session in sessions:
  15 + data = session.get_decoded()
  16 + uid_list.append(data.get('_auth_user_id', None))
  17 +
  18 + return uid_list
  19 +
  20 +@register.filter(name = 'is_online')
  21 +def is_online(user, online_list):
  22 + if str(user.id) in online_list:
  23 + print(str(user.id) in online_list)
  24 + return "active"
  25 +
  26 + return ""
0 27 \ No newline at end of file
... ...
chat/tests.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.test import TestCase
  2 +
  3 +# Create your tests here.
... ...
chat/urls.py 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +from django.conf.urls import url
  2 +from . import views
  3 +
  4 +urlpatterns = [
  5 + url(r'^$', views.GeneralIndex.as_view(), name='manage_general'),
  6 + url(r'^participants/$', views.GeneralParticipants.as_view(), name='participants_general'),
  7 +]
0 8 \ No newline at end of file
... ...
chat/views.py 0 → 100644
... ... @@ -0,0 +1,76 @@
  1 +from django.shortcuts import get_object_or_404, redirect, render
  2 +from django.core.paginator import Paginator, EmptyPage
  3 +from django.http import Http404
  4 +from django.views import generic
  5 +from django.contrib import messages
  6 +from django.http import JsonResponse
  7 +from django.template.loader import render_to_string
  8 +from django.core.urlresolvers import reverse, reverse_lazy
  9 +from django.utils.translation import ugettext_lazy as _
  10 +from django.contrib.auth.mixins import LoginRequiredMixin
  11 +from django.db.models import Q
  12 +
  13 +from users.models import User
  14 +
  15 +from .models import Conversation, ChatVisualizations
  16 +
  17 +class GeneralIndex(LoginRequiredMixin, generic.ListView):
  18 + login_url = reverse_lazy("users:login")
  19 + redirect_field_name = 'next'
  20 +
  21 + template_name = 'chat/list.html'
  22 + context_object_name = "conversations"
  23 + paginate_by = 10
  24 +
  25 + totals = {}
  26 +
  27 + def get_queryset(self):
  28 + user = self.request.user
  29 + page = self.request.GET.get('page', False)
  30 +
  31 + conversations = Conversation.objects.filter(Q(user_one = user) | Q(user_two = user))
  32 +
  33 + self.totals['general'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__generaltalk__isnull = False).count()
  34 + self.totals['category'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__categorytalk__isnull = False).count()
  35 + self.totals['subject'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__subjecttalk__isnull = False).count()
  36 +
  37 + return conversations
  38 +
  39 + def get_context_data(self, **kwargs):
  40 + context = super(GeneralIndex, self).get_context_data(**kwargs)
  41 +
  42 + context['title'] = _('Messages')
  43 + context['totals'] = self.totals
  44 + context['chat_menu_active'] = 'subjects_menu_active'
  45 +
  46 + return context
  47 +
  48 +class GeneralParticipants(LoginRequiredMixin, generic.ListView):
  49 + login_url = reverse_lazy("users:login")
  50 + redirect_field_name = 'next'
  51 +
  52 + template_name = 'chat/list_participants.html'
  53 + context_object_name = "participants"
  54 + paginate_by = 10
  55 +
  56 + totals = {}
  57 +
  58 + def get_queryset(self):
  59 + user = self.request.user
  60 +
  61 + users = User.objects.all().exclude(id = user.id)
  62 +
  63 + self.totals['general'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__generaltalk__isnull = False).count()
  64 + self.totals['category'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__categorytalk__isnull = False).count()
  65 + self.totals['subject'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__subjecttalk__isnull = False).count()
  66 +
  67 + return users
  68 +
  69 + def get_context_data(self, **kwargs):
  70 + context = super(GeneralParticipants, self).get_context_data(**kwargs)
  71 +
  72 + context['title'] = _('Messages - Participants')
  73 + context['totals'] = self.totals
  74 + context['chat_menu_active'] = 'subjects_menu_active'
  75 +
  76 + return context
0 77 \ No newline at end of file
... ...
reports/forms.py
... ... @@ -2,8 +2,36 @@ from django import forms
2 2 from django.utils.translation import ugettext_lazy as _
3 3 import datetime
4 4  
  5 +from django.forms.formsets import BaseFormSet
5 6  
6 7  
  8 +class BaseResourceAndTagFormset(BaseFormSet):
  9 + def clean(self):
  10 + """
  11 + Adds validation to check that no two links have the same anchor or URL
  12 + and that all links have both an anchor and URL.
  13 + """
  14 + print("here 2")
  15 + print(self.errors)
  16 + if any(self.errors):
  17 + return
  18 +
  19 + for form in self.forms:
  20 + print(form)
  21 +
  22 +class ResourceAndTagForm(forms.Form):
  23 +
  24 + resource = forms.ChoiceField(label=_("Kind Of Resource"), required=True)
  25 + tag = forms.ChoiceField(label=_('Tag'), required=True)
  26 +
  27 + def __init__(self, *args, **kwargs):
  28 + super(ResourceAndTagForm, self).__init__(*args, **kwargs)
  29 + if kwargs.get('initial'):
  30 + initial = kwargs['initial']
  31 + self.fields['resource'].choices = [(classes.__name__, classes.__name__) for classes in initial['class_name']]
  32 + self.fields['tag'].choices = [(tag.id, tag.name) for tag in initial['tag']]
  33 +
  34 +
7 35 class CreateInteractionReportForm(forms.Form):
8 36 topic = forms.ChoiceField( label= _("Topics to select data from"))
9 37 init_date = forms.DateField()
... ... @@ -17,21 +45,29 @@ class CreateInteractionReportForm(forms.Form):
17 45  
18 46 def __init__(self, *args, **kwargs):
19 47 super(CreateInteractionReportForm, self).__init__(*args, **kwargs)
20   -
21 48 initial = kwargs['initial']
22 49 topics = list(initial['topic'])
23 50 self.subject = initial['subject'] #so we can check date cleaned data
24 51 self.fields['topic'].choices = [(topic.id, topic.name) for topic in topics]
25 52 self.fields['topic'].choices.append((_("All"), _("All")))
26 53  
  54 +
  55 + def clean(self):
  56 + cleaned_data = super(CreateInteractionReportForm, self).clean()
  57 + init_date = cleaned_data.get("init_date")
  58 + end_date = cleaned_data.get("end_date")
  59 + if init_date and end_date:
  60 + if init_date > end_date:
  61 + raise forms.ValidationError(_("The initial date can't be after the end one."))
  62 +
27 63 def clean_init_date(self):
28   - init_date = self.cleaned_data.get('init_date')
  64 + init_date = self.cleaned_data['init_date']
29 65 if init_date < self.subject.init_date:
30 66 self._errors['init_date'] = [_('This date should be right or after ' + str(self.subject.init_date) + ', which is when the subject started. ')]
31 67 return init_date
32 68  
33 69 def clean_end_date(self):
34   - end_date = self.cleaned_data.get('init_date')
35   - if end_date > self.subject.init_date:
36   - self._errors['end_date'] = [_('This date should be right or before ' + str(self.subject.init_date) + ', which is when the subject finishes. ')]
  70 + end_date = self.cleaned_data['end_date']
  71 + if end_date > self.subject.end_date:
  72 + self._errors['end_date'] = [_('This date should be right or before ' + str(self.subject.end_date) + ', which is when the subject finishes. ')]
37 73 return end_date
38 74 \ No newline at end of file
... ...
reports/static/reports/js/report.js 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +
  2 +//Function to get all resources of all topics related to that subjct
  3 +$(function (){
  4 +
  5 +});
0 6 \ No newline at end of file
... ...
reports/templates/reports/_form.html
1 1 {% load widget_tweaks static i18n %}
2 2  
3 3 <form action="" method="post">{% csrf_token %}
4   - {% for field in form %}
5   - {% if field.auto_id == 'id_init_date' or field.auto_id == 'id_end_date' %}
6   - <label> {{field.label}} </label>
7   - {% render_field field class='form-control date-picker' %}
8   -
9   - {% else %}
10   - <label> {{field.label}} </label>
11   - {% render_field field class='form-control' %}
12   - {% endif %}
13   -
14   - {% if field.errors %}
15   - <div class="row">
16   - </br>
17   - <div class="alert alert-danger alert-dismissible" role="alert">
18   - <button type="button" class="close" data-dismiss="alert" aria-label="Close">
19   - <span aria-hidden="true">&times;</span>
20   - </button>
21   - <ul>
22   - {% for error in field.errors %}
23   - <li>{{ error }}</li>
24   - {% endfor %}
25   - </ul>
26   - </div>
  4 + <p>{% trans "General Parameters" %}</p><hr>
  5 + {% if form.errors %}
  6 + <div class="alert alert-danger alert-dismissible" role="alert">
  7 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  8 + <span aria-hidden="true">&times;</span>
  9 + </button>
  10 + <ul>
  11 + {% for key, message in form.errors.items %}
  12 + <li>{{message}}</li>
  13 + {% endfor %}
  14 + </ul>
27 15 </div>
28 16 {% endif %}
  17 + {% for field in form %}
  18 +
  19 +
  20 + {% if field.auto_id == 'id_init_date' or field.auto_id == 'id_end_date' %}
  21 + <label> {{field.label}} </label>
  22 + {% render_field field class='form-control date-picker' %}
  23 +
  24 +
  25 + {% elif field.auto_id == 'id_from_mural' %}
  26 + <p>{% trans "Data Source" %}</p><hr>
  27 + <label> {{field.label}} </label>
  28 + {% render_field field class='form-control' %}
  29 + {% else %}
  30 + <label> {{field.label}} </label>
  31 + {% render_field field class='form-control' %}
  32 + {% endif %}
  33 +
  34 + {% if field.errors %}
  35 + <div class="row">
  36 + </br>
  37 + <div class="alert alert-danger alert-dismissible" role="alert">
  38 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  39 + <span aria-hidden="true">&times;</span>
  40 + </button>
  41 + <ul>
  42 + {% for error in field.errors %}
  43 + <li>{{ error }}</li>
  44 + {% endfor %}
  45 + </ul>
  46 + </div>
  47 + </div>
  48 + {% endif %}
29 49 {% endfor %}
  50 +
  51 + <!---Adding the selector -->
  52 + <div class="panel-group" id="resources_accordion" role="tablist" aria-multiselectable="true">
  53 + <div class="panel panel-info">
  54 + <div class="panel-heading">
  55 + <div class="row">
  56 + <div class="col-md-12">
  57 + <a data-parent="#resources_accordion" data-toggle="collapse" href="#resources">
  58 + <h4 class="panel-title">
  59 + <button class="btn btn-default btn-xs text-center cat-selector"><i class="fa fa-angle-right fa-2x" aria-hidden="true"></i></button><label for="resources">{% trans "Interaction with resources" %}</label>
  60 + </h4>
  61 + </a>
  62 + </div>
  63 + </div>
  64 + </div>
  65 +
  66 + <div id="resources" class="panel-collapse collapse">
  67 + {{ resource_tag_formset.management_form }}
  68 +
  69 +
  70 + {% for resource_tag_form in resource_tag_formset %}
  71 +
  72 + {% if resource_tag_form.anchor.errors %}
  73 + {% for error in resource_tag_form.anchor.errors %}
  74 + {{ error|escape }}
  75 + {% endfor %}
  76 + {% endif %}
  77 + <div class="resource-tag-formset">
  78 + {% for field in resource_tag_form %}
  79 + <label>{{field.label}}</label>
  80 + {% render_field field class="form-control" %}
  81 +
  82 +
  83 + {% endfor %}
  84 + </div>
  85 + {% endfor %}
  86 + </div>
  87 + </div>
  88 + </div>
  89 +
30 90 <div class="row text-center">
31 91 <input type="submit" value="Search" class="btn btn-success btn-raised" />
32 92 </div>
33 93 </form>
  94 +
  95 +
... ...
reports/templates/reports/create.html
... ... @@ -11,6 +11,12 @@
11 11 {% breadcrumb 'analytics' '' %}
12 12 {% endblock %}
13 13  
  14 +{% block javascript %}
  15 + {{block.super}}
  16 + <script type="text/javascript" src="{% static "js/jquery.formset.js" %} "></script>
  17 +
  18 +{% endblock javascript %}
  19 +
14 20 {% block content %}
15 21  
16 22 <div class="panel panel-info topic-panel">
... ... @@ -41,5 +47,44 @@
41 47  
42 48 {% include "reports/_form.html" %}
43 49  
44   -
  50 + <script type="text/javascript" src="{% static "reports/js/report.js" %}"></script>
  51 + <script>
  52 +
  53 +
  54 + $('.resource-tag-formset').formset({
  55 + addText: 'add data source',
  56 + deleteText: 'remove data source',
  57 + added: function(object){
  58 + $.get("{% url 'subjects:reports:get_resource_and_tags' %}?subject_id={{subject.id}}", function(data){
  59 + fields = object.children("select");
  60 +
  61 + for(var j = 0; j < data.resources.length; j++){
  62 + fields[0].options[fields[0].options.length] = new Option(data.resources[j].name,data.resources[j].id);
  63 +
  64 + }
  65 + //Set initial tag options
  66 + var form_topic = $("select#id_topic :selected").filter(":selected").val(); //get user selected topic option
  67 + $.get("{% url 'subjects:reports:get_tags' %}?resource_class_name="+fields[0].value+"&subject_id={{subject.id}}"+"&topic_choice="+form_topic, function(data){
  68 + fields[1].options.length = 0;
  69 + for(var j = 0; j < data.tags.length; j++){
  70 + fields[1].options[fields[1].options.length] = new Option(data.tags[j].name,data.tags[j].id);
  71 + }
  72 + });
  73 +
  74 + //Modify tags fields - on resource type value modifies
  75 + fields[0].onchange = function(item){
  76 + //it request all tags associated with that resource
  77 + var form_topic = $("select#id_topic :selected").filter(":selected").val(); //get user selected topic option
  78 +
  79 + $.get("{% url 'subjects:reports:get_tags' %}?resource_class_name="+item.target.value+"&"+"subject_id={{subject.id}}"+"&topic_choice="+form_topic, function(data){
  80 + fields[1].options.length = 0;
  81 + for(var j = 0; j < data.tags.length; j++){
  82 + fields[1].options[fields[1].options.length] = new Option(data.tags[j].name,data.tags[j].id);
  83 + }
  84 + });
  85 + };
  86 + });
  87 + },
  88 + });
  89 + </script>
45 90 {% endblock content %}
46 91 \ No newline at end of file
... ...
reports/templates/reports/view.html
... ... @@ -6,9 +6,9 @@
6 6  
7 7 {% block breadcrumbs %}
8 8 {{ block.super }}
9   - {% breadcrumb view.subject.category 'subjects:cat_view' view.subject.category.slug %}
10   - {% breadcrumb view.subject 'subjects:view' view.subject.slug %}
11   - {% breadcrumb 'analytics' '' %}
  9 + {% breadcrumb subject.category 'subjects:cat_view' subject.category.slug %}
  10 + {% breadcrumb subject 'subjects:view' subject.slug %}
  11 + {% breadcrumb 'Analytics' '' %}
12 12 {% endblock %}
13 13  
14 14 {% block content %}
... ... @@ -65,10 +65,6 @@
65 65 <ul id="report-info">
66 66 <li> {{data.values|length}} {% trans "register(s)" %} </li>
67 67 <li>
68   - <i class="fa fa-download" aria-hidden="true"></i> {% trans "Variable Descriptions" %}
69   -
70   - </li>
71   - <li>
72 68 <i class="fa fa-download" aria-hidden="true"></i> {% trans "Interactions Data" %}
73 69 </li>
74 70 </ul>
... ...
reports/urls.py
... ... @@ -5,4 +5,6 @@ from . import views
5 5 urlpatterns = [
6 6 url(r'^create/interactions/$', views.ReportView.as_view(), name='create_interaction'),
7 7 url(r'^view/interactions/$', views.ViewReportView.as_view(), name='view_report'),
  8 + url(r'^get/resources/$', views.get_resources, name='get_resource_and_tags'),
  9 + url(r'^get/tags/$', views.get_tags, name='get_tags'),
8 10 ]
9 11 \ No newline at end of file
... ...
reports/views.py
... ... @@ -13,9 +13,11 @@ from django.db.models import Q
13 13 from django.contrib.auth.mixins import LoginRequiredMixin
14 14 from datetime import datetime, date
15 15 from subjects.models import Subject
16   -from .forms import CreateInteractionReportForm
  16 +from .forms import CreateInteractionReportForm, ResourceAndTagForm, BaseResourceAndTagFormset
17 17 from log.models import Log
  18 +from topics.models import Resource, Topic
18 19  
  20 +from django.forms import formset_factory
19 21  
20 22 class ReportView(LoginRequiredMixin, generic.FormView):
21 23 template_name = "reports/create.html"
... ... @@ -40,7 +42,24 @@ class ReportView(LoginRequiredMixin, generic.FormView):
40 42 subject = Subject.objects.get(id=self.request.GET['subject_id'])
41 43  
42 44 context['subject'] = subject
43   -
  45 +
  46 + topics = subject.topic_subject.all()
  47 + #get all resources associated with topics
  48 + tags = []
  49 + for topic in topics:
  50 + resources_set = topic.resource_topic.all()
  51 + for resource in resources_set:
  52 + for tag in resource.tags.all():
  53 + tags.append(tag)
  54 +
  55 +
  56 + classes = Resource.__subclasses__()
  57 +
  58 +
  59 + #set formset
  60 + resourceTagFormSet = formset_factory(ResourceAndTagForm, formset=BaseResourceAndTagFormset)
  61 + resourceTagFormSet = resourceTagFormSet(initial=[{'class_name': classes, 'tag':tags}])
  62 + context['resource_tag_formset'] = resourceTagFormSet
44 63 return context
45 64  
46 65 def get_success_url(self):
... ... @@ -53,6 +72,10 @@ class ReportView(LoginRequiredMixin, generic.FormView):
53 72 get_params += key + "=" + str(value) + "&"
54 73  
55 74  
  75 + for form_data in self.formset_data:
  76 + for key, value in form_data.items():
  77 + get_params += key + "=" + str(value) + "&"
  78 +
56 79 #retrieving subject id for data purposes
57 80 for key, value in self.request.GET.items():
58 81 get_params += key + "=" + str(value)
... ... @@ -65,9 +88,30 @@ class ReportView(LoginRequiredMixin, generic.FormView):
65 88 POST variables and then checked for validity.
66 89 """
67 90 form = self.get_form()
68   - if form.is_valid():
69 91  
  92 + subject = Subject.objects.get(id=self.request.GET['subject_id'])
  93 +
  94 + topics = subject.topic_subject.all()
  95 + #get all resources associated with topics
  96 + tags = []
  97 + for topic in topics:
  98 + resources_set = topic.resource_topic.all()
  99 + for resource in resources_set:
  100 + for tag in resource.tags.all():
  101 + tags.append(tag)
  102 +
  103 + classes = Resource.__subclasses__()
  104 + amount_of_forms = self.request.POST['form-TOTAL_FORMS']
  105 + initial_datum = {'class_name': classes , 'tag': tags}
  106 + initial_data = []
  107 + for i in range(int(amount_of_forms)):
  108 + initial_data.append(initial_datum)
  109 +
  110 + resourceTagFormSet = formset_factory(ResourceAndTagForm, formset=BaseResourceAndTagFormset)
  111 + resources_formset = resourceTagFormSet(self.request.POST, initial = initial_data)
  112 + if form.is_valid() and resources_formset.is_valid():
70 113 self.form_data = form.cleaned_data
  114 + self.formset_data = resources_formset.cleaned_data
71 115 return self.form_valid(form)
72 116 else:
73 117 return self.form_invalid(form)
... ... @@ -86,6 +130,8 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView):
86 130 context['init_date'] = params_data['init_date']
87 131 context['end_date'] = params_data['end_date']
88 132 context['subject'] = subject
  133 + print(params_data)
  134 +
89 135 if params_data['from_mural']:
90 136 context['data'], context['header'] = self.get_mural_data(subject, params_data['init_date'], params_data['end_date'])
91 137 return context
... ... @@ -115,22 +161,22 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView):
115 161 create_date__range=(init_date, end_date))
116 162  
117 163 #number of help posts created by the student
118   - interactions['v01'] = help_posts_made_by_user.count()
  164 + interactions['number of help posts created by the user'] = help_posts_made_by_user.count()
119 165  
120 166 help_posts = SubjectPost.objects.filter(action="help", create_date__range=(init_date, end_date),
121 167 space__id=subject.id)
122 168  
123 169 #comments count on help posts created by the student
124   - interactions['v02'] = Comment.objects.filter(post__in = help_posts.filter(user=student),
  170 + interactions['amount of comments on help posts created by the student'] = Comment.objects.filter(post__in = help_posts.filter(user=student),
125 171 create_date__range=(init_date, end_date)).count()
126 172  
127 173  
128 174 #count the amount of comments made by the student on posts made by one of the professors
129   - interactions['v03'] = Comment.objects.filter(post__in = help_posts.filter(user__in= subject.professor.all()), create_date__range=(init_date, end_date),
  175 + interactions['amount of comments made by the student on teachers help posts'] = Comment.objects.filter(post__in = help_posts.filter(user__in= subject.professor.all()), create_date__range=(init_date, end_date),
130 176 user=student).count()
131 177  
132 178 #comments made by the user on other users posts
133   - interactions['v04'] = Comment.objects.filter(post__in = help_posts.exclude(user=student),
  179 + interactions['amount of comments made by the student on other students help posts'] = Comment.objects.filter(post__in = help_posts.exclude(user=student),
134 180 create_date__range=(init_date, end_date),
135 181 user= student).count()
136 182  
... ... @@ -141,7 +187,7 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView):
141 187 for comment in comments_by_teacher:
142 188 help_posts_ids.append(comment.post.id)
143 189 #number of help posts created by the user that the teacher commented on
144   - interactions['v05'] = help_posts.filter(user=student, id__in = help_posts_ids).count()
  190 + interactions['Number of help posts created by the user that the teacher commented on'] = help_posts.filter(user=student, id__in = help_posts_ids).count()
145 191  
146 192  
147 193 comments_by_others = Comment.objects.filter(user__in=subject.students.exclude(id = student.id))
... ... @@ -149,39 +195,78 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView):
149 195 for comment in comments_by_teacher:
150 196 help_posts_ids.append(comment.post.id)
151 197 #number of help posts created by the user others students commented on
152   - interactions['v06'] = help_posts.filter(user=student, id__in = help_posts_ids).count()
  198 + interactions['number of help posts created by the user others students commented on'] = help_posts.filter(user=student, id__in = help_posts_ids).count()
153 199  
154 200 #Number of student visualizations on the mural of the subject
155   - interactions['v07'] = MuralVisualizations.objects.filter(post__in = SubjectPost.objects.filter(space__id=subject.id),
  201 + interactions['Number of student visualizations on the mural of the subject'] = MuralVisualizations.objects.filter(post__in = SubjectPost.objects.filter(space__id=subject.id),
156 202 user = student).count()
157 203  
158 204  
  205 + #VAR08 -
  206 +
159 207 #VAR20 - number of access to mural between 6 a.m to 12a.m.
160   - interactions['v20'] = Log.objects.filter(action="access", resource="subject",
  208 + interactions[' number of access to mural between 6 a.m to 12a.m.'] = Log.objects.filter(action="access", resource="subject",
161 209 user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (5, 11)).count()
162 210  
163   - #VAR21 - number of access to mural between 6 a.m to 12a.m.
164   - interactions['v21'] = Log.objects.filter(action="access", resource="subject",
  211 + #VAR21 - number of access to mural between 0 p.m to 6p.m.
  212 + interactions['number of access to mural between 0 p.m to 6p.m.'] = Log.objects.filter(action="access", resource="subject",
165 213 user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (11, 17)).count()
166 214 #VAR22
167   - interactions['v22'] = Log.objects.filter(action="access", resource="subject",
  215 + interactions['number of access to mural between 6 p.m to 12p.m.'] = Log.objects.filter(action="access", resource="subject",
168 216 user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (17, 23)).count()
169 217  
170 218 #VAR23
171   - interactions['v23'] = Log.objects.filter(action="access", resource="subject",
  219 + interactions['number of access to mural between 0 a.m to 6a.m.'] = Log.objects.filter(action="access", resource="subject",
172 220 user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (23, 5)).count()
173 221  
174 222 #VAR24 through 30
175 223 day_numbers = [0, 1, 2, 3, 4, 5, 6]
176 224 day_names = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]
177 225 for day_num in day_numbers:
178   - interactions['v'+ str(24+day_num)] = Log.objects.filter(action="access", resource="subject",
  226 + interactions['number of access to the subject on '+ day_names[day_num]] = Log.objects.filter(action="access", resource="subject",
179 227 user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__week_day = day_num).count()
180 228  
181 229 for value in interactions.values():
182 230 data[student].append(value)
183   - if len(header) <= 1:
184   - for key in interactions.keys():
185   - header.append(key)
  231 +
  232 +
  233 + for key in interactions.keys():
  234 + header.append(key)
186 235 return data, header
187 236  
  237 +
  238 +
  239 +def get_resources(request):
  240 +
  241 + #get all possible resources
  242 + classes = Resource.__subclasses__()
  243 +
  244 + data = {}
  245 +
  246 +
  247 + data['resources']= [ {'id':class_name.__name__, 'name':class_name.__name__} for class_name in classes]
  248 + return JsonResponse(data)
  249 +
  250 +
  251 +def get_tags(request):
  252 + resource_type = request.GET['resource_class_name']
  253 + subject = Subject.objects.get(id=request.GET['subject_id'])
  254 + topic_choice = request.GET["topic_choice"]
  255 + if topic_choice.lower() == "all":
  256 + topics = subject.topic_subject.all()
  257 + else:
  258 + topics = [Topic.objects.get(id=int(topic_choice))]
  259 + data = {}
  260 + tags = []
  261 + for topic in topics:
  262 + resource_set = Resource.objects.select_related(resource_type.lower()).filter(topic = topic)
  263 +
  264 + for resource in resource_set:
  265 + if resource._my_subclass == resource_type.lower():
  266 + for tag in resource.tags.all():
  267 + tags.append(tag)
  268 +
  269 +
  270 +
  271 + data['tags'] = [ {'id':tag.id, 'name':tag.name} for tag in tags]
  272 + return JsonResponse(data)
... ...
topics/views.py
... ... @@ -57,7 +57,6 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
57 57 subject = get_object_or_404(Subject, slug = slug)
58 58  
59 59 self.object.subject = subject
60   - print (subject.topic_subject.count())
61 60 self.object.order = subject.topic_subject.count() + 1
62 61  
63 62 self.object.save()
... ...