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