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 }}"?
+
+
+
+{% 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".
+
+
+
+{% 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'