commit 60e78c999a766ddb70ffe147c62c574a64a3f561
Author: Kostas Papadimitriou <kpap@grnet.gr>
Date:   Thu Aug 2 19:27:14 2012 +0300

    Page notification messages improvements
    
    - New template tag {% display_messages %} which handles messages
      display, both for django.contrib.messages and ASTAKOS_*_MESSAGES.
    - Apply messages block class from python code (instead of js).
    - Changed format of ASTAKOS_*_MESSAGES to list of tuples, to allow
      multiple messages of the same level to exist in a page.
    - Fixed link colors for info/warning messages

diff --git a/snf-astakos-app/Changelog b/snf-astakos-app/Changelog
index 093a0ca..9b8d1bd 100644
--- a/snf-astakos-app/Changelog
+++ b/snf-astakos-app/Changelog
@@ -1,6 +1,11 @@
 Changelog
 ---------
 
+v0.7.1
+^^^^^^
+- ASTAKOS_*_MESSAGES settings changed from dict to tuple lists
+- Theme changes (new colors, new font)
+
 v0.7.0
 ^^^^^^
 - Rename management commands
diff --git a/snf-astakos-app/astakos/im/context_processors.py b/snf-astakos-app/astakos/im/context_processors.py
index 4f63315..31ba885 100644
--- a/snf-astakos-app/astakos/im/context_processors.py
+++ b/snf-astakos-app/astakos/im/context_processors.py
@@ -57,8 +57,21 @@ def media(request):
     return {'IM_STATIC_URL' : IM_STATIC_URL}
 
 def custom_messages(request):
+    global GLOBAL_MESSAGES, SIGNUP_MESSAGES, LOGIN_MESSAGES, PROFILE_MESSAGES
+
+    # keep backwards compatibility with dict settings
+    if type(GLOBAL_MESSAGES) == dict:
+        GLOBAL_MESSAGES = GLOBAL_MESSAGES.items()
+    if type(SIGNUP_MESSAGES) == dict:
+        SIGNUP_MESSAGES = SIGNUP_MESSAGES.items()
+    if type(LOGIN_MESSAGES) == dict:
+        LOGIN_MESSAGES = LOGIN_MESSAGES.items()
+    if type(PROFILE_MESSAGES) == dict:
+        PROFILE_MESSAGES = PROFILE_MESSAGES.items()
+
     EXTRA_MESSAGES_SET = bool(GLOBAL_MESSAGES or SIGNUP_MESSAGES or \
             LOGIN_MESSAGES or PROFILE_MESSAGES)
