liquid_feedback_frontend
view app/main/timeline/index.lua @ 89:d68d16371b88
Changed version to beta25
| author | bsw | 
|---|---|
| date | Thu Aug 05 11:56:34 2010 +0200 (2010-08-05) | 
| 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
