liquid_feedback_frontend

view app/main/vote/list.lua @ 20:0a23f39b3e21

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

Impressum / About Us