| rev | line source | 
| bsw/jbe@19 | 1 local issue = Issue:by_id(param.get("issue_id"), atom.integer) | 
| bsw/jbe@19 | 2 | 
| bsw/jbe@19 | 3 local member_id = param.get("member_id", atom.integer) | 
| bsw/jbe@19 | 4 local member | 
| bsw/jbe@19 | 5 | 
| bsw/jbe@19 | 6 local readonly = false | 
| poelzi@156 | 7 | 
| bsw/jbe@19 | 8 if member_id then | 
| bsw/jbe@19 | 9   if not issue.closed then | 
| bsw/jbe@19 | 10     error("access denied") | 
| bsw/jbe@19 | 11   end | 
| bsw/jbe@19 | 12   member = Member:by_id(member_id) | 
| bsw/jbe@19 | 13   readonly = true | 
| bsw/jbe@19 | 14 end | 
| bsw/jbe@19 | 15 | 
| poelzi@138 | 16 if issue.closed then | 
| poelzi@156 | 17   if not member then | 
| poelzi@156 | 18     slot.put_into("error", _"This issue is already closed.") | 
| poelzi@156 | 19   end | 
| poelzi@158 | 20   if not member then | 
| poelzi@158 | 21     member = app.session.member | 
| poelzi@158 | 22   end | 
| poelzi@156 | 23   readonly = true | 
| poelzi@138 | 24 end | 
| poelzi@138 | 25 | 
| bsw/jbe@19 | 26 if member then | 
| poelzi@156 | 27   local str = _("Ballot of '#{member_name}' for issue ##{issue_id}", | 
| poelzi@156 | 28                   {member_name = string.format('<a href="%s">%s</a>', | 
| poelzi@156 | 29                                           encode.url{ | 
| poelzi@156 | 30                                             module    = "member", | 
| poelzi@156 | 31                                             view      = "show", | 
| poelzi@156 | 32                                             id        = member.id, | 
| poelzi@156 | 33                                           }, | 
| poelzi@156 | 34                                           encode.html(member.name)), | 
| poelzi@156 | 35                    issue_id = string.format('<a href="%s">%s</a>', | 
| poelzi@156 | 36                                           encode.url{ | 
| poelzi@156 | 37                                             module    = "issue", | 
| poelzi@156 | 38                                             view      = "show", | 
| poelzi@156 | 39                                             id        = issue.id, | 
| poelzi@156 | 40                                           }, | 
| poelzi@156 | 41                                           encode.html(tostring(issue.id))) | 
| poelzi@156 | 42                   } | 
| poelzi@156 | 43               ) | 
| bsw@604 | 44   ui.title(str) | 
| bsw/jbe@19 | 45 else | 
| bsw/jbe@19 | 46   member = app.session.member | 
| bsw@604 | 47   ui.title(_"Voting") | 
| bsw/jbe@19 | 48 | 
| bsw@604 | 49   ui.actions(function() | 
| bsw/jbe@19 | 50     ui.link{ | 
| bsw@604 | 51       text = _"Cancel", | 
| bsw/jbe@19 | 52       module = "issue", | 
| bsw/jbe@19 | 53       view = "show", | 
| bsw/jbe@19 | 54       id = issue.id | 
| bsw/jbe@19 | 55     } | 
| bsw@604 | 56     slot.put(" · ") | 
| bsw@26 | 57     ui.link{ | 
| bsw@86 | 58       text = _"Discard voting", | 
| bsw@26 | 59       module = "vote", | 
| bsw@26 | 60       action = "update", | 
| bsw@26 | 61       params = { | 
| bsw@26 | 62         issue_id = issue.id, | 
| bsw@26 | 63         discard = true | 
| bsw@26 | 64       }, | 
| bsw@26 | 65       routing = { | 
| bsw@26 | 66         default = { | 
| bsw@26 | 67           mode = "redirect", | 
| bsw@26 | 68           module = "issue", | 
| bsw@26 | 69           view = "show", | 
| bsw@26 | 70           id = issue.id | 
| bsw@26 | 71         } | 
| bsw@26 | 72       } | 
| bsw@26 | 73     } | 
| bsw/jbe@19 | 74   end) | 
| bsw/jbe@19 | 75 end | 
| bsw/jbe@19 | 76 | 
| bsw/jbe@19 | 77 | 
| bsw/jbe@19 | 78 local tempvoting_string = param.get("scoring") | 
| bsw/jbe@19 | 79 | 
| bsw/jbe@19 | 80 local tempvotings = {} | 
| bsw/jbe@19 | 81 if tempvoting_string then | 
| bsw/jbe@19 | 82   for match in tempvoting_string:gmatch("([^;]+)") do | 
| bsw/jbe@19 | 83     for initiative_id, grade in match:gmatch("([^:;]+):([^:;]+)") do | 
| bsw/jbe@19 | 84       tempvotings[tonumber(initiative_id)] = tonumber(grade) | 
| bsw/jbe@19 | 85     end | 
| bsw/jbe@5 | 86   end | 
| bsw/jbe@19 | 87 end | 
| bsw/jbe@5 | 88 | 
| bsw@95 | 89 local initiatives = issue:get_reference_selector("initiatives"):add_where("initiative.admitted"):add_order_by("initiative.satisfied_supporter_count DESC"):exec() | 
| bsw/jbe@5 | 90 | 
| bsw/jbe@5 | 91 local min_grade = -1; | 
| bsw/jbe@5 | 92 local max_grade = 1; | 
| bsw/jbe@5 | 93 | 
| bsw/jbe@5 | 94 for i, initiative in ipairs(initiatives) do | 
| bsw/jbe@5 | 95   -- TODO performance | 
| bsw/jbe@19 | 96   initiative.vote = Vote:by_pk(initiative.id, member.id) | 
| bsw/jbe@19 | 97   if tempvotings[initiative.id] then | 
| bsw/jbe@19 | 98     initiative.vote = {} | 
| bsw/jbe@19 | 99     initiative.vote.grade = tempvotings[initiative.id] | 
| bsw/jbe@19 | 100   end | 
| bsw/jbe@5 | 101   if initiative.vote then | 
| bsw/jbe@5 | 102     if initiative.vote.grade > max_grade then | 
| bsw/jbe@5 | 103       max_grade = initiative.vote.grade | 
| bsw/jbe@5 | 104     end | 
| bsw/jbe@5 | 105     if initiative.vote.grade < min_grade then | 
| bsw/jbe@5 | 106       min_grade = initiative.vote.grade | 
| bsw/jbe@5 | 107     end | 
| bsw/jbe@5 | 108   end | 
| bsw/jbe@5 | 109 end | 
| bsw/jbe@5 | 110 | 
| bsw/jbe@5 | 111 local sections = {} | 
| bsw/jbe@5 | 112 for i = min_grade, max_grade do | 
| bsw/jbe@5 | 113   sections[i] = {} | 
| bsw/jbe@5 | 114   for j, initiative in ipairs(initiatives) do | 
| bsw/jbe@5 | 115     if (initiative.vote and initiative.vote.grade == i) or (not initiative.vote and i == 0) then | 
| bsw/jbe@5 | 116       sections[i][#(sections[i])+1] = initiative | 
| bsw/jbe@5 | 117     end | 
| bsw/jbe@5 | 118   end | 
| bsw/jbe@5 | 119 end | 
| bsw/jbe@5 | 120 | 
| bsw/jbe@19 | 121 local approval_count, disapproval_count = 0, 0 | 
| bsw/jbe@19 | 122 for i = min_grade, -1 do | 
| bsw/jbe@19 | 123   if #sections[i] > 0 then | 
| bsw/jbe@19 | 124     disapproval_count = disapproval_count + 1 | 
| bsw/jbe@19 | 125   end | 
| bsw/jbe@19 | 126 end | 
| bsw/jbe@19 | 127 local approval_count = 0 | 
| bsw/jbe@19 | 128 for i = 1, max_grade do | 
| bsw/jbe@19 | 129   if #sections[i] > 0 then | 
| bsw/jbe@19 | 130     approval_count = approval_count + 1 | 
| bsw/jbe@19 | 131   end | 
| bsw/jbe@19 | 132 end | 
| bsw/jbe@5 | 133 | 
| bsw/jbe@5 | 134 | 
| bsw/jbe@5 | 135 | 
| bsw/jbe@19 | 136 if not readonly then | 
| bsw/jbe@19 | 137   util.help("vote.list", _"Voting") | 
| bsw/jbe@19 | 138   slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/dragdrop.js"></script>') | 
| bsw/jbe@19 | 139   slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/voting.js"></script>') | 
| bsw/jbe@19 | 140 end | 
| bsw/jbe@19 | 141 | 
| bsw/jbe@19 | 142 ui.script{ | 
| bsw/jbe@19 | 143   script = function() | 
| bsw/jbe@19 | 144     slot.put( | 
| bsw/jbe@19 | 145       "voting_text_approval_single               = ", encode.json(_"Approval [single entry]"), ";\n", | 
| bsw/jbe@19 | 146       "voting_text_approval_multi                = ", encode.json(_"Approval [many entries]"), ";\n", | 
| bsw/jbe@19 | 147       "voting_text_first_preference_single       = ", encode.json(_"Approval (first preference) [single entry]"), ";\n", | 
| bsw/jbe@19 | 148       "voting_text_first_preference_multi        = ", encode.json(_"Approval (first preference) [many entries]"), ";\n", | 
| bsw/jbe@19 | 149       "voting_text_second_preference_single      = ", encode.json(_"Approval (second preference) [single entry]"), ";\n", | 
| bsw/jbe@19 | 150       "voting_text_second_preference_multi       = ", encode.json(_"Approval (second preference) [many entries]"), ";\n", | 
| bsw/jbe@19 | 151       "voting_text_third_preference_single       = ", encode.json(_"Approval (third preference) [single entry]"), ";\n", | 
| bsw/jbe@19 | 152       "voting_text_third_preference_multi        = ", encode.json(_"Approval (third preference) [many entries]"), ";\n", | 
| bsw/jbe@19 | 153       "voting_text_numeric_preference_single     = ", encode.json(_"Approval (#th preference) [single entry]"), ";\n", | 
| bsw/jbe@19 | 154       "voting_text_numeric_preference_multi      = ", encode.json(_"Approval (#th preference) [many entries]"), ";\n", | 
| bsw/jbe@19 | 155       "voting_text_abstention_single             = ", encode.json(_"Abstention [single entry]"), ";\n", | 
| bsw/jbe@19 | 156       "voting_text_abstention_multi              = ", encode.json(_"Abstention [many entries]"), ";\n", | 
| bsw/jbe@19 | 157       "voting_text_disapproval_above_one_single  = ", encode.json(_"Disapproval (prefer to lower block) [single entry]"), ";\n", | 
| bsw/jbe@19 | 158       "voting_text_disapproval_above_one_multi   = ", encode.json(_"Disapproval (prefer to lower block) [many entries]"), ";\n", | 
| bsw/jbe@19 | 159       "voting_text_disapproval_above_many_single = ", encode.json(_"Disapproval (prefer to lower blocks) [single entry]"), ";\n", | 
| bsw/jbe@19 | 160       "voting_text_disapproval_above_many_multi  = ", encode.json(_"Disapproval (prefer to lower blocks) [many entries]"), ";\n", | 
| bsw/jbe@19 | 161       "voting_text_disapproval_above_last_single = ", encode.json(_"Disapproval (prefer to last block) [single entry]"), ";\n", | 
| bsw/jbe@19 | 162       "voting_text_disapproval_above_last_multi  = ", encode.json(_"Disapproval (prefer to last block) [many entries]"), ";\n", | 
| bsw/jbe@19 | 163       "voting_text_disapproval_single            = ", encode.json(_"Disapproval [single entry]"), ";\n", | 
| bsw/jbe@19 | 164       "voting_text_disapproval_multi             = ", encode.json(_"Disapproval [many entries]"), ";\n" | 
| bsw/jbe@19 | 165     ) | 
| bsw/jbe@19 | 166   end | 
| bsw/jbe@19 | 167 } | 
| bsw/jbe@5 | 168 | 
| bsw/jbe@5 | 169 ui.form{ | 
| bsw/jbe@19 | 170   attr = { | 
| bsw/jbe@19 | 171     id = "voting_form", | 
| bsw/jbe@19 | 172     class = readonly and "voting_form_readonly" or "voting_form_active" | 
| bsw/jbe@19 | 173   }, | 
| bsw/jbe@5 | 174   module = "vote", | 
| bsw/jbe@5 | 175   action = "update", | 
| bsw/jbe@5 | 176   params = { issue_id = issue.id }, | 
| bsw/jbe@5 | 177   routing = { | 
| bsw/jbe@5 | 178     default = { | 
| bsw/jbe@5 | 179       mode = "redirect", | 
| bsw/jbe@5 | 180       module = "issue", | 
| bsw/jbe@5 | 181       view = "show", | 
| bsw/jbe@5 | 182       id = issue.id | 
| bsw/jbe@5 | 183     } | 
| bsw/jbe@5 | 184   }, | 
| bsw/jbe@5 | 185   content = function() | 
| bsw/jbe@19 | 186     if not readonly then | 
| bsw/jbe@19 | 187       local scoring = param.get("scoring") | 
| bsw/jbe@19 | 188       if not scoring then | 
| bsw/jbe@19 | 189         for i, initiative in ipairs(initiatives) do | 
| bsw/jbe@19 | 190           local vote = initiative.vote | 
| bsw/jbe@19 | 191           if vote then | 
| bsw/jbe@19 | 192             tempvotings[initiative.id] = vote.grade | 
| bsw@522 | 193           else | 
| bsw@522 | 194             tempvotings[initiative.id] = 0 | 
| bsw/jbe@19 | 195           end | 
| bsw/jbe@19 | 196         end | 
| bsw/jbe@19 | 197         local tempvotings_list = {} | 
| bsw/jbe@19 | 198         for key, val in pairs(tempvotings) do | 
| bsw/jbe@19 | 199           tempvotings_list[#tempvotings_list+1] = tostring(key) .. ":" .. tostring(val) | 
| bsw/jbe@19 | 200         end | 
| bsw/jbe@19 | 201         if #tempvotings_list > 0 then | 
| bsw/jbe@19 | 202           scoring = table.concat(tempvotings_list, ";") | 
| bsw/jbe@19 | 203         else | 
| bsw/jbe@19 | 204           scoring = "" | 
| bsw/jbe@19 | 205         end | 
| bsw/jbe@19 | 206       end | 
| bsw/jbe@19 | 207       slot.put('<input type="hidden" name="scoring" value="' .. scoring .. '"/>') | 
| bsw/jbe@19 | 208       -- TODO abstrahieren | 
| bsw/jbe@19 | 209       ui.tag{ | 
| bsw/jbe@19 | 210         tag = "input", | 
| bsw/jbe@19 | 211         attr = { | 
| bsw@86 | 212           type = "submit", | 
| bsw/jbe@19 | 213           class = "voting_done", | 
| bsw/jbe@19 | 214           value = _"Finish voting" | 
| bsw/jbe@19 | 215         } | 
| bsw/jbe@5 | 216       } | 
| bsw/jbe@19 | 217     end | 
| bsw/jbe@5 | 218     ui.container{ | 
| bsw/jbe@5 | 219       attr = { id = "voting" }, | 
| bsw/jbe@5 | 220       content = function() | 
| bsw/jbe@19 | 221         local approval_index, disapproval_index = 0, 0 | 
| bsw/jbe@5 | 222         for grade = max_grade, min_grade, -1 do | 
| bsw/jbe@19 | 223           local entries = sections[grade] | 
| bsw/jbe@5 | 224           local class | 
| bsw/jbe@5 | 225           if grade > 0 then | 
| bsw/jbe@5 | 226             class = "approval" | 
| bsw/jbe@5 | 227           elseif grade < 0 then | 
| bsw/jbe@5 | 228             class = "disapproval" | 
| bsw/jbe@5 | 229           else | 
| bsw/jbe@5 | 230             class = "abstention" | 
| bsw/jbe@5 | 231           end | 
| bsw/jbe@19 | 232           if | 
| bsw/jbe@19 | 233             #entries > 0 or | 
| bsw/jbe@19 | 234             (grade == 1 and not approval_used) or | 
| bsw/jbe@19 | 235             (grade == -1 and not disapproval_used) or | 
| bsw/jbe@19 | 236             grade == 0 | 
| bsw/jbe@19 | 237           then | 
| bsw/jbe@19 | 238             ui.container{ | 
| bsw/jbe@19 | 239               attr = { class = class }, | 
| bsw/jbe@19 | 240               content = function() | 
| bsw/jbe@19 | 241                 local heading | 
| bsw/jbe@19 | 242                 if class == "approval" then | 
| bsw/jbe@19 | 243                   approval_used = true | 
| bsw/jbe@19 | 244                   approval_index = approval_index + 1 | 
| bsw/jbe@19 | 245                   if approval_count > 1 then | 
| bsw/jbe@19 | 246                     if approval_index == 1 then | 
| bsw/jbe@19 | 247                       if #entries == 1 then | 
| bsw/jbe@19 | 248                         heading = _"Approval (first preference) [single entry]" | 
| bsw/jbe@19 | 249                       else | 
| bsw/jbe@19 | 250                         heading = _"Approval (first preference) [many entries]" | 
| bsw/jbe@19 | 251                       end | 
| bsw/jbe@19 | 252                     elseif approval_index == 2 then | 
| bsw/jbe@19 | 253                       if #entries == 1 then | 
| bsw/jbe@19 | 254                         heading = _"Approval (second preference) [single entry]" | 
| bsw/jbe@19 | 255                       else | 
| bsw/jbe@19 | 256                         heading = _"Approval (second preference) [many entries]" | 
| bsw/jbe@19 | 257                       end | 
| bsw/jbe@19 | 258                     elseif approval_index == 3 then | 
| bsw/jbe@19 | 259                       if #entries == 1 then | 
| bsw/jbe@19 | 260                         heading = _"Approval (third preference) [single entry]" | 
| bsw/jbe@19 | 261                       else | 
| bsw/jbe@19 | 262                         heading = _"Approval (third preference) [many entries]" | 
| bsw/jbe@19 | 263                       end | 
| bsw/jbe@19 | 264                     else | 
| bsw/jbe@19 | 265                       if #entries == 1 then | 
| bsw/jbe@19 | 266                         heading = _"Approval (#th preference) [single entry]" | 
| bsw/jbe@19 | 267                       else | 
| bsw/jbe@19 | 268                         heading = _"Approval (#th preference) [many entries]" | 
| bsw/jbe@19 | 269                       end | 
| bsw/jbe@19 | 270                     end | 
| bsw/jbe@19 | 271                   else | 
| bsw/jbe@19 | 272                     if #entries == 1 then | 
| bsw/jbe@19 | 273                       heading = _"Approval [single entry]" | 
| bsw/jbe@19 | 274                     else | 
| bsw/jbe@19 | 275                       heading = _"Approval [many entries]" | 
| bsw/jbe@19 | 276                     end | 
| bsw/jbe@19 | 277                   end | 
| bsw/jbe@19 | 278                 elseif class == "abstention" then | 
| bsw/jbe@19 | 279                     if #entries == 1 then | 
| bsw/jbe@19 | 280                       heading = _"Abstention [single entry]" | 
| bsw/jbe@19 | 281                     else | 
| bsw/jbe@19 | 282                       heading = _"Abstention [many entries]" | 
| bsw/jbe@19 | 283                     end | 
| bsw/jbe@19 | 284                 elseif class == "disapproval" then | 
| bsw/jbe@19 | 285                   disapproval_used = true | 
| bsw/jbe@19 | 286                   disapproval_index = disapproval_index + 1 | 
| bsw/jbe@19 | 287                   if disapproval_count > disapproval_index + 1 then | 
| bsw/jbe@19 | 288                     if #entries == 1 then | 
| bsw/jbe@19 | 289                       heading = _"Disapproval (prefer to lower blocks) [single entry]" | 
| bsw/jbe@19 | 290                     else | 
| bsw/jbe@19 | 291                       heading = _"Disapproval (prefer to lower blocks) [many entries]" | 
| bsw/jbe@19 | 292                     end | 
| bsw/jbe@19 | 293                   elseif disapproval_count == 2 and disapproval_index == 1 then | 
| bsw/jbe@19 | 294                     if #entries == 1 then | 
| bsw/jbe@19 | 295                       heading = _"Disapproval (prefer to lower block) [single entry]" | 
| bsw/jbe@19 | 296                     else | 
| bsw/jbe@19 | 297                       heading = _"Disapproval (prefer to lower block) [many entries]" | 
| bsw/jbe@19 | 298                     end | 
| bsw/jbe@19 | 299                   elseif disapproval_index == disapproval_count - 1 then | 
| bsw/jbe@19 | 300                     if #entries == 1 then | 
| bsw/jbe@19 | 301                       heading = _"Disapproval (prefer to last block) [single entry]" | 
| bsw/jbe@19 | 302                     else | 
| bsw/jbe@19 | 303                       heading = _"Disapproval (prefer to last block) [many entries]" | 
| bsw/jbe@19 | 304                     end | 
| bsw/jbe@19 | 305                   else | 
| bsw/jbe@19 | 306                     if #entries == 1 then | 
| bsw/jbe@19 | 307                       heading = _"Disapproval [single entry]" | 
| bsw/jbe@19 | 308                     else | 
| bsw/jbe@19 | 309                       heading = _"Disapproval [many entries]" | 
| bsw/jbe@6 | 310                     end | 
| bsw/jbe@19 | 311                   end | 
| bsw/jbe@19 | 312                 end | 
| bsw/jbe@19 | 313                 ui.tag { | 
| bsw/jbe@19 | 314                   tag     = "div", | 
| bsw/jbe@19 | 315                   attr    = { class = "cathead" }, | 
| bsw/jbe@19 | 316                   content = heading | 
| bsw/jbe@19 | 317                 } | 
| bsw/jbe@19 | 318                 for i, initiative in ipairs(entries) do | 
| bsw/jbe@19 | 319                   ui.container{ | 
| bsw/jbe@19 | 320                     attr = { | 
| bsw/jbe@19 | 321                       class = "movable", | 
| bsw/jbe@19 | 322                       id = "entry_" .. tostring(initiative.id) | 
| bsw/jbe@19 | 323                     }, | 
| bsw/jbe@19 | 324                     content = function() | 
| bsw/jbe@19 | 325                       local initiators_selector = initiative:get_reference_selector("initiating_members") | 
| bsw/jbe@19 | 326                         :add_where("accepted") | 
| bsw/jbe@19 | 327                       local initiators = initiators_selector:exec() | 
| bsw/jbe@19 | 328                       local initiator_names = {} | 
| bsw/jbe@19 | 329                       for i, initiator in ipairs(initiators) do | 
| bsw/jbe@19 | 330                         initiator_names[#initiator_names+1] = initiator.name | 
| bsw/jbe@19 | 331                       end | 
| bsw/jbe@19 | 332                       local initiator_names_string = table.concat(initiator_names, ", ") | 
| bsw/jbe@19 | 333                       ui.container{ | 
| bsw@519 | 334                         attr = { style = "float: right; position: relative;" }, | 
| bsw/jbe@19 | 335                         content = function() | 
| bsw/jbe@19 | 336                           ui.link{ | 
| bsw/jbe@19 | 337                             attr = { class = "clickable" }, | 
| bsw/jbe@19 | 338                             content = _"Show", | 
| bsw/jbe@19 | 339                             module = "initiative", | 
| bsw/jbe@19 | 340                             view = "show", | 
| bsw/jbe@19 | 341                             id = initiative.id | 
| bsw/jbe@19 | 342                           } | 
| bsw/jbe@19 | 343                           slot.put(" ") | 
| bsw/jbe@19 | 344                           ui.link{ | 
| bsw/jbe@19 | 345                             attr = { class = "clickable", target = "_blank" }, | 
| bsw/jbe@19 | 346                             content = _"(new window)", | 
| bsw/jbe@19 | 347                             module = "initiative", | 
| bsw/jbe@19 | 348                             view = "show", | 
| bsw/jbe@19 | 349                             id = initiative.id | 
| bsw/jbe@19 | 350                           } | 
| bsw/jbe@19 | 351                           if not readonly then | 
| bsw/jbe@19 | 352                             slot.put(" ") | 
| bsw/jbe@19 | 353                             ui.image{ attr = { class = "grabber" }, static = "icons/grabber.png" } | 
| bsw/jbe@19 | 354                           end | 
| bsw/jbe@19 | 355                         end | 
| bsw/jbe@19 | 356                       } | 
| bsw/jbe@19 | 357                       if not readonly then | 
| bsw/jbe@19 | 358                         ui.container{ | 
| bsw@519 | 359                           attr = { style = "float: left; position: relative;" }, | 
| bsw/jbe@19 | 360                           content = function() | 
| bsw/jbe@19 | 361                             ui.tag{ | 
| bsw/jbe@19 | 362                               tag = "input", | 
| bsw/jbe@19 | 363                               attr = { | 
| bsw@519 | 364                                 onclick = "if (jsFail) return true; voting_moveUp(this.parentNode.parentNode); return(false);", | 
| bsw@519 | 365                                 name = "move_up_" .. tostring(initiative.id), | 
| bsw/jbe@19 | 366                                 class = not disabled and "clickable" or nil, | 
| bsw/jbe@19 | 367                                 type = "image", | 
| bsw/jbe@19 | 368                                 src = encode.url{ static = "icons/move_up.png" }, | 
| bsw/jbe@19 | 369                                 alt = _"Move up" | 
| bsw/jbe@19 | 370                               } | 
| bsw/jbe@19 | 371                             } | 
| bsw/jbe@19 | 372                             slot.put(" ") | 
| bsw/jbe@19 | 373                             ui.tag{ | 
| bsw/jbe@19 | 374                               tag = "input", | 
| bsw/jbe@19 | 375                               attr = { | 
| bsw@519 | 376                                 onclick = "if (jsFail) return true; voting_moveDown(this.parentNode.parentNode); return(false);", | 
| bsw@519 | 377                                 name = "move_down_" .. tostring(initiative.id), | 
| bsw/jbe@19 | 378                                 class = not disabled and "clickable" or nil, | 
| bsw/jbe@19 | 379                                 type = "image", | 
| bsw/jbe@19 | 380                                 src = encode.url{ static = "icons/move_down.png" }, | 
| bsw/jbe@19 | 381                                 alt = _"Move down" | 
| bsw/jbe@19 | 382                               } | 
| bsw/jbe@19 | 383                             } | 
| bsw/jbe@19 | 384                             slot.put(" ") | 
| bsw/jbe@19 | 385                           end | 
| bsw/jbe@6 | 386                         } | 
| bsw/jbe@6 | 387                       end | 
| bsw/jbe@6 | 388                       ui.container{ | 
| bsw/jbe@19 | 389                         content = function() | 
| bsw@285 | 390                           ui.tag{ content = "i" .. initiative.id .. ": " } | 
| bsw@285 | 391                           ui.tag{ content = initiative.shortened_name } | 
| bsw@286 | 392                           slot.put("<br />") | 
| bsw@286 | 393                           for i, initiator in ipairs(initiators) do | 
| bsw@286 | 394                             ui.link{ | 
| bsw@286 | 395                               attr = { class = "clickable" }, | 
| bsw@286 | 396                               content = function () | 
| bsw@286 | 397                                 execute.view{ | 
| bsw@286 | 398                                   module = "member_image", | 
| bsw@286 | 399                                   view = "_show", | 
| bsw@286 | 400                                   params = { | 
| bsw@286 | 401                                     member = initiator, | 
| bsw@286 | 402                                     image_type = "avatar", | 
| bsw@286 | 403                                     show_dummy = true, | 
| bsw@286 | 404                                     class = "micro_avatar", | 
| bsw@286 | 405                                     popup_text = text | 
| bsw@286 | 406                                   } | 
| bsw@286 | 407                                 } | 
| bsw@286 | 408                               end, | 
| bsw@286 | 409                               module = "member", view = "show", id = initiator.id | 
| bsw/jbe@19 | 410                             } | 
| bsw@286 | 411                             slot.put(" ") | 
| bsw@290 | 412                             ui.tag{ content = initiator.name } | 
| bsw@286 | 413                             slot.put(" ") | 
| bsw/jbe@19 | 414                           end | 
| bsw/jbe@19 | 415                         end | 
| bsw/jbe@6 | 416                       } | 
| bsw/jbe@6 | 417                     end | 
| bsw/jbe@19 | 418                   } | 
| bsw/jbe@19 | 419                 end | 
| bsw/jbe@5 | 420               end | 
| bsw/jbe@19 | 421             } | 
| bsw/jbe@19 | 422           end | 
| bsw/jbe@5 | 423         end | 
| bsw/jbe@5 | 424       end | 
| bsw/jbe@5 | 425     } | 
| bsw/jbe@19 | 426     if not readonly then | 
| bsw/jbe@19 | 427       ui.tag{ | 
| bsw/jbe@19 | 428         tag = "input", | 
| bsw/jbe@19 | 429         attr = { | 
| bsw@86 | 430           type = "submit", | 
| bsw/jbe@19 | 431           class = "voting_done", | 
| bsw/jbe@19 | 432           value = _"Finish voting" | 
| bsw/jbe@19 | 433         } | 
| bsw/jbe@5 | 434       } | 
| bsw/jbe@19 | 435     end | 
| bsw/jbe@5 | 436   end | 
| bsw/jbe@5 | 437 } | 
| bsw/jbe@5 | 438 | 
| bsw/jbe@5 | 439 |