commit 3cbd5e4723bdd8eb61bd938e71d01ec1bc1dc875
Author: Olga Brani <olgabrani@grnet.gr>
Date:   Fri Nov 23 16:44:55 2012 +0200

    - New styles for select
    - new Class ResourcePresentation
    - Group add form javascript validation

diff --git a/snf-astakos-app/astakos/im/forms.py b/snf-astakos-app/astakos/im/forms.py
index 3d35c0d..5eecd46 100644
--- a/snf-astakos-app/astakos/im/forms.py
+++ b/snf-astakos-app/astakos/im/forms.py
@@ -539,7 +539,7 @@ class AstakosGroupCreationForm(forms.ModelForm):
         initial=True
     )
     max_participants = forms.IntegerField(
-        required=False, min_value=1
+        required=True, min_value=1
     )
 
     class Meta:
@@ -661,9 +661,11 @@ class AstakosGroupCreationSummaryForm(forms.ModelForm):
         super(AstakosGroupCreationSummaryForm, self).clean()
         self.cleaned_data['policies'] = []
         append = self.cleaned_data['policies'].append
+        print '#', self.cleaned_data
         #tbd = [f for f in self.fields if (f.startswith('is_selected_') and (not f.endswith('_proxy')))]
         tbd = [f for f in self.fields if f.startswith('is_selected_')]
         for name, uplimit in self.cleaned_data.iteritems():
+            print '####', name, uplimit
             subs = name.split('_uplimit')
             if len(subs) == 2:
                 tbd.append(name)
@@ -671,9 +673,10 @@ class AstakosGroupCreationSummaryForm(forms.ModelForm):
                 s, sep, r = prefix.partition(RESOURCE_SEPARATOR)
                 resource = Resource.objects.get(service__name=s, name=r)
                 
+                print '#### ####', resource
                 # keep only resource limits for selected resource groups
                 if self.cleaned_data.get(
-                    'is_selected_%s' % resource.group, True
+                    'is_selected_%s' % resource.group, False
                 ):
                     append(dict(service=s, resource=r, uplimit=uplimit))
         for name in tbd:
diff --git a/snf-astakos-app/astakos/im/messages.py b/snf-astakos-app/astakos/im/messages.py
index f8449d3..4595f4e 100644
--- a/snf-astakos-app/astakos/im/messages.py
+++ b/snf-astakos-app/astakos/im/messages.py
@@ -36,7 +36,7 @@ ACCOUNT_INACTIVE                        =   'Inactive account.'
 ACCOUNT_ALREADY_ACTIVE                  =   'Account is already active.'
 TOKEN_UNKNOWN                           =   'There is no user matching this token.'
 
-INVITATION_SENT                         =   'Invitation sent to %(emails.'
+INVITATION_SENT                         =   'Invitation sent to %(email)s.'
 PROFILE_UPDATED                         =   'Profile has been updated successfully.'
 FEEDBACK_SENT                           =   'Feedback successfully sent.'
 EMAIL_CHANGED                           =   'Account email has been changed successfully.'
@@ -44,8 +44,8 @@ EMAIL_CHANGE_REGISTERED                 =   'Change email request has been regis
                                                You are going to receive a verification email in the new address.'
 
 OBJECT_CREATED                          =   'The %(verbose_name)s was created successfully.'
-MEMBER_JOINED_GROUP                     =   '%(realnames has been successfully joined the group.'
-MEMBER_REMOVED                          =   '%(realnames has been successfully removed from the group.'
+MEMBER_JOINED_GROUP                     =   '%(realname)s has been successfully joined the group.'
+MEMBER_REMOVED                          =   '%(realname)s has been successfully removed from the group.'
 BILLING_ERROR                           =   'Service response status: %(status)d' 
 LOGOUT_SUCCESS                          =   'You have successfully logged out.'
 
@@ -56,7 +56,7 @@ MAX_INVITATION_NUMBER_REACHED   =           'There are no invitations left.'
 GROUP_MAX_PARTICIPANT_NUMBER_REACHED    =   'Group maximum participant number has been reached.'
 NO_APPROVAL_TERMS                       =   'There are no approval terms.'
 PENDING_EMAIL_CHANGE_REQUEST            =   'There is already a pending change email request.'
-OBJECT_CREATED_FAILED                   =   'The %(verbose_names creation failed: %(reasons.'
+OBJECT_CREATED_FAILED                   =   'The %(verbose_name)s creation failed: %(reason)s.'
 GROUP_JOIN_FAILURE                      =   'Failed to join group.'
 GROUPKIND_UNKNOWN                       =   'There is no such a group kind'
 NOT_MEMBER                              =   'User is not member of the group.'
@@ -105,7 +105,7 @@ MISSING_NEXT_PARAMETER                  =   'No next parameter'
 VERIFICATION_SENT                       =   'Verification sent.'
 
 SWITCH_ACCOUNT_LINK_SENT                =   'This email is already associated with another local account. \
-                                               To change this account to a shibboleth one follow the link in the verification email sent to %(emails. \
+                                               To change this account to a shibboleth one follow the link in the verification email sent to %(email)s. \
                                                Otherwise just ignore it.'
 NOTIFACATION_SENT                       =   'Your request for an account was successfully received and is now pending approval. \
                                                You will be notified by email in the next few days. \
diff --git a/snf-astakos-app/astakos/im/settings.py b/snf-astakos-app/astakos/im/settings.py
index 17a4d9a..9db5076 100644
--- a/snf-astakos-app/astakos/im/settings.py
+++ b/snf-astakos-app/astakos/im/settings.py
@@ -186,3 +186,68 @@ PAGINATE_BY = getattr(settings, 'ASTAKOS_PAGINATE_BY', 8)
 # Enforce token renewal on password change/reset
 NEWPASSWD_INVALIDATE_TOKEN = getattr(
     settings, 'ASTAKOS_NEWPASSWD_INVALIDATE_TOKEN', True)
