Commit b90d2ef31afcb1647fcaefe3b6c2a5b6d5010f76

Authored by Erik Zambom
Committed by GitHub
2 parents 7f659a35 006b4402

Merge pull request #470 from amadeusproject/refactoring

Daily Update - 11_04_2017
amadeus/static/js/mural.js
... ... @@ -24,9 +24,47 @@ $(function () {
24 24 });
25 25  
26 26 postHeightLimits();
  27 + setUserDataPopover();
27 28  
28 29 });
29 30  
  31 +function setUserDataPopover() {
  32 + $('[data-toggle="popover"]').popover({
  33 + html: true,
  34 + content: function () {
  35 + return $(this).parent().find(".popover").html();
  36 + }
  37 + }).on('show.bs.popover', function (e) {
  38 + $('[data-toggle="popover"]').not(e.target).popover('hide');
  39 + }).on('shown.bs.popover', function (e) {
  40 + if($(this).is(e.target)){
  41 + var popover = $(".popover.fade.in"),
  42 + buttons = popover.parent().find('a'),
  43 + close = popover.parent().find('.close:visible');
  44 +
  45 + popover.animate({
  46 + 'max-width': '330px',
  47 + }, 0);
  48 +
  49 + popover.find('.popover-content').animate({
  50 + padding: '9px 5px',
  51 + }, 0);
  52 +
  53 + popover.find('h4').animate({
  54 + 'font-size': '16px',
  55 + }, 0);
  56 +
  57 + close.on("click", function () {
  58 + popover.popover('hide');
  59 + });
  60 +
  61 + buttons.on("click", function () {
  62 + popover.popover('hide');
  63 + })
  64 + }
  65 + });
  66 +}
  67 +
