77from django .conf import settings
88from django .http import HttpResponse , HttpResponseForbidden , HttpResponseRedirect , Http404
99from django .shortcuts import render , get_object_or_404 , redirect
10+ from django .template .defaultfilters import striptags
1011from django .template .loader import render_to_string
1112from django .urls import reverse as urlreverse
1213from django .views .decorators .csrf import csrf_exempt
@@ -108,6 +109,74 @@ def clean_discuss(self):
108109 raise forms .ValidationError ("You must enter a non-empty discuss" )
109110 return entered_discuss
110111
112+ def save_position (form , doc , ballot , ad , login = None ):
113+ # save the vote
114+ if login is None :
115+ login = ad
116+ clean = form .cleaned_data
117+
118+ old_pos = doc .latest_event (BallotPositionDocEvent , type = "changed_ballot_position" , ad = ad , ballot = ballot )
119+ pos = BallotPositionDocEvent (doc = doc , rev = doc .rev , by = login )
120+ pos .type = "changed_ballot_position"
121+ pos .ballot = ballot
122+ pos .ad = ad
123+ pos .pos = clean ["position" ]
124+ pos .comment = clean ["comment" ].rstrip ()
125+ pos .comment_time = old_pos .comment_time if old_pos else None
126+ pos .discuss = clean ["discuss" ].rstrip ()
127+ if not pos .pos .blocking :
128+ pos .discuss = ""
129+ pos .discuss_time = old_pos .discuss_time if old_pos else None
130+
131+ changes = []
132+ added_events = []
133+ # possibly add discuss/comment comments to history trail
134+ # so it's easy to see what's happened
135+ old_comment = old_pos .comment if old_pos else ""
136+ if pos .comment != old_comment :
137+ pos .comment_time = pos .time
138+ changes .append ("comment" )
139+
140+ if pos .comment :
141+ e = DocEvent (doc = doc , rev = doc .rev )
142+ e .by = ad # otherwise we can't see who's saying it
143+ e .type = "added_comment"
144+ e .desc = "[Ballot comment]\n " + pos .comment
145+ added_events .append (e )
146+
147+ old_discuss = old_pos .discuss if old_pos else ""
148+ if pos .discuss != old_discuss :
149+ pos .discuss_time = pos .time
150+ changes .append ("discuss" )
151+
152+ if pos .pos .blocking :
153+ e = DocEvent (doc = doc , rev = doc .rev , by = login )
154+ e .by = ad # otherwise we can't see who's saying it
155+ e .type = "added_comment"
156+ e .desc = "[Ballot %s]\n " % pos .pos .name .lower ()
157+ e .desc += pos .discuss
158+ added_events .append (e )
159+
160+ # figure out a description
161+ if not old_pos and pos .pos .slug != "norecord" :
162+ pos .desc = u"[Ballot Position Update] New position, %s, has been recorded for %s" % (pos .pos .name , pos .ad .plain_name ())
163+ elif old_pos and pos .pos != old_pos .pos :
164+ pos .desc = "[Ballot Position Update] Position for %s has been changed to %s from %s" % (pos .ad .plain_name (), pos .pos .name , old_pos .pos .name )
165+
166+ if not pos .desc and changes :
167+ pos .desc = u"Ballot %s text updated for %s" % (u" and " .join (changes ), ad .plain_name ())
168+
169+ # only add new event if we actually got a change
170+ if pos .desc :
171+ if login != ad :
172+ pos .desc += u" by %s" % login .plain_name ()
173+
174+ pos .save ()
175+
176+ for e in added_events :
177+ e .save () # save them after the position is saved to get later id for sorting order
178+
179+
111180@role_required ('Area Director' ,'Secretariat' )
112181def edit_position (request , name , ballot_id ):
113182 """Vote and edit discuss and comment on document as Area Director."""
@@ -128,77 +197,14 @@ def edit_position(request, name, ballot_id):
128197 raise Http404
129198 ad = get_object_or_404 (Person , pk = ad_id )
130199
131- old_pos = doc .latest_event (BallotPositionDocEvent , type = "changed_ballot_position" , ad = ad , ballot = ballot )
132-
133200 if request .method == 'POST' :
134201 if not has_role (request .user , "Secretariat" ) and not ad .role_set .filter (name = "ad" , group__type = "area" , group__state = "active" ):
135202 # prevent pre-ADs from voting
136203 return HttpResponseForbidden ("Must be a proper Area Director in an active area to cast ballot" )
137204
138205 form = EditPositionForm (request .POST , ballot_type = ballot .ballot_type )
139206 if form .is_valid ():
140- # save the vote
141- clean = form .cleaned_data
142-
143- pos = BallotPositionDocEvent (doc = doc , rev = doc .rev , by = login )
144- pos .type = "changed_ballot_position"
145- pos .ballot = ballot
146- pos .ad = ad
147- pos .pos = clean ["position" ]
148- pos .comment = clean ["comment" ].rstrip ()
149- pos .comment_time = old_pos .comment_time if old_pos else None
150- pos .discuss = clean ["discuss" ].rstrip ()
151- if not pos .pos .blocking :
152- pos .discuss = ""
153- pos .discuss_time = old_pos .discuss_time if old_pos else None
154-
155- changes = []
156- added_events = []
157- # possibly add discuss/comment comments to history trail
158- # so it's easy to see what's happened
159- old_comment = old_pos .comment if old_pos else ""
160- if pos .comment != old_comment :
161- pos .comment_time = pos .time
162- changes .append ("comment" )
163-
164- if pos .comment :
165- e = DocEvent (doc = doc , rev = doc .rev )
166- e .by = ad # otherwise we can't see who's saying it
167- e .type = "added_comment"
168- e .desc = "[Ballot comment]\n " + pos .comment
169- added_events .append (e )
170-
171- old_discuss = old_pos .discuss if old_pos else ""
172- if pos .discuss != old_discuss :
173- pos .discuss_time = pos .time
174- changes .append ("discuss" )
175-
176- if pos .pos .blocking :
177- e = DocEvent (doc = doc , rev = doc .rev , by = login )
178- e .by = ad # otherwise we can't see who's saying it
179- e .type = "added_comment"
180- e .desc = "[Ballot %s]\n " % pos .pos .name .lower ()
181- e .desc += pos .discuss
182- added_events .append (e )
183-
184- # figure out a description
185- if not old_pos and pos .pos .slug != "norecord" :
186- pos .desc = u"[Ballot Position Update] New position, %s, has been recorded for %s" % (pos .pos .name , pos .ad .plain_name ())
187- elif old_pos and pos .pos != old_pos .pos :
188- pos .desc = "[Ballot Position Update] Position for %s has been changed to %s from %s" % (pos .ad .plain_name (), pos .pos .name , old_pos .pos .name )
189-
190- if not pos .desc and changes :
191- pos .desc = u"Ballot %s text updated for %s" % (u" and " .join (changes ), ad .plain_name ())
192-
193- # only add new event if we actually got a change
194- if pos .desc :
195- if login != ad :
196- pos .desc += u" by %s" % login .plain_name ()
197-
198- pos .save ()
199-
200- for e in added_events :
201- e .save () # save them after the position is saved to get later id for sorting order
207+ save_position (form , doc , ballot , ad , login )
202208
203209 if request .POST .get ("send_mail" ):
204210 qstr = ""
@@ -213,6 +219,7 @@ def edit_position(request, name, ballot_id):
213219 return HttpResponseRedirect (return_to_url )
214220 else :
215221 initial = {}
222+ old_pos = doc .latest_event (BallotPositionDocEvent , type = "changed_ballot_position" , ad = ad , ballot = ballot )
216223 if old_pos :
217224 initial ['position' ] = old_pos .pos .slug
218225 initial ['discuss' ] = old_pos .discuss
@@ -240,10 +247,37 @@ def edit_position(request, name, ballot_id):
240247@role_required ('Area Director' , 'Secretariat' )
241248@csrf_exempt
242249def api_set_position (request ):
250+ def err (code , text ):
251+ return HttpResponse (text , status = code , content_type = 'text/plain' )
243252 if request .method == 'POST' :
244- pass
253+ ad = request .user .person
254+ name = request .POST .get ('doc' )
255+ if not name :
256+ return err (400 , "Missing document name" )
257+ try :
258+ doc = Document .objects .get (docalias__name = name )
259+ except Document .DoesNotExist :
260+ return err (404 , "Document not found" )
261+ position_names = BallotPositionName .objects .values_list ('slug' , flat = True )
262+ position = request .POST .get ('position' )
263+ if not position :
264+ return err (400 , "Missing parameter: position, one of: %s " % ',' .join (position_names ))
265+ if not position in position_names :
266+ return err (400 , "Bad position name, must be one of: %s " % ',' .join (position_names ))
267+ ballot = doc .active_ballot ()
268+ if not ballot :
269+ return err (404 , "No open ballot found" )
270+ form = EditPositionForm (request .POST , ballot_type = ballot .ballot_type )
271+ if form .is_valid ():
272+ save_position (form , doc , ballot , ad )
273+ else :
274+ debug .type ('form.errors' )
275+ debug .show ('form.errors' )
276+ errors = form .errors
277+ summary = ',' .join ([ "%s: %s" % (f , striptags (errors [f ])) for f in errors ])
278+ return err (400 , "Form not valid: %s" % summary )
245279 else :
246- return HttpResponse ( "Method not allowed" , status = 405 , content_type = 'text/plain' )
280+ return err ( 405 , "Method not allowed" )
247281
248282 return HttpResponse ("Done" , status = 200 , content_type = 'text/plain' )
249283
0 commit comments