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