From 7e3b621a05c7589f66f2431c494c305f55bf8eec Mon Sep 17 00:00:00 2001 From: Ole Laursen Date: Tue, 30 Aug 2011 11:33:47 +0000 Subject: [PATCH] Port shepherd management, adding tests - Legacy-Id: 3401 --- ietf/wgchairs/forms.py | 34 +++++++- ietf/wgchairs/templatetags/wgchairs_tags.py | 9 +++ ietf/wgchairs/tests.py | 88 +++++++++++++++++++++ ietf/wgchairs/views.py | 37 ++++++--- redesign/doc/models.py | 3 + redesign/group/proxy.py | 11 ++- 6 files changed, 166 insertions(+), 16 deletions(-) diff --git a/ietf/wgchairs/forms.py b/ietf/wgchairs/forms.py index 943fec450..78931e7a3 100644 --- a/ietf/wgchairs/forms.py +++ b/ietf/wgchairs/forms.py @@ -1,3 +1,5 @@ +import datetime + from django import forms from django.conf import settings from django.core.mail import EmailMessage @@ -181,6 +183,31 @@ class RemoveDelegateForm(RelatedWGForm): WGDelegate.objects.filter(pk__in=delegates).delete() self.set_message('success', 'Delegates removed') +def assign_shepherd(user, internetdraft, shepherd): + if internetdraft.shepherd == shepherd: + return + + from redesign.doc.models import save_document_in_history, DocEvent, Document + + # saving the proxy object is a bit of a mess, so convert it to a + # proper document + doc = Document.objects.get(name=internetdraft.name) + + save_document_in_history(doc) + e = DocEvent(doc=doc, by=user.get_profile()) + if not shepherd: + e.desc = u"Unassigned shepherd" + else: + e.desc = u"Changed shepherd to %s" % shepherd.name + e.type = "changed_document" + e.save() + + doc.time = e.time + doc.shepherd = shepherd + doc.save() + + # update proxy too + internetdraft.shepherd = shepherd class AddDelegateForm(RelatedWGForm): @@ -225,8 +252,11 @@ class AddDelegateForm(RelatedWGForm): self.create_delegate(person) def assign_shepherd(self, person): - self.shepherd.shepherd = person - self.shepherd.save() + if settings.USE_DB_REDESIGN_PROXY_CLASSES: + assign_shepherd(self.user, self.shepherd, person) + else: + self.shepherd.shepherd = person + self.shepherd.save() self.next_form = AddDelegateForm(wg=self.wg, user=self.user, shepherd=self.shepherd) self.next_form.set_message('success', 'Shepherd assigned successfully') diff --git a/ietf/wgchairs/templatetags/wgchairs_tags.py b/ietf/wgchairs/templatetags/wgchairs_tags.py index e81301c78..0bcb4cda4 100644 --- a/ietf/wgchairs/templatetags/wgchairs_tags.py +++ b/ietf/wgchairs/templatetags/wgchairs_tags.py @@ -1,3 +1,4 @@ +from django.conf import settings from django import template from ietf.ietfworkflows.utils import get_state_for_draft @@ -23,6 +24,10 @@ def wgchairs_admin_options(context, wg): @register.simple_tag def writeup(doc): + if settings.USE_DB_REDESIGN_PROXY_CLASSES: + e = doc.latest_event(type="changed_protocol_writeup") + return e.text if e else "" + writeup = doc.protowriteup_set.all() if not writeup.count(): return '' @@ -32,6 +37,10 @@ def writeup(doc): @register.simple_tag def writeupdate(doc): + if settings.USE_DB_REDESIGN_PROXY_CLASSES: + e = doc.latest_event(type="changed_protocol_writeup") + return e.time if e else "" + writeup = doc.protowriteup_set.all() if not writeup.count(): return '' diff --git a/ietf/wgchairs/tests.py b/ietf/wgchairs/tests.py index b34fb98cd..9c40c79b9 100644 --- a/ietf/wgchairs/tests.py +++ b/ietf/wgchairs/tests.py @@ -14,6 +14,7 @@ from ietf.utils.test_data import make_test_data if settings.USE_DB_REDESIGN_PROXY_CLASSES: from redesign.person.models import Person, Email from redesign.group.models import Group, Role + from redesign.doc.models import Document class ManageDelegatesTestCase(django.test.TestCase): fixtures = ['names'] @@ -93,7 +94,94 @@ class ManageDelegatesTestCase(django.test.TestCase): self.assertTrue("new delegate" in r.content) self.assertTrue(Email.objects.get(address="plain@example.com").person.name in r.content) + +class ManageShepherdsTestCase(django.test.TestCase): + fixtures = ['names'] + + def test_manage_shepherds(self): + make_test_data() + + url = urlreverse('manage_shepherds', kwargs=dict(acronym="mars")) + login_testing_unauthorized(self, "secretary", url) + + # setup test documents + group = Group.objects.get(acronym="mars") + + from redesign.doc.models import Document + common = dict(group=group, + state_id="active", + ad=Person.objects.get(user__username="ad"), + type_id="draft") + Document.objects.create(name="test-no-shepherd", + title="No shepherd", + shepherd=None, + **common) + Document.objects.create(name="test-shepherd-me", + title="Shepherd me", + shepherd=Person.objects.get(user__username="secretary"), + **common) + Document.objects.create(name="test-shepherd-other", title="Shepherd other", + shepherd=Person.objects.get(user__username="plain"), + **common) + # get and make sure they are divided correctly + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertEquals(len(q('div#noshepherd a:contains("No shepherd")')), 1) + self.assertEquals(len(q('div#mydocs a:contains("Shepherd me")')), 1) + self.assertEquals(len(q('div#othershepherds a:contains("Shepherd other")')), 1) + + def test_set_shepherd(self): + draft = make_test_data() + + url = urlreverse('doc_managing_shepherd', kwargs=dict(acronym="mars", name=draft.name)) + login_testing_unauthorized(self, "secretary", url) + + # get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertEquals(len(q('input[type=submit][name=setme]')), 1) + + # set me + events_before = draft.docevent_set.count() + r = self.client.post(url, + dict(setme="1")) + self.assertEquals(r.status_code, 200) + draft = Document.objects.get(name=draft.name) + self.assertTrue(draft.shepherd) + self.assertEquals(draft.shepherd.user.username, "secretary") + self.assertEquals(draft.docevent_set.count(), events_before + 1) + + # get + r = self.client.get(url) + self.assertEquals(r.status_code, 200) + self.assertTrue(Person.objects.get(user__username="secretary").name in r.content) + q = PyQuery(r.content) + self.assertEquals(len(q('input[type=submit][name=remove_shepherd]')), 1) + + # unassign + events_before = draft.docevent_set.count() + r = self.client.post(url, + dict(remove_shepherd="1")) + self.assertEquals(r.status_code, 200) + draft = Document.objects.get(name=draft.name) + self.assertTrue(not draft.shepherd) + self.assertEquals(draft.docevent_set.count(), events_before + 1) + + # change to existing person + events_before = draft.docevent_set.count() + r = self.client.post(url, + dict(email="plain@example.com", + form_type="single")) + self.assertEquals(r.status_code, 200) + q = PyQuery(r.content) + self.assertTrue("Shepherd assigned" in r.content) + self.assertTrue(Email.objects.get(address="plain@example.com").person.name in r.content) + self.assertEquals(draft.docevent_set.count(), events_before + 1) + if not settings.USE_DB_REDESIGN_PROXY_CLASSES: # the above tests only work with the new schema del ManageDelegatesTestCase + del ManageShepherdsTestCase diff --git a/ietf/wgchairs/views.py b/ietf/wgchairs/views.py index 2e33543ff..4f2344892 100644 --- a/ietf/wgchairs/views.py +++ b/ietf/wgchairs/views.py @@ -92,6 +92,9 @@ def manage_workflow(request, acronym): }, RequestContext(request)) +if settings.USE_DB_REDESIGN_PROXY_CLASSES: + from ietf.wgchairs.forms import assign_shepherd + def managing_shepherd(request, acronym, name): """ View for managing the assigned shepherd of a document. @@ -107,11 +110,17 @@ def managing_shepherd(request, acronym, name): add_form = add_form_factory(request, wg, user, shepherd=doc) if request.method == 'POST': if request.POST.get('remove_shepherd'): - doc.shepherd = None - doc.save() + if settings.USE_DB_REDESIGN_PROXY_CLASSES: + assign_shepherd(user, doc, None) + else: + doc.shepherd = None + doc.save() elif request.POST.get('setme'): - doc.shepherd = person - doc.save() + if settings.USE_DB_REDESIGN_PROXY_CLASSES: + assign_shepherd(user, doc, person) + else: + doc.shepherd = person + doc.save() elif add_form.is_valid(): add_form.save() add_form = add_form.get_next_form() @@ -132,16 +141,18 @@ def wg_shepherd_documents(request, acronym): return HttpResponseForbidden('You have no permission to access this view') current_person = get_person_for_user(user) - form = SearchForm({'by': 'group', 'group': str(wg.group_acronym.acronym), - 'activeDrafts': 'on'}) - if not form.is_valid(): - raise ValueError("form did not validate") - (docs, meta) = search_query(form.cleaned_data) - - base_qs = InternetDraft.objects.filter(pk__in=[i.id._draft.pk for i in docs if i.id]).select_related('status') - documents_no_shepherd = base_qs.filter(shepherd__isnull=True) + if settings.USE_DB_REDESIGN_PROXY_CLASSES: + base_qs = InternetDraft.objects.filter(group=wg, state="active").select_related("status").order_by('title') + else: + form = SearchForm({'by': 'group', 'group': str(wg.group_acronym.acronym), + 'activeDrafts': 'on'}) + if not form.is_valid(): + raise ValueError("form did not validate") + (docs, meta) = search_query(form.cleaned_data) + base_qs = InternetDraft.objects.filter(pk__in=[i.id._draft.pk for i in docs if i.id]).select_related('status') + documents_no_shepherd = base_qs.filter(shepherd=None) documents_my = base_qs.filter(shepherd=current_person) - documents_other = base_qs.exclude(shepherd__isnull=True).exclude(shepherd__pk__in=[current_person.pk, 0]) + documents_other = base_qs.exclude(shepherd=None).exclude(shepherd__pk__in=[current_person.pk, 0]) context = { 'no_shepherd': documents_no_shepherd, 'my_documents': documents_my, diff --git a/redesign/doc/models.py b/redesign/doc/models.py index 550abe3b4..670abaf30 100644 --- a/redesign/doc/models.py +++ b/redesign/doc/models.py @@ -210,6 +210,9 @@ EVENT_TYPES = [ ("requested_resurrect", "Requested resurrect"), ("completed_resurrect", "Completed resurrect"), ("published_rfc", "Published RFC"), + + # WG events + ("changed_protocol_writeup", "Changed protocol writeup"), # IESG events ("started_iesg_process", "Started IESG process on document"), diff --git a/redesign/group/proxy.py b/redesign/group/proxy.py index c746a2b7e..c0f929a48 100644 --- a/redesign/group/proxy.py +++ b/redesign/group/proxy.py @@ -25,12 +25,16 @@ class Acronym(Group): def name_key(self): return self.name.upper() + @property + def ietfwg(self): + return IETFWG().from_object(self) + def __str__(self): return self.acronym def __unicode__(self): return self.acronym - + class Meta: proxy = True @@ -102,6 +106,11 @@ class IETFWG(Group): ), always_filter=dict(type__in=("wg", "individ"))) + def from_object(self, base): + for f in base._meta.fields: + setattr(self, f.name, getattr(base, f.name)) + return self + ACTIVE=1 #group_acronym = models.OneToOneField(Acronym, primary_key=True, editable=False) @property