Skip to content

Commit ea7f45d

Browse files
committed
Port ietfworkflows and wgchairs to new schema, fix missing state
setting in I-D submission, add tests - Legacy-Id: 3617
1 parent e01ba98 commit ea7f45d

21 files changed

Lines changed: 934 additions & 121 deletions

File tree

ietf/ietfworkflows/accounts.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def is_wgchairREDESIGN(person):
2727
def is_wgdelegate(person):
2828
return bool(person.wgdelegate_set.all())
2929

30-
def is_delegateREDESIGN(person):
30+
def is_wgdelegateREDESIGN(person):
3131
return bool(Role.objects.filter(name="delegate", group__type="wg", group__state="active", person=person))
3232

3333

@@ -51,14 +51,14 @@ def is_chair_of_draftREDESIGN(user, draft):
5151

5252
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
5353
from ietf.wgchairs.accounts import is_secretariat, get_person_for_user
54-
is_delegate = is_delegateREDESIGN
54+
is_wgdelegate = is_wgdelegateREDESIGN
5555
is_wgchair = is_wgchairREDESIGN
5656
is_chair_of_draft = is_chair_of_draftREDESIGN
5757

5858

5959
def can_edit_state(user, draft):
6060
streamed = get_streamed_draft(draft)
61-
if not streamed or not streamed.stream:
61+
if not settings.USE_DB_REDESIGN_PROXY_CLASSES and (not streamed or not streamed.stream):
6262
person = get_person_for_user(user)
6363
if not person:
6464
return False
@@ -71,3 +71,13 @@ def can_edit_state(user, draft):
7171

7272
def can_edit_stream(user, draft):
7373
return is_secretariat(user)
74+
75+
def can_adopt(user, draft):
76+
if settings.USE_DB_REDESIGN_PROXY_CLASSES and draft.stream_id == "ise":
77+
person = get_person_for_user(user)
78+
if not person:
79+
return False
80+
return is_wgchair(person) or is_wgdelegate(person)
81+
else:
82+
return is_secretariat(user)
83+

ietf/ietfworkflows/forms.py

Lines changed: 160 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import datetime
22

3-
3+
from django.conf import settings
44
from django import forms
55
from django.template.loader import render_to_string
66
from workflows.models import State
77
from workflows.utils import set_workflow_for_object
88

