liquid_feedback_frontend

view app/main/timeline/index.lua @ 144:7c3e8a1678fc

fix timeline saved filters

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

Impressum / About Us