liquid_feedback_frontend

annotate app/main/timeline/index.lua @ 227:9245f74e08f5

Added tag beta33 for changeset 4905d7d79486
author bsw
date Tue May 17 12:12:29 2011 +0200 (2011-05-17)
parents 165f4bd02cf3
children
rev   line source
bsw@11 1 execute.view{
bsw@11 2 module = "timeline",
bsw@11 3 view = "_constants"
bsw@11 4 }
bsw@11 5
poelzi@144 6 local active_name = ""
poelzi@145 7 local areas_ignored = {}
bsw@11 8 local options_box_count = param.get("options_box_count", atom.number) or 1
bsw@11 9 if options_box_count > 10 then
bsw@11 10 options_box_count = 10
bsw@11 11 end
bsw@10 12
bsw@10 13 local function format_dow(dow)
bsw@10 14 local dows = {
bsw@10 15 _"Monday",
bsw@10 16 _"Tuesday",
bsw@10 17 _"Wednesday",
bsw@10 18 _"Thursday",
bsw@10 19 _"Friday",
bsw@10 20 _"Saturday",
bsw@10 21 _"Sunday"
bsw@10 22 }
bsw@10 23 return dows[dow+1]
bsw@10 24 end
bsw@11 25 slot.put_into("title", _"Timeline")
bsw@10 26
bsw@11 27 slot.select("actions", function()
bsw@11 28 local setting_key = "liquidfeedback_frontend_timeline_current_options"
bsw@11 29 local setting = Setting:by_pk(app.session.member.id, setting_key)
bsw@11 30 local current_options = ""
bsw@11 31 if setting then
bsw@11 32 current_options = setting.value
bsw@11 33 end
bsw@11 34 local setting_maps = app.session.member:get_setting_maps_by_key("timeline_filters")
bsw@11 35 for i, setting_map in ipairs(setting_maps) do
bsw@11 36 local active
bsw@11 37 local options_string = setting_map.value
bsw@11 38 local name = setting_map.subkey
bsw@11 39 if options_string == current_options then
bsw@11 40 active = true
poelzi@144 41 active_name = name
bsw@11 42 end
bsw@11 43 ui.link{
bsw/jbe@19 44 image = { static = "icons/16/time.png" },
bsw/jbe@19 45 attr = { class = active and "action_active" or nil },
bsw/jbe@19 46 text = name,
poelzi@145 47 form_attr = { class = "inline" },
bsw@11 48 module = 'timeline',
bsw@11 49 action = 'update',
bsw@11 50 params = {
bsw@11 51 options_string = options_string
bsw@11 52 },
bsw@11 53 }
bsw@11 54 end
bsw@11 55 if #setting_maps > 0 then
bsw@11 56 ui.link{
bsw@11 57 content = function()
bsw@11 58 ui.image{ static = "icons/16/wrench.png" }
bsw@11 59 slot.put(_"Manage filter")
bsw@11 60 end,
bsw@11 61 module = "timeline",
bsw@11 62 view = "list_filter",
bsw@11 63 }
bsw@11 64 end
bsw@11 65 ui.link{
bsw@11 66 content = function()
bsw@11 67 ui.image{ static = "icons/16/bullet_disk.png" }
bsw@11 68 slot.put(_"Save current filter")
bsw@11 69 end,
bsw@11 70 module = "timeline",
bsw@11 71 view = "save_filter",
poelzi@144 72 params = {
poelzi@144 73 current_name = active_name
poelzi@144 74 },
bsw@11 75 attr = {
bsw@11 76 onclick = "el=document.getElementById('timeline_save');el.checked=true;el.form.submit();return(false);"
bsw@11 77 }
bsw@11 78 }
bsw@11 79 end)
bsw@10 80
bsw@11 81 util.help("timeline.index", _"Timeline")
bsw@10 82
bsw@10 83 ui.form{
bsw@10 84 module = "timeline",
bsw@11 85 action = "update",
bsw@10 86 content = function()
bsw/jbe@19 87 ui.container{
bsw@11 88
bsw@11 89 content = function()
bsw/jbe@19 90
bsw/jbe@19 91 ui.tag{
bsw/jbe@19 92 tag = "input",
bsw/jbe@19 93 attr = {
bsw/jbe@19 94 type = "radio",
bsw/jbe@19 95 id = "timeline_search_last_24h",
bsw/jbe@19 96 name = "search_from",
bsw/jbe@19 97 value = "last_24h",
bsw/jbe@19 98 checked = param.get("date") == "last_24h" and "checked" or nil
bsw/jbe@19 99 },
bsw@11 100 }
bsw/jbe@19 101
bsw/jbe@19 102 ui.tag{
bsw/jbe@19 103 tag = "label",
bsw/jbe@19 104 attr = {
bsw/jbe@19 105 ["for"] = "timeline_search_last_24h"
bsw/jbe@19 106 },
bsw/jbe@19 107 content = " " .. _"last 24 hours" .. " "
bsw/jbe@19 108 }
bsw/jbe@19 109
bsw/jbe@19 110 ui.tag{
bsw/jbe@19 111 tag = "input",
bsw/jbe@19 112 attr = {
bsw/jbe@19 113 type = "radio",
bsw/jbe@19 114 id = "timeline_search_from_date",
bsw/jbe@19 115 name = "search_from",
bsw/jbe@19 116 value = "date",
bsw/jbe@19 117 checked = not (param.get("date") == "last_24h") and "checked" or nil
bsw/jbe@19 118 },
bsw@11 119 }
bsw@11 120
bsw/jbe@19 121 slot.put(" ")
bsw/jbe@19 122 local current_date = param.get("date")
bsw/jbe@19 123 if not current_date or #current_date == 0 or current_date == "last_24h" then
bsw/jbe@19 124 current_date = tostring(db:query("select now()::date as date")[1].date)
bsw/jbe@19 125 end
bsw/jbe@19 126 ui.tag{
bsw/jbe@19 127 tag = "input",
bsw/jbe@19 128 attr = {
bsw/jbe@19 129 type = "text",
bsw/jbe@19 130 id = "timeline_search_date",
bsw/jbe@19 131 style = "width: 10em;",
bsw/jbe@19 132 onchange = "this.form.submit();",
bsw/jbe@19 133 onclick = "document.getElementById('timeline_search_from_date').checked = true;",
bsw/jbe@19 134 name = "date",
bsw/jbe@19 135 value = current_date
bsw/jbe@19 136 },
bsw/jbe@19 137 content = function() end
bsw/jbe@19 138 }
bsw/jbe@19 139
bsw/jbe@19 140 ui.script{ static = "gregor.js/gregor.js" }
poelzi@146 141 util.gregor("timeline_search_date", true)
bsw/jbe@19 142
bsw/jbe@19 143
bsw/jbe@19 144 ui.link{
bsw/jbe@19 145 attr = { style = "margin-left: 1em; font-weight: bold;", onclick = "document.getElementById('timeline_search_date').form.submit();return(false);" },
bsw/jbe@19 146 content = function()
bsw/jbe@19 147 ui.image{
bsw/jbe@19 148 attr = { style = "margin-right: 0.25em;" },
bsw/jbe@19 149 static = "icons/16/magnifier.png"
bsw/jbe@19 150 }
bsw/jbe@19 151 slot.put(_"Search")
bsw/jbe@19 152 end,
bsw/jbe@19 153 external = "#",
bsw/jbe@19 154 }
bsw/jbe@19 155 local show_options = param.get("show_options", atom.boolean)
bsw/jbe@19 156 ui.link{
bsw/jbe@19 157 attr = { style = "margin-left: 1em;", onclick = "el=document.getElementById('timeline_show_options');el.checked=" .. tostring(not show_options) .. ";el.form.submit();return(false);" },
bsw/jbe@19 158 content = function()
bsw/jbe@19 159 ui.image{
bsw/jbe@19 160 attr = { style = "margin-right: 0.25em;" },
bsw/jbe@19 161 static = "icons/16/text_list_bullets.png"
bsw/jbe@19 162 }
bsw/jbe@19 163 slot.put(not show_options and _"Show filter details" or _"Hide filter details")
bsw/jbe@19 164 end,
bsw/jbe@19 165 external = "#",
bsw/jbe@19 166 }
bsw@11 167
bsw/jbe@19 168 ui.field.boolean{
bsw/jbe@19 169 attr = { id = "timeline_show_options", style = "display: none;", onchange="this.form.submit();" },
bsw/jbe@19 170 name = "show_options",
bsw/jbe@19 171 value = param.get("show_options", atom.boolean)
bsw/jbe@19 172 }
poelzi@144 173 ui.hidden_field{ name = "current_name", value = active_name }
bsw/jbe@19 174 ui.field.boolean{
bsw/jbe@19 175 attr = { id = "timeline_save", style = "display: none;", onchange="this.form.submit();" },
bsw/jbe@19 176 name = "save",
bsw/jbe@19 177 value = false
bsw/jbe@19 178 }
bsw/jbe@19 179
bsw/jbe@19 180 end
bsw@10 181 }
bsw@11 182
bsw@11 183 ui.container{
bsw@11 184 attr = {
bsw@11 185 id = "timeline_options_boxes",
bsw@11 186 class = "vertical",
bsw@11 187 style = not param.get("show_options", atom.boolean) and "display: none;" or nil
bsw@10 188 },
bsw@11 189 content = function()
bsw@11 190
bsw@11 191 local function option_field(event_ident, filter_ident)
bsw@11 192 local param_name
bsw@11 193 if not filter_ident then
bsw@11 194 param_name = "option_" .. event_ident
bsw@11 195 else
bsw@11 196 param_name = "option_" .. event_ident .. "_" .. filter_ident
bsw@11 197 end
bsw@11 198 local value = param.get(param_name, atom.boolean)
bsw@11 199 ui.field.boolean{
bsw@11 200 attr = { id = param_name },
bsw@11 201 name = param_name,
bsw@11 202 value = value,
bsw@11 203 }
bsw@11 204 end
bsw@11 205
bsw@11 206 local function filter_option_fields(event_ident, filter_idents)
bsw@11 207
bsw@11 208 for i, filter_ident in ipairs(filter_idents) do
bsw@11 209 slot.put("<td>")
bsw@11 210 option_field(event_ident, filter_ident)
bsw@11 211 slot.put("</td><td><div class='ui_field_label label_right'>")
bsw@11 212 ui.tag{
bsw@11 213 attr = { ["for"] = "option_" .. event_ident .. "_" .. filter_ident },
bsw@11 214 tag = "label",
bsw@11 215 content = filter_names[filter_ident]
bsw@11 216 }
bsw@11 217 slot.put("</div></td>")
bsw@11 218 end
bsw@11 219
bsw@11 220 end
bsw@10 221
bsw@11 222 local event_groups = {
bsw@11 223 {
bsw@11 224 title = _"Issue events",
bsw@11 225 event_idents = {
bsw@11 226 "issue_created",
bsw@11 227 "issue_canceled",
bsw@11 228 "issue_accepted",
bsw@11 229 "issue_half_frozen",
bsw@11 230 "issue_finished_without_voting",
bsw@11 231 "issue_voting_started",
bsw@11 232 "issue_finished_after_voting",
bsw@11 233 },
bsw@11 234 filter_idents = {
bsw@11 235 "membership",
bsw@11 236 "interested"
bsw@11 237 }
bsw@11 238 },
bsw@11 239 {
bsw@11 240 title = _"Initiative events",
bsw@11 241 event_idents = {
bsw@11 242 "initiative_created",
bsw@11 243 "initiative_revoked",
bsw@11 244 "draft_created",
bsw@11 245 "suggestion_created",
bsw@11 246 },
bsw@11 247 filter_idents = {
bsw@11 248 "membership",
bsw@11 249 "interested",
bsw@11 250 "supporter",
bsw@11 251 "potential_supporter",
bsw@11 252 "initiator"
bsw@11 253 }
bsw@11 254 }
bsw@11 255 }
bsw@11 256
bsw@11 257 slot.put("<table>")
bsw@11 258
bsw@11 259 for i_event_group, event_group in ipairs(event_groups) do
bsw@11 260 slot.put("<tr>")
bsw@11 261 slot.put("<th colspan='2'>")
bsw@11 262 slot.put(event_group.title)
bsw@11 263 slot.put("</th><th colspan='10'>")
bsw@11 264 slot.put(_"Show only events which match... (or associtated)")
bsw@11 265 slot.put("</th>")
bsw@11 266 slot.put("</tr>")
bsw@11 267 local event_idents = event_group.event_idents
bsw@11 268 for i, event_ident in ipairs(event_idents) do
bsw@11 269 slot.put("<tr><td>")
bsw@11 270 option_field(event_ident)
bsw@11 271 slot.put("</td><td><div class='ui_field_label label_right'>")
bsw@11 272 ui.tag{
bsw@11 273 attr = { ["for"] = "option_" .. event_ident },
bsw@11 274 tag = "label",
bsw@11 275 content = event_names[event_ident]
bsw@11 276 }
bsw@11 277 slot.put("</div></td>")
bsw@11 278 filter_option_fields(event_ident, event_group.filter_idents)
bsw@11 279 slot.put("</tr>")
bsw@11 280 end
bsw@11 281 end
bsw@11 282
bsw@11 283 slot.put("</table>")
bsw@11 284
poelzi@145 285 local areas = Area:new_selector():add_where("active='t'"):exec()
poelzi@145 286 for i, area in ipairs(areas) do
poelzi@145 287 if param.get("option_ignore_area_"..tostring(area.id)) then
poelzi@145 288 areas_ignored[#areas_ignored+1] = area.id
poelzi@145 289 end
poelzi@145 290 end
poelzi@145 291
poelzi@145 292 ui.multiselect{
poelzi@145 293 style = "checkbox",
poelzi@145 294 selected_ids = areas_ignored,
poelzi@145 295 container_attr = { class = "ignore_area_list" },
poelzi@145 296 container2_attr = { class = "ignore_area_item" },
poelzi@145 297 label = _"Ignore Areas",
poelzi@145 298 name = "option_ignore_area[]",
poelzi@145 299 foreign_records = areas,
poelzi@145 300 foreign_id = "id",
poelzi@145 301 foreign_name = "name"
poelzi@145 302 }
poelzi@145 303
bsw@11 304 end
bsw@10 305 }
bsw@10 306 end
bsw@10 307 }
bsw@10 308
bsw@10 309 local date = param.get("date")
bsw/jbe@19 310
bsw@11 311 if not date or #date == 0 then
bsw@10 312 date = "today"
bsw@10 313 end
bsw@11 314
bsw@11 315 local timeline_selector
bsw@11 316
bsw@11 317 for event, event_name in pairs(event_names) do
bsw@11 318
bsw@11 319 if param.get("option_" .. event, atom.boolean) then
bsw@11 320
bsw@11 321 local tmp = Timeline:new_selector()
bsw/jbe@19 322 if event == "draft_created" then
bsw/jbe@19 323 tmp
bsw/jbe@19 324 :reset_fields()
bsw/jbe@19 325 :add_field("max(timeline.occurrence)", "occurrence")
bsw/jbe@19 326 :add_field("timeline.event", nil, { "grouped" })
bsw/jbe@19 327 :add_field("timeline.issue_id", nil, { "grouped" })
bsw@41 328 :add_field("draft.initiative_id", nil, { "grouped" })
bsw/jbe@19 329 :add_field("max(timeline.draft_id)", "draft_id")
bsw/jbe@19 330 :add_field("timeline.suggestion_id", nil, { "grouped" })
bsw/jbe@19 331 :add_field("COUNT(*)", "count")
bsw/jbe@19 332 else
bsw/jbe@19 333 tmp
bsw/jbe@19 334 :add_field("1", "count")
bsw/jbe@19 335 end
bsw@11 336
bsw/jbe@19 337 if date == "last_24h" then
bsw/jbe@19 338 tmp:add_where{ "occurrence > now() - '24 hours'::interval" }
bsw/jbe@19 339 else
poelzi@146 340 local start,stop = string.gmatch(date, "(%d+-%d+-%d+):(%d+-%d+-%d+)")()
poelzi@146 341 if start and stop then
poelzi@146 342 tmp:add_where{ "occurrence::date >= ?::date AND occurrence::date <= ?::date", start, stop }
poelzi@146 343 else
poelzi@146 344 local age = string.gmatch(date, "age:(.+)")()
poelzi@146 345 if age then
poelzi@146 346 tmp:add_where{ "occurrence >= now() - ?::interval", age }
poelzi@146 347 else
poelzi@146 348 local since = string.gmatch(date, "since:%s*(%d+-%d+-%d+)%s*")()
poelzi@146 349 if since then
poelzi@146 350 tmp:add_where{ "occurrence::date >= ?::date", since }
poelzi@146 351 else
poelzi@146 352 tmp:add_where{ "occurrence::date = ?::date", date }
poelzi@146 353 end
poelzi@146 354 end
poelzi@146 355 end
bsw/jbe@19 356 end
bsw/jbe@19 357 tmp
bsw/jbe@19 358 :left_join("draft", nil, "draft.id = timeline.draft_id")
bsw/jbe@19 359 :left_join("suggestion", nil, "suggestion.id = timeline.suggestion_id")
bsw/jbe@19 360 :left_join("initiative", nil, "initiative.id = timeline.initiative_id or initiative.id = draft.initiative_id or initiative.id = suggestion.initiative_id")
bsw/jbe@19 361 :left_join("issue", nil, "issue.id = timeline.issue_id or issue.id = initiative.issue_id")
bsw/jbe@19 362 :left_join("area", nil, "area.id = issue.area_id")
bsw@11 363
bsw/jbe@19 364 :left_join("interest", "_interest", { "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id} )
bsw/jbe@19 365 :left_join("initiator", "_initiator", { "_initiator.initiative_id = initiative.id AND _initiator.member_id = ?", app.session.member.id} )
bsw/jbe@19 366 :left_join("membership", "_membership", { "_membership.area_id = area.id AND _membership.member_id = ?", app.session.member.id} )
bsw/jbe@19 367 :left_join("supporter", "_supporter", { "_supporter.initiative_id = initiative.id AND _supporter.member_id = ?", app.session.member.id} )
bsw/jbe@19 368
bsw/jbe@19 369 local group
bsw/jbe@19 370 if event == "draft_created" then
bsw/jbe@19 371 group = { "grouped" }
poelzi@172 372 tmp:add_where{"EXISTS(SELECT 1 from draft as cdraft WHERE draft.initiative_id = cdraft.initiative_id AND cdraft.id != draft.id ORDER BY cdraft.id DESC)"}
bsw/jbe@19 373 end
bsw/jbe@19 374
bsw/jbe@19 375 tmp
bsw/jbe@19 376 :add_field("(_interest.member_id NOTNULL)", "is_interested", group)
bsw/jbe@19 377 :add_field("(_initiator.member_id NOTNULL)", "is_initiator", group)
bsw/jbe@19 378 :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)
bsw/jbe@19 379 :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)
bsw/jbe@19 380 -- :left_join("member", nil, "member.id = timeline.member_id", group)
bsw/jbe@19 381
poelzi@145 382 if #areas_ignored > 0 then
poelzi@145 383 tmp:add_where{"area.id NOT IN ($)", areas_ignored}
poelzi@145 384 end
bsw@11 385
bsw@11 386 tmp:add_where{ "event = ?", event }
bsw@11 387
bsw@11 388 local filters = {}
bsw@11 389 if param.get("option_" .. event .. "_membership", atom.boolean) then
bsw@11 390 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"
bsw@11 391 end
bsw@11 392
bsw@11 393 if param.get("option_" .. event .. "_supporter", atom.boolean) then
bsw@11 394 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))"
bsw@11 395 end
bsw@11 396
bsw@11 397 if param.get("option_" .. event .. "_potential_supporter", atom.boolean) then
bsw@11 398 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))"
bsw@11 399 end
bsw@10 400
bsw@11 401 if param.get("option_" .. event .. "_interested", atom.boolean) then
bsw@11 402 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"
bsw@11 403 end
bsw@11 404
bsw@11 405 if param.get("option_" .. event .. "_initiator", atom.boolean) then
bsw@11 406 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"
bsw@11 407 end
bsw@11 408
bsw@11 409 if #filters > 0 then
bsw@11 410 local filter_string = "(" .. table.concat(filters, ") OR (") .. ")"
bsw/jbe@19 411 tmp:add_where{ filter_string, app.session.member.id, app.session.member.id }
bsw@11 412 end
bsw@11 413
bsw@11 414 if not timeline_selector then
bsw@11 415 timeline_selector = tmp
bsw@11 416 else
bsw@11 417 timeline_selector:union_all(tmp)
bsw@11 418 end
bsw@11 419 end
bsw@11 420 end
bsw@11 421
bsw@11 422 if timeline_selector then
bsw@11 423
bsw@11 424 local initiatives_per_page = param.get("initiatives_per_page", atom.number)
bsw@11 425
bsw@11 426 local outer_timeline_selector = db:new_selector()
bsw@11 427 outer_timeline_selector._class = Timeline
bsw/jbe@19 428 outer_timeline_selector
bsw/jbe@19 429 :add_field{ "timeline.*" }
bsw/jbe@19 430 :from({"($)", { timeline_selector }}, "timeline" )
bsw/jbe@19 431 :add_order_by("occurrence DESC")
bsw/jbe@19 432
bsw@11 433 slot.put("<br />")
bsw@11 434 execute.view{
bsw@11 435 module = "timeline",
bsw@11 436 view = "_list",
bsw@11 437 params = {
bsw@11 438 timeline_selector = outer_timeline_selector,
bsw@11 439 per_page = param.get("per_page", atom.number),
bsw@11 440 event_names = event_names,
bsw@11 441 initiatives_per_page = initiatives_per_page
bsw@11 442 }
bsw@10 443 }
bsw@11 444
bsw@11 445 else
bsw@10 446
bsw@11 447 slot.put(_"No events selected to list")
bsw@11 448
bsw@11 449 end

Impressum / About Us