liquid_feedback_frontend

changeset 718:cc64a4fc6ab6

Cleaned up initiative page
author bsw
date Wed Jun 27 14:37:46 2012 +0200 (2012-06-27)
parents 46b94112781d
children 17a33bd0d48a
files app/main/draft/_show.lua app/main/initiative/_battles.lua app/main/initiative/_details.lua app/main/initiative/_show.lua app/main/initiative/_show_voting.lua app/main/initiative/_suggestions.lua app/main/initiative/show.lua app/main/issue/_details.lua app/main/member/_list.lua app/main/suggestion/_list.lua app/main/suggestion/_list_element.lua app/main/suggestion/_suggestion.lua app/main/suggestion/show.lua static/style.css
line diff
     1.1 --- a/app/main/draft/_show.lua	Wed Jun 27 12:35:34 2012 +0200
     1.2 +++ b/app/main/draft/_show.lua	Wed Jun 27 14:37:46 2012 +0200
     1.3 @@ -1,24 +1,16 @@
     1.4  local draft = param.get("draft", "table")
     1.5  local source = param.get("source", atom.boolean)
     1.6  
     1.7 -ui.form{
     1.8 -  attr = { class = "vertical" },
     1.9 -  record = draft,
    1.10 -  readonly = true,
    1.11 +ui.container{
    1.12 +  attr = { class = "draft_content wiki" },
    1.13    content = function()
    1.14 -
    1.15 -    ui.container{
    1.16 -      attr = { class = "draft_content wiki" },
    1.17 -      content = function()
    1.18 -        if source then
    1.19 -          ui.tag{
    1.20 -            tag = "pre",
    1.21 -            content = draft.content
    1.22 -          }
    1.23 -        else
    1.24 -          slot.put(draft:get_content("html"))
    1.25 -        end
    1.26 -      end
    1.27 -    }
    1.28 +    if source then
    1.29 +      ui.tag{
    1.30 +        tag = "pre",
    1.31 +        content = draft.content
    1.32 +      }
    1.33 +    else
    1.34 +      slot.put(draft:get_content("html"))
    1.35 +    end
    1.36    end
    1.37  }
     2.1 --- a/app/main/initiative/_battles.lua	Wed Jun 27 12:35:34 2012 +0200
     2.2 +++ b/app/main/initiative/_battles.lua	Wed Jun 27 14:37:46 2012 +0200
     2.3 @@ -19,11 +19,6 @@
     2.4    :count()
     2.5  
     2.6  if number_of_initiatives > 1 then
     2.7 -  ui.container{
     2.8 -    attr = { class = "heading first" },
     2.9 -    content = _"This initiative compared to alternative initiatives"
    2.10 -  }
    2.11 -
    2.12    ui.list{
    2.13      records = battled_initiatives,
    2.14      columns = {
     3.1 --- a/app/main/initiative/_details.lua	Wed Jun 27 12:35:34 2012 +0200
     3.2 +++ b/app/main/initiative/_details.lua	Wed Jun 27 14:37:46 2012 +0200
     3.3 @@ -1,12 +1,30 @@
     3.4  local initiative = param.get("initiative", "table")
     3.5  
     3.6 -ui.container{ content = _"Initiative details" }
     3.7 -
     3.8  ui.form{
     3.9    attr = { class = "vertical" },
    3.10    record = initiative,
    3.11    readonly = true,
    3.12    content = function()
    3.13 +    if initiative.issue.closed then
    3.14 +      ui.field.boolean{ label = _"Direct majority", value = initiative.direct_majority }
    3.15 +      ui.field.boolean{ label = _"Indirect majority", value = initiative.indirect_majority }
    3.16 +      ui.field.text{ label = _"Schulze rank", value = tostring(initiative.schulze_rank) .. " (" .. _("Status quo: #{rank}", { rank = initiative.issue.status_quo_schulze_rank }) .. ")" }
    3.17 +      local texts = {}
    3.18 +      if initiative.reverse_beat_path then
    3.19 +        texts[#texts+1] = _"reverse beat path to status quo (including ties)"
    3.20 +      end
    3.21 +      if initiative.multistage_majority then
    3.22 +        texts[#texts+1] = _"possibly instable result caused by multistage majority"
    3.23 +      end
    3.24 +      if #texts == 0 then
    3.25 +      texts[#texts+1] = _"none"
    3.26 +      end
    3.27 +      ui.field.text{
    3.28 +        label = _"Other failures",
    3.29 +        value = table.concat(texts, ", ")
    3.30 +      }
    3.31 +      ui.field.boolean{ label = _"Eligible as winner", value = initiative.eligible }
    3.32 +    end
    3.33      ui.field.text{
    3.34        label = _"Created at",
    3.35        value = tostring(initiative.created)
    3.36 @@ -17,10 +35,10 @@
    3.37           value = format.timestamp(initiative.revoked)
    3.38         }
    3.39      end
    3.40 -    ui.field.boolean{ label = _"Admitted", name = "admitted" }
    3.41 +    if initiative.admitted ~= nil then
    3.42 +      ui.field.boolean{ label = _"Admitted", name = "admitted" }
    3.43 +    end
    3.44    end
    3.45  }
    3.46  
    3.47 -ui.container{ content = _"Issue details" }
    3.48 -
    3.49  execute.view{ module = "issue", view = "_details", params = { issue = initiative.issue } }
    3.50 \ No newline at end of file
     4.1 --- a/app/main/initiative/_show.lua	Wed Jun 27 12:35:34 2012 +0200
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,309 +0,0 @@
     4.4 -local initiative = param.get("initiative", "table")
     4.5 -
     4.6 -local initiators_members_selector = initiative:get_reference_selector("initiating_members")
     4.7 -  :add_field("initiator.accepted", "accepted")
     4.8 -  :add_order_by("member.name")
     4.9 -if initiator and initiator.accepted then
    4.10 -  initiators_members_selector:add_where("initiator.accepted ISNULL OR initiator.accepted")
    4.11 -else
    4.12 -  initiators_members_selector:add_where("initiator.accepted")
    4.13 -end
    4.14 -
    4.15 -local initiators = initiators_members_selector:exec()
    4.16 -
    4.17 -
    4.18 -local initiatives_selector = initiative.issue:get_reference_selector("initiatives")
    4.19 -slot.select("head", function()
    4.20 -  execute.view{
    4.21 -    module = "issue",
    4.22 -    view = "_show",
    4.23 -    params = {
    4.24 -      issue = initiative.issue,
    4.25 -      initiative_limit = 3,
    4.26 -      for_initiative = initiative
    4.27 -    }
    4.28 -  }
    4.29 -end)
    4.30 -
    4.31 -ui.container{ attr = { class = "initiative_head" }, content = function()
    4.32 -
    4.33 -  ui.container{
    4.34 -    attr = { class = "title" },
    4.35 -    content = _("Initiative i#{id}: #{name}", { id = initiative.id, name = initiative.name })
    4.36 -  }
    4.37 -
    4.38 -  ui.container{ attr = { class = "content" }, content = function()
    4.39 -    if app.session.member_id or config.public_access == "pseudonym" or config.public_access == "full" then
    4.40 -      ui.tag{
    4.41 -        attr = { class = "initiator_names" },
    4.42 -        content = function()
    4.43 -          for i, initiator in ipairs(initiators) do
    4.44 -            slot.put(" ")
    4.45 -            if app.session.member_id or config.public_access == "full" then
    4.46 -              ui.link{
    4.47 -                content = function ()
    4.48 -                  execute.view{
    4.49 -                    module = "member_image",
    4.50 -                    view = "_show",
    4.51 -                    params = {
    4.52 -                      member = initiator,
    4.53 -                      image_type = "avatar",
    4.54 -                      show_dummy = true,
    4.55 -                      class = "micro_avatar",
    4.56 -                      popup_text = text
    4.57 -                    }
    4.58 -                  }
    4.59 -                end,
    4.60 -                module = "member", view = "show", id = initiator.id
    4.61 -              }
    4.62 -              slot.put(" ")
    4.63 -            end
    4.64 -            ui.link{
    4.65 -              text = initiator.name,
    4.66 -              module = "member", view = "show", id = initiator.id
    4.67 -            }
    4.68 -            if not initiator.accepted then
    4.69 -              ui.tag{ attr = { title = _"Not accepted yet" }, content = "?" }
    4.70 -            end
    4.71 -          end
    4.72 -        end
    4.73 -      }
    4.74 -    end
    4.75 -
    4.76 -    if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
    4.77 -      slot.put(" · ")
    4.78 -      ui.link{
    4.79 -        attr = { class = "action" },
    4.80 -        content = function()
    4.81 -          slot.put(_"Invite initiator")
    4.82 -        end,
    4.83 -        module = "initiative",
    4.84 -        view = "add_initiator",
    4.85 -        params = { initiative_id = initiative.id }
    4.86 -      }
    4.87 -      if #initiators > 1 then
    4.88 -        slot.put(" · ")
    4.89 -        ui.link{
    4.90 -          content = function()
    4.91 -            slot.put(_"Remove initiator")
    4.92 -          end,
    4.93 -          module = "initiative",
    4.94 -          view = "remove_initiator",
    4.95 -          params = { initiative_id = initiative.id }
    4.96 -        }
    4.97 -      end
    4.98 -    end
    4.99 -    if initiator and initiator.accepted == false then
   4.100 -        slot.put(" · ")
   4.101 -        ui.link{
   4.102 -          text   = _"Cancel refuse of invitation",
   4.103 -          module = "initiative",
   4.104 -          action = "remove_initiator",
   4.105 -          params = {
   4.106 -            initiative_id = initiative.id,
   4.107 -            member_id = app.session.member.id
   4.108 -          },
   4.109 -          routing = {
   4.110 -            ok = {
   4.111 -              mode = "redirect",
   4.112 -              module = "initiative",
   4.113 -              view = "show",
   4.114 -              id = initiative.id
   4.115 -            }
   4.116 -          }
   4.117 -        }
   4.118 -    end
   4.119 -  end }
   4.120 -  ui.container{ attr = { class = "content" }, content = function()
   4.121 -    if app.session.member_id then
   4.122 -      execute.view{
   4.123 -        module = "supporter",
   4.124 -        view = "_show_box",
   4.125 -        params = {
   4.126 -          initiative = initiative
   4.127 -        }
   4.128 -      }
   4.129 -    end
   4.130 -
   4.131 -  end }
   4.132 -
   4.133 -  if initiative.issue.ranks_available and initiative.admitted then
   4.134 -    local class = initiative.winner and "admitted_info" or "not_admitted_info"
   4.135 -    ui.container{
   4.136 -      attr = { class = class },
   4.137 -      content = function()
   4.138 -        local max_value = initiative.issue.voter_count
   4.139 -        slot.put(" ")
   4.140 -        local positive_votes = initiative.positive_votes
   4.141 -        local negative_votes = initiative.negative_votes
   4.142 -        local sum_votes = initiative.positive_votes + initiative.negative_votes
   4.143 -        local function perc(votes, sum)
   4.144 -          if sum > 0 and votes > 0 then return " (" .. string.format( "%.f", votes * 100 / sum ) .. "%)" end
   4.145 -          return ""
   4.146 -        end
   4.147 -        slot.put(_"Yes" .. ": <b>" .. tostring(positive_votes) .. perc(positive_votes, sum_votes) .. "</b>")
   4.148 -        slot.put(" &middot; ")
   4.149 -        slot.put(_"Abstention" .. ": <b>" .. tostring(max_value - initiative.negative_votes - initiative.positive_votes)  .. "</b>")
   4.150 -        slot.put(" &middot; ")
   4.151 -        slot.put(_"No" .. ": <b>" .. tostring(initiative.negative_votes) .. perc(negative_votes, sum_votes) .. "</b>")
   4.152 -        slot.put(" &middot; ")
   4.153 -        slot.put("<b>")
   4.154 -        if initiative.winner then
   4.155 -          slot.put(_"Approved")
   4.156 -        elseif initiative.rank then
   4.157 -          slot.put(_("Not approved (rank #{rank})", { rank = initiative.rank }))
   4.158 -        else
   4.159 -          slot.put(_"Not approved")
   4.160 -        end
   4.161 -        slot.put("</b>")
   4.162 -      end
   4.163 -    }
   4.164 -  end
   4.165 -
   4.166 -  if initiative.admitted == false then
   4.167 -    local policy = initiative.issue.policy
   4.168 -    ui.container{
   4.169 -      attr = { class = "not_admitted_info" },
   4.170 -      content = _("This initiative has not been admitted! It failed the quorum of #{quorum}.", { quorum = format.percentage(policy.initiative_quorum_num / policy.initiative_quorum_den) })
   4.171 -    }
   4.172 -  end
   4.173 -
   4.174 -  if initiative.revoked then
   4.175 -    ui.container{
   4.176 -      attr = { class = "revoked_info" },
   4.177 -      content = function()
   4.178 -        slot.put(_("This initiative has been revoked at #{revoked}", { revoked = format.timestamp(initiative.revoked) }))
   4.179 -        local suggested_initiative = initiative.suggested_initiative
   4.180 -        if suggested_initiative then
   4.181 -          slot.put("<br /><br />")
   4.182 -          slot.put(_("The initiators suggest to support the following initiative:"))
   4.183 -          slot.put(" ")
   4.184 -          ui.link{
   4.185 -            content = _("Issue ##{id}", { id = suggested_initiative.issue.id } ) .. ": " .. encode.html(suggested_initiative.name),
   4.186 -            module = "initiative",
   4.187 -            view = "show",
   4.188 -            id = suggested_initiative.id
   4.189 -          }
   4.190 -        end
   4.191 -      end
   4.192 -    }
   4.193 -  end
   4.194 -
   4.195 -end }
   4.196 -
   4.197 -util.help("initiative.show")
   4.198 -
   4.199 -
   4.200 -if initiator and initiator.accepted == nil and not initiative.issue.half_frozen and not initiative.issue.closed then
   4.201 -  ui.container{
   4.202 -    attr = { class = "initiator_invite_info" },
   4.203 -    content = function()
   4.204 -      slot.put(_"You are invited to become initiator of this initiative.")
   4.205 -      slot.put(" ")
   4.206 -      ui.link{
   4.207 -        image  = { static = "icons/16/tick.png" },
   4.208 -        text   = _"Accept invitation",
   4.209 -        module = "initiative",
   4.210 -        action = "accept_invitation",
   4.211 -        id     = initiative.id,
   4.212 -        routing = {
   4.213 -          default = {
   4.214 -            mode = "redirect",
   4.215 -            module = request.get_module(),
   4.216 -            view = request.get_view(),
   4.217 -            id = param.get_id_cgi(),
   4.218 -            params = param.get_all_cgi()
   4.219 -          }
   4.220 -        }
   4.221 -      }
   4.222 -      slot.put(" ")
   4.223 -      ui.link{
   4.224 -        image  = { static = "icons/16/cross.png" },
   4.225 -        text   = _"Refuse invitation",
   4.226 -        module = "initiative",
   4.227 -        action = "reject_initiator_invitation",
   4.228 -        params = {
   4.229 -          initiative_id = initiative.id,
   4.230 -          member_id = app.session.member.id
   4.231 -        },
   4.232 -        routing = {
   4.233 -          default = {
   4.234 -            mode = "redirect",
   4.235 -            module = request.get_module(),
   4.236 -            view = request.get_view(),
   4.237 -            id = param.get_id_cgi(),
   4.238 -            params = param.get_all_cgi()
   4.239 -          }
   4.240 -        }
   4.241 -      }
   4.242 -    end
   4.243 -  }
   4.244 -  slot.put("<br />")
   4.245 -end
   4.246 -
   4.247 -
   4.248 -local supporter
   4.249 -
   4.250 -if app.session.member_id then
   4.251 -  supporter = app.session.member:get_reference_selector("supporters")
   4.252 -    :add_where{ "initiative_id = ?", initiative.id }
   4.253 -    :optional_object_mode()
   4.254 -    :exec()
   4.255 -end
   4.256 -
   4.257 -if supporter and not initiative.issue.closed then
   4.258 -  local old_draft_id = supporter.draft_id
   4.259 -  local new_draft_id = initiative.current_draft.id
   4.260 -  if old_draft_id ~= new_draft_id then
   4.261 -    ui.container{
   4.262 -      attr = { class = "draft_updated_info" },
   4.263 -      content = function()
   4.264 -        slot.put(_"The draft of this initiative has been updated!")
   4.265 -        slot.put(" ")
   4.266 -        ui.link{
   4.267 -          content = _"Show diff",
   4.268 -          module = "draft",
   4.269 -          view = "diff",
   4.270 -          params = {
   4.271 -            old_draft_id = old_draft_id,
   4.272 -            new_draft_id = new_draft_id
   4.273 -          }
   4.274 -        }
   4.275 -        if not initiative.revoked then
   4.276 -          slot.put(" ")
   4.277 -          ui.link{
   4.278 -            text   = _"Refresh support to current draft",
   4.279 -            module = "initiative",
   4.280 -            action = "add_support",
   4.281 -            id     = initiative.id,
   4.282 -            routing = {
   4.283 -              default = {
   4.284 -                mode = "redirect",
   4.285 -                module = "initiative",
   4.286 -                view = "show",
   4.287 -                id = initiative.id
   4.288 -              }
   4.289 -            }
   4.290 -          }
   4.291 -        end
   4.292 -      end
   4.293 -    }
   4.294 -  end
   4.295 -end
   4.296 -
   4.297 -execute.view{
   4.298 -  module = "initiative",
   4.299 -  view = "show_tab",
   4.300 -  params = {
   4.301 -    initiative = initiative,
   4.302 -    initiator = initiator
   4.303 -  }
   4.304 -}
   4.305 -
   4.306 -if initiative.issue.snapshot then
   4.307 -  slot.put("<br />")
   4.308 -  ui.field.timestamp{ label = _"Last snapshot:", value = initiative.issue.snapshot }
   4.309 -end
   4.310 -
   4.311 -
   4.312 -
     5.1 --- a/app/main/initiative/_show_voting.lua	Wed Jun 27 12:35:34 2012 +0200
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,70 +0,0 @@
     5.4 -local initiative = param.get("initiative", "table")
     5.5 -
     5.6 -if initiative.revoked then
     5.7 -  slot.put(_"Not voted (revoked from initiator)")
     5.8 -elseif initiative.admitted == false then
     5.9 -  slot.put(_"Not voted (not admitted)")
    5.10 -else
    5.11 -
    5.12 -  execute.view{
    5.13 -    module = "initiative",
    5.14 -    view = "_battles",
    5.15 -    params = { initiative = initiative }
    5.16 -  }
    5.17 -
    5.18 -  slot.put("<br />")
    5.19 -  
    5.20 -  ui.container{
    5.21 -    attr = { class = "heading" },
    5.22 -    content = _"Member voting"
    5.23 -  }
    5.24 -
    5.25 -  execute.view{
    5.26 -    module = "member",
    5.27 -    view = "_list",
    5.28 -    params = {
    5.29 -      initiative = initiative,
    5.30 -      for_votes = true,
    5.31 -      members_selector =  initiative.issue:get_reference_selector("direct_voters")
    5.32 -        :left_join("vote", nil, { "vote.initiative_id = ? AND vote.member_id = member.id", initiative.id })
    5.33 -        :add_field("direct_voter.weight as voter_weight")
    5.34 -        :add_field("coalesce(vote.grade, 0) as grade")
    5.35 -        :left_join("initiative", nil, "initiative.id = vote.initiative_id")
    5.36 -        :left_join("issue", nil, "issue.id = initiative.issue_id")
    5.37 -    }
    5.38 -  }
    5.39 -
    5.40 -  slot.put("<br />")
    5.41 -  
    5.42 -  ui.container{
    5.43 -    attr = { class = "heading" },
    5.44 -    content = _"Voting details"
    5.45 -  }
    5.46 -  
    5.47 -  ui.form{
    5.48 -    attr = { class = "vertical" },
    5.49 -    content = function()
    5.50 - 
    5.51 -    ui.field.boolean{ label = _"Direct majority", value = initiative.direct_majority }
    5.52 -    ui.field.boolean{ label = _"Indirect majority", value = initiative.indirect_majority }
    5.53 -    ui.field.text{ label = _"Schulze rank", value = tostring(initiative.schulze_rank) .. " (" .. _("Status quo: #{rank}", { rank = initiative.issue.status_quo_schulze_rank }) .. ")" }
    5.54 -    local texts = {}
    5.55 -    if initiative.reverse_beat_path then
    5.56 -      texts[#texts+1] = _"reverse beat path to status quo (including ties)"
    5.57 -    end
    5.58 -    if initiative.multistage_majority then
    5.59 -      texts[#texts+1] = _"possibly instable result caused by multistage majority"
    5.60 -    end
    5.61 -    if #texts == 0 then
    5.62 -     texts[#texts+1] = _"none"
    5.63 -    end
    5.64 -    ui.field.text{
    5.65 -      label = _"Other failures",
    5.66 -      value = table.concat(texts, ", ")
    5.67 -    }
    5.68 -    ui.field.boolean{ label = _"Eligible as winner", value = initiative.eligible }
    5.69 -  end
    5.70 -}
    5.71 -
    5.72 -
    5.73 -end
     6.1 --- a/app/main/initiative/_suggestions.lua	Wed Jun 27 12:35:34 2012 +0200
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,5 +0,0 @@
     6.4 -local initiative = param.get("initiative", "table")
     6.5 -
     6.6 -
     6.7 -
     6.8 -
     7.1 --- a/app/main/initiative/show.lua	Wed Jun 27 12:35:34 2012 +0200
     7.2 +++ b/app/main/initiative/show.lua	Wed Jun 27 14:37:46 2012 +0200
     7.3 @@ -17,11 +17,447 @@
     7.4    }
     7.5  end)
     7.6    
     7.7 +local initiators_members_selector = initiative:get_reference_selector("initiating_members")
     7.8 +  :add_field("initiator.accepted", "accepted")
     7.9 +  :add_order_by("member.name")
    7.10 +if initiator and initiator.accepted then
    7.11 +  initiators_members_selector:add_where("initiator.accepted ISNULL OR initiator.accepted")
    7.12 +else
    7.13 +  initiators_members_selector:add_where("initiator.accepted")
    7.14 +end
    7.15 +
    7.16 +local initiators = initiators_members_selector:exec()
    7.17 +
    7.18 +
    7.19 +local initiatives_selector = initiative.issue:get_reference_selector("initiatives")
    7.20 +slot.select("head", function()
    7.21 +  execute.view{
    7.22 +    module = "issue",
    7.23 +    view = "_show",
    7.24 +    params = {
    7.25 +      issue = initiative.issue,
    7.26 +      initiative_limit = 3,
    7.27 +      for_initiative = initiative
    7.28 +    }
    7.29 +  }
    7.30 +end)
    7.31 +
    7.32 +util.help("initiative.show")
    7.33 +
    7.34 +ui.container{ attr = { class = "initiative_head" }, content = function()
    7.35 +
    7.36 +  ui.container{
    7.37 +    attr = { class = "title" },
    7.38 +    content = _("Initiative i#{id}: #{name}", { id = initiative.id, name = initiative.name })
    7.39 +  }
    7.40 +
    7.41 +  ui.container{ attr = { class = "content" }, content = function()
    7.42 +    if app.session.member_id or config.public_access == "pseudonym" or config.public_access == "full" then
    7.43 +      ui.tag{
    7.44 +        attr = { class = "initiator_names" },
    7.45 +        content = function()
    7.46 +          for i, initiator in ipairs(initiators) do
    7.47 +            slot.put(" ")
    7.48 +            if app.session.member_id or config.public_access == "full" then
    7.49 +              ui.link{
    7.50 +                content = function ()
    7.51 +                  execute.view{
    7.52 +                    module = "member_image",
    7.53 +                    view = "_show",
    7.54 +                    params = {
    7.55 +                      member = initiator,
    7.56 +                      image_type = "avatar",
    7.57 +                      show_dummy = true,
    7.58 +                      class = "micro_avatar",
    7.59 +                      popup_text = text
    7.60 +                    }
    7.61 +                  }
    7.62 +                end,
    7.63 +                module = "member", view = "show", id = initiator.id
    7.64 +              }
    7.65 +              slot.put(" ")
    7.66 +            end
    7.67 +            ui.link{
    7.68 +              text = initiator.name,
    7.69 +              module = "member", view = "show", id = initiator.id
    7.70 +            }
    7.71 +            if not initiator.accepted then
    7.72 +              ui.tag{ attr = { title = _"Not accepted yet" }, content = "?" }
    7.73 +            end
    7.74 +          end
    7.75 +        end
    7.76 +      }
    7.77 +    end
    7.78 +
    7.79 +    if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
    7.80 +      slot.put(" &middot; ")
    7.81 +      ui.link{
    7.82 +        attr = { class = "action" },
    7.83 +        content = function()
    7.84 +          slot.put(_"Invite initiator")
    7.85 +        end,
    7.86 +        module = "initiative",
    7.87 +        view = "add_initiator",
    7.88 +        params = { initiative_id = initiative.id }
    7.89 +      }
    7.90 +      if #initiators > 1 then
    7.91 +        slot.put(" &middot; ")
    7.92 +        ui.link{
    7.93 +          content = function()
    7.94 +            slot.put(_"Remove initiator")
    7.95 +          end,
    7.96 +          module = "initiative",
    7.97 +          view = "remove_initiator",
    7.98 +          params = { initiative_id = initiative.id }
    7.99 +        }
   7.100 +      end
   7.101 +    end
   7.102 +    if initiator and initiator.accepted == false then
   7.103 +        slot.put(" &middot; ")
   7.104 +        ui.link{
   7.105 +          text   = _"Cancel refuse of invitation",
   7.106 +          module = "initiative",
   7.107 +          action = "remove_initiator",
   7.108 +          params = {
   7.109 +            initiative_id = initiative.id,
   7.110 +            member_id = app.session.member.id
   7.111 +          },
   7.112 +          routing = {
   7.113 +            ok = {
   7.114 +              mode = "redirect",
   7.115 +              module = "initiative",
   7.116 +              view = "show",
   7.117 +              id = initiative.id
   7.118 +            }
   7.119 +          }
   7.120 +        }
   7.121 +    end
   7.122 +  end }
   7.123 +  ui.container{ attr = { class = "content" }, content = function()
   7.124 +    if app.session.member_id then
   7.125 +      execute.view{
   7.126 +        module = "supporter",
   7.127 +        view = "_show_box",
   7.128 +        params = {
   7.129 +          initiative = initiative
   7.130 +        }
   7.131 +      }
   7.132 +    end
   7.133 +
   7.134 +  end }
   7.135 +
   7.136 +  
   7.137 +  -- voting results
   7.138 +  if initiative.issue.ranks_available and initiative.admitted then
   7.139 +    local class = initiative.winner and "admitted_info" or "not_admitted_info"
   7.140 +    ui.container{
   7.141 +      attr = { class = class },
   7.142 +      content = function()
   7.143 +        local max_value = initiative.issue.voter_count
   7.144 +        slot.put("&nbsp;")
   7.145 +        local positive_votes = initiative.positive_votes
   7.146 +        local negative_votes = initiative.negative_votes
   7.147 +        local sum_votes = initiative.positive_votes + initiative.negative_votes
   7.148 +        local function perc(votes, sum)
   7.149 +          if sum > 0 and votes > 0 then return " (" .. string.format( "%.f", votes * 100 / sum ) .. "%)" end
   7.150 +          return ""
   7.151 +        end
   7.152 +        slot.put(_"Yes" .. ": <b>" .. tostring(positive_votes) .. perc(positive_votes, sum_votes) .. "</b>")
   7.153 +        slot.put(" &middot; ")
   7.154 +        slot.put(_"Abstention" .. ": <b>" .. tostring(max_value - initiative.negative_votes - initiative.positive_votes)  .. "</b>")
   7.155 +        slot.put(" &middot; ")
   7.156 +        slot.put(_"No" .. ": <b>" .. tostring(initiative.negative_votes) .. perc(negative_votes, sum_votes) .. "</b>")
   7.157 +        slot.put(" &middot; ")
   7.158 +        slot.put("<b>")
   7.159 +        if initiative.winner then
   7.160 +          slot.put(_"Approved")
   7.161 +        elseif initiative.rank then
   7.162 +          slot.put(_("Not approved (rank #{rank})", { rank = initiative.rank }))
   7.163 +        else
   7.164 +          slot.put(_"Not approved")
   7.165 +        end
   7.166 +        slot.put("</b>")
   7.167 +      end
   7.168 +    }
   7.169 +  end
   7.170 +
   7.171 +  ui.container{ attr = { class = "content" }, content = function()
   7.172 +    execute.view{
   7.173 +      module = "initiative",
   7.174 +      view = "_battles",
   7.175 +      params = { initiative = initiative }
   7.176 +    }
   7.177 +  end }
   7.178 +    
   7.179 +  -- initiative not admitted info
   7.180 +  if initiative.admitted == false then
   7.181 +    local policy = initiative.issue.policy
   7.182 +    ui.container{
   7.183 +      attr = { class = "not_admitted_info" },
   7.184 +      content = _("This initiative has not been admitted! It failed the quorum of #{quorum}.", { quorum = format.percentage(policy.initiative_quorum_num / policy.initiative_quorum_den) })
   7.185 +    }
   7.186 +  end
   7.187 +
   7.188 +  -- initiative revoked info
   7.189 +  if initiative.revoked then
   7.190 +    ui.container{
   7.191 +      attr = { class = "revoked_info" },
   7.192 +      content = function()
   7.193 +        slot.put(_("This initiative has been revoked at #{revoked}", { revoked = format.timestamp(initiative.revoked) }))
   7.194 +        local suggested_initiative = initiative.suggested_initiative
   7.195 +        if suggested_initiative then
   7.196 +          slot.put("<br /><br />")
   7.197 +          slot.put(_("The initiators suggest to support the following initiative:"))
   7.198 +          slot.put(" ")
   7.199 +          ui.link{
   7.200 +            content = _("Issue ##{id}", { id = suggested_initiative.issue.id } ) .. ": " .. encode.html(suggested_initiative.name),
   7.201 +            module = "initiative",
   7.202 +            view = "show",
   7.203 +            id = suggested_initiative.id
   7.204 +          }
   7.205 +        end
   7.206 +      end
   7.207 +    }
   7.208 +  end
   7.209 +
   7.210 +
   7.211 +  -- invited as initiator
   7.212 +  if initiator and initiator.accepted == nil and not initiative.issue.half_frozen and not initiative.issue.closed then
   7.213 +    ui.container{
   7.214 +      attr = { class = "initiator_invite_info" },
   7.215 +      content = function()
   7.216 +        slot.put(_"You are invited to become initiator of this initiative.")
   7.217 +        slot.put(" ")
   7.218 +        ui.link{
   7.219 +          image  = { static = "icons/16/tick.png" },
   7.220 +          text   = _"Accept invitation",
   7.221 +          module = "initiative",
   7.222 +          action = "accept_invitation",
   7.223 +          id     = initiative.id,
   7.224 +          routing = {
   7.225 +            default = {
   7.226 +              mode = "redirect",
   7.227 +              module = request.get_module(),
   7.228 +              view = request.get_view(),
   7.229 +              id = param.get_id_cgi(),
   7.230 +              params = param.get_all_cgi()
   7.231 +            }
   7.232 +          }
   7.233 +        }
   7.234 +        slot.put(" ")
   7.235 +        ui.link{
   7.236 +          image  = { static = "icons/16/cross.png" },
   7.237 +          text   = _"Refuse invitation",
   7.238 +          module = "initiative",
   7.239 +          action = "reject_initiator_invitation",
   7.240 +          params = {
   7.241 +            initiative_id = initiative.id,
   7.242 +            member_id = app.session.member.id
   7.243 +          },
   7.244 +          routing = {
   7.245 +            default = {
   7.246 +              mode = "redirect",
   7.247 +              module = request.get_module(),
   7.248 +              view = request.get_view(),
   7.249 +              id = param.get_id_cgi(),
   7.250 +              params = param.get_all_cgi()
   7.251 +            }
   7.252 +          }
   7.253 +        }
   7.254 +      end
   7.255 +    }
   7.256 +  end
   7.257 +
   7.258 +  -- draft updated
   7.259 +  local supporter
   7.260 +
   7.261 +  if app.session.member_id then
   7.262 +    supporter = app.session.member:get_reference_selector("supporters")
   7.263 +      :add_where{ "initiative_id = ?", initiative.id }
   7.264 +      :optional_object_mode()
   7.265 +      :exec()
   7.266 +  end
   7.267 +
   7.268 +  if supporter and not initiative.issue.closed then
   7.269 +    local old_draft_id = supporter.draft_id
   7.270 +    local new_draft_id = initiative.current_draft.id
   7.271 +    if old_draft_id ~= new_draft_id then
   7.272 +      ui.container{
   7.273 +        attr = { class = "draft_updated_info" },
   7.274 +        content = function()
   7.275 +          slot.put(_"The draft of this initiative has been updated!")
   7.276 +          slot.put(" ")
   7.277 +          ui.link{
   7.278 +            content = _"Show diff",
   7.279 +            module = "draft",
   7.280 +            view = "diff",
   7.281 +            params = {
   7.282 +              old_draft_id = old_draft_id,
   7.283 +              new_draft_id = new_draft_id
   7.284 +            }
   7.285 +          }
   7.286 +          if not initiative.revoked then
   7.287 +            slot.put(" ")
   7.288 +            ui.link{
   7.289 +              text   = _"Refresh support to current draft",
   7.290 +              module = "initiative",
   7.291 +              action = "add_support",
   7.292 +              id     = initiative.id,
   7.293 +              routing = {
   7.294 +                default = {
   7.295 +                  mode = "redirect",
   7.296 +                  module = "initiative",
   7.297 +                  view = "show",
   7.298 +                  id = initiative.id
   7.299 +                }
   7.300 +              }
   7.301 +            }
   7.302 +          end
   7.303 +        end
   7.304 +      }
   7.305 +    end
   7.306 +  end
   7.307 +
   7.308 +
   7.309 +  execute.view{
   7.310 +    module = "draft",
   7.311 +    view = "_show",
   7.312 +    params = {
   7.313 +      draft = initiative.current_draft
   7.314 +    }
   7.315 +  }
   7.316 +  
   7.317 +end }
   7.318 +
   7.319 +execute.view{
   7.320 +  module = "suggestion",
   7.321 +  view = "_list",
   7.322 +  params = {
   7.323 +    initiative = initiative,
   7.324 +    suggestions_selector = initiative:get_reference_selector("suggestions"),
   7.325 +    tab_id = param.get("tab_id")
   7.326 +  }
   7.327 +}
   7.328 +
   7.329 +
   7.330 +if config.public_access == "full" or app.session.member_id then
   7.331 +  if initiative.issue.ranks_available then
   7.332 +    local members_selector = initiative.issue:get_reference_selector("direct_voters")
   7.333 +          :left_join("vote", nil, { "vote.initiative_id = ? AND vote.member_id = member.id", initiative.id })
   7.334 +          :add_field("direct_voter.weight as voter_weight")
   7.335 +          :add_field("coalesce(vote.grade, 0) as grade")
   7.336 +          :left_join("initiative", nil, "initiative.id = vote.initiative_id")
   7.337 +          :left_join("issue", nil, "issue.id = initiative.issue_id")
   7.338 +          
   7.339 +    ui.container{ attr = { class = "heading"}, content = _"Member voting" }
   7.340 +    
   7.341 +    execute.view{
   7.342 +      module = "member",
   7.343 +      view = "_list",
   7.344 +      params = {
   7.345 +        initiative = initiative,
   7.346 +        for_votes = true,
   7.347 +        members_selector = members_selector
   7.348 +      }
   7.349 +    }
   7.350 +  end
   7.351 +  
   7.352 +  local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
   7.353 +            :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
   7.354 +            :join("direct_interest_snapshot", nil, "direct_interest_snapshot.event = issue.latest_snapshot_event AND direct_interest_snapshot.issue_id = issue.id AND direct_interest_snapshot.member_id = member.id")
   7.355 +            :add_field("direct_interest_snapshot.weight")
   7.356 +            :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
   7.357 +            :add_where("direct_supporter_snapshot.satisfied")
   7.358 +            :add_field("direct_supporter_snapshot.informed", "is_informed")
   7.359 +
   7.360 +
   7.361 +
   7.362 +  if members_selector:count() > 0 then
   7.363 +    if issue.fully_frozen then
   7.364 +      ui.container{ attr = { class = "heading"}, content = _"Supporters (before begin of voting)" }
   7.365 +    else
   7.366 +      ui.container{ attr = { class = "heading"}, content = _"Supporters" }
   7.367 +    end      
   7.368 +    
   7.369 +    execute.view{
   7.370 +      module = "member",
   7.371 +      view = "_list",
   7.372 +      params = {
   7.373 +        
   7.374 +        initiative = initiative,
   7.375 +        members_selector = members_selector
   7.376 +      }
   7.377 +  }
   7.378 +  else
   7.379 +    if issue.fully_frozen then
   7.380 +      ui.container{ attr = { class = "heading"}, content = _"No supporters (before begin of voting)" }
   7.381 +    else
   7.382 +      ui.container{ attr = { class = "heading"}, content = _"No supporters" }
   7.383 +    end
   7.384 +    slot.put("<br />")
   7.385 +  end
   7.386 +
   7.387 +  local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
   7.388 +            :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
   7.389 +            :join("direct_interest_snapshot", nil, "direct_interest_snapshot.event = issue.latest_snapshot_event AND direct_interest_snapshot.issue_id = issue.id AND direct_interest_snapshot.member_id = member.id")
   7.390 +            :add_field("direct_interest_snapshot.weight")
   7.391 +            :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
   7.392 +            :add_where("NOT direct_supporter_snapshot.satisfied")
   7.393 +            :add_field("direct_supporter_snapshot.informed", "is_informed")
   7.394 +
   7.395 +
   7.396 +  if members_selector:count() > 0 then
   7.397 +    if issue.fully_frozen then
   7.398 +      ui.container{ attr = { class = "heading"}, content = _"Potential supporters (before begin of voting" }
   7.399 +    else
   7.400 +      ui.container{ attr = { class = "heading"}, content = _"Potential supporters" }
   7.401 +    end
   7.402 +              
   7.403 +    execute.view{
   7.404 +      module = "member",
   7.405 +      view = "_list",
   7.406 +      params = {
   7.407 +        
   7.408 +        initiative = initiative,
   7.409 +        members_selector = members_selector
   7.410 +      }
   7.411 +    }
   7.412 +  else
   7.413 +    if issue.fully_frozen then
   7.414 +      ui.container{ attr = { class = "heading"}, content = _"No potential supporters (before begin of voting)" }
   7.415 +    else
   7.416 +      ui.container{ attr = { class = "heading"}, content = _"No potential supporters" }
   7.417 +    end
   7.418 +    slot.put("<br />")
   7.419 +  end
   7.420 +  
   7.421 +  ui.container{ attr = { class = "heading"}, content = _"Details" }
   7.422 +  execute.view {
   7.423 +    module = "initiative",
   7.424 +    view = "_details",
   7.425 +    params = {
   7.426 +      initiative = initiative,
   7.427 +      members_selector = members_selector
   7.428 +    }
   7.429 +  }
   7.430 +
   7.431 +end
   7.432 +
   7.433 +
   7.434 +--[[
   7.435  execute.view{
   7.436    module = "initiative",
   7.437 -  view = "_show",
   7.438 +  view = "show_tab",
   7.439    params = {
   7.440      initiative = initiative,
   7.441      initiator = initiator
   7.442    }
   7.443  }
   7.444 +
   7.445 +if initiative.issue.snapshot then
   7.446 +  slot.put("<br />")
   7.447 +  ui.field.timestamp{ label = _"Last snapshot:", value = initiative.issue.snapshot }
   7.448 +end
   7.449 +
   7.450 +
   7.451 +--]]
     8.1 --- a/app/main/issue/_details.lua	Wed Jun 27 12:35:34 2012 +0200
     8.2 +++ b/app/main/issue/_details.lua	Wed Jun 27 14:37:46 2012 +0200
     8.3 @@ -7,7 +7,7 @@
     8.4    attr = { class = "vertical" },
     8.5    content = function()
     8.6      ui.field.text{       label = _"Population",            name = "population" }
     8.7 -    ui.field.text{       label = _"State",                 name = "state" }
     8.8 +    ui.field.text{       label = _"State",                 name = "state_name" }
     8.9      ui.field.timestamp{  label = _"Created at",            name = "created" }
    8.10      ui.field.text{       label = _"Admission time",        value = issue.admission_time }
    8.11      ui.field.text{
    8.12 @@ -20,9 +20,13 @@
    8.13          value = math.ceil(issue.population * policy.issue_quorum_num / policy.issue_quorum_den)
    8.14        }
    8.15      end
    8.16 -    ui.field.timestamp{  label = _"Accepted at",           name = "accepted" }
    8.17 +    if issue.accepted then
    8.18 +      ui.field.timestamp{  label = _"Accepted at",           name = "accepted" }
    8.19 +    end
    8.20      ui.field.text{       label = _"Discussion time",       value = issue.discussion_time }
    8.21 -    ui.field.timestamp{  label = _"Half frozen at",        name = "half_frozen" }
    8.22 +    if issue.half_frozen then
    8.23 +      ui.field.timestamp{  label = _"Half frozen at",        name = "half_frozen" }
    8.24 +    end
    8.25      ui.field.text{       label = _"Verification time",     value = issue.verification_time }
    8.26      ui.field.text{
    8.27        label   = _"Initiative quorum",
    8.28 @@ -34,9 +38,13 @@
    8.29          value = math.ceil(issue.population * (issue.policy.initiative_quorum_num / issue.policy.initiative_quorum_den)),
    8.30        }
    8.31      end
    8.32 -    ui.field.timestamp{  label = _"Fully frozen at",       name = "fully_frozen" }
    8.33 +    if issue.fully_frozen then
    8.34 +      ui.field.timestamp{  label = _"Fully frozen at",       name = "fully_frozen" }
    8.35 +    end
    8.36      ui.field.text{       label = _"Voting time",           value = issue.voting_time }
    8.37 -    ui.field.timestamp{  label = _"Closed",                name = "closed" }
    8.38 +    if issue.closed then
    8.39 +      ui.field.timestamp{  label = _"Closed",                name = "closed" }
    8.40 +    end
    8.41    end
    8.42  }
    8.43  ui.form{
     9.1 --- a/app/main/member/_list.lua	Wed Jun 27 12:35:34 2012 +0200
     9.2 +++ b/app/main/member/_list.lua	Wed Jun 27 14:37:46 2012 +0200
     9.3 @@ -22,19 +22,6 @@
     9.4  local filter = { name = "member_list" }
     9.5  
     9.6  if issue or initiative then
     9.7 -  if for_votes then
     9.8 -    filter[#filter+1] = {
     9.9 -      name = "delegations",
    9.10 -      label = _"Delegations",
    9.11 -      selector_modifier = function(selector) selector:add_order_by("voter_weight DESC") end
    9.12 -    }
    9.13 -  else
    9.14 -    filter[#filter+1] = {
    9.15 -      name = "delegations",
    9.16 -      label = _"Delegations",
    9.17 -      selector_modifier = function(selector) selector:add_order_by("weight DESC") end
    9.18 -    }
    9.19 -  end
    9.20  end
    9.21  
    9.22  filter[#filter+1] = {
    9.23 @@ -59,7 +46,17 @@
    9.24    selector_modifier = function(selector) selector:add_order_by("name DESC") end
    9.25  }
    9.26  
    9.27 -ui.filters{
    9.28 +local ui_filters = ui.filters
    9.29 +if issue or initiative then
    9.30 +  ui_filters = function(args) args.content() end
    9.31 +  if for_votes then
    9.32 +      members_selector:add_order_by("voter_weight DESC, name, id")
    9.33 +  else
    9.34 +      members_selector:add_order_by("weight DESC, name, id")
    9.35 +  end
    9.36 +end
    9.37 +
    9.38 +ui_filters{
    9.39    label = _"Change order",
    9.40    selector = members_selector,
    9.41    filter,
    10.1 --- a/app/main/suggestion/_list.lua	Wed Jun 27 12:35:34 2012 +0200
    10.2 +++ b/app/main/suggestion/_list.lua	Wed Jun 27 14:37:46 2012 +0200
    10.3 @@ -4,319 +4,95 @@
    10.4  
    10.5  suggestions_selector:add_order_by("plus2_unfulfilled_count + plus1_unfulfilled_count DESC, id")
    10.6  
    10.7 -local tab_id = param.get("tab_id")
    10.8 -local show_name = param.get("show_name", atom.boolean)
    10.9 -if show_name == nil then
   10.10 -  show_name = true
   10.11 -end
   10.12 -local show_filter = param.get("show_filter", atom.boolean)
   10.13 -if show_filter == nil then
   10.14 -  show_filter = true
   10.15 -end
   10.16 -
   10.17 -local partial = {
   10.18 -  routing = {
   10.19 -    default = {
   10.20 -      mode = "redirect",
   10.21 -      module = "initiative",
   10.22 -      view = "show_tab",
   10.23 -      params = {
   10.24 -        initiative_id = initiative.id,
   10.25 -        tab = "suggestions",
   10.26 -        tab_id = tab_id
   10.27 -      },
   10.28 -    }
   10.29 -  }
   10.30 -}
   10.31 -
   10.32  local ui_filters = ui.filters
   10.33  if true or not show_filter then
   10.34    ui_filters = function(args) args.content() end
   10.35  end
   10.36  
   10.37 -ui.container{ attr = { class = "box" },
   10.38 +
   10.39 +ui.container{ attr = { class = "initiative_head" },
   10.40    content = function()
   10.41 -    ui.paginate{
   10.42 -      selector = suggestions_selector,
   10.43 -      content = function()
   10.44 -        ui.list{
   10.45 -          attr = { style = "table-layout: fixed;" },
   10.46 -          records = suggestions_selector:exec(),
   10.47 -          columns = {
   10.48 -            {
   10.49 -              label = show_name and _"Suggestion" or nil,
   10.50 -              content = function(record)
   10.51 -                if show_name then
   10.52 -                  ui.link{
   10.53 -                    text = record.name,
   10.54 -                    module = "suggestion",
   10.55 -                    view = "show",
   10.56 -                    id = record.id
   10.57 -                  }
   10.58 -                end
   10.59 -              end
   10.60 -            },
   10.61 -            {
   10.62 -              label = _"Collective opinion of supporters",
   10.63 -              label_attr = { style = "width: 101px;" },
   10.64 -              content = function(record)
   10.65 -                if record.minus2_unfulfilled_count then
   10.66 -                  local max_value = record.initiative.supporter_count
   10.67 -                  ui.bargraph{
   10.68 -                    max_value = max_value,
   10.69 -                    width = 100,
   10.70 -                    bars = {
   10.71 -                      { color = "#0a0", value = record.plus2_unfulfilled_count + record.plus2_fulfilled_count },
   10.72 -                      { color = "#8f8", value = record.plus1_unfulfilled_count + record.plus1_fulfilled_count },
   10.73 -                      { color = "#eee", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count - record.minus2_fulfilled_count - record.minus1_fulfilled_count - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count - record.plus1_fulfilled_count - record.plus2_fulfilled_count},
   10.74 -                      { color = "#f88", value = record.minus1_unfulfilled_count + record.minus1_fulfilled_count },
   10.75 -                      { color = "#a00", value = record.minus2_unfulfilled_count + record.minus2_fulfilled_count },
   10.76 -                    }
   10.77 -                  }
   10.78 -                end
   10.79 -              end
   10.80 -            },
   10.81 -            {
   10.82 -              label = _"My opinion",
   10.83 -              label_attr = { style = "width: 130px; font-style: italic;" },
   10.84 -              content = function(record)
   10.85 -                local degree
   10.86 -                local opinion
   10.87 -                if app.session.member_id then
   10.88 -                  opinion = Opinion:by_pk(app.session.member.id, record.id)
   10.89 -                end
   10.90 -                if opinion then
   10.91 -                  degree = opinion.degree
   10.92 -                end
   10.93 -                ui.container{
   10.94 -                  attr = { class = "suggestion_my_opinion" },
   10.95 -                  content = function()
   10.96 -                    local has_voting_right = app.session.member and app.session.member:has_voting_right_for_unit_id(initiative.issue.area.unit_id)
   10.97 -                    if app.session.member_id and has_voting_right then
   10.98 -                      if initiative.issue.state == "voting" or initiative.issue.state == "closed" then
   10.99 -                        if degree == -2 then
  10.100 -                          ui.tag{
  10.101 -                            tag = "span",
  10.102 -                            attr = {
  10.103 -                              class = "action" .. (degree == -2 and " active_red2" or "")
  10.104 -                            },
  10.105 -                            content = _"must not"
  10.106 -                          }
  10.107 -                        end
  10.108 -                        if degree == -1 then
  10.109 -                          ui.tag{
  10.110 -                            tag = "span",
  10.111 -                            attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
  10.112 -                            content = _"should not"
  10.113 -                          }
  10.114 -                        end
  10.115 -                        if degree == nil then
  10.116 -                          ui.tag{
  10.117 -                            tag = "span",
  10.118 -                            attr = { class = "action" .. (degree == nil and " active" or "") },
  10.119 -                            content = _"neutral"
  10.120 -                          }
  10.121 -                        end
  10.122 -                        if degree == 1 then
  10.123 -                          ui.tag{
  10.124 -                            tag = "span",
  10.125 -                            attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
  10.126 -                            content = _"should"
  10.127 -                          }
  10.128 -                        end
  10.129 -                        if degree == 2 then
  10.130 -                          ui.tag{
  10.131 -                            tag = "span",
  10.132 -                            attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
  10.133 -                            content = _"must"
  10.134 -                          }
  10.135 -                        end
  10.136 -                      else
  10.137 -                        -- we need to put initiative_id into the parameters to have a redirect target in case the suggestion is gone after the action
  10.138 -                        params = param.get_all_cgi()
  10.139 -                        params['initiative_id'] = initiative.id
  10.140 -
  10.141 -                        ui.link{
  10.142 -                          attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
  10.143 -                          text = _"must",
  10.144 -                          module = "opinion",
  10.145 -                          action = "update",
  10.146 -                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params } },
  10.147 -                          params = {
  10.148 -                            suggestion_id = record.id,
  10.149 -                            degree = 2
  10.150 -                          },
  10.151 -                          partial = partial
  10.152 +    ui.container{ attr = { class = "title" }, content = _"Suggestions" }
  10.153 +    ui.container{ attr = { class = "content" }, content = function()
  10.154 +      ui.paginate{
  10.155 +        selector = suggestions_selector,
  10.156 +        content = function()
  10.157 +          local suggestions = suggestions_selector:exec()
  10.158 +          if #suggestions < 1 then
  10.159 +            if not initiative.issue.fully_frozen and not initiative.issue.closed then
  10.160 +              ui.tag{ content = _"No suggestions yet" }
  10.161 +            else
  10.162 +              ui.tag{ content = _"No suggestions" }
  10.163 +            end
  10.164 +          else
  10.165 +            ui.list{
  10.166 +              attr = { style = "table-layout: fixed;" },
  10.167 +              records = suggestions,
  10.168 +              columns = {
  10.169 +                {
  10.170 +                  label_attr = { style = "width: 101px;" },
  10.171 +                  content = function(record)
  10.172 +                    if record.minus2_unfulfilled_count then
  10.173 +                      local max_value = record.initiative.supporter_count
  10.174 +                      ui.bargraph{
  10.175 +                        max_value = max_value,
  10.176 +                        width = 100,
  10.177 +                        bars = {
  10.178 +                          { color = "#0a0", value = record.plus2_unfulfilled_count + record.plus2_fulfilled_count },
  10.179 +                          { color = "#8f8", value = record.plus1_unfulfilled_count + record.plus1_fulfilled_count },
  10.180 +                          { color = "#eee", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count - record.minus2_fulfilled_count - record.minus1_fulfilled_count - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count - record.plus1_fulfilled_count - record.plus2_fulfilled_count},
  10.181 +                          { color = "#f88", value = record.minus1_unfulfilled_count + record.minus1_fulfilled_count },
  10.182 +                          { color = "#a00", value = record.minus2_unfulfilled_count + record.minus2_fulfilled_count },
  10.183                          }
  10.184 -                        slot.put(" ")
  10.185 -                        ui.link{
  10.186 -                          attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
  10.187 -                          text = _"should",
  10.188 -                          module = "opinion",
  10.189 -                          action = "update",
  10.190 -                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params} },
  10.191 -                          params = {
  10.192 -                            suggestion_id = record.id,
  10.193 -                            degree = 1
  10.194 -                          },
  10.195 -                          partial = partial
  10.196 -                        }
  10.197 -                        slot.put(" ")
  10.198 -                        ui.link{
  10.199 -                          attr = { class = "action" .. (degree == nil and " active" or "") },
  10.200 -                          text = _"neutral",
  10.201 -                          module = "opinion",
  10.202 -                          action = "update",
  10.203 -                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params } },
  10.204 -                          params = {
  10.205 -                            suggestion_id = record.id,
  10.206 -                            delete = true
  10.207 -                          },
  10.208 -                          partial = partial
  10.209 -                        }
  10.210 -                        slot.put(" ")
  10.211 -                        ui.link{
  10.212 -                          attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
  10.213 -                          text = _"should not",
  10.214 -                          module = "opinion",
  10.215 -                          action = "update",
  10.216 -                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params } },
  10.217 -                          params = {
  10.218 -                            suggestion_id = record.id,
  10.219 -                            degree = -1
  10.220 -                          },
  10.221 -                          partial = partial
  10.222 -                        }
  10.223 -                        slot.put(" ")
  10.224 -                        ui.link{
  10.225 -                          attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
  10.226 -                          text = _"must not",
  10.227 -                          module = "opinion",
  10.228 -                          action = "update",
  10.229 -                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params } },
  10.230 -                          params = {
  10.231 -                            suggestion_id = record.id,
  10.232 -                            degree = -2
  10.233 -                          },
  10.234 -                          partial = partial
  10.235 -                        }
  10.236 -                      end
  10.237 -                    elseif app.session.member_id then
  10.238 -                      ui.field.text{ value = _"[No voting privilege]" }
  10.239 -                    else
  10.240 -                      ui.field.text{ value = _"[Registered members only]" }
  10.241 +                      }
  10.242                      end
  10.243                    end
  10.244 -                }
  10.245 -              end
  10.246 -            },
  10.247 -            {
  10.248 -              label = _"Suggestion currently not implemented",
  10.249 -              label_attr = { style = "width: 101px;" },
  10.250 -              content = function(record)
  10.251 -                if record.minus2_unfulfilled_count then
  10.252 -                  local max_value = record.initiative.supporter_count
  10.253 -                  ui.bargraph{
  10.254 -                    max_value = max_value,
  10.255 -                    width = 100,
  10.256 -                    bars = {
  10.257 -                      { color = "#0a0", value = record.plus2_unfulfilled_count },
  10.258 -                      { color = "#8f8", value = record.plus1_unfulfilled_count },
  10.259 -                      { color = "#eee", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count },
  10.260 -                      { color = "#f88", value = record.minus1_unfulfilled_count },
  10.261 -                      { color = "#a00", value = record.minus2_unfulfilled_count },
  10.262 -                    }
  10.263 -                  }
  10.264 -                end
  10.265 -              end
  10.266 -            },
  10.267 -            {
  10.268 -              label = _"Suggestion currently implemented",
  10.269 -              label_attr = { style = "width: 101px;" },
  10.270 -              content = function(record)
  10.271 -                if record.minus2_fulfilled_count then
  10.272 -                  local max_value = record.initiative.supporter_count
  10.273 -                  ui.bargraph{
  10.274 -                    max_value = max_value,
  10.275 -                    width = 100,
  10.276 -                    bars = {
  10.277 -                      { color = "#0a0", value = record.plus2_fulfilled_count },
  10.278 -                      { color = "#8f8", value = record.plus1_fulfilled_count },
  10.279 -                      { color = "#eee", value = max_value - record.minus2_fulfilled_count - record.minus1_fulfilled_count - record.plus1_fulfilled_count - record.plus2_fulfilled_count},
  10.280 -                      { color = "#f88", value = record.minus1_fulfilled_count },
  10.281 -                      { color = "#a00", value = record.minus2_fulfilled_count },
  10.282 +                },
  10.283 +                {
  10.284 +                  content = function(record)
  10.285 +                    ui.link{
  10.286 +                      text = record.name,
  10.287 +                      module = "suggestion",
  10.288 +                      view = "show",
  10.289 +                      id = record.id
  10.290                      }
  10.291 -                  }
  10.292 -                end
  10.293 -              end
  10.294 -            },
  10.295 -            {
  10.296 -              label = app.session.member_id and _"I consider suggestion as" or nil,
  10.297 -              label_attr = { style = "width: 100px; font-style: italic;" },
  10.298 -              content = function(record)
  10.299 -                local degree
  10.300 -                local opinion
  10.301 -                if app.session.member_id then
  10.302 -                  opinion = Opinion:by_pk(app.session.member.id, record.id)
  10.303 -                end
  10.304 -                if opinion then
  10.305 -                  degree = opinion.degree
  10.306 -                end
  10.307 -                if opinion then
  10.308 -
  10.309 -                  ui.link{
  10.310 -                    attr = { class = opinion.fulfilled and "action active" or "action" },
  10.311 -                    text = _"implemented",
  10.312 -                    module = "opinion",
  10.313 -                    action = "update",
  10.314 -                    routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  10.315 -                    params = {
  10.316 -                      suggestion_id = record.id,
  10.317 -                      fulfilled = true
  10.318 -                    },
  10.319 -                    partial = partial
  10.320 -                  }
  10.321 -                  slot.put("<br />")
  10.322 -                  ui.link{
  10.323 -                    attr = { class = not opinion.fulfilled and "action active" or "action" },
  10.324 -                    text = _"not implemented",
  10.325 -                    module = "opinion",
  10.326 -                    action = "update",
  10.327 -                    routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  10.328 -                    params = {
  10.329 -                      suggestion_id = record.id,
  10.330 -                      fulfilled = false
  10.331 -                    },
  10.332 -                    partial = partial
  10.333 -                  }
  10.334 -
  10.335 -                end
  10.336 -              end
  10.337 -            },
  10.338 -            {
  10.339 -              label = app.session.member_id and _"So I'm" or nil,
  10.340 -              content = function(record)
  10.341 -                local opinion
  10.342 -                if app.session.member_id then
  10.343 -                  opinion = Opinion:by_pk(app.session.member.id, record.id)
  10.344 -                end
  10.345 -                if opinion then
  10.346 -                  if (opinion.fulfilled and opinion.degree > 0) or (not opinion.fulfilled and opinion.degree < 0) then
  10.347 -                    local title = _"satisfied"
  10.348 -                    ui.image{ attr = { alt = title, title = title }, static = "icons/emoticon_happy.png" }
  10.349 -                  elseif opinion.degree == 1 or opinion.degree == -1 then
  10.350 -                    local title = _"a bit unsatisfied"
  10.351 -                    ui.image{ attr = { alt = title, title = title }, static = "icons/emoticon_unhappy.png" }
  10.352 -                  else
  10.353 -                    local title = _"more unsatisfied"
  10.354 -                    ui.image{ attr = { alt = title, title = title }, static = "icons/emoticon_unhappy_red.png" }
  10.355 +                    local degree
  10.356 +                    local opinion
  10.357 +                    if app.session.member_id then
  10.358 +                      opinion = Opinion:by_pk(app.session.member.id, record.id)
  10.359 +                    end
  10.360 +                    if opinion then
  10.361 +                      local degrees = {
  10.362 +                        ["-2"] = _"must not",
  10.363 +                        ["-1"] = _"should not",
  10.364 +                        ["0"] = _"neutral",
  10.365 +                        ["1"] = _"should",
  10.366 +                        ["2"] = _"must"
  10.367 +                      }
  10.368 +                      slot.put(" &middot; ")
  10.369 +                      ui.tag{ content = degrees[tostring(opinion.degree)] }
  10.370 +                      slot.put(" &middot; ")
  10.371 +                      if opinion.fulfilled then
  10.372 +                        ui.tag{ content = _"implemented" }
  10.373 +                      else
  10.374 +                        ui.tag{ content = _"not implemented" }
  10.375 +                      end
  10.376 +                    end
  10.377                    end
  10.378 -                end
  10.379 -              end
  10.380 -            },
  10.381 -          }
  10.382 +                },
  10.383 +              }
  10.384 +            }
  10.385 +          end
  10.386 +        end
  10.387 +      }
  10.388 +    end }
  10.389 +    if not initiative.issue.fully_frozen and not initiative.issue.closed then
  10.390 +      ui.container{ attr = { class = "content" }, content = function()
  10.391 +        ui.link{
  10.392 +          module = "suggestion", view = "new", params = { initiative_id = initiative.id },
  10.393 +          text = _"New suggestion"
  10.394          }
  10.395 -      end
  10.396 -    }
  10.397 +      end }
  10.398 +    end
  10.399    end
  10.400  }
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/app/main/suggestion/_list_element.lua	Wed Jun 27 14:37:46 2012 +0200
    11.3 @@ -0,0 +1,322 @@
    11.4 +
    11.5 +local initiative = param.get("initiative", "table")
    11.6 +local suggestions_selector = param.get("suggestions_selector", "table")
    11.7 +
    11.8 +suggestions_selector:add_order_by("plus2_unfulfilled_count + plus1_unfulfilled_count DESC, id")
    11.9 +
   11.10 +local tab_id = param.get("tab_id")
   11.11 +local show_name = param.get("show_name", atom.boolean)
   11.12 +if show_name == nil then
   11.13 +  show_name = true
   11.14 +end
   11.15 +local show_filter = param.get("show_filter", atom.boolean)
   11.16 +if show_filter == nil then
   11.17 +  show_filter = true
   11.18 +end
   11.19 +
   11.20 +local partial = {
   11.21 +  routing = {
   11.22 +    default = {
   11.23 +      mode = "redirect",
   11.24 +      module = "initiative",
   11.25 +      view = "show_tab",
   11.26 +      params = {
   11.27 +        initiative_id = initiative.id,
   11.28 +        tab = "suggestions",
   11.29 +        tab_id = tab_id
   11.30 +      },
   11.31 +    }
   11.32 +  }
   11.33 +}
   11.34 +
   11.35 +local ui_filters = ui.filters
   11.36 +if true or not show_filter then
   11.37 +  ui_filters = function(args) args.content() end
   11.38 +end
   11.39 +
   11.40 +ui.container{ attr = { class = "box" },
   11.41 +  content = function()
   11.42 +    ui.paginate{
   11.43 +      selector = suggestions_selector,
   11.44 +      content = function()
   11.45 +        ui.list{
   11.46 +          attr = { style = "table-layout: fixed;" },
   11.47 +          records = suggestions_selector:exec(),
   11.48 +          columns = {
   11.49 +            {
   11.50 +              label = show_name and _"Suggestion" or nil,
   11.51 +              content = function(record)
   11.52 +                if show_name then
   11.53 +                  ui.link{
   11.54 +                    text = record.name,
   11.55 +                    module = "suggestion",
   11.56 +                    view = "show",
   11.57 +                    id = record.id
   11.58 +                  }
   11.59 +                end
   11.60 +              end
   11.61 +            },
   11.62 +            {
   11.63 +              label = _"Collective opinion of supporters",
   11.64 +              label_attr = { style = "width: 101px;" },
   11.65 +              content = function(record)
   11.66 +                if record.minus2_unfulfilled_count then
   11.67 +                  local max_value = record.initiative.supporter_count
   11.68 +                  ui.bargraph{
   11.69 +                    max_value = max_value,
   11.70 +                    width = 100,
   11.71 +                    bars = {
   11.72 +                      { color = "#0a0", value = record.plus2_unfulfilled_count + record.plus2_fulfilled_count },
   11.73 +                      { color = "#8f8", value = record.plus1_unfulfilled_count + record.plus1_fulfilled_count },
   11.74 +                      { color = "#eee", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count - record.minus2_fulfilled_count - record.minus1_fulfilled_count - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count - record.plus1_fulfilled_count - record.plus2_fulfilled_count},
   11.75 +                      { color = "#f88", value = record.minus1_unfulfilled_count + record.minus1_fulfilled_count },
   11.76 +                      { color = "#a00", value = record.minus2_unfulfilled_count + record.minus2_fulfilled_count },
   11.77 +                    }
   11.78 +                  }
   11.79 +                end
   11.80 +              end
   11.81 +            },
   11.82 +            {
   11.83 +              label = _"My opinion",
   11.84 +              label_attr = { style = "width: 130px; font-style: italic;" },
   11.85 +              content = function(record)
   11.86 +                local degree
   11.87 +                local opinion
   11.88 +                if app.session.member_id then
   11.89 +                  opinion = Opinion:by_pk(app.session.member.id, record.id)
   11.90 +                end
   11.91 +                if opinion then
   11.92 +                  degree = opinion.degree
   11.93 +                end
   11.94 +                ui.container{
   11.95 +                  attr = { class = "suggestion_my_opinion" },
   11.96 +                  content = function()
   11.97 +                    local has_voting_right = app.session.member and app.session.member:has_voting_right_for_unit_id(initiative.issue.area.unit_id)
   11.98 +                    if app.session.member_id and has_voting_right then
   11.99 +                      if initiative.issue.state == "voting" or initiative.issue.state == "closed" then
  11.100 +                        if degree == -2 then
  11.101 +                          ui.tag{
  11.102 +                            tag = "span",
  11.103 +                            attr = {
  11.104 +                              class = "action" .. (degree == -2 and " active_red2" or "")
  11.105 +                            },
  11.106 +                            content = _"must not"
  11.107 +                          }
  11.108 +                        end
  11.109 +                        if degree == -1 then
  11.110 +                          ui.tag{
  11.111 +                            tag = "span",
  11.112 +                            attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
  11.113 +                            content = _"should not"
  11.114 +                          }
  11.115 +                        end
  11.116 +                        if degree == nil then
  11.117 +                          ui.tag{
  11.118 +                            tag = "span",
  11.119 +                            attr = { class = "action" .. (degree == nil and " active" or "") },
  11.120 +                            content = _"neutral"
  11.121 +                          }
  11.122 +                        end
  11.123 +                        if degree == 1 then
  11.124 +                          ui.tag{
  11.125 +                            tag = "span",
  11.126 +                            attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
  11.127 +                            content = _"should"
  11.128 +                          }
  11.129 +                        end
  11.130 +                        if degree == 2 then
  11.131 +                          ui.tag{
  11.132 +                            tag = "span",
  11.133 +                            attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
  11.134 +                            content = _"must"
  11.135 +                          }
  11.136 +                        end
  11.137 +                      else
  11.138 +                        -- we need to put initiative_id into the parameters to have a redirect target in case the suggestion is gone after the action
  11.139 +                        params = param.get_all_cgi()
  11.140 +                        params['initiative_id'] = initiative.id
  11.141 +
  11.142 +                        ui.link{
  11.143 +                          attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
  11.144 +                          text = _"must",
  11.145 +                          module = "opinion",
  11.146 +                          action = "update",
  11.147 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params } },
  11.148 +                          params = {
  11.149 +                            suggestion_id = record.id,
  11.150 +                            degree = 2
  11.151 +                          },
  11.152 +                          partial = partial
  11.153 +                        }
  11.154 +                        slot.put(" ")
  11.155 +                        ui.link{
  11.156 +                          attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
  11.157 +                          text = _"should",
  11.158 +                          module = "opinion",
  11.159 +                          action = "update",
  11.160 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params} },
  11.161 +                          params = {
  11.162 +                            suggestion_id = record.id,
  11.163 +                            degree = 1
  11.164 +                          },
  11.165 +                          partial = partial
  11.166 +                        }
  11.167 +                        slot.put(" ")
  11.168 +                        ui.link{
  11.169 +                          attr = { class = "action" .. (degree == nil and " active" or "") },
  11.170 +                          text = _"neutral",
  11.171 +                          module = "opinion",
  11.172 +                          action = "update",
  11.173 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params } },
  11.174 +                          params = {
  11.175 +                            suggestion_id = record.id,
  11.176 +                            delete = true
  11.177 +                          },
  11.178 +                          partial = partial
  11.179 +                        }
  11.180 +                        slot.put(" ")
  11.181 +                        ui.link{
  11.182 +                          attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
  11.183 +                          text = _"should not",
  11.184 +                          module = "opinion",
  11.185 +                          action = "update",
  11.186 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params } },
  11.187 +                          params = {
  11.188 +                            suggestion_id = record.id,
  11.189 +                            degree = -1
  11.190 +                          },
  11.191 +                          partial = partial
  11.192 +                        }
  11.193 +                        slot.put(" ")
  11.194 +                        ui.link{
  11.195 +                          attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
  11.196 +                          text = _"must not",
  11.197 +                          module = "opinion",
  11.198 +                          action = "update",
  11.199 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = params } },
  11.200 +                          params = {
  11.201 +                            suggestion_id = record.id,
  11.202 +                            degree = -2
  11.203 +                          },
  11.204 +                          partial = partial
  11.205 +                        }
  11.206 +                      end
  11.207 +                    elseif app.session.member_id then
  11.208 +                      ui.field.text{ value = _"[No voting privilege]" }
  11.209 +                    else
  11.210 +                      ui.field.text{ value = _"[Registered members only]" }
  11.211 +                    end
  11.212 +                  end
  11.213 +                }
  11.214 +              end
  11.215 +            },
  11.216 +            {
  11.217 +              label = _"Suggestion currently not implemented",
  11.218 +              label_attr = { style = "width: 101px;" },
  11.219 +              content = function(record)
  11.220 +                if record.minus2_unfulfilled_count then
  11.221 +                  local max_value = record.initiative.supporter_count
  11.222 +                  ui.bargraph{
  11.223 +                    max_value = max_value,
  11.224 +                    width = 100,
  11.225 +                    bars = {
  11.226 +                      { color = "#0a0", value = record.plus2_unfulfilled_count },
  11.227 +                      { color = "#8f8", value = record.plus1_unfulfilled_count },
  11.228 +                      { color = "#eee", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count },
  11.229 +                      { color = "#f88", value = record.minus1_unfulfilled_count },
  11.230 +                      { color = "#a00", value = record.minus2_unfulfilled_count },
  11.231 +                    }
  11.232 +                  }
  11.233 +                end
  11.234 +              end
  11.235 +            },
  11.236 +            {
  11.237 +              label = _"Suggestion currently implemented",
  11.238 +              label_attr = { style = "width: 101px;" },
  11.239 +              content = function(record)
  11.240 +                if record.minus2_fulfilled_count then
  11.241 +                  local max_value = record.initiative.supporter_count
  11.242 +                  ui.bargraph{
  11.243 +                    max_value = max_value,
  11.244 +                    width = 100,
  11.245 +                    bars = {
  11.246 +                      { color = "#0a0", value = record.plus2_fulfilled_count },
  11.247 +                      { color = "#8f8", value = record.plus1_fulfilled_count },
  11.248 +                      { color = "#eee", value = max_value - record.minus2_fulfilled_count - record.minus1_fulfilled_count - record.plus1_fulfilled_count - record.plus2_fulfilled_count},
  11.249 +                      { color = "#f88", value = record.minus1_fulfilled_count },
  11.250 +                      { color = "#a00", value = record.minus2_fulfilled_count },
  11.251 +                    }
  11.252 +                  }
  11.253 +                end
  11.254 +              end
  11.255 +            },
  11.256 +            {
  11.257 +              label = app.session.member_id and _"I consider suggestion as" or nil,
  11.258 +              label_attr = { style = "width: 100px; font-style: italic;" },
  11.259 +              content = function(record)
  11.260 +                local degree
  11.261 +                local opinion
  11.262 +                if app.session.member_id then
  11.263 +                  opinion = Opinion:by_pk(app.session.member.id, record.id)
  11.264 +                end
  11.265 +                if opinion then
  11.266 +                  degree = opinion.degree
  11.267 +                end
  11.268 +                if opinion then
  11.269 +
  11.270 +                  ui.link{
  11.271 +                    attr = { class = opinion.fulfilled and "action active" or "action" },
  11.272 +                    text = _"implemented",
  11.273 +                    module = "opinion",
  11.274 +                    action = "update",
  11.275 +                    routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  11.276 +                    params = {
  11.277 +                      suggestion_id = record.id,
  11.278 +                      fulfilled = true
  11.279 +                    },
  11.280 +                    partial = partial
  11.281 +                  }
  11.282 +                  slot.put("<br />")
  11.283 +                  ui.link{
  11.284 +                    attr = { class = not opinion.fulfilled and "action active" or "action" },
  11.285 +                    text = _"not implemented",
  11.286 +                    module = "opinion",
  11.287 +                    action = "update",
  11.288 +                    routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  11.289 +                    params = {
  11.290 +                      suggestion_id = record.id,
  11.291 +                      fulfilled = false
  11.292 +                    },
  11.293 +                    partial = partial
  11.294 +                  }
  11.295 +
  11.296 +                end
  11.297 +              end
  11.298 +            },
  11.299 +            {
  11.300 +              label = app.session.member_id and _"So I'm" or nil,
  11.301 +              content = function(record)
  11.302 +                local opinion
  11.303 +                if app.session.member_id then
  11.304 +                  opinion = Opinion:by_pk(app.session.member.id, record.id)
  11.305 +                end
  11.306 +                if opinion then
  11.307 +                  if (opinion.fulfilled and opinion.degree > 0) or (not opinion.fulfilled and opinion.degree < 0) then
  11.308 +                    local title = _"satisfied"
  11.309 +                    ui.image{ attr = { alt = title, title = title }, static = "icons/emoticon_happy.png" }
  11.310 +                  elseif opinion.degree == 1 or opinion.degree == -1 then
  11.311 +                    local title = _"a bit unsatisfied"
  11.312 +                    ui.image{ attr = { alt = title, title = title }, static = "icons/emoticon_unhappy.png" }
  11.313 +                  else
  11.314 +                    local title = _"more unsatisfied"
  11.315 +                    ui.image{ attr = { alt = title, title = title }, static = "icons/emoticon_unhappy_red.png" }
  11.316 +                  end
  11.317 +                end
  11.318 +              end
  11.319 +            },
  11.320 +          }
  11.321 +        }
  11.322 +      end
  11.323 +    }
  11.324 +  end
  11.325 +}
    12.1 --- a/app/main/suggestion/_suggestion.lua	Wed Jun 27 12:35:34 2012 +0200
    12.2 +++ b/app/main/suggestion/_suggestion.lua	Wed Jun 27 14:37:46 2012 +0200
    12.3 @@ -19,7 +19,7 @@
    12.4  }
    12.5  execute.view{
    12.6    module = "suggestion",
    12.7 -  view = "_list",
    12.8 +  view = "_list_element",
    12.9    params = {
   12.10      suggestions_selector = Suggestion:new_selector():add_where{ "id = ?", suggestion.id },
   12.11      initiative = suggestion.initiative,
    13.1 --- a/app/main/suggestion/show.lua	Wed Jun 27 12:35:34 2012 +0200
    13.2 +++ b/app/main/suggestion/show.lua	Wed Jun 27 14:37:46 2012 +0200
    13.3 @@ -21,9 +21,9 @@
    13.4  app.html_title.title = suggestion.name
    13.5  app.html_title.subtitle = _("Suggestion ##{id}", { id = suggestion.id })
    13.6  
    13.7 -slot.put_into("title", encode.html(_"Suggestion for initiative: '#{name}'":gsub("#{name}", suggestion.initiative.name) ))
    13.8 +ui.title(_"Suggestion for initiative: '#{name}'":gsub("#{name}", suggestion.initiative.name))
    13.9  
   13.10 -slot.select("actions", function()
   13.11 +ui.actions(function()
   13.12    ui.link{
   13.13      content = function()
   13.14          ui.image{ static = "icons/16/resultset_previous.png" }
    14.1 --- a/static/style.css	Wed Jun 27 12:35:34 2012 +0200
    14.2 +++ b/static/style.css	Wed Jun 27 14:37:46 2012 +0200
    14.3 @@ -68,10 +68,6 @@
    14.4    margin: 0 auto;
    14.5  }
    14.6  
    14.7 -table {
    14.8 -  margin-top: 1ex;
    14.9 -}
   14.10 -
   14.11  body, a {
   14.12    color: #000;
   14.13  }
   14.14 @@ -321,7 +317,6 @@
   14.15  
   14.16  .member_thumb,
   14.17  .member_statement,
   14.18 -.draft_content,
   14.19  .suggestion_content,
   14.20  .slot_head,
   14.21  .area_list,
   14.22 @@ -329,7 +324,6 @@
   14.23  .issues .issue,
   14.24  .ui_tabs_links a,
   14.25  .ui_filter a,
   14.26 -.draft_content,
   14.27  .help,
   14.28  .use_terms,
   14.29  .motd,
   14.30 @@ -375,6 +369,10 @@
   14.31    line-height: 120%;
   14.32  }
   14.33  
   14.34 +.initiative_head {
   14.35 +  margin-bottom: 10px;
   14.36 +}
   14.37 +
   14.38  .page_head .actions:last-child,
   14.39  .page_head .unit_head .content:last-child,
   14.40  .page_head .area_head .content:last-child,
   14.41 @@ -1211,30 +1209,34 @@
   14.42    text-decoration: line-through;
   14.43  }
   14.44  
   14.45 +.admitted_info,
   14.46 +.not_admitted_info,
   14.47 +.revoked_info,
   14.48 +.draft_updated_info,
   14.49 +.initiator_invite_info {
   14.50 +  padding: 1ex;
   14.51 +}
   14.52 +
   14.53  .admitted_info {
   14.54    background-color: #afc;
   14.55 -  padding: 1ex;
   14.56 -  border-radius: 0 0 8px 8px;
   14.57  }
   14.58  
   14.59  .not_admitted_info,
   14.60  .revoked_info {
   14.61    background-color: #fbb;
   14.62 -  padding: 1ex;
   14.63 -  border-radius: 8px;
   14.64 -  border-radius: 0 0 8px 8px;
   14.65  }
   14.66  
   14.67  .draft_updated_info,
   14.68 -.initiator_invite_info,
   14.69 +.initiator_invite_info {
   14.70 +  background-color: #fda;
   14.71 +}
   14.72 +
   14.73  .motd,
   14.74  .public_access_issue_head {
   14.75    background-color: #fda;
   14.76    padding: 1ex;
   14.77    margin-top: 1ex;
   14.78    margin-bottom: 2ex;
   14.79 -  border: 1px solid #fa0;
   14.80 -  border-radius: 10px;
   14.81  }
   14.82  
   14.83  .suggestion_fulfilled {
   14.84 @@ -1336,6 +1338,7 @@
   14.85    display: block;
   14.86    font-size: 115%;
   14.87    font-weight: bold;
   14.88 +  margin-bottom: 10px;
   14.89  }
   14.90  
   14.91  .heading.first {
   14.92 @@ -1418,7 +1421,6 @@
   14.93  /* shadows */
   14.94  
   14.95  .member_statement,
   14.96 -.draft_content,
   14.97  .suggestion_content,
   14.98  .initiative_head,
   14.99  .box,
  14.100 @@ -1427,7 +1429,6 @@
  14.101  }
  14.102  
  14.103  .member_statement,
  14.104 -.draft_content,
  14.105  .suggestion_content,
  14.106  .initiative_head,
  14.107  .box {

Impressum / About Us