Skip to content

Commit

Permalink
[#176] Merge branch 'develop' into feature/176_filter_performance
Browse files Browse the repository at this point in the history
Conflicts:
	akvo/rsr/filters.py
  • Loading branch information
zzgvh committed May 20, 2014
2 parents c851baa + b76fc9d commit 7b2bcd3
Show file tree
Hide file tree
Showing 66 changed files with 2,984 additions and 625 deletions.
137 changes: 137 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,143 @@ We provide Akvo RSR as a service on your own URL and with your own branding, as
Check out [Introducing Akvo Really Simple Reporting](http://akvo.org/products/rsr/).
Read more about [Akvo Products](http://akvo.org/products/).

Akvo RSR ver 2.3.6 Voavanga
---

Wednesday 14th May 2014, adriancollier

New Features
---

### Add Update button change

If a user was attempting to add an update to a project that they didn't have the permission for, then they were being served a 403 error page. We have now changed this activity to grey out the Add Update button for users that do not have permission to add updates on individual projects.

Github issue [#150](https://github.com/akvo/akvo-rsr/issues/150)

### Character validation in admin

Now that we are working with XML more deeply with the API and IATI information, we have added validation to the RSR admin to check for any characters that have been included within the added fields that are not valid within XML. A warning is now displayed in the event that any of these characters are present.

Github issue [#242](https://github.com/akvo/akvo-rsr/issues/242)

### Back button on Akvo Pages

We have added a custom option to Akvo Pages to allow the back button to have a different text added. So now our partners can allow this button to say something more appropriate to the location that the user will be taken to upon pressing.

Github issue [#258](https://github.com/akvo/akvo-rsr/issues/258)

### Sign in target location

We have tidied up the signing in process to direct users to the main page after completing the sign in process.

Github issue [#301](https://github.com/akvo/akvo-rsr/issues/301)

### Organisation filter on Akvo Pages

We had previously removed the project filter on Akvo Pages that allows any project to be viewed within a Pages instance. This has now been extended to organisations so that organisations can be visualised within an instance without the need for that organisation to be present within projects.

Github issue [#433](https://github.com/akvo/akvo-rsr/issues/433)

### Facebook meta information

We have tidied up the meta information when sharing projects via Facebook to provide the information of the organisation that owns the Akvo Pages instance in place of Akvo.

Github issue [#442](https://github.com/akvo/akvo-rsr/issues/442)

### RSR favicon

We have replaced the favicon being used within RSR to use the more updated icon as is present within the Akvo.org website.

Github issue [#443](https://github.com/akvo/akvo-rsr/issues/443)

### Donation redirect page for Akvo Pages

We have added a new timed redirection page that users will see when completing a donation from an Akvo Pages instance. This provides information to the user to inform them that they will be leaving the previous domain and be directed to the Akvo.org donation process.

Github issue [#480](https://github.com/akvo/akvo-rsr/issues/480)

### Translation management process

We have documented our process for managing the content translations with a team of external language translators. This is just a documentation update.

Github issue [#494](https://github.com/akvo/akvo-rsr/issues/494)

### Documentation Update

We have performed a merging process to pull some recent documentation efforts into the main code repository to ensure that the right information is always available for users to see.

Github issue [#512](https://github.com/akvo/akvo-rsr/issues/512)

### Project summary pop-up Akvo Pages map widget

We have added a project summary pop-up to the Akvo Pages map widget that displays basic information about a project to the user when they click on the pin for a specific project.

Github issue [#505](https://github.com/akvo/akvo-rsr/issues/505)

### Project and organisation management flags

Following on from recent work on management flags, we have extended this functionality to projects. Now it is possible to set a flag on both projects and organisations that will prevent unwanted changes being made.

Organisations can have an owner flag set so that any changes made by other organisations inform the user that these changes could be overwritten by the managing organisation.

Partners can also set a flag on their organisation record to prevent their projects being modified by other organisations. Only Admins from the support partner organisation will be able to make changes to the project content for these projects.

Github issue [#233](https://github.com/akvo/akvo-rsr/issues/233)


Bug Fixes
---

### Blank location error

We were experiencing a problem where if new locations were added to a project but no information was completed, the admin form would not save. This has been corrected to now ignore any added but incomplete locations.

Github issue [#312](https://github.com/akvo/akvo-rsr/issues/312)

### Budget totals

We previously had 2 different budget items within the dataset that referred to total budgets. This has now been consolidated so that we only have a single entry and all information will be merged to this single entry.

Github issue [#471](https://github.com/akvo/akvo-rsr/issues/471)

### Akvo Pages widgets layout error

We have tidied up some layout issues with the widgets being provided for Akvo Pages.

Github issue [#498](https://github.com/akvo/akvo-rsr/issues/498)

### Wrapped links on project pages

We have fixed an issue that long links provided on projects were extending beyond the box provided in the visual layout. These links will now wrap to the next line if they are too long to fit within the available space.

Github issue [#506](https://github.com/akvo/akvo-rsr/issues/506)

### Global maps in Internet Explorer 8

We have resolved some visualisation issues when viewing the global maps in IE8. Now the maps are correctly displaying the points.

Github issue [#507](https://github.com/akvo/akvo-rsr/issues/507)

### IATI export missing data

We were missing some date information within the budget item export when creating IATI files. This prevented the files from validating as a correct IATI XML file. This has now been included.

Github issue [#533](https://github.com/akvo/akvo-rsr/issues/533)

### Live server logging

We have made a small change to the underlying code that will provide better logging information for our system to help discover and troubleshoot any issues that occur.

Github issue [#432](https://github.com/akvo/akvo-rsr/issues/432)

### Using Sentry within RSR

We have added Sentry as a tool to assist us with monitoring and logging with RSR as part of our efforts to ensure we have a great performing system and access to all the right information to investigate when things don't go entirely to plan. You can read more about Sentry [here](http://sentry.readthedocs.org/en/latest/).

Github issue [#541](https://github.com/akvo/akvo-rsr/issues/541)


Akvo RSR ver 2.3.5 Uglyfruit
---

Expand Down
Binary file modified akvo/mediaroot/akvo/img/base/favicon.ico
Binary file not shown.
Binary file modified akvo/mediaroot/akvo/img/favicon.ico
Binary file not shown.
10 changes: 8 additions & 2 deletions akvo/mediaroot/ps_widgets/projectList.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,17 @@ td.projectDescrTd { width: 35%; }
td.projectLocTd { width: 15%; }
td.projectStatusTd { width: 15%; }
td.projectPartnerTd { width: 15%; }
td.projectFundingTd { margin-top:-45px; display:inline-block !important;}
td.projectFundingTd {
margin-top:-45px;
display:inline-block !important;
width:90%;
height:220px;
}
.projectListWidget .projectBudget {
position: relative;
overflow: auto;
float: none;
width: 95%;
width: 100%;
margin: 0;
}
.projectStatusTd span { display: block; }
Expand All @@ -87,6 +92,7 @@ td.projectFundingTd { margin-top:-45px; display:inline-block !important;}
white-space: normal;
text-overflow: ellipsis;
overflow: hidden;
line-height: 1.5;
}
.rsrWidget {
font-size:0.8em;
Expand Down
6 changes: 2 additions & 4 deletions akvo/mediaroot/ps_widgets/rsrWidgets.css
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,6 @@ ul.basicInfo li .projectLocation {
background: url(pinLocation.png) left center no-repeat;
margin: 0 0 0 5px;
text-overflow: ellipsis;
overflow: hidden;
line-height: 1;
}
#container.lightBG ul.basicInfo li .projectLocation {
Expand Down Expand Up @@ -428,11 +427,10 @@ li.neededBudget {
.html5-progress-bar progress {
background-color: #f3f3f3;
border: 0;
width: 90%;
height: 2px;
border-radius: 9px;
border-radius: 15px;
margin: 0 auto;
border: 3px solid rgb(52,52,52);
width: 95%;
}
.html5-progress-bar progress::-webkit-progress-bar {
background-color: rgb(225,225,225);
Expand Down
2 changes: 1 addition & 1 deletion akvo/mediaroot/ps_widgets/w170px.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
display: inline-block;
position: relative;
float: none;
width: 148px;
width: 95%;
margin: 10px 5px 0 0;
max-height: none;
padding: 15px 4px;
Expand Down
60 changes: 45 additions & 15 deletions akvo/rsr/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,14 @@ def clean(self):
for form in self.forms:
if form.is_valid() and not form.cleaned_data.get('DELETE', False):
form_count += 1
primary_count += 1 if form.cleaned_data['primary'] else 0
try:
primary_count += 1 if form.cleaned_data['primary'] else 0
except:
pass
# if we have any forms left there must be exactly 1 primary location
if form_count > 0 and not primary_count == 1:
self._non_form_errors = ErrorList([
_(u'The project must have exactly one primary location if any locations at all are to be included')
_(u'The project must have exactly one filled in primary location if any locations at all are to be included')
])


Expand Down Expand Up @@ -120,7 +123,7 @@ class OrganisationAdmin(TimestampsAdminDisplayMixin, admin.ModelAdmin):
fieldsets = (
(_(u'General information'), {'fields': ('name', 'long_name', 'partner_types', 'organisation_type',
'new_organisation_type', 'logo', 'url', 'iati_org_id', 'language',
'content_owner',)}),
'allow_edit',)}),
(_(u'Contact information'), {'fields': ('phone', 'mobile', 'fax', 'contact_person', 'contact_email', ), }),
(_(u'About the organisation'), {'fields': ('description', 'notes',)}),
)
Expand Down Expand Up @@ -354,9 +357,28 @@ class BudgetItemLabelAdmin(admin.ModelAdmin):
admin.site.register(get_model('rsr', 'budgetitemlabel'), BudgetItemLabelAdmin)


class BudgetItemAdminInLineFormSet(forms.models.BaseInlineFormSet):
def clean(self):
super(BudgetItemAdminInLineFormSet, self).clean()

budget_item_count = 0
including_total = False
for form in self.forms:
if not form.is_valid():
return
if form.cleaned_data and not form.cleaned_data.get('DELETE'):
budget_item_count += 1
if form.cleaned_data.get('label').label == 'total':
including_total = True

if budget_item_count > 1 and including_total:
raise forms.ValidationError(_("The 'total' budget item cannot be used in combination with other budget items."))


class BudgetItemAdminInLine(admin.TabularInline):
model = get_model('rsr', 'budgetitem')
extra = 1
formset = BudgetItemAdminInLineFormSet

class Media:
css = {'all': (os.path.join(settings.MEDIA_URL, 'akvo/css/src/rsr_admin.css').replace('\\', '/'),)}
Expand Down Expand Up @@ -674,12 +696,14 @@ def queryset(self, request):
"""
qs = super(ProjectAdmin, self).queryset(request)
opts = self.opts
user_profile = request.user.get_profile()
if request.user.has_perm(opts.app_label + '.' + opts.get_change_permission()):
return qs
elif request.user.has_perm(opts.app_label + '.' + get_rsr_limited_change_permission(opts)):
projects = request.user.get_profile().organisation.all_projects()
#projects = get_model('rsr', 'organisation').projects.filter(pk__in=[request.user.get_profile().organisation.pk])
return qs.filter(pk__in=projects)
projects = user_profile.organisation.all_projects()
# Access to Partner users may be limited by Support partner "ownership"
allowed_projects = [project.pk for project in projects if user_profile.allow_edit(project)]
return qs.filter(pk__in=allowed_projects)
else:
raise PermissionDenied

Expand All @@ -695,17 +719,23 @@ def has_change_permission(self, request, obj=None):
"own" projects, organisation and user profiles
"""
opts = self.opts
if request.user.has_perm(opts.app_label + '.' + opts.get_change_permission()):
user = request.user
user_profile = user.get_profile()

# RSR editors/managers
if user.has_perm(opts.app_label + '.' + opts.get_change_permission()):
return True
if request.user.has_perm(opts.app_label + '.' + get_rsr_limited_change_permission(opts)):
projects = request.user.get_profile().organisation.all_projects()
#projects = get_model('rsr', 'organisation').projects.filter(pk__in=[request.user.get_profile().organisation.pk])

# RSR Partner admins/editors
if user.has_perm(opts.app_label + '.' + get_rsr_limited_change_permission(opts)):
# On the Project form
if obj:
return obj in projects
else:
return True
return user_profile.allow_edit(obj)
return True

return False


@csrf_protect_m
@transaction.commit_on_success
def add_view(self, request, form_url='', extra_context=None):
Expand Down Expand Up @@ -1100,7 +1130,7 @@ class ProjectUpdateAdmin(TimestampsAdminDisplayMixin, admin.ModelAdmin):
'fields': ('title','text','language', ),
}),
(_(u'Image and video'), {
'fields': ('photo', 'photo_location', 'photo_caption', 'photo_credit', 'video', 'video_caption', 'video_credit',),
'fields': ('photo', 'photo_caption', 'photo_credit', 'video', 'video_caption', 'video_credit',),
}),
)
#Methods overridden from ModelAdmin (django/contrib/admin/options.py)
Expand Down Expand Up @@ -1179,7 +1209,7 @@ class PartnerSiteAdmin(TimestampsAdminDisplayMixin, admin.ModelAdmin):
fieldsets = (
# the 'notes' field is added in get_fieldsets() for eligible users
(u'General', dict(fields=('organisation', 'enabled',))),
(u'HTTP', dict(fields=('hostname', 'cname', 'custom_return_url',))),
(u'HTTP', dict(fields=('hostname', 'cname', 'custom_return_url', 'custom_return_url_text'))),
(u'Style and content',
dict(fields=('about_box', 'about_image', 'custom_css', 'custom_logo', 'custom_favicon',))),
(u'Languages and translation', dict(fields=('default_language', 'ui_translation', 'google_translation',))),
Expand Down
24 changes: 23 additions & 1 deletion akvo/rsr/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

from south.modelsinspector import add_introspection_rules

from akvo.rsr.validators import string_validator


class NullCharField(models.CharField):

Expand Down Expand Up @@ -48,7 +50,25 @@ def __init__(self, *args, **kwargs):
self.validators = [MinValueValidator(-180), MaxValueValidator(180)]


class LimitedTextField(models.TextField):
class ValidXMLCharField(models.CharField):

description = "A CharField containing only valid XML characters"

def __init__(self, *args, **kwargs):
super(ValidXMLCharField, self).__init__(*args, **kwargs)
self.validators += [string_validator]


class ValidXMLTextField(models.TextField):

description = "A TextField containing only valid XML characters"

def __init__(self, *args, **kwargs):
super(ValidXMLTextField, self).__init__(*args, **kwargs)
self.validators += [string_validator]


class LimitedTextField(ValidXMLTextField):

description = "A TextField that honors the max_length param"

Expand Down Expand Up @@ -78,5 +98,7 @@ def clean(self, value, model_instance):
add_introspection_rules([], ["^akvo\.rsr\.fields\.NullCharField"])
add_introspection_rules([], ["^akvo\.rsr\.fields\.LatitudeField"])
add_introspection_rules([], ["^akvo\.rsr\.fields\.LongitudeField"])
add_introspection_rules([], ["^akvo\.rsr\.fields\.ValidXMLCharField"])
add_introspection_rules([], ["^akvo\.rsr\.fields\.ValidXMLTextField"])
add_introspection_rules([], ["^akvo\.rsr\.fields\.LimitedTextField"])
add_introspection_rules([], ["^akvo\.rsr\.fields\.ProjectLimitedTextField"])
4 changes: 1 addition & 3 deletions akvo/rsr/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@

from akvo.rsr.iso3166 import CONTINENTS

from akvo.rsr.models import (
Organisation, Project, STATUSES, CURRENCY_CHOICES
)
from akvo.rsr.models import Organisation, Project, STATUSES, CURRENCY_CHOICES

class CheckboxMultipleChoiceField(MultipleChoiceField):
widget = widgets.CheckboxSelectMultiple
Expand Down
6 changes: 0 additions & 6 deletions akvo/rsr/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,6 @@ def get_form(self, request, obj=None, **kwargs):
class ProjectUpdateForm(forms.ModelForm):
"""Form representing a ProjectUpdate."""

MEDIA_LOCATIONS = (
('B', _('At the beginning of the update.')),
('E', _('At the end of the update.'))
)
title = forms.CharField(widget=forms.TextInput(attrs={
'class': 'input',
'size': '42',
Expand All @@ -347,8 +343,6 @@ class ProjectUpdateForm(forms.ModelForm):
'size': '15',
'style': 'height: 2em',
}))
photo_location = forms.CharField(required=False, widget=forms.RadioSelect(
choices=ProjectUpdate.PHOTO_LOCATIONS, attrs={'class': 'radio'}))
photo_caption = forms.CharField(required=False, widget=forms.TextInput(attrs={
'class': 'input',
'size': '25',
Expand Down
Loading

0 comments on commit 7b2bcd3

Please sign in to comment.