From 26ab9dbb28841bde7b77141d8874f302dc7f7927 Mon Sep 17 00:00:00 2001 From: Paul Eggleton Date: Wed, 27 Feb 2013 19:11:58 +0000 Subject: [PATCH] Add ability to add, edit and delete layer notes This allows adding an important notice to a layer e.g. "this layer is deprecated, please use layer xyz instead". Only one layer note can be added through the interface although the data structures allow multiple, so notes may be added programmatically without disturbing user-added ones. With this change we also add a get_absolute_url() function to the LayerItem model and change the calls to reverse() for layers to use it. Signed-off-by: Paul Eggleton --- TODO | 1 - layerindex/deleteconfirm.html | 34 +++++++++++++++++++++++++ layerindex/detail.html | 11 +++++++- layerindex/editlayernote.html | 42 ++++++++++++++++++++++++++++++ layerindex/forms.py | 12 ++++++++- layerindex/models.py | 4 +++ layerindex/urls.py | 8 +++++- layerindex/views.py | 48 ++++++++++++++++++++++++++++++++--- 8 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 layerindex/deleteconfirm.html create mode 100644 layerindex/editlayernote.html diff --git a/TODO b/TODO index b1b10e9..bfdd1d4 100644 --- a/TODO +++ b/TODO @@ -14,7 +14,6 @@ TODO: * Captcha Later: -* Allow adding/editing notes * Usage links in list page? * Avoid page content changing size depending on whether scrollbar is there or not? * Style/extend about page? diff --git a/layerindex/deleteconfirm.html b/layerindex/deleteconfirm.html new file mode 100644 index 0000000..341b91f --- /dev/null +++ b/layerindex/deleteconfirm.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} +{% load i18n %} + +{% comment %} + + layerindex-web - delete confirmation template + + Copyright (C) 2013 Intel Corporation + Licensed under the MIT license, see COPYING.MIT for details + +{% endcomment %} + + + +{% block content %} +{% autoescape on %} + +

Delete {{ object_type }}

+ +

Are you sure you want to delete "{{ object }}"?

+ +
+ {% csrf_token %} + + Cancel +
+ +{% endautoescape %} + +{% endblock %} diff --git a/layerindex/detail.html b/layerindex/detail.html index 27b4ad3..2912211 100644 --- a/layerindex/detail.html +++ b/layerindex/detail.html @@ -33,6 +33,9 @@ {% if perms.layeritem.publish_layer or useredit %} Edit layer + {% if layeritem.layernote_set.count = 0 %} + Add note + {% endif %} {% endif %} {% if layeritem.status = "N" and perms.layeritem.publish_layer %} Publish layer @@ -48,7 +51,13 @@
{% for note in layeritem.layernote_set.all %}
- {{ note.text }} +

{{ note.text }}

+ {% if perms.layeritem.publish_layer or useredit %} +

+ Edit note + Delete note +

+ {% endif %}
{% endfor %}
diff --git a/layerindex/editlayernote.html b/layerindex/editlayernote.html new file mode 100644 index 0000000..4c823d9 --- /dev/null +++ b/layerindex/editlayernote.html @@ -0,0 +1,42 @@ +{% extends "base.html" %} +{% load i18n %} + +{% comment %} + + layerindex-web - add/edit layer note form page template + + Copyright (C) 2013 Intel Corporation + Licensed under the MIT license, see COPYING.MIT for details + +{% endcomment %} + + + +{% block content %} +{% autoescape on %} + +

Add layer note to {{ form.instance.layer.name }}

+ +

This note will appear at the very top of the layer detail page. This would typically be used for important notices, e.g. "This layer is obsolete, use layer xyz instead".

