Исходный код вики Poll application macros

Редактировал(а) Андрей Ганьков 2024/04/25 09:20

Скрыть последних авторов
Андрей Ганьков 1.1 1 {{include reference="Polls.Parameters"/}}
2
3 {{velocity output=false}}
4 #**
5 * Read poll data from the document. Running this macro
6 * will store the poll object in $pollObj, the poll type
7 * in $pollType, and poll options in $options.
8 *
9 * @param $pollDoc The document containing the poll
10 *#
11 #macro(poll_readPollData $pollDoc)
12 #set($pollObj = $pollDoc.getObject($pollClass))
13 #set($pollType = $pollObj.getProperty('type').value)
14 #poll_getOptions($pollDoc $options)
15 #end
16
17 #**
18 * Obtain the poll options ordered by their
19 * 'position' property
20 * @param $pollDoc The document containing the poll
21 * @param $options An array that will be populated
22 * with the instances of PollOptionClass
23 * existing in this document, ordered by their
24 * 'position' property
25 *#
26 #macro(poll_getOptions $pollDoc $options)
27 #set($rawOptions = $pollDoc.getObjects($pollOptionClass))
28 #set($resultOrdering = [])
29 #set($options = [])
30 #foreach($option in $rawOptions)
31 #set($discard = $resultOrdering.add({'object' : $option, 'position' : $option.getProperty('position').value}))
32 #end
33 #set($resultOrdering = $sorttool.sort($resultOrdering, ['position']))
34 #foreach($option in $resultOrdering)
35 #set($discard = $options.add($option.object))
36 #end
37 #if ($options.size() == 0)
38 #set($options = $rawOptions)
39 #end
40 #end
41
42 #**
43 * Generate the input id for a certain property
44 * of an object
45 *
46 * @param property
47 * @param xobject
48 *#
49 #macro(poll_generateInputID $property $xobject $cssclass)$!{xobject.xWikiClass.name}_$!{xobject.number}_$!{property} #end
50
51 #**
52 * Display the input for a certain property
53 * of an object.
54 * This intends to replace $object.display(),
55 * which FTM generates some very annoying markup.
56 *
57 * @param property
58 * @param xobject
59 *#
60 #macro(poll_input $property $xobject)
61 <input type="text" name="$!{xobject.xWikiClass.name}_$!{xobject.number}_$!{property}" value="$!{xobject.getProperty(${property}).value}"/>
62 #end
63 #**
64 * Display the label for a certain property
65 * of an object
66 *
67 * @param property
68 * @param xobject
69 *#
70 #macro(poll_label $property $xobject)
71 <label for="$!{xobject.xWikiClass.name}_$!{xobject.number}_$!{property}">$doc.displayPrettyName($property)</label>
72 #end
73
74 #**
75 * Display the label and the input for a certain property
76 * of an object, wrapped in a div element.
77 * This intends to replace $object.display(),
78 * which FTM generates some very annoying markup.
79 *
80 * @param property
81 * @param xobject
82 * @param cssclass
83 *#
84 #macro(poll_displayPropertyInForm $property $xobject $cssclass)
85 <div class="$!{cssclass}">
86 #label($property $xobject)
87 #input($property $xobject)
88 </div>
89 #end
90
91 #**
92 * Displays a tool that allows deleting an object
93 *
94 * @param theObj The object to delete
95 * @param text A custom text for the delete link
96 * @param tooltip A custom tooltip for the delete link
97 *
98 * DO NOT INDENT OR INSERT SPACES
99 *#
100 #macro(poll_objectDeleteTool $theObj $text $tooltip)#set($url = $doc.getURL("objectremove", "classname=${theObj.xWikiClass.name}&amp;classid=${theObj.number}&amp;xredirect=$escapetool.url(${doc.getURL($context.action)})"))<a class="tool delete" href="${url}" title="${tooltip}">$text</a>#end
101
102
103 #**
104 * Displays a tool that allows adding a new object
105 * of a certain xclass
106 *
107 * @param class The xclass to instantiate
108 * @param text A custom text for the delete link
109 *#
110 #macro(poll_objectAddTool $class $text)
111 #set($nextPosition = 1)
112 #foreach($object in $doc.getObjects($class))
113 #set($crtPosition = $object.getProperty('position').value)
114 #if ($crtPosition >= $nextPosition)
115 #set($nextPosition = $crtPosition + 1)
116 #end
117 #end
118 #set($nextId = $util.generateRandomString(6))
119 #set($url = $doc.getURL('objectadd', "classname=${class}&amp;${class}_id=${nextId}&amp;${class}_position=${nextPosition}&amp;xredirect=$escapetool.url(${doc.getURL($context.action)})"))
120 <a class="add" href="${url}">$text</a>
121 #end
122
123 #**
124 * Custom display of the poll options in the form
125 * according to the poll type (field 'type' of the
126 * poll object).
127 *
128 * - single choice => radio boxes
129 * - multiple choice => check boxes
130 * - weighted multiple choice => weight selectors
131 * - rating => radio box groups
132 * - ranking => reodering tool
133 *
134 * @param $poll The PollsClass instance giving the
135 * vote type
136 * @param $options An array with all the PollOptionClass
137 * instances for this poll
138 * @param $expressedVotes An array of the votes already
139 * given by the current user, if any; the elements
140 * of the array are instances of PollVoteClass
141 *#
142 #macro(poll_displayOptions $poll $options $expressedVotes)
143 #set($pollType = $poll.getProperty('type').value)
144 #set($maxOptions = $poll.getProperty('optionsPerVoter').value)
145 #if($pollType == 'rating' && ($maxOptions > $pollMaxRatingLevel || $maxOptions <= 0))
146 #set($maxOptions = $pollMaxRatingLevel)
147 #end
148 #if("$!{maxOptions}" == '')
149 #set($maxOptions = $options.size())
150 #end
151 #set($myVotes = {})
152 #foreach($voteObj in $expressedVotes)
153 #set($value = $voteObj.getProperty('value').value)
154 #if ("$!{value}" == '')
155 #set($value = 1)
156 #end
157 #set($discard = $myVotes.put($voteObj.getProperty('optionID').value, $value))
158 #end
159 #if ($pollType == 'multiple')
160 #poll_displayMultipleChoiceTool($options $maxOptions $myVotes)
161 #elseif ($pollType == 'weighted')
162 #poll_displayWeightedChoiceTool($options $maxOptions $myVotes)
163 #elseif ($pollType == 'rating')
164 #poll_displayRatingTool($options $maxOptions $myVotes)
165 #elseif ($pollType == 'ranking')
166 #poll_displayRankingTool($options $myVotes)
167 #else## includes ($pollType == 'single')
168 #poll_displaySingleChoiceTool($options $myVotes)
169 #end
170 #end
171
172 #**
173 * Display a single choice tool for the poll options:
174 * radiobuttons
175 *
176 * @param $options An array with all the PollOptionClass
177 * instances for this poll
178 * @param $myVotes An map {optionID -> voteValue} array of
179 * the votes already given by the current user, if any
180 *#
181 #macro(poll_displaySingleChoiceTool $options $myVotes)
182 <table summary="Poll options">
183 #foreach($option in $options)
184 <tr class="#if($velocityCount % 2 == 1)odd #else even #end">
185 <td><input type="radio" name="${pollVoteClass}_optionID" value="${option.id}" #if($myVotes.get($option.id)) checked="checked" #end/></td>
186 <td>$option.text</td>
187 </tr>
188 #end
189 </table>
190 #end
191
192 #**
193 * Display a multiple choice tool for the poll options:
194 * checkboxes
195 *
196 * @param $options An array with all the PollOptionClass
197 * instances for this poll
198 * @param maxChoices The maximum number of allowed choices
199 * @param $myVotes An map {optionID -> voteValue} array of
200 * the votes already given by the current user, if any
201 *#
202 #macro(poll_displayMultipleChoiceTool $options $maxChoices $myVotes)
203 <input type="hidden" id="poll-max-choices" value="${maxChoices}"/>
204 <table summary="Poll options">
205 #foreach($option in $options)
206 <tr class="#if($velocityCount % 2 == 1)odd #else even #end">
207 <td><input type="checkbox" name="${pollVoteClass}_optionID" value="${option.id}" #if($myVotes.get($option.id)) checked="checked" #end/></td>
208 <td>$option.text</td>
209 </tr>
210 #end
211 </table>
212 #end
213
214 #**
215 * Display a weighted choice tool for the poll options:
216 * select controls with values from 0 to 100
217 * (only for non-js browsing).
218 * These will be replaced in js with nice sliders.
219 *
220 * @param $options An array with all the PollOptionClass
221 * instances for this poll
222 * @param maxChoices The maximum number of allowed choices
223 * @param $myVotes An map {optionID -> voteValue} array of
224 * the votes already given by the current user, if any
225 *#
226 #macro(poll_displayWeightedChoiceTool $options $maxChoices $myVotes)
227 <input type="hidden" id="poll-max-choices" value="${maxChoices}"/>
228 <table summary="Poll options" class="poll-options-weighted">
229 #foreach($option in $options)
230 <tr class="poll-option-weighted #if($velocityCount % 2 == 1)odd #else even #end">
231 <td>$option.text</td>
232 <td><span class="poll-option-weight">
233 <select name="${pollVoteClass}_optionID_${option.id}">
234 #foreach($i in [0..100])
235 <option value="$i" #if("${myVotes.get($option.id)}" == "${i}") selected="selected" #end>$i</option>
236 #end
237 </select>%
238 </span></td>
239 </tr>
240 #end
241 </table>
242 #end
243
244 #**
245 * Display a rating tool for the poll options:
246 * radiobuttons for rating from 0 to max for
247 * each option
248 *
249 * @param $options An array with all the PollOptionClass
250 * instances for this poll
251 * @param maxLevel The number of rating levels
252 * (rating from 0 to max)
253 * @param $myVotes An map {optionID -> voteValue} array of
254 * the votes already given by the current user, if any
255 *#
256 #macro(poll_displayRatingTool $options $maxLevel $myVotes)
257 <table summary="Poll options">
258 #foreach($option in $options)
259 <tr class="poll-option #if($velocityCount % 2 == 1)odd #else even #end">
260 <td>$option.text</td>
261 <td>
262 #foreach($i in [0..$maxLevel])
263 <label><input type="radio" name="${pollVoteClass}_optionID_${option.id}" value="$i" #if(${i} == 0 || "${myVotes.get($option.id)}" == "${i}") checked="checked" #end/>$i</label>
264 #end
265 </td>
266 </tr>
267 #end
268 </table>
269 #end
270
271 #**
272 * Display a ranking tool for the poll options:
273 * allows the users to order the options according
274 * to their preference
275 *
276 * @param $options An array with all the PollOptionClass
277 * instances for this poll
278 * @param $myVotes An map {optionID -> voteValue} array of
279 * the votes already given by the current user, if any
280 *#
281 #macro(poll_displayRankingTool $options $myVotes)
282 #set($sep = ',')
283 ## Arrange the options according to the permutation given as a parameter
284 ## If the permutation is invalid, keep the original order
285 #poll_internal_RankingOrderFromRequest($options $sep $orderedOptions)
286 #if ($orderedOptions == $options)
287 #poll_internal_RankingOrderFromUserVotes($options $myVotes $orderedOptions)
288 #end
289 ## Do not rely on the $order array, it may be missing or wrong
290 #set($newOrder = [])
291 #foreach($option in $orderedOptions)
292 #set($discard = $newOrder.add($option.id))
293 #end
294 <div class="hidden"><input type="hidden" name="order" value="$escapetool.xml("#poll_internal_join($newOrder, $sep)")" id="ranking-order"/></div>
295 <ol id='poll-ranking-tool'>
296 #foreach($option in $orderedOptions)
297 <li id="ranking-order_$velocityCount" class="#if($velocityCount % 2 == 1)odd #else even #end">
298 <span class="reordering-tools tools">
299 #if($velocityCount != 1)
300 ## the same order as for the 'move down' link of the previous option
301 <a href="?order=$escapetool.url("#poll_internal_join($!{newOrder}, $sep)")" class="tool moveup" title="$msg.get('polls.vote.tools.moveup.tooltip')">$msg.get('polls.vote.tools.moveup')</a>
302 ## swap back, to obtain the initial order again; $i and $j were also set in the previous step of the loop
303 #poll_internal_swap($newOrder $i $j)
304 #else
305 <span class="tool moveup disabled">$msg.get('polls.vote.tools.moveup')</span>
306 #end
307 #if($velocityCount != $options.size())
308 #set($i = $velocityCount)
309 #set($j = $velocityCount - 1)
310 #poll_internal_swap($newOrder $i $j)
311 <a href="?order=$escapetool.url("#poll_internal_join($!{newOrder}, $sep)")" class="tool movedown" title="$msg.get('polls.vote.tools.movedown.tooltip')">$msg.get('polls.vote.tools.movedown')</a>
312 #else
313 <span class="tool movedown disabled">$msg.get('polls.vote.tools.movedown')</span>
314 #end
315 </span>
316 <input type="hidden" value="${option.id}"/>
317 $option.text
318 </li>
319 #end
320 </ol>
321 #end
322 #**
323 * Internal: swap two elements in an array
324 *
325 * @param array
326 * @param position of the first element
327 * @param position of the second element
328 *#
329 #macro(poll_internal_swap $array $i $j)
330 ## only used internally; don't waste time checking
331 ## if $i and $j are lower than $array.size()
332 #set($tmp = $array.get($i))
333 #set($discard = $array.set($i, $array.get($j)))
334 #set($discard = $array.set($j, $tmp))
335 #end
336
337 #**
338 * Internal: display all elements in an array,
339 * separated by a certain separator
340 *
341 * @param array
342 * @param separator
343 *
344 * DO NOT INDENT OR INTRODUCE SPACES
345 *#
346 #macro(poll_internal_join $array $separator)#foreach($elt in $array)#if($velocityCount>1)${separator}#end${elt}#end#end
347 #**
348 * Internal: read and apply ranking from request parameter
349 *
350 * @param $options The array of options (instances of PollOptionClass)
351 * being ranked
352 * @param $separator The character separating the ordered option IDs
353 * in the request parameter value
354 * @param $orderedOptions Result: array of ordered options
355 *#
356 #macro(poll_internal_RankingOrderFromRequest $options $separator $orderedOptions)
357 #set($order = "$!{request.order}")
358 #set($order = $order.split($separator))
359 #poll_internal_RankingOrderFromPermutation($options $order $orderedOptions)
360 #end
361
362 #**
363 * Internal: read and apply ranking from user votes
364 *
365 * @param $options The array of options (instances of PollOptionClass)
366 * being ranked
367 * @param $userVotes A map {optionID -> positions} containing the current
368 * user votes
369 * @param $orderedOptions Result: array of ordered options
370 *#
371 #macro(poll_internal_RankingOrderFromUserVotes $options $userVotes $orderedOptions)
372 #set($resultOrdering = [])
373 #set($order = [])
374 #foreach($votedOption in $userVotes.keySet())
375 #set($discard = $resultOrdering.add({'id' : $votedOption, 'position' : $userVotes.get($votedOption)}))
376 #end
377 #set($resultOrdering = $sorttool.sort($resultOrdering, ['position']))
378 #foreach($optionID in $resultOrdering)
379 #set($discard = $order.add($optionID.id))
380 #end
381 #poll_internal_RankingOrderFromPermutation($options $order $orderedOptions)
382 #end
383
384 #**
385 * Internal: apply ranking from and option id permutation
386 *
387 * @param $options The array of options (instances of PollOptionClass)
388 * being ranked
389 * @param $permutation An array containing the ordered option ids
390 * @param $orderedOptions Result: array of ordered options
391 *#
392 #macro(poll_internal_RankingOrderFromPermutation $options $permutation $orderedOptions)
393 ## Arrange the options according to the permutation given as a parameter
394 ## If the permutation is invalid, keep the original order
395 #if($order.size() != $options.size())
396 #set($orderedOptions = $options)
397 #else
398 #set($optionMap = {})
399 #set($orderedOptions = [])
400 #foreach($option in $options)
401 #set($discard = $optionMap.put($option.id, $option))
402 #end
403 #foreach($elt in $order)
404 #set($next = $optionMap.get("${elt}"))
405 #if ("$!{next}" == '')
406 #set($orderedOptions = $options)
407 #break
408 #else
409 #set($discard = $orderedOptions.add($next))
410 #end
411 #end
412 #end
413 #end
414
415 #*---------------------------------------------**
416 Vote macros
417 **---------------------------------------------*#
418 #**
419 * Processes the vote for single choice polls.
420 *
421 *#
422 #macro(poll_voteSingle)
423 #set($voteOption = "$!{request.getParameter($pollVoteClass.concat('_optionID'))}")
424 #if(!$doc.getObject($pollOptionClass, 'id', $voteOption, false))
425
426
427 {{error}}$msg.get('polls.vote.error.single.noneSelected'){{/error}}
428
429 #else
430 #set($voteObject = $doc.getObject($pollVoteClass, 'voter', $context.user, false))
431 #if(!$voteObject)
432 #set($voteObject = $doc.newObject($pollVoteClass))
433 #end
434 #set($discard = $voteObject.set('voter', $context.user))
435 #set($discard = $voteObject.set('optionID', $voteOption))
436 #set($discard = $voteObject.set('value', 1))
437 $doc.save($msg.get('polls.versionSummary.userVoted', [$xwiki.getUserName($context.user, false)]), true)
438 $response.sendRedirect($doc.getURL())
439 #stop
440 #end
441 #end
442
443 #**
444 * Processes the vote for multiple choice polls.
445 *
446 * @param $maxChoices The maximum number of allowed choices.
447 *#
448 #macro(poll_voteMultiple $maxChoices)
449 #set($voteOptions = $!{request.getParameterValues($pollVoteClass.concat('_optionID'))})
450 #set($validOptions = [])
451 #foreach ($voteOption in $voteOptions)
452 #if($doc.getObject($pollOptionClass, 'id', $voteOption, false))
453 #set($discard = $validOptions.add($voteOption))
454 #end
455 #end
456 #if ($validOptions.size() == 0 || $validOptions.size() > $maxChoices)
457
458
459 {{error}}$msg.get('polls.vote.error.multiple.wrongSelectedNumber', [${maxChoices}]){{/error}}
460
461
462 #else
463 #foreach($vote in $doc.getObjects($pollVoteClass, 'voter', $context.user))
464 #set($discard = $doc.removeObject($vote))
465 #end
466 #foreach($voteOption in $validOptions)
467 #set($voteObject = $doc.newObject($pollVoteClass))
468 #set($discard = $voteObject.set('voter', $context.user))
469 #set($discard = $voteObject.set('optionID', $voteOption))
470 #set($discard = $voteObject.set('value', 1))
471 #end
472 $doc.save($msg.get('polls.versionSummary.userVoted', [$xwiki.getUserName($context.user, false)]), true)
473 $response.sendRedirect($doc.getURL())
474 #stop
475 #end
476 #end
477
478 #**
479 * Processes the vote for weighted multiple choice polls.
480 *
481 * @param $maxChoices The maximum number of allowed choices.
482 * @param $options The options of this poll - an array of
483 * PollOptionClass instances
484 *#
485 #macro(poll_voteWeighted $maxChoices $options)
486 #set($optionWeights = {})
487 #set($totalWeight = 0)
488 #set($expressedChoices = 0)
489 #foreach ($option in $options)
490 #set($optionWeight = $mathtool.toInteger("$!{request.getParameter($pollVoteClass.concat('_optionID_').concat($option.id))}"))
491 #set($totalWeight = $totalWeight + $optionWeight)
492 #if ($optionWeight > 0)
493 #set($discard = $optionWeights.put($option.id, $optionWeight))
494 #set($expressedChoices = $expressedChoices + 1)
495 #end
496 #end
497 #if ($expressedChoices > $maxChoices)
498
499
500
501 {{error}}$msg.get('polls.vote.error.multiple.wrongSelectedNumber', [${maxChoices}]){{/error}}
502
503 #elseif($totalWeight != 100)
504
505
506 {{error}}$msg.get('polls.vote.error.multiple.wrongSelectedNumber', [${totalWeight}]){{/error}}
507
508 #else
509 #foreach($vote in $doc.getObjects($pollVoteClass, 'voter', $context.user))
510 #set($discard = $doc.removeObject($vote))
511 #end
512 #foreach($voteOption in $optionWeights.keySet())
513 #set($voteObject = $doc.newObject($pollVoteClass))
514 #set($discard = $voteObject.set('voter', $context.user))
515 #set($discard = $voteObject.set('optionID', $voteOption))
516 #set($discard = $voteObject.set('value', $optionWeights.get($voteOption)))
517 #end
518 $doc.save($msg.get('polls.versionSummary.userVoted', [$xwiki.getUserName($context.user, false)]), true)
519 $response.sendRedirect($doc.getURL())
520 #stop
521 #end
522 #end
523
524
525 #**
526 * Processes the vote for rating polls.
527 *
528 * @param maxLevel The maximum rating level. Ratings should
529 * range between 0 and maxLevel
530 * @param $options The options of this poll - an array of
531 * PollOptionClass instances
532 *#
533 #macro(poll_voteRating $maxLevel $options)
534 #set($optionRatings = {})
535 #set($errorMessage = '')
536 #foreach ($option in $options)
537 #set($optionRating = "$!{request.getParameter($pollVoteClass.concat('_optionID_').concat($option.id))}")
538 #if ($optionRating == '')
539 #set($errorMessage = $msg.get('polls.vote.error.rating.optionMissing', [${option.position}]))
540 #break
541 #else
542 #set($optionRating = $mathtool.toInteger($optionRating))
543 #if ($optionRating < 0 || $optionRating > $maxLevel)
544 #set($errorMessage = $msg.get('polls.vote.error.rating.ratingOutOfRange', [${option.position}]))
545 #break
546 #else
547 #set($discard = $optionRatings.put($option.id, $optionRating))
548 #end
549 #end
550 #end
551 #if ($errorMessage != '')
552
553
554 {{error}}$errorMessage{{/error}}
555
556 #else
557 #foreach($vote in $doc.getObjects($pollVoteClass, 'voter', $context.user))
558 #set($newRating = $optionRatings.get(${vote.getProperty('optionID').value}))
559 #if ("$!{newRating}" == '')
560 #set($discard = $doc.removeObject($vote))
561 #else
562 #set($discard = $vote.set('value', $optionRatings.get(${vote.getProperty('optionID').value})))
563 #set($discard = $optionRatings.remove(${vote.getProperty('optionID').value}))
564 #end
565 #end
566 #foreach($voteOption in $optionRatings.keySet())
567 #set($voteObject = $doc.newObject($pollVoteClass))
568 #set($discard = $voteObject.set('voter', $context.user))
569 #set($discard = $voteObject.set('optionID', $voteOption))
570 #set($discard = $voteObject.set('value', $optionRatings.get($voteOption)))
571 #end
572 $doc.save($msg.get('polls.versionSummary.userVoted', [$xwiki.getUserName($context.user, false)]), true)
573 $response.sendRedirect($doc.getURL())
574 #stop
575 #end
576 #end
577
578
579 #**
580 * Processes the vote for ranking polls.
581 *
582 * @param $options The options of this poll - an array of
583 * PollOptionClass instances
584 *#
585 #macro(poll_voteRanking $options)
586 ## Arrange the options according to the permutation given as a parameter
587 #set($errorMessage = '')
588 #set($order = "$!{request.order}")
589 #set($sep = ',')
590 #set($order = $order.split($sep))
591 #if($order.size() != $options.size())
592 #set($errorMessage = "Invalid ordering, wrong number of elements: ${order.size()} instead of ${options.size()}.")
593 #else
594 #set($optionMap = {})
595 #set($sortedOptions = {})
596 #foreach($option in $options)
597 #set($discard = $optionMap.put($option.id, $option))
598 #end
599 #foreach($elt in $order)
600 #set($next = $optionMap.get("$!{elt}"))
601 #if ("$!{next}" == '')
602 #set($errorMessage = $msg.get('polls.vote.error.ranking.unknownElement', [${elt}]))
603 #break
604 #elseif($sortedOptions.containsKey($elt))
605 #set($errorMessage = $msg.get('polls.vote.error.ranking.duplicateElement', [${elt}]))
606 #break
607 #else
608 #set($discard = $sortedOptions.put($elt, $velocityCount))
609 #end
610 #end
611 #end
612 #if ($errorMessage != '')
613
614
615 {{error}}$errorMessage{{/error}}
616
617 #else
618 #foreach($vote in $doc.getObjects($pollVoteClass, 'voter', $context.user))
619 #set($newPosition = $sortedOptions.get(${vote.getProperty('optionID').value}))
620 #if ("$!{newPosition}" == '')
621 #set($discard = $doc.removeObject($vote))
622 #else
623 #set($discard = $vote.set('value', $sortedOptions.get(${vote.getProperty('optionID').value})))
624 #set($discard = $sortedOptions.remove(${vote.getProperty('optionID').value}))
625 #end
626 #end
627 #foreach($voteOption in $sortedOptions.keySet())
628 #set($voteObject = $doc.newObject($pollVoteClass))
629 #set($discard = $voteObject.set('voter', $context.user))
630 #set($discard = $voteObject.set('optionID', $voteOption))
631 #set($discard = $voteObject.set('value', $sortedOptions.get($voteOption)))
632 #end
633 $doc.save($msg.get('polls.versionSummary.userVoted', [$xwiki.getUserName($context.user, false)]), true)
634 $response.sendRedirect($doc.getURL())
635 #stop
636 #end
637 #end
638
639 #**
640 * Display poll results
641 *
642 * @param poll
643 * @param type
644 * @param options
645 * @param votes
646 * @param showtable
647 * @param showchart
648 *#
649 #macro(poll_results $poll $type $options $votes $showtable $showchart)
650 #if ($votes.size() > 0)
651 #set($allVoters = {})
652 #foreach($vote in $votes)
653 #set($discard = $allVoters.put($vote.getProperty('voter').value, 1))
654 #end
655 <div class="box poll-participants">$msg.get('polls.vote.results.participants', [$allVoters.size()])</div>
656 #if ($type == 'rating' || $type == 'ranking')
657 #poll_resultsPerValue($poll $type $options $votes $showtable $showchart)
658 #else
659 #poll_resultsCounts($poll $type $options $votes $showtable $showchart)
660 #end
661 #end
662 #end
663
664 #**
665 * Display poll results for rating and ranking
666 *
667 * @param poll
668 * @param type
669 * @param options
670 * @param votes
671 * @param showtable
672 * @param showchart
673 *#
674 #macro(poll_resultsPerValue $poll $type $options $votes $showtable $showchart)
675 #if ($type == 'rating')
676 #set($minLevel = 0)
677 #set($maxLevel = $poll.getProperty('optionsPerVoter').value)
678 #if($maxLevel > $pollMaxRatingLevel || $maxLevel <= 0)
679 #set($maxLevel = $pollMaxRatingLevel)
680 #end
681 #else## ranking
682 #set($minLevel = 1)
683 #set($maxLevel = $options.size())
684 #end
685 #set($voteCounts = {})
686 #set($voteResults = {})
687 #foreach($option in $options)
688 #set($discard = $voteCounts.put($option.id, {}))
689 #foreach($i in [${minLevel}..${maxLevel}])
690 #set($discard = $voteCounts.get($option.id).put($i, 0))
691 #end
692 #set($discard = $voteResults.put($option.id, 0))
693 #end
694 #foreach($voteObj in $votes)
695 #set($key = $voteObj.getProperty('optionID').value)
696 #set($value = $voteObj.getProperty('value').value)
697 #set($row = $voteCounts.get($key))
698 #set($discard = $row.put($value, $mathtool.add($row.get($value), 1)))
699 #end
700 #foreach($option in $options)
701 #set($key = $option.id)
702 #set($sum = 0)
703 #set($row = $voteCounts.get($key))
704 #foreach($i in [${minLevel}..${maxLevel}])
705 #set($discard = $voteResults.put($key, $mathtool.add($voteResults.get($key), $mathtool.mul($i, $row.get($i)))))
706 #set($sum = $sum + $row.get($i))
707 #end
708 #set($discard = $voteResults.put($key, $mathtool.div($voteResults.get($key), $sum)))
709 #end
710
711 ## Must obtain an actual order
712 #set($resultRanking = [])
713 #set($optionsMap = {})
714 #foreach($option in $options)
715 #set($discard = $resultRanking.add({'text' : $option.getProperty('text').value, 'id' : $option.getProperty('id').value, 'voteValue' : $voteResults.get($option.getProperty('id').value).doubleValue()}))
716 #set($discard = $optionsMap.put($option.id, $option.getProperty('text').value))
717 #end
718 #if($type == 'ranking')
719 #set($sortBy = ['voteValue', 'text'])
720 #else
721 #set($sortBy = ['voteValue:desc', 'text:asc'])
722 #end
723 #set($resultRanking = $sorttool.sort($resultRanking, $sortBy))
724 ## display the ordered options:
725 <ol class="poll-ranking-order">
726 #foreach($option in $resultRanking)
727 <li>$optionsMap.get($option.id) <span class="details">($!mathtool.roundTo(2, ${option.voteValue}))</span></li>
728 #end
729 </ol>
730
731 #if ($showchart)
732 #set($pollDocument = $xwiki.getDocument($poll.getName()))
733 #set($column = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
734 #set($span = $maxLevel - $minLevel + 1)
735 #set($firstCharIndex = $span % $column.length())
736 #set($secondCharIndex = $span / $column.length() - 1)
737 #set($columnIdentifier = $column.charAt($firstCharIndex))
738 #if($secondCharIndex >= 0)
739 #if($secondCharIndex < $column.length())
740 #set($columnIdentifier = "${column.charAt(${secondCharIndex})}${columnIdentifier}")
741 #else
742 #set($columnIdentifier = 'ZZ')
743
744
745 {{warning}}$msg.get('polls.vote.results.chart.columnsNumberWarning', [701]){{/warning}}
746
747 #end
748 #end
749 {{chart source="inline" type="bar" params="range:B2-${columnIdentifier}${mathtool.add($options.size(), 1)};series:columns;" title="$pollDocument.getDisplayTitle().replaceAll('"', '')"}}
750 | #foreach($i in [${minLevel}..${maxLevel}])|$i#end
751
752 #foreach($option in $options)
753 #set($row = $voteCounts.get($option.id))
754 |${option.getProperty('text').value.replaceAll('\r?\n|\r', ' ').trim().replaceAll('[!|]', '~$0')}#foreach($i in [${minLevel}..${maxLevel}])|$row.get(${i})#end
755
756 #end
757 {{/chart}}
758 #end
759
760 #if($showtable)
761 <table class="poll-results">
762 <tr>
763 <th>$msg.get('polls.vote.results.table.option')</th>
764 #foreach($i in [${minLevel}..${maxLevel}])
765 <th>${i}</th>
766 #end
767 <th>$msg.get('polls.vote.results.table.average')</th>
768 </tr>
769 #foreach($option in $options)
770 #set($row = $voteCounts.get($option.id))
771 <tr>
772 <td>$option.text</td>
773 #foreach($i in [${minLevel}..${maxLevel}])
774 <td>$row.get(${i})</td>
775 #end
776 <td>$!mathtool.roundTo(2, $voteResults.get($option.id))</td>
777 </tr>
778 #end
779 </table>
780 #end## show table
781 #end
782
783
784 #**
785 * Display poll results for single, multiple and
786 * weighted multiple choice
787 *
788 * @param poll
789 * @param type
790 * @param options
791 * @param votes
792 * @param showtable
793 * @param showchart
794 *#
795 #macro(poll_resultsCounts $poll $type $options $votes $showtable $showchart)
796 #set($voteValues = {})
797 #set($voteCounts = {})
798 #set($voteVoters = {})
799 #set($voters = {})
800 #foreach($option in $options)
801 #set($discard = $voteValues.put($option.id, 0))
802 #set($discard = $voteCounts.put($option.id, 0))
803 #set($discard = $voteVoters.put($option.id, []))
804 #end
805 #foreach($voteObj in $votes)
806 #set($key = $voteObj.getProperty('optionID').value)
807 #if($type == 'weighted')
808 #set($value = $mathtool.div($voteObj.value, 100.0))
809 #else
810 #set($value = 1)
811 #end
812 #set($discard = $voteValues.put($key, $mathtool.add($voteValues.get($key), $value)))
813 #set($discard = $voteCounts.put($key, $mathtool.add($voteCounts.get($key), 1)))
814 #set($discard = $voteVoters.get($key).add($voteObj.voter))
815 #set($discard = $voters.put($voteObj.voter, 1))
816 #end
817 #if($showchart)
818 #set($pollDocument = $xwiki.getDocument($poll.getName()))
819 {{chart source="inline" type="bar" params="range:B2-B${mathtool.add($options.size(), 1)};series:columns;" title="$pollDocument.getDisplayTitle().replaceAll('"', '')"}}
820 #if($type == 'single' || $type == 'multiple')
821 | |$msg.get('polls.vote.results.chart.voteCount')
822 #foreach($option in $options)
823 |${option.getProperty('text').value.replaceAll('\r?\n|\r', ' ').trim().replaceAll('[!|]', '~$0')}|$voteCounts.get($option.id)
824 #end
825 #elseif($type == 'weighted')
826 | |$msg.get('polls.vote.results.chart.percentage')
827 #foreach($option in $options)
828 |${option.getProperty('text').value.replaceAll('\r?\n|\r', ' ').trim()}|$mathtool.div($mathtool.mul($voteValues.get($option.id), 100.0), $voters.size())
829 #end
830 #end
831 {{/chart}}
832
833 #end## show chart
834 #if ($showtable)
835 <table class="poll-results">
836 <tr><th>$msg.get('polls.vote.results.table.option')</th><th>$msg.get('polls.vote.results.table.percentage')</th>#if($type == 'multiple')<th>$msg.get('polls.vote.results.table.percentageVoters')</th>#end<th>$msg.get('polls.vote.results.table.voteCount')</th><th>$msg.get('polls.vote.results.table.voters')</th></tr>
837 #foreach($option in $options)
838 <tr>
839 <td>$option.text</td>
840 #if ($type == 'multiple')
841 <td>#if($votes.size() > 0)
842 #set($percentage = $!{mathtool.roundTo(2, $mathtool.div($mathtool.mul($!{voteValues.get($option.id)}, 100.0), $votes.size()))})
843 ${percentage}%
844 #end</td>
845 #end
846 <td>#if($voters.size() > 0)
847 #set($percentage = $!{mathtool.roundTo(2, $mathtool.div($mathtool.mul($!{voteValues.get($option.id)}, 100.0), $voters.size()))})
848 ${percentage}%
849 #end</td>
850 <td>$voteCounts.get($option.id)</td>
851 <td>
852 #foreach($voter in $voteVoters.get($option.id)) $voter #end
853 </td>
854 </tr>
855 #end
856 </table>
857 #end## show table
858 #end
859 {{/velocity}}