+
+
+RESOURCES_PRESENTATION_DATA = getattr(
+    settings, 'ASTAKOS_RESOURCES_PRESENTATION_DATA', {
+        'groups': {
+             'compute': {
+                'help_text':'group compute help text',
+                'is_abbreviation':False,
+                'report_desc':'',
+                 'verbose_name':'compute', 
+            },
+            'storage': {
+                'help_text':'group storage help text',
+                'is_abbreviation':False,
+                'report_desc':'',
+                 'verbose_name':'storage', 
+            },
+        },
+        'resources': {
+            'pithos+.diskspace': {
+                'help_text':'resource pithos+.diskspace help text',
+                'is_abbreviation':False,
+                'report_desc':'Pithos+ Diskspace',
+                'placeholder':'eg. 10GB',
+                'verbose_name':'diskspace', 
+            },
+            'cyclades.vm': {
+                'help_text':'resource cyclades.vm help text resource cyclades.vm help text resource cyclades.vm help text resource cyclades.vm help text',
+                'is_abbreviation':True,
+                'report_desc':'Virtual Machines',
+                'placeholder':'eg. 2',
+                'verbose_name':'vm', 
+            },
+            'cyclades.disk': {
+                'help_text':'resource cyclades.disk help text',
+                'is_abbreviation':False,
+                'report_desc':'Disk',
+                'placeholder':'eg. 5GB, 2GB etc',
+                'verbose_name':'disk'
+            },
+            'cyclades.ram': {
+                'help_text':'resource cyclades.ram help text',
+                'is_abbreviation':True,
+                'report_desc':'RAM',
+                'placeholder':'eg. 4GB',
+                'verbose_name':'ram'
+            },
+            'cyclades.cpu': {
+                'help_text':'resource cyclades.cpu help text',
+                'is_abbreviation':True,
+                'report_desc':'CPUs',
+                'placeholder':'eg. 1',
+                'verbose_name':'cpu'
+            },
+            'cyclades.network.private': {
+                'help_text':'resource cyclades.network.private help text',
+                'is_abbreviation':False,
+                'report_desc':'Network',
+                'placeholder':'eg. 1',
+                'verbose_name':'private network'
+            }
+        
+        }
+        
+    })
diff --git a/snf-astakos-app/astakos/im/static/im/css/dropkick.css b/snf-astakos-app/astakos/im/static/im/css/dropkick.css
index 8f5767b..8deaa6a 100644
--- a/snf-astakos-app/astakos/im/static/im/css/dropkick.css
+++ b/snf-astakos-app/astakos/im/static/im/css/dropkick.css
@@ -14,7 +14,7 @@
 /* dropkick select extra styles */
 
 .form-row .dk_container							{ border-radius:0; margin-bottom:0; border: 1px solid #ccc; height: 21px; letter-spacing: 1px; line-height: 22px; margin-bottom: -1px; width:240px; padding:5px 0; font-weight:normal; font-family: 'Didact Gothic', Verdana, sans-serif; font-size:1em; background:transparent; color:#808080;}
-.form-row .dk_toggle  							{ border-radius:0;  padding:0;  border:0 none; text-indent:1.5em; text-decoration:none;background-image:url(../images/arrow-down_black.png); background-position:90% 5px;}
+.form-row .dk_toggle  							{ border-radius:0;  padding:0;  border:0 none; text-indent:1.5em; text-decoration:none;background-image:url(../images/arrow-down_grey.png); background-position:90% 5px;}
 .form-row .dk_toggle:hover						{ text-decoration:none; }
 .form-row .dk_open								{ background:transparent; box-shadow: none; }
 .form-row .dk_open .dk_toggle					{ background-color:transparent; border:0 none; color:#000; box-shadow: none;}
diff --git a/snf-astakos-app/astakos/im/static/im/images/arrow-down_grey.png b/snf-astakos-app/astakos/im/static/im/images/arrow-down_grey.png
new file mode 100644
index 0000000..88127ff
Binary files /dev/null and b/snf-astakos-app/astakos/im/static/im/images/arrow-down_grey.png differ
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 f39e3b7..cdc33fa 100644
--- a/snf-astakos-app/astakos/im/static/im/js/common.js
+++ b/snf-astakos-app/astakos/im/static/im/js/common.js
@@ -115,6 +115,7 @@ $(document).ready(function() {
 	$('select.dropkicked').dropkick({
 		change: function (value, label) {
 		    $(this).parents('form').submit();
+		    
 		}
 	});
     
diff --git a/snf-astakos-app/astakos/im/static/im/js/quotas.js b/snf-astakos-app/astakos/im/static/im/js/quotas.js
index aa13470..1b7bf1e 100644
--- a/snf-astakos-app/astakos/im/static/im/js/quotas.js
+++ b/snf-astakos-app/astakos/im/static/im/js/quotas.js
@@ -4,7 +4,7 @@ function group_form_show_resources(el){
 	var id = el.attr('id');
 	$('.quotas-form .group').each(function() {
 		if( $(this).hasClass(id) ) {
-			$(this).appendTo('.foo');
+			$(this).appendTo('.visible');
 			$(this).show('slow');
 			$(this).find('input')[0].focus()
 		}
@@ -68,7 +68,7 @@ $(document).ready(function() {
 		 
 		// hide relevant fieldset 
 		$(this).parents('.group').hide('slow', function() {
-		    $(this).appendTo('.not-foo');	
+		    $(this).appendTo('.not-visible');	
 		});
 		
 		group_class = $(this).parents('.group').attr('class').replace('group ', '');
@@ -114,49 +114,68 @@ $(document).ready(function() {
 		 	if ($(this).hasClass('dehumanize')){
 		 		
 		 		var flag = 0;
+
+				// check if the value is not float
+		 		var num_float = parseFloat(value);
+		 		num_float= String(num_float);
+
+		 		if (num_float.indexOf(".") == 1){
+		 			flag = 1 ; 
+		 			msg="Please enter an integer";
+		 		} else {
+		 			var num = parseInt(value);
+					if ( num == '0' ) { 
+						flag = 1 ; msg="zero"
+					} else {
+						if ( value && !num ) { flag = 1 ; msg="Invalid format"}
+				 	
+					 	var bytes = num;
+				 		
+						// remove any numbers and get suffix		 		
+				 		var suffix = value.replace( num, '');
+		
+				 		 // validate suffix. 'i' renders it case insensitive
+					 	var suf = suffix.match( new RegExp('^(GB|KB|MB|TB|bytes|G|K|M|T|byte)$', 'i'));
+					 	if (suf){
+					 		
+					 		suf = suf[0].toLowerCase(); 
+					 		suf = suf.substr(0,1);
+					 	
+						 	// transform to bytes
+						 	switch (suf){
+						 		case 'b': 
+						 		  bytes = num*Math.pow(1024,0);
+						 		  break;
+						 		case 'k':
+						 		  bytes = num*Math.pow(1024,1);
+						 		  break;
+						 		case 'm':
+						 		  bytes = num*Math.pow(1024,2);
+						 		  break;
+						 		case 'g':
+						 		  bytes = num*Math.pow(1024,3);
+						 		  break;
+						 		case 't':
+						 		  bytes = num*Math.pow(1024,4);
+						 		  break;    
+						 		default:
+						 		  bytes = num; 
+					 		}
+					 	} else {
+					 		if (num) {
+					 		 	flag = 1;
+					 		 	msg ="You must specify correct units" 
+					 		}  
+					 		 
+					 	}
+					}
+				 	
+		 			
+		 			
+		 		}
 		 		
-		 		// replace , with .  and get number 
-			 	value = value.replace(",",".");
-			 	var num = parseFloat(value);
-			 	
-			 	if ( value && !num ) { flag = 1 ; msg="Invalid format"}
-			 	
-			 	var bytes = num;
-		 		
-		 		 // get suffix. 'i' renders it case insensitive
-			 	var suf = value.match( new RegExp('GB|KB|MB|TB|bytes|G|K|M|T|byte', 'i'));
-			 	if (suf){
-			 		
-			 		suf = suf[0].toLowerCase(); 
-			 		suf = suf.substr(0,1);
+		 		 
 			 	
-				 	// transform to bytes
-				 	switch (suf){
-				 		case 'b': 
-				 		  bytes = num*Math.pow(1024,0);
-				 		  break;
-				 		case 'k':
-				 		  bytes = num*Math.pow(1024,1);
-				 		  break;
-				 		case 'm':
-				 		  bytes = num*Math.pow(1024,2);
-				 		  break;
-				 		case 'g':
-				 		  bytes = num*Math.pow(1024,3);
-				 		  break;
-				 		case 't':
-				 		  bytes = num*Math.pow(1024,4);
-				 		  break;    
-				 		default:
-				 		  bytes = num; 
-			 		}
-			 	} else {
-			 		if (num) {
-			 		 	flag = 1;
-			 		 	msg ="You must specify correct units" 
-			 		}  
-			 		 
-			 	}
 			 	
 			 	if ( flag == '1' ){ 
 			 		$(this).parents('.form-row').addClass('with-errors');
@@ -171,14 +190,15 @@ $(document).ready(function() {
 			 	
 			 	hidden_input.val(bytes);
 			 	
+			 	
 		 	}
 		 	 
-		 	// actions for int fields
+		 	// validation actions for int fields
 		 	else {
 	
 		 		var is_int = value.match (new RegExp('^[0-9]*$'));
 		 		if ( !is_int ){ 
-		 			$(this).parents('.form-row').find('.error-msg').html('Enter a positive intiger');
+		 			$(this).parents('.form-row').find('.error-msg').html('Enter a positive integer');
 			 		$(this).parents('.form-row').addClass('with-errors');
 			 		 
 			 	} else {
@@ -198,6 +218,7 @@ $(document).ready(function() {
 	 	} else {
 	 		hidden_input.removeAttr('value');
 	 	}
+	 	$('#icons span.info').removeClass('error-msg');
 	 	
 	 });
 	 
diff --git a/snf-astakos-app/astakos/im/templates/im/astakosgroup_detail.html b/snf-astakos-app/astakos/im/templates/im/astakosgroup_detail.html
index 290683a..b817935 100644
--- a/snf-astakos-app/astakos/im/templates/im/astakosgroup_detail.html
+++ b/snf-astakos-app/astakos/im/templates/im/astakosgroup_detail.html
@@ -4,9 +4,9 @@
 
 {% block page.body %}
 {% with object.owners as owners %}
-{% with object.quota as quota %}
+ 
 <div class="projects">
-	
+
 	<h2>
 	 	{% if object.is_member %}
 			<em>
@@ -79,46 +79,38 @@
 		 	<dd>{% if object.max_participants%}{{object.max_participants}}{% else %}&nbsp;{% endif %}</dd>
 		 </dl>
 	 </div>
-	 
-     <div class="full-dotted">
+	 <div class="full-dotted">
 		 <h3>RESOURCES:</h3>		 
 		 {% if quota %}
-		 <dl class="alt-style">
-		 	{% for k in quota|dkeys %}
-			 	{% with resource_catalog|lookup:'resources' as resources %}
-			 		{% with resources|lookup_uni:k as info %}
-			 		{% with resource_presentation|lookup_uni:k as resource_info %}
-						<dt>
-	           				Max {% if resource_info.is_abbreviation %}{{ info.name|upper }}{% else %}{{ info.name }}{% endif %}{% if not info.unit %}s {% endif  %}  per user
-	           			</dt>		                
-						<dd>
-						{% with quota|lookup:k as uplimit%}	
-		           			 {% if uplimit %}
-		           				 {% if info.unit %}
-		           				 	{{ uplimit|sizeof_fmt }}
-		           				 {% else %}
-		           				 	{{ uplimit|isinf }}
-		           				 {% endif %}
-		           			
-		           			{% endif %}
-		           			 
-	           			{% endwith%}
-	           			</dd>
-	           		 
-	                {% endwith%}
-	                {% endwith %}
-                {% endwith %}
-            {% endfor %}
-		</dl>
+		 <dl class="alt-style">	
+	 		{% for q in quota %}
+		 		 
+		 		<dt>
+       				Max {% if q.is_abbreviation %}{{ q.verbose_name|upper }}{% else %}{{ q.verbose_name }}{% endif %}{% if not q.unit %}s {% endif  %}  per user
+       			</dt>
+		 		<dd>
+       			{% if q.value %}
+       				 {% if q.unit %}
+       				 	{{ q.value|sizeof_fmt }}
+       				 {% else %}
+       				 	{{ q.value|isinf }}
+       				 {% endif %}
+       			{% else %}
+       				Unlimited
+       			{% endif %}
+       			</dd>
+	 		{% endfor %}
+	 	</dl>
 		{% else %}
-            <p>No policies</p>
+            <p>No resources</p>
         {% endif %} 
 	 </div>
+     
 	 <div class="full-dotted">
 	    {% with page|concat:sorting as args %}
 	    {% with object.membership_set.select_related.all|paginate:args as membership %}
             {% if membership %}
-            <form method="GET" class="minimal" action="">
+            <form method="GET" class="minimal" action="#members-table">
                 <div class="form-row">
                     <select name="sorting" onchange="this.form.submit();" class="dropkicked">
                         <option value="">Sort by</option>
@@ -128,7 +120,7 @@
                     </select>
                 </div>
             </form>
-             <table class="alt-style">
+             <table class="alt-style" id="members-table">
                 <caption>MEMBERS:</caption>
                 <thead>
                     <tr>
@@ -199,6 +191,6 @@
      
     
 </div>
-{% endwith %}
+ 
 {% endwith %}
 {% endblock %}
diff --git a/snf-astakos-app/astakos/im/templates/im/astakosgroup_form.html b/snf-astakos-app/astakos/im/templates/im/astakosgroup_form.html
index b35016e..c9465ee 100644
--- a/snf-astakos-app/astakos/im/templates/im/astakosgroup_form.html
+++ b/snf-astakos-app/astakos/im/templates/im/astakosgroup_form.html
@@ -6,10 +6,8 @@
 	<script src="{{ IM_STATIC_URL }}js/quotas.js"></script>	
 {% endblock %}	
 {% block page.body %}
- 
-	
 <form action="#top" method="post" class="withlabels quotas-form" id="group_create_form">{% csrf_token %}
-	 
+
     <fieldset class="with-info" id="top">
     	<legend>
     		1. CREATE GROUP
@@ -31,93 +29,68 @@
 		    	<span>You need to specify at least one resource</span>
 	    	</span>    
     	</legend>
-
-    {% with resource_catalog|lookup:'resources' as resources %}
-    {% with resource_catalog|lookup:'groups' as groups %}    	
     	<ul class="clearfix">
-            {% for g, rs in groups.items %}   
-            {% with resource_presentation|lookup:g as group_info %} 		
-    		<li>
-    			<a href="#{{ g }}" id="{{'group_'|add:g}}"><img src="/static/im/images/create-{{ g }}.png" alt="vm"/></a>
-    			<input type="hidden" name="proxy_{{ 'is_selected_'|add:g }}"  id="proxy_{{ 'id_is_selected_'|add:g }}">
-    			<p class="msg">{{ group_info.help_text }}</p>
-    		</li>
-    		{% endwith %}
+            {% for g, group_info in resource_catalog.groups.items %}  
+            	{% if g %}
+	    		<li>
+	    			<a href="#{{ g }}" id="{{'group_'|add:g}}"><img src="/static/im/images/create-{{ g }}.png" alt="vm"/></a>
+	    			<input type="hidden" name="proxy_{{ 'is_selected_'|add:g }}"  id="proxy_{{ 'id_is_selected_'|add:g }}">
+	    			<p class="msg">{{ group_info.help_text }}</p>
+	    		</li>
+	    		{% endif %}
             {% endfor %}
     	</ul>
     	
     </fieldset>
    
-    <div class="foo">
-    
+    <div class="visible">
+    	
+    </div>
+    <div class="not-visible">
+    	{% for gname, resources in resource_catalog.get_groups_resources %}
+	    	<div class="group {{'group_'|add:gname}}" id="{{ g }}">
+	    		<a href="#icons" class="delete">X remove resource</a>	
+	    		{% for rname, rdata in resources.items %}
+	    		<fieldset class="quota">
+			    	
+			    	<legend>
+			    		{% if rdata.is_abbreviation %}
+			    			{{ rdata.verbose_name|upper }}
+			    		{% else %}
+			    			{{ rdata.verbose_name|capfirst }}
+			    		{% endif %}
+			    		<span class="info"> 
+					    	<em>more info</em>
+					    	<span>{{ rdata.help_text }}</span>
+				    	</span>  
+			    	</legend>
+			    	<div class="form-row">
+			    		<p class="clearfix">
+			    			<label for="{{'id_'|add:rname|add:'_uplimit'}}_proxy" >
+								Max {% if rdata.is_abbreviation %}{{ rdata.verbose_name|upper }}{% else %}{{ rdata.verbose_name }}{% endif %}{% if not rdata.unit %}s {% endif  %} per user
+							</label>
+			    			<input 	type="text" 
+			       						id="{{'id_'|add:rname|add:'_uplimit'}}_proxy" 
+			       						name="{{rname|add:'_uplimit'}}_proxy" 
+			       						placeholder="{{ rdata.placeholder}} " 
+			       						{% if rdata.unit == 'bytes' %} 
+										 	class="dehumanize"
+										{% endif  %}
+			       						/> 
+			    			<span class="extra-img">&nbsp;</span>
+			         		<span class="info"><em>more info</em><span>Leave this field blank if you don't want to specify this resource</span></span>
+			         		<p class="error-msg">Invalid format</p>
+			    		</p>
+			    		<p class="msg"></p>
+			    	</div>
+				</fieldset>	
+				{% endfor %}
+	    	</div>
+	    	 
+	    {% endfor %}
     </div>
-    <div class="not-foo">
-        {% for g, rs in groups.items %}
-        
-        <div class="group {{'group_'|add:g}}" id="{{ g }}">
-			<a href="#icons" class="delete">X remove resource</a>	
-		    {% for r in rs %}
-		    {% with resource_presentation|lookup:r as resource_info %}
-		    {% with resources|lookup:r as resource%}
-		    <fieldset class="quota">
-		    	<legend>
-		    		{% if resource_info.is_abbreviation %}
-		    			{{ r|get_value_after_dot|upper }}
-		    		{% else %}
-		    			{{ r|get_value_after_dot|capfirst }}
-		    		{% endif %}
-		    		<span class="info"> 
-				    	<em>more info</em>
-				    	<span>{{ resource_info.help_text }}</span>
-			    	</span>  
-		    	</legend>
-<!--	    	<div class="form-row">
-		    		<p class="clearfix">
-		    			<label for="num_storage">Total storage</label>
-		    			<input type="text" name="num_storage">
-		    			<span class="extra-img">&nbsp;</span>
-		         		<span class="info"><em>more info</em><span>Help Text</span></span>
-		    		</p>
-		    	</div>-->
- 				 
-		    	
-		    	<div class="form-row">
-		    		<p class="clearfix">
-		    			<label for="{{'id_'|add:r|add:'_uplimit'}}_proxy" >
-							Max {% if resource_info.is_abbreviation %}{{ r|get_value_after_dot|upper }}{% else %}{{ r|get_value_after_dot }}{% endif %}{% if not resource.unit %}s {% endif  %} per user
-						</label>
-		    			<input 	type="text" 
-		       						id="{{'id_'|add:r|add:'_uplimit'}}_proxy" 
-		       						name="{{r|add:'_uplimit'}}_proxy" 
-		       						placeholder="{{ resource_info.placeholder}} " 
-		       						{% if resource.unit == 'bytes' %} 
-									 	class="dehumanize"
-									{% endif  %}
-		       						/> 
-		    			<span class="extra-img">&nbsp;</span>
-		         		<span class="info"><em>more info</em><span>Leave this field blank if you don't want to specify this resource</span></span>
-		         		<p class="error-msg">Invalid format</p>
-		    		</p>
-		    		<p class="msg"></p>
-		    	</div>
-		    	 
- 
- 
-		    </fieldset>
-		    {% endwith %}
-		    {% endwith %}
-		    {% endfor %}
-	    </div>
-	    
-    	{% endfor %}
-	</div>
-    {% endwith %}
-    {% endwith %}
-	 
     <div class="form-row submit">
- 
    		<input type="submit" value="CONTINUE" class="submit altcol" autocomplete="off">
- 
 	</div>     
 </form>
 	 
diff --git a/snf-astakos-app/astakos/im/templates/im/astakosgroup_form_summary.html b/snf-astakos-app/astakos/im/templates/im/astakosgroup_form_summary.html
index 5270b45..6929734 100644
--- a/snf-astakos-app/astakos/im/templates/im/astakosgroup_form_summary.html
+++ b/snf-astakos-app/astakos/im/templates/im/astakosgroup_form_summary.html
@@ -6,7 +6,6 @@
  
 {% with form.data as data %}	 	
 <div class="projects summary">
-	 
 	<form action="{% url group_add_complete %}" method="post" class="quotas-form">{% csrf_token %}
 		<legend>3. CONFIRM YOUR REQUEST</legend>
 <!-- 
@@ -39,41 +38,35 @@
 			 	<dd>{% if  data.max_participants %}{{ data.max_participants }}{% else %}Unlimited{% endif %}</dd>
 			 </dl>
 		 </div>
+		 
+		 
 		 <div class="full-dotted">
-			 <h3>RESOURCES:</h3>
-	           <dl class="alt-style">	           	
-	           	{% for r in policies %}
-	           		{% with r.service|add:'.'|add:r.resource as t %}
-	           		{% with resource_catalog|lookup:'resources' as resources %}
-	           		{% with resources|lookup:t as info %}
-	           		{% with resource_presentation|lookup:t as resource_info %}
-	           			<dt>
-	           				Max {% if resource_info.is_abbreviation %}{{ r.resource|upper }}{% else %}{{ r.resource }}{% endif %}{% if not info.unit %}s {% endif  %}  per user
-	           			</dt>
-	           			
-	           			<dd>
-	           			{% if r.uplimit %}
-	           				 {% if info.unit %}
-	           				 	{{ r.uplimit|sizeof_fmt }}
-	           				 {% else %}
-	           				 	{{ r.uplimit }}
-	           				 {% endif %}
-	           			{% else %}
-	           				Unlimited
-	           			{% endif %}
-	           			</dd>
-	           		{% endwith %}
-	           		{% endwith %}
-	           		{% endwith %}
-	           		{% endwith %}
-	           	{% endfor %}
-			 	
-			 </dl>
-	         
+			<h3>RESOURCES:</h3>
+		 	<dl class="alt-style">	
+		 		{% for p in policies %}
+			 		 
+			 		<dt>
+           				Max {% if p.is_abbreviation %}{{ p.name|upper }}{% else %}{{ p.name }}{% endif %}{% if not p.unit %}s {% endif  %}  per user
+           			</dt>
+			 		<dd>
+           			{% if p.uplimit %}
+           				 {% if p.unit %}
+           				 	{{ p.uplimit|sizeof_fmt }}
+           				 {% else %}
+           				 	{{ p.uplimit }}
+           				 {% endif %}
+           			{% else %}
+           				Unlimited
+           			{% endif %}
+           			</dd>
+		 		{% endfor %}
+		 	</dl>      
 		 </div>
+		 
 		 <div class="full-dotted">
 		 	 
 		 </div>
+		
 		 
 		 <div class="form-row submit">
 	   		<input type="submit" value="SUBMIT" class="submit altcol" autocomplete="off">
diff --git a/snf-astakos-app/astakos/im/templates/im/astakosgroup_list.html b/snf-astakos-app/astakos/im/templates/im/astakosgroup_list.html
index 1cde708..8edabac 100644
--- a/snf-astakos-app/astakos/im/templates/im/astakosgroup_list.html
+++ b/snf-astakos-app/astakos/im/templates/im/astakosgroup_list.html
@@ -65,8 +65,8 @@
         <div class="full-dotted">
         	<form method="GET" class="minimal" action="#searchResults"> 
 				<div class="form-row">
-					<select name="sorting" onchange="this.form.submit();" class="dropkicked">
-					    <option value="">Sort by</option>
+					<select name="sorting" onchange="this.form.submit();" class="dropkicked" tabindex="1">
+					    <option value="">Sort by Creation Date</option>
 					    <option value="groupname" {% if sorting == 'groupname' %}selected{% endif %}>Name</option>
 			            <!--option value="kindname" {% if sorting == 'kindname' %}selected{% endif %}>Type</option-->			
 			            <option value="issue_date" {% if sorting == 'issue_date' %}selected{% endif %}>Issue date</option>			
@@ -193,15 +193,14 @@
 	      	    <div >
 					<form method="GET" class="minimal" action="#allGroups" id="mygroups">
 						<div class="form-row">
-						    <select name="sorting"  class="dropkicked">
-							    <option value="">Sort by</option>
-							    <option value="groupname" {% if sorting == 'groupname' %}selected{% endif %}>Name</option>
+						    <select name="sorting"  class="dropkicked"  tabindex="1">
+							    <option value="">Sort by Creation Date</option>
+							    <option value="groupname" {% if sorting == 'groupname' %}selected{% endif %}>Sort by Name</option>
 					            <!--<option value="kindname" {% if sorting == 'kindname' %}selected{% endif %}>Type</option>-->			
-					            <option value="issue_date" {% if sorting == 'issue_date' %}selected{% endif %}>Issue date</option>			
-					            <option value="expiration_date" {% if sorting == 'expiration_date' %}selected{% endif %}>Expiration Date</option>
-					            <option value="approved_members_num" {% if sorting == 'approved_members_num' %}selected{% endif %}>Participants</option>
-					            <option value="is_enabled" {% if sorting == 'is_enabled' %}selected{% endif %}>Status</option>
-					            <option value="moderation_enabled" {% if sorting == 'moderation_enabled' %}selected{% endif %}>Moderation</option>		
+					            <option value="issue_date" {% if sorting == 'issue_date' %}selected{% endif %}>Sort by Issue date</option>			
+					            <option value="expiration_date" {% if sorting == 'expiration_date' %}selected{% endif %}>Sort by Expiration Date</option>
+					            <option value="approved_members_num" {% if sorting == 'approved_members_num' %}selected{% endif %}>Sort by Participants</option>
+					            <option value="moderation_enabled" {% if sorting == 'moderation_enabled' %}selected{% endif %}>Sort by Moderation</option>		
 							</select>
 						</div>
 					</form>
diff --git a/snf-astakos-app/astakos/im/templates/im/resource_list.html b/snf-astakos-app/astakos/im/templates/im/resource_list.html
index 7aed12d..fe1def0 100644
--- a/snf-astakos-app/astakos/im/templates/im/resource_list.html
+++ b/snf-astakos-app/astakos/im/templates/im/resource_list.html
@@ -4,34 +4,31 @@
 
 {% block page.body %}
 <div class="maincol {% block innerpage.class %}{% endblock %}">
-    <div class="stats clearfix">
+	<div class="stats clearfix">
 		<ul>
-			{% for r in data %}
-			{% with resource_presentation|lookup:r.name as resource_info %}
-    		<li class="clearfix  {{ r.load_class }} {{ r.name|get_value_after_dot}}">
-    			<div class="img-wrap">&nbsp;</div>
-    			<div class="info">
-    				<h3>{{ resource_info.report_desc }}</h3>
-    				<p>
-    					{{ r.ratio|floatformat }}% Used<br>
-    					You are using 
-    					{% if r.unit == 'bytes' %}
-    						{{ r.currValue|sizeof_fmt  }} out of your {{ r.maxValue|sizeof_fmt }}
-    					{% else %}
-    						{{ r.currValue }} {{ r.unit }} out of your {{ r.maxValue }} {{ r.unit }}
-    					{% endif %}
-    					 
-    					{% if resource_info.is_abbreviation %}{{ r.name|get_value_after_dot|upper }}{% else %}{{ r.name|get_value_after_dot }}{% endif %}{% if r.maxValue|floatformat:"0" != "1" and not r.unit %}s {% endif  %}
-    					  
-    				</p>
-    			</div>
-    			<div class="bar">
-    				<div><span style="width:{{ r.ratio|floatformat }}%;">{{ r.ratio|floatformat }}% &nbsp;&nbsp;</span></div>
-    			</div>
-    		</li>
-    		{% endwith %}
-    		{% endfor %}
-    	</ul>
-    </div>    
+			{% for rname, rdata in resource_catalog.resources.items %}
+		 		<li class="clearfix  {{ rdata.load_class }} {{ rdata.verbose_name}}">
+		 			<div class="img-wrap">&nbsp;</div>
+		 			<div class="info">
+						<h3>{{ rdata.report_desc }}</h3>
+						<p>
+						{{ rdata.ratio|floatformat }}% Used<br>
+						You are using 
+						{% if rdata.unit == 'bytes' %}
+							{{ rdata.currValue|sizeof_fmt  }} out of your {{ rdata.maxValue|sizeof_fmt }}
+						{% else %}
+							{{ rdata.currValue }} {{ rdata.unit }} out of your {{ rdata.maxValue }} {{ rdata.unit }}
+						{% endif %}		
+						{% if rdata.is_abbreviation %}{{ rdata.verbose_name|upper }}{% else %}{{ rdata.verbose_name }}{% endif %}{% if rdata.maxValue|floatformat:"0" != "1" and not rdata.unit %}s {% endif  %}
+						</p>
+					</div>
+					<div class="bar">
+						<div><span style="width:{{ rdata.ratio|floatformat }}%;">{{ rdata.ratio|floatformat }}% &nbsp;&nbsp;</span></div>
+					</div>
+		 		</li>
+		 	{% endfor%}
+		</ul>
+			 
+	</div>    
 </div>
 {% endblock %}
diff --git a/snf-astakos-app/astakos/im/views.py b/snf-astakos-app/astakos/im/views.py
index e877f16..237af07 100644
--- a/snf-astakos-app/astakos/im/views.py
+++ b/snf-astakos-app/astakos/im/views.py
@@ -87,7 +87,7 @@ from astakos.im.functions import (send_feedback, SendMailError,
                                   SendNotificationError)
 from astakos.im.endpoints.qh import timeline_charge
 from astakos.im.settings import (COOKIE_NAME, COOKIE_DOMAIN, LOGOUT_NEXT,
-                                 LOGGING_LEVEL, PAGINATE_BY)
+                                 LOGGING_LEVEL, PAGINATE_BY, RESOURCES_PRESENTATION_DATA)
 from astakos.im.tasks import request_billing
 from astakos.im.api.callpoint import AstakosCallpoint
 
@@ -667,85 +667,98 @@ def change_email(request, activation_key=None,
                            context_instance=get_context(request,
                                                         extra_context))
 
-
-
-resource_presentation = {
-       'compute': {
-            'help_text':'group compute help text',
-            'is_abbreviation':False,
-            'report_desc':''
-        },
-        'storage': {
-            'help_text':'group storage help text',
-            'is_abbreviation':False,
-            'report_desc':''
-        },
-        'pithos+.diskspace': {
-            'help_text':'resource pithos+.diskspace help text',
-            'is_abbreviation':False,
-            'report_desc':'Pithos+ Diskspace',
-            'placeholder':'eg. 10GB'
-        },
-        'cyclades.vm': {
-            'help_text':'resource cyclades.vm help text resource cyclades.vm help text resource cyclades.vm help text resource cyclades.vm help text',
-            'is_abbreviation':True,
-            'report_desc':'Virtual Machines',
-            'placeholder':'eg. 2'
-        },
-        'cyclades.disksize': {
-            'help_text':'resource cyclades.disksize help text',
-            'is_abbreviation':False,
-            'report_desc':'Disksize',
-            'placeholder':'eg. 5GB, 2GB etc'
-        },
-        'cyclades.disk': {
-            'help_text':'resource cyclades.disk help text',
-            'is_abbreviation':False,
-            'report_desc':'Disk',
-            'placeholder':'eg. 5GB, 2GB etc'
-        },
-        'cyclades.ram': {
-            'help_text':'resource cyclades.ram help text',
-            'is_abbreviation':True,
-            'report_desc':'RAM',
-            'placeholder':'eg. 4GB'
-        },
-        'cyclades.cpu': {
-            'help_text':'resource cyclades.cpu help text',
-            'is_abbreviation':True,
-            'report_desc':'CPUs',
-            'placeholder':'eg. 1'
-        },
-        'cyclades.network.private': {
-            'help_text':'resource cyclades.network.private help text',
-            'is_abbreviation':False,
-            'report_desc':'Network',
-            'placeholder':'eg. 1'
-        }
-    }
+class ResourcePresentation():
+    
+    def __init__(self, data):
+        self.data = data
+        
+    def update_from_result(self, result):
+        if result.is_success:
+            for r in result.data:
+                rname = '%s%s%s' % (r.get('service'), RESOURCE_SEPARATOR, r.get('name'))
+                if not rname in self.data['resources']:
+                    self.data['resources'][rname] = {}
+                    
+                self.data['resources'][rname].update(r)
+                self.data['resources'][rname]['id'] = rname
+                group = r.get('group')
+                if not group in self.data['groups']:
+                    self.data['groups'][group] = {}
+                    
+                self.data['groups'][r.get('group')].update({'name': r.get('group')})
+    
+    def test(self, quota_dict):
+        for k, v in quota_dict.iteritems():
+            rname = k
+            value = v
+            if not rname in self.data['resources']:
+                    self.data['resources'][rname] = {}
+                    
+ 
+            self.data['resources'][rname]['value'] = value
+            
+    
+    def update_from_result_report(self, result):
+        if result.is_success:
+            for r in result.data:
+                rname = r.get('name')
+                if not rname in self.data['resources']:
+                    self.data['resources'][rname] = {}
+                    
+                self.data['resources'][rname].update(r)
+                self.data['resources'][rname]['id'] = rname
+                group = r.get('group')
+                if not group in self.data['groups']:
+                    self.data['groups'][group] = {}
+                    
+                self.data['groups'][r.get('group')].update({'name': r.get('group')})
+                
+    def get_group_resources(self, group):
+        return dict(filter(lambda t: t[1].get('group') == group, self.data['resources'].iteritems()))
+    
+    def get_groups_resources(self):
+        for g in self.data['groups']:
+            yield g, self.get_group_resources(g)
+    
+    def get_quota(self, group_quotas):
+        print '!!!!!', group_quotas
+        for r, v in group_quotas.iteritems():
+            rname = str(r)
+            quota = self.data['resources'].get(rname)
+            quota['value'] = v
+            yield quota
+    
+    
+    def get_policies(self, policies_data):
+        for policy in policies_data:
+            rname = '%s%s%s' % (policy.get('service'), RESOURCE_SEPARATOR, policy.get('resource'))
+            policy.update(self.data['resources'].get(rname))
+            yield policy
+        
+    def __repr__(self):
+        return self.data.__repr__()
+                
+    def __iter__(self, *args, **kwargs):
+        return self.data.__iter__(*args, **kwargs)
+    
+    def __getitem__(self, *args, **kwargs):
+        return self.data.__getitem__(*args, **kwargs)
+    
+    def get(self, *args, **kwargs):
+        return self.data.get(*args, **kwargs)
+        
+        
 
 @require_http_methods(["GET", "POST"])
 @signed_terms_required
 @login_required
 def group_add(request, kind_name='default'):
+    
     result = callpoint.list_resources()
-    print '###', result
-    resource_catalog = {'resources':defaultdict(defaultdict),
-                        'groups':defaultdict(list)}
-    if result.is_success:
-        for r in result.data:
-            service = r.get('service', '')
-            name = r.get('name', '')
-            group = r.get('group', '')
-            unit = r.get('unit', '')
-            fullname = '%s%s%s' % (service, RESOURCE_SEPARATOR, name)
-            resource_catalog['resources'][fullname] = dict(unit=unit)
-            resource_catalog['groups'][group].append(fullname)
-        
-        resource_catalog = dict(resource_catalog)
-        for k, v in resource_catalog.iteritems():
-            resource_catalog[k] = dict(v)
-    else:
+    resource_catalog = ResourcePresentation(RESOURCES_PRESENTATION_DATA)
+    resource_catalog.update_from_result(result)
+    
+    if not result.is_success:
         messages.error(
             request,
             'Unable to retrieve system resources: %s' % result.reason
@@ -765,28 +778,24 @@ def group_add(request, kind_name='default'):
         form_class=AstakosGroupCreationForm
     )
     
-    resources = resource_catalog['resources']
-    
- 
     if request.method == 'POST':
         form = form_class(request.POST, request.FILES)
         if form.is_valid():
+            print '!!!!!!!!!! CLEANED DATA', form.cleaned_data
             return render_response(
                 template='im/astakosgroup_form_summary.html',
                 context_instance=get_context(request),
                 form = AstakosGroupCreationSummaryForm(form.cleaned_data),
-                policies = form.policies(),
-                resource_presentation=resource_presentation,
+                policies = resource_catalog.get_policies(form.policies()),
                 resource_catalog= resource_catalog,
-                resources = resources,
-            
             )
+         
     else:
         now = datetime.now()
         data = {
             'kind': kind,
         }
-        for group, resources in resource_catalog['groups'].iteritems():
+        for group, resources in resource_catalog.get_groups_resources():
             data['is_selected_%s' % group] = False
             for resource in resources:
                 data['%s_uplimit' % resource] = ''
@@ -803,7 +812,6 @@ def group_add(request, kind_name='default'):
         'form': form,
         'kind': kind,
         'resource_catalog':resource_catalog,
-        'resource_presentation':resource_presentation,
     }, context_processors)
     return HttpResponse(t.render(c))
 
@@ -840,9 +848,9 @@ def group_add_complete(request):
             post_save_redirect = '/im/group/%(id)s/'
             return HttpResponseRedirect(post_save_redirect % new_object)
         else:
-            msg = _(astakos_messages.OBJECT_CREATED_FAILED) %\
-                {"verbose_name": model._meta.verbose_name,
+            d = {"verbose_name": model._meta.verbose_name,
                  "reason":result.reason}
+            msg = _(astakos_messages.OBJECT_CREATED_FAILED) % d 
             messages.error(request, msg, fail_silently=True)
     return render_response(
         template='im/astakosgroup_form_summary.html',
@@ -857,7 +865,7 @@ def group_add_complete(request):
 def group_list(request):
     none = request.user.astakos_groups.none()
     sorting = request.GET.get('sorting')
-    q = AstakosGroup.objects.raw("""
+    query = """
         SELECT auth_group.id,
         %s AS groupname,
         im_groupkind.name AS kindname,
@@ -880,10 +888,17 @@ def group_list(request):
             im_astakosuser_owner.astakosgroup_id = im_astakosgroup.group_ptr_id)
         LEFT JOIN auth_user as owner ON (
             im_astakosuser_owner.astakosuser_id = owner.id)
-        WHERE im_membership.person_id = %s
-        """ % (DB_REPLACE_GROUP_SCHEME, request.user.id, request.user.id))
+        WHERE im_membership.person_id = %s 
+        """ % (DB_REPLACE_GROUP_SCHEME, request.user.id, request.user.id)
+       
+    if sorting:
+        query = query+" ORDER BY %s ASC" %sorting    
+    else:
+        query = query+" ORDER BY creation_date DESC"     
+    q = AstakosGroup.objects.raw(query)
 
-            
+       
+       
     # Create the template, context, response
     template_name = "%s/%s_list.html" % (
         q.model._meta.app_label,
@@ -965,31 +980,28 @@ def group_detail(request, group_id):
         form = MembersSortForm({'sort_by': sorting})
         if form.is_valid():
             sorting = form.cleaned_data.get('sort_by')
-
+    
+ 
+    
     result = callpoint.list_resources()
-    resource_catalog = {'resources':defaultdict(defaultdict),
-                        'groups':defaultdict(list)}
-    if result.is_success:
-        for r in result.data:
-            service = r.get('service', '')
-            name = r.get('name', '')
-            group = r.get('group', '')
-            unit = r.get('unit', '')
-            fullname = '%s%s%s' % (service, RESOURCE_SEPARATOR, name)
-            resource_catalog['resources'][fullname] = dict(unit=unit, name=name)
-            resource_catalog['groups'][group].append(fullname)
-        
-        resource_catalog = dict(resource_catalog)
-        for k, v in resource_catalog.iteritems():
-            resource_catalog[k] = dict(v)
+    resource_catalog = ResourcePresentation(RESOURCES_PRESENTATION_DATA)
+    resource_catalog.update_from_result(result)
+
+    
+    if not result.is_success:
+        messages.error(
+            request,
+            'Unable to retrieve system resources: %s' % result.reason
+    )
     
-    print '####', resource_catalog, obj.quota
+    print '######', obj.quota
+   
     extra_context = {'update_form': update_form,
                      'addmembers_form': addmembers_form,
                      'page': request.GET.get('page', 1),
                      'sorting': sorting,
                      'resource_catalog':resource_catalog,
-                     'resource_presentation':resource_presentation,}
+                     'quota':resource_catalog.get_quota(obj.quota)}
     for key, value in extra_context.items():
         if callable(value):
             c[key] = value()
@@ -1005,7 +1017,6 @@ def group_detail(request, group_id):
 @signed_terms_required
 @login_required
 def group_search(request, extra_context=None, **kwargs):
-    print '###', request
     q = request.GET.get('q')
     sorting = request.GET.get('sorting')
     if request.method == 'GET':
@@ -1050,6 +1061,7 @@ def group_search(request, extra_context=None, **kwargs):
         if sorting:
             # TODO check sorting value
             queryset = queryset.order_by(sorting)
+
     else:
         queryset = AstakosGroup.objects.none()
     return object_list(
@@ -1251,10 +1263,16 @@ def resource_list(request):
     else:
         data = None
         messages.error(request, result.reason)
+    resource_catalog = ResourcePresentation(RESOURCES_PRESENTATION_DATA)
+    resource_catalog.update_from_result_report(result)
+    
+
+    
     return render_response('im/resource_list.html',
                            data=data,
-                           resource_presentation=resource_presentation,
-                           context_instance=get_context(request))
+                           context_instance=get_context(request),
+			               resource_catalog=resource_catalog,
+                           result=result)
 
 
 def group_create_list(request):
