Browse Source

Module notifications (en cours)

omassot 7 years ago
parent
commit
44a17d7f48
8 changed files with 76 additions and 26 deletions
  1. 0 1
      backlog/settings.py
  2. 1 1
      backlog/urls.py
  3. 5 5
      main/apps.py
  4. 18 1
      main/models.py
  5. 17 0
      main/static/js/custom.js
  6. 14 5
      main/templates/_layout.html
  7. 20 11
      main/views.py
  8. 1 2
      requirements.txt

+ 0 - 1
backlog/settings.py

@@ -37,7 +37,6 @@ INSTALLED_APPS = [
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'martor',
-    'widget_tweaks',
 ]
 
 MIDDLEWARE = [

+ 1 - 1
backlog/urls.py

@@ -15,7 +15,7 @@ Including another URLconf
 """
 from django.contrib import admin
 from django.urls import path, include
-
+import notifications.urls
 
 urlpatterns = [
     path('', include('main.urls')),

+ 5 - 5
main/apps.py

@@ -1,5 +1,5 @@
-from django.apps import AppConfig
-
-
-class MainConfig(AppConfig):
-    name = 'main'
+from django.apps import AppConfig
+
+
+class MainConfig(AppConfig):
+    name = 'main'

+ 18 - 1
main/models.py

@@ -209,4 +209,21 @@ class Comment(BaseModel):
     author = models.ForeignKey(User, 
                                on_delete=models.PROTECT, 
                                verbose_name="Auteur")
-    
+    
+    
+class Notification(BaseModel):
+    class Meta:
+        verbose_name = "notification"
+        verbose_name_plural = "notifications"
+        ordering = ('-created', )
+    
+    title = models.CharField(max_length=200, default="")
+    description = models.TextField()
+    recipient = models.ForeignKey(User)
+    obj_type = models.IntegerField()
+    obj_id = models.IntegerField()
+    unread = models.BooleanField(default=True)
+    emailed = models.BooleanField(default=False)
+
+    def __str__(self):
+        return self.title

+ 17 - 0
main/static/js/custom.js

@@ -68,9 +68,15 @@ $(document).ready( function () {
 	            $('#user-dropdown').hide();
 	        }
 	    }
+	    if(!$(event.target).closest('#notif-panel').length) {
+	    	if($('#notif-dropdown').is(":visible")) {
+	    		$('#notif-dropdown').hide();
+	    	}
+	    }
 	});
 	
 	$(document).on('click', '#user-show-btn', function(event) {
+		event.preventDefault();
 		if($('#user-dropdown').is(":visible")) {
 			$('#user-dropdown').hide();
 		}
@@ -79,4 +85,15 @@ $(document).ready( function () {
 		}
 	});
 	
+	$(document).on('click', '#notif-show-btn', function(event) {
+		event.preventDefault();
+		if($('#notif-dropdown').is(":visible")) {
+			$('#notif-dropdown').hide();
+		}
+		else {
+			$('#notif-dropdown').show();
+		}
+	});
+	
+	
 });

+ 14 - 5
main/templates/_layout.html

@@ -1,5 +1,6 @@
 
 {% load staticfiles %}
+
 <!DOCTYPE html>
 <html lang="fr">
 	<head>
@@ -36,8 +37,7 @@
 		<script type="text/javascript" src="{% static 'plugins/js/emojis.min.js' %}"></script>
 		<script type="text/javascript" src="{% static 'martor/js/martor.min.js' %}"></script>
 		<script type="text/javascript" src="{% static 'js/Chart.bundle.js' %}"></script>
-		
-		<script src="{% static 'js/custom.js' %}"></script>
+		<script type="text/javascript" src="{% static 'js/custom.js' %}"></script>
 		
 	</head>
 	
@@ -56,6 +56,15 @@
 				    	<input name="q" type="text" placeholder="Rechercher...">
 				    </form>
 	        		
+	        		<div id="notif-panel" class="dropdown">
+	        			<a href="#" id="notif-show-btn">
+	        				<i class="fa fa-bell"></i>0 <i class="fa fa-caret-down" style="margin-left: 0.5em;"></i>
+	        			</a>
+	        		
+						<div id="notif-dropdown" class="dropdown-content">
+						</div>
+					</div>
+	        		
 	        		<a class="tool-btn" href="{% url 'story_create' %}" style="margin-right: 1em;" title="Nouvelle Story">
 	        			<i class="fa fa-plus" style="color:#4183c4;"></i><span class="hide-on-small-screen"> Nouvelle Story</span>
 	        		</a>
@@ -65,11 +74,11 @@
 	        		</a>
 	        		
 	        		<div id="user-panel" class="dropdown">
-	        			<a href="#" id="user-show-btn"><i class="fa fa-user"></i><span class="hide-on-small-screen"> {{ request.user.first_name }} {{ request.user.last_name }}</span> <i class="fa fa-caret-down" style="margin-left: 0.5em;"></i></a>
+	        			<a href="" id="user-show-btn"><i class="fa fa-user"></i><span class="hide-on-small-screen"> {{ request.user.first_name }} {{ request.user.last_name }}</span> <i class="fa fa-caret-down" style="margin-left: 0.5em;"></i></a>
 	        		
 						<div id="user-dropdown" class="dropdown-content">
-							<a href="{% url 'profile_update' %}">Mettre à jour son profil</a>
-							<a href="{% url 'change_password' %}">Changer son mot de passe</a>
+							<a href="{% url 'profile_update' %}">Mise à jour du profil</a>
+							<a href="{% url 'change_password' %}">Changer de mot de passe</a>
 							<a href="{% url 'logout' %}">Se déconnecter</a>
 						</div>
 					</div>

+ 20 - 11
main/views.py

@@ -1,14 +1,13 @@
 from datetime import datetime
-import json
 
 from django.contrib.auth import logout, login, update_session_auth_hash
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.forms import PasswordChangeForm
 from django.contrib.auth.models import User
-from django.core import serializers
 from django.core.paginator import Paginator
-from django.http.response import HttpResponse, HttpResponseRedirect
+from django.http.response import HttpResponse
 from django.shortcuts import render, get_object_or_404, redirect
+from notifications.signals import notify
 
 from main.forms import StoryForm, EpicForm, RegisterForm, ProfileForm, \
     CommentForm, SprintForm
@@ -159,17 +158,27 @@ def story_delete(request, story_id):
         story = get_object_or_404(Story, id=story_id)
         return render(request, 'deletion.html', {'object': story})
 
-@login_required
-def story_close(request, story_id):
+def _story_close(request, story_id):
     story = get_object_or_404(Story, id=story_id)
     story.closed = True
     story.save()
-    return render(request, 'epic_details.html', {'epic': story.epic})
+    
+#     for u in story.assignees.all():
+#     for u in story.assignees.filter(id != request.user.id):
+#         notify.send(request.user, 
+#                     recipient=u, 
+#                     verb="Story clôturée",
+#                     action_object=story,
+#                     description="La story #{} a été clôturée".format(story.id))
+    return story
 
-def story_close_ajax(_, story_id):
-    story = get_object_or_404(Story, id=story_id)
-    story.closed = True
-    story.save()
+@login_required
+def story_close(request, story_id):
+    story = _story_close(request, story_id)
+    return redirect('epic_details', story.epic.id)
+
+def story_close_ajax(request, story_id):
+    story = _story_close(request, story_id)
     return HttpResponse(story.to_json())
 
 @login_required
@@ -192,7 +201,7 @@ def story_reopen(_, story_id):
     story = get_object_or_404(Story, id=story_id)
     story.closed = False
     story.save()
-    return redirect('story_details.html', {'story_id': story_id})
+    return redirect('story_details', story_id)
 
 @login_required
 def epic_details(request, epic_id):

+ 1 - 2
requirements.txt

@@ -2,5 +2,4 @@ psycopg2-binary
 Django
 martor
 path.py>=11.1.0
-mod_wsgi
-django-widget-tweaks
+mod_wsgi