Commit ce4a2010bb39f8c5013ddade7d5a4fbd7fae0ffa

Authored by Zambom
1 parent 68f21ee3

Refactoring chat app to remove the division in conversations between general, category and subject

amadeus/static/js/socket.js
@@ -267,30 +267,6 @@ function messageReceived(content) { @@ -267,30 +267,6 @@ function messageReceived(content) {
267 $(this).show(); 267 $(this).show();
268 }); 268 });
269 269
270 - $('.chat-tabs').find('li').each(function () {  
271 - var identity = $(this).data('chat');  
272 -  
273 - if (identity == content.subtype) {  
274 - var span = $(this).find('span'),  
275 - actual = span.text();  
276 -  
277 - actual = parseInt(actual, 10) + 1;  
278 -  
279 - span.text(actual);  
280 - }  
281 - });  
282 -  
283 - var item = $("#" + content.space);  
284 -  
285 - if (typeof(item) != "undefined") {  
286 - var span = item.parent().find('span.item_badge'),  
287 - actual = span.text();  
288 -  
289 - actual = parseInt(actual, 10) + 1;  
290 -  
291 - span.text(actual);  
292 - }  
293 -  
294 if (content.subtype == "subject") { 270 if (content.subtype == "subject") {
295 var subject_cbadge = $("#subject_" + content.space).find('.chat_notify'), 271 var subject_cbadge = $("#subject_" + content.space).find('.chat_notify'),
296 actual = subject_cbadge.text(); 272 actual = subject_cbadge.text();
categories/migrations/0015_auto_20170402_2207.py 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-04-03 01:07
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +
  7 +
  8 +class Migration(migrations.Migration):
  9 +
  10 + dependencies = [
  11 + ('categories', '0014_auto_20170224_0023'),
  12 + ]
  13 +
  14 + operations = [
  15 + migrations.AlterField(
  16 + model_name='category',
  17 + name='description',
  18 + field=models.CharField(blank=True, max_length=300, null=True, verbose_name='description'),
  19 + ),
  20 + ]
chat/migrations/0002_auto_20170402_2207.py 0 → 100644
@@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-04-03 01:07
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + dependencies = [
  13 + ('subjects', '0014_auto_20170130_1828'),
  14 + ('chat', '0001_initial'),
  15 + ]
  16 +
  17 + operations = [
  18 + migrations.RemoveField(
  19 + model_name='categorytalk',
  20 + name='conversation_ptr',
  21 + ),
  22 + migrations.RemoveField(
  23 + model_name='categorytalk',
  24 + name='space',
  25 + ),
  26 + migrations.RemoveField(
  27 + model_name='generaltalk',
  28 + name='conversation_ptr',
  29 + ),
  30 + migrations.RemoveField(
  31 + model_name='subjecttalk',
  32 + name='conversation_ptr',
  33 + ),
  34 + migrations.RemoveField(
  35 + model_name='subjecttalk',
  36 + name='space',
  37 + ),
  38 + migrations.RemoveField(
  39 + model_name='conversation',
  40 + name='_my_subclass',
  41 + ),
  42 + migrations.AddField(
  43 + model_name='talkmessages',
  44 + name='subject',
  45 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='message_subject', to='subjects.Subject', verbose_name='Subject'),
  46 + ),
  47 + migrations.AlterField(
  48 + model_name='talkmessages',
  49 + name='talk',
  50 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='message_talk', to='chat.Conversation', verbose_name='Conversation'),
  51 + ),
  52 + migrations.AlterField(
  53 + model_name='talkmessages',
  54 + name='user',
  55 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='message_user', to=settings.AUTH_USER_MODEL, verbose_name='User'),
  56 + ),
  57 + migrations.DeleteModel(
  58 + name='CategoryTalk',
  59 + ),
  60 + migrations.DeleteModel(
  61 + name='GeneralTalk',
  62 + ),
  63 + migrations.DeleteModel(
  64 + name='SubjectTalk',
  65 + ),
  66 + ]
chat/models.py
@@ -5,11 +5,7 @@ from django.core import validators @@ -5,11 +5,7 @@ from django.core import validators
5 from django.core.exceptions import ValidationError 5 from django.core.exceptions import ValidationError
6 from django.utils.translation import ugettext_lazy as _ 6 from django.utils.translation import ugettext_lazy as _
7 7
8 -from topics.decorators import always_as_child  
9 -  
10 -from categories.models import Category  
11 from subjects.models import Subject 8 from subjects.models import Subject
12 -from topics.models import KnowsChild  
13 from users.models import User 9 from users.models import User
14 10
15 def validate_img_extension(value): 11 def validate_img_extension(value):
@@ -25,24 +21,16 @@ def upload_filename(instance, filename): @@ -25,24 +21,16 @@ def upload_filename(instance, filename):
25 21
26 return os.path.join(path, filename) 22 return os.path.join(path, filename)
27 23
28 -class Conversation(KnowsChild): 24 +class Conversation(models.Model):
29 user_one = models.ForeignKey(User, verbose_name = _('User One'), related_name = 'talk_user_start') 25 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') 26 user_two = models.ForeignKey(User, verbose_name = _('User Two'), related_name = 'talk_user_end')
31 27
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', null = True)  
40 -  
41 class TalkMessages(models.Model): 28 class TalkMessages(models.Model):
42 text = models.TextField(_('Comment'), blank = True) 29 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]) 30 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', null = True) 31 talk = models.ForeignKey(Conversation, verbose_name = _('Conversation'), related_name = 'message_talk', null = True)
45 user = models.ForeignKey(User, verbose_name = _('User'), related_name = 'message_user', null = True) 32 user = models.ForeignKey(User, verbose_name = _('User'), related_name = 'message_user', null = True)
  33 + subject = models.ForeignKey(Subject, verbose_name = _('Subject'), related_name = 'message_subject', null = True)
