correct bug and add email sending
authorymh <ymh.work@gmail.com>
Sat, 28 Feb 2015 06:40:48 +0100
changeset 462 df8b3b49e81c
parent 461 65fc0c646d74
child 463 2a3ef4dcbb6b
correct bug and add email sending
.settings/org.eclipse.core.resources.prefs
src/hdalab/models/renkan.py
src/hdalab/services.py
src/hdalab/templates/editorial/manage_renkans.html
src/hdalab/templates/mails/published_renkan.html
src/hdalab/templates/mails/published_renkan.txt
src/hdalab/templates/mails/rejected_renkan.html
src/hdalab/templates/mails/rejected_renkan.txt
src/hdalab/utils.py
src/hdalab/views/editorial.py
--- a/.settings/org.eclipse.core.resources.prefs	Fri Feb 27 02:27:31 2015 +0100
+++ b/.settings/org.eclipse.core.resources.prefs	Sat Feb 28 06:40:48 2015 +0100
@@ -61,6 +61,7 @@
 encoding//src/hdalab/migrations/0013_auto__chg_field_dbpediafields_tag__add_unique_tagyears_tag.py=utf-8
 encoding//src/hdalab/migrations/0014_auto__add_hdalabrenkanstatetransition__chg_field_dbpediafields_tag.py=utf-8
 encoding//src/hdalab/models/dataviz.py=utf-8
+encoding//src/hdalab/models/renkan.py=utf-8
 encoding//src/hdalab/services.py=utf-8
 encoding//src/hdalab/settings.py=utf-8
 encoding//src/hdalab/urls.py=utf-8
--- a/src/hdalab/models/renkan.py	Fri Feb 27 02:27:31 2015 +0100
+++ b/src/hdalab/models/renkan.py	Sat Feb 28 06:40:48 2015 +0100
@@ -1,15 +1,27 @@
+# -*- coding: utf-8 -*-
 '''
 Created on Jul 17, 2014
 
 @author: tc
 '''
+import logging
 from renkanmanager.models import Renkan
 
 from django.conf import settings
+from django.core.mail import send_mail
 from django.db import models
+from django.db.models.signals import post_save
+from django.template import loader
+from django.template.base import TemplateDoesNotExist
+from django.template.context import Context
 from django.utils.translation import ugettext as _
+from django.template.loader import render_to_string
+from django.core.mail.message import EmailMultiAlternatives
+from django.utils.html import strip_tags
 
 
+logger = logging.getLogger(__name__)
+
 class HdalabRenkan(models.Model):
     
     EDITION = 1
@@ -49,3 +61,48 @@
     
     class Meta:
         app_label = 'hdalab'
