Skip to content

Commit 27935fb

Browse files
committed
Don't prompt for the day of the month in setting up milestones,
instead set the deadline to the last day of the month, also remove any references to the day of the month from the output - Legacy-Id: 4596
1 parent 95b1445 commit 27935fb

6 files changed

Lines changed: 68 additions & 294 deletions

File tree

ietf/templates/wginfo/edit_milestones.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ <h1>{{ title }}</h1>
9393
{% block content_end %}
9494
<script type="text/javascript" src="/js/lib/jquery.tokeninput.js"></script>
9595
<script type="text/javascript" src="/js/lib/json2.js"></script>
96-
<script type="text/javascript" src="/js/lib/jquery.maskedinput.js"></script>
9796
<script type="text/javascript" src="/js/tokenized-field.js"></script>
9897
<script>
9998
var finishedMilestoneText = "{{ finished_milestone_text|escapejs }}";

ietf/templates/wginfo/milestone_form.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
</tr>
1919
{% if form.desc.errors %}<tr><td></td><td colspan="2">{{ form.desc.errors }}</td></tr>{% endif %}
2020
<tr>
21-
<td>{{ form.due.label_tag }}:</td>
22-
<td><span class="due">{{ form.due }}</span> {{ form.due.errors }}
21+
<td>Due date:</td>
22+
<td><span class="due">{{ form.due_month }} {{ form.due_year }}</span> {{ form.due_month.errors }} {{ form.due_year.errors }}
2323
<span class="resolved">{{ form.resolved_checkbox }} {{ form.resolved_checkbox.label_tag }} {{ form.resolved }}</span>
2424
{{ form.resolved.errors }}
2525
</td>

ietf/wginfo/milestones.py

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# WG milestone editing views
22

3-
import re, os, string, datetime, shutil
3+
import re, os, string, datetime, shutil, calendar
44

55
from django.shortcuts import render_to_response, get_object_or_404, redirect
66
from django.core.urlresolvers import reverse
@@ -29,7 +29,8 @@ class MilestoneForm(forms.Form):
2929
id = forms.IntegerField(required=True, widget=forms.HiddenInput)
3030

3131
desc = forms.CharField(max_length=500, label="Milestone", required=True)
32-
due = forms.DateField(required=True, label="Due date")
32+
due_month = forms.TypedChoiceField(choices=(), required=True, coerce=int)
33+
due_year = forms.TypedChoiceField(choices=(), required=True, coerce=int)
3334
resolved_checkbox = forms.BooleanField(required=False, label="Resolved")
3435
resolved = forms.CharField(max_length=50, required=False)
3536

@@ -50,7 +51,8 @@ def __init__(self, *args, **kwargs):
5051
kwargs["initial"] = {}
5152
kwargs["initial"].update(dict(id=m.pk,
5253
desc=m.desc,
53-
due=m.due,
54+
due_month=m.due.month,
55+
due_year=m.due.year,
5456
resolved_checkbox=bool(m.resolved),
5557
resolved=m.resolved,
5658
docs=",".join(m.docs.values_list("pk", flat=True)),
@@ -62,6 +64,20 @@ def __init__(self, *args, **kwargs):
6264

6365
super(MilestoneForm, self).__init__(*args, **kwargs)
6466

67+
# set choices for due date
68+
this_year = datetime.date.today().year
69+
70+
self.fields["due_month"].choices = [(m, datetime.date(this_year, m, 1).strftime("%B")) for m in range(1, 13)]
71+
72+
years = [ y for y in range(this_year, this_year + 10)]
73+
74+
initial = self.initial.get("due_year")
75+
if initial and initial not in years:
76+
years.insert(0, initial)
77+
78+
self.fields["due_year"].choices = zip(years, map(str, years))
79+
80+
6581
# figure out what to prepopulate many-to-many field with
6682
pre = ""
6783
if not self.is_bound:
@@ -122,6 +138,11 @@ def edit_milestones(request, acronym, milestone_set="current"):
122138

123139
milestones_dict = dict((str(m.id), m) for m in milestones)
124140

141+
def due_month_year_to_date(c):
142+
y = c["due_year"]
143+
m = c["due_month"]
144+
return datetime.date(y, m, calendar.monthrange(y, m)[1])
145+
125146
def set_attributes_from_form(f, m):
126147
c = f.cleaned_data
127148
m.group = group
@@ -133,7 +154,7 @@ def set_attributes_from_form(f, m):
133154
elif milestone_set == "charter":
134155
m.state = GroupMilestoneStateName.objects.get(slug="charter")
135156
m.desc = c["desc"]
136-
m.due = c["due"]
157+
m.due = due_month_year_to_date(c)
137158
m.resolved = c["resolved"]
138159

139160
def save_milestone_form(f):
@@ -177,11 +198,13 @@ def save_milestone_form(f):
177198
m.desc = c["desc"]
178199
changes.append('set description to "%s"' % m.desc)
179200

180-
if c["due"] != m.due:
201+
202+
c_due = due_month_year_to_date(c)
203+
if c_due != m.due:
181204
if not history:
182205
history = save_milestone_in_history(m)
183-
changes.append('set due date to %s from %s' % (c["due"].strftime("%Y-%m-%d"), m.due.strftime("%Y-%m-%d")))
184-
m.due = c["due"]
206+
changes.append('set due date to %s from %s' % (c_due.strftime("%B %Y"), m.due.strftime("%B %Y")))
207+
m.due = c_due
185208

186209
resolved = c["resolved"]
187210
if resolved != m.resolved:
@@ -230,9 +253,9 @@ def save_milestone_form(f):
230253
named_milestone = "charter " + named_milestone
231254

232255
if m.state_id in ("active", "charter"):
233-
return 'Added %s, due %s' % (named_milestone, m.due.strftime("%Y-%m-%d"))
256+
return 'Added %s, due %s' % (named_milestone, m.due.strftime("%B %Y"))
234257
elif m.state_id == "review":
235-
return 'Added %s for review, due %s' % (named_milestone, m.due.strftime("%Y-%m-%d"))
258+
return 'Added %s for review, due %s' % (named_milestone, m.due.strftime("%B %Y"))
236259

237260
finished_milestone_text = "Done"
238261

@@ -353,7 +376,7 @@ def reset_charter_milestones(request, acronym):
353376

354377
DocEvent.objects.create(type="changed_charter_milestone",
355378
doc=group.charter,
356-
desc='Added milestone "%s", due %s, from current group milestones' % (new.desc, new.due.strftime("%Y-%m-%d")),
379+
desc='Added milestone "%s", due %s, from current group milestones' % (new.desc, new.due.strftime("%B %Y")),
357380
by=login,
358381
)
359382

ietf/wginfo/tests.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3131
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3232

33-
import os, unittest, shutil
33+
import os, unittest, shutil, calendar
3434

3535
import django.test
3636
from django.conf import settings
@@ -275,6 +275,9 @@ def create_test_milestones(self):
275275

276276
return (m1, m2, group)
277277

278+
def last_day_of_month(self, d):
279+
return datetime.date(d.year, d.month, calendar.monthrange(d.year, d.month)[1])
280+
278281

279282
def test_milestone_sets(self):
280283
m1, m2, group = self.create_test_milestones()
@@ -308,13 +311,14 @@ def test_add_milestone(self):
308311
events_before = group.groupevent_set.count()
309312
docs = Document.objects.filter(type="draft").values_list("name", flat=True)
310313

311-
due = datetime.date.today() + datetime.timedelta(days=365)
314+
due = self.last_day_of_month(datetime.date.today() + datetime.timedelta(days=365))
312315

313316
# faulty post
314317
r = self.client.post(url, { 'prefix': "m-1",
315-
'm-1-id': -1,
318+
'm-1-id': "-1",
316319
'm-1-desc': "", # no description
317-
'm-1-due': due.strftime("%Y-%m-%d"),
320+
'm-1-due_month': str(due.month),
321+
'm-1-due_year': str(due.year),
318322
'm-1-resolved': "",
319323
'm-1-docs': ",".join(docs),
320324
'action': "save",
@@ -326,9 +330,10 @@ def test_add_milestone(self):
326330

327331
# add
328332
r = self.client.post(url, { 'prefix': "m-1",
329-
'm-1-id': -1,
333+
'm-1-id': "-1",
330334
'm-1-desc': "Test 3",
331-
'm-1-due': due.strftime("%Y-%m-%d"),
335+
'm-1-due_month': str(due.month),
336+
'm-1-due_year': str(due.year),
332337
'm-1-resolved': "",
333338
'm-1-docs': ",".join(docs),
334339
'action': "save",
@@ -356,13 +361,14 @@ def test_add_milestone_as_chair(self):
356361

357362
milestones_before = GroupMilestone.objects.count()
358363
events_before = group.groupevent_set.count()
359-
due = datetime.date.today() + datetime.timedelta(days=365)
364+
due = self.last_day_of_month(datetime.date.today() + datetime.timedelta(days=365))
360365

361366
# add
362367
r = self.client.post(url, { 'prefix': "m-1",
363368
'm-1-id': -1,
364369
'm-1-desc': "Test 3",
365-
'm-1-due': due.strftime("%Y-%m-%d"),
370+
'm-1-due_month': str(due.month),
371+
'm-1-due_year': str(due.year),
366372
'm-1-resolved': "",
367373
'm-1-docs': "",
368374
'action': "save",
@@ -388,18 +394,20 @@ def test_accept_milestone(self):
388394
self.assertEquals(r.status_code, 200)
389395

390396
events_before = group.groupevent_set.count()
391-
due = datetime.date.today() + datetime.timedelta(days=365)
397+
due = self.last_day_of_month(datetime.date.today() + datetime.timedelta(days=365))
392398

393399
# add
394400
r = self.client.post(url, { 'prefix': "m1",
395401
'm1-id': m1.id,
396402
'm1-desc': m1.desc,
397-
'm1-due': m1.due.strftime("%Y-%m-%d"),
403+
'm1-due_month': str(m1.due.month),
404+
'm1-due_year': str(m1.due.year),
398405
'm1-resolved': m1.resolved,
399406
'm1-docs': ",".join(m1.docs.values_list("name", flat=True)),
400407
'm1-accept': "accept",
401408
'action': "save",
402409
})
410+
print r.content
403411
self.assertEquals(r.status_code, 302)
404412

405413
m = GroupMilestone.objects.get(pk=m1.pk)
@@ -420,7 +428,8 @@ def test_delete_milestone(self):
420428
r = self.client.post(url, { 'prefix': "m1",
421429
'm1-id': m1.id,
422430
'm1-desc': m1.desc,
423-
'm1-due': m1.due.strftime("%Y-%m-%d"),
431+
'm1-due_month': str(m1.due.month),
432+
'm1-due_year': str(m1.due.year),
424433
'm1-resolved': "",
425434
'm1-docs': ",".join(m1.docs.values_list("name", flat=True)),
426435
'm1-delete': "checked",
@@ -444,13 +453,14 @@ def test_edit_milestone(self):
444453
events_before = group.groupevent_set.count()
445454
docs = Document.objects.filter(type="draft").values_list("name", flat=True)
446455

447-
due = datetime.date.today() + datetime.timedelta(days=365)
456+
due = self.last_day_of_month(datetime.date.today() + datetime.timedelta(days=365))
448457

449458
# faulty post
450459
r = self.client.post(url, { 'prefix': "m1",
451460
'm1-id': m1.id,
452461
'm1-desc': "", # no description
453-
'm1-due': due.strftime("%Y-%m-%d"),
462+
'm1-due_month': str(due.month),
463+
'm1-due_year': str(due.year),
454464
'm1-resolved': "",
455465
'm1-docs': ",".join(docs),
456466
'action': "save",
@@ -467,7 +477,8 @@ def test_edit_milestone(self):
467477
r = self.client.post(url, { 'prefix': "m1",
468478
'm1-id': m1.id,
469479
'm1-desc': "Test 2 - changed",
470-
'm1-due': due.strftime("%Y-%m-%d"),
480+
'm1-due_month': str(due.month),
481+
'm1-due_year': str(due.year),
471482
'm1-resolved': "Done",
472483
'm1-resolved_checkbox': "checked",
473484
'm1-docs': ",".join(docs),
@@ -566,6 +577,9 @@ def test_send_milestones_due_reminders(self):
566577

567578
early_warning_days = 30
568579

580+
# due dates here aren't aligned on the last day of the month,
581+
# but everything should still work
582+
569583
m1 = GroupMilestone.objects.create(group=group,
570584
desc="Test 1",
571585
due=datetime.date.today(),
@@ -606,6 +620,9 @@ def test_send_milestones_overdue_reminders(self):
606620
group = Group.objects.get(acronym="mars")
607621
person = Person.objects.get(user__username="marschairman")
608622

623+
# due dates here aren't aligned on the last day of the month,
624+
# but everything should still work
625+
609626
m1 = GroupMilestone.objects.create(group=group,
610627
desc="Test 1",
611628
due=datetime.date.today() - datetime.timedelta(days=200),
@@ -627,7 +644,7 @@ def test_send_milestones_overdue_reminders(self):
627644
m1.resolved = ""
628645
m1.save()
629646

630-
m2.due = datetime.date.today() - datetime.timedelta(days=300)
647+
m2.due = self.last_day_of_month(datetime.date.today() - datetime.timedelta(days=300))
631648
m2.save()
632649

633650
# send

static/js/edit-milestones.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jQuery(function () {
1010

1111
function setSubmitButtonState() {
1212
var action, label;
13-
if (jQuery("#milestones-form input[name$=due]:visible").length > 0)
13+
if (jQuery("#milestones-form input[name$=delete]:visible").length > 0)
1414
action = "review";
1515
else
1616
action = "save";
@@ -46,7 +46,6 @@ jQuery(function () {
4646

4747
editRow.removeClass("template");
4848
setupTokenizedField(editRow.find(".tokenized-field")); // from tokenized-field.js
49-
setInputMasks(editRow);
5049
editRow.show();
5150
}
5251
else {
@@ -102,12 +101,6 @@ jQuery(function () {
102101
.each(setDeleteState)
103102
.live("change", setDeleteState);
104103

105-
function setInputMasks(editRows) {
106-
editRows.find(".due input").mask("9999-99-99");
107-
}
108-
109-
setInputMasks(jQuery("#milestone-form .edit-milestone").not(".template"));
110-
111104
jQuery('#milestones-form .edit-milestone .errorlist').each(function () {
112105
jQuery(this).closest(".edit-milestone").prev().click();
113106
});

0 commit comments

Comments
 (0)