30 68 function postHeightLimits() {
31 69 $('.post-body').each(function () {
32 70 if ($(this).outerHeight() > 500) {
... ... @@ -77,6 +115,7 @@ function setPostFormSubmit(post = "") {
77 115 $('.no-subjects:visible').attr('style', 'display:none');
78 116 }
79 117  
  118 + setUserDataPopover();
80 119 setTimeout(function () { postHeightLimits() }, 100);
81 120  
82 121 $('#post-modal-form').modal('hide');
... ... @@ -325,6 +364,8 @@ function loadComments (btn) {
325 364 btn.show();
326 365  
327 366 btn.after(response.loaded);
  367 +
  368 + setUserDataPopover();
328 369 }
329 370 });
330 371 }
... ...
amadeus/static/js/mural_ungeneral.js
... ... @@ -35,7 +35,8 @@ $('.mural-ungeneral').on('shown.bs.collapse', function(e) {
35 35 mural.data('pages', data.num_pages);
36 36 mural.data('page', data.num_page);
37 37  
38   - setTimeout(function () { postHeightLimits() }, 100);
  38 + setUserDataPopover();
  39 + setTimeout(function () { postHeightLimits(); }, 100);
39 40  
40 41 if (data.num_page < data.num_pages) {
41 42 more.show();
... ... @@ -112,7 +113,8 @@ $(&#39;.mural-ungeneral&#39;).on(&#39;shown.bs.collapse&#39;, function(e) {
112 113 mural.data('pages', data.num_pages);
113 114 mural.data('page', data.num_page);
114 115  
115   - setTimeout(function () { postHeightLimits() }, 100);
  116 + setUserDataPopover();
  117 + setTimeout(function () { postHeightLimits(); }, 100);
116 118  
117 119 if (data.num_page < data.num_pages) {
118 120 more.show();
... ... @@ -168,7 +170,8 @@ $(&#39;.mural-ungeneral&#39;).on(&#39;shown.bs.collapse&#39;, function(e) {
168 170 more.hide();
169 171 }
170 172  
171   - setTimeout(function () { postHeightLimits() }, 100);
  173 + setUserDataPopover();
  174 + setTimeout(function () { postHeightLimits(); }, 100);
172 175  
173 176 without.hide();
174 177 } else {
... ...
chat/migrations/0003_auto_20170407_2154.py 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-04-08 00:54
  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 + ('chat', '0002_auto_20170402_2207'),
  12 + ]
  13 +
  14 + operations = [
  15 + migrations.AlterField(
  16 + model_name='talkmessages',
  17 + name='text',
  18 + field=models.TextField(blank=True, verbose_name='Message'),
  19 + ),
  20 + ]
... ...
mural/templates/mural/_view.html
... ... @@ -7,7 +7,37 @@
7 7 </div>
8 8 <div class="col-lg-11 col-md-11 col-sm-11 col-xs-11 post-body">
9 9 <h4 class="post-user">
10   - {{ post.user }}
  10 + {% if not post.user == request.user %}
  11 + {% is_online post.user as status %}
  12 +
  13 + <span data-toggle="popover" data-placement="right">{{ post.user }}</span>
  14 +
  15 + <div class="popover">
  16 + <div class="popover-content participant">
  17 + <button type="button" class="close" aria-label="{% trans 'Close' %}"><span aria-hidden="true">&times;</span></button>
  18 +
  19 + <br clear="all" />
  20 +
  21 + <div class="col-md-3 col-sm-3 user-img">
  22 + <img src="{{ post.user.image_url }}" class="img-responsive" />
  23 + </div>
  24 + <div class="col-md-9 col-sm-9 user-info">
  25 + <h4><a class="status {{ status }}" data-toggle="tooltip" title="{{ status|status_text }}"></a> {{ post.user }}</h4>
  26 + </div>
  27 + </div>
  28 + <div class="popover-footer">
  29 + <a href="#" onclick="getModalInfo($(this), '{{ post|chat_space }}', '{{ post|chat_space_type }}'); return false;" data-url='{% url "chat:profile" post.user.email %}' class="btn btn-default btn-sm btn-raised pull-left">
  30 + {% trans 'See Profile' %}
  31 + </a>
  32 + <a href="#" onclick="getModalInfo($(this), '{{ post|chat_space }}', '{{ post|chat_space_type }}'); return false;" data-url='{% url "chat:talk" post.user.email %}' class="btn btn-success btn-sm btn-raised pull-right">
  33 + {% trans 'Send Message' %}
  34 + </a>
  35 + </div>
  36 + </div>
  37 + {% else %}
  38 + {{ post.user }}
  39 + {% endif %}
  40 +
11 41 <span class="user-action">
12 42 <i class="fa {{ post.action|action_icon }}"></i>
13 43 {{ post.get_action_display }}
... ... @@ -63,4 +93,4 @@
63 93 </div>
64 94 </div>
65 95 </div>
66 96 -</div>
  97 +</div>
67 98 \ No newline at end of file
... ...
mural/templates/mural/_view_comment.html
... ... @@ -8,7 +8,37 @@
8 8 </div>
9 9 <div class="col-lg-11 col-md-11 col-sm-11 col-xs-11 comment-body">
10 10 <h4 class="comment-user">
11   - {{ comment.user }}
  11 + {% if not post.user == request.user %}
  12 + {% is_online comment.user as status %}
  13 +
  14 + <span data-toggle="popover" data-container="body" data-placement="right">{{ comment.user }}</span>
  15 +
  16 + <div class="popover">
  17 + <div class="popover-content participant">
  18 + <button type="button" class="close" aria-label="{% trans 'Close' %}"><span aria-hidden="true">&times;</span></button>
  19 +
  20 + <br clear="all" />
  21 +
  22 + <div class="col-md-3 col-sm-3 user-img">
  23 + <img src="{{ comment.user.image_url }}" class="img-responsive" />
  24 + </div>
  25 + <div class="col-md-9 col-sm-9 user-info">
  26 + <h4><a class="status {{ status }}" data-toggle="tooltip" title="{{ status|status_text }}"></a> {{ comment.user }}</h4>
  27 + </div>
  28 + </div>
  29 + <div class="popover-footer">
  30 + <a href="#" onclick="getModalInfo($(this), '{{ comment.post|chat_space }}', '{{ comment.post|chat_space_type }}'); return false;" data-url='{% url "chat:profile" comment.user.email %}' class="btn btn-default btn-sm btn-raised pull-left">
  31 + {% trans 'See Profile' %}
  32 + </a>
  33 + <a href="#" onclick="getModalInfo($(this), '{{ comment.post|chat_space }}', '{{ comment.post|chat_space_type }}'); return false;" data-url='{% url "chat:talk" comment.user.email %}' class="btn btn-success btn-sm btn-raised pull-right">
  34 + {% trans 'Send Message' %}
  35 + </a>
  36 + </div>
  37 + </div>
  38 + {% else %}
  39 + {{ comment.user }}
  40 + {% endif %}
  41 +
12 42 <span class="user-action">
13 43 <i class="fa fa-commenting-o"></i>
14 44 {% trans 'Comment' context "view" %}
... ...
mural/templates/mural/list.html
... ... @@ -91,7 +91,13 @@
91 91 </div>
92 92  
93 93 <div class="modal fade" id="post-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
  94 +
  95 + <div class="modal fade" id="chat-modal-info" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
  96 +
  97 + <div class="modal fade" id="chat-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
  98 +
94 99  
  100 + <script type="text/javascript" src="{% static 'js/chat.js' %}"></script>
95 101 <script type="text/javascript" src="{% static 'js/mural.js' %}"></script>
96 102 <script type="text/javascript" src="{% static 'js/mural_general.js' %}"></script>
97 103 {% endblock %}
98 104 \ No newline at end of file
... ...
mural/templates/mural/list_category.html
... ... @@ -155,7 +155,12 @@
155 155  
156 156 <div class="modal fade" id="post-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
157 157  
  158 + <div class="modal fade" id="chat-modal-info" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
  159 +
  160 + <div class="modal fade" id="chat-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
  161 +
158 162 <script type="text/javascript" src="{% static 'js/category.js' %}"></script>
  163 + <script type="text/javascript" src="{% static 'js/chat.js' %}"></script>
159 164 <script type="text/javascript" src="{% static 'js/mural.js' %}"></script>
160 165 <script type="text/javascript" src="{% static 'js/mural_ungeneral.js' %}"></script>
161 166 {% endblock %}
162 167 \ No newline at end of file
... ...
mural/templates/mural/list_subject.html
... ... @@ -154,7 +154,13 @@
154 154  
155 155 <div class="modal fade" id="post-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
156 156  
  157 + <div class="modal fade" id="chat-modal-info" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
  158 +
  159 + <div class="modal fade" id="chat-modal-form" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"></div>
  160 +
  161 +
157 162 <script type="text/javascript" src="{% static 'js/category.js' %}"></script>
  163 + <script type="text/javascript" src="{% static 'js/chat.js' %}"></script>
158 164 <script type="text/javascript" src="{% static 'js/mural.js' %}"></script>
159 165 <script type="text/javascript" src="{% static 'js/mural_ungeneral.js' %}"></script>
160 166 <script type="text/javascript" src="{% static 'subjects/js/modal_subject.js' %}"></script>
... ...
mural/templatetags/mural_filters.py
1 1 from django import template
  2 +from django.conf import settings
  3 +from django.utils import timezone
2 4 from django.db.models import Q
3 5 from django.utils.translation import ugettext_lazy as _
  6 +from django.contrib.sessions.models import Session
  7 +
  8 +from log.models import Log
4 9  
5 10 from mural.models import MuralFavorites, MuralVisualizations
6 11  
... ... @@ -105,4 +110,45 @@ def has_resource(post):
105 110 if post.subjectpost.resource:
106 111 return _("about") + " <span class='post_resource'>" + str(post.subjectpost.resource) + "</span>"
107 112  
108   - return ""
109 113 \ No newline at end of file
  114 + return ""
  115 +
  116 +@register.assignment_tag(name = 'is_online')
  117 +def is_online(user):
  118 + expire_time = settings.SESSION_SECURITY_EXPIRE_AFTER
  119 + now = timezone.now()
  120 +
  121 + activities = Log.objects.filter(user_id = user.id).order_by('-datetime')
  122 +
  123 + if activities.count() > 0:
  124 + last_activity = activities[0]
  125 +
  126 + if last_activity.action != 'logout':
  127 + if (now - last_activity.datetime).total_seconds() < expire_time:
  128 + return "active"
  129 + else:
  130 + return "away"
  131 +
  132 + return ""
  133 +
  134 +@register.filter(name = 'status_text')
  135 +def status_text(status):
  136 + if status == "active":
  137 + return _("Online")
  138 + elif status == "away":
  139 + return _('Away')
  140 + else:
  141 + return _("Offline")
  142 +
  143 +@register.filter(name = 'chat_space')
  144 +def chat_space(post):
  145 + if post._my_subclass == "subjectpost":
  146 + return post.subjectpost.space.id
  147 +
  148 + return 0
  149 +
  150 +@register.filter(name = 'chat_space_type')
  151 +def chat_space_type(post):
  152 + if post._my_subclass == "subjectpost":
  153 + return "subject"
  154 +
  155 + return "general"
110 156 \ No newline at end of file
... ...
news/migrations/0001_initial.py 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-04-08 00:54
  3 +from __future__ import unicode_literals
  4 +
  5 +import autoslug.fields
  6 +from django.conf import settings
  7 +from django.db import migrations, models
  8 +import django.db.models.deletion
  9 +import news.models
  10 +
  11 +
  12 +class Migration(migrations.Migration):
  13 +
  14 + initial = True
  15 +
  16 + dependencies = [
  17 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  18 + ]
  19 +
  20 + operations = [
  21 + migrations.CreateModel(
  22 + name='News',
  23 + fields=[
  24 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  25 + ('title', models.CharField(max_length=200, unique=True, verbose_name='Name')),
  26 + ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='title', unique=True, verbose_name='Slug')),
  27 + ('image', models.ImageField(upload_to='news/', validators=[news.models.validate_img_extension], verbose_name='News Image')),
  28 + ('content', models.TextField(verbose_name='News Content')),
  29 + ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Create Date')),
  30 + ('creator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='news_creator_user', to=settings.AUTH_USER_MODEL, verbose_name='Creator')),
  31 + ],
  32 + options={
  33 + 'verbose_name_plural': 'News',
  34 + 'verbose_name': 'News',
  35 + },
  36 + ),
  37 + ]
... ...
news/templates/news/list.html
... ... @@ -26,11 +26,55 @@
26 26 {% endfor %}
27 27 {% endif %}
28 28  
29   -<div class='row'>
30   - <div class="col-md-offset-3 col-md-6">
31   - <a href="{% url 'news:create' %}" class="btn btn-raised btn-success btn-block">{% trans "Create news" %}</a>
  29 +<div class="row">
  30 + <div class="col-md-9">
  31 + <form action="{% url 'users:search' %}" method="GET" class="form-horizontal">
  32 + <div class="form-group">
  33 + <div class="col-md-11 col-sm-11 col-xs-11">
  34 + <input type="text" class="form-control" name="search" placeholder="{% trans 'Search...' %}" />
  35 + </div>
  36 + <div class="col-md-1 col-sm-1 col-xs-1">
  37 + <button type="submit" class="btn btn-fab btn-fab-mini">
  38 + <i class="fa fa-search"></i>
  39 + </button>
  40 + </div>
  41 + </div>
  42 + </form>
  43 + </div>
  44 + <div class="col-md-3">
  45 + <a href="{% url 'news:create' %}" class="pull-right btn btn-success btn-raised btn-md"><i class="fa fa-plus"></i> {% trans 'Create News' %}</a>
32 46 </div>
33 47 </div>
34 48  
  49 +{% if news %}
  50 + {% for new in news %}
  51 + <div class="row-fluid panel panel-default">
  52 + <div class="panel-body">
  53 + <div class="col-md-6">
  54 + <!-- <a href="{% url 'news:view' new.slug %}"> <h3> <b>{{ new }}</b> </h3><a> -->
  55 + <h3> <b>{{ new }}</b> </h3>
  56 + <p>{{ new.creator}}, em {{ new.create_date }}</p>
  57 + </div>
  58 + <div class="col-md-6">
  59 + <div align="right">
  60 + <a href="{% url 'news:update' new.slug %}" class="btn btn-success btn-raised btn-sm"><i class="fa fa-edit"></i> {% trans 'Edit' %}</a>
  61 + <a href="" class="btn btn-default btn-raised btn-sm"><i class="fa fa-trash"></i> {% trans 'Delete' %}</a>
  62 + </div>
  63 + </div>
  64 + </div>
  65 +
  66 + </div>
  67 + {% endfor %}
  68 + {% pagination request paginator page_obj %}
  69 +{% else %}
  70 + <div class="row">
  71 + <div class="col-md-12 col-sm-12 col-xs-12">
  72 + <p>{% trans 'No news found' %}</p>
  73 + </div>
  74 + </div>
  75 +{% endif %}
  76 +<div id="modal_remove">
  77 +
  78 +</div>
35 79  
36 80 {% endblock %}
... ...
news/templates/news/update.html 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +{% extends 'news/list.html' %}
  2 +
  3 +{% load widget_tweaks static i18n django_bootstrap_breadcrumbs permission_tags pagination %}
  4 +
  5 +{% block breadcrumbs %}
  6 + {{ block.super }}
  7 + {% trans 'Update News' as update_news %}
  8 + {% breadcrumb update_news 'news:update' %}
  9 +{% endblock %}
  10 +
  11 +{% block render_breadcrumbs %}
  12 + {% render_breadcrumbs %}
  13 +{% endblock %}
  14 +
  15 +{% block content %}
  16 +<div class="card card-content">
  17 + <div class="card-body">
  18 + {% include 'news/_form.html' %}
  19 + </div>
  20 +</div>
  21 +<br clear="all">
  22 +<br clear="all">
  23 +
  24 +{% endblock %}
... ...
news/templates/news/view.html
1   -{{news}}
  1 +{% extends 'news/list.html' %}
  2 +
  3 +{% load widget_tweaks static i18n django_bootstrap_breadcrumbs permission_tags pagination %}
  4 +
  5 +{% block breadcrumbs %}
  6 + {{ block.super }}
  7 + {% trans 'Visualize News' as visualize_news %}
  8 + {% breadcrumb visualize_news 'news:view' %}
  9 +{% endblock %}
  10 +
  11 +{% block render_breadcrumbs %}
  12 + {% render_breadcrumbs %}
  13 +{% endblock %}
  14 +
  15 +
  16 +{% block content %}
  17 +
  18 +{% if messages %}
  19 + {% for message in messages %}
  20 + <script type="text/javascript">
  21 + {% if message.tags == "danger" %}
  22 + alertify.error('{{message}}');
  23 + {% else %}
  24 + alertify.success('{{message}}');
  25 + {% endif %}
  26 + </script>
  27 + {% endfor %}
  28 +{% endif %}
  29 +
  30 +{{new.title}}
  31 +<br>{{new.creator}}
  32 +<br>{{new.create_date}}
  33 +{% endblock %}
... ...
news/views.py
... ... @@ -15,17 +15,20 @@ class VisualizeNews(LoginRequiredMixin,LogMixin,generic.ListView):
15 15 login_url = reverse_lazy("users:login")
16 16 redirect_field_name = 'next'
17 17 template_name = 'news/view.html'
18   - context_object_name = "news"
  18 + context_object_name = "new"
19 19  
20 20 def get_context_data(self, **kwargs):
21 21 context = super(VisualizeNews, self).get_context_data(**kwargs)
22 22 context['title'] = _('Visualize News')
23 23  
24 24 return context
  25 +
25 26 def get_queryset(self):
26 27 slug = self.kwargs.get('slug', '')
27   - news = News.objects.get(slug=slug)
28   - return news
  28 + new = News.objects.get(slug=slug)
  29 +
  30 + return new
  31 +
29 32 class ListNewsView(LoginRequiredMixin,LogMixin,generic.ListView):
30 33 login_url = reverse_lazy("users:login")
31 34 redirect_field_name = 'next'
... ... @@ -36,25 +39,65 @@ class ListNewsView(LoginRequiredMixin,LogMixin,generic.ListView):
36 39  
37 40 def get_queryset(self):
38 41 news = News.objects.all().order_by('create_date')
  42 +
39 43 return news
40 44  
  45 + def get_context_data(self, **kwargs):
  46 + context = super(ListNewsViewNews, self).get_context_data(**kwargs)
  47 + context['title'] = _('Manage News')
  48 +
  49 + return context
  50 +
  51 +
41 52 class CreateNewsView(LoginRequiredMixin,LogMixin,generic.edit.CreateView):
42 53 login_url = reverse_lazy("users:login")
43 54 redirect_field_name = 'next'
44 55 template_name = 'news/create.html'
45 56 form_class = NewsForm
  57 +
46 58 def form_valid(self, form):
47   - self.object = form.save()
  59 + self.object = form.save(commit = False)
  60 + creator = self.request.user
  61 + self.object.creator = creator
  62 +
  63 + self.object.save()
  64 +
48 65 return super(CreateNewsView, self).form_valid(form)
49 66  
50 67 def get_success_url(self):
51 68 messages.success(self.request, _('News successfully created!'))
52 69  
53 70 return reverse_lazy('news:view', kwargs = {'slug': self.object.slug} )
  71 +
54 72 def get_context_data (self, **kwargs):
55 73 context = super(CreateNewsView, self).get_context_data(**kwargs)
56 74 context['title'] = _("Create News")
  75 +
57 76 return context
58 77  
59 78 class UpdateNewsView(LoginRequiredMixin,LogMixin,generic.UpdateView):
60   - pass
  79 + login_url = reverse_lazy("users:login")
  80 + redirect_field_name = 'next'
  81 + template_name = 'news/update.html'
  82 + form_class = NewsForm
  83 + model = News
  84 +
  85 + def get_success_url(self):
  86 + messages.success(self.request, _('News successfully created!'))
  87 +
  88 + return reverse_lazy('news:view', kwargs = {'slug': self.object.slug} )
  89 +
  90 + def get_context_data (self, **kwargs):
  91 + context = super(UpdateNewsView, self).get_context_data(**kwargs)
  92 + context['title'] = _("Update News")
  93 +
  94 + return context
  95 +
  96 + def form_valid(self, form):
  97 + self.object = form.save(commit = False)
  98 + creator = self.request.user
  99 + self.object.creator = creator
  100 +
  101 + self.object.save()
  102 +
  103 + return super(UpdateNewsView, self).form_valid(form)
... ...