liquid_feedback_frontend

changeset 127:4fb486bce608

add pageinator to issue view.

this "paginator" shows links to the prev/area/next issues that have the same
state then the current one. This helps a lot when inspecting new issues or voting.
The voting filter works a little bit different, as he also activtes the not_voted subfilter
because it is most likely only not voted issues are interessting to the user
author Daniel Poelzleithner <poelzi@poelzi.org>
date Tue Oct 05 04:44:06 2010 +0200 (2010-10-05)
parents 36aedac3e4bf
children 082450e65aa8
files app/main/_layout/default.html app/main/issue/_filters.lua app/main/issue/_list.lua app/main/issue/_show_head.lua static/style.css
line diff
     1.1 --- a/app/main/_layout/default.html	Mon Oct 04 15:52:22 2010 +0200
     1.2 +++ b/app/main/_layout/default.html	Tue Oct 05 04:44:06 2010 +0200
     1.3 @@ -63,6 +63,9 @@
     1.4          <div style="clear: left;"></div>
     1.5        </div>
     1.6      </div>
     1.7 +    <div class="content_navigation" id="content_navigation">
     1.8 +      <!-- WEBMCP SLOT content_navigation -->
     1.9 +    </div>
    1.10      <div class="main" id="default">
    1.11        <!-- WEBMCP SLOT default -->
    1.12      </div>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/app/main/issue/_filters.lua	Tue Oct 05 04:44:06 2010 +0200
     2.3 @@ -0,0 +1,186 @@
     2.4 +local filters = {}
     2.5 +
     2.6 +-- FIXME: the filter should be named like the corresponding issue.state value
     2.7 +
     2.8 +filters[#filters+1] = {
     2.9 +  label = _"Filter",
    2.10 +  name = "filter",
    2.11 +  {
    2.12 +    name = "open",
    2.13 +    label = _"Open",
    2.14 +    selector_modifier = function(selector)
    2.15 +        selector:add_where("issue.closed ISNULL")
    2.16 +    end
    2.17 +  },
    2.18 +  {
    2.19 +    name = "new",
    2.20 +    label = _"New",
    2.21 +    selector_modifier = function(selector)
    2.22 +      selector:add_where("issue.accepted ISNULL AND issue.closed ISNULL")
    2.23 +    end
    2.24 +  },
    2.25 +  {
    2.26 +    name = "accepted",
    2.27 +    label = _"In discussion",
    2.28 +    selector_modifier = function(selector)
    2.29 +      selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL")
    2.30 +    end
    2.31 +  },
    2.32 +  {
    2.33 +    name = "half_frozen",
    2.34 +    label = _"Frozen",
    2.35 +    selector_modifier = function(selector)
    2.36 +      selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL")
    2.37 +    end
    2.38 +  },
    2.39 +  {
    2.40 +    name = "frozen",
    2.41 +    label = _"Voting",
    2.42 +    selector_modifier = function(selector)
    2.43 +      selector:add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL")
    2.44 +      filter_voting = true
    2.45 +    end
    2.46 +  },
    2.47 +  {
    2.48 +    name = "finished",
    2.49 +    label = _"Finished",
    2.50 +    selector_modifier = function(selector)
    2.51 +      selector:add_where("issue.closed NOTNULL AND issue.fully_frozen NOTNULL")
    2.52 +    end
    2.53 +  },
    2.54 +  {
    2.55 +    name = "cancelled",
    2.56 +    label = _"Cancelled",
    2.57 +    selector_modifier = function(selector)
    2.58 +      selector:add_where("issue.closed NOTNULL AND issue.fully_frozen ISNULL")
    2.59 +    end
    2.60 +  },
    2.61 +  {
    2.62 +    name = "any",
    2.63 +    label = _"Any",
    2.64 +    selector_modifier = function(selector) end
    2.65 +  },
    2.66 +}
    2.67 +
    2.68 +
    2.69 +if app.session.member and param.get("filter") == "frozen" then
    2.70 +  filters[#filters+1] = {
    2.71 +    label = _"Filter",
    2.72 +    name = "filter_voting",
    2.73 +    {
    2.74 +      name = "any",
    2.75 +      label = _"Any",
    2.76 +      selector_modifier = function()  end
    2.77 +    },
    2.78 +    {
    2.79 +      name = "not_voted",
    2.80 +      label = _"Not voted",
    2.81 +      selector_modifier = function(selector)
    2.82 +        selector:left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
    2.83 +        selector:add_where("direct_voter.member_id ISNULL")
    2.84 +      end
    2.85 +    },
    2.86 +    {
    2.87 +      name = "voted",
    2.88 +      label = _"Voted",
    2.89 +      selector_modifier = function(selector)
    2.90 +        selector:join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
    2.91 +      end
    2.92 +    },
    2.93 +  }
    2.94 +end
    2.95 +
    2.96 +
    2.97 +filters[#filters+1] = {
    2.98 +  label = _"Filter",
    2.99 +  name = "filter_interest",
   2.100 +  {
   2.101 +    name = "any",
   2.102 +    label = _"Any",
   2.103 +    selector_modifier = function()  end
   2.104 +  },
   2.105 +  {
   2.106 +    name = "my",
   2.107 +    label = _"Interested",
   2.108 +    selector_modifier = function(selector)
   2.109 +      selector:join("interest", "filter_interest", { "filter_interest.issue_id = issue.id AND filter_interest.member_id = ? ", app.session.member.id })
   2.110 +    end
   2.111 +  },
   2.112 +  {
   2.113 +    name = "supported",
   2.114 +    label = _"Supported",
   2.115 +    selector_modifier = function(selector)
   2.116 +      selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? LEFT JOIN opinion ON opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) WHERE initiative.issue_id = issue.id AND opinion.member_id ISNULL LIMIT 1)", app.session.member.id, app.session.member.id })
   2.117 +    end
   2.118 +  },
   2.119 +  {
   2.120 +    name = "potentially_supported",
   2.121 +    label = _"Potential supported",
   2.122 +    selector_modifier = function(selector)
   2.123 +      selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? JOIN opinion ON opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) WHERE initiative.issue_id = issue.id LIMIT 1)", app.session.member.id, app.session.member.id })
   2.124 +    end
   2.125 +  },
   2.126 +  {
   2.127 +    name = "initiated",
   2.128 +    label = _"Initiated",
   2.129 +    selector_modifier = function(selector)
   2.130 +      selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN initiator ON initiator.initiative_id = initiative.id AND initiator.member_id = ? WHERE initiative.issue_id = issue.id)", app.session.member.id })
   2.131 +    end
   2.132 +  },
   2.133 +}
   2.134 +
   2.135 +if not param.get("no_sort", atom.boolean) then
   2.136 +  filters[#filters+1] = {
   2.137 +    label = _"Order by",
   2.138 +    name = "issue_list",
   2.139 +    {
   2.140 +      name = "max_potential_support",
   2.141 +      label = _"Max potential support",
   2.142 +      selector_modifier = function(selector)
   2.143 +        selector:add_order_by("(SELECT max(supporter_count) FROM initiative WHERE initiative.issue_id = issue.id) DESC")
   2.144 +      end
   2.145 +    },
   2.146 +    {
   2.147 +      name = "max_support",
   2.148 +      label = _"Max support",
   2.149 +      selector_modifier = function(selector)
   2.150 +        selector:add_order_by("(SELECT max(satisfied_supporter_count) FROM initiative WHERE initiative.issue_id = issue.id) DESC")
   2.151 +      end
   2.152 +    },
   2.153 +    {
   2.154 +      name = "population",
   2.155 +      label = _"Population",
   2.156 +      selector_modifier = function(selector)
   2.157 +        selector:add_order_by("issue.population DESC")
   2.158 +      end
   2.159 +    },
   2.160 +    {
   2.161 +      name = "newest",
   2.162 +      label = _"Newest",
   2.163 +      selector_modifier = function(selector)
   2.164 +        selector:add_order_by("issue.created DESC")
   2.165 +      end
   2.166 +    },
   2.167 +    {
   2.168 +      name = "oldest",
   2.169 +      label = _"Oldest",
   2.170 +      selector_modifier = function(selector)
   2.171 +        selector:add_order_by("issue.created")
   2.172 +      end
   2.173 +    }
   2.174 +  }
   2.175 +end
   2.176 +
   2.177 +function filters:get_filter(group, name)
   2.178 +  for i,grp in ipairs(self) do
   2.179 +    if grp.name == group then
   2.180 +      for i,entry in ipairs(grp) do
   2.181 +        if entry.name == name then
   2.182 +          return entry
   2.183 +        end
   2.184 +      end
   2.185 +    end
   2.186 +  end
   2.187 +end
   2.188 +
   2.189 +return filters
   2.190 \ No newline at end of file
     3.1 --- a/app/main/issue/_list.lua	Mon Oct 04 15:52:22 2010 +0200
     3.2 +++ b/app/main/issue/_list.lua	Tue Oct 05 04:44:06 2010 +0200
     3.3 @@ -14,175 +14,7 @@
     3.4    "issue_list" 
     3.5  }
     3.6  
     3.7 -local filters = {}
     3.8 -
     3.9 -filters[#filters+1] = {
    3.10 -  label = _"Filter",
    3.11 -  {
    3.12 -    name = "open",
    3.13 -    label = _"Open",
    3.14 -    selector_modifier = function(selector)
    3.15 -        selector:add_where("issue.closed ISNULL")
    3.16 -    end
    3.17 -  },
    3.18 -  {
    3.19 -    name = "new",
    3.20 -    label = _"New",
    3.21 -    selector_modifier = function(selector)
    3.22 -      selector:add_where("issue.accepted ISNULL AND issue.closed ISNULL")
    3.23 -    end
    3.24 -  },
    3.25 -  {
    3.26 -    name = "accepted",
    3.27 -    label = _"In discussion",
    3.28 -    selector_modifier = function(selector)
    3.29 -      selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL")
    3.30 -    end
    3.31 -  },
    3.32 -  {
    3.33 -    name = "half_frozen",
    3.34 -    label = _"Frozen",
    3.35 -    selector_modifier = function(selector)
    3.36 -      selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL")
    3.37 -    end
    3.38 -  },
    3.39 -  {
    3.40 -    name = "frozen",
    3.41 -    label = _"Voting",
    3.42 -    selector_modifier = function(selector)
    3.43 -      selector:add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL")
    3.44 -      filter_voting = true
    3.45 -    end
    3.46 -  },
    3.47 -  {
    3.48 -    name = "finished",
    3.49 -    label = _"Finished",
    3.50 -    selector_modifier = function(selector)
    3.51 -      selector:add_where("issue.closed NOTNULL AND issue.fully_frozen NOTNULL")
    3.52 -    end
    3.53 -  },
    3.54 -  {
    3.55 -    name = "cancelled",
    3.56 -    label = _"Cancelled",
    3.57 -    selector_modifier = function(selector)
    3.58 -      selector:add_where("issue.closed NOTNULL AND issue.fully_frozen ISNULL")
    3.59 -    end
    3.60 -  },
    3.61 -  {
    3.62 -    name = "any",
    3.63 -    label = _"Any",
    3.64 -    selector_modifier = function(selector) end
    3.65 -  },
    3.66 -}
    3.67 -
    3.68 -
    3.69 -if app.session.member and param.get("filter") == "frozen" then
    3.70 -  filters[#filters+1] = {
    3.71 -    label = _"Filter",
    3.72 -    name = "filter_voting",
    3.73 -    {
    3.74 -      name = "any",
    3.75 -      label = _"Any",
    3.76 -      selector_modifier = function()  end
    3.77 -    },
    3.78 -    {
    3.79 -      name = "not_voted",
    3.80 -      label = _"Not voted",
    3.81 -      selector_modifier = function(selector)
    3.82 -        selector:left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
    3.83 -        selector:add_where("direct_voter.member_id ISNULL")
    3.84 -      end
    3.85 -    },
    3.86 -    {
    3.87 -      name = "voted",
    3.88 -      label = _"Voted",
    3.89 -      selector_modifier = function(selector)
    3.90 -        selector:join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
    3.91 -      end
    3.92 -    },
    3.93 -  }
    3.94 -end
    3.95 -
    3.96 -
    3.97 -filters[#filters+1] = {
    3.98 -  label = _"Filter",
    3.99 -  name = "filter_interest",
   3.100 -  {
   3.101 -    name = "any",
   3.102 -    label = _"Any",
   3.103 -    selector_modifier = function()  end
   3.104 -  },
   3.105 -  {
   3.106 -    name = "my",
   3.107 -    label = _"Interested",
   3.108 -    selector_modifier = function(selector)
   3.109 -      selector:join("interest", "filter_interest", { "filter_interest.issue_id = issue.id AND filter_interest.member_id = ? ", app.session.member.id })
   3.110 -    end
   3.111 -  },
   3.112 -  {
   3.113 -    name = "supported",
   3.114 -    label = _"Supported",
   3.115 -    selector_modifier = function(selector)
   3.116 -      selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? LEFT JOIN opinion ON opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) WHERE initiative.issue_id = issue.id AND opinion.member_id ISNULL LIMIT 1)", app.session.member.id, app.session.member.id })
   3.117 -    end
   3.118 -  },
   3.119 -  {
   3.120 -    name = "potentially_supported",
   3.121 -    label = _"Potential supported",
   3.122 -    selector_modifier = function(selector)
   3.123 -      selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? JOIN opinion ON opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) WHERE initiative.issue_id = issue.id LIMIT 1)", app.session.member.id, app.session.member.id })
   3.124 -    end
   3.125 -  },
   3.126 -  {
   3.127 -    name = "initiated",
   3.128 -    label = _"Initiated",
   3.129 -    selector_modifier = function(selector)
   3.130 -      selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN initiator ON initiator.initiative_id = initiative.id AND initiator.member_id = ? WHERE initiative.issue_id = issue.id)", app.session.member.id })
   3.131 -    end
   3.132 -  },
   3.133 -}
   3.134 -
   3.135 -if not param.get("no_sort", atom.boolean) then
   3.136 -  filters[#filters+1] = {
   3.137 -    label = _"Order by",
   3.138 -    name = "issue_list",
   3.139 -    {
   3.140 -      name = "max_potential_support",
   3.141 -      label = _"Max potential support",
   3.142 -      selector_modifier = function(selector)
   3.143 -        selector:add_order_by("(SELECT max(supporter_count) FROM initiative WHERE initiative.issue_id = issue.id) DESC")
   3.144 -      end
   3.145 -    },
   3.146 -    {
   3.147 -      name = "max_support",
   3.148 -      label = _"Max support",
   3.149 -      selector_modifier = function(selector)
   3.150 -        selector:add_order_by("(SELECT max(satisfied_supporter_count) FROM initiative WHERE initiative.issue_id = issue.id) DESC")
   3.151 -      end
   3.152 -    },
   3.153 -    {
   3.154 -      name = "population",
   3.155 -      label = _"Population",
   3.156 -      selector_modifier = function(selector)
   3.157 -        selector:add_order_by("issue.population DESC")
   3.158 -      end
   3.159 -    },
   3.160 -    {
   3.161 -      name = "newest",
   3.162 -      label = _"Newest",
   3.163 -      selector_modifier = function(selector)
   3.164 -        selector:add_order_by("issue.created DESC")
   3.165 -      end
   3.166 -    },
   3.167 -    {
   3.168 -      name = "oldest",
   3.169 -      label = _"Oldest",
   3.170 -      selector_modifier = function(selector)
   3.171 -        selector:add_order_by("issue.created")
   3.172 -      end
   3.173 -    }
   3.174 -  }
   3.175 -end
   3.176 +local filters = execute.load_chunk{module="issue", chunk="_filters.lua"}
   3.177  
   3.178  filters.content = function()
   3.179    local ui_paginate = ui.paginate
     4.1 --- a/app/main/issue/_show_head.lua	Mon Oct 04 15:52:22 2010 +0200
     4.2 +++ b/app/main/issue/_show_head.lua	Tue Oct 05 04:44:06 2010 +0200
     4.3 @@ -37,6 +37,111 @@
     4.4  end)
     4.5  
     4.6  
     4.7 +slot.select("content_navigation", function()
     4.8 +
     4.9 +  if app.session.member_id then
    4.10 +
    4.11 +    local this = 0
    4.12 +    local issues_selector = Issue:new_selector()
    4.13 +
    4.14 +    -- FIXME: !DRY
    4.15 +    local issue_filter_map = {
    4.16 +      new = "new.png",
    4.17 +      accepted = "comments.png",
    4.18 +      half_frozen = "lock.png",
    4.19 +      frozen ="email_open.png",
    4.20 +      finished = "tick.png",
    4.21 +      cancelled = "cross.png",
    4.22 +    }
    4.23 +
    4.24 +
    4.25 +    local mk_link = function(index, text, icon, ltr)
    4.26 +       content = function()
    4.27 +          if ltr then
    4.28 +            slot.put(text)
    4.29 +            ui.image{ static = "icons/16/"..icon }
    4.30 +          else
    4.31 +            ui.image{ static = "icons/16/"..icon }
    4.32 +            slot.put(text)
    4.33 +          end
    4.34 +      end
    4.35 +      if records[this+index] then
    4.36 +        ui.link{
    4.37 +          content = content,
    4.38 +          module = "issue",
    4.39 +          view = "show",
    4.40 +          id = records[this+index].id,
    4.41 +        }
    4.42 +      else
    4.43 +        ui.container{
    4.44 +          content = content,
    4.45 +        }
    4.46 +      end
    4.47 +    end
    4.48 +
    4.49 +    issues_selector
    4.50 +       :add_where{"issue.area_id = ?", issue.area.id}
    4.51 +
    4.52 +    local filters = execute.load_chunk{module="issue", chunk="_filters.lua", params = {filter = "frozen"}}
    4.53 +
    4.54 +    local state = issue.state
    4.55 +
    4.56 +    -- FIXME: fix filter names to reflect issue.state values
    4.57 +    if state == "voting" then
    4.58 +      state = "frozen"
    4.59 +    elseif state == "frozen" then
    4.60 +      state = "half_frozen"
    4.61 +    end
    4.62 +
    4.63 +    filter = filters:get_filter("filter", state)
    4.64 +    if filter then
    4.65 +      filter.selector_modifier(issues_selector)
    4.66 +
    4.67 +      -- add subfilter to voting pager, so only not voted entries will be shown
    4.68 +      -- as this seems the most usefull exception
    4.69 +      if filter.name == "frozen" then
    4.70 +        filter_voting_name = "not_voted"
    4.71 +        local vfilter = filters:get_filter("filter_voting", "not_voted")
    4.72 +        if vfilter then
    4.73 +          vfilter.selector_modifier(issues_selector)
    4.74 +        end
    4.75 +      end
    4.76 +    end
    4.77 +
    4.78 +    records = issues_selector:exec()
    4.79 +
    4.80 +    for i,cissue in ipairs(records) do
    4.81 +      if cissue.id == issue.id then
    4.82 +        this = i
    4.83 +        break
    4.84 +      end
    4.85 +    end
    4.86 +
    4.87 +    mk_link(-1, "Previous", "resultset_previous.png")
    4.88 +    if issue.area then
    4.89 +      ui.link{
    4.90 +        content = function()
    4.91 +          if issue_filter_map[state] then
    4.92 +            ui.image{ static = "icons/16/"..issue_filter_map[state] }
    4.93 +          end
    4.94 +          slot.put(issue.area.name)
    4.95 +        end,
    4.96 +        module = "area",
    4.97 +        view = "show",
    4.98 +        id = issue.area.id,
    4.99 +        params = {
   4.100 +          filter = filter and filter.name or nil,
   4.101 +          filter_voting = filter_voting_name,
   4.102 +          tab = "issues"
   4.103 +        }
   4.104 +      }
   4.105 +    end
   4.106 +    mk_link(1, "Next", "resultset_next.png", 1)
   4.107 +  end
   4.108 +end
   4.109 +
   4.110 +)
   4.111 +
   4.112  slot.select("actions", function()
   4.113  
   4.114    if app.session.member_id then
     5.1 --- a/static/style.css	Mon Oct 04 15:52:22 2010 +0200
     5.2 +++ b/static/style.css	Tue Oct 05 04:44:06 2010 +0200
     5.3 @@ -182,7 +182,6 @@
     5.4  
     5.5  .title_bar {
     5.6    border-bottom: 1px solid #777;
     5.7 -  margin-bottom: 2ex;
     5.8    padding-top: 1ex;
     5.9    padding-bottom: 0.5ex;
    5.10  }
    5.11 @@ -250,6 +249,21 @@
    5.12    vertical-align: middle;
    5.13  }
    5.14  
    5.15 +.content_navigation {
    5.16 +  font-size: 75%;
    5.17 +  background-color: #eee;
    5.18 +  margin-bottom: 2ex;
    5.19 +  padding-left: 1em;
    5.20 +}
    5.21 +
    5.22 +.content_navigation div,
    5.23 +.content_navigation a {
    5.24 +  display: inline-block;
    5.25 +  padding: 3px 0.5em 3px 0.0em;
    5.26 +  margin-right: 1em;
    5.27 +  vertical-align: middle;
    5.28 +}
    5.29 +
    5.30  .actions a:hover {
    5.31    background-color: #d7d7d7;
    5.32  }
    5.33 @@ -265,6 +279,9 @@
    5.34    margin-right: 1em;
    5.35  }
    5.36  
    5.37 +
    5.38 +
    5.39 +
    5.40  /*************************************************************************
    5.41   * vote info / delegation 
    5.42   */

Impressum / About Us