liquid_feedback_frontend

annotate 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
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
jbe@945 5 local readonly = false
bsw/jbe@19 6
jbe@950 7 local preview = param.get("preview") and true or false
poelzi@156 8
bsw/jbe@19 9 if member_id then
bsw/jbe@19 10 if not issue.closed then
bsw/jbe@19 11 error("access denied")
bsw/jbe@19 12 end
bsw/jbe@19 13 member = Member:by_id(member_id)
bsw/jbe@19 14 readonly = true
bsw/jbe@19 15 end
bsw/jbe@19 16
poelzi@138 17 if issue.closed then
poelzi@156 18 if not member then
poelzi@158 19 member = app.session.member
poelzi@158 20 end
poelzi@156 21 readonly = true
poelzi@138 22 end
poelzi@138 23
bsw@1045 24 if preview then
bsw@1045 25 readonly = true
bsw@1045 26 end
bsw@1045 27
bsw@879 28 local submit_button_text = _"Finish voting"
bsw@1045 29 local edit_button_text = _"Edit again"
bsw@879 30
bsw@879 31 if issue.closed then
bsw@1045 32 submit_button_text = _"Save voting comment"
bsw@1045 33 edit_button_text = _"Edit voting comment"
bsw@879 34 end
bsw@879 35
bsw@1045 36 execute.view {
bsw@1045 37 module = "issue", view = "_head", params = { issue = issue }
bsw@1045 38 }
bsw@1045 39
bsw@879 40 local direct_voter
bsw@879 41
bsw/jbe@19 42 if member then
bsw@879 43 direct_voter = DirectVoter:by_pk(issue.id, member.id)
bsw/jbe@19 44 else
bsw/jbe@19 45 member = app.session.member
bsw@879 46 direct_voter = DirectVoter:by_pk(issue.id, member.id)
bsw/jbe@19 47 end
bsw/jbe@19 48
bsw/jbe@19 49
bsw@879 50
bsw/jbe@19 51 local tempvoting_string = param.get("scoring")
bsw/jbe@19 52
bsw/jbe@19 53 local tempvotings = {}
bsw/jbe@19 54 if tempvoting_string then
bsw/jbe@19 55 for match in tempvoting_string:gmatch("([^;]+)") do
bsw/jbe@19 56 for initiative_id, grade in match:gmatch("([^:;]+):([^:;]+)") do
bsw/jbe@19 57 tempvotings[tonumber(initiative_id)] = tonumber(grade)
bsw/jbe@19 58 end
bsw/jbe@5 59 end
bsw/jbe@19 60 end
bsw/jbe@5 61
bsw@95 62 local initiatives = issue:get_reference_selector("initiatives"):add_where("initiative.admitted"):add_order_by("initiative.satisfied_supporter_count DESC"):exec()
bsw/jbe@5 63
bsw/jbe@5 64 local min_grade = -1;
bsw/jbe@5 65 local max_grade = 1;
bsw/jbe@5 66
bsw/jbe@5 67 for i, initiative in ipairs(initiatives) do
bsw/jbe@5 68 -- TODO performance
bsw/jbe@19 69 initiative.vote = Vote:by_pk(initiative.id, member.id)
bsw/jbe@19 70 if tempvotings[initiative.id] then
bsw/jbe@19 71 initiative.vote = {}
bsw/jbe@19 72 initiative.vote.grade = tempvotings[initiative.id]
bsw/jbe@19 73 end
bsw/jbe@5 74 if initiative.vote then
bsw/jbe@5 75 if initiative.vote.grade > max_grade then
bsw/jbe@5 76 max_grade = initiative.vote.grade
bsw/jbe@5 77 end
bsw/jbe@5 78 if initiative.vote.grade < min_grade then
bsw/jbe@5 79 min_grade = initiative.vote.grade
bsw/jbe@5 80 end
bsw/jbe@5 81 end
bsw/jbe@5 82 end
bsw/jbe@5 83
bsw/jbe@5 84 local sections = {}
bsw/jbe@5 85 for i = min_grade, max_grade do
bsw/jbe@5 86 sections[i] = {}
bsw/jbe@5 87 for j, initiative in ipairs(initiatives) do
bsw/jbe@5 88 if (initiative.vote and initiative.vote.grade == i) or (not initiative.vote and i == 0) then
bsw/jbe@5 89 sections[i][#(sections[i])+1] = initiative
bsw/jbe@5 90 end
bsw/jbe@5 91 end
bsw/jbe@5 92 end
bsw/jbe@5 93
bsw/jbe@19 94 local approval_count, disapproval_count = 0, 0
bsw/jbe@19 95 for i = min_grade, -1 do
bsw/jbe@19 96 if #sections[i] > 0 then
bsw/jbe@19 97 disapproval_count = disapproval_count + 1
bsw/jbe@19 98 end
bsw/jbe@19 99 end
bsw/jbe@19 100 local approval_count = 0
bsw/jbe@19 101 for i = 1, max_grade do
bsw/jbe@19 102 if #sections[i] > 0 then
bsw/jbe@19 103 approval_count = approval_count + 1
bsw/jbe@19 104 end
bsw/jbe@19 105 end
bsw/jbe@5 106
bsw/jbe@19 107 if not readonly then
bsw/jbe@19 108 slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/dragdrop.js"></script>')
bsw/jbe@19 109 slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/voting.js"></script>')
bsw/jbe@19 110 end
bsw/jbe@19 111
bsw/jbe@19 112 ui.script{
bsw/jbe@19 113 script = function()
bsw/jbe@19 114 slot.put(
bsw/jbe@19 115 "voting_text_approval_single = ", encode.json(_"Approval [single entry]"), ";\n",
bsw/jbe@19 116 "voting_text_approval_multi = ", encode.json(_"Approval [many entries]"), ";\n",
bsw/jbe@19 117 "voting_text_first_preference_single = ", encode.json(_"Approval (first preference) [single entry]"), ";\n",
bsw/jbe@19 118 "voting_text_first_preference_multi = ", encode.json(_"Approval (first preference) [many entries]"), ";\n",
bsw/jbe@19 119 "voting_text_second_preference_single = ", encode.json(_"Approval (second preference) [single entry]"), ";\n",
bsw/jbe@19 120 "voting_text_second_preference_multi = ", encode.json(_"Approval (second preference) [many entries]"), ";\n",
bsw/jbe@19 121 "voting_text_third_preference_single = ", encode.json(_"Approval (third preference) [single entry]"), ";\n",
bsw/jbe@19 122 "voting_text_third_preference_multi = ", encode.json(_"Approval (third preference) [many entries]"), ";\n",
bsw/jbe@19 123 "voting_text_numeric_preference_single = ", encode.json(_"Approval (#th preference) [single entry]"), ";\n",
bsw/jbe@19 124 "voting_text_numeric_preference_multi = ", encode.json(_"Approval (#th preference) [many entries]"), ";\n",
bsw/jbe@19 125 "voting_text_abstention_single = ", encode.json(_"Abstention [single entry]"), ";\n",
bsw/jbe@19 126 "voting_text_abstention_multi = ", encode.json(_"Abstention [many entries]"), ";\n",
bsw/jbe@19 127 "voting_text_disapproval_above_one_single = ", encode.json(_"Disapproval (prefer to lower block) [single entry]"), ";\n",
bsw/jbe@19 128 "voting_text_disapproval_above_one_multi = ", encode.json(_"Disapproval (prefer to lower block) [many entries]"), ";\n",
bsw/jbe@19 129 "voting_text_disapproval_above_many_single = ", encode.json(_"Disapproval (prefer to lower blocks) [single entry]"), ";\n",
bsw/jbe@19 130 "voting_text_disapproval_above_many_multi = ", encode.json(_"Disapproval (prefer to lower blocks) [many entries]"), ";\n",
bsw/jbe@19 131 "voting_text_disapproval_above_last_single = ", encode.json(_"Disapproval (prefer to last block) [single entry]"), ";\n",
bsw/jbe@19 132 "voting_text_disapproval_above_last_multi = ", encode.json(_"Disapproval (prefer to last block) [many entries]"), ";\n",
bsw/jbe@19 133 "voting_text_disapproval_single = ", encode.json(_"Disapproval [single entry]"), ";\n",
bsw/jbe@19 134 "voting_text_disapproval_multi = ", encode.json(_"Disapproval [many entries]"), ";\n"
bsw/jbe@19 135 )
bsw/jbe@19 136 end
bsw/jbe@19 137 }
bsw/jbe@5 138
bsw@1045 139 if issue.state == "finished_with_winner"
bsw@1045 140 or issue.state == "finished_without_winner"
bsw@1045 141 then
bsw@1045 142
bsw@1045 143 local members_selector = Member:new_selector()
bsw@1045 144 :join("delegating_voter", nil, "delegating_voter.member_id = member.id")
bsw@1045 145 :add_where{ "delegating_voter.issue_id = ?", issue.id }
bsw@1045 146 :add_where{ "delegating_voter.delegate_member_ids[1] = ?", member.id }
bsw@1045 147 :add_field("delegating_voter.weight", "voter_weight")
bsw@1045 148 :join("issue", nil, "issue.id = delegating_voter.issue_id")
bsw@1045 149
bsw@1045 150 ui.sidebar( "tab-members", function()
bsw@1045 151 ui.sidebarHead(function()
bsw@1045 152 ui.heading{ level = 2, content = _"Incoming delegations" }
bsw@1045 153 end)
bsw@1045 154 execute.view{
bsw@1045 155 module = "member",
bsw@1045 156 view = "_list",
bsw@1045 157 params = {
bsw@1045 158 members_selector = members_selector,
bsw@1045 159 trustee = member,
bsw@1045 160 issue = issue,
bsw@1045 161 initiative = initiative,
bsw@1045 162 for_votes = true, no_filter = true,
bsw@1045 163 member_class = "sidebarRow sidebarRowNarrow",
bsw/jbe@5 164 }
bsw@1045 165 }
bsw@1045 166 end)
bsw@1045 167 end
bsw@1045 168
bsw@1045 169
bsw@1045 170 ui.section( function()
bsw@1045 171
bsw@1045 172 ui.sectionHead( function()
bsw@1045 173 if preview then
bsw@1045 174 ui.heading { level = 1, content = _"Preview of voting ballot" }
bsw@1045 175 elseif readonly then
bsw@1045 176 local str = _("Ballot of '#{member_name}'",
bsw@1045 177 {member_name = string.format('<a href="%s">%s</a>',
bsw@1045 178 encode.url{
bsw@1045 179 module = "member",
bsw@1045 180 view = "show",
bsw@1045 181 id = member.id,
bsw@1045 182 },
bsw@1045 183 encode.html(member.name))
bsw@1045 184 }
bsw@1045 185 )
bsw@1045 186 ui.heading { level = 1, content = function () slot.put ( str ) end }
bsw@1045 187 else
bsw@1045 188 ui.heading { level = 1, content = _"Voting" }
bsw/jbe@19 189 end
bsw@1045 190 end )
bsw@1045 191
bsw@1045 192 ui.sectionRow( function()
bsw@1045 193
bsw@1045 194 ui.form{
bsw@1045 195 record = direct_voter,
bsw@1045 196 attr = {
bsw@1045 197 id = "voting_form",
bsw@1045 198 class = readonly and "voting_form_readonly" or "voting_form_active"
bsw@1045 199 },
bsw@1045 200 module = "vote",
bsw@1045 201 action = "update",
bsw@1045 202 params = { issue_id = issue.id },
bsw/jbe@5 203 content = function()
bsw@1045 204 if not readonly or preview then
bsw@1045 205 local scoring = param.get("scoring")
bsw@1045 206 if not scoring then
bsw@1045 207 for i, initiative in ipairs(initiatives) do
bsw@1045 208 local vote = initiative.vote
bsw@1045 209 if vote then
bsw@1045 210 tempvotings[initiative.id] = vote.grade
bsw@1045 211 else
bsw@1045 212 tempvotings[initiative.id] = 0
bsw@1045 213 end
bsw@1045 214 end
bsw@1045 215 local tempvotings_list = {}
bsw@1045 216 for key, val in pairs(tempvotings) do
bsw@1045 217 tempvotings_list[#tempvotings_list+1] = tostring(key) .. ":" .. tostring(val)
bsw@1045 218 end
bsw@1045 219 if #tempvotings_list > 0 then
bsw@1045 220 scoring = table.concat(tempvotings_list, ";")
bsw@1045 221 else
bsw@1045 222 scoring = ""
bsw@1045 223 end
bsw/jbe@5 224 end
bsw@1045 225 slot.put('<input type="hidden" name="scoring" value="' .. scoring .. '"/>')
bsw@1045 226 end
bsw@1045 227 if preview then
bsw@1045 228 ui.heading{ level = 2, content = _"Your choice" }
bsw@1045 229 elseif not readonly then
bsw@1045 230 ui.heading{ level = 2, content = _"Make your choice by placing the initiatives" }
bsw@1045 231 end
bsw@1045 232
bsw@1045 233 ui.container{
bsw@1045 234 attr = { id = "voting" },
bsw@1045 235 content = function()
bsw@1045 236 local approval_index, disapproval_index = 0, 0
bsw@1045 237 for grade = max_grade, min_grade, -1 do
bsw@1045 238 local entries = sections[grade]
bsw@1045 239 local class
bsw@1045 240 if grade > 0 then
bsw@1045 241 class = "approval"
bsw@1045 242 elseif grade < 0 then
bsw@1045 243 class = "disapproval"
bsw@1045 244 else
bsw@1045 245 class = "abstention"
bsw@1045 246 end
bsw@1045 247 if
bsw@1045 248 #entries > 0 or
bsw@1045 249 (grade == 1 and not approval_used) or
bsw@1045 250 (grade == -1 and not disapproval_used) or
bsw@1045 251 grade == 0
bsw@1045 252 then
bsw@1045 253 ui.container{
bsw@1045 254 attr = { class = class },
bsw@1045 255 content = function()
bsw@1045 256 local heading
bsw@1045 257 if class == "approval" then
bsw@1045 258 approval_used = true
bsw@1045 259 approval_index = approval_index + 1
bsw@1045 260 if approval_count > 1 then
bsw@1045 261 if approval_index == 1 then
bsw@1045 262 if #entries == 1 then
bsw@1045 263 heading = _"Approval (first preference) [single entry]"
bsw@1045 264 else
bsw@1045 265 heading = _"Approval (first preference) [many entries]"
bsw@1045 266 end
bsw@1045 267 elseif approval_index == 2 then
bsw@1045 268 if #entries == 1 then
bsw@1045 269 heading = _"Approval (second preference) [single entry]"
bsw@1045 270 else
bsw@1045 271 heading = _"Approval (second preference) [many entries]"
bsw@1045 272 end
bsw@1045 273 elseif approval_index == 3 then
bsw@1045 274 if #entries == 1 then
bsw@1045 275 heading = _"Approval (third preference) [single entry]"
bsw@1045 276 else
bsw@1045 277 heading = _"Approval (third preference) [many entries]"
bsw@1045 278 end
bsw@1045 279 else
bsw@1045 280 if #entries == 1 then
bsw@1045 281 heading = _"Approval (#th preference) [single entry]"
bsw@1045 282 else
bsw@1045 283 heading = _"Approval (#th preference) [many entries]"
bsw@1045 284 end
bsw@1045 285 end
bsw/jbe@19 286 else
bsw@1045 287 if #entries == 1 then
bsw@1045 288 heading = _"Approval [single entry]"
bsw@1045 289 else
bsw@1045 290 heading = _"Approval [many entries]"
bsw@1045 291 end
bsw/jbe@19 292 end
bsw@1045 293 elseif class == "abstention" then
bsw@1045 294 if #entries == 1 then
bsw@1045 295 heading = _"Abstention [single entry]"
bsw@1045 296 else
bsw@1045 297 heading = _"Abstention [many entries]"
bsw@1045 298 end
bsw@1045 299 elseif class == "disapproval" then
bsw@1045 300 disapproval_used = true
bsw@1045 301 disapproval_index = disapproval_index + 1
bsw@1045 302 if disapproval_count > disapproval_index + 1 then
bsw@1045 303 if #entries == 1 then
bsw@1045 304 heading = _"Disapproval (prefer to lower blocks) [single entry]"
bsw@1045 305 else
bsw@1045 306 heading = _"Disapproval (prefer to lower blocks) [many entries]"
bsw@1045 307 end
bsw@1045 308 elseif disapproval_count == 2 and disapproval_index == 1 then
bsw@1045 309 if #entries == 1 then
bsw@1045 310 heading = _"Disapproval (prefer to lower block) [single entry]"
bsw@1045 311 else
bsw@1045 312 heading = _"Disapproval (prefer to lower block) [many entries]"
bsw@1045 313 end
bsw@1045 314 elseif disapproval_index == disapproval_count - 1 then
bsw@1045 315 if #entries == 1 then
bsw@1045 316 heading = _"Disapproval (prefer to last block) [single entry]"
bsw@1045 317 else
bsw@1045 318 heading = _"Disapproval (prefer to last block) [many entries]"
bsw@1045 319 end
bsw/jbe@19 320 else
bsw@1045 321 if #entries == 1 then
bsw@1045 322 heading = _"Disapproval [single entry]"
bsw@1045 323 else
bsw@1045 324 heading = _"Disapproval [many entries]"
bsw@1045 325 end
bsw/jbe@19 326 end
bsw/jbe@19 327 end
bsw@1045 328 ui.tag {
bsw@1045 329 tag = "div",
bsw@1045 330 attr = { class = "cathead" },
bsw@1045 331 content = heading
bsw@1045 332 }
bsw@1045 333 for i, initiative in ipairs(entries) do
bsw/jbe@19 334 ui.container{
bsw@1045 335 attr = {
bsw@1045 336 class = "movable",
bsw@1045 337 id = "entry_" .. tostring(initiative.id)
bsw@1045 338 },
bsw/jbe@19 339 content = function()
bsw@1045 340 local initiators_selector = initiative:get_reference_selector("initiating_members")
bsw@1045 341 :add_where("accepted")
bsw@1045 342 local initiators = initiators_selector:exec()
bsw@1045 343 local initiator_names = {}
bsw@1045 344 for i, initiator in ipairs(initiators) do
bsw@1045 345 initiator_names[#initiator_names+1] = initiator.name
bsw@1045 346 end
bsw@1045 347 local initiator_names_string = table.concat(initiator_names, ", ")
bsw@1045 348 ui.container{
bsw@1045 349 attr = { style = "float: right; position: relative;" },
bsw@1045 350 content = function()
bsw@1045 351 ui.link{
bsw@1045 352 attr = { class = "clickable" },
bsw@1045 353 content = _"Show",
bsw@1045 354 module = "initiative",
bsw@1045 355 view = "show",
bsw@1045 356 id = initiative.id
bsw@1045 357 }
bsw@1045 358 slot.put(" ")
bsw@1045 359 ui.link{
bsw@1045 360 attr = { class = "clickable", target = "_blank" },
bsw@1045 361 content = _"(new window)",
bsw@1045 362 module = "initiative",
bsw@1045 363 view = "show",
bsw@1045 364 id = initiative.id
bsw@1045 365 }
bsw@1045 366 if not readonly then
bsw@1045 367 slot.put(" ")
bsw@1045 368 ui.image{ attr = { class = "grabber" }, static = "icons/grabber.png" }
bsw@1045 369 end
bsw@1045 370 end
bsw/jbe@19 371 }
bsw/jbe@19 372 if not readonly then
bsw@1045 373 ui.container{
bsw@1045 374 attr = { style = "float: left; position: relative;" },
bsw@1045 375 content = function()
bsw@1045 376 ui.tag{
bsw@1045 377 tag = "input",
bsw@1045 378 attr = {
bsw@1045 379 onclick = "if (jsFail) return true; voting_moveUp(this.parentNode.parentNode); return(false);",
bsw@1045 380 name = "move_up_" .. tostring(initiative.id),
bsw@1045 381 class = not disabled and "clickable" or nil,
bsw@1045 382 type = "image",
bsw@1045 383 src = encode.url{ static = "icons/move_up.png" },
bsw@1045 384 alt = _"Move up"
bsw@1045 385 }
bsw@1045 386 }
bsw@1045 387 slot.put("&nbsp;")
bsw@1045 388 ui.tag{
bsw@1045 389 tag = "input",
bsw@1045 390 attr = {
bsw@1045 391 onclick = "if (jsFail) return true; voting_moveDown(this.parentNode.parentNode); return(false);",
bsw@1045 392 name = "move_down_" .. tostring(initiative.id),
bsw@1045 393 class = not disabled and "clickable" or nil,
bsw@1045 394 type = "image",
bsw@1045 395 src = encode.url{ static = "icons/move_down.png" },
bsw@1045 396 alt = _"Move down"
bsw@286 397 }
bsw@286 398 }
bsw@1045 399 slot.put("&nbsp;")
bsw@1045 400 end
bsw/jbe@19 401 }
bsw/jbe@19 402 end
bsw@1045 403 ui.container{
bsw@1045 404 content = function()
bsw@1045 405 ui.tag{ content = "i" .. initiative.id .. ": " }
bsw@1045 406 ui.tag{ content = initiative.shortened_name }
bsw@1045 407 slot.put("<br />")
bsw@1045 408 for i, initiator in ipairs(initiators) do
bsw@1045 409 ui.link{
bsw@1045 410 attr = { class = "clickable" },
bsw@1045 411 content = function ()
bsw@1045 412 execute.view{
bsw@1045 413 module = "member_image",
bsw@1045 414 view = "_show",
bsw@1045 415 params = {
bsw@1045 416 member = initiator,
bsw@1045 417 image_type = "avatar",
bsw@1045 418 show_dummy = true,
bsw@1045 419 class = "micro_avatar",
bsw@1045 420 popup_text = text
bsw@1045 421 }
bsw@1045 422 }
bsw@1045 423 end,
bsw@1045 424 module = "member", view = "show", id = initiator.id
bsw@1045 425 }
bsw@1045 426 slot.put(" ")
bsw@1045 427 ui.tag{ content = initiator.name }
bsw@1045 428 slot.put(" ")
bsw@1045 429 end
bsw@1045 430 end
bsw@1045 431 }
bsw/jbe@19 432 end
bsw/jbe@6 433 }
bsw/jbe@6 434 end
bsw@1045 435 end
bsw@1045 436 }
bsw@1045 437 end
bsw@1045 438 end
bsw@1045 439 end
bsw@1045 440 }
bsw@1045 441 if app.session.member_id and preview then
bsw@1045 442 local formatting_engine = param.get("formatting_engine") or config.enforce_formatting_engine
bsw@1045 443 local comment = param.get("comment")
bsw@1045 444 if comment and #comment > 0 then
bsw@1045 445 local rendered_comment = format.wiki_text(comment, formatting_engine)
bsw@1045 446 ui.heading{ level = "2", content = _"Voting comment" }
bsw@1045 447 ui.container { attr = { class = "member_statement" }, content = function()
bsw@1045 448 slot.put(rendered_comment)
bsw@1045 449 end }
bsw@1045 450 slot.put("<br />")
bsw@1045 451 end
bsw@1045 452 end
bsw@1045 453 if (readonly or direct_voter and direct_voter.comment) and not preview and not (app.session.member_id == member.id) then
bsw@1045 454 local text
bsw@1045 455 if direct_voter and direct_voter.comment_changed then
bsw@1045 456 text = _("Voting comment (last updated: #{timestamp})", { timestamp = format.timestamp(direct_voter.comment_changed) })
bsw@1045 457 elseif direct_voter and direct_voter.comment then
bsw@1045 458 text = _"Voting comment"
bsw@1045 459 end
bsw@1045 460 if text then
bsw@1045 461 ui.heading{ level = "2", content = text }
bsw@1045 462 end
bsw@1045 463 if direct_voter and direct_voter.comment then
bsw@1045 464 local rendered_comment = direct_voter:get_content('html')
bsw@1045 465 ui.container { attr = { class = "member_statement" }, content = function()
bsw@1045 466 slot.put(rendered_comment)
bsw@1045 467 end }
bsw@1045 468 slot.put("<br />")
bsw@1045 469 end
bsw@1045 470 end
bsw@1045 471 if app.session.member_id and app.session.member_id == member.id then
bsw@1045 472 if (not readonly or direct_voter) and not preview then
bsw@1045 473 ui.container{ content = function()
bsw@1045 474 if not config.enforce_formatting_engine then
bsw@1045 475 ui.field.select{
bsw@1045 476 label = _"Wiki engine for statement",
bsw@1045 477 name = "formatting_engine",
bsw@1045 478 foreign_records = config.formatting_engines,
bsw@1045 479 attr = {id = "formatting_engine"},
bsw@1045 480 foreign_id = "id",
bsw@1045 481 foreign_name = "name",
bsw@1045 482 value = param.get("formatting_engine") or direct_voter and direct_voter.formatting_engine
bsw@1045 483 }
bsw@1045 484 end
bsw@1045 485 ui.heading { level = 2, content = _"Voting comment (optional)" }
bsw@1045 486 ui.field.text{
bsw@1045 487 name = "comment",
bsw@1045 488 multiline = true,
bsw@1045 489 value = param.get("comment") or direct_voter and direct_voter.comment,
bsw@1045 490 attr = { style = "height: 10ex; width: 100%;" },
bsw@1045 491 }
bsw@1045 492 end }
bsw@1045 493 end
bsw@1045 494
bsw@1045 495 if preview then
bsw@1045 496 if not config.enforce_formatting_engine then
bsw@1045 497 ui.field.hidden{ name = "formatting_engine", value = param.get("formatting_engine") }
bsw@1045 498 end
bsw@1045 499 ui.field.hidden{ name = "comment", value = param.get("comment") or direct_voter and direct_voter.comment }
bsw@1045 500 end
bsw@1045 501
bsw@1045 502 if not readonly or direct_voter or preview then
bsw@1045 503 ui.container{ content = function()
bsw@1045 504 if preview then
bsw@1045 505 slot.put(" ")
bsw@1045 506 ui.tag{
bsw@1045 507 tag = "input",
bsw@1045 508 attr = {
bsw@1045 509 type = "submit",
bsw@1045 510 class = "btn btn-default",
bsw@1045 511 name = issue.closed and "update_comment" or nil,
bsw@1045 512 value = submit_button_text -- finish voting / update comment
bsw/jbe@19 513 }
bsw@1045 514 }
bsw/jbe@5 515 end
bsw@1045 516 if not preview then
bsw@1045 517 ui.tag{
bsw@1045 518 tag = "input",
bsw@1045 519 attr = {
bsw@1045 520 type = "submit",
bsw@1045 521 name = "preview",
bsw@1045 522 class = "btn btn-default",
bsw@1045 523 value = _"Preview",
bsw@1045 524 }
bsw@1045 525 }
bsw@1045 526 else
bsw@1045 527 slot.put(" ")
bsw@1045 528 ui.tag{
bsw@1045 529 tag = "input",
bsw@1045 530 attr = {
bsw@1045 531 type = "submit",
bsw@1045 532 name = "edit",
bsw@1045 533 class = "btn-link",
bsw@1045 534 value = edit_button_text,
bsw@1045 535 }
bsw@1045 536 }
bsw@1045 537 end
bsw@1045 538 end }
bsw/jbe@19 539 end
bsw/jbe@5 540 end
bsw/jbe@5 541 end
bsw/jbe@5 542 }
bsw@1045 543 slot.put("<br />")
bsw@1045 544 ui.link{
bsw@1045 545 text = _"Cancel",
bsw@1045 546 module = "issue",
bsw@1045 547 view = "show",
bsw@1045 548 id = issue.id
bsw@1045 549 }
bsw@1045 550 if direct_voter then
bsw@1045 551 slot.put(" | ")
bsw@1045 552 ui.link {
bsw@1045 553 module = "vote", action = "update",
bsw@1045 554 params = {
bsw@1045 555 issue_id = issue.id,
bsw@1045 556 discard = true
bsw@1045 557 },
bsw@1045 558 routing = {
bsw@1045 559 default = {
bsw@1045 560 mode = "redirect",
bsw@1045 561 module = "issue",
bsw@1045 562 view = "show",
bsw@1045 563 id = issue.id
bsw@1045 564 }
bsw@1045 565 },
bsw@1045 566 text = _"Discard my vote"
bsw@1045 567 }
bsw@879 568 end
bsw/jbe@5 569
bsw@1045 570 end )
bsw@1045 571 end )

Impressum / About Us