bsw/jbe@19: local issue = Issue:by_id(param.get("issue_id"), atom.integer)
bsw/jbe@19:
bsw/jbe@19: local member_id = param.get("member_id", atom.integer)
bsw/jbe@19: local member
bsw/jbe@19:
bsw/jbe@19: local readonly = false
poelzi@156:
bsw/jbe@19: if member_id then
bsw/jbe@19: if not issue.closed then
bsw/jbe@19: error("access denied")
bsw/jbe@19: end
bsw/jbe@19: member = Member:by_id(member_id)
bsw/jbe@19: readonly = true
bsw/jbe@19: end
bsw/jbe@19:
poelzi@138: if issue.closed then
poelzi@156: if not member then
poelzi@156: slot.put_into("error", _"This issue is already closed.")
poelzi@156: end
poelzi@158: if not member then
poelzi@158: member = app.session.member
poelzi@158: end
poelzi@156: readonly = true
poelzi@138: end
poelzi@138:
bsw/jbe@19: if member then
poelzi@156: local str = _("Ballot of '#{member_name}' for issue ##{issue_id}",
poelzi@156: {member_name = string.format('%s',
poelzi@156: encode.url{
poelzi@156: module = "member",
poelzi@156: view = "show",
poelzi@156: id = member.id,
poelzi@156: },
poelzi@156: encode.html(member.name)),
poelzi@156: issue_id = string.format('%s',
poelzi@156: encode.url{
poelzi@156: module = "issue",
poelzi@156: view = "show",
poelzi@156: id = issue.id,
poelzi@156: },
poelzi@156: encode.html(tostring(issue.id)))
poelzi@156: }
poelzi@156: )
poelzi@156: slot.put_into("title", str)
bsw/jbe@19: else
bsw/jbe@19: member = app.session.member
bsw/jbe@19: slot.put_into("title", _"Voting")
bsw/jbe@19:
bsw/jbe@19: slot.select("actions", function()
bsw/jbe@19: ui.link{
bsw/jbe@19: content = function()
bsw/jbe@19: ui.image{ static = "icons/16/cancel.png" }
bsw/jbe@19: slot.put(_"Cancel")
bsw/jbe@19: end,
bsw/jbe@19: module = "issue",
bsw/jbe@19: view = "show",
bsw/jbe@19: id = issue.id
bsw/jbe@19: }
bsw@26: ui.link{
bsw@86: text = _"Discard voting",
bsw@26: content = function()
bsw@26: ui.image{ static = "icons/16/email_delete.png" }
bsw@26: slot.put(_"Discard voting")
bsw@26: end,
bsw@26: module = "vote",
bsw@26: action = "update",
bsw@26: params = {
bsw@26: issue_id = issue.id,
bsw@26: discard = true
bsw@26: },
bsw@26: routing = {
bsw@26: default = {
bsw@26: mode = "redirect",
bsw@26: module = "issue",
bsw@26: view = "show",
bsw@26: id = issue.id
bsw@26: }
bsw@26: }
bsw@26: }
bsw/jbe@19: end)
bsw/jbe@19: end
bsw/jbe@19:
bsw/jbe@19:
jbe@231: local warning_text = _"Some JavaScript based functions (voting in particular) will not work.\nFor this beta, please use a current version of Firefox, Safari, Chrome, Opera(?), Konqueror or another (more) standard compliant browser.\nAlternative access without JavaScript will be available soon."
bsw/jbe@5:
bsw/jbe@5: ui.script{ static = "js/browser_warning.js" }
bsw/jbe@5: ui.script{ script = "checkBrowser(" .. encode.json(_"Your web browser is not fully supported yet." .. " " .. warning_text:gsub("\n", "\n\n")) .. ");" }
bsw/jbe@5:
bsw/jbe@19:
bsw/jbe@19: local tempvoting_string = param.get("scoring")
bsw/jbe@19:
bsw/jbe@19: local tempvotings = {}
bsw/jbe@19: if tempvoting_string then
bsw/jbe@19: for match in tempvoting_string:gmatch("([^;]+)") do
bsw/jbe@19: for initiative_id, grade in match:gmatch("([^:;]+):([^:;]+)") do
bsw/jbe@19: tempvotings[tonumber(initiative_id)] = tonumber(grade)
bsw/jbe@19: end
bsw/jbe@5: end
bsw/jbe@19: end
bsw/jbe@5:
bsw@95: local initiatives = issue:get_reference_selector("initiatives"):add_where("initiative.admitted"):add_order_by("initiative.satisfied_supporter_count DESC"):exec()
bsw/jbe@5:
bsw/jbe@5: local min_grade = -1;
bsw/jbe@5: local max_grade = 1;
bsw/jbe@5:
bsw/jbe@5: for i, initiative in ipairs(initiatives) do
bsw/jbe@5: -- TODO performance
bsw/jbe@19: initiative.vote = Vote:by_pk(initiative.id, member.id)
bsw/jbe@19: if tempvotings[initiative.id] then
bsw/jbe@19: initiative.vote = {}
bsw/jbe@19: initiative.vote.grade = tempvotings[initiative.id]
bsw/jbe@19: end
bsw/jbe@5: if initiative.vote then
bsw/jbe@5: if initiative.vote.grade > max_grade then
bsw/jbe@5: max_grade = initiative.vote.grade
bsw/jbe@5: end
bsw/jbe@5: if initiative.vote.grade < min_grade then
bsw/jbe@5: min_grade = initiative.vote.grade
bsw/jbe@5: end
bsw/jbe@5: end
bsw/jbe@5: end
bsw/jbe@5:
bsw/jbe@5: local sections = {}
bsw/jbe@5: for i = min_grade, max_grade do
bsw/jbe@5: sections[i] = {}
bsw/jbe@5: for j, initiative in ipairs(initiatives) do
bsw/jbe@5: if (initiative.vote and initiative.vote.grade == i) or (not initiative.vote and i == 0) then
bsw/jbe@5: sections[i][#(sections[i])+1] = initiative
bsw/jbe@5: end
bsw/jbe@5: end
bsw/jbe@5: end
bsw/jbe@5:
bsw/jbe@19: local approval_count, disapproval_count = 0, 0
bsw/jbe@19: for i = min_grade, -1 do
bsw/jbe@19: if #sections[i] > 0 then
bsw/jbe@19: disapproval_count = disapproval_count + 1
bsw/jbe@19: end
bsw/jbe@19: end
bsw/jbe@19: local approval_count = 0
bsw/jbe@19: for i = 1, max_grade do
bsw/jbe@19: if #sections[i] > 0 then
bsw/jbe@19: approval_count = approval_count + 1
bsw/jbe@19: end
bsw/jbe@19: end
bsw/jbe@5:
bsw/jbe@5:
bsw/jbe@5:
bsw/jbe@19: if not readonly then
bsw/jbe@19: util.help("vote.list", _"Voting")
bsw/jbe@19: slot.put('')
bsw/jbe@19: slot.put('')
bsw/jbe@19: end
bsw/jbe@19:
bsw/jbe@19: ui.script{
bsw/jbe@19: script = function()
bsw/jbe@19: slot.put(
bsw/jbe@19: "voting_text_approval_single = ", encode.json(_"Approval [single entry]"), ";\n",
bsw/jbe@19: "voting_text_approval_multi = ", encode.json(_"Approval [many entries]"), ";\n",
bsw/jbe@19: "voting_text_first_preference_single = ", encode.json(_"Approval (first preference) [single entry]"), ";\n",
bsw/jbe@19: "voting_text_first_preference_multi = ", encode.json(_"Approval (first preference) [many entries]"), ";\n",
bsw/jbe@19: "voting_text_second_preference_single = ", encode.json(_"Approval (second preference) [single entry]"), ";\n",
bsw/jbe@19: "voting_text_second_preference_multi = ", encode.json(_"Approval (second preference) [many entries]"), ";\n",
bsw/jbe@19: "voting_text_third_preference_single = ", encode.json(_"Approval (third preference) [single entry]"), ";\n",
bsw/jbe@19: "voting_text_third_preference_multi = ", encode.json(_"Approval (third preference) [many entries]"), ";\n",
bsw/jbe@19: "voting_text_numeric_preference_single = ", encode.json(_"Approval (#th preference) [single entry]"), ";\n",
bsw/jbe@19: "voting_text_numeric_preference_multi = ", encode.json(_"Approval (#th preference) [many entries]"), ";\n",
bsw/jbe@19: "voting_text_abstention_single = ", encode.json(_"Abstention [single entry]"), ";\n",
bsw/jbe@19: "voting_text_abstention_multi = ", encode.json(_"Abstention [many entries]"), ";\n",
bsw/jbe@19: "voting_text_disapproval_above_one_single = ", encode.json(_"Disapproval (prefer to lower block) [single entry]"), ";\n",
bsw/jbe@19: "voting_text_disapproval_above_one_multi = ", encode.json(_"Disapproval (prefer to lower block) [many entries]"), ";\n",
bsw/jbe@19: "voting_text_disapproval_above_many_single = ", encode.json(_"Disapproval (prefer to lower blocks) [single entry]"), ";\n",
bsw/jbe@19: "voting_text_disapproval_above_many_multi = ", encode.json(_"Disapproval (prefer to lower blocks) [many entries]"), ";\n",
bsw/jbe@19: "voting_text_disapproval_above_last_single = ", encode.json(_"Disapproval (prefer to last block) [single entry]"), ";\n",
bsw/jbe@19: "voting_text_disapproval_above_last_multi = ", encode.json(_"Disapproval (prefer to last block) [many entries]"), ";\n",
bsw/jbe@19: "voting_text_disapproval_single = ", encode.json(_"Disapproval [single entry]"), ";\n",
bsw/jbe@19: "voting_text_disapproval_multi = ", encode.json(_"Disapproval [many entries]"), ";\n"
bsw/jbe@19: )
bsw/jbe@19: end
bsw/jbe@19: }
bsw/jbe@5:
bsw/jbe@5: ui.form{
bsw/jbe@19: attr = {
bsw/jbe@19: id = "voting_form",
bsw/jbe@19: class = readonly and "voting_form_readonly" or "voting_form_active"
bsw/jbe@19: },
bsw/jbe@5: module = "vote",
bsw/jbe@5: action = "update",
bsw/jbe@5: params = { issue_id = issue.id },
bsw/jbe@5: routing = {
bsw/jbe@5: default = {
bsw/jbe@5: mode = "redirect",
bsw/jbe@5: module = "issue",
bsw/jbe@5: view = "show",
bsw/jbe@5: id = issue.id
bsw/jbe@5: }
bsw/jbe@5: },
bsw/jbe@5: content = function()
bsw/jbe@19: if not readonly then
bsw/jbe@19: local scoring = param.get("scoring")
bsw/jbe@19: if not scoring then
bsw/jbe@19: for i, initiative in ipairs(initiatives) do
bsw/jbe@19: local vote = initiative.vote
bsw/jbe@19: if vote then
bsw/jbe@19: tempvotings[initiative.id] = vote.grade
bsw/jbe@19: end
bsw/jbe@19: end
bsw/jbe@19: local tempvotings_list = {}
bsw/jbe@19: for key, val in pairs(tempvotings) do
bsw/jbe@19: tempvotings_list[#tempvotings_list+1] = tostring(key) .. ":" .. tostring(val)
bsw/jbe@19: end
bsw/jbe@19: if #tempvotings_list > 0 then
bsw/jbe@19: scoring = table.concat(tempvotings_list, ";")
bsw/jbe@19: else
bsw/jbe@19: scoring = ""
bsw/jbe@19: end
bsw/jbe@19: end
bsw/jbe@19: slot.put('')
bsw/jbe@19: -- TODO abstrahieren
bsw/jbe@19: ui.tag{
bsw/jbe@19: tag = "input",
bsw/jbe@19: attr = {
bsw@86: type = "submit",
bsw/jbe@19: class = "voting_done",
bsw/jbe@19: value = _"Finish voting"
bsw/jbe@19: }
bsw/jbe@5: }
bsw/jbe@19: end
bsw/jbe@5: ui.container{
bsw/jbe@5: attr = { id = "voting" },
bsw/jbe@5: content = function()
bsw/jbe@19: local approval_index, disapproval_index = 0, 0
bsw/jbe@5: for grade = max_grade, min_grade, -1 do
bsw/jbe@19: local entries = sections[grade]
bsw/jbe@5: local class
bsw/jbe@5: if grade > 0 then
bsw/jbe@5: class = "approval"
bsw/jbe@5: elseif grade < 0 then
bsw/jbe@5: class = "disapproval"
bsw/jbe@5: else
bsw/jbe@5: class = "abstention"
bsw/jbe@5: end
bsw/jbe@19: if
bsw/jbe@19: #entries > 0 or
bsw/jbe@19: (grade == 1 and not approval_used) or
bsw/jbe@19: (grade == -1 and not disapproval_used) or
bsw/jbe@19: grade == 0
bsw/jbe@19: then
bsw/jbe@19: ui.container{
bsw/jbe@19: attr = { class = class },
bsw/jbe@19: content = function()
bsw/jbe@19: local heading
bsw/jbe@19: if class == "approval" then
bsw/jbe@19: approval_used = true
bsw/jbe@19: approval_index = approval_index + 1
bsw/jbe@19: if approval_count > 1 then
bsw/jbe@19: if approval_index == 1 then
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Approval (first preference) [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Approval (first preference) [many entries]"
bsw/jbe@19: end
bsw/jbe@19: elseif approval_index == 2 then
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Approval (second preference) [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Approval (second preference) [many entries]"
bsw/jbe@19: end
bsw/jbe@19: elseif approval_index == 3 then
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Approval (third preference) [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Approval (third preference) [many entries]"
bsw/jbe@19: end
bsw/jbe@19: else
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Approval (#th preference) [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Approval (#th preference) [many entries]"
bsw/jbe@19: end
bsw/jbe@19: end
bsw/jbe@19: else
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Approval [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Approval [many entries]"
bsw/jbe@19: end
bsw/jbe@19: end
bsw/jbe@19: elseif class == "abstention" then
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Abstention [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Abstention [many entries]"
bsw/jbe@19: end
bsw/jbe@19: elseif class == "disapproval" then
bsw/jbe@19: disapproval_used = true
bsw/jbe@19: disapproval_index = disapproval_index + 1
bsw/jbe@19: if disapproval_count > disapproval_index + 1 then
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Disapproval (prefer to lower blocks) [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Disapproval (prefer to lower blocks) [many entries]"
bsw/jbe@19: end
bsw/jbe@19: elseif disapproval_count == 2 and disapproval_index == 1 then
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Disapproval (prefer to lower block) [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Disapproval (prefer to lower block) [many entries]"
bsw/jbe@19: end
bsw/jbe@19: elseif disapproval_index == disapproval_count - 1 then
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Disapproval (prefer to last block) [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Disapproval (prefer to last block) [many entries]"
bsw/jbe@19: end
bsw/jbe@19: else
bsw/jbe@19: if #entries == 1 then
bsw/jbe@19: heading = _"Disapproval [single entry]"
bsw/jbe@19: else
bsw/jbe@19: heading = _"Disapproval [many entries]"
bsw/jbe@6: end
bsw/jbe@19: end
bsw/jbe@19: end
bsw/jbe@19: ui.tag {
bsw/jbe@19: tag = "div",
bsw/jbe@19: attr = { class = "cathead" },
bsw/jbe@19: content = heading
bsw/jbe@19: }
bsw/jbe@19: for i, initiative in ipairs(entries) do
bsw/jbe@19: ui.container{
bsw/jbe@19: attr = {
bsw/jbe@19: class = "movable",
bsw/jbe@19: id = "entry_" .. tostring(initiative.id)
bsw/jbe@19: },
bsw/jbe@19: content = function()
bsw/jbe@19: local initiators_selector = initiative:get_reference_selector("initiating_members")
bsw/jbe@19: :add_where("accepted")
bsw/jbe@19: local initiators = initiators_selector:exec()
bsw/jbe@19: local initiator_names = {}
bsw/jbe@19: for i, initiator in ipairs(initiators) do
bsw/jbe@19: initiator_names[#initiator_names+1] = initiator.name
bsw/jbe@19: end
bsw/jbe@19: local initiator_names_string = table.concat(initiator_names, ", ")
bsw/jbe@19: ui.container{
bsw/jbe@19: attr = { style = "float: right;" },
bsw/jbe@19: content = function()
bsw/jbe@19: ui.link{
bsw/jbe@19: attr = { class = "clickable" },
bsw/jbe@19: content = _"Show",
bsw/jbe@19: module = "initiative",
bsw/jbe@19: view = "show",
bsw/jbe@19: id = initiative.id
bsw/jbe@19: }
bsw/jbe@19: slot.put(" ")
bsw/jbe@19: ui.link{
bsw/jbe@19: attr = { class = "clickable", target = "_blank" },
bsw/jbe@19: content = _"(new window)",
bsw/jbe@19: module = "initiative",
bsw/jbe@19: view = "show",
bsw/jbe@19: id = initiative.id
bsw/jbe@19: }
bsw/jbe@19: if not readonly then
bsw/jbe@19: slot.put(" ")
bsw/jbe@19: ui.image{ attr = { class = "grabber" }, static = "icons/grabber.png" }
bsw/jbe@19: end
bsw/jbe@19: end
bsw/jbe@19: }
bsw/jbe@19: if not readonly then
bsw/jbe@19: ui.container{
bsw/jbe@19: attr = { style = "float: left;" },
bsw/jbe@19: content = function()
bsw/jbe@19: ui.tag{
bsw/jbe@19: tag = "input",
bsw/jbe@19: attr = {
bsw/jbe@19: onclick = "voting_moveUp(this.parentNode.parentNode); return(false);",
bsw/jbe@19: name = "move_up",
bsw/jbe@19: value = initiative.id,
bsw/jbe@19: class = not disabled and "clickable" or nil,
bsw/jbe@19: type = "image",
bsw/jbe@19: src = encode.url{ static = "icons/move_up.png" },
bsw/jbe@19: alt = _"Move up"
bsw/jbe@19: }
bsw/jbe@19: }
bsw/jbe@19: slot.put(" ")
bsw/jbe@19: ui.tag{
bsw/jbe@19: tag = "input",
bsw/jbe@19: attr = {
bsw/jbe@19: onclick = "voting_moveDown(this.parentNode.parentNode); return(false);",
bsw/jbe@19: name = "move_down",
bsw/jbe@19: value = initiative.id,
bsw/jbe@19: class = not disabled and "clickable" or nil,
bsw/jbe@19: type = "image",
bsw/jbe@19: src = encode.url{ static = "icons/move_down.png" },
bsw/jbe@19: alt = _"Move down"
bsw/jbe@19: }
bsw/jbe@19: }
bsw/jbe@19: slot.put(" ")
bsw/jbe@19: end
bsw/jbe@6: }
bsw/jbe@6: end
bsw/jbe@6: ui.container{
bsw/jbe@19: content = function()
bsw@285: ui.tag{ content = "i" .. initiative.id .. ": " }
bsw@285: ui.tag{ content = initiative.shortened_name }
bsw@286: slot.put("
")
bsw@286: for i, initiator in ipairs(initiators) do
bsw@286: ui.link{
bsw@286: attr = { class = "clickable" },
bsw@286: content = function ()
bsw@286: execute.view{
bsw@286: module = "member_image",
bsw@286: view = "_show",
bsw@286: params = {
bsw@286: member = initiator,
bsw@286: image_type = "avatar",
bsw@286: show_dummy = true,
bsw@286: class = "micro_avatar",
bsw@286: popup_text = text
bsw@286: }
bsw@286: }
bsw@286: end,
bsw@286: module = "member", view = "show", id = initiator.id
bsw/jbe@19: }
bsw@286: slot.put(" ")
bsw@286: ui.link{
bsw@286: attr = { class = "clickable" },
bsw@286: text = initiator.name,
bsw@286: module = "member", view = "show", id = initiator.id
bsw/jbe@19: }
bsw@286: slot.put(" ")
bsw/jbe@19: end
bsw/jbe@19: end
bsw/jbe@6: }
bsw/jbe@6: end
bsw/jbe@19: }
bsw/jbe@19: end
bsw/jbe@5: end
bsw/jbe@19: }
bsw/jbe@19: end
bsw/jbe@5: end
bsw/jbe@5: end
bsw/jbe@5: }
bsw/jbe@19: if not readonly then
bsw/jbe@19: ui.tag{
bsw/jbe@19: tag = "input",
bsw/jbe@19: attr = {
bsw@86: type = "submit",
bsw/jbe@19: class = "voting_done",
bsw/jbe@19: value = _"Finish voting"
bsw/jbe@19: }
bsw/jbe@5: }
bsw/jbe@19: end
bsw/jbe@5: end
bsw/jbe@5: }
bsw/jbe@5:
bsw/jbe@5: