Commit e5998e96 authored by Kostas Papadimitriou's avatar Kostas Papadimitriou

astakos: New projects improvements

- Fine grained handling of project modification field (exclude unchanged fields)
- Display modified fields in project modification details/summary views
- Set distinguished content in project/app details/summary views
- Minor styling improvements
parent bad53f57
......@@ -767,7 +767,7 @@ class ProjectApplicationForm(forms.ModelForm):
def clean(self):
userid = self.data.get('user', None)
self.resource_policies
policies = self.resource_policies
self.user = None
if userid:
try:
......@@ -776,8 +776,8 @@ class ProjectApplicationForm(forms.ModelForm):
pass
if not self.user:
raise forms.ValidationError(_(astakos_messages.NO_APPLICANT))
super(ProjectApplicationForm, self).clean()
return self.cleaned_data
cleaned_data = super(ProjectApplicationForm, self).clean()
return cleaned_data
@property
def resource_policies(self):
......@@ -908,7 +908,7 @@ class ProjectApplicationForm(forms.ModelForm):
return policies
def fill_api_data(self):
def get_api_data(self):
data = dict(self.cleaned_data)
is_new = self.instance.id is None
if isinstance(self.instance, Project):
......@@ -916,18 +916,45 @@ class ProjectApplicationForm(forms.ModelForm):
else:
data['project_id'] = self.instance.chain.id if not is_new else None
data['owner'] = self.user.uuid if is_new else self.instance.owner.uuid
data['resources'] = self.cleaned_resource_policies()
data['request_user'] = self.user
user_uuid = self.user.uuid if is_new else self.instance.owner.uuid
data['owner'] = AstakosUser.objects.get(uuid=user_uuid)
exclude_keys = ['owner', 'comments', 'project_id', 'start_date']
# is_valid changes instance attributes
instance = self.instance
if not is_new:
instance = Project.objects.get(pk=self.instance.pk)
for key in [dkey for dkey in data.keys() if not dkey in exclude_keys]:
if not is_new and \
(getattr(instance, key) == data.get(key)):
del data[key]
resources = self.cleaned_resource_policies()
if resources:
data['resources'] = resources
if data.get('start_date', None):
data['start_date'] = date_util.isoformat(data.get('start_date'))
data['end_date'] = date_util.isoformat(data.get('end_date'))
data['max_members'] = data.get('limit_on_members_number')
else:
del data['start_date']
if data.get('end_date', None):
data['end_date'] = date_util.isoformat(data.get('end_date'))
if 'limit_on_members_number' in data:
data['max_members'] = data.get('limit_on_members_number')
data['request_user'] = self.user
if 'owner' in data:
data['owner'] = data['owner'].uuid
return data
def save(self, commit=True, **kwargs):
from astakos.api import projects as api
data = self.fill_api_data()
data = self.get_api_data()
return api.submit_new_project(data, self.user)
......@@ -941,7 +968,7 @@ class ProjectModificationForm(ProjectApplicationForm):
def save(self, commit=True, **kwargs):
from astakos.api import projects as api
data = self.fill_api_data()
data = self.get_api_data()
return api.submit_modification(data, self.user, self.instance.uuid)
......
......@@ -212,9 +212,26 @@ h2 .header-actions { float: right; font-size: 0.8em;}
color:#F24E53;
font-family: monospace;
}
.policy-diff.green {
color: green;
}
.policy-diff.gray {
color: #444;
}
.policy-diff.red {
color: red;
}
.policy-diff.details span {
color: #aaa;
}
.policy-diff.details {
display: block;
padding: 0;
margin: 0;
font-size: 0.8em;
}
{% extends "im/projects/project_detail.html" %}
{% load filters %}
{% block project.title %}
{% if is_modification %}
......@@ -19,10 +20,50 @@ PROJECT APPLICATION {{ object.state_display|upper}}
{% endif %}
{% endblock %}
{% block object.details.name %}
{{ object.name }}
{% block page.project_details %}
<dt>Name</dt>
<dd>
{{ application|display_modification_param:"name" }}&nbsp;
</dd>
<dt>Homepage url</dt>
<dd>
{{ application|display_modification_param:"homepage" }}&nbsp;
</dd>
<dt>Description</dt>
<dd>
{{ application|display_modification_param:"description" }}&nbsp;
</dd>
<dt>End Date</dt>
<dd>{{ application|display_date_modification_param:"end_date,d/m/Y" }}&nbsp;</dd>
<dt>Owner</dt>
{% if admin_mode %}
<dd>{{ application|display_modification_param:"owner,owner_admin" }}&nbsp;</dd>
{% else %}
{% if owner_mode %}
<dd>{{ application|display_modification_param:"owner,owner_owner" }}&nbsp;</dd>
{% else %}
<dd>{{ application|display_modification_param:"owner,owner" }}&nbsp;</dd>
{% endif %}
{% endif %}
</dl>
</div>
<div class="full-dotted">
<h3>MEMBERSHIP OPTIONS</h3>
<dl class="alt-style">
<dt>Member join policy</dt>
<dd>{{ application|display_modification_param:"member_join_policy" }}&nbsp;</dd>
<dt>Member leave policy</dt>
<dd>{{ application|display_modification_param:"member_leave_policy" }}&nbsp;</dd>
<dt>Total number of members</dt>
<dd>{{ application|display_modification_param_diff:"limit_on_members_number" }}&nbsp;</dd>
{% endblock %}
{% block object.created_at %}
<dd>{{object.issue_date|date:"d/m/Y"}}&nbsp;</dd>
{% block page.members %}{% endblock %}
{% block page.resources_heading %}
{% if is_modification %}
MODIFIED RESOURCES (per user / total)
{% else %}
{{ block.super }}
{% endif %}
{% endblock %}
......@@ -36,16 +36,15 @@
<div class="full-dotted">
<h3>PROJECT DETAILS</h3>
<dl class="alt-style">
{% block page.project_details %}
<dt>Name</dt>
<dd>
{% block object.details.name %}{{ object.realname|upper }}{% endblock %}&nbsp;
</dd>
<dd>{{ object.realname }}&nbsp;</dd>
<dt>Homepage url</dt>
<dd>
{% if object.homepage %}
<a href="{{ object.homepage }}">{{ object.homepage }}</a>
<a href="{{ object.homepage }}">{{ object.homepage }}</a>
{% else %}
Not set yet
Not set yet
{% endif %}
</dd>
<dt>Description</dt>
......@@ -63,19 +62,23 @@
<dt>Owner</dt>
<dd>
{% if owner_mode %}
Me
{% else %}
{{object.owner.realname}} {% if admin_mode or user.is_superuser %}({{object.owner.email}}){% endif %}
{% if owner_mode %}
Me
{% else %}
{{ object.owner.realname }}
{% if admin_mode or user.is_superuser %}
({{object.owner.email}})
{% endif %}
{% endif %}
&nbsp;
</dd>
{% endblock page.project_details %}
</dl>
</div>
<div class="full-dotted">
<h3>RESOURCES (per user / total)</h3>
<h3>{% block page.resources_heading %}RESOURCES (per user / total){% endblock %}</h3>
{% if resources_set.all %}
<dl class="alt-style">
{% for rp in resources_set.all|sorted_resources %}
......@@ -102,7 +105,7 @@
{% endif %}
</div>
{% block page.members %}
<div class="full-dotted">
<h3>
......@@ -158,6 +161,7 @@
{% endif %}
</div>
{% endblock page.members %}
{% endblock inner_project %}
<div class="full-dotted">
......
......@@ -8,7 +8,7 @@
{% endblock %}
{% block page.body %}
<h2>{% block form_title %}REQUEST PROJECT{% endblock %}</h2>
<h2>{% block page.heading %}REQUEST PROJECT{% endblock %}</h2>
<form action="?verify=1"
method="post"
......
......@@ -8,12 +8,19 @@
{% block page.body %}
<h2>
{% if update_form %}REQUEST PROJECT MODIFICATION{% else %}REQUEST PROJECT{% endif %}
{% block page.heading %}
REQUEST PROJECT
{% endblock %}
</h2>
<p>These are the specifications of the Project you want to create. If you hit the "Submit" button
this form will be officially sent to {{ BRANDING_COMPANY_NAME }} for review. Please make sure the following reflect
exactly your request.</p>
<p>
{% block page.description %}
These are the specifications of the Project you want to create. If you hit the
"Submit" button this form will be officially sent to {{ BRANDING_COMPANY_NAME }}
for review. Please make sure the following reflect exactly your request.
{% endblock %}
</p>
<div class="projects summary">
<form action="?edit=0&verify=0" method="post" class="quotas-form">{% csrf_token %}
......@@ -23,9 +30,10 @@ exactly your request.</p>
{% endif %}
{% endfor %}
<div class="full-dotted">
<h3>PROJECT DETAILS</h3>
<h3>{% block page.project_details.heading %}PROJECT DETAILS{% endblock %}</h3>
<p class="restricted">{{ form_data.desc }}</p>
<dl class="alt-style">
<dl class="alt-style">
{% block page.project_details %}
<dt>Name</dt>
<dd>{{ form_data.name }}&nbsp;</dd>
<dt>Homepage Url</dt>
......@@ -40,18 +48,20 @@ exactly your request.</p>
<dd>{{ form_data.end_date|date:"d/m/Y"}}&nbsp;</dd>
<dt>Comments</dt>
<dd>{{ form_data.comments }}&nbsp;</dd>
{% endblock %}
</dl>
</div>
<div class="full-dotted">
<h3>MEMBERSHIP OPTIONS</h3>
<dl class="alt-style">
{% block page.project_membership_details %}
<dt>Member join policy</dt>
<dd>{{ join_policies|lookup:form_data.member_join_policy|title }}</dd>
<dt>Member leave policy</dt>
<dd>{{ leave_policies|lookup:form_data.member_leave_policy|title }}</dd>
<dt>Total number of members</dt>
<dd>{{ form_data.limit_on_members_number }}</dd>
{% endblock %}
</dl>
</div>
<div class="full-dotted">
......@@ -75,8 +85,9 @@ exactly your request.</p>
{% if rp.p_diff %}
{% with rp.p_diff as diff %}
<span class="policy-diff
{% if diff.increased %}green{% else %}red{% endif %}"
>({{diff.operator}}{{ diff.diff_display }})</span>
{% if diff.increased %}green{% else %}red{% endif %}">
({{diff.operator}}{{ diff.diff_display }})
</span>
{% endwith %}
{% endif %}
</dd>
......@@ -92,7 +103,8 @@ exactly your request.</p>
<input type="hidden" name="user" id="id_user" value="{{user.id}}">
<div class="form-row submit">
<input type="submit" value="BACK" class="submit lt" onclick='this.form.action="?edit=1&verify=0";'>
<input type="submit" value="BACK" class="submit lt"
onclick='this.form.action="?edit=1&verify=0";'>
<input type="submit" value="SUBMIT" class="submit" >
<a href="{% url project_list %}" class="rt-link">CANCEL</a>
</div>
......
{% extends "im/projects/projectapplication_form.html" %}
{% block page.heading %}REQUEST PROJECT MODIFICATION{% endblock %}
{% extends "im/projects/projectapplication_form_summary.html" %}
{% load filters %}
{% block form.start_date %}
{% block page.heading %}
REQUEST PROJECT MODIFICATION
{% endblock %}
{% block page.description %}
These are the modifications you want to apply to the Project. If you hit the
"Submit" button this form will be officially sent to {{ BRANDING_COMPANY_NAME }}
for review. Please make sure the following reflect exactly your modification
request.
{% endblock %}
{% block page.project_details %}
<dt>Name</dt>
<dd>{{ form|display_modification_param:"name" }}&nbsp;</dd>
<dt>Homepage Url</dt>
<dd>{{ form|display_modification_param:"homepage" }}&nbsp;</dd>
<dt>Description</dt>
<dd>{{ form|display_modification_param:"description" }}&nbsp;</dd>
<dt>End Date</dt>
<dd>{{ form|display_date_modification_param:"end_date,d/m/Y" }}&nbsp;</dd>
<dt>Comments</dt>
<dd>{{ form_data.comments }}&nbsp;</dd>
{% endblock %}
{% block page.project_membership_details %}
<dt>Member join policy</dt>
<dd>{{ form|display_modification_param:"member_join_policy" }}&nbsp;</dd>
<dt>Member leave policy</dt>
<dd>{{ form|display_modification_param:"member_leave_policy" }}&nbsp;</dd>
<dt>Total number of members</dt>
<dd>{{ form|display_modification_param_diff:"limit_on_members_number" }}&nbsp;</dd>
{% endblock %}
......@@ -41,13 +41,15 @@ from django import template
from django.core.paginator import Paginator, EmptyPage
from django.db.models.query import QuerySet
from django.utils.safestring import mark_safe
from django.template import defaultfilters
from synnefo.lib.ordereddict import OrderedDict
from astakos.im import settings
from astakos.im.models import ProjectResourceGrant
from astakos.im.models import ProjectResourceGrant, Project
from astakos.im.views import util as views_util
from astakos.im import util
from astakos.im import presentation
register = template.Library()
......@@ -259,3 +261,145 @@ def is_denied_app(app):
if not app:
return False
return app.state in [app.DENIED]
def _member_policy_formatter(form_or_app, value, changed, mapping):
if changed:
changed = defaultfilters.title(mapping.get(changed))
value = defaultfilters.title(mapping.get(value))
return value, changed, None, None
def _owner_formatter(form_or_app, value, changed):
if not changed:
changed_name = None
else:
changed_name = changed.realname
return value.realname, changed_name, None, None
def _owner_admin_formatter(form_or_app, value, changed):
if not changed:
changed_name = None
else:
changed_name = changed.realname + " (%s)" % changed.email
return value.realname + " (%s)" % value.email, changed_name, None, None
def _owner_owner_formatter(form_or_app, value, changed):
if not changed:
changed_name = None
else:
changed_name = changed.realname
return "Me", changed_name, None, None
MODIFICATION_FORMATTERS = {
'member_policy': _member_policy_formatter,
'owner': _owner_formatter,
'owner_admin': _owner_admin_formatter,
'owner_owner': _owner_owner_formatter
}
@register.filter
def display_modification_param(form_or_app, param, formatter=None):
formatter_name = None
if "," in param:
param, formatter_name = param.split(",", 1)
project_attr = param
if hasattr(form_or_app, 'instance'):
# form
project = Project.objects.get(pk=form_or_app.instance.pk)
app_value = form_or_app.cleaned_data[param]
project_value = getattr(project, project_attr)
else:
# app
project = form_or_app.chain
app_value = getattr(form_or_app, project_attr)
project_value = getattr(project, project_attr)
if app_value == None:
app_value = project_value
formatter_params = {}
if param == "member_join_policy":
formatter_name = 'member_policy'
formatter_params = {'mapping':
presentation.PROJECT_MEMBER_JOIN_POLICIES}
if param == "member_leave_policy":
formatter_name = 'member_policy'
formatter_params = {'mapping':
presentation.PROJECT_MEMBER_LEAVE_POLICIES}
changed = False
changed_cls = "gray details"
if project_value != app_value:
changed = project_value
if not formatter and formatter_name:
formatter = MODIFICATION_FORMATTERS.get(formatter_name)
changed_prefix = "<span>current: </span>"
if formatter:
app_value, changed, cls, prefix = formatter(form_or_app,
app_value, changed,
**formatter_params)
if cls:
changed_cls = cls
if prefix:
changed_prefix = prefix
tpl = """%(value)s"""
if changed:
tpl += """<span class="policy-diff %(changed_cls)s">""" + \
"""%(changed_prefix)s%(changed)s</span>"""
return mark_safe(tpl % {
'value': app_value,
'changed': changed,
'changed_cls': changed_cls,
'changed_prefix': changed_prefix
})
@register.filter
def display_modification_param_diff(form_or_app, param):
def formatter(form_or_app, value, changed):
if changed in [None, False]:
return value, changed, None, " "
diff = value - changed
sign = "+"
cls = "green"
if diff < 0:
sign = "-"
diff = abs(diff)
cls = "red"
if diff != 0:
changed = "(%s)" % (sign + str(diff))
else:
changed = None
return value, changed, cls, " "
return display_modification_param(form_or_app, param, formatter)
@register.filter
def display_date_modification_param(form_or_app, params):
param, date_format = params.split(",", 1)
def formatter(form_or_app, value, changed):
if changed not in [None, False]:
changed = defaultfilters.date(changed, date_format)
formatted_value = defaultfilters.date(value, date_format)
return formatted_value, changed, None, None
return display_modification_param(form_or_app, param, formatter)
......@@ -293,6 +293,7 @@ def project_or_app_detail(request, project_uuid, app_id=None):
queryset = ProjectApplication.objects.select_related()
object_id = application.pk
resources_set = application.resource_set
project_resources_set = project.resource_set
template_name = "im/projects/project_application_detail.html"
return object_detail(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment