liquid_feedback_frontend
diff app/main/vote/list.lua @ 1045:701a5cf6b067
Imported LiquidFeedback Frontend 3.0 branch
author | bsw |
---|---|
date | Thu Jul 10 01:19:48 2014 +0200 (2014-07-10) |
parents | 37e31dd73e45 |
children | 904f6807f7fa |
line diff
1.1 --- a/app/main/vote/list.lua Thu Jul 10 01:02:43 2014 +0200 1.2 +++ b/app/main/vote/list.lua Thu Jul 10 01:19:48 2014 +0200 1.3 @@ -21,69 +21,29 @@ 1.4 readonly = true 1.5 end 1.6 1.7 +if preview then 1.8 + readonly = true 1.9 +end 1.10 + 1.11 local submit_button_text = _"Finish voting" 1.12 +local edit_button_text = _"Edit again" 1.13 1.14 if issue.closed then 1.15 - submit_button_text = _"Update voting comment" 1.16 + submit_button_text = _"Save voting comment" 1.17 + edit_button_text = _"Edit voting comment" 1.18 end 1.19 1.20 +execute.view { 1.21 + module = "issue", view = "_head", params = { issue = issue } 1.22 +} 1.23 + 1.24 local direct_voter 1.25 1.26 if member then 1.27 direct_voter = DirectVoter:by_pk(issue.id, member.id) 1.28 - local str = _("Ballot of '#{member_name}' for issue ##{issue_id}", 1.29 - {member_name = string.format('<a href="%s">%s</a>', 1.30 - encode.url{ 1.31 - module = "member", 1.32 - view = "show", 1.33 - id = member.id, 1.34 - }, 1.35 - encode.html(member.name)), 1.36 - issue_id = string.format('<a href="%s">%s</a>', 1.37 - encode.url{ 1.38 - module = "issue", 1.39 - view = "show", 1.40 - id = issue.id, 1.41 - }, 1.42 - encode.html(tostring(issue.id))) 1.43 - } 1.44 - ) 1.45 - ui.raw_title(str) 1.46 else 1.47 member = app.session.member 1.48 - 1.49 direct_voter = DirectVoter:by_pk(issue.id, member.id) 1.50 - 1.51 - ui.title(_"Voting") 1.52 - 1.53 - ui.actions(function() 1.54 - ui.link{ 1.55 - text = _"Cancel", 1.56 - module = "issue", 1.57 - view = "show", 1.58 - id = issue.id 1.59 - } 1.60 - if direct_voter then 1.61 - slot.put(" · ") 1.62 - ui.link{ 1.63 - text = _"Discard voting", 1.64 - module = "vote", 1.65 - action = "update", 1.66 - params = { 1.67 - issue_id = issue.id, 1.68 - discard = true 1.69 - }, 1.70 - routing = { 1.71 - default = { 1.72 - mode = "redirect", 1.73 - module = "issue", 1.74 - view = "show", 1.75 - id = issue.id 1.76 - } 1.77 - } 1.78 - } 1.79 - end 1.80 - end) 1.81 end 1.82 1.83 1.84 @@ -144,10 +104,7 @@ 1.85 end 1.86 end 1.87 1.88 - 1.89 - 1.90 if not readonly then 1.91 - util.help("vote.list", _"Voting") 1.92 slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/dragdrop.js"></script>') 1.93 slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/voting.js"></script>') 1.94 end 1.95 @@ -179,321 +136,436 @@ 1.96 end 1.97 } 1.98 1.99 -ui.form{ 1.100 - record = direct_voter, 1.101 - attr = { 1.102 - id = "voting_form", 1.103 - class = readonly and "voting_form_readonly" or "voting_form_active" 1.104 - }, 1.105 - module = "vote", 1.106 - action = "update", 1.107 - params = { issue_id = issue.id }, 1.108 - content = function() 1.109 - if not readonly or preview then 1.110 - local scoring = param.get("scoring") 1.111 - if not scoring then 1.112 - for i, initiative in ipairs(initiatives) do 1.113 - local vote = initiative.vote 1.114 - if vote then 1.115 - tempvotings[initiative.id] = vote.grade 1.116 - else 1.117 - tempvotings[initiative.id] = 0 1.118 - end 1.119 - end 1.120 - local tempvotings_list = {} 1.121 - for key, val in pairs(tempvotings) do 1.122 - tempvotings_list[#tempvotings_list+1] = tostring(key) .. ":" .. tostring(val) 1.123 - end 1.124 - if #tempvotings_list > 0 then 1.125 - scoring = table.concat(tempvotings_list, ";") 1.126 - else 1.127 - scoring = "" 1.128 - end 1.129 - end 1.130 - slot.put('<input type="hidden" name="scoring" value="' .. scoring .. '"/>') 1.131 - -- TODO abstrahieren 1.132 - ui.tag{ 1.133 - tag = "input", 1.134 - attr = { 1.135 - type = "submit", 1.136 - class = "voting_done1", 1.137 - value = submit_button_text 1.138 - } 1.139 +if issue.state == "finished_with_winner" 1.140 + or issue.state == "finished_without_winner" 1.141 +then 1.142 + 1.143 + local members_selector = Member:new_selector() 1.144 + :join("delegating_voter", nil, "delegating_voter.member_id = member.id") 1.145 + :add_where{ "delegating_voter.issue_id = ?", issue.id } 1.146 + :add_where{ "delegating_voter.delegate_member_ids[1] = ?", member.id } 1.147 + :add_field("delegating_voter.weight", "voter_weight") 1.148 + :join("issue", nil, "issue.id = delegating_voter.issue_id") 1.149 + 1.150 + ui.sidebar( "tab-members", function() 1.151 + ui.sidebarHead(function() 1.152 + ui.heading{ level = 2, content = _"Incoming delegations" } 1.153 + end) 1.154 + execute.view{ 1.155 + module = "member", 1.156 + view = "_list", 1.157 + params = { 1.158 + members_selector = members_selector, 1.159 + trustee = member, 1.160 + issue = issue, 1.161 + initiative = initiative, 1.162 + for_votes = true, no_filter = true, 1.163 + member_class = "sidebarRow sidebarRowNarrow", 1.164 } 1.165 + } 1.166 + end) 1.167 +end 1.168 + 1.169 + 1.170 +ui.section( function() 1.171 + 1.172 + ui.sectionHead( function() 1.173 + if preview then 1.174 + ui.heading { level = 1, content = _"Preview of voting ballot" } 1.175 + elseif readonly then 1.176 + local str = _("Ballot of '#{member_name}'", 1.177 + {member_name = string.format('<a href="%s">%s</a>', 1.178 + encode.url{ 1.179 + module = "member", 1.180 + view = "show", 1.181 + id = member.id, 1.182 + }, 1.183 + encode.html(member.name)) 1.184 + } 1.185 + ) 1.186 + ui.heading { level = 1, content = function () slot.put ( str ) end } 1.187 + else 1.188 + ui.heading { level = 1, content = _"Voting" } 1.189 end 1.190 - ui.container{ 1.191 - attr = { id = "voting" }, 1.192 + end ) 1.193 + 1.194 + ui.sectionRow( function() 1.195 + 1.196 + ui.form{ 1.197 + record = direct_voter, 1.198 + attr = { 1.199 + id = "voting_form", 1.200 + class = readonly and "voting_form_readonly" or "voting_form_active" 1.201 + }, 1.202 + module = "vote", 1.203 + action = "update", 1.204 + params = { issue_id = issue.id }, 1.205 content = function() 1.206 - local approval_index, disapproval_index = 0, 0 1.207 - for grade = max_grade, min_grade, -1 do 1.208 - local entries = sections[grade] 1.209 - local class 1.210 - if grade > 0 then 1.211 - class = "approval" 1.212 - elseif grade < 0 then 1.213 - class = "disapproval" 1.214 - else 1.215 - class = "abstention" 1.216 + if not readonly or preview then 1.217 + local scoring = param.get("scoring") 1.218 + if not scoring then 1.219 + for i, initiative in ipairs(initiatives) do 1.220 + local vote = initiative.vote 1.221 + if vote then 1.222 + tempvotings[initiative.id] = vote.grade 1.223 + else 1.224 + tempvotings[initiative.id] = 0 1.225 + end 1.226 + end 1.227 + local tempvotings_list = {} 1.228 + for key, val in pairs(tempvotings) do 1.229 + tempvotings_list[#tempvotings_list+1] = tostring(key) .. ":" .. tostring(val) 1.230 + end 1.231 + if #tempvotings_list > 0 then 1.232 + scoring = table.concat(tempvotings_list, ";") 1.233 + else 1.234 + scoring = "" 1.235 + end 1.236 end 1.237 - if 1.238 - #entries > 0 or 1.239 - (grade == 1 and not approval_used) or 1.240 - (grade == -1 and not disapproval_used) or 1.241 - grade == 0 1.242 - then 1.243 - ui.container{ 1.244 - attr = { class = class }, 1.245 - content = function() 1.246 - local heading 1.247 - if class == "approval" then 1.248 - approval_used = true 1.249 - approval_index = approval_index + 1 1.250 - if approval_count > 1 then 1.251 - if approval_index == 1 then 1.252 - if #entries == 1 then 1.253 - heading = _"Approval (first preference) [single entry]" 1.254 + slot.put('<input type="hidden" name="scoring" value="' .. scoring .. '"/>') 1.255 + end 1.256 + if preview then 1.257 + ui.heading{ level = 2, content = _"Your choice" } 1.258 + elseif not readonly then 1.259 + ui.heading{ level = 2, content = _"Make your choice by placing the initiatives" } 1.260 + end 1.261 + 1.262 + ui.container{ 1.263 + attr = { id = "voting" }, 1.264 + content = function() 1.265 + local approval_index, disapproval_index = 0, 0 1.266 + for grade = max_grade, min_grade, -1 do 1.267 + local entries = sections[grade] 1.268 + local class 1.269 + if grade > 0 then 1.270 + class = "approval" 1.271 + elseif grade < 0 then 1.272 + class = "disapproval" 1.273 + else 1.274 + class = "abstention" 1.275 + end 1.276 + if 1.277 + #entries > 0 or 1.278 + (grade == 1 and not approval_used) or 1.279 + (grade == -1 and not disapproval_used) or 1.280 + grade == 0 1.281 + then 1.282 + ui.container{ 1.283 + attr = { class = class }, 1.284 + content = function() 1.285 + local heading 1.286 + if class == "approval" then 1.287 + approval_used = true 1.288 + approval_index = approval_index + 1 1.289 + if approval_count > 1 then 1.290 + if approval_index == 1 then 1.291 + if #entries == 1 then 1.292 + heading = _"Approval (first preference) [single entry]" 1.293 + else 1.294 + heading = _"Approval (first preference) [many entries]" 1.295 + end 1.296 + elseif approval_index == 2 then 1.297 + if #entries == 1 then 1.298 + heading = _"Approval (second preference) [single entry]" 1.299 + else 1.300 + heading = _"Approval (second preference) [many entries]" 1.301 + end 1.302 + elseif approval_index == 3 then 1.303 + if #entries == 1 then 1.304 + heading = _"Approval (third preference) [single entry]" 1.305 + else 1.306 + heading = _"Approval (third preference) [many entries]" 1.307 + end 1.308 + else 1.309 + if #entries == 1 then 1.310 + heading = _"Approval (#th preference) [single entry]" 1.311 + else 1.312 + heading = _"Approval (#th preference) [many entries]" 1.313 + end 1.314 + end 1.315 else 1.316 - heading = _"Approval (first preference) [many entries]" 1.317 - end 1.318 - elseif approval_index == 2 then 1.319 - if #entries == 1 then 1.320 - heading = _"Approval (second preference) [single entry]" 1.321 - else 1.322 - heading = _"Approval (second preference) [many entries]" 1.323 + if #entries == 1 then 1.324 + heading = _"Approval [single entry]" 1.325 + else 1.326 + heading = _"Approval [many entries]" 1.327 + end 1.328 end 1.329 - elseif approval_index == 3 then 1.330 - if #entries == 1 then 1.331 - heading = _"Approval (third preference) [single entry]" 1.332 + elseif class == "abstention" then 1.333 + if #entries == 1 then 1.334 + heading = _"Abstention [single entry]" 1.335 + else 1.336 + heading = _"Abstention [many entries]" 1.337 + end 1.338 + elseif class == "disapproval" then 1.339 + disapproval_used = true 1.340 + disapproval_index = disapproval_index + 1 1.341 + if disapproval_count > disapproval_index + 1 then 1.342 + if #entries == 1 then 1.343 + heading = _"Disapproval (prefer to lower blocks) [single entry]" 1.344 + else 1.345 + heading = _"Disapproval (prefer to lower blocks) [many entries]" 1.346 + end 1.347 + elseif disapproval_count == 2 and disapproval_index == 1 then 1.348 + if #entries == 1 then 1.349 + heading = _"Disapproval (prefer to lower block) [single entry]" 1.350 + else 1.351 + heading = _"Disapproval (prefer to lower block) [many entries]" 1.352 + end 1.353 + elseif disapproval_index == disapproval_count - 1 then 1.354 + if #entries == 1 then 1.355 + heading = _"Disapproval (prefer to last block) [single entry]" 1.356 + else 1.357 + heading = _"Disapproval (prefer to last block) [many entries]" 1.358 + end 1.359 else 1.360 - heading = _"Approval (third preference) [many entries]" 1.361 - end 1.362 - else 1.363 - if #entries == 1 then 1.364 - heading = _"Approval (#th preference) [single entry]" 1.365 - else 1.366 - heading = _"Approval (#th preference) [many entries]" 1.367 + if #entries == 1 then 1.368 + heading = _"Disapproval [single entry]" 1.369 + else 1.370 + heading = _"Disapproval [many entries]" 1.371 + end 1.372 end 1.373 end 1.374 - else 1.375 - if #entries == 1 then 1.376 - heading = _"Approval [single entry]" 1.377 - else 1.378 - heading = _"Approval [many entries]" 1.379 - end 1.380 - end 1.381 - elseif class == "abstention" then 1.382 - if #entries == 1 then 1.383 - heading = _"Abstention [single entry]" 1.384 - else 1.385 - heading = _"Abstention [many entries]" 1.386 - end 1.387 - elseif class == "disapproval" then 1.388 - disapproval_used = true 1.389 - disapproval_index = disapproval_index + 1 1.390 - if disapproval_count > disapproval_index + 1 then 1.391 - if #entries == 1 then 1.392 - heading = _"Disapproval (prefer to lower blocks) [single entry]" 1.393 - else 1.394 - heading = _"Disapproval (prefer to lower blocks) [many entries]" 1.395 - end 1.396 - elseif disapproval_count == 2 and disapproval_index == 1 then 1.397 - if #entries == 1 then 1.398 - heading = _"Disapproval (prefer to lower block) [single entry]" 1.399 - else 1.400 - heading = _"Disapproval (prefer to lower block) [many entries]" 1.401 - end 1.402 - elseif disapproval_index == disapproval_count - 1 then 1.403 - if #entries == 1 then 1.404 - heading = _"Disapproval (prefer to last block) [single entry]" 1.405 - else 1.406 - heading = _"Disapproval (prefer to last block) [many entries]" 1.407 - end 1.408 - else 1.409 - if #entries == 1 then 1.410 - heading = _"Disapproval [single entry]" 1.411 - else 1.412 - heading = _"Disapproval [many entries]" 1.413 - end 1.414 - end 1.415 - end 1.416 - ui.tag { 1.417 - tag = "div", 1.418 - attr = { class = "cathead" }, 1.419 - content = heading 1.420 - } 1.421 - for i, initiative in ipairs(entries) do 1.422 - ui.container{ 1.423 - attr = { 1.424 - class = "movable", 1.425 - id = "entry_" .. tostring(initiative.id) 1.426 - }, 1.427 - content = function() 1.428 - local initiators_selector = initiative:get_reference_selector("initiating_members") 1.429 - :add_where("accepted") 1.430 - local initiators = initiators_selector:exec() 1.431 - local initiator_names = {} 1.432 - for i, initiator in ipairs(initiators) do 1.433 - initiator_names[#initiator_names+1] = initiator.name 1.434 - end 1.435 - local initiator_names_string = table.concat(initiator_names, ", ") 1.436 + ui.tag { 1.437 + tag = "div", 1.438 + attr = { class = "cathead" }, 1.439 + content = heading 1.440 + } 1.441 + for i, initiative in ipairs(entries) do 1.442 ui.container{ 1.443 - attr = { style = "float: right; position: relative;" }, 1.444 + attr = { 1.445 + class = "movable", 1.446 + id = "entry_" .. tostring(initiative.id) 1.447 + }, 1.448 content = function() 1.449 - ui.link{ 1.450 - attr = { class = "clickable" }, 1.451 - content = _"Show", 1.452 - module = "initiative", 1.453 - view = "show", 1.454 - id = initiative.id 1.455 - } 1.456 - slot.put(" ") 1.457 - ui.link{ 1.458 - attr = { class = "clickable", target = "_blank" }, 1.459 - content = _"(new window)", 1.460 - module = "initiative", 1.461 - view = "show", 1.462 - id = initiative.id 1.463 + local initiators_selector = initiative:get_reference_selector("initiating_members") 1.464 + :add_where("accepted") 1.465 + local initiators = initiators_selector:exec() 1.466 + local initiator_names = {} 1.467 + for i, initiator in ipairs(initiators) do 1.468 + initiator_names[#initiator_names+1] = initiator.name 1.469 + end 1.470 + local initiator_names_string = table.concat(initiator_names, ", ") 1.471 + ui.container{ 1.472 + attr = { style = "float: right; position: relative;" }, 1.473 + content = function() 1.474 + ui.link{ 1.475 + attr = { class = "clickable" }, 1.476 + content = _"Show", 1.477 + module = "initiative", 1.478 + view = "show", 1.479 + id = initiative.id 1.480 + } 1.481 + slot.put(" ") 1.482 + ui.link{ 1.483 + attr = { class = "clickable", target = "_blank" }, 1.484 + content = _"(new window)", 1.485 + module = "initiative", 1.486 + view = "show", 1.487 + id = initiative.id 1.488 + } 1.489 + if not readonly then 1.490 + slot.put(" ") 1.491 + ui.image{ attr = { class = "grabber" }, static = "icons/grabber.png" } 1.492 + end 1.493 + end 1.494 } 1.495 if not readonly then 1.496 - slot.put(" ") 1.497 - ui.image{ attr = { class = "grabber" }, static = "icons/grabber.png" } 1.498 - end 1.499 - end 1.500 - } 1.501 - if not readonly then 1.502 - ui.container{ 1.503 - attr = { style = "float: left; position: relative;" }, 1.504 - content = function() 1.505 - ui.tag{ 1.506 - tag = "input", 1.507 - attr = { 1.508 - onclick = "if (jsFail) return true; voting_moveUp(this.parentNode.parentNode); return(false);", 1.509 - name = "move_up_" .. tostring(initiative.id), 1.510 - class = not disabled and "clickable" or nil, 1.511 - type = "image", 1.512 - src = encode.url{ static = "icons/move_up.png" }, 1.513 - alt = _"Move up" 1.514 - } 1.515 - } 1.516 - slot.put(" ") 1.517 - ui.tag{ 1.518 - tag = "input", 1.519 - attr = { 1.520 - onclick = "if (jsFail) return true; voting_moveDown(this.parentNode.parentNode); return(false);", 1.521 - name = "move_down_" .. tostring(initiative.id), 1.522 - class = not disabled and "clickable" or nil, 1.523 - type = "image", 1.524 - src = encode.url{ static = "icons/move_down.png" }, 1.525 - alt = _"Move down" 1.526 - } 1.527 - } 1.528 - slot.put(" ") 1.529 - end 1.530 - } 1.531 - end 1.532 - ui.container{ 1.533 - content = function() 1.534 - ui.tag{ content = "i" .. initiative.id .. ": " } 1.535 - ui.tag{ content = initiative.shortened_name } 1.536 - slot.put("<br />") 1.537 - for i, initiator in ipairs(initiators) do 1.538 - ui.link{ 1.539 - attr = { class = "clickable" }, 1.540 - content = function () 1.541 - execute.view{ 1.542 - module = "member_image", 1.543 - view = "_show", 1.544 - params = { 1.545 - member = initiator, 1.546 - image_type = "avatar", 1.547 - show_dummy = true, 1.548 - class = "micro_avatar", 1.549 - popup_text = text 1.550 + ui.container{ 1.551 + attr = { style = "float: left; position: relative;" }, 1.552 + content = function() 1.553 + ui.tag{ 1.554 + tag = "input", 1.555 + attr = { 1.556 + onclick = "if (jsFail) return true; voting_moveUp(this.parentNode.parentNode); return(false);", 1.557 + name = "move_up_" .. tostring(initiative.id), 1.558 + class = not disabled and "clickable" or nil, 1.559 + type = "image", 1.560 + src = encode.url{ static = "icons/move_up.png" }, 1.561 + alt = _"Move up" 1.562 + } 1.563 + } 1.564 + slot.put(" ") 1.565 + ui.tag{ 1.566 + tag = "input", 1.567 + attr = { 1.568 + onclick = "if (jsFail) return true; voting_moveDown(this.parentNode.parentNode); return(false);", 1.569 + name = "move_down_" .. tostring(initiative.id), 1.570 + class = not disabled and "clickable" or nil, 1.571 + type = "image", 1.572 + src = encode.url{ static = "icons/move_down.png" }, 1.573 + alt = _"Move down" 1.574 } 1.575 } 1.576 - end, 1.577 - module = "member", view = "show", id = initiator.id 1.578 + slot.put(" ") 1.579 + end 1.580 } 1.581 - slot.put(" ") 1.582 - ui.tag{ content = initiator.name } 1.583 - slot.put(" ") 1.584 end 1.585 + ui.container{ 1.586 + content = function() 1.587 + ui.tag{ content = "i" .. initiative.id .. ": " } 1.588 + ui.tag{ content = initiative.shortened_name } 1.589 + slot.put("<br />") 1.590 + for i, initiator in ipairs(initiators) do 1.591 + ui.link{ 1.592 + attr = { class = "clickable" }, 1.593 + content = function () 1.594 + execute.view{ 1.595 + module = "member_image", 1.596 + view = "_show", 1.597 + params = { 1.598 + member = initiator, 1.599 + image_type = "avatar", 1.600 + show_dummy = true, 1.601 + class = "micro_avatar", 1.602 + popup_text = text 1.603 + } 1.604 + } 1.605 + end, 1.606 + module = "member", view = "show", id = initiator.id 1.607 + } 1.608 + slot.put(" ") 1.609 + ui.tag{ content = initiator.name } 1.610 + slot.put(" ") 1.611 + end 1.612 + end 1.613 + } 1.614 end 1.615 } 1.616 end 1.617 + end 1.618 + } 1.619 + end 1.620 + end 1.621 + end 1.622 + } 1.623 + if app.session.member_id and preview then 1.624 + local formatting_engine = param.get("formatting_engine") or config.enforce_formatting_engine 1.625 + local comment = param.get("comment") 1.626 + if comment and #comment > 0 then 1.627 + local rendered_comment = format.wiki_text(comment, formatting_engine) 1.628 + ui.heading{ level = "2", content = _"Voting comment" } 1.629 + ui.container { attr = { class = "member_statement" }, content = function() 1.630 + slot.put(rendered_comment) 1.631 + end } 1.632 + slot.put("<br />") 1.633 + end 1.634 + end 1.635 + if (readonly or direct_voter and direct_voter.comment) and not preview and not (app.session.member_id == member.id) then 1.636 + local text 1.637 + if direct_voter and direct_voter.comment_changed then 1.638 + text = _("Voting comment (last updated: #{timestamp})", { timestamp = format.timestamp(direct_voter.comment_changed) }) 1.639 + elseif direct_voter and direct_voter.comment then 1.640 + text = _"Voting comment" 1.641 + end 1.642 + if text then 1.643 + ui.heading{ level = "2", content = text } 1.644 + end 1.645 + if direct_voter and direct_voter.comment then 1.646 + local rendered_comment = direct_voter:get_content('html') 1.647 + ui.container { attr = { class = "member_statement" }, content = function() 1.648 + slot.put(rendered_comment) 1.649 + end } 1.650 + slot.put("<br />") 1.651 + end 1.652 + end 1.653 + if app.session.member_id and app.session.member_id == member.id then 1.654 + if (not readonly or direct_voter) and not preview then 1.655 + ui.container{ content = function() 1.656 + if not config.enforce_formatting_engine then 1.657 + ui.field.select{ 1.658 + label = _"Wiki engine for statement", 1.659 + name = "formatting_engine", 1.660 + foreign_records = config.formatting_engines, 1.661 + attr = {id = "formatting_engine"}, 1.662 + foreign_id = "id", 1.663 + foreign_name = "name", 1.664 + value = param.get("formatting_engine") or direct_voter and direct_voter.formatting_engine 1.665 + } 1.666 + end 1.667 + ui.heading { level = 2, content = _"Voting comment (optional)" } 1.668 + ui.field.text{ 1.669 + name = "comment", 1.670 + multiline = true, 1.671 + value = param.get("comment") or direct_voter and direct_voter.comment, 1.672 + attr = { style = "height: 10ex; width: 100%;" }, 1.673 + } 1.674 + end } 1.675 + end 1.676 + 1.677 + if preview then 1.678 + if not config.enforce_formatting_engine then 1.679 + ui.field.hidden{ name = "formatting_engine", value = param.get("formatting_engine") } 1.680 + end 1.681 + ui.field.hidden{ name = "comment", value = param.get("comment") or direct_voter and direct_voter.comment } 1.682 + end 1.683 + 1.684 + if not readonly or direct_voter or preview then 1.685 + ui.container{ content = function() 1.686 + if preview then 1.687 + slot.put(" ") 1.688 + ui.tag{ 1.689 + tag = "input", 1.690 + attr = { 1.691 + type = "submit", 1.692 + class = "btn btn-default", 1.693 + name = issue.closed and "update_comment" or nil, 1.694 + value = submit_button_text -- finish voting / update comment 1.695 } 1.696 - end 1.697 + } 1.698 end 1.699 - } 1.700 + if not preview then 1.701 + ui.tag{ 1.702 + tag = "input", 1.703 + attr = { 1.704 + type = "submit", 1.705 + name = "preview", 1.706 + class = "btn btn-default", 1.707 + value = _"Preview", 1.708 + } 1.709 + } 1.710 + else 1.711 + slot.put(" ") 1.712 + ui.tag{ 1.713 + tag = "input", 1.714 + attr = { 1.715 + type = "submit", 1.716 + name = "edit", 1.717 + class = "btn-link", 1.718 + value = edit_button_text, 1.719 + } 1.720 + } 1.721 + end 1.722 + end } 1.723 end 1.724 end 1.725 end 1.726 } 1.727 - if app.session.member_id and preview then 1.728 - local formatting_engine = param.get("formatting_engine") 1.729 - local comment = param.get("comment") 1.730 - local rendered_comment = format.wiki_text(comment, formatting_engine) 1.731 - slot.put(rendered_comment) 1.732 - end 1.733 - if (readonly or direct_voter and direct_voter.comment) and not preview then 1.734 - local text 1.735 - if direct_voter and direct_voter.comment_changed then 1.736 - text = _("Voting comment (last updated: #{timestamp})", { timestamp = format.timestamp(direct_voter.comment_changed) }) 1.737 - elseif direct_voter and direct_voter.comment then 1.738 - text = _"Voting comment" 1.739 - end 1.740 - if text then 1.741 - ui.heading{ level = "2", content = text } 1.742 - end 1.743 - if direct_voter and direct_voter.comment then 1.744 - local rendered_comment = direct_voter:get_content('html') 1.745 - ui.container{ attr = { class = "member_statement" }, content = function() 1.746 - slot.put(rendered_comment) 1.747 - end } 1.748 - slot.put("<br />") 1.749 - end 1.750 + slot.put("<br />") 1.751 + ui.link{ 1.752 + text = _"Cancel", 1.753 + module = "issue", 1.754 + view = "show", 1.755 + id = issue.id 1.756 + } 1.757 + if direct_voter then 1.758 + slot.put(" | ") 1.759 + ui.link { 1.760 + module = "vote", action = "update", 1.761 + params = { 1.762 + issue_id = issue.id, 1.763 + discard = true 1.764 + }, 1.765 + routing = { 1.766 + default = { 1.767 + mode = "redirect", 1.768 + module = "issue", 1.769 + view = "show", 1.770 + id = issue.id 1.771 + } 1.772 + }, 1.773 + text = _"Discard my vote" 1.774 + } 1.775 end 1.776 - if app.session.member_id and app.session.member_id == member.id then 1.777 - if not readonly or direct_voter then 1.778 - ui.field.hidden{ name = "update_comment", value = param.get("update_comment") or issue.closed and "1" } 1.779 - ui.field.select{ 1.780 - label = _"Wiki engine for statement", 1.781 - name = "formatting_engine", 1.782 - foreign_records = { 1.783 - { id = "rocketwiki", name = "RocketWiki" }, 1.784 - { id = "compat", name = _"Traditional wiki syntax" } 1.785 - }, 1.786 - attr = {id = "formatting_engine"}, 1.787 - foreign_id = "id", 1.788 - foreign_name = "name", 1.789 - value = param.get("formatting_engine") or direct_voter and direct_voter.formatting_engine 1.790 - } 1.791 - ui.field.text{ 1.792 - label = _"Voting comment (optional)", 1.793 - name = "comment", 1.794 - multiline = true, 1.795 - value = param.get("comment") or direct_voter and direct_voter.comment, 1.796 - attr = { style = "height: 20ex;" }, 1.797 - } 1.798 - ui.submit{ 1.799 - name = "preview", 1.800 - value = _"Preview voting comment", 1.801 - attr = { class = "preview" } 1.802 - } 1.803 - end 1.804 - if not readonly or preview or direct_voter then 1.805 - slot.put(" ") 1.806 - ui.tag{ 1.807 - tag = "input", 1.808 - attr = { 1.809 - type = "submit", 1.810 - class = "voting_done2", 1.811 - value = submit_button_text 1.812 - } 1.813 - } 1.814 - end 1.815 - end 1.816 - end 1.817 -} 1.818 1.819 - 1.820 + end ) 1.821 +end ) 1.822 \ No newline at end of file