liquid_feedback_frontend

annotate app/main/vote/list.lua @ 118:93f4e465b50d

add initiator support in delegation

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

Impressum / About Us