44
55# Portion Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
66# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
7- #
7+ #
88# Redistribution and use in source and binary forms, with or without
9- # modification, are permitted provided that the following conditions
9+ # modification, are permitted provided that the following conditions
1010# are met:
11- #
11+ #
1212# * Redistributions of source code must retain the above copyright
1313# notice, this list of conditions and the following disclaimer.
14- #
14+ #
1515# * Redistributions in binary form must reproduce the above
1616# copyright notice, this list of conditions and the following
1717# disclaimer in the documentation and/or other materials provided
1818# with the distribution.
19- #
19+ #
2020# * Neither the name of the Nokia Corporation and/or its
2121# subsidiary(-ies) nor the names of its contributors may be used
2222# to endorse or promote products derived from this software
2323# without specific prior written permission.
24- #
24+ #
2525# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2626# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2727# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7373from ietf .group .mails import email_admin_re_charter , email_personnel_change , email_comment
7474from ietf .group .models import ( Group , Role , GroupEvent , GroupStateTransitions , GroupURL ,
7575 ChangeStateGroupEvent , GroupFeatures )
76- from ietf .group .utils import (get_charter_text , can_manage_group_type ,
76+ from ietf .group .utils import (get_charter_text , can_manage_group_type ,
7777 milestone_reviewer_for_group_type , can_provide_status_update ,
78- can_manage_materials ,
78+ can_manage_materials ,
7979 construct_group_menu_context , get_group_materials ,
80- save_group_in_history , can_manage_group ,
81- get_group_or_404 , setup_default_community_list_for_group , )
80+ save_group_in_history , can_manage_group ,
81+ get_group_or_404 , setup_default_community_list_for_group , )
8282#
8383from ietf .ietfauth .utils import has_role , is_authorized_in_group
8484from ietf .mailtrigger .utils import gather_relevant_expansions
@@ -337,7 +337,7 @@ def active_programs(request):
337337 return render (request , 'group/active_programs.html' , {'programs' : programs })
338338
339339def active_areas (request ):
340- areas = Group .objects .filter (type = "area" , state = "active" ).order_by ("name" )
340+ areas = Group .objects .filter (type = "area" , state = "active" ).order_by ("name" )
341341 return render (request , 'group/active_areas.html' , {'areas' : areas })
342342
343343def active_wgs (request ):
@@ -371,7 +371,7 @@ def active_rgs(request):
371371 group .chairs = sorted (roles (group , "chair" ), key = extract_last_name )
372372
373373 return render (request , 'group/active_rgs.html' , { 'irtf' : irtf , 'groups' : groups })
374-
374+
375375def active_ags (request ):
376376
377377 groups = Group .objects .filter (type = "ag" , state = "active" ).order_by ("acronym" )
@@ -380,7 +380,7 @@ def active_ags(request):
380380 group .ads = sorted (roles (group , "ad" ), key = extract_last_name )
381381
382382 return render (request , 'group/active_ags.html' , { 'groups' : groups })
383-
383+
384384def bofs (request , group_type ):
385385 groups = Group .objects .filter (type = group_type , state = "bof" )
386386 return render (request , 'group/bofs.html' ,dict (groups = groups ))
@@ -415,7 +415,7 @@ def concluded_groups(request):
415415 sections ['Teams' ] = Group .objects .filter (type = 'team' , state = "conclude" ).select_related ("state" , "charter" ).order_by ("parent__name" ,"acronym" )
416416
417417 for name , groups in sections .items ():
418-
418+
419419 # add start/conclusion date
420420 d = dict ((g .pk , g ) for g in groups )
421421
@@ -519,9 +519,9 @@ def group_about(request, acronym, group_type=None):
519519 requested_close = group .state_id != "conclude" and e and e .type == "requested_close"
520520
521521 can_manage = can_manage_group_type (request .user , group )
522- charter_submit_url = ""
523- if group .features .has_chartering_process :
524- charter_submit_url = urlreverse ('ietf.doc.views_charter.submit' , kwargs = { "name" : charter_name_for_group (group ) })
522+ charter_submit_url = ""
523+ if group .features .has_chartering_process :
524+ charter_submit_url = urlreverse ('ietf.doc.views_charter.submit' , kwargs = { "name" : charter_name_for_group (group ) })
525525
526526 can_provide_update = can_provide_status_update (request .user , group )
527527 status_update = group .latest_event (type = "status_update" )
@@ -606,7 +606,7 @@ def group_about_status_edit(request, acronym, group_type=None):
606606 by = login ,
607607 type = 'status_update' ,
608608 desc = update_text ,
609- )
609+ )
610610 return redirect ('ietf.group.views.group_about' ,acronym = group .acronym )
611611 else :
612612 form = None
@@ -617,7 +617,7 @@ def group_about_status_edit(request, acronym, group_type=None):
617617 form = StatusUpdateForm (initial = {"content" : old_update .desc if old_update else "" })
618618
619619 return render (request , 'group/group_about_status_edit.html' ,
620- {
620+ {
621621 'form' : form ,
622622 'group' :group ,
623623 }
@@ -650,7 +650,7 @@ def email(request, acronym, group_type=None):
650650 'aliases' :aliases ,
651651 'group' :group ,
652652 'ietf_domain' :settings .IETF_DOMAIN ,
653- }))
653+ }))
654654
655655def history (request , acronym , group_type = None ):
656656 group = get_group_or_404 (acronym , group_type )
@@ -727,7 +727,7 @@ def email_aliases(request, acronym=None, group_type=None):
727727
728728 if not acronym :
729729 # require login for the overview page, but not for the group-specific
730- # pages
730+ # pages
731731 if not request .user .is_authenticated :
732732 return redirect ('%s?next=%s' % (settings .LOGIN_URL , request .path ))
733733
@@ -789,7 +789,7 @@ def reorder_roles(roles, role_names):
789789 list += [ r for r in roles if r .name_id == name ]
790790 list += [ r for r in roles if not r in list ]
791791 return list
792-
792+
793793def group_photos (request , group_type = None , acronym = None ):
794794 group = get_object_or_404 (Group , acronym = acronym )
795795 roles = sorted (Role .objects .filter (group__acronym = acronym ),key = lambda x : x .name .name + x .person .last_name ())
@@ -808,7 +808,7 @@ def group_photos(request, group_type=None, acronym=None):
808808## XXX Remove after testing
809809# def get_or_create_initial_charter(group, group_type):
810810# charter_name = charter_name_for_group(group)
811- #
811+ #
812812# try:
813813# charter = Document.objects.get(docalias__name=charter_name)
814814# except Document.DoesNotExist:
@@ -822,40 +822,40 @@ def group_photos(request, group_type=None, acronym=None):
822822# )
823823# charter.save()
824824# charter.set_state(State.objects.get(used=True, type="charter", slug="notrev"))
825- #
825+ #
826826# # Create an alias as well
827827# DocAlias.objects.create(name=charter.name, document=charter)
828- #
828+ #
829829# return charter
830- #
830+ #
831831# @login_required
832832# def submit_initial_charter(request, group_type=None, acronym=None):
833- #
833+ #
834834# # This needs refactoring.
835835# # The signature assumed you could have groups with the same name, but with different types, which we do not allow.
836- # # Consequently, this can be called with an existing group acronym and a type
836+ # # Consequently, this can be called with an existing group acronym and a type
837837# # that doesn't match the existing group type. The code below essentially ignores the group_type argument.
838838# #
839839# # If possible, the use of get_or_create_initial_charter should be moved
840840# # directly into charter_submit, and this function should go away.
841- #
841+ #
842842# if acronym==None:
843843# raise Http404
844- #
844+ #
845845# group = get_object_or_404(Group, acronym=acronym)
846846# if not group.features.has_chartering_process:
847847# raise Http404
848- #
848+ #
849849# # This is where we start ignoring the passed in group_type
850850# group_type = group.type_id
851- #
851+ #
852852# if not can_manage_group(request.user, group):
853853# return HttpResponseForbidden("You don't have permission to access this view")
854- #
854+ #
855855# if not group.charter:
856856# group.charter = get_or_create_initial_charter(group, group_type)
857857# group.save()
858- #
858+ #
859859# return redirect('ietf.doc.views_charter.submit', name=group.charter.name, option="initcharter")
860860
861861@login_required
@@ -1068,7 +1068,7 @@ def conclude(request, acronym, group_type=None):
10681068 kwargs = {'acronym' :group .acronym }
10691069 if group_type :
10701070 kwargs ['group_type' ] = group_type
1071-
1071+
10721072 return redirect (group .features .about_page , ** kwargs )
10731073 else :
10741074 form = ConcludeGroupForm ()
@@ -1384,10 +1384,11 @@ def reviewer_overview(request, acronym, group_type=None):
13841384 person .completely_unavailable = any (p .availability == "unavailable"
13851385 and (p .start_date is None or p .start_date <= today ) and (p .end_date is None or today <= p .end_date )
13861386 for p in person .unavailable_periods )
1387- person .busy = person .id in days_needed
1388-
1387+ person .busy = person .id in days_needed
1388+
13891389
13901390 MAX_CLOSED_REQS = 10
1391+ days_since = 9999
13911392 req_data = req_data_for_reviewers .get (person .pk , [])
13921393 open_reqs = sum (1 for d in req_data if d .state in ["requested" , "accepted" ])
13931394 latest_reqs = []
@@ -1396,7 +1397,15 @@ def reviewer_overview(request, acronym, group_type=None):
13961397 latest_reqs .append ((d .req_pk , d .doc , d .reviewed_rev , d .assigned_time , d .deadline ,
13971398 review_state_by_slug .get (d .state ),
13981399 int (math .ceil (d .assignment_to_closure_days )) if d .assignment_to_closure_days is not None else None ))
1400+ if d .state in ["completed" , "completed_in_time" , "completed_late" ]:
1401+ if d .assigned_time is not None :
1402+ delta = datetime .datetime .now () - d .assigned_time
1403+ if d .assignment_to_closure_days is not None :
1404+ days = int (delta .days - d .assignment_to_closure_days )
1405+ if days_since > days : days_since = days
1406+
13991407 person .latest_reqs = latest_reqs
1408+ person .days_since_completed_review = days_since
14001409
14011410 return render (request , 'group/reviewer_overview.html' ,
14021411 construct_group_menu_context (request , group , "reviewers" , group_type , {
@@ -1503,7 +1512,7 @@ def manage_review_requests(request, acronym, group_type=None, assignment_status=
15031512 if not person in assignments_by_person :
15041513 assignments_by_person [person ] = []
15051514 assignments_by_person [person ].append (r )
1506-
1515+
15071516 # Make sure the any assignments to the person at the head
15081517 # of the rotation queue are processed first so that the queue
15091518 # rotates before any more assignments are processed
@@ -1517,15 +1526,15 @@ def manage_review_requests(request, acronym, group_type=None, assignment_status=
15171526
15181527 for review_req in reqs_to_assign :
15191528 assign_review_request_to_reviewer (request , review_req , review_req .form .cleaned_data ["reviewer" ],review_req .form .cleaned_data ["add_skip" ])
1520-
1529+
15211530 kwargs = { "acronym" : group .acronym }
15221531 if group_type :
15231532 kwargs ["group_type" ] = group_type
15241533
15251534 if form_action == "save-continue" :
15261535 if assignment_status :
15271536 kwargs ["assignment_status" ] = assignment_status
1528-
1537+
15291538 return redirect (manage_review_requests , ** kwargs )
15301539 else :
15311540 import ietf .group .views
@@ -1625,7 +1634,7 @@ def email_open_review_assignments(request, acronym, group_type=None):
16251634 "rotation_list" : reviewer_rotation_list (group )[:10 ],
16261635 "group" : group ,
16271636 })
1628-
1637+
16291638 (msg ,_ ,_ ) = parse_preformatted (partial_msg )
16301639
16311640 body = msg .get_payload ()
@@ -1840,7 +1849,7 @@ def add_comment(request, acronym, group_type=None):
18401849
18411850 if not is_authorized_in_group (request .user ,group ):
18421851 return HttpResponseForbidden ("You need to a chair, secretary, or delegate of this group to add a comment." )
1843-
1852+
18441853 if request .method == 'POST' :
18451854 form = AddCommentForm (request .POST )
18461855 if form .is_valid ():
0 commit comments