liquid_feedback_frontend

view app/main/vote/list.lua @ 157:24e47baf5f9b

strip html from fallback title

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

Impressum / About Us