46 create_date = models.DateTimeField(_('Create Date'), auto_now_add = True) 34 create_date = models.DateTimeField(_('Create Date'), auto_now_add = True)
47 35
48 class ChatVisualizations(models.Model): 36 class ChatVisualizations(models.Model):
chat/templates/chat/_participants.html
@@ -1,23 +0,0 @@ @@ -1,23 +0,0 @@
1 -{% load static i18n chat_tags %}  
2 -  
3 -{% if participants.count > 0 %}  
4 - <div class="panel category-panel-content panel-body">  
5 - <h2 class="my-subjects-title"><b>{% trans 'Participants' %}</b></h2>  
6 -  
7 - <div id="content-list" class="participants-group">  
8 - {% for participant in participants %}  
9 - {% include 'chat/_view_participant.html' with space=space space_type=space_type %}  
10 - {% endfor %}  
11 - </div>  
12 - <div class="col-md-12">  
13 - <div class="text-center">  
14 - <div class="holder"></div>  
15 - </div>  
16 - </div>  
17 - </div>  
18 -{% else %}  
19 - <div class="text-center no-subjects">  
20 - <i class="fa fa-envelope-o"></i>  
21 - <h4>{% trans 'There is no other participants in this space yet.' %}</h4>  
22 - </div>  
23 -{% endif %}  
24 \ No newline at end of file 0 \ No newline at end of file
chat/templates/chat/_talks_list.html
@@ -1,23 +0,0 @@ @@ -1,23 +0,0 @@
1 -{% load static i18n chat_tags %}  
2 -  
3 -{% if conversations.count > 0 %}  
4 - <div class="panel category-panel-content panel-body">  
5 - <h2 class="my-subjects-title"><b>{% trans 'Conversations' %}</b></h2>  
6 -  
7 - <div id="content-list" class="talks-group">  
8 - {% for chat in conversations %}  
9 - {% include 'chat/_view.html' with space=space space_type=space_type %}  
10 - {% endfor %}  
11 - </div>  
12 - <div class="col-md-12">  
13 - <div class="text-center">  
14 - <div class="holder"></div>  
15 - </div>  
16 - </div>  
17 - </div>  
18 -{% else %}  
19 - <div class="text-center no-subjects">  
20 - <i class="fa fa-envelope-o"></i>  
21 - <h4>{% trans 'You do not posses messages in this space yet.' %}</h4>  
22 - </div>  
23 -{% endif %}  
24 \ No newline at end of file 0 \ No newline at end of file
chat/templates/chat/list.html
@@ -6,21 +6,13 @@ @@ -6,21 +6,13 @@
6 {% block breadcrumbs %} 6 {% block breadcrumbs %}
7 {{ block.super }} 7 {{ block.super }}
8 8
9 - {% trans 'Messages General' as general %} 9 + {% trans 'Messages' as general %}
10 10
11 {% breadcrumb general 'chat:manage_general' %} 11 {% breadcrumb general 'chat:manage_general' %}
12 {% endblock %} 12 {% endblock %}
13 13
14 {% block content %} 14 {% block content %}
15 - <div id="core-subjects-options-div">  
16 - <ul class="core-subjects-options chat-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="{% url 'chat:manage_category' %}"><li data-chat="category">{% trans "Per Category" %} (<span>{{ totals.category }}</span>)</li></a>  
19 - <a href="{% url 'chat:manage_subject' %}"><li data-chat="subject">{% trans "Per Subject" %} (<span>{{ totals.subject }}</span>)</li></a>  
20 - </ul>  
21 - </div>  
22 -  
23 - <div class="col-md-12 cards-content"> 15 + <div class="col-md-12 cards-content">
24 <div class="row"> 16 <div class="row">
25 <div class="col-md-12 col-sm-12 col-xs-12"> 17 <div class="col-md-12 col-sm-12 col-xs-12">
26 <div class="panel panel-default"> 18 <div class="panel panel-default">
chat/templates/chat/list_category.html
@@ -1,110 +0,0 @@ @@ -1,110 +0,0 @@
1 -{% extends 'base.html' %}  
2 -  
3 -{% load static i18n pagination permissions_tags chat_tags %}  
4 -{% load django_bootstrap_breadcrumbs %}  
5 -  
6 -{% block breadcrumbs %}  
7 - {{ block.super }}  
8 -  
9 - {% trans 'Messages per Category' as category %}  
10 -  
11 - {% breadcrumb category 'chat:manage_category' %}  
12 -{% endblock %}  
13 -  
14 -{% block content %}  
15 - <input type="hidden" value="{% url 'chat:manage_category' %}" class="item_url">  
16 -  
17 - <div id="core-subjects-options-div">  
18 - <ul class="core-subjects-options chat-tabs">  
19 - <a href="{% url 'chat:manage_general' %}"><li data-chat="general">{% trans "General" %} (<span>{{ totals.general }}</span>)</li></a>  
20 - <a href="{% url 'chat:manage_category' %}"><li data-chat="category" class="active">{% trans "Per Category" %} (<span>{{ totals.category }}</span>)</li></a>  
21 - <a href="{% url 'chat:manage_subject' %}"><li data-chat="subject">{% trans "Per Subject" %} (<span>{{ totals.subject }}</span>)</li></a>  
22 - </ul>  
23 - </div>  
24 -  
25 - <div class="col-md-12 cards-content">  
26 - {% if categories.count > 0 %}  
27 - <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">  
28 - {% for category in categories %}  
29 - {% category_permissions request.user category as has_category_permissions %}  
30 -  
31 - {% if category.visible or has_category_permissions %}  
32 - {% if category.visible %}  
33 - <div class="panel panel-info category-panel chat-panel">  
34 - <div class="panel-heading">  
35 - {% elif has_category_permissions %}  
36 - <div class="panel special-panel">  
37 - <div class="panel-heading panel-invisible chat-panel">  
38 - {% endif %}  
39 -  
40 - <div class="row">  
41 - <div class="col-md-12 category-header">  
42 - <h4 class="panel-title">  
43 - <a class="category-course-link pull-left" data-parent="#accordion" data-toggle="collapse" href="#{{category.slug}}">  
44 - <button class="btn btn-default btn-xs text-center cat-selector"><i class="fa fa-angle-right fa-2x" aria-hidden="true"></i></button> <span class="item_name">{{ category.name }}</span> (<span class="item_badge" style="margin-left:0px">{{ category|notifies_category:request.user }}</span>)  
45 -  
46 - </a>  
47 - </h4>  
48 -  
49 - <div class="col-md-5 pull-right category-card-items">  
50 - {% if has_category_permissions %}  
51 - <a href="" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">  
52 - <i class="fa fa-ellipsis-v" aria-hidden="true"></i>  
53 - </a>  
54 - <ul class="dropdown-menu pull-right" aria-labelledby="moreActions">  
55 - {% if request.user.is_staff %}  
56 - <li><a href="{% url 'categories:replicate' category.slug %}"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i> {% trans 'Replicate' %}</a></li>  
57 - {% endif %}  
58 - <li><a href="{% url 'categories:update' category.slug %}"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i> {% trans 'Edit' %}</a></li>  
59 - <li>  
60 - <a href="javascript:delete_course.get('{% url 'categories:delete' category.slug %}?view=index','#category','#modal_course')" aria-hidden="true"><i class="fa fa-trash fa-fw" aria-hidden="true"></i> {% trans 'Remove' %}</a></li>  
61 - </ul>  
62 - {% endif %}  
63 - </div>  
64 - </div>  
65 - </div>  
66 - </div>  
67 - <div id="{{category.slug}}" class="panel-collapse panel-body collapse chat-collapse" data-url="{% url 'chat:category_talks' category.id %}" data-breadurl="{% url 'subjects:cat_view' category.slug %}" data-breadtext="{% trans 'Participants' %}">  
68 - <div class="panel panel-default">  
69 - <div class="panel-body">  
70 - <div class="col-md-8">  
71 - <form id="search-participants" action="{% url 'chat:participants_category' category.id %}" method="GET" class="form-horizontal">  
72 - <div class="form-group">  
73 - <div class="col-md-11 col-sm-11 col-xs-11">  
74 - <input type="text" class="form-control" name="search" value="{{ search }}" placeholder="{% trans 'Search...' %}" />  
75 - </div>  
76 - <div class="col-md-1 col-sm-1 col-xs-1">  
77 - <button type="submit" class="btn btn-fab btn-fab-mini">  
78 - <i class="fa fa-search"></i>  
79 - </button>  
80 - </div>  
81 - </div>  
82 - </form>  
83 - </div>  
84 - <div class="col-md-4">  
85 - <a href="{% url 'chat:participants_category' category.id %}" onclick="getParticipants($(this)); return false;" class="pull-right btn btn-default btn-raised btn-md">{% trans 'List all participants' %}</a>  
86 - </div>  
87 - </div>  
88 - </div>  
89 -  
90 - <div class="content">  
91 - </div>  
92 - </div>  
93 - </div>  
94 - {% endif %}  
95 - {% endfor %}  
96 -  
97 - {% pagination request paginator page_obj %}  
98 - </div>  
99 - {% endif %}  
100 - </div>  
101 -  
102 - <div id="modal_course"></div>  
103 -  
104 - <div class="modal fade" id="chat-modal-info" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>  
105 -  
106 - <div class="modal fade" id="chat-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>  
107 -  
108 - <script type="text/javascript" src="{% static 'js/category.js' %}"></script>  
109 - <script type="text/javascript" src="{% static 'js/chat.js' %}"></script>  
110 -{% endblock %}  
111 \ No newline at end of file 0 \ No newline at end of file
chat/templates/chat/list_participants.html
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 {% block breadcrumbs %} 6 {% block breadcrumbs %}
7 {{ block.super }} 7 {{ block.super }}
8 8
9 - {% trans 'Messages General' as general %} 9 + {% trans 'Messages' as general %}
10 {% trans 'Participants' as participants_bread %} 10 {% trans 'Participants' as participants_bread %}
11 11
12 {% breadcrumb general 'chat:manage_general' %} 12 {% breadcrumb general 'chat:manage_general' %}
@@ -14,15 +14,7 @@ @@ -14,15 +14,7 @@
14 {% endblock %} 14 {% endblock %}
15 15
16 {% block content %} 16 {% block content %}
17 - <div id="core-subjects-options-div">  
18 - <ul class="core-subjects-options mural-tabs">  
19 - <a href="{% url 'chat:manage_general' %}"><li data-chat="general" class="active">{% trans "General" %} (<span>{{ totals.general }}</span>)</li></a>  
20 - <a href="{% url 'chat:manage_category' %}"><li data-chat="categories">{% trans "Per Category" %} (<span>{{ totals.category }}</span>)</li></a>  
21 - <a href=""><li data-chat="subjects">{% trans "Per Subject" %} (<span>{{ totals.subject }}</span>)</li></a>  
22 - </ul>  
23 - </div>  
24 -  
25 - <div class="col-md-12 cards-content"> 17 + <div class="col-md-12 cards-content">
26 <div class="row"> 18 <div class="row">
27 <div class="col-md-12 col-sm-12 col-xs-12"> 19 <div class="col-md-12 col-sm-12 col-xs-12">
28 <div class="panel panel-default"> 20 <div class="panel panel-default">
chat/templates/chat/list_subject.html
@@ -1,111 +0,0 @@ @@ -1,111 +0,0 @@
1 -{% extends 'base.html' %}  
2 -  
3 -{% load static i18n pagination permissions_tags chat_tags %}  
4 -{% load django_bootstrap_breadcrumbs %}  
5 -  
6 -{% block breadcrumbs %}  
7 - {{ block.super }}  
8 -  
9 - {% trans 'Messages per Subject' as subject %}  
10 -  
11 - {% breadcrumb subject 'chat:manage_category' %}  
12 -{% endblock %}  
13 -  
14 -{% block content %}  
15 - <input type="hidden" value="{% url 'chat:manage_subject' %}" class="item_url">  
16 -  
17 - <div id="core-subjects-options-div">  
18 - <ul class="core-subjects-options chat-tabs">  
19 - <a href="{% url 'chat:manage_general' %}"><li data-chat="general">{% trans "General" %} (<span>{{ totals.general }}</span>)</li></a>  
20 - <a href="{% url 'chat:manage_category' %}"><li data-chat="category">{% trans "Per Category" %} (<span>{{ totals.category }}</span>)</li></a>  
21 - <a href="{% url 'chat:manage_subject' %}"><li data-chat="subject" class="active">{% trans "Per Subject" %} (<span>{{ totals.subject }}</span>)</li></a>  
22 - </ul>  
23 - </div>  
24 -  
25 - <div class="col-md-12 cards-content">  
26 - {% if subjects.count > 0 %}  
27 - <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">  
28 - {% for subject in subjects %}  
29 - {% subject_permissions request.user subject as has_subject_permissions %}  
30 -  
31 - {% if subject.visible or has_subject_permissions %}  
32 - {% if subject.visible %}  
33 - <div class="panel panel-info subject-panel chat-panel">  
34 - <div class="panel-heading">  
35 - {% elif has_subject_permissions %}  
36 - <div class="panel panel-info subject-panel-invisible chat-panel">  
37 - <div class="panel-heading panel-invisible">  
38 - {% endif %}  
39 - <div class="row">  
40 - <div class="col-md-12 category-header">  
41 - <h4 class="panel-title">  
42 - <a class="category-course-link pull-left" data-parent="#accordion" data-toggle="collapse" href="#{{subject.slug}}">  
43 - <button class="btn btn-default btn-xs text-center cat-selector"><i class="fa fa-angle-right fa-2x" aria-hidden="true"></i></button> <span class="item_name">{{ subject }}</span>  
44 -  
45 - (<span class="item_badge" style="margin-left:0px">{{ subject|notifies_subject:request.user }}</span>)  
46 - </a>  
47 - </h4>  
48 -  
49 - <div class="col-md-5 pull-right category-card-items">  
50 - {% if has_subject_permissions %}  
51 - <a href="" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">  
52 - <i class="fa fa-ellipsis-v" aria-hidden="true"></i>  
53 - </a>  
54 - <ul class="dropdown-menu pull-right" aria-labelledby="moreActions">  
55 - {% if request.user not in subject.professor.all %}  
56 - <li><a href="{% url 'subjects:replicate' subject.slug %}"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>{% trans 'Replicate' %}</a></li>  
57 - {% endif %}  
58 - <li><a href="{% url 'subjects:update' subject.slug %}"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>{% trans 'Edit' %}</a></li>  
59 - <li><a href="{% url 'groups:index' subject.slug %}"><i class="fa fa-group fa-fw" aria-hidden="true"></i>{% trans 'Groups' %}</a></li>  
60 - <li><a href="javascript:delete_subject.get('{% url 'subjects:delete' subject.slug %}?view=index','#subject','#modal_subject')"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp;{% trans 'Remove' %}</a></li>  
61 - </ul>  
62 - {% endif %}  
63 - </div>  
64 - </div>  
65 - </div>  
66 - </div>  
67 - <div id="{{subject.slug}}" class="panel-collapse panel-body collapse chat-collapse"data-url="{% url 'chat:subject_talks' subject.id %}" data-breadurl="{% url 'subjects:view' subject.slug %}" data-breadtext="{% trans 'Participants' %}">  
68 - <div class="panel panel-default">  
69 - <div class="panel-body">  
70 - <div class="col-md-8">  
71 - <form id="search-participants" action="{% url 'chat:participants_subject' subject.id %}?type=modal" method="GET" class="form-horizontal">  
72 - <div class="form-group">  
73 - <div class="col-md-11 col-sm-11 col-xs-11">  
74 - <input type="text" class="form-control" name="search" value="{{ search }}" placeholder="{% trans 'Search...' %}" />  
75 - </div>  
76 - <div class="col-md-1 col-sm-1 col-xs-1">  
77 - <button type="submit" class="btn btn-fab btn-fab-mini">  
78 - <i class="fa fa-search"></i>  
79 - </button>  
80 - </div>  
81 - </div>  
82 - </form>  
83 - </div>  
84 - <div class="col-md-4">  
85 - <a href="{% url 'chat:participants_subject' subject.id %}?type=modal" onclick="getParticipants($(this)); return false;" class="pull-right btn btn-default btn-raised btn-md">{% trans 'List all participants' %}</a>  
86 - </div>  
87 - </div>  
88 - </div>  
89 -  
90 - <div class="content">  
91 - </div>  
92 - </div>  
93 - </div>  
94 - {% endif %}  
95 - {% endfor %}  
96 -  
97 - {% pagination request paginator page_obj %}  
98 - </div>  
99 - {% endif %}  
100 - </div>  
101 -  
102 - <div id="modal_subject"></div>  
103 -  
104 - <div class="modal fade" id="chat-modal-info" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>  
105 -  
106 - <div class="modal fade" id="chat-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>  
107 -  
108 - <script type="text/javascript" src="{% static 'js/category.js' %}"></script>  
109 - <script type="text/javascript" src="{% static 'js/chat.js' %}"></script>  
110 - <script type="text/javascript" src="{% static 'subjects/js/modal_subject.js' %}"></script>  
111 -{% endblock %}  
112 \ No newline at end of file 0 \ No newline at end of file
chat/templatetags/chat_tags.py
1 from django import template 1 from django import template
2 from django.conf import settings 2 from django.conf import settings
3 from django.utils import timezone 3 from django.utils import timezone
4 -from django.db.models import Count, F 4 +from django.db.models import Count, F, Q
5 from django.utils.translation import ugettext_lazy as _ 5 from django.utils.translation import ugettext_lazy as _
6 from django.contrib.sessions.models import Session 6 from django.contrib.sessions.models import Session
7 7
@@ -78,14 +78,8 @@ def fav_class(message, user): @@ -78,14 +78,8 @@ def fav_class(message, user):
78 78
79 return "btn_fav" 79 return "btn_fav"
80 80
81 -@register.filter(name = 'notifies_category')  
82 -def notifies_category(category, user):  
83 - total = ChatVisualizations.objects.filter(message__talk__categorytalk__space = category, user = user, viewed = False).count()  
84 -  
85 - return total  
86 -  
87 @register.filter(name = 'notifies_subject') 81 @register.filter(name = 'notifies_subject')
88 def notifies_subject(subject, user): 82 def notifies_subject(subject, user):
89 - total = ChatVisualizations.objects.filter(message__talk__subjecttalk__space = subject, user = user, viewed = False).count() 83 + total = ChatVisualizations.objects.filter(Q(message__subject = subject, user = user, viewed = False) & (Q(user__is_staff = True) | Q(message__subject__students = user) | Q(message__subject__professor = user) | Q(message__subject__category__coordinators = user))).distinct().count()
90 84
91 return total 85 return total
92 \ No newline at end of file 86 \ No newline at end of file
@@ -3,13 +3,8 @@ from . import views @@ -3,13 +3,8 @@ from . import views
3 3
4 urlpatterns = [ 4 urlpatterns = [
5 url(r'^$', views.GeneralIndex.as_view(), name='manage_general'), 5 url(r'^$', views.GeneralIndex.as_view(), name='manage_general'),
6 - url(r'^categories/$', views.CategoryIndex.as_view(), name='manage_category'),  
7 - url(r'^subjects/$', views.SubjectIndex.as_view(), name='manage_subject'),  
8 url(r'^subject/(?P<slug>[\w_-]+)/$', views.SubjectView.as_view(), name='subject_view'), 6 url(r'^subject/(?P<slug>[\w_-]+)/$', views.SubjectView.as_view(), name='subject_view'),
9 url(r'^participants/$', views.GeneralParticipants.as_view(), name='participants_general'), 7 url(r'^participants/$', views.GeneralParticipants.as_view(), name='participants_general'),
10 - url(r'^category/talks/(?P<category>[\w_-]+)/$', views.CategoryTalks.as_view(), name='category_talks'),  
11 - url(r'^category/participants/(?P<category>[\w_-]+)/$', views.CategoryParticipants.as_view(), name='participants_category'),  
12 - url(r'^subject/talks/(?P<subject>[\w_-]+)/$', views.SubjectTalks.as_view(), name='subject_talks'),  
13 url(r'^subject/participants/(?P<subject>[\w_-]+)/$', views.SubjectParticipants.as_view(), name='participants_subject'), 8 url(r'^subject/participants/(?P<subject>[\w_-]+)/$', views.SubjectParticipants.as_view(), name='participants_subject'),
14 url(r'^render_message/([\w_-]+)/([\w_-]+)/([\w_-]+)/([\w_-]+)/([\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/$', views.render_message, name='render_message'), 9 url(r'^render_message/([\w_-]+)/([\w_-]+)/([\w_-]+)/([\w_-]+)/([\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/$', views.render_message, name='render_message'),
15 url(r'^favorite/([\w_-]+)/$', views.favorite, name='favorite'), 10 url(r'^favorite/([\w_-]+)/$', views.favorite, name='favorite'),
@@ -24,7 +24,7 @@ from categories.models import Category @@ -24,7 +24,7 @@ from categories.models import Category
24 from subjects.models import Subject 24 from subjects.models import Subject
25 from users.models import User 25 from users.models import User
26 26
27 -from .models import Conversation, GeneralTalk, CategoryTalk, SubjectTalk, TalkMessages, ChatVisualizations, ChatFavorites 27 +from .models import Conversation, TalkMessages, ChatVisualizations, ChatFavorites
28 from .forms import ChatMessageForm 28 from .forms import ChatMessageForm
29 29
30 class GeneralIndex(LoginRequiredMixin, generic.ListView): 30 class GeneralIndex(LoginRequiredMixin, generic.ListView):
@@ -40,12 +40,8 @@ class GeneralIndex(LoginRequiredMixin, generic.ListView): @@ -40,12 +40,8 @@ class GeneralIndex(LoginRequiredMixin, generic.ListView):
40 def get_queryset(self): 40 def get_queryset(self):
41 user = self.request.user 41 user = self.request.user
42 42
43 - conversations = Conversation.objects.filter((Q(user_one = user) | Q(user_two = user)) & Q(categorytalk__isnull = True) & Q(subjecttalk__isnull = True))  
44 -  
45 - self.totals['general'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__generaltalk__isnull = False).count()  
46 - self.totals['category'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__categorytalk__isnull = False).count()  
47 - self.totals['subject'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__subjecttalk__isnull = False).count()  
48 - 43 + conversations = Conversation.objects.filter((Q(user_one = user) | Q(user_two = user)))
  44 +
49 return conversations 45 return conversations
50 46
51 def get_context_data(self, **kwargs): 47 def get_context_data(self, **kwargs):
@@ -72,11 +68,7 @@ class GeneralParticipants(LoginRequiredMixin, generic.ListView): @@ -72,11 +68,7 @@ class GeneralParticipants(LoginRequiredMixin, generic.ListView):
72 search = self.request.GET.get('search', '') 68 search = self.request.GET.get('search', '')
73 69
74 users = User.objects.filter(Q(username__icontains = search) | Q(last_name__icontains = search) | Q(social_name__icontains = search) | Q(email__icontains = search)).distinct().order_by('social_name','username').exclude(email = user.email) 70 users = User.objects.filter(Q(username__icontains = search) | Q(last_name__icontains = search) | Q(social_name__icontains = search) | Q(email__icontains = search)).distinct().order_by('social_name','username').exclude(email = user.email)
75 -  
76 - self.totals['general'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__generaltalk__isnull = False).count()  
77 - self.totals['category'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__categorytalk__isnull = False).count()  
78 - self.totals['subject'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__subjecttalk__isnull = False).count()  
79 - 71 +
80 return users 72 return users
81 73
82 def get_context_data(self, **kwargs): 74 def get_context_data(self, **kwargs):
@@ -89,151 +81,13 @@ class GeneralParticipants(LoginRequiredMixin, generic.ListView): @@ -89,151 +81,13 @@ class GeneralParticipants(LoginRequiredMixin, generic.ListView):
89 81
90 return context 82 return context
91 83
92 -class CategoryIndex(LoginRequiredMixin, generic.ListView):  
93 - login_url = reverse_lazy("users:login")  
94 - redirect_field_name = 'next'  
95 -  
96 - template_name = 'chat/list_category.html'  
97 - context_object_name = "categories"  
98 - paginate_by = 10  
99 -  
100 - totals = {}  
101 -  
102 - def get_queryset(self):  
103 - user = self.request.user  
104 - page = self.request.GET.get('page', False)  
105 -  
106 - if user.is_staff:  
107 - categories = Category.objects.all()  
108 - else:  
109 - categories = Category.objects.filter(Q(coordinators__pk = user.pk) | Q(subject_category__professor__pk = user.pk) | Q(subject_category__students__pk = user.pk, visible = True)).distinct()  
110 -  
111 - self.totals['general'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__generaltalk__isnull = False).count()  
112 - self.totals['category'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__categorytalk__isnull = False).count()  
113 - self.totals['subject'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__subjecttalk__isnull = False).count()  
114 -  
115 - return categories  
116 -  
117 - def get_context_data(self, **kwargs):  
118 - context = super(CategoryIndex, self).get_context_data(**kwargs)  
119 -  
120 - context['title'] = _('Messages per Category')  
121 - context['totals'] = self.totals  
122 - context['chat_menu_active'] = 'subjects_menu_active'  
123 -  
124 - return context  
125 -  
126 -class CategoryTalks(LoginRequiredMixin, generic.ListView):  
127 - login_url = reverse_lazy("users:login")  
128 - redirect_field_name = 'next'  
129 -  
130 - template_name = 'chat/_talks_list.html'  
131 - context_object_name = "conversations"  
132 -  
133 - def get_queryset(self):  
134 - user = self.request.user  
135 - cat = self.kwargs.get('category', 0)  
136 -  
137 - conversations = CategoryTalk.objects.filter((Q(user_one = user) | Q(user_two = user)) & Q(space__id = cat))  
138 -  
139 - return conversations  
140 -  
141 - def get_context_data(self, **kwargs):  
142 - context = super(CategoryTalks, self).get_context_data(**kwargs)  
143 -  
144 - context['space'] = self.kwargs.get('category', 0)  
145 - context['space_type'] = 'category'  
146 -  
147 - return context  
148 -  
149 -class CategoryParticipants(LoginRequiredMixin, generic.ListView):  
150 - login_url = reverse_lazy("users:login")  
151 - redirect_field_name = 'next'  
152 -  
153 - template_name = 'chat/_participants.html'  
154 - context_object_name = "participants"  
155 -  
156 - def get_queryset(self):  
157 - user = self.request.user  
158 - cat = self.kwargs.get('category', 0)  
159 - search = self.request.GET.get('search', '')  
160 -  
161 - users = User.objects.filter((Q(username__icontains = search) | Q(last_name__icontains = search) | Q(social_name__icontains = search) | Q(email__icontains = search)) & (Q(is_staff = True) | Q(subject_student__category__id = cat) | Q(professors__category__id = cat) | Q(coordinators__id = cat))).distinct().order_by('social_name','username').exclude(email = user.email)  
162 -  
163 - return users  
164 -  
165 - def get_context_data(self, **kwargs):  
166 - context = super(CategoryParticipants, self).get_context_data(**kwargs)  
167 -  
168 - context['space'] = self.kwargs.get('category', 0)  
169 - context['space_type'] = 'category'  
170 -  
171 - return context  
172 -  
173 -class SubjectIndex(LoginRequiredMixin, generic.ListView):  
174 - login_url = reverse_lazy("users:login")  
175 - redirect_field_name = 'next'  
176 -  
177 - template_name = 'chat/list_subject.html'  
178 - context_object_name = "subjects"  
179 - paginate_by = 10  
180 -  
181 - totals = {}  
182 -  
183 - def get_queryset(self):  
184 - user = self.request.user  
185 - page = self.request.GET.get('page', False)  
186 -  
187 - if user.is_staff:  
188 - subjects = Subject.objects.all()  
189 - else:  
190 - subjects = Subject.objects.filter(Q(professor__pk = user.pk) | Q(students__pk = user.pk, visible = True) | Q(category__coordinators__pk = user.pk)).distinct()  
191 -  
192 - self.totals['general'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__generaltalk__isnull = False).count()  
193 - self.totals['category'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__categorytalk__isnull = False).count()  
194 - self.totals['subject'] = ChatVisualizations.objects.filter(user = user, viewed = False, message__talk__subjecttalk__isnull = False).count()  
195 -  
196 - return subjects  
197 -  
198 - def get_context_data(self, **kwargs):  
199 - context = super(SubjectIndex, self).get_context_data(**kwargs)  
200 -  
201 - context['title'] = _('Messages per Subject')  
202 - context['totals'] = self.totals  
203 - context['chat_menu_active'] = 'subjects_menu_active'  
204 -  
205 - return context  
206 -  
207 -class SubjectTalks(LoginRequiredMixin, generic.ListView):  
208 - login_url = reverse_lazy("users:login")  
209 - redirect_field_name = 'next'  
210 -  
211 - template_name = 'chat/_talks_list.html'  
212 - context_object_name = "conversations"  
213 -  
214 - def get_queryset(self):  
215 - user = self.request.user  
216 - sub = self.kwargs.get('subject', 0)  
217 -  
218 - conversations = SubjectTalk.objects.filter((Q(user_one = user) | Q(user_two = user)) & Q(space__id = sub))  
219 -  
220 - return conversations  
221 -  
222 - def get_context_data(self, **kwargs):  
223 - context = super(SubjectTalks, self).get_context_data(**kwargs)  
224 -  
225 - context['space'] = self.kwargs.get('subject', 0)  
226 - context['space_type'] = 'subject'  
227 -  
228 - return context  
229 -  
230 class SubjectParticipants(LoginRequiredMixin, generic.ListView): 84 class SubjectParticipants(LoginRequiredMixin, generic.ListView):
231 login_url = reverse_lazy("users:login") 85 login_url = reverse_lazy("users:login")
232 redirect_field_name = 'next' 86 redirect_field_name = 'next'
233 87
234 - template_name = 'chat/_participants.html' 88 + template_name = 'chat/subject_view_participants.html'
235 context_object_name = "participants" 89 context_object_name = "participants"
236 - paginate_by = None 90 + paginate_by = 10
237 91
238 def dispatch(self, request, *args,**kwargs): 92 def dispatch(self, request, *args,**kwargs):
239 typep = self.request.GET.get('type', '') 93 typep = self.request.GET.get('type', '')
@@ -253,27 +107,18 @@ class SubjectParticipants(LoginRequiredMixin, generic.ListView): @@ -253,27 +107,18 @@ class SubjectParticipants(LoginRequiredMixin, generic.ListView):
253 107
254 users = User.objects.filter((Q(username__icontains = search) | Q(last_name__icontains = search) | Q(social_name__icontains = search) | Q(email__icontains = search)) & (Q(is_staff = True) | Q(subject_student__id = sub) | Q(professors__id = sub) | Q(coordinators__subject_category__id = sub))).distinct().order_by('social_name','username').exclude(email = user.email) 108 users = User.objects.filter((Q(username__icontains = search) | Q(last_name__icontains = search) | Q(social_name__icontains = search) | Q(email__icontains = search)) & (Q(is_staff = True) | Q(subject_student__id = sub) | Q(professors__id = sub) | Q(coordinators__subject_category__id = sub))).distinct().order_by('social_name','username').exclude(email = user.email)
255 109
256 - typep = self.request.GET.get('type', '')  
257 -  
258 - if not typep == 'modal':  
259 - self.paginate_by = 10  
260 -  
261 return users 110 return users
262 111
263 def get_context_data(self, **kwargs): 112 def get_context_data(self, **kwargs):
264 context = super(SubjectParticipants, self).get_context_data(**kwargs) 113 context = super(SubjectParticipants, self).get_context_data(**kwargs)
265 114
266 - typep = self.request.GET.get('type', '')  
267 -  
268 - if not typep == 'modal':  
269 - sub = self.kwargs.get('subject', 0)  
270 - subject = get_object_or_404(Subject, id = sub)  
271 -  
272 - context['subject'] = subject  
273 - context['search'] = self.request.GET.get('search', '')  
274 - context['title'] = _('%s - Participants')%(str(subject))  
275 - self.template_name = 'chat/subject_view_participants.html' 115 + sub = self.kwargs.get('subject', 0)
  116 + subject = get_object_or_404(Subject, id = sub)
276 117
  118 + context['subject'] = subject
  119 + context['search'] = self.request.GET.get('search', '')
  120 + context['title'] = _('%s - Participants')%(str(subject))
  121 +
277 context['space'] = self.kwargs.get('subject', 0) 122 context['space'] = self.kwargs.get('subject', 0)
278 context['space_type'] = 'subject' 123 context['space_type'] = 'subject'
279 124
@@ -300,7 +145,10 @@ class SubjectView(LoginRequiredMixin, generic.ListView): @@ -300,7 +145,10 @@ class SubjectView(LoginRequiredMixin, generic.ListView):
300 slug = self.kwargs.get('slug') 145 slug = self.kwargs.get('slug')
301 subject = get_object_or_404(Subject, slug = slug) 146 subject = get_object_or_404(Subject, slug = slug)
302 147
303 - conversations = SubjectTalk.objects.filter((Q(user_one = user) | Q(user_two = user)) & Q(space = subject)) 148 + conversations = Conversation.objects.filter((Q(user_one = user) & (Q(user_two__is_staff = True) |
  149 + Q(user_two__subject_student = subject) | Q(user_two__professors = subject) | Q(user_two__coordinators__subject_category = subject))) |
  150 + (Q(user_two = user) & (Q(user_one__is_staff = True) | Q(user_one__subject_student = subject) |
  151 + Q(user_one__professors = subject) | Q(user_one__coordinators__subject_category = subject)))).distinct()
304 152
305 return conversations 153 return conversations
306 154
@@ -399,37 +247,23 @@ class SendMessage(LoginRequiredMixin, generic.edit.CreateView): @@ -399,37 +247,23 @@ class SendMessage(LoginRequiredMixin, generic.edit.CreateView):
399 space = self.kwargs.get('space', 0) 247 space = self.kwargs.get('space', 0)
400 248
401 if talk_id == "-1": 249 if talk_id == "-1":
402 - if space_type == 'general':  
403 - talk = GeneralTalk.objects.create(user_one = self.request.user, user_two = user, space = 0)  
404 - elif space_type == 'category':  
405 - cat = get_object_or_404(Category, id = space)  
406 - talk = CategoryTalk.objects.create(user_one = self.request.user, user_two = user, space = cat)  
407 - else:  
408 - sub = get_object_or_404(Subject, id = space)  
409 - talk = SubjectTalk.objects.create(user_one = self.request.user, user_two = user, space = sub) 250 + talk = Conversation.objects.create(user_one = self.request.user, user_two = user)
410 else: 251 else:
411 talk = get_object_or_404(Conversation, id = talk_id) 252 talk = get_object_or_404(Conversation, id = talk_id)
412 253
413 self.object.talk = talk 254 self.object.talk = talk
414 255
  256 + if space_type == 'subject':
  257 + self.object.subject = get_object_or_404(Subject, id = space)
  258 + space = self.object.subject.slug
  259 +
415 self.object.save() 260 self.object.save()
416 261
417 simple_notify = textwrap.shorten(strip_tags(self.object.text), width = 30, placeholder = "...") 262 simple_notify = textwrap.shorten(strip_tags(self.object.text), width = 30, placeholder = "...")
418 263
419 if self.object.image: 264 if self.object.image:
420 simple_notify += " ".join(_("[Photo]")) 265 simple_notify += " ".join(_("[Photo]"))
421 -  
422 - subclass = self.object.talk._my_subclass  
423 -  
424 - if subclass == "generaltalk":  
425 - space_type = "general"  
426 - elif subclass == "categorytalk":  
427 - space_type = "category"  
428 - space = self.object.talk.categorytalk.space.slug  
429 - else:  
430 - space_type = "subject"  
431 - space = self.object.talk.subjecttalk.space.slug  
432 - 266 +
433 notification = { 267 notification = {
434 "type": "chat", 268 "type": "chat",
435 "subtype": space_type, 269 "subtype": space_type,
subjects/templatetags/subject_counter.py
@@ -43,7 +43,7 @@ def mural_number(subject, user): @@ -43,7 +43,7 @@ def mural_number(subject, user):
43 def chat_number(subject, user): 43 def chat_number(subject, user):
44 context = {} 44 context = {}
45 45
46 - context['number'] = ChatVisualizations.objects.filter(Q(user = user) & Q(viewed = False) & Q(message__talk__subjecttalk__space = subject)).count() 46 + context['number'] = ChatVisualizations.objects.filter(Q(user = user) & Q(viewed = False) & Q(message__subject = subject) & (Q(user__is_staff = True) | Q(message__subject__students = user) | Q(message__subject__professor = user) | Q(message__subject__category__coordinators = user))).distinct().count()
47 context['custom_class'] = 'chat_notify' 47 context['custom_class'] = 'chat_notify'
48 48
49 return context 49 return context