3636from ietf .idtracker .models import IDInternal , BallotInfo
3737from ietf .idrfc .idrfc_wrapper import position_to_string , BALLOT_ACTIVE_STATES
3838from ietf .idtracker .templatetags .ietf_filters import in_group , timesince_days
39+ from ietf .ietfauth .decorators import has_role
40+ from ietf .doc .utils import active_ballot_positions
41+ from ietf .doc .models import BallotDocEvent
3942
4043register = template .Library ()
4144
42- def get_user_adid (context ):
43- if 'user' in context and in_group (context ['user' ], "Area_Director" ):
44- if settings .USE_DB_REDESIGN_PROXY_CLASSES :
45- return context ['user' ].get_profile ().id
46- return context ['user' ].get_profile ().iesg_login_id ()
47- else :
48- return None
49-
5045def get_user_name (context ):
5146 if 'user' in context and context ['user' ].is_authenticated ():
5247 if settings .USE_DB_REDESIGN_PROXY_CLASSES :
@@ -60,105 +55,64 @@ def get_user_name(context):
6055 if person :
6156 return str (person )
6257 return None
63-
64- def render_ballot_icon (context , doc ):
65- if isinstance (doc ,IDInternal ):
66- try :
67- ballot = doc .ballot
68- if not ballot .ballot_issued :
69- return ""
70- except BallotInfo .DoesNotExist :
71- return ""
72- if str (doc .cur_state ) not in BALLOT_ACTIVE_STATES :
73- return ""
74- if doc .rfc_flag and not settings .USE_DB_REDESIGN_PROXY_CLASSES :
75- name = doc .document ().filename ()
76- else :
77- name = doc .document ().filename
78- else :
79- if doc .in_ietf_process () and doc .ietf_process .has_active_iesg_ballot ():
80- ballot = doc ._idinternal .ballot
81- else :
82- return ""
83- if doc .is_rfc_wrapper :
84- name = "rfc" + str (doc .rfc_number )
85- else :
86- name = doc .draft_name
87- adId = get_user_adid (context )
88- red = 0
89- green = 0
90- yellow = 0
91- gray = 0
92- blank = 0
93- my = None
94- for p in ballot .active_positions ():
95- if not p ['pos' ]:
96- blank = blank + 1
97- elif (p ['pos' ].yes > 0 ) or (p ['pos' ].noobj > 0 ):
98- green = green + 1
99- elif (p ['pos' ].discuss > 0 ):
100- red = red + 1
101- elif (p ['pos' ].abstain > 0 ):
102- yellow = yellow + 1
103- elif (p ['pos' ].recuse > 0 ):
104- gray = gray + 1
58+
59+ def render_ballot_icon (user , doc ):
60+ if not doc :
61+ return ""
62+
63+ s = doc .get_state ("draft-iesg" )
64+ if s and s .name not in BALLOT_ACTIVE_STATES :
65+ return ""
66+
67+ ballot = doc .latest_event (BallotDocEvent , type = "created_ballot" )
68+ if not ballot :
69+ return ""
70+
71+ edit_position_url = urlreverse ('doc_edit_position' , kwargs = dict (name = doc .name , ballot_id = ballot .pk ))
72+
73+ def sort_key (t ):
74+ _ , pos = t
75+ if not pos :
76+ return (2 , 0 )
77+ elif pos .pos .blocking :
78+ return (0 , pos .pos .order )
10579 else :
106- blank = blank + 1
107- if adId and (p ['ad' ].id == adId ):
108- my = position_to_string (p ['pos' ])
109- return render_ballot_icon2 (name , red ,yellow ,green ,gray ,blank , my , adId )+ "<!-- adId=" + str (adId )+ " my=" + str (my )+ "-->"
110-
111- def render_ballot_icon2 (draft_name , red ,yellow ,green ,gray ,blank , my ,adId ):
112- from ietf .doc .models import BallotDocEvent
113- ballots = BallotDocEvent .objects .filter (doc__docalias__name = draft_name ).order_by ("-time" , "-id" )
114- if ballots :
115- edit_position_url = urlreverse ('doc_edit_position' , kwargs = dict (name = draft_name , ballot_id = ballots [0 ].pk ))
116- else :
117- edit_position_url = ""
118- if adId :
119- res_cm = ' oncontextmenu="editBallot(\' ' + str (edit_position_url )+ '\' );return false;"'
120- else :
121- res_cm = ''
122- res = '<table class="ballot_icon" title="IESG Evaluation Record (click to show more, right-click to edit position)" onclick="showBallot(\' ' + draft_name + '\' ,\' ' + str (edit_position_url ) + '\' )"' + res_cm + '>'
123- for y in range (3 ):
124- res = res + "<tr>"
125- for x in range (5 ):
126- myMark = False
127- if red > 0 :
128- c = "ballot_icon_red"
129- red = red - 1
130- myMark = (my == "Discuss" )
131- elif yellow > 0 :
132- c = "ballot_icon_yellow"
133- yellow = yellow - 1
134- myMark = (my == "Abstain" )
135- elif green > 0 :
136- c = "ballot_icon_green"
137- green = green - 1
138- myMark = (my == "Yes" ) or (my == "No Objection" )
139- elif gray > 0 :
140- c = "ballot_icon_gray"
141- gray = gray - 1
142- myMark = (my == "Recuse" )
143- else :
144- c = ""
145- myMark = (y == 2 ) and (x == 4 ) and (my == "No Record" )
146- if myMark :
147- res = res + '<td class="' + c + ' ballot_icon_my" />'
148- my = None
149- else :
150- res = res + '<td class="' + c + '" />'
151- res = res + '</tr>'
152- res = res + '</table>'
153- return res
154-
155-
80+ return (1 , pos .pos .order )
81+
82+ positions = list (active_ballot_positions (doc , ballot ).items ())
83+ positions .sort (key = sort_key )
84+
85+ cm = ""
86+ if has_role (user , "Area Director" ):
87+ cm = ' oncontextmenu="editBallot(\' ' + str (edit_position_url )+ '\' );return false;"'
88+
89+ res = ['<table class="ballot_icon" title="IESG Evaluation Record (click to show more, right-click to edit position)" onclick="showBallot(\' ' + doc .name + '\' ,\' ' + str (edit_position_url ) + '\' )"' + cm + '>' ]
90+
91+ res .append ("<tr>" )
92+
93+ for i , (ad , pos ) in enumerate (positions ):
94+ if i > 0 and i % 5 == 0 :
95+ res .append ("</tr>" )
96+ res .append ("<tr>" )
97+
98+ c = "position-%s" % (pos .pos .slug if pos else "norecord" )
99+
100+ if ad == user .get_profile ():
101+ c += " my"
102+
103+ res .append ('<td class="%s" />' % c )
104+
105+ res .append ("</tr>" )
106+ res .append ("</table>" )
107+
108+ return "" .join (res )
109+
156110class BallotIconNode (template .Node ):
157111 def __init__ (self , doc_var ):
158112 self .doc_var = doc_var
159113 def render (self , context ):
160114 doc = template .resolve_variable (self .doc_var , context )
161- return render_ballot_icon (context , doc )
115+ return render_ballot_icon (context . get ( "user" ) , doc . _idinternal )
162116
163117def do_ballot_icon (parser , token ):
164118 try :
0 commit comments