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