Skip to content

Commit

Permalink
Merge pull request #940 from akvo/933_add_update
Browse files Browse the repository at this point in the history
[#933] Add an update page
  • Loading branch information
kardan committed Dec 2, 2014
2 parents c60626d + 4439a06 commit 1a96177
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 42 deletions.
2 changes: 1 addition & 1 deletion akvo/rest/views/project_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ def get_queryset(self):
uuid = self.request.QUERY_PARAMS.get('uuid', None)
if uuid is not None:
queryset = self.queryset.filter(uuid=uuid)
return queryset
return queryset
105 changes: 104 additions & 1 deletion akvo/rsr/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@

from registration.models import RegistrationProfile

from .models import Country, Organisation
from urlparse import urlsplit, urlunsplit

from .models import Country, Organisation, ProjectUpdate, ProjectUpdateLocation

from akvo import settings

class RegisterForm(forms.Form):
email = forms.EmailField(
Expand Down Expand Up @@ -204,3 +208,102 @@ def save(self, request):
"""
# TODO: The approval process of users
request.user.organisations.add(self.cleaned_data['organisation'])


class ProjectUpdateForm(forms.ModelForm):
"""Form representing a ProjectUpdate."""

title = forms.CharField(label='', widget=forms.TextInput(attrs={
'class': 'input',
'size': '42',
'maxlength': '50',
'placeholder': 'Title',
}))
text = forms.CharField(label='', required=False, widget=forms.Textarea(attrs={
'class': 'textarea',
'placeholder': 'Description',
}))
language = forms.ChoiceField(choices=settings.LANGUAGES, initial='en')
photo = forms.ImageField(required=False, widget=forms.FileInput(attrs={
'class': 'input',
'size': '15',
}))
photo_caption = forms.CharField(label='', required=False, widget=forms.TextInput(attrs={
'class': 'input',
'size': '25',
'maxlength': '75',
'placeholder': 'Photo caption',
}))
photo_credit = forms.CharField(label='', required=False, widget=forms.TextInput(attrs={
'class': 'input',
'size': '25',
'maxlength': '25',
'placeholder': 'Photo credit',
}))
video = forms.CharField(required=False, widget=forms.TextInput(attrs={
'class': 'input',
'size': '42',
'maxlength': '255',
'placeholder': 'Video link',
}))
video_caption = forms.CharField(label='', required=False, widget=forms.TextInput(attrs={
'class': 'input',
'size': '25',
'maxlength': '75',
'placeholder': 'Video caption',
}))
video_credit = forms.CharField(label='', required=False, widget=forms.TextInput(attrs={
'class': 'input',
'size': '25',
'maxlength': '25',
'placeholder': 'Video credit',
}))
latitude = forms.FloatField(widget=forms.HiddenInput())
longitude = forms.FloatField(widget=forms.HiddenInput())

class Meta:
model = ProjectUpdate
fields = ('title', 'text', 'language', 'photo', 'photo_caption', 'photo_credit', 'video', 'video_caption',
'video_credit')

def clean_video(self):
data = self.cleaned_data['video']
if data:
scheme, netloc, path, query, fragment = urlsplit(data)
netloc = netloc.lower()
valid_url = (netloc == 'blip.tv' or
netloc == 'vimeo.com' or
netloc == 'www.youtube.com' and path == '/watch' or
netloc == 'youtu.be')
if not valid_url:
raise forms.ValidationError(_('Invalid video URL. Currently '
'Blip.TV, Vimeo and YouTube are supported.'))
if netloc == 'youtu.be':
netloc = 'www.youtube.com'
path = '/watch?v=%s' % path.lstrip('/')
data = urlunsplit((scheme, netloc, path, query, fragment))
return data

def save(self, project=None, user=None):
if project and user:
# Save update
update = super(ProjectUpdateForm, self).save(commit=False)
update.project = project
update.user = user
update.update_method = 'W'
update.save()

# Save update location
# Only when adding an update. When editing an update, the initial location is maintained.
if not update.primary_location:
latitude_data = self.cleaned_data['latitude']
longitude_data = self.cleaned_data['longitude']
ProjectUpdateLocation.objects.create(
latitude=latitude_data,
longitude=longitude_data,
location_target=update,
)

return update
else:
raise forms.ValidationError('Project or user not found.')
42 changes: 40 additions & 2 deletions akvo/rsr/views/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@

import json

from ..forms import ProjectUpdateForm
from ..filters import remove_empty_querydict_items, ProjectFilter
from ..models import Invoice, Project
from ..models import Invoice, Project, ProjectUpdate
from ...utils import pagination

from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, render
from django.shortcuts import get_object_or_404, redirect, render


def _get_accordion_data(project):
Expand Down Expand Up @@ -135,6 +137,42 @@ def main(request, project_id):
return render(request, 'project_main.html', context)


@login_required()
def set_update(request, project_id, edit_mode=False, form_class=ProjectUpdateForm, update_id=None):
project = get_object_or_404(Project, id=project_id)
updates = project.updates_desc()[:5]
update = None

if update_id is not None:
edit_mode = True
update = get_object_or_404(ProjectUpdate, id=update_id)
if not request.user == update.user:
request.error_message = u'You can only edit your own updates.'
raise PermissionDenied

if update.edit_window_has_expired():
request.error_message = u'You cannot edit this update anymore, the 30 minutes time limit has passed.'
raise PermissionDenied

if request.method == 'POST':
updateform = form_class(request.POST, request.FILES, instance=update)
if updateform.is_valid():
update = updateform.save(project=project, user=request.user)
return redirect(update.get_absolute_url())
else:
updateform = form_class(instance=update)

context = {
'project': project,
'updates': updates,
'update': update,
'updateform': updateform,
'edit_mode': edit_mode,
}

return render(request, 'update_add.html', context)


def search(request):
context = {'projects': Project.objects.published()}
return render(request, 'project_search.html', context)
6 changes: 4 additions & 2 deletions akvo/rsr/views/project_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ def directory(request):


def main(request, project_id, update_id):
context = {'update': get_object_or_404(ProjectUpdate, pk=update_id,
project=project_id)}
context = {
'update': get_object_or_404(ProjectUpdate, pk=update_id, project=project_id),
'project': get_object_or_404(Project, pk=project_id)
}
return render(request, 'update_main.html', context)


Expand Down
13 changes: 11 additions & 2 deletions akvo/templates/myrsr/my_projects.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
{% block myrsr_main %}
<div class="table-responsive">
<h1>{% trans "My project" %}s</h1>
{% if page %}
<table class="table table-striped">
<thead>
<tr>
Expand Down Expand Up @@ -44,6 +45,9 @@ <h4 class="media-heading">{{ project.title }}</h4>
{% endif %}
</a>
{% endif %}
{% has_perm 'rsr.post_updates' project as can_add_update %}
<br>
<a href="{% url 'add-update' project.pk %}">Add an update</a>
</td>
</tr>
{% endfor %}
Expand All @@ -52,7 +56,12 @@ <h4 class="media-heading">{{ project.title }}</h4>
<p>Viewing {{ page.start_index }} - {{ page.end_index }} of {{ paginator.count }} projects</p>
{% include 'navigation/pagination.html' %}
</div>

{% else %}
<h2><small>You can't see any projects yet.</small></h2>
<p>
Go to the <a href="{% url 'my_details' %}">My details</a> page to request to join an organisation.
Once your request is approved, you will see the projects of this organisation on this page.
</p>
{% endif %}
</div>

{% endblock %}
7 changes: 4 additions & 3 deletions akvo/templates/navigation/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

{% url 'project-directory' as project_url %}
{% url 'update-directory' as update_url %}
{% url 'update-directory' as update_url %}
{% url 'organisation-directory' as organisation_url %}
{% url 'my_details' as myrsr_url %}

Expand All @@ -25,8 +26,7 @@
<div class="collapse navbar-collapse" id="navbar-collapsed">
<ul class="nav navbar-nav">
<li>
<a class="{% if current_path == project_path %}
active{% endif %}"
<a class="{% if current_path == project_path %}active{% endif %}"
href="{% url 'project-directory' %}">
{% trans "Projects" %}
</a>
Expand All @@ -46,7 +46,8 @@
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
<a href="/#" class="btn btn-primary btn-xs navbar-btn addUpdateBtn">
<a href="{% if project %}{% url 'add-update' project.pk %}{% else %}{% url 'my_projects' %}{% endif %}"
class="btn btn-primary btn-xs navbar-btn addUpdateBtn">
{% bootstrap_icon "bullhorn" %} Add an update
</a>
</li>
Expand Down
84 changes: 84 additions & 0 deletions akvo/templates/update_add.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{% extends "base.html" %}

{% load i18n markup_tags rsr_utils bootstrap3 %}

{% block title %}{{project.title}}{% endblock %}

{% block head_js %}
<script>
$(document).ready(function() {
$( "#id_latitude").val(0);
$( "#id_longitude").val(0);
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(storePosition);
}
function storePosition(position) {
$( "#id_latitude").val(position.coords.latitude);
$( "#id_longitude").val(position.coords.longitude);
}
});
</script>
{% endblock %}

{% block maincontent %}
<article class="touch-navbar">
{% include "partials/project_header.html" %}

<div class="container">
<div class="row">
<div class="col-md-12">
<h1>{% if edit_mode %}{% trans 'Edit an update' %}{% else %}{% trans 'Add an update' %}{% endif %}</h1>
{% if edit_mode %}
<p class="small">You posted this update at {{ update.time_gmt|date:"H:i T"}}. You have until {{ update.expires_at|date:"H:i T" }} to save your edits.</p>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-lg-7 col-md-7 col-sm-12 col-xs-12" id="update">
{% if update and update.photo and edit_mode %}
<p>{% img update 400 300 update.title %}</p>
{% endif %}
<form method="post" action="" id="updateForm" enctype="multipart/form-data">
{% csrf_token %}
{% for field in updateform %}
{% bootstrap_field field %}
{% endfor %}
{% buttons %}
<button type="submit" class="btn btn-primary">
{% if edit_mode %}{% trans 'Edit update' %}{% else %}{% trans 'Add update' %}{% endif %}
</button>
{% endbuttons %}
</form>
</div>
{% if updates %}
<div class="col-lg-5 col-md-5 hidden-sm hidden-xs">
<h2>Previous updates of this project</h2>
{% for u in updates %}
{% if update and not u.id = update.id %}
<div class="row">
<div class="col-lg-5 col-md-5 thumbImg">
<a href="{% url 'update-main' u.project.id u.id %}">
{% img u 160 160 u.title %}
</a>
</div>
<div class="col-lg-7 col-md-7">
<h4><a href="{% url 'update-main' u.project.id u.id %}">{{u.title}}</a></h4>
<p class="small">
<span class="glyphicon glyphicon-user"></span> {{u.user.first_name}} {{u.user.last_name}}<br>
{% if u.primary_location.country %}
<span class="glyphicon glyphicon-map-marker"></span> {{u.primary_location.country}}, {{u.primary_location.country.continent}} <br>
{% endif %}
<span class="glyphicon glyphicon-calendar"></span> {{u.created_at|date:"d-M-Y"}}<br>
</p>
</div>
</div>
<br>
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
</div>
</article>

{% endblock %}
Loading

0 comments on commit 1a96177

Please sign in to comment.