+
     return {
             'GLOBAL_MESSAGES' : GLOBAL_MESSAGES,
             'SIGNUP_MESSAGES' : SIGNUP_MESSAGES,
diff --git a/snf-astakos-app/astakos/im/settings.py b/snf-astakos-app/astakos/im/settings.py
index 42e252b..43f4f98 100644
--- a/snf-astakos-app/astakos/im/settings.py
+++ b/snf-astakos-app/astakos/im/settings.py
@@ -50,7 +50,7 @@ SITENAME = getattr(settings, 'ASTAKOS_SITENAME', 'GRNET Cloud')
 # Set recaptcha keys
 RECAPTCHA_PUBLIC_KEY = getattr(settings, 'ASTAKOS_RECAPTCHA_PUBLIC_KEY', '')
 RECAPTCHA_PRIVATE_KEY = getattr(settings, 'ASTAKOS_RECAPTCHA_PRIVATE_KEY', '')
-RECAPTCHA_OPTIONS = getattr(settings, 'ASTAKOS_RECAPTCHA_OPTIONS', 
+RECAPTCHA_OPTIONS = getattr(settings, 'ASTAKOS_RECAPTCHA_OPTIONS',
                             {'theme' : 'custom', 'custom_theme_widget': 'okeanos_recaptcha'})
 RECAPTCHA_USE_SSL = getattr(settings, 'ASTAKOS_RECAPTCHA_USE_SSL', True)
 RECAPTCHA_ENABLED = getattr(settings, 'ASTAKOS_RECAPTCHA_ENABLED', True)
@@ -69,19 +69,19 @@ RE_USER_EMAIL_PATTERNS = getattr(settings, 'ASTAKOS_RE_USER_EMAIL_PATTERNS', [])
 
 # Messages to display on login page header
 # e.g. {'warning': 'This warning message will be displayed on the top of login page'}
-LOGIN_MESSAGES = getattr(settings, 'ASTAKOS_LOGIN_MESSAGES', {})
+LOGIN_MESSAGES = getattr(settings, 'ASTAKOS_LOGIN_MESSAGES', [])
 
 # Messages to display on login page header
 # e.g. {'warning': 'This warning message will be displayed on the top of signup page'}
-SIGNUP_MESSAGES = getattr(settings, 'ASTAKOS_SIGNUP_MESSAGES', {})
+SIGNUP_MESSAGES = getattr(settings, 'ASTAKOS_SIGNUP_MESSAGES', [])
 
 # Messages to display on login page header
 # e.g. {'warning': 'This warning message will be displayed on the top of profile page'}
-PROFILE_MESSAGES = getattr(settings, 'ASTAKOS_PROFILE_MESSAGES', {})
+PROFILE_MESSAGES = getattr(settings, 'ASTAKOS_PROFILE_MESSAGES', [])
 
 # Messages to display on all pages
 # e.g. {'warning': 'This warning message will be displayed on the top of every page'}
-GLOBAL_MESSAGES = getattr(settings, 'ASTAKOS_GLOBAL_MESSAGES', {})
+GLOBAL_MESSAGES = getattr(settings, 'ASTAKOS_GLOBAL_MESSAGES', [])
 
 # messages to display as extra actions in account forms
 # e.g. {'https://cms.okeanos.grnet.gr/': 'Back to ~okeanos'}
diff --git a/snf-astakos-app/astakos/im/static/im/css/modules.css b/snf-astakos-app/astakos/im/static/im/css/modules.css
index eb51f82..ad953d6 100644
--- a/snf-astakos-app/astakos/im/static/im/css/modules.css
+++ b/snf-astakos-app/astakos/im/static/im/css/modules.css
@@ -30,6 +30,12 @@ img.right						                { margin:0 0 1em 1em; float:right;}
 .top-msg +.mainlogo                             { margin-top:-73px;}
 .top-msg .close                                 { position:absolute; bottom:20px; right:20px; font-size:1.3em; font-weight:bold; border:0 none; color:#fff; text-decoration:none;}
 .top-msg .close:hover                           { color:#000;}
+.top-msg.success                             	{ background-color:#77C596; color: #fff}
+.top-msg.error                              	{ background-color:#EF4F54; color: #fff}
+.top-msg.warning                                { background-color:#F6921E; color: #fff}
+.top-msg.info                                 	{ background-color:#C3C3B9; color: #fff}
+.top-msg.warning a                              { color: #3582AC}
+.top-msg.info a                                 { color: #222}
 
 /* container */
 .container .wrapper                             { padding-bottom:100px;}
@@ -280,4 +286,4 @@ dl.alt-style dt:nth-child(2n)					{ background:black; }
 .widjets li										{ width:50%; float:left; list-style:none outside; margin:30px 0; }
 .widjets li div									{ border:1px dashed #000; padding:20px 20px 70px; width:60%; margin:0 auto; position:relative; }
 .widjets li div img								{ max-width:100%; }
-.widjets li .btn								{ text-align:center; position:absolute; bottom:0; left:0; right:0; }
\ No newline at end of file
+.widjets li .btn								{ text-align:center; position:absolute; bottom:0; left:0; right:0; }
diff --git a/snf-astakos-app/astakos/im/static/im/js/common.js b/snf-astakos-app/astakos/im/static/im/js/common.js
index 299584d..b743709 100644
--- a/snf-astakos-app/astakos/im/static/im/js/common.js
+++ b/snf-astakos-app/astakos/im/static/im/js/common.js
@@ -114,34 +114,10 @@ $(document).ready(function() {
     
  
     
-    $('.top-msg .success').parents('.top-msg').css(
-    	{
-    		backgroundColor: '#77C596',
-    		color: '#fff'
-    	}
-    );
-    
-    $('.top-msg .error').parents('.top-msg').css(
-    	{
-    		backgroundColor: '#EF4F54',
-    		color: '#fff'
-    	}
-    );
-    
-    
-    $('.top-msg .warning').parents('.top-msg').css(
-    	{
-    		backgroundColor: '#F6921E',
-    		color: '#fff'
-    	}
-    );
-    
-    $('.top-msg .info').parents('.top-msg').css(
-    	{
-    		backgroundColor: '#C3C3B9',
-    		color: '#fff'
-    	}
-    );
+    $('.top-msg .success').parents('.top-msg').addClass('success');
+    $('.top-msg .error').parents('.top-msg').addClass('error');
+    $('.top-msg .warning').parents('.top-msg').addClass('warning');
+    $('.top-msg .info').parents('.top-msg').addClass('info');
     
     // clouds homepage animation
     $('#animation a').hover(
diff --git a/snf-astakos-app/astakos/im/templates/im/account_base.html b/snf-astakos-app/astakos/im/templates/im/account_base.html
index 04ebf18..f75af97 100644
--- a/snf-astakos-app/astakos/im/templates/im/account_base.html
+++ b/snf-astakos-app/astakos/im/templates/im/account_base.html
@@ -1,16 +1,5 @@
 {% extends "im/base.html" %}
 
-{% block extra_messages %}
-    {% if not messages %}
-        {% for msg_type, msg in GLOBAL_MESSAGES.items %}
-            <div class="{{ msg_type }}">{{ msg|safe }}</div>
-        {% endfor %}
-        {% for msg_type, msg in PROFILE_MESSAGES.items %}
-            <div class="{{ msg_type }}">{{ msg|safe }}</div>
-        {% endfor %}
-    {% endif %}
-{% endblock %}
-
 {% load filters %}
 
 {% block page.title %}Profile{% endblock %}
diff --git a/snf-astakos-app/astakos/im/templates/im/base.html b/snf-astakos-app/astakos/im/templates/im/base.html
index d9ff14e..e8616c3 100644
--- a/snf-astakos-app/astakos/im/templates/im/base.html
+++ b/snf-astakos-app/astakos/im/templates/im/base.html
@@ -1,4 +1,4 @@
-<!doctype html>
+{% load astakos_tags %}<!doctype html>
 <head>
   {% block starthead %}{% endblock starthead %}
   <meta charset="UTF-8">
@@ -74,20 +74,12 @@
 
 <body>
     <div class="container">
-	    <div class="wrapper">       
-	        {% if messages or EXTRA_MESSAGES_SET %}
-	        <div class="top-msg active">
-	            {% block extra_messages %}{% endblock %}
-	            {% for message in messages %}
-	            <div{% if message.tags %} 
-	                class="msg {{ message.tags }}"{% endif %}>
-	                {{ message|safe }}</div>
-	            {% endfor %}
-	            <a href="#" title="close" class="close">X</a>
-	        </div>
-	        {% endif %}
+        <div class="wrapper">       
+            
+            {% display_messages %}
+
 	        <div class="mainlogo">
-	        	<a href="/im/">
+                <a href="{% url astakos.im.views.index %}">
 	        		<img src="{{ IM_STATIC_URL }}images/accounts-logo.png" alt="accounts" />
 	        	</a>
 	        </div>
diff --git a/snf-astakos-app/astakos/im/templates/im/login_base.html b/snf-astakos-app/astakos/im/templates/im/login_base.html
index 300b9c8..33b1872 100644
--- a/snf-astakos-app/astakos/im/templates/im/login_base.html
+++ b/snf-astakos-app/astakos/im/templates/im/login_base.html
@@ -1,16 +1,5 @@
 {% extends 'im/base_two_cols.html'%}
 
-{% block extra_messages %}
-    {% if not messages %}
-        {% for msg_type, msg in GLOBAL_MESSAGES.items %}
-            <li class="{{ msg_type }}">{{ msg|safe }}</li>
-        {% endfor %}
-        {% for msg_type, msg in LOGIN_MESSAGES.items %}
-            <li class="{{ msg_type }}">{{ msg|safe }}</li>
-        {% endfor %}
-    {% endif %}
-{% endblock %}
-
 {% block signup_class %}hidden{% endblock %}
 {% block page.title %}{% endblock %}
 
diff --git a/snf-astakos-app/astakos/im/templates/im/signup.html b/snf-astakos-app/astakos/im/templates/im/signup.html
index 8e41245..eaeb5be 100644
--- a/snf-astakos-app/astakos/im/templates/im/signup.html
+++ b/snf-astakos-app/astakos/im/templates/im/signup.html
@@ -1,16 +1,5 @@
 {% extends 'im/base_two_cols.html' %}
 
-{% block extra_messages %}
-    {% if not messages %}
-        {% for msg_type, msg in GLOBAL_MESSAGES.items %}
-            <li class="{{ msg_type }}">{{ msg|safe }}</li>
-        {% endfor %}
-        {% for msg_type, msg in SIGNUP_MESSAGES.items %}
-            <li class="{{ msg_type }}">{{ msg|safe }}</li>
-        {% endfor %}
-    {% endif %}
-{% endblock %}
-
 {% block page.title %}
     Signup
 {% endblock %}
diff --git a/snf-astakos-app/astakos/im/templatetags/astakos_tags.py b/snf-astakos-app/astakos/im/templatetags/astakos_tags.py
new file mode 100644
index 0000000..b8b18b3
--- /dev/null
+++ b/snf-astakos-app/astakos/im/templatetags/astakos_tags.py
@@ -0,0 +1,62 @@
+from django import template
+from django.core.urlresolvers import reverse, resolve
+from django.conf import settings
+
+register = template.Library()
+
+MESSAGES_VIEWS_MAP = getattr(settings, 'ASTAKOS_MESSAGES_VIEWS_MAP', {
+    'astakos.im.views.index': 'LOGIN_MESSAGES',
+    'astakos.im.views.logout': 'LOGIN_MESSAGES',
+    'astakos.im.views.login': 'LOGIN_MESSAGES',
+    'astakos.im.views.signup': 'SIGNUP_MESSAGES',
+    'astakos.im.views.edit_profile': 'PROFILE_MESSAGES',
+    'astakos.im.views.change_password': 'PROFILE_MESSAGES',
+    'astakos.im.views.invite': 'PROFILE_MESSAGES',
+    'astakos.im.views.feedback': 'PROFILE_MESSAGES',
+})
+
+@register.tag(name='display_messages')
+def display_messages(parser, token):
+    return MessagesNode()
+
+class DummyMessage(object):
+    def __init__(self, type, msg):
+        self.message = msg
+        self.tags = type
+
+    def __repr__(self):
+        return "%s: %s" % (self.tags, self.message)
+
+class MessagesNode(template.Node):
+
+    def get_view_messages(self, context):
+        messages = list(context['GLOBAL_MESSAGES'])
+        try:
+            view = resolve(context['request'].get_full_path())[0]
+            view_name = "%s.%s" % (view.__module__, view.func_name)
+            messages += context[MESSAGES_VIEWS_MAP.get(view_name)]
+            return messages
+        except Exception, e:
+            return messages
+
+    def render(self, context):
+        if self not in context.render_context:
+            messages = list(context['messages'])
+            if context['EXTRA_MESSAGES_SET']:
+                view_messages = self.get_view_messages(context)
+                for msg_object in view_messages:
+                    messages.append(DummyMessage(msg_object[0], msg_object[1]))
+
+            if not messages:
+                return ""
+
+            cls = messages[-1].tags
+            content = '<div class="top-msg active %s">' % cls
+            for msg in messages:
+                content += '<div class="msg %s">%s</div>' % (msg.tags, msg.message)
+
+            content += '<a href="#" title="close" class="close">X</a>'
+            content += '</div>'
+            context.render_context[self] = content
+
+        return context.render_context[self]
diff --git a/snf-astakos-app/conf/20-snf-astakos-app-settings.conf b/snf-astakos-app/conf/20-snf-astakos-app-settings.conf
index 6506337..38ac2dd 100644
--- a/snf-astakos-app/conf/20-snf-astakos-app-settings.conf
+++ b/snf-astakos-app/conf/20-snf-astakos-app-settings.conf
@@ -68,24 +68,24 @@
 #ASTAKOS_RE_USER_EMAIL_PATTERNS = []
 
 # Messages to display on login page header
-# e.g. {'warning': 'This warning message will be displayed on the top of login page'}
-#ASTAKOS_LOGIN_MESSAGES = {}
+# e.g. [('warning', 'This warning message will be displayed on the top of login page')]
+#ASTAKOS_LOGIN_MESSAGES = []
 
 # Messages to display on signup page header
-# e.g. {'warning': 'This warning message will be displayed on the top of signup page'}
-#ASTAKOS_SIGNUP_MESSAGES = {}
+# e.g. [('warning', 'This warning message will be displayed on the top of signup page')]
+#ASTAKOS_SIGNUP_MESSAGES = []
 
 # Messages to display on profile page header
-# e.g. {'warning': 'This warning message will be displayed on the top of profile pages'}
-#ASTAKOS_PROFILE_MESSAGES = {}
+# e.g. [('warning', 'This warning message will be displayed on the top of profile pages')]
+#ASTAKOS_PROFILE_MESSAGES = []
 
 # Messages to display on global page header
-# e.g. {'warning': 'This warning message will be displayed on the top of all pages'}
-#ASTAKOS_GLOBAL_MESSAGES = {}
+# e.g. [('warning', 'This warning message will be displayed on the top of all pages')]
+#ASTAKOS_GLOBAL_MESSAGES = []
 
 # messages to display as extra actions in account forms
 # e.g. {'https://cms.okeanos.grnet.gr/': 'Back to ~okeanos'}
-#ASTAKOS_PROFILE_EXTRA_LINKS = {}
+#ASTAKOS_PROFILE_EXTRA_LINKS = []
 
 # The number of unsuccessful login requests per minute allowed for a specific email
 #ASTAKOS_RATELIMIT_RETRIES_ALLOWED = 3
