liquid_feedback_frontend

view app/main/vote/list.lua @ 158:39d49cf933d8

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

Impressum / About Us