+
+MAIL_TEMPLATES = {
+    HdalabRenkan.PUBLISHED: ("mails/published_renkan", "Renkan publié"),
+    HdalabRenkan.REJECTED: ("mails/rejected_renkan", "Renkan rejeté")
+}
+
+
+#TODO put into queue
+def send_renkan_moderation_messages(sender, **kwargs):
+    renkan_state = kwargs.get('instance', None)
+    if not renkan_state or renkan_state.to_state not in MAIL_TEMPLATES:
+        return
+
+    msg_txt = ""
+    msg_html = ""
+    subject = ""
+    try:
+        template_name, subject = MAIL_TEMPLATES[renkan_state.to_state]
+#        template = loader.get_template(template_name)
+        context = {'renkan_state': renkan_state, 'WEB_URL': settings.WEB_URL}
+        msg_html = render_to_string(template_name+".txt", context)
+        msg_txt = render_to_string(template_name+".html", context)
+    except TemplateDoesNotExist:
+        logger.error("Mail template %s for state %s not found", MAIL_TEMPLATES[renkan_state.to_state], HdalabRenkan.STATE_CHOICES_DICT[renkan_state.to_state])
+        return
+    except Exception as e:
+        logger.error("Error rendering template %s for state %s : %r", MAIL_TEMPLATES[renkan_state.to_state], HdalabRenkan.STATE_CHOICES_DICT[renkan_state.to_state], e)
+    
+    if msg_txt and msg_html and renkan_state.renkan and renkan_state.renkan.renkan and renkan_state.renkan.renkan.owner and renkan_state.renkan.renkan.owner.email:
+        logger.debug("Sending following mail to %s : %s", renkan_state.renkan.renkan.owner.email, msg_txt)
+        emsg = EmailMultiAlternatives(subject, strip_tags(msg_txt), settings.ADMINS[0][1], [renkan_state.renkan.renkan.owner.email])
+        emsg.attach_alternative(msg_html, "text/html")
+        emsg.send(fail_silently=True)
+
+
+def queue_renkan_rendering(sender, **kwargs):
+    pass
+    #check state
+    #queue renkan for endering
+    
+    
+RENKAN_MODERATION_UUID = "e2f84503-609b-4efa-819d-908e2efe7b1b"
+RENKAN_RENDERING_UUID = "b8830748-be2b-479a-8aef-c8d952437b2f"
+
+post_save.connect(send_renkan_moderation_messages, sender=HdalabRenkanStateTransition, dispatch_uid=RENKAN_MODERATION_UUID)
--- a/src/hdalab/services.py	Fri Feb 27 02:27:31 2015 +0100
+++ b/src/hdalab/services.py	Sat Feb 28 06:40:48 2015 +0100
@@ -4,9 +4,15 @@
 
 @author: ymh
 '''
+import logging
+
 from django.db import transaction
+
 from hdalab.models.renkan import HdalabRenkanStateTransition
 
+
+logger = logging.getLogger(__name__)
+
 @transaction.atomic
 def change_renkan_state(hda_renkan, state, message=None, author=None):
     
@@ -14,4 +20,5 @@
         
         HdalabRenkanStateTransition.objects.create(renkan=hda_renkan, from_state=hda_renkan.state, to_state=state, message=message, author=author)
         hda_renkan.state = state
-        hda_renkan.save()
\ No newline at end of file
+        hda_renkan.save()
+        
--- a/src/hdalab/templates/editorial/manage_renkans.html	Fri Feb 27 02:27:31 2015 +0100
+++ b/src/hdalab/templates/editorial/manage_renkans.html	Sat Feb 28 06:40:48 2015 +0100
@@ -76,7 +76,7 @@
                     <input type="hidden" name="next" value="{% url 'manage_renkans' %}" />
                 {% if hr.state == 2 or hr.state == 4 %}<button name="state" value="3" title="{% trans 'publish renkan' %}" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to PUBLISH this renkan ?" %}');"><span class="ui-icon ui-icon-unlocked"></button>
                 {% else %}<button name="state" title="{% trans 'unpublish renkan' %}" value="1" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to UNPUBLISH this renkan ?" %}');"><span class="ui-icon ui-icon-locked"></button>{% endif %}
-                {% if hr.state != 4 %}<button name="state" title="{% trans 'reject renkan' %}" value="4" class="renkan-basic-action" onclick=" onclick="return confirm('{% trans "Are you sure you want to REJECT this renkan ?" %}');" ><span class="ui-icon ui-icon-close"></span></button>{% endif %}
+                {% if hr.state != 4 %}<button name="state" title="{% trans 'reject renkan' %}" value="4" class="renkan-basic-action" onclick="return confirm('{% trans "Are you sure you want to REJECT this renkan ?" %}');" ><span class="ui-icon ui-icon-close"></span></button>{% endif %}
                 </form>
             </td>
         </tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templates/mails/published_renkan.html	Sat Feb 28 06:40:48 2015 +0100
@@ -0,0 +1,210 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!-- Template from https://github.com/leemunroe/html-email-template -->
+<head>
+<meta name="viewport" content="width=device-width" />
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>Renkan publié</title>
+<style>
+/* -------------------------------------
+        GLOBAL
+------------------------------------- */
+* {
+    margin: 0;
+    padding: 0;
+    font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+    font-size: 100%;
+    line-height: 1.6;
+}
+
+img {
+    max-width: 100%;
+}
+
+body {
+    -webkit-font-smoothing: antialiased;
+    -webkit-text-size-adjust: none;
+    width: 100%!important;
+    height: 100%;
+}
+
+
+/* -------------------------------------
+        ELEMENTS
+------------------------------------- */
+a {
+    color: #348eda;
+}
+
+.btn-primary {
+    text-decoration: none;
+    color: #FFF;
+    background-color: #348eda;
+    border: solid #348eda;
+    border-width: 10px 20px;
+    line-height: 2;
+    font-weight: bold;
+    margin-right: 10px;
+    text-align: center;
+    cursor: pointer;
+    display: inline-block;
+    border-radius: 25px;
+}
+
+.btn-secondary {
+    text-decoration: none;
+    color: #FFF;
+    background-color: #aaa;
+    border: solid #aaa;
+    border-width: 10px 20px;
+    line-height: 2;
+    font-weight: bold;
+    margin-right: 10px;
+    text-align: center;
+    cursor: pointer;
+    display: inline-block;
+    border-radius: 25px;
+}
+
+.last {
+    margin-bottom: 0;
+}
+
+.first {
+    margin-top: 0;
+}
+
+.padding {
+    padding: 10px 0;
+}
+
+
+/* -------------------------------------
+        BODY
+------------------------------------- */
+table.body-wrap {
+    width: 100%;
+    padding: 20px;
+}
+
+table.body-wrap .container {
+    border: 1px solid #f0f0f0;
+}
+
+
+/* -------------------------------------
+        FOOTER
+------------------------------------- */
+table.footer-wrap {
+    width: 100%;    
+    clear: both!important;
+}
+
+.footer-wrap .container p {
+    font-size: 12px;
+    color: #666;
+    
+}
+
+table.footer-wrap a {
+    color: #999;
+}
+
+
+/* -------------------------------------
+        TYPOGRAPHY
+------------------------------------- */
+h1, h2, h3 {
+    font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
+    line-height: 1.1;
+    margin-bottom: 15px;
+    color: #000;
+    margin: 40px 0 10px;
+    line-height: 1.2;
+    font-weight: 200;
+}
+
+h1 {
+    font-size: 36px;
+}
+h2 {
+    font-size: 28px;
+}
+h3 {
+    font-size: 22px;
+}
+
+p, ul, ol {
+    margin-bottom: 10px;
+    font-weight: normal;
+    font-size: 14px;
+}
+
+ul li, ol li {
+    margin-left: 5px;
+    list-style-position: inside;
+}
+
+/* ---------------------------------------------------
+        RESPONSIVENESS
+
+------------------------------------------------------ */
+
+/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+.container {
+    display: block!important;
+    max-width: 600px!important;
+    margin: 0 auto!important; /* makes it centered */
+    clear: both!important;
+}
+
+/* Set the padding on the td rather than the div for Outlook compatibility */
+.body-wrap .container {
+    padding: 20px;
+}
+
+/* This should also be a block element, so that it will fill 100% of the .container */
+.content {
+    max-width: 600px;
+    margin: 0 auto;
+    display: block;
+}
+
+/* Let's make sure tables in the content area are 100% wide */
+.content table {
+    width: 100%;
+}
+
+</style>
+</head>
+
+<body bgcolor="#f6f6f6">
+
+<!-- body -->
+<table class="body-wrap">
+    <tr>
+        <td></td>
+        <td class="container" bgcolor="#FFFFFF">
+
+            <!-- content -->
+            <div class="content">
+            <table>
+                <tr>
+                    <td>
+                        <p>Bonjour,</p>
+                        <p>Votre Renkan intitulé {{ renkan_state.renkan.renkan.title}} a été publié.</p>
+                        <p>Vous pouvez le retrouver à l'url suivante: <a href="{{WEB_URL}}{% url 'renkan_view' %}?rk_id={{ renkan_state.renkan.renkan.rk_id }}">{{WEB_URL}}{% url 'renkan_view' %}?rk_id={{ renkan_state.renkan.renkan.rk_id }}</a>.</p>
+                    </td>
+                </tr>
+            </table>
+            </div>
+            <!-- /content -->
+            
+        </td>
+        <td></td>
+    </tr>
+</table>
+<!-- /body -->
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templates/mails/published_renkan.txt	Sat Feb 28 06:40:48 2015 +0100
@@ -0,0 +1,4 @@
+Bonjour,
+
+Votre Renkan intitulé {{ renkan_state.renkan.renkan.title}} a été publié.
+Vous pouvez le retrouver à l'url suivante: {{WEB_URL}}{% url 'renkan_view' %}?rk_id={{ renkan_state.renkan.renkan.rk_id }}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templates/mails/rejected_renkan.html	Sat Feb 28 06:40:48 2015 +0100
@@ -0,0 +1,213 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!-- Template from https://github.com/leemunroe/html-email-template -->
+<head>
+<meta name="viewport" content="width=device-width" />
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>Renkan rejeté</title>
+<style>
+/* -------------------------------------
+        GLOBAL
+------------------------------------- */
+* {
+    margin: 0;
+    padding: 0;
+    font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+    font-size: 100%;
+    line-height: 1.6;
+}
+
+img {
+    max-width: 100%;
+}
+
+body {
+    -webkit-font-smoothing: antialiased;
+    -webkit-text-size-adjust: none;
+    width: 100%!important;
+    height: 100%;
+}
+
+
+/* -------------------------------------
+        ELEMENTS
+------------------------------------- */
+a {
+    color: #348eda;
+}
+
+.btn-primary {
+    text-decoration: none;
+    color: #FFF;
+    background-color: #348eda;
+    border: solid #348eda;
+    border-width: 10px 20px;
+    line-height: 2;
+    font-weight: bold;
+    margin-right: 10px;
+    text-align: center;
+    cursor: pointer;
+    display: inline-block;
+    border-radius: 25px;
+}
+
+.btn-secondary {
+    text-decoration: none;
+    color: #FFF;
+    background-color: #aaa;
+    border: solid #aaa;
+    border-width: 10px 20px;
+    line-height: 2;
+    font-weight: bold;
+    margin-right: 10px;
+    text-align: center;
+    cursor: pointer;
+    display: inline-block;
+    border-radius: 25px;
+}
+
+.last {
+    margin-bottom: 0;
+}
+
+.first {
+    margin-top: 0;
+}
+
+.padding {
+    padding: 10px 0;
+}
+
+
+/* -------------------------------------
+        BODY
+------------------------------------- */
+table.body-wrap {
+    width: 100%;
+    padding: 20px;
+}
+
+table.body-wrap .container {
+    border: 1px solid #f0f0f0;
+}
+
+
+/* -------------------------------------
+        FOOTER
+------------------------------------- */
+table.footer-wrap {
+    width: 100%;    
+    clear: both!important;
+}
+
+.footer-wrap .container p {
+    font-size: 12px;
+    color: #666;
+    
+}
+
+table.footer-wrap a {
+    color: #999;
+}
+
+
+/* -------------------------------------
+        TYPOGRAPHY
+------------------------------------- */
+h1, h2, h3 {
+    font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
+    line-height: 1.1;
+    margin-bottom: 15px;
+    color: #000;
+    margin: 40px 0 10px;
+    line-height: 1.2;
+    font-weight: 200;
+}
+
+h1 {
+    font-size: 36px;
+}
+h2 {
+    font-size: 28px;
+}
+h3 {
+    font-size: 22px;
+}
+
+p, ul, ol {
+    margin-bottom: 10px;
+    font-weight: normal;
+    font-size: 14px;
+}
+
+ul li, ol li {
+    margin-left: 5px;
+    list-style-position: inside;
+}
+
+/* ---------------------------------------------------
+        RESPONSIVENESS
+
+------------------------------------------------------ */
+
+/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+.container {
+    display: block!important;
+    max-width: 600px!important;
+    margin: 0 auto!important; /* makes it centered */
+    clear: both!important;
+}
+
+/* Set the padding on the td rather than the div for Outlook compatibility */
+.body-wrap .container {
+    padding: 20px;
+}
+
+/* This should also be a block element, so that it will fill 100% of the .container */
+.content {
+    max-width: 600px;
+    margin: 0 auto;
+    display: block;
+}
+
+/* Let's make sure tables in the content area are 100% wide */
+.content table {
+    width: 100%;
+}
+
+</style>
+</head>
+
+<body bgcolor="#f6f6f6">
+
+<!-- body -->
+<table class="body-wrap">
+    <tr>
+        <td></td>
+        <td class="container" bgcolor="#FFFFFF">
+
+            <!-- content -->
+            <div class="content">
+            <table>
+                <tr>
+                    <td>
+                        <p>Bonjour,</p>
+                        <p>Votre Renkan intitulé {{ renkan_state.renkan.renkan.title}} a été rejeté.</p>
+                        {% if renkan_state.message %}
+                        <p>Avec le message suivant : {{ renkan_state.message }}</p>
+                        {% endif %}
+                        <p></p>
+                    </td>
+                </tr>
+            </table>
+            </div>
+            <!-- /content -->
+            
+        </td>
+        <td></td>
+    </tr>
+</table>
+<!-- /body -->
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templates/mails/rejected_renkan.txt	Sat Feb 28 06:40:48 2015 +0100
@@ -0,0 +1,5 @@
+Bonjour,
+Votre Renkan intitulé {{ renkan_state.renkan.renkan.title}} a été rejeté.
+{% if renkan_state.message %}
+Avec le message suivant : {{ renkan_state.message }}
+{% endif %}
\ No newline at end of file
--- a/src/hdalab/utils.py	Fri Feb 27 02:27:31 2015 +0100
+++ b/src/hdalab/utils.py	Sat Feb 28 06:40:48 2015 +0100
@@ -20,4 +20,13 @@
         cache_key = cache_key[:(250-(2+len(cache.key_prefix)+len(str(cache.version)))-33)] + '-' + hashlib.md5(cache_key).hexdigest()
     return cache_key
         
-        
\ No newline at end of file
+#
+# from : http://cs.stackexchange.com/a/10321
+#
+def toDigits(n, b):
+    """Convert a positive number n to its digit representation in base b."""
+    digits = []
+    while n > 0:
+        digits.insert(0, n % b)
+        n  = n // b
+    return digits
\ No newline at end of file
--- a/src/hdalab/views/editorial.py	Fri Feb 27 02:27:31 2015 +0100
+++ b/src/hdalab/views/editorial.py	Sat Feb 28 06:40:48 2015 +0100
@@ -17,7 +17,7 @@
     template_name = "editorial/manage_renkans.html"
     
     def get_context_data(self, **kwargs):
-        return self.update_context(super(ManageRenkans, self).get_context_data(**kwargs), HdalabRenkan.objects.exclude(state=HdalabRenkan.EDITION).select_related("renkan", "renkan__owner"))
+        return self.update_context(super(ManageRenkans, self).get_context_data(**kwargs), HdalabRenkan.objects.exclude(state=HdalabRenkan.EDITION).exclude(state=HdalabRenkan.REJECTED).select_related("renkan", "renkan__owner"))
 
 
 class HdalabFolders(Folders):