liquid_feedback_frontend

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

Impressum / About Us