57c305c1 |
1 | <% @header[("title", ["Polls"])]; |
2 | |
3 | val pollAdmin = Group.inGroupName "poll"; |
4 | |
5 | ref editingPoll = NONE; |
6 | ref showNormal = true; |
7 | |
8 | if $"cmd" = "list" then |
9 | showNormal := false %> |
10 | |
1fe415e0 |
11 | <h2>All polls</h2> |
57c305c1 |
12 | |
13 | <% foreach pol in Poll.listPolls () do %> |
14 | <li> <a href="poll?id=<% #id pol %>"><% Web.html (#title pol) %></a> |
15 | <% if pollAdmin then %><a href="poll?del=<% #id pol %>">[Delete]</a> <% end %> |
16 | </li> |
17 | <% end |
18 | |
7f97ec97 |
19 | elseif $"vote" <> "" then |
20 | showNormal := false; |
21 | val id = Web.stoi ($"vote"); |
22 | val poll = Poll.lookupPoll id %> |
23 | |
1fe415e0 |
24 | <table class="blanks"> |
25 | <tr> <td>Poll#:</td> <td><% id %></td> </tr> |
26 | <tr> <td>Title:</td> <td><% Web.html (#title poll) %></td> </tr> |
27 | <tr> <td>Start:</td> <td><% Web.html (#starts poll) %></td> </tr> |
28 | <tr> <td>End:</td> <td><% Web.html (#ends poll) %></td> </tr> |
29 | <tr> <td>Votes/person:</td> <td><% #votes poll %></td> </tr> |
30 | <tr> <td>Description:</td> <td><% Web.htmlNl (#descr poll) %></td> </tr> |
7f97ec97 |
31 | </table> |
32 | |
1fe415e0 |
33 | <h3>Choices</h3> |
7f97ec97 |
34 | |
add44c00 |
35 | <form action="poll" method="post"> |
7f97ec97 |
36 | <input type="hidden" name="vote2" value="<% id %>"> |
37 | <% val choices = Poll.listChoicesWithMyVotes id; |
38 | if #votes poll = 1 then %> |
39 | <select name="v"> |
40 | <option value="">Abstain</option> |
41 | <% else %> |
42 | <select name="v" multiple size="<% length choices %>"> |
43 | <% end |
44 | foreach (you, cho) in choices do %> |
45 | <option value="<% #id cho %>"<% if you then %> selected<% end %>><% Web.html (#descr cho) %></option> |
46 | <% end %></select><br><br> |
47 | <input type="submit" value="Vote"> |
48 | </form> |
49 | |
50 | <% elseif $"vote2" <> "" then |
51 | val id = Web.stoi ($"vote2"); |
52 | val poll = Poll.lookupPoll id; |
53 | editingPoll := SOME id; |
54 | |
55 | val votes = case Web.getMultiParam "v" of |
56 | [""] => [] |
57 | | v => map Web.stoi v; |
58 | |
59 | if length votes > #votes poll then |
1fe415e0 |
60 | %><h3>You can't vote for that many different choices!</h3><% |
7f97ec97 |
61 | elseif not (Poll.noDupes votes) then |
1fe415e0 |
62 | %><h3>You can't vote multiple times for the same choice!</h3><% |
7f97ec97 |
63 | else |
64 | Poll.vote (Init.getUserId (), id, votes) |
1fe415e0 |
65 | %><h3>Thanks for voting!</h3> |
7f97ec97 |
66 | <% end |
67 | |
57c305c1 |
68 | elseif $"cmd" = "add" then |
69 | val title = $"title"; |
70 | val starts = $"starts"; |
71 | val ends = $"ends"; |
72 | val votes = Web.stoi ($"votes"); |
73 | if title = "" then |
1fe415e0 |
74 | %><h3>Your poll must have a title.</h3><% |
646dca75 |
75 | elseif not pollAdmin and not (Poll.dateGeNow starts) then |
1fe415e0 |
76 | %><h3>That start date is in the past!</h3><% |
646dca75 |
77 | elseif not pollAdmin and not (Poll.dateLe (starts, ends)) then |
1fe415e0 |
78 | %><h3>The end date comes before the start date!</h3><% |
57c305c1 |
79 | elseif votes <= 0 then |
1fe415e0 |
80 | %><h3>You must specify a positive number of votes per person.</h3><% |
57c305c1 |
81 | else |
82 | val id = Poll.addPoll (Init.getUserId(), title, $"descr", starts, ends, votes); |
83 | editingPoll := SOME id; |
1fe415e0 |
84 | %><h3>Poll added!</h3><% |
57c305c1 |
85 | end |
86 | |
87 | elseif $"mod" <> "" then |
88 | showNormal := false; |
89 | val poll = Poll.lookupPoll (Web.stoi ($"mod")); |
90 | |
91 | Poll.requireCanModify poll %> |
1fe415e0 |
92 | <h3>Modify poll</h3> |
57c305c1 |
93 | |
add44c00 |
94 | <form action="poll" method="post"> |
57c305c1 |
95 | <input type="hidden" name="id" value="<% $"mod" %>"> |
1fe415e0 |
96 | <table class="blanks"> |
97 | <tr> <td>Title:</td> <td><input name="title" value="<% Web.html (#title poll) %>"></td> </tr> |
98 | <tr> <td>Start date:</td> <td><input name="starts" value="<% Web.html (#starts poll) %>"></td> </tr> |
99 | <tr> <td>End date:</td> <td><input name="ends" value="<% Web.html (#ends poll) %>"></td> </tr> |
100 | <tr> <td>Max votes/person:</td> <td><input name="votes" value="<% #votes poll %>"></td> </tr> |
101 | <tr> <td>Description:</td> <td><textarea name="descr" wrap="soft" rows="5" cols="80"><% Web.html (#descr poll) %></textarea></td> </tr> |
57c305c1 |
102 | <tr> <td><input type="submit" name="cmd" value="Save"></td> </tr> |
103 | </table> |
104 | </form> |
105 | |
106 | <% elseif $"cmd" = "Save" then |
107 | val poll = Poll.lookupPoll (Web.stoi ($"id")); |
108 | |
109 | Poll.requireCanModify poll; |
110 | |
111 | val title = $"title"; |
112 | val starts = $"starts"; |
113 | val ends = $"ends"; |
114 | val votes = Web.stoi ($"votes"); |
115 | if title = "" then |
1fe415e0 |
116 | %><h3>Your poll must have a title.</h3><% |
646dca75 |
117 | elseif not pollAdmin and not (Poll.dateGeNow starts) then |
1fe415e0 |
118 | %><h3>That start date is in the past!</h3><% |
646dca75 |
119 | elseif not pollAdmin and not (Poll.dateLe (starts, ends)) then |
1fe415e0 |
120 | %><h3>The end date comes before the start date!</h3><% |
57c305c1 |
121 | elseif votes <= 0 then |
1fe415e0 |
122 | %><h3>You must specify a positive number of votes per person.</h3><% |
57c305c1 |
123 | else |
124 | Poll.modPoll {poll with title = title, descr = $"descr", starts = starts, ends = ends, votes = votes}; |
125 | editingPoll := SOME (#id poll); |
1fe415e0 |
126 | %><h3>Poll record saved.</h3><% |
57c305c1 |
127 | end |
128 | |
129 | elseif $"del" <> "" then |
130 | Group.requireGroupName "poll"; |
131 | showNormal := false; |
132 | val poll = Poll.lookupPoll (Web.stoi ($"del")) %> |
1fe415e0 |
133 | <h3>Are you sure you want to delete poll <a href="poll?id=<% #id poll %>"><% Web.html (#title poll) %></a>?</h3> |
57c305c1 |
134 | <a href="poll?del2=<% $"del" %>">Yes, delete <% Web.html (#title poll) %>!</a> |
135 | |
136 | <% elseif $"del2" <> "" then |
137 | Group.requireGroupName "poll"; |
138 | val poll = Poll.lookupPoll (Web.stoi ($"del2")); |
139 | Poll.deletePoll (Web.stoi ($"del2")) %> |
1fe415e0 |
140 | <h3><% Web.html (#title poll) %> deleted!</h3> |
57c305c1 |
141 | |
142 | <% elseif $"addChoice" <> "" then |
143 | val id = Web.stoi ($"addChoice"); |
144 | editingPoll := SOME id; |
145 | val descr = $"descr"; |
146 | if descr = "" then |
1fe415e0 |
147 | %><h3>Your poll choice must have a description.</h3><% |
57c305c1 |
148 | else |
149 | val id = Poll.addChoice (id, Web.stor ($"seq"), descr); |
1fe415e0 |
150 | %><h3>Choice added!</h3><% |
57c305c1 |
151 | end |
152 | |
153 | elseif $"modChoice" <> "" then |
154 | showNormal := false; |
155 | val id = Web.stoi ($"modChoice"); |
156 | val cho = Poll.lookupChoice id; |
157 | val poll = Poll.lookupPoll (#pol cho); |
158 | Poll.requireCanModify poll %> |
159 | |
add44c00 |
160 | <form action="poll" method="post"> |
57c305c1 |
161 | <input type="hidden" name="saveChoice" value="<% id %>"> |
1fe415e0 |
162 | <table class="blanks"> |
163 | <tr> <td>Text:</td> <td><input name="descr" value="<% Web.html (#descr cho) %>"></td> </tr> |
164 | <tr> <td>Sequence#:</td> <td><input name="seq" value="<% #seq cho %>"></td> </tr> |
57c305c1 |
165 | <tr> <td><input type="submit" value="Save"></td> </tr> |
166 | </table> |
167 | </form> |
168 | |
169 | <% elseif $"saveChoice" <> "" then |
170 | val id = Web.stoi ($"saveChoice"); |
171 | val cho = Poll.lookupChoice id; |
172 | val poll = Poll.lookupPoll (#pol cho); |
173 | Poll.requireCanModify poll; |
174 | editingPoll := SOME (#id poll); |
175 | val descr = $"descr"; |
176 | if descr = "" then |
1fe415e0 |
177 | %><h3>Your poll choice must have a description.</h3><% |
57c305c1 |
178 | else |
179 | Poll.modChoice {cho with seq = Web.stor ($"seq"), descr = descr}; |
1fe415e0 |
180 | %><h3>Choice saved!</h3><% |
57c305c1 |
181 | end |
182 | |
183 | elseif $"delChoice" <> "" then |
184 | val id = Web.stoi ($"delChoice"); |
185 | val cho = Poll.lookupChoice id; |
186 | val poll = Poll.lookupPoll (#pol cho); |
187 | Poll.requireCanModify poll; |
188 | showNormal := false %> |
1fe415e0 |
189 | <h3>Are you sure you want to delete choice "<% Web.html (#descr cho) %>"</a>?</h3> |
57c305c1 |
190 | <a href="poll?delChoice2=<% $"delChoice" %>">Yes, delete "<% Web.html (#descr cho) %>"!</a> |
191 | |
192 | <% elseif $"delChoice2" <> "" then |
193 | val id = Web.stoi ($"delChoice2"); |
194 | val cho = Poll.lookupChoice id; |
195 | val poll = Poll.lookupPoll (#pol cho); |
196 | Poll.requireCanModify poll; |
197 | Poll.deleteChoice id; |
198 | editingPoll := SOME (#id poll) %> |
1fe415e0 |
199 | <h3>"<% Web.html (#descr cho) %>" deleted!</h3> |
57c305c1 |
200 | |
7f97ec97 |
201 | <% elseif $"report" <> "" then |
202 | showNormal := false; |
203 | val id = Web.stoi ($"report"); |
204 | |
205 | val poll = Poll.lookupPoll id; |
206 | val canModify = Poll.canModify poll %> |
207 | |
1fe415e0 |
208 | <h3>Vote Report</h3> |
7f97ec97 |
209 | |
fd650826 |
210 | <p>Voters: |
211 | <% ref first = true; |
212 | foreach user in Poll.listPollVoters id do |
213 | if first then |
214 | first := false |
215 | else |
216 | %>, <% |
217 | end |
218 | %><a href="user?id=<% #id user %>"><% #name user %></a><% |
219 | end %></p> |
220 | |
1fe415e0 |
221 | <table class="blanks"> |
222 | <tr> <td>Poll#</b>:</td> <td><% id %></td> </tr> |
223 | <tr> <td>Title</b>:</td> <td><% Web.html (#title poll) %></td> </tr> |
7c1a0a61 |
224 | <tr> <td>Start:</td> <td><% Web.html (#starts poll) %></td> </tr> |
1fe415e0 |
225 | <tr> <td>End:</td> <td><% Web.html (#ends poll) %></td> </tr> |
226 | <tr> <td>Votes/person:</td> <td><% #votes poll %></td> </tr> |
227 | <tr> <td>Description:</td> <td><% Web.htmlNl (#descr poll) %></td> </tr> |
7f97ec97 |
228 | </table> |
229 | |
230 | <br><hr><br> |
231 | |
232 | <table> |
233 | <tr> <td><b>Votes</b></td> <td><b>Choice</b></td> <td><b>Voters</b></td> </tr> |
234 | <% foreach (_, total, cho) in Poll.listChoicesWithVotes id do %> |
235 | <tr> <td><% total %></td> <td><% Web.html (#descr cho) %></td> <td> |
236 | <% ref first = true; |
237 | foreach user in Poll.listVoters (#id cho) do |
238 | if first then |
239 | first := false |
240 | else |
241 | %>, <% |
242 | end |
243 | %><a href="user?id=<% #id user %>"><% #name user %></a><% |
244 | end |
245 | %></td> </tr><% |
246 | end %> |
247 | </table> |
248 | |
57c305c1 |
249 | <% elseif $"id" <> "" then |
250 | editingPoll := SOME (Web.stoi ($"id")) |
251 | |
252 | end %> |
253 | |
254 | <% switch editingPoll of |
255 | SOME id => |
7f97ec97 |
256 | val poll = Poll.lookupPoll id; |
257 | val canModify = Poll.canModify poll %> |
57c305c1 |
258 | |
1fe415e0 |
259 | <table class="blanks"> |
57c305c1 |
260 | <% if canModify then %><tr> <td></td> <td><a href="poll?mod=<% id %>">Edit poll data</a></td> </tr><% end %> |
1fe415e0 |
261 | <tr> <td>Poll#:</td> <td><% id %></td> </tr> |
262 | <tr> <td>Title:</td> <td><% Web.html (#title poll) %></td> </tr> |
263 | <tr> <td>Start:</td> <td><% Web.html (#starts poll) %></td> </tr> |
264 | <tr> <td>End:</td> <td><% Web.html (#ends poll) %></td> </tr> |
265 | <tr> <td>Votes/person:</td> <td><% #votes poll %></td> </tr> |
266 | <tr> <td>Description:</td> <td><% Web.htmlNl (#descr poll) %></td> </tr> |
57c305c1 |
267 | </table> |
268 | |
1fe415e0 |
269 | <h3>Choices<% if Poll.takingVotes poll then %><a href="poll?vote=<% id %>">(Vote!)</a><% end %></h3> |
57c305c1 |
270 | |
fd650826 |
271 | <p><% Poll.countVoters (#id poll) %> people have voted.</p> |
272 | |
7f97ec97 |
273 | <% if Poll.takingVotes poll then %> |
274 | <table> |
275 | <tr> <td><b>You</b></td> <td><b>Total</b></td> </tr> |
276 | <% foreach (you, total, cho) in Poll.listChoicesWithVotes id do %> |
277 | <tr> <td align="center"><% if you then %>X<% end %></td> |
278 | <td align="center"><% total %></td> |
279 | <td><% Web.html (#descr cho) %></td> |
280 | <% if canModify then %> |
281 | <td><i>(<% #seq cho %>)</i> |
282 | <a href="poll?modChoice=<% #id cho %>">[Modify]</a> |
283 | <a href="poll?delChoice=<% #id cho %>">[Delete]</a></td> |
284 | <% end %></tr> |
285 | <% end %> |
286 | </table> |
287 | |
7f97ec97 |
288 | <% else |
289 | foreach cho in Poll.listChoices id do %> |
57c305c1 |
290 | <li> <% Web.html (#descr cho) %> |
291 | <% if canModify then %> |
292 | <i>(<% #seq cho %>)</i> |
293 | <a href="poll?modChoice=<% #id cho %>">[Modify]</a> |
294 | <a href="poll?delChoice=<% #id cho %>">[Delete]</a> |
295 | <% end %></li> |
7f97ec97 |
296 | <% end |
297 | end %> |
57c305c1 |
298 | |
ce7b516a |
299 | <a href="poll?report=<% id %>">Vote Report</a> |
300 | |
57c305c1 |
301 | <% if canModify then %> |
302 | <br><hr><br> |
1fe415e0 |
303 | <h3>Add a new choice</h3> |
57c305c1 |
304 | |
add44c00 |
305 | <form action="poll" method="post"> |
57c305c1 |
306 | <input type="hidden" name="addChoice" value="<% id %>"> |
1fe415e0 |
307 | <table class="blanks"> |
308 | <tr> <td>Text:</td> <td><input name="descr"></td> </tr> |
309 | <tr> <td>Sequence#:</td> <td><input name="seq" value="<% Poll.nextSeq id %>"></td> </tr> |
57c305c1 |
310 | <tr> <td><input type="submit" value="Add"></td> </tr> |
311 | </table> |
312 | </form> |
313 | |
314 | <% end %> |
315 | <% | NONE => |
316 | if showNormal then %> |
317 | |
318 | <a href="poll?cmd=list">Show all polls</a><br> |
319 | |
1fe415e0 |
320 | <h3>Create a poll</h3> |
57c305c1 |
321 | |
add44c00 |
322 | <form action="poll" method="post"> |
57c305c1 |
323 | <input type="hidden" name="cmd" value="add"> |
1fe415e0 |
324 | <table class="blanks"> |
325 | <tr> <td>Title:</td> <td><input name="title"></td> </tr> |
326 | <tr> <td>Start date:</td> <td><input name="starts"></td> </tr> |
327 | <tr> <td>End date:</td> <td><input name="ends"></td> </tr> |
328 | <tr> <td>Max votes/person:</td> <td><input name="votes"></td> </tr> |
329 | <tr> <td>Description:</td> <td><textarea name="descr" wrap="soft" rows="5" cols="80"></textarea></td> </tr> |
57c305c1 |
330 | <tr> <td><input type="submit" value="Create"></td> </tr> |
331 | </table> |
332 | </form> |
333 | |
334 | <% end |
335 | end %> |
336 | |
337 | <% @footer[] %> |