Skip to content
This repository was archived by the owner on Jun 1, 2022. It is now read-only.

Commit fe40b3c

Browse files
committed
Merge pull request #206 from editorsnotes/fix-editing-bugs
Fix editing bugs
2 parents 2c310d1 + dfbf037 commit fe40b3c

33 files changed

+1812
-223
lines changed

editorsnotes/admin_custom/forms/topics.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,10 @@ class Media:
1616
)
1717
class Meta:
1818
model = Topic
19-
fields = ('preferred_name', 'topic_type',)
19+
fields = ('preferred_name', 'topic_type', 'summary',)
2020
widgets = {
2121
'topic': forms.HiddenInput()
2222
}
23-
def __init__(self, *args, **kwargs):
24-
super(TopicForm, self).__init__(*args, **kwargs)
25-
instance = kwargs.get('instance', None)
26-
if instance is not None:
27-
self.fields['topic_type'].initial = instance.topic.type
2823

2924
AlternateNameFormset = models.inlineformset_factory(
3025
Topic, AlternateName, fields=('name',), extra=1)
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
$(document).ready(function() {
2-
var editor = new wysihtml5.Editor('id_topicsummary-0-content', {
2+
var editor = new wysihtml5.Editor('id_summary', {
33
toolbar: 'summary-toolbar',
44
parserRules: wysihtml5ParserRules,
5+
useLineBreaks: false,
56
stylesheets: ['/static/function/wysihtml5/stylesheet.css']
67
});
78
});

editorsnotes/admin_custom/templates/topic_admin.html

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{% extends "admin_base.html" %}
22

3+
{% load display %}
4+
35
{% block page_title %}
46
<h3>{% if form.instance.id %}Change {% else %}Add {% endif %}topic</h3>
57
{% endblock %}
@@ -9,12 +11,11 @@ <h3>{% if form.instance.id %}Change {% else %}Add {% endif %}topic</h3>
911

1012
{% include "includes/bootstrap_errors.html" with errors=form.non_field_errors %}
1113

12-
<fieldset>
13-
<legend>Project</legend>
14-
<div class="fieldset-content">
15-
{{ project }}
16-
</div>
17-
</fieldset>
14+
{% if not form.instance.pk and form.instance.topic_node_id %}
15+
<div class="well">
16+
Connecting to topic node {{ form.instance.topic_node|as_link }}
17+
</div>
18+
{% endif %}
1819

1920
<fieldset name="preferred_name_fields">
2021
<legend>Name</legend>
@@ -51,7 +52,7 @@ <h3>{% if form.instance.id %}Change {% else %}Add {% endif %}topic</h3>
5152
{% include "includes/bootstrap_errors.html" with errors=form.summary.errors %}
5253
<div class="fieldset-content article">
5354
{% include "includes/wysihtml5_full_toolbar.html" with toolbar_id="summary-toolbar" %}
54-
{{ formsets.topicsummary.0.content }}
55+
{{ form.summary }}
5556
</div>
5657

5758
<div class="article-citations" style="margin: 1em .5em;">

editorsnotes/admin_custom/tests.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from django.core.urlresolvers import reverse
4+
5+
from django_webtest import WebTest
6+
7+
from editorsnotes.main.tests import create_test_user
8+
from editorsnotes.main import models as main_models
9+
10+
class TopicAdminTestCase(WebTest):
11+
fixtures = ['projects.json']
12+
def test_create_topic(self):
13+
"A user should be able to create a topic with a unique name."
14+
topic_name = u'Emma Goldman'
15+
add_url = reverse('admin:main_topic_add', kwargs={'project_slug': 'emma'})
16+
17+
form = self.app.get(add_url, user='barry').forms[1]
18+
form['preferred_name'] = topic_name
19+
20+
resp = form.submit()
21+
self.assertEqual(resp.status_code, 302)
22+
resp = resp.follow()
23+
self.assertEqual(resp.context['topic'].preferred_name, topic_name)
24+
25+
# Duplicate should raise an error
26+
duplicate_form = self.app.get(add_url, user='barry').forms[1]
27+
form['preferred_name'] = topic_name
28+
resp = form.submit()
29+
self.assertEqual(resp.status_code, 200)
30+
31+
error_messages = resp.forms[1].html.select('.error-message li')
32+
self.assertEqual(1, len(error_messages))
33+
self.assertEqual(error_messages[0].text.strip(),
34+
u'Topic with this preferred name already exists.')
35+
36+
def test_create_empty_topic_error(self):
37+
"A user should not be able to create a topic with an empty name."
38+
add_url = reverse('admin:main_topic_add', kwargs={'project_slug': 'emma'})
39+
40+
# Submit a blank form
41+
resp = self.app.get(add_url, user='barry').forms[1].submit()
42+
self.assertEqual(resp.status_code, 200)
43+
44+
error_messages = resp.forms[1].html.select('.error-message li')
45+
self.assertEqual(1, len(error_messages))
46+
self.assertEqual(error_messages[0].text.strip(), u'This field is required.')
47+
48+
def test_connect_to_topic_node(self):
49+
"A user should create a new topic connecting to an existing topic node."
50+
node_name = u'Емма Голдман'
51+
topic_node = main_models.TopicNode.objects.create(
52+
_preferred_name=node_name, creator_id=2, last_updater_id=2)
53+
54+
add_url = reverse('admin:main_topic_add', kwargs={'project_slug': 'emma'})
55+
add_url += '?topic_node={}'.format(topic_node.id)
56+
57+
resp = self.app.get(add_url, user='barry')
58+
form = resp.forms[1]
59+
self.assertEqual(form['preferred_name'].value, node_name)
60+
61+
form['preferred_name'] = 'Emma Goldman'
62+
resp = form.submit().follow()
63+
self.assertEqual(resp.context['topic'].topic_node_id, topic_node.id)
64+
65+
# doing this again should fail, since the project is already connected
66+
# to the node
67+
form = self.app.get(add_url, user='barry').forms[1]
68+
form['preferred_name'] = u'shouldn\'t matter'
69+
resp = form.submit()
70+
self.assertEqual(resp.status_code, 200)
71+
error_messages = resp.forms[1].html.select('.error-message li')
72+
self.assertEqual(1, len(error_messages))
73+
self.assertEqual(error_messages[0].text.strip(),
74+
u'This project is already connected with topic node '
75+
'{}.'.format(topic_node))

editorsnotes/admin_custom/tests.py.old

Lines changed: 0 additions & 91 deletions
This file was deleted.

editorsnotes/admin_custom/views/common.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ def post(self, request, *args, **kwargs):
9494
return super(BaseAdminView, self).post(request, *args, **kwargs)
9595
def get_default_perms(self):
9696
opts = self.model._meta
97-
perm = opts.get_add_permission if self.object is None \
98-
else opts.get_change_permission()
97+
add_action = self.object is None or not self.object.id
98+
perm = opts.get_add_permission() if add_action else opts.get_change_permission()
9999
return ['{}.{}'.format(opts.app_label, perm)]
100100
def check_perms(self):
101101
perms = getattr(self, 'permissions', self.get_default_perms())
@@ -109,9 +109,27 @@ def get_form_kwargs(self):
109109
kwargs = super(ModelFormMixin, self).get_form_kwargs()
110110
if hasattr(self, 'object') and self.object:
111111
kwargs.update({'instance': self.object})
112+
else:
113+
has_project_field = all([
114+
hasattr(self.model, 'project'),
115+
hasattr(self.model.project, 'field'),
116+
hasattr(self.model.project.field, 'related'),
117+
self.model.project.field.related.parent_model == Project
118+
])
119+
if has_project_field:
120+
# Then create an instance with the project already set
121+
instance = self.model(project=self.project)
122+
kwargs.update({ 'instance': instance })
123+
112124
return kwargs
113125

114-
def set_additional_object_properties(self, obj):
126+
def set_additional_object_properties(self, obj, form):
127+
"""
128+
This must be called for additional object properties which must be set
129+
but are not edited by the user. A common example is an item's last
130+
updater or creator. It is called *after* the object instance is already
131+
cleaned.
132+
"""
115133
return obj
116134

117135
def save_object(self, form, formsets):
@@ -135,7 +153,6 @@ def form_valid(self, form, formsets):
135153

136154
self.save_formsets(formsets)
137155
form.save_m2m()
138-
139156
return redirect(self.get_success_url())
140157
def form_invalid(self, form, formsets):
141158
return self.render_to_response(

editorsnotes/admin_custom/views/documents.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def get_object(self, document_id):
106106
self.document = get_object_or_404(
107107
Document, id=document_id, project_id=self.project.id)
108108
return self.document.transcript if self.document.has_transcript() else None
109-
def set_additional_object_properties(self, obj):
109+
def set_additional_object_properties(self, obj, form):
110110
obj.document = self.document
111111
return obj
112112
def save_object(self, form, formsets):

editorsnotes/admin_custom/views/notes.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@ def get_breadcrumb(self):
4040
('Edit', None)
4141
)
4242
return breadcrumbs
43-
def set_additional_object_properties(self, obj, form):
44-
obj.project = self.project
45-
return obj
4643
def get_form(self, form_class):
4744
form = form_class(**self.get_form_kwargs())
4845
form.fields['assigned_users'].queryset = self.project.members.all()

editorsnotes/admin_custom/views/topics.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ class TopicAdminView(BaseAdminView):
1313
form_class = forms.TopicForm
1414
formset_classes = (
1515
forms.topics.AlternateNameFormset,
16-
#forms.topics.TopicSummaryFormset,
1716
# forms.TopicAssignmentFormset,
1817
forms.topics.CitationFormset,
1918
)
@@ -28,28 +27,37 @@ def get_breadcrumb(self):
2827
kwargs={'project_slug': self.project.slug})),
2928
)
3029
if self.object is None:
31-
breadcrumbs += (
32-
('Add', None),
33-
)
30+
breadcrumbs += ( ('Add', None),)
3431
else:
3532
breadcrumbs += (
3633
(self.object.as_text(), self.object.get_absolute_url()),
3734
('Edit', None)
3835
)
3936
return breadcrumbs
37+
def get_form_kwargs(self):
38+
"""
39+
Set topic node if it's been included in the request. Needs to be set now
40+
so that it can be validated unique within a project.
41+
"""
42+
kwargs = super(TopicAdminView, self).get_form_kwargs()
43+
instance = kwargs.get('instance', None)
44+
if instance and not instance.id and 'topic_node' in self.request.GET:
45+
topic_node_id = self.request.GET.get('topic_node')
46+
topic_node = get_object_or_404(TopicNode, id=topic_node_id)
47+
instance.topic_node = topic_node
48+
if 'initial' not in kwargs:
49+
kwargs['initial'] = {}
50+
kwargs['initial']['preferred_name'] = topic_node.preferred_name
51+
kwargs['initial']['topic_type'] = topic_node.type
52+
return kwargs
4053
def set_additional_object_properties(self, obj, form):
41-
if not obj.id:
42-
existing_node_id = self.request.GET.get('topic_node')
43-
if existing_node_id:
44-
topic_node = get_object_or_404(TopicNode, id=existing_node_id)
45-
else:
46-
topic_node = TopicNode.objects.create(
47-
_preferred_name=obj.preferred_name,
48-
type=form.cleaned_data['topic_type'],
49-
creator=self.request.user,
50-
last_updater=self.request.user)
51-
obj.topic_node_id = topic_node.id
52-
obj.project_id = self.project.id
54+
if not obj.id and not obj.topic_node_id:
55+
topic_node = TopicNode.objects.create(
56+
_preferred_name=obj.preferred_name,
57+
type=form.cleaned_data['topic_type'],
58+
creator=self.request.user,
59+
last_updater=self.request.user)
60+
obj.topic_node = topic_node
5361
return obj
5462
def save_citation_formset_form(self, form):
5563
obj = form.save(commit=False)

0 commit comments

Comments
 (0)