9-
from ietf.idtracker.models import PersonOrOrgInfo, IETFWG
9+
from ietf.idtracker.models import PersonOrOrgInfo, IETFWG, InternetDraft
1010
from ietf.wgchairs.accounts import get_person_for_user
1111
from ietf.ietfworkflows.models import Stream
1212
from ietf.ietfworkflows.utils import (get_workflow_for_draft, get_workflow_for_wg,
@@ -18,7 +18,10 @@
1818
from ietf.ietfworkflows.streams import (get_stream_from_draft, get_streamed_draft,
1919
get_stream_by_name, set_stream_for_draft)
2020
from ietf.ietfworkflows.constants import CALL_FOR_ADOPTION, IETF_STREAM
21-
21+
from redesign.doc.utils import get_tags_for_stream_id
22+
from redesign.doc.models import save_document_in_history, DocEvent, Document
23+
from redesign.name.models import DocTagName, DocStreamName
24+
from redesign.group.models import Group, GroupStateTransitions
2225

2326
class StreamDraftForm(forms.Form):
2427

@@ -55,45 +58,91 @@ class NoWorkflowStateForm(StreamDraftForm):
5558
def __init__(self, *args, **kwargs):
5659
super(NoWorkflowStateForm, self).__init__(*args, **kwargs)
5760
self.wgs = None
58-
self.onlywg = None
5961
if is_secretariat(self.user):
60-
wgs = IETFWG.objects.all()
62+
wgs = IETFWG.objects.all().order_by('group_acronym__acronym')
6163
else:
62-
wgs = set([i.group_acronym for i in self.person.wgchair_set.all()]).union(set([i.wg for i in self.person.wgdelegate_set.all()]))
63-
if len(wgs) > 1:
64-
self.wgs = list(wgs)
65-
self.wgs.sort(lambda x,y: cmp(x.group_acronym.acronym, y.group_acronym.acronym))
66-
self.fields['wg'].choices = [(i.pk, '%s - %s' % (i.group_acronym.acronym, i.group_acronym.name)) for i in self.wgs]
64+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
65+
wgs = IETFWG.objects.filter(type="wg", state="active", role__name__in=("chair", "delegate"), role__person__user=self.user).order_by('acronym').distinct()
66+
else:
67+
wgs = set([i.group_acronym for i in self.person.wgchair_set.all()]).union(set([i.wg for i in self.person.wgdelegate_set.all()]))
68+
wgs = list(wgs)
69+
wgs.sort(lambda x,y: cmp(x.group_acronym.acronym, y.group_acronym.acronym))
70+
self.wgs = wgs
71+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
72+
self.fields['wg'].choices = [(i.pk, '%s - %s' % (i.acronym, i.name)) for i in self.wgs]
6773
else:
68-
self.onlywg = list(wgs)[0].group_acronym
74+
self.fields['wg'].choices = [(i.pk, '%s - %s' % (i.group_acronym.acronym, i.group_acronym.name)) for i in self.wgs]
6975

7076
def save(self):
71-
comment = self.cleaned_data.get('comment')
77+
comment = self.cleaned_data.get('comment').strip()
7278
weeks = self.cleaned_data.get('weeks')
73-
if self.onlywg:
74-
wg = self.onlywg
75-
else:
76-
wg = IETFWG.objects.get(pk=self.cleaned_data.get('wg'))
79+
wg = IETFWG.objects.get(pk=self.cleaned_data.get('wg'))
7780
estimated_date = None
7881
if weeks:
7982
now = datetime.date.today()
8083
estimated_date = now + datetime.timedelta(weeks=weeks)
81-
workflow = get_workflow_for_wg(wg)
82-
set_workflow_for_object(self.draft, workflow)
83-
stream = get_stream_by_name(IETF_STREAM)
84-
streamed = get_streamed_draft(self.draft)
85-
if not streamed:
86-
set_stream_for_draft(self.draft, stream)
84+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
85+
# do changes on real Document object instead of proxy to avoid trouble
86+
doc = Document.objects.get(pk=self.draft.pk)
87+
save_document_in_history(doc)
88+
89+
doc.time = datetime.datetime.now()
90+
91+
new_stream = DocStreamName.objects.get(slug="ietf")
92+
93+
if doc.stream != new_stream:
94+
e = DocEvent(type="changed_stream")
95+
e.time = doc.time
96+
e.by = self.user.get_profile()
97+
e.doc = doc
98+
e.desc = u"Stream changed to <b>%s</b> from %s" % (new_stream.name, doc.stream.name)
99+
e.save()
100+
doc.stream = new_stream
101+
102+
if doc.group.pk != wg.pk:
103+
e = DocEvent(type="changed_group")
104+
e.time = doc.time
105+
e.by = self.user.get_profile()
106+
e.doc = doc
107+
e.desc = u"Changed group to <b>%s (%s)</b>" % (wg.name, wg.acronym.upper())
108+
if doc.group.type_id != "individ":
109+
e.desc += " from %s (%s)" % (doc.group.name, doc.group.acronym)
110+
e.save()
111+
doc.group_id = wg.pk
112+
113+
doc.save()
114+
self.draft = InternetDraft.objects.get(pk=doc.pk) # make sure proxy object is updated
115+
else:
116+
workflow = get_workflow_for_wg(wg)
117+
set_workflow_for_object(self.draft, workflow)
118+
stream = get_stream_by_name(IETF_STREAM)
87119
streamed = get_streamed_draft(self.draft)
88-
streamed.stream = stream
89-
streamed.group = wg
90-
streamed.save()
91-
update_state(obj=self.draft,
120+
if not streamed:
121+
set_stream_for_draft(self.draft, stream)
122+
streamed = get_streamed_draft(self.draft)
123+
streamed.stream = stream
124+
streamed.group = wg
125+
streamed.save()
126+
127+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
128+
from redesign.doc.models import State
129+
to_state = State.objects.get(slug="c-adopt", type="draft-stream-%s" % self.draft.stream_id)
130+
else:
131+
to_state = get_state_by_name(CALL_FOR_ADOPTION)
132+
update_state(self.draft,
92133
comment=comment,
93134
person=self.person,
94-
to_state=get_state_by_name(CALL_FOR_ADOPTION),
135+
to_state=to_state,
95136
estimated_date=estimated_date)
96137

138+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
139+
if comment:
140+
e = DocEvent(type="added_comment")
141+
e.time = self.draft.time
142+
e.by = self.person
143+
e.doc_id = self.draft.pk
144+
e.desc = comment
145+
e.save()
97146

98147
class DraftTagsStateForm(StreamDraftForm):
99148

@@ -115,8 +164,20 @@ def __init__(self, *args, **kwargs):
115164
if new_state:
116165
self.data = self.data.copy()
117166
self.data.update({'new_state': new_state.id})
118-
self.available_tags = self.workflow.get_tags()
119-
self.tags = [i.annotation_tag for i in get_annotation_tags_for_draft(self.draft)]
167+
if key.startswith('new_state_'): # hack to get value from submit buttons
168+
self.data = self.data.copy()
169+
self.data['new_state'] = key.replace('new_state_', '')
170+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
171+
possible_tags = get_tags_for_stream_id(self.draft.stream_id)
172+
if self.draft.stream_id == "ietf" and self.draft.group:
173+
unused_tags = self.draft.group.unused_tags.values_list("slug", flat=True)
174+
possible_tags = [t for t in possible_tags if t not in unused_tags]
175+
self.available_tags = DocTagName.objects.filter(slug__in=possible_tags)
176+
self.tags = self.draft.tags.filter(slug__in=possible_tags)
177+
else:
178+
self.available_tags = self.workflow.get_tags()
179+
self.tags = [i.annotation_tag for i in get_annotation_tags_for_draft(self.draft)]
180+
120181
self.fields['tags'].choices = [(i.pk, i.name) for i in self.available_tags]
121182
self.fields['tags'].initial = [i.pk for i in self.tags]
122183

@@ -128,9 +189,46 @@ def get_new_state(self, key):
128189
return None
129190

130191
def get_transitions(self):
192+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
193+
return []
131194
return self.state.transitions.filter(workflow=self.workflow)
132195

196+
def get_next_states(self):
197+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
198+
from redesign.doc.models import State
199+
state_type = "draft-stream-%s" % self.draft.stream_id
200+
s = self.draft.get_state(state_type)
201+
next_states = []
202+
if s:
203+
next_states = s.next_states.all()
204+
205+
if self.draft.stream_id == "ietf" and self.draft.group:
206+
transitions = self.draft.group.groupstatetransitions_set.filter(state=s)
207+
if transitions:
208+
next_states = transitions[0].next_states.all()
209+
else:
210+
# return the initial state
211+
states = State.objects.filter(type=state_type).order_by('order')
212+
if states:
213+
next_states = states[:1]
214+
215+
unused = []
216+
if self.draft.group:
217+
unused = self.draft.group.unused_states.values_list("pk", flat=True)
218+
return [n for n in next_states if n.pk not in unused]
219+
220+
return []
221+
222+
133223
def get_states(self):
224+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
225+
from redesign.doc.models import State
226+
states = State.objects.filter(type="draft-stream-%s" % self.draft.stream_id)
227+
if self.draft.stream_id == "ietf" and self.draft.group:
228+
unused_states = self.draft.group.unused_states.values_list("pk", flat=True)
229+
states = [s for s in states if s.pk not in unused_states]
230+
return [(i.pk, i.name) for i in states]
231+
134232
return [(i.pk, i.name) for i in self.workflow.get_states()]
135233

136234
def save_tags(self):
@@ -145,7 +243,10 @@ def save_tags(self):
145243
try:
146244
shepherd = self.draft.shepherd
147245
if shepherd:
148-
extra_notify = ['%s <%s>' % shepherd.email()]
246+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
247+
extra_notify = [shepherd.formatted_email()]
248+
else:
249+
extra_notify = ['%s <%s>' % shepherd.email()]
149250
except PersonOrOrgInfo.DoesNotExist:
150251
pass
151252
if not set_tags and not reset_tags:
@@ -159,29 +260,44 @@ def save_tags(self):
159260

160261
def save_state(self):
161262
comment = self.cleaned_data.get('comment')
263+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
264+
from redesign.doc.models import State
162265
state = State.objects.get(pk=self.cleaned_data.get('new_state'))
163266
weeks = self.cleaned_data.get('weeks')
164267
estimated_date = None
165268
if weeks:
166269
now = datetime.date.today()
167270
estimated_date = now + datetime.timedelta(weeks=weeks)
168-
update_state(obj=self.draft,
271+
272+
update_state(self.draft,
169273
comment=comment,
170274
person=self.person,
171275
to_state=state,
172276
estimated_date=estimated_date)
173277

174278
def save(self):
175279
self.save_tags()
176-
if 'only_tags' in self.data.keys():
177-
return
178-
self.save_state()
280+
if 'only_tags' not in self.data.keys():
281+
self.save_state()
282+
283+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
284+
comment = self.cleaned_data.get('comment').strip()
285+
if comment:
286+
e = DocEvent(type="added_comment")
287+
e.time = self.draft.time
288+
e.by = self.person
289+
e.doc_id = self.draft.pk
290+
e.desc = comment
291+
e.save()
179292

180293

181294
class DraftStreamForm(StreamDraftForm):
182295

183296
comment = forms.CharField(widget=forms.Textarea)
184-
stream = forms.ModelChoiceField(Stream.objects.all())
297+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
298+
stream = forms.ModelChoiceField(DocStreamName.objects.exclude(slug="legacy"))
299+
else:
300+
stream = forms.ModelChoiceField(Stream.objects.all())
185301

186302
template = 'ietfworkflows/stream_form.html'
187303

@@ -193,10 +309,18 @@ def __init__(self, *args, **kwargs):
193309
self.fields['stream'].initial = self.stream.pk
194310

195311
def save(self):
196-
comment = self.cleaned_data.get('comment')
312+
comment = self.cleaned_data.get('comment').strip()
197313
to_stream = self.cleaned_data.get('stream')
198314

199315
update_stream(self.draft,
200316
comment=comment,
201317
person=self.person,
202318
to_stream=to_stream)
319+
320+
if comment:
321+
e = DocEvent(type="added_comment")
322+
e.time = self.draft.time
323+
e.by = self.person
324+
e.doc_id = self.draft.pk
325+
e.desc = comment
326+
e.save()

0 commit comments

Comments
 (0)