liquid_feedback_frontend

view app/main/timeline/index.lua @ 111:bf885faf3452

add initiator support in delegation

if a delegation is issued from the initiative view, the initiators
from that one are added to the delegation target list. this makes it easier to delegate to the author without the need to add him to the contact list.
author Daniel Poelzleithner <poelzi@poelzi.org>
date Mon Sep 20 20:32:04 2010 +0200 (2010-09-20)
parents 53a45356c107
children 7c3e8a1678fc
line source
1 execute.view{
2 module = "timeline",
3 view = "_constants"
4 }
6 local options_box_count = param.get("options_box_count", atom.number) or 1
7 if options_box_count > 10 then
8 options_box_count = 10
9 end
11 local function format_dow(dow)
12 local dows = {
13 _"Monday",
14 _"Tuesday",
15 _"Wednesday",
16 _"Thursday",
17 _"Friday",
18 _"Saturday",
19 _"Sunday"
20 }
21 return dows[dow+1]
22 end
23 slot.put_into("title", _"Timeline")
25 slot.select("actions", function()
26 local setting_key = "liquidfeedback_frontend_timeline_current_options"
27 local setting = Setting:by_pk(app.session.member.id, setting_key)
28 local current_options = ""
29 if setting then
30 current_options = setting.value
31 end
32 local setting_maps = app.session.member:get_setting_maps_by_key("timeline_filters")
33 for i, setting_map in ipairs(setting_maps) do
34 local active
35 local options_string = setting_map.value
36 local name = setting_map.subkey
37 if options_string == current_options then
38 active = true
39 end
40 ui.link{
41 image = { static = "icons/16/time.png" },
42 attr = { class = active and "action_active" or nil },
43 text = name,
44 module = 'timeline',
45 action = 'update',
46 params = {
47 options_string = options_string
48 },
49 }
50 end
51 if #setting_maps > 0 then
52 ui.link{
53 content = function()
54 ui.image{ static = "icons/16/wrench.png" }
55 slot.put(_"Manage filter")
56 end,
57 module = "timeline",
58 view = "list_filter",
59 }
60 end
61 ui.link{
62 content = function()
63 ui.image{ static = "icons/16/bullet_disk.png" }
64 slot.put(_"Save current filter")
65 end,
66 module = "timeline",
67 view = "save_filter",
68 attr = {
69 onclick = "el=document.getElementById('timeline_save');el.checked=true;el.form.submit();return(false);"
70 }
71 }
72 end)
74 util.help("timeline.index", _"Timeline")
76 ui.form{
77 module = "timeline",
78 action = "update",
79 content = function()
81 ui.container{
83 content = function()
85 ui.tag{
86 tag = "input",
87 attr = {
88 type = "radio",
89 id = "timeline_search_last_24h",
90 name = "search_from",
91 value = "last_24h",
92 checked = param.get("date") == "last_24h" and "checked" or nil
93 },
94 }
96 ui.tag{
97 tag = "label",
98 attr = {
99 ["for"] = "timeline_search_last_24h"
100 },
101 content = " " .. _"last 24 hours" .. " "
102 }
104 ui.tag{
105 tag = "input",
106 attr = {
107 type = "radio",
108 id = "timeline_search_from_date",
109 name = "search_from",
110 value = "date",
111 checked = not (param.get("date") == "last_24h") and "checked" or nil
112 },
113 }
115 slot.put(" ")
116 local current_date = param.get("date")
117 if not current_date or #current_date == 0 or current_date == "last_24h" then
118 current_date = tostring(db:query("select now()::date as date")[1].date)
119 end
120 ui.tag{
121 tag = "input",
122 attr = {
123 type = "text",
124 id = "timeline_search_date",
125 style = "width: 10em;",
126 onchange = "this.form.submit();",
127 onclick = "document.getElementById('timeline_search_from_date').checked = true;",
128 name = "date",
129 value = current_date
130 },
131 content = function() end
132 }
134 ui.script{ static = "gregor.js/gregor.js" }
135 util.gregor("timeline_search_date", "document.getElementById('timeline_search_date').form.submit();")
138 ui.link{
139 attr = { style = "margin-left: 1em; font-weight: bold;", onclick = "document.getElementById('timeline_search_date').form.submit();return(false);" },
140 content = function()
141 ui.image{
142 attr = { style = "margin-right: 0.25em;" },
143 static = "icons/16/magnifier.png"
144 }
145 slot.put(_"Search")
146 end,
147 external = "#",
148 }
149 local show_options = param.get("show_options", atom.boolean)
150 ui.link{
151 attr = { style = "margin-left: 1em;", onclick = "el=document.getElementById('timeline_show_options');el.checked=" .. tostring(not show_options) .. ";el.form.submit();return(false);" },
152 content = function()
153 ui.image{
154 attr = { style = "margin-right: 0.25em;" },
155 static = "icons/16/text_list_bullets.png"
156 }
157 slot.put(not show_options and _"Show filter details" or _"Hide filter details")
158 end,
159 external = "#",
160 }
162 ui.field.boolean{
163 attr = { id = "timeline_show_options", style = "display: none;", onchange="this.form.submit();" },
164 name = "show_options",
165 value = param.get("show_options", atom.boolean)
166 }
168 ui.field.boolean{
169 attr = { id = "timeline_save", style = "display: none;", onchange="this.form.submit();" },
170 name = "save",
171 value = false
172 }
174 end
175 }
177 ui.container{
178 attr = {
179 id = "timeline_options_boxes",
180 class = "vertical",
181 style = not param.get("show_options", atom.boolean) and "display: none;" or nil
182 },
183 content = function()
185 local function option_field(event_ident, filter_ident)
186 local param_name
187 if not filter_ident then
188 param_name = "option_" .. event_ident
189 else
190 param_name = "option_" .. event_ident .. "_" .. filter_ident
191 end
192 local value = param.get(param_name, atom.boolean)
193 ui.field.boolean{
194 attr = { id = param_name },
195 name = param_name,
196 value = value,
197 }
198 end
200 local function filter_option_fields(event_ident, filter_idents)
202 for i, filter_ident in ipairs(filter_idents) do
203 slot.put("<td>")
204 option_field(event_ident, filter_ident)
205 slot.put("</td><td><div class='ui_field_label label_right'>")
206 ui.tag{
207 attr = { ["for"] = "option_" .. event_ident .. "_" .. filter_ident },
208 tag = "label",
209 content = filter_names[filter_ident]
210 }
211 slot.put("</div></td>")
212 end
214 end
216 local event_groups = {
217 {
218 title = _"Issue events",
219 event_idents = {
220 "issue_created",
221 "issue_canceled",
222 "issue_accepted",
223 "issue_half_frozen",
224 "issue_finished_without_voting",
225 "issue_voting_started",
226 "issue_finished_after_voting",
227 },
228 filter_idents = {
229 "membership",
230 "interested"
231 }
232 },
233 {
234 title = _"Initiative events",
235 event_idents = {
236 "initiative_created",
237 "initiative_revoked",
238 "draft_created",
239 "suggestion_created",
240 },
241 filter_idents = {
242 "membership",
243 "interested",
244 "supporter",
245 "potential_supporter",
246 "initiator"
247 }
248 }
249 }
251 slot.put("<table>")
253 for i_event_group, event_group in ipairs(event_groups) do
254 slot.put("<tr>")
255 slot.put("<th colspan='2'>")
256 slot.put(event_group.title)
257 slot.put("</th><th colspan='10'>")
258 slot.put(_"Show only events which match... (or associtated)")
259 slot.put("</th>")
260 slot.put("</tr>")
261 local event_idents = event_group.event_idents
262 for i, event_ident in ipairs(event_idents) do
263 slot.put("<tr><td>")
264 option_field(event_ident)
265 slot.put("</td><td><div class='ui_field_label label_right'>")
266 ui.tag{
267 attr = { ["for"] = "option_" .. event_ident },
268 tag = "label",
269 content = event_names[event_ident]
270 }
271 slot.put("</div></td>")
272 filter_option_fields(event_ident, event_group.filter_idents)
273 slot.put("</tr>")
274 end
275 end
277 slot.put("</table>")
279 end
280 }
281 end
282 }
284 local date = param.get("date")
286 if not date or #date == 0 then
287 date = "today"
288 end
290 local timeline_selector
292 for event, event_name in pairs(event_names) do
294 if param.get("option_" .. event, atom.boolean) then
296 local tmp = Timeline:new_selector()
297 if event == "draft_created" then
298 tmp
299 :reset_fields()
300 :add_field("max(timeline.occurrence)", "occurrence")
301 :add_field("timeline.event", nil, { "grouped" })
302 :add_field("timeline.issue_id", nil, { "grouped" })
303 :add_field("draft.initiative_id", nil, { "grouped" })
304 :add_field("max(timeline.draft_id)", "draft_id")
305 :add_field("timeline.suggestion_id", nil, { "grouped" })
306 :add_field("COUNT(*)", "count")
307 else
308 tmp
309 :add_field("1", "count")
310 end
312 if date == "last_24h" then
313 tmp:add_where{ "occurrence > now() - '24 hours'::interval" }
314 else
315 tmp:add_where{ "occurrence::date = ?::date", date }
316 end
317 tmp
318 :left_join("draft", nil, "draft.id = timeline.draft_id")
319 :left_join("suggestion", nil, "suggestion.id = timeline.suggestion_id")
320 :left_join("initiative", nil, "initiative.id = timeline.initiative_id or initiative.id = draft.initiative_id or initiative.id = suggestion.initiative_id")
321 :left_join("issue", nil, "issue.id = timeline.issue_id or issue.id = initiative.issue_id")
322 :left_join("area", nil, "area.id = issue.area_id")
324 :left_join("interest", "_interest", { "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id} )
325 :left_join("initiator", "_initiator", { "_initiator.initiative_id = initiative.id AND _initiator.member_id = ?", app.session.member.id} )
326 :left_join("membership", "_membership", { "_membership.area_id = area.id AND _membership.member_id = ?", app.session.member.id} )
327 :left_join("supporter", "_supporter", { "_supporter.initiative_id = initiative.id AND _supporter.member_id = ?", app.session.member.id} )
329 local group
330 if event == "draft_created" then
331 group = { "grouped" }
332 end
334 tmp
335 :add_field("(_interest.member_id NOTNULL)", "is_interested", group)
336 :add_field("(_initiator.member_id NOTNULL)", "is_initiator", group)
337 :add_field({"(_supporter.member_id NOTNULL) AND NOT EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1)", app.session.member.id }, "is_supporter", group)
338 :add_field({"EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1)", app.session.member.id }, "is_potential_supporter", group)
339 -- :left_join("member", nil, "member.id = timeline.member_id", group)
342 tmp:add_where{ "event = ?", event }
344 local filters = {}
345 if param.get("option_" .. event .. "_membership", atom.boolean) then
346 filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR _membership.member_id NOTNULL"
347 end
349 if param.get("option_" .. event .. "_supporter", atom.boolean) then
350 filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR ((_supporter.member_id NOTNULL) AND NOT EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1))"
351 end
353 if param.get("option_" .. event .. "_potential_supporter", atom.boolean) then
354 filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR ((_supporter.member_id NOTNULL) AND EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1))"
355 end
357 if param.get("option_" .. event .. "_interested", atom.boolean) then
358 filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR _interest.member_id NOTNULL"
359 end
361 if param.get("option_" .. event .. "_initiator", atom.boolean) then
362 filters[#filters+1] = "(timeline.initiative_id ISNULL AND timeline.issue_id ISNULL AND timeline.draft_id ISNULL AND timeline.suggestion_id ISNULL) OR _initiator.member_id NOTNULL"
363 end
365 if #filters > 0 then
366 local filter_string = "(" .. table.concat(filters, ") OR (") .. ")"
367 tmp:add_where{ filter_string, app.session.member.id, app.session.member.id }
368 end
370 if not timeline_selector then
371 timeline_selector = tmp
372 else
373 timeline_selector:union_all(tmp)
374 end
375 end
376 end
378 if timeline_selector then
380 local initiatives_per_page = param.get("initiatives_per_page", atom.number)
382 local outer_timeline_selector = db:new_selector()
383 outer_timeline_selector._class = Timeline
384 outer_timeline_selector
385 :add_field{ "timeline.*" }
386 :from({"($)", { timeline_selector }}, "timeline" )
387 :add_order_by("occurrence DESC")
389 slot.put("<br />")
390 execute.view{
391 module = "timeline",
392 view = "_list",
393 params = {
394 timeline_selector = outer_timeline_selector,
395 per_page = param.get("per_page", atom.number),
396 event_names = event_names,
397 initiatives_per_page = initiatives_per_page
398 }
399 }
401 else
403 slot.put(_"No events selected to list")
405 end

Impressum / About Us