+ +
+ {% csrf_token %} + {{ form.as_p }} + +Cancel +
+ +{% endautoescape %} + +{% endblock %} + + +{% block scripts %} + +{% endblock %} diff --git a/layerindex/forms.py b/layerindex/forms.py index c5ce82c..38e84a8 100644 --- a/layerindex/forms.py +++ b/layerindex/forms.py @@ -4,7 +4,7 @@ # # Licensed under the MIT license, see COPYING.MIT for details -from layerindex.models import LayerItem, LayerMaintainer +from layerindex.models import LayerItem, LayerMaintainer, LayerNote from django import forms from django.core.validators import URLValidator, RegexValidator, email_re from django.forms.models import inlineformset_factory @@ -110,3 +110,13 @@ class SubmitLayerForm(forms.ModelForm): val = URLValidator(verify_exists=False) val(url) return url + + +class EditNoteForm(forms.ModelForm): + class Meta: + model = LayerNote + fields = ('text',) + + def clean_text(self): + text = self.cleaned_data['text'].strip() + return text diff --git a/layerindex/models.py b/layerindex/models.py index fc31fe1..ee5a063 100644 --- a/layerindex/models.py +++ b/layerindex/models.py @@ -7,6 +7,7 @@ from django.db import models from datetime import datetime from django.contrib.auth.models import User +from django.core.urlresolvers import reverse import os.path class LayerItem(models.Model): @@ -88,6 +89,9 @@ class LayerItem(models.Model): return True return False + def get_absolute_url(self): + return reverse('layer_item', args=(self.name,)); + def __unicode__(self): return self.name diff --git a/layerindex/urls.py b/layerindex/urls.py index fa6d900..0ad7546 100644 --- a/layerindex/urls.py +++ b/layerindex/urls.py @@ -7,7 +7,7 @@ from django.conf.urls.defaults import * from django.views.generic import DetailView, ListView from layerindex.models import LayerItem, Recipe -from layerindex.views import LayerListView, RecipeSearchView, MachineSearchView, PlainTextListView, LayerDetailView, edit_layer_view +from layerindex.views import LayerListView, RecipeSearchView, MachineSearchView, PlainTextListView, LayerDetailView, edit_layer_view, edit_layernote_view, delete_layernote_view urlpatterns = patterns('', url(r'^$', @@ -35,6 +35,12 @@ urlpatterns = patterns('', LayerDetailView.as_view( template_name='layerindex/detail.html'), name='layer_item'), + url(r'^layer/(?P[-\w]+)/addnote/$', + edit_layernote_view, {'template_name': 'layerindex/editlayernote.html'}, name="add_layernote"), + url(r'^layer/(?P[-\w]+)/editnote/(?P[-\w]+)/$', + edit_layernote_view, {'template_name': 'layerindex/editlayernote.html'}, name="edit_layernote"), + url(r'^layer/(?P[-\w]+)/deletenote/(?P[-\w]+)/$', + delete_layernote_view, {'template_name': 'layerindex/deleteconfirm.html'}, name="delete_layernote"), url(r'^recipe/(?P[-\w]+)/$', DetailView.as_view( model=Recipe, diff --git a/layerindex/views.py b/layerindex/views.py index 0a55e0b..80d0260 100644 --- a/layerindex/views.py +++ b/layerindex/views.py @@ -9,10 +9,10 @@ from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidde from django.core.urlresolvers import reverse from django.core.exceptions import PermissionDenied from django.template import RequestContext -from layerindex.models import LayerItem, LayerMaintainer, LayerDependency, Recipe, Machine +from layerindex.models import LayerItem, LayerMaintainer, LayerDependency, LayerNote, Recipe, Machine from datetime import datetime from django.views.generic import DetailView, ListView -from layerindex.forms import SubmitLayerForm, LayerMaintainerFormSet +from layerindex.forms import SubmitLayerForm, LayerMaintainerFormSet, EditNoteForm from django.db import transaction from django.contrib.auth.models import User, Permission from django.db.models import Q @@ -23,6 +23,46 @@ import simplesearch import settings +def edit_layernote_view(request, template_name, slug, pk=None): + layeritem = get_object_or_404(LayerItem, name=slug) + if not (request.user.is_authenticated() and (request.user.has_perm('layerindex.publish_layer') or layeritem.user_can_edit(request.user))): + raise PermissionDenied + if pk: + # Edit mode + layernote = get_object_or_404(LayerNote, pk=pk) + else: + # Add mode + layernote = LayerNote() + layernote.layer = layeritem + + if request.method == 'POST': + form = EditNoteForm(request.POST, instance=layernote) + if form.is_valid(): + form.save() + return HttpResponseRedirect(layeritem.get_absolute_url()) + else: + form = EditNoteForm(instance=layernote) + + return render(request, template_name, { + 'form': form, + }) + +def delete_layernote_view(request, template_name, slug, pk): + layeritem = get_object_or_404(LayerItem, name=slug) + if not (request.user.is_authenticated() and (request.user.has_perm('layerindex.publish_layer') or layeritem.user_can_edit(request.user))): + raise PermissionDenied + layernote = get_object_or_404(LayerNote, pk=pk) + if request.method == 'POST': + layernote.delete() + return HttpResponseRedirect(layeritem.get_absolute_url()) + else: + return render(request, template_name, { + 'object': layernote, + 'object_type': layernote._meta.verbose_name, + 'return_url': layeritem.get_absolute_url() + }) + + def edit_layer_view(request, template_name, slug=None): useredit = False if slug: @@ -68,7 +108,7 @@ def edit_layer_view(request, template_name, slug=None): d = Context({ 'user_name': user.get_full_name(), 'layer_name': layeritem.name, - 'layer_url': request.build_absolute_uri(reverse('layer_item', args=(layeritem.name,))), + 'layer_url': request.build_absolute_uri(layeritem.get_absolute_url()), }) subject = '%s - %s' % (settings.SUBMIT_EMAIL_SUBJECT, layeritem.name) from_email = settings.SUBMIT_EMAIL_FROM @@ -105,7 +145,7 @@ def _statuschange(request, name, newstatus): if w.status != newstatus: w.change_status(newstatus, request.user.username) w.save() - return HttpResponseRedirect(reverse('layer_item', args=(name,))) + return HttpResponseRedirect(w.get_absolute_url()) class LayerListView(ListView): context_object_name = 'layer_list'