liquid_feedback_frontend

changeset 51:0849be391140

Public read access; Read-only API for initiatives; Prepared integration of OpenID
author bsw
date Sun Apr 04 22:05:11 2010 +0200 (2010-04-04)
parents ff1926efa6aa
children 88ac7798b562
files app/main/_filter/21_auth.lua app/main/_filter_view/30_navigation.lua app/main/_filter_view/34_stylesheet.lua app/main/_filter_view/35_openid.lua app/main/_layout/xml.html app/main/api/_filter/00_api.lua app/main/api/initiative.lua app/main/area/_list.lua app/main/area/list.lua app/main/area/show.lua app/main/area/show_tab.lua app/main/draft/_list.lua app/main/draft/_show.lua app/main/index/login.lua app/main/initiative/_list.lua app/main/initiative/_show.lua app/main/initiative/_suggestions.lua app/main/initiative/show_partial.lua app/main/initiative/show_static.lua app/main/initiative/show_tab.lua app/main/issue/_list.lua app/main/issue/_show_head.lua app/main/issue/show_tab.lua app/main/member/_action/update_api_key.lua app/main/member/_show_thumb.lua app/main/member/developer_settings.lua app/main/member/settings.lua app/main/openid/_action/initiate.lua app/main/openid/_filter/00_openid.lua app/main/openid/announce.xrds.lua app/main/openid/verify.lua app/main/suggestion/_list.lua app/main/suggestion/_suggestion.lua app/main/suggestion/show_tab.lua app/main/timeline/_filter/29_filter.lua config/default.lua config/development.lua env/util/autoapi.lua env/util/help.lua locale/translations.de.lua locale/translations.en.lua locale/translations.eo.lua locale/translations.fr.lua model/initiative.lua model/issue.lua
line diff
     1.1 --- a/app/main/_filter/21_auth.lua	Wed Mar 31 17:50:32 2010 +0200
     1.2 +++ b/app/main/_filter/21_auth.lua	Sun Apr 04 22:05:11 2010 +0200
     1.3 @@ -1,8 +1,8 @@
     1.4  local auth_needed = not (
     1.5    request.get_module() == 'index'
     1.6    and (
     1.7 -       request.get_view()   == 'login'
     1.8 -    or request.get_action() == 'login'
     1.9 +       request.get_view()   == "login"
    1.10 +    or request.get_action() == "login"
    1.11      or request.get_view()   == "register"
    1.12      or request.get_action() == "register"
    1.13      or request.get_view()   == "about"
    1.14 @@ -12,8 +12,35 @@
    1.15      or request.get_action() == "confirm_notify_email"
    1.16      or request.get_action() == "set_lang"
    1.17    )
    1.18 +  or request.get_module() == "openid"
    1.19  )
    1.20  
    1.21 +if config.public_access then
    1.22 +
    1.23 +  if
    1.24 +    request.get_module() == "area" and (
    1.25 +     request.get_view() == "list"
    1.26 +     or request.get_view() == "show"
    1.27 +     or request.get_view() == "show_tab"
    1.28 +    )
    1.29 +    or request.get_module() == "issue" and request.get_view() == "show"
    1.30 +    or request.get_module() == "issue" and request.get_view() == "show_tab"
    1.31 +    or request.get_module() == "initiative" and request.get_view() == "show"
    1.32 +    or request.get_module() == "initiative" and request.get_view() == "show_partial"
    1.33 +    or request.get_module() == "initiative" and request.get_view() == "show_tab"
    1.34 +    or request.get_module() == "suggestion" and request.get_view() == "show"
    1.35 +    or request.get_module() == "draft" and request.get_view() == "diff"
    1.36 +  then
    1.37 +    auth_needed = false
    1.38 +  end
    1.39 +
    1.40 +end
    1.41 +
    1.42 +if config.public_access and not app.session.member_id and auth_needed and request.get_module() == "index" and request.get_view() == "index" then
    1.43 +  request.redirect{ module = "area", view = "list" }
    1.44 +  return
    1.45 +end
    1.46 +
    1.47  -- if not app.session.user_id then
    1.48  --   trace.debug("DEBUG: AUTHENTICATION BYPASS ENABLED")
    1.49  --   app.session.user_id = 1
     2.1 --- a/app/main/_filter_view/30_navigation.lua	Wed Mar 31 17:50:32 2010 +0200
     2.2 +++ b/app/main/_filter_view/30_navigation.lua	Sun Apr 04 22:05:11 2010 +0200
     2.3 @@ -1,13 +1,37 @@
     2.4  slot.put_into("app_name", config.app_title)
     2.5  
     2.6 --- display navigation only, if user is logged in
     2.7 -if app.session.member == nil then
     2.8 -  slot.select('navigation', function()
     2.9 +slot.select('navigation', function()
    2.10 +
    2.11 +  if app.session.member then
    2.12 +    ui.link{
    2.13 +      image  = { static = "icons/16/house.png" },
    2.14 +      text   = _"Home",
    2.15 +      module = 'index',
    2.16 +      view   = 'index'
    2.17 +    }
    2.18 +  end
    2.19 +
    2.20 +  if app.session.member or config.public_access then
    2.21 +    ui.link{
    2.22 +      image  = { static = "icons/16/package.png" },
    2.23 +      text   = _"Areas",
    2.24 +      module = 'area',
    2.25 +      view   = 'list'
    2.26 +    }
    2.27 +
    2.28 +  end
    2.29 +
    2.30 +  if app.session.member == nil then
    2.31      ui.link{
    2.32        image  = { static = "icons/16/key.png" },
    2.33        text   = _"Login",
    2.34        module = 'index',
    2.35 -      view   = 'login'
    2.36 +      view   = 'login',
    2.37 +      params = {
    2.38 +        redirect_module = request.get_module(),
    2.39 +        redirect_view = request.get_view(),
    2.40 +        redirect_id = param.get_id()
    2.41 +      }
    2.42      }
    2.43      ui.link{
    2.44        image  = { static = "icons/16/book_edit.png" },
    2.45 @@ -27,68 +51,50 @@
    2.46        module = 'index',
    2.47        view   = 'about'
    2.48      }
    2.49 -  end)
    2.50 -  execute.inner()
    2.51 -  return
    2.52 -end
    2.53 -
    2.54 -slot.select('navigation', function()
    2.55 -
    2.56 -  ui.link{
    2.57 -    image  = { static = "icons/16/house.png" },
    2.58 -    text   = _"Home",
    2.59 -    module = 'index',
    2.60 -    view   = 'index'
    2.61 -  }
    2.62 -
    2.63 -  ui.link{
    2.64 -    image  = { static = "icons/16/time.png" },
    2.65 -    text   = _"Timeline",
    2.66 -    module = "timeline",
    2.67 -    view   = "index"
    2.68 -  }
    2.69 +  else 
    2.70  
    2.71 -  ui.link{
    2.72 -    image  = { static = "icons/16/package.png" },
    2.73 -    text   = _"Areas",
    2.74 -    module = 'area',
    2.75 -    view   = 'list'
    2.76 -  }
    2.77 -
    2.78 -  ui.link{
    2.79 -    image  = { static = "icons/16/group.png" },
    2.80 -    text   = _"Members",
    2.81 -    module = 'member',
    2.82 -    view   = 'list',
    2.83 -    params = { member_list = "newest" }
    2.84 -  }
    2.85 +    ui.link{
    2.86 +      image  = { static = "icons/16/time.png" },
    2.87 +      text   = _"Timeline",
    2.88 +      module = "timeline",
    2.89 +      view   = "index"
    2.90 +    }
    2.91  
    2.92 -  ui.link{
    2.93 -    image  = { static = "icons/16/book_edit.png" },
    2.94 -    text   = _"Contacts",
    2.95 -    module = 'contact',
    2.96 -    view   = 'list'
    2.97 -  }
    2.98 -
    2.99 -  ui.link{
   2.100 -    image  = { static = "icons/16/information.png" },
   2.101 -    text   = _"About",
   2.102 -    module = 'index',
   2.103 -    view   = 'about'
   2.104 -  }
   2.105 -
   2.106 -  if app.session.member.admin then
   2.107 -
   2.108 -    slot.put(" ")
   2.109 +    ui.link{
   2.110 +      image  = { static = "icons/16/group.png" },
   2.111 +      text   = _"Members",
   2.112 +      module = 'member',
   2.113 +      view   = 'list',
   2.114 +      params = { member_list = "newest" }
   2.115 +    }
   2.116  
   2.117      ui.link{
   2.118 -      attr   = { class = { "admin_only" } },
   2.119 -      image  = { static = "icons/16/cog.png" },
   2.120 -      text   = _"Admin",
   2.121 -      module = 'admin',
   2.122 -      view   = 'index'
   2.123 +      image  = { static = "icons/16/book_edit.png" },
   2.124 +      text   = _"Contacts",
   2.125 +      module = 'contact',
   2.126 +      view   = 'list'
   2.127 +    }
   2.128 +
   2.129 +    ui.link{
   2.130 +      image  = { static = "icons/16/information.png" },
   2.131 +      text   = _"About",
   2.132 +      module = 'index',
   2.133 +      view   = 'about'
   2.134      }
   2.135  
   2.136 +    if app.session.member.admin then
   2.137 +
   2.138 +      slot.put(" ")
   2.139 +
   2.140 +      ui.link{
   2.141 +        attr   = { class = { "admin_only" } },
   2.142 +        image  = { static = "icons/16/cog.png" },
   2.143 +        text   = _"Admin",
   2.144 +        module = 'admin',
   2.145 +        view   = 'index'
   2.146 +      }
   2.147 +
   2.148 +    end
   2.149    end
   2.150  
   2.151  end)
     3.1 --- a/app/main/_filter_view/34_stylesheet.lua	Wed Mar 31 17:50:32 2010 +0200
     3.2 +++ b/app/main/_filter_view/34_stylesheet.lua	Sun Apr 04 22:05:11 2010 +0200
     3.3 @@ -25,6 +25,8 @@
     3.4    if tab_mode then
     3.5      config.user_tab_mode = tab_mode
     3.6    end
     3.7 +else
     3.8 +  config.user_tab_mode = "accordeon_first_expanded"
     3.9  end
    3.10  
    3.11  local web20 = config.user_tab_mode == "accordeon"
    3.12 @@ -39,12 +41,15 @@
    3.13    slot.set_layout("blank")
    3.14  end
    3.15  
    3.16 -
    3.17 -ui.container{
    3.18 -  attr = {
    3.19 -    class = web20 and "web20" or "web10"
    3.20 -  },
    3.21 -  content = function()
    3.22 -    execute.inner()
    3.23 -  end
    3.24 -}
    3.25 \ No newline at end of file
    3.26 +if request.get_module() ~= "api" then
    3.27 +  ui.container{
    3.28 +    attr = {
    3.29 +      class = web20 and "web20" or "web10"
    3.30 +    },
    3.31 +    content = function()
    3.32 +      execute.inner()
    3.33 +    end
    3.34 +  }
    3.35 +else
    3.36 +  execute.inner()
    3.37 +end
    3.38 \ No newline at end of file
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/app/main/_filter_view/35_openid.lua	Sun Apr 04 22:05:11 2010 +0200
     4.3 @@ -0,0 +1,6 @@
     4.4 +auth.openid.xrds_header{
     4.5 +  module = "openid",
     4.6 +  view = "announce.xrds"
     4.7 +}
     4.8 +
     4.9 +execute.inner()
    4.10 \ No newline at end of file
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/app/main/_layout/xml.html	Sun Apr 04 22:05:11 2010 +0200
     5.3 @@ -0,0 +1,2 @@
     5.4 +<?xml version="1.0" encoding="utf-8"?>
     5.5 +<!-- WEBMCP SLOTNODIV default -->
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/app/main/api/_filter/00_api.lua	Sun Apr 04 22:05:11 2010 +0200
     6.3 @@ -0,0 +1,25 @@
     6.4 +if not config.api_enabled then
     6.5 +  error("API is not enabled.")
     6.6 +end
     6.7 +
     6.8 +local api_key = param.get("key")
     6.9 +
    6.10 +if not api_key then
    6.11 +  error("No API key supplied.")
    6.12 +end
    6.13 +
    6.14 +local setting_key = "liquidfeedback_frontend_api_key"
    6.15 +
    6.16 +local setting = Setting:new_selector()
    6.17 +  :add_where{ "key = ?", setting_key }
    6.18 +  :add_where{ "value = ?", api_key }
    6.19 +  :join("member", nil, "member.id = setting.member_id")
    6.20 +  :add_where("member.active")
    6.21 +  :optional_object_mode()
    6.22 +  :exec()
    6.23 +
    6.24 +if not setting then
    6.25 +  error("Supplied API key is not valid.")
    6.26 +end
    6.27 +
    6.28 +execute.inner()
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/app/main/api/initiative.lua	Sun Apr 04 22:05:11 2010 +0200
     7.3 @@ -0,0 +1,193 @@
     7.4 +local id             = param.get_id()
     7.5 +local min_id         = param.get("min_id")
     7.6 +local max_id         = param.get("max_id")
     7.7 +local area_id        = param.get("area_id", atom.integer)
     7.8 +local issue_id       = param.get("issue_id", atom.integer)
     7.9 +local policy_id      = param.get("policy_id", atom.integer)
    7.10 +local state          = param.get("state")
    7.11 +local agreed         = param.get("agreed")
    7.12 +local rank           = param.get("rank")
    7.13 +local search         = param.get("search")
    7.14 +local search_context = param.get("search_context") or "full"
    7.15 +local limit          = param.get("limit", atom.integer)
    7.16 +local order          = param.get("order")
    7.17 +
    7.18 +local initiatives_selector = Initiative:new_selector()
    7.19 +  :join("issue", nil, "issue.id = initiative.id")
    7.20 +  :join("area", nil, "area.id = issue.area_id")
    7.21 +  :join("policy", nil, "policy.id = issue.policy_id")
    7.22 +
    7.23 +if id then
    7.24 +  initiatives_selector:add_where{"initiative.id = ?", id}
    7.25 +end
    7.26 +
    7.27 +if min_id then
    7.28 +  initiatives_selector:add_where{"initiative.id >= ?", min_id}
    7.29 +end
    7.30 +
    7.31 +if max_id then
    7.32 +  initiatives_selector:add_where{"initiative.id <= ?", max_id}
    7.33 +end
    7.34 +
    7.35 +if area_id then
    7.36 +  initiatives_selector:add_where{"area.id = ?", area_id}
    7.37 +end
    7.38 +
    7.39 +if issue_id then
    7.40 +  initiatives_selector:add_where{"issue.id = ?", issue_id}
    7.41 +end
    7.42 +
    7.43 +if policy_id then
    7.44 +  initiatives_selector:add_where{"policy.id = ?", policy_id}
    7.45 +end
    7.46 +
    7.47 +if state then
    7.48 +  Issue:modify_selector_for_state(state)
    7.49 +end
    7.50 +
    7.51 +if agreed then
    7.52 +  initiatives_selector:add_where("initiative.agreed")
    7.53 +end
    7.54 +
    7.55 +if rank then
    7.56 +  initiatives_selector:add_where{ "initiative.rank = ?", rank }
    7.57 +end
    7.58 +
    7.59 +if search then
    7.60 +  if search_context == "full" then
    7.61 +  elseif search_context == "title" then
    7.62 +  end
    7.63 +end
    7.64 +
    7.65 +if order == "supporter_count" then
    7.66 +  initiatives_selector:add_order_by("initiative.supporter_count")
    7.67 +end
    7.68 +
    7.69 +initiatives_selector:add_order_by("initiative.id")
    7.70 +
    7.71 +if limit then
    7.72 +  initiatives_selector:limit(limit)
    7.73 +end
    7.74 +
    7.75 +local api_engine = param.get("api_engine") or "xml"
    7.76 +
    7.77 +local function format_timestamp(timestamp)
    7.78 +  if timestamp then
    7.79 +    return format.timestamp(timestamp)
    7.80 +  else
    7.81 +    return ""
    7.82 +  end
    7.83 +end
    7.84 +
    7.85 +local fields = {
    7.86 +
    7.87 +  { name = "area_id",                   field = "area.id" },
    7.88 +  { name = "area_name",                 field = "area.name" },
    7.89 +  { name = "issue_id",                  field = "issue.id" },
    7.90 +  {
    7.91 +    name = "issue_state",
    7.92 +    func = function(record)
    7.93 +      return record.issue.state
    7.94 +    end
    7.95 +  },
    7.96 +  {
    7.97 +    name = "issue_created",
    7.98 +    field = "issue.created",
    7.99 +    func = function(record)
   7.100 +      return format_timestamp(record.issue_created)
   7.101 +    end
   7.102 +  },
   7.103 +  {
   7.104 +    name = "issue_accepted",
   7.105 +    field = "issue.accepted",
   7.106 +    func = function(record)
   7.107 +      return format_timestamp(record.issue_accepted)
   7.108 +    end
   7.109 +  },
   7.110 +  {
   7.111 +    name = "issue_half_frozen",
   7.112 +    field = "issue.half_frozen",
   7.113 +    func = function(record)
   7.114 +      return format_timestamp(record.issue_half_frozen)
   7.115 +    end
   7.116 +  },
   7.117 +  {
   7.118 +    name = "issue_fully_frozen",
   7.119 +    field = "issue.fully_frozen",
   7.120 +    func = function(record)
   7.121 +      return format_timestamp(record.issue_fully_frozen)
   7.122 +    end
   7.123 +  },
   7.124 +  {
   7.125 +    name = "issue_closed",
   7.126 +    field = "issue.closed",
   7.127 +    func = function(record)
   7.128 +      return format_timestamp(record.issue_closed)
   7.129 +    end
   7.130 +  },
   7.131 +  { name = "issue_admission_time",      field = "issue.admission_time" },
   7.132 +  { name = "issue_discussion_time",     field = "issue.discussion_time" },
   7.133 +  { name = "issue_verification_time",   field = "issue.verification_time" },
   7.134 +  { name = "issue_voting_time",         field = "issue.voting_time" },
   7.135 +  { name = "issue_ranks_available",     field = "issue.ranks_available" },
   7.136 +
   7.137 +  { name = "policy_issue_quorum_num",   field = "policy.issue_quorum_num" },
   7.138 +  { name = "policy_issue_quorum_den",   field = "policy.issue_quorum_den" },
   7.139 +  { name = "policy_initiative_quorum_num",
   7.140 +                                        field = "policy.initiative_quorum_num" },
   7.141 +  { name = "policy_initiative_quorum_den",
   7.142 +                                        field = "policy.initiative_quorum_den" },
   7.143 +  { name = "policy_majority_num",       field = "policy.majority_num" },
   7.144 +  { name = "policy_majority_den",       field = "policy.majority_den" },
   7.145 +  { name = "policy_majority_strict",    field = "policy.majority_strict" },
   7.146 +  { name = "id",                        field = "initiative.id" },
   7.147 +  { name = "name",                      field = "initiative.name" },
   7.148 +  { name = "discussion_url",            field = "initiative.discussion_url" },
   7.149 +  {
   7.150 +    name = "created",
   7.151 +    field = "initiative.created",
   7.152 +    func = function(record)
   7.153 +      return format.timestamp(record.created)
   7.154 +    end
   7.155 +  },
   7.156 +  { name = "revoked",                   field = "initiative.revoked" },
   7.157 +  { name = "suggested_initiative_id",   field = "initiative.suggested_initiative_id" },
   7.158 +  { name = "admitted",                  field = "initiative.admitted" },
   7.159 +  { name = "issue_population",          field = "issue.population" },
   7.160 +  { name = "supporter_count",           field = "initiative.supporter_count" },
   7.161 +  { name = "informed_supporter_count",  field = "initiative.informed_supporter_count" },
   7.162 +  { name = "satisfied_supporter_count", field = "initiative.satisfied_supporter_count" },
   7.163 +  { name = "satisfied_informed_supporter_count",
   7.164 +                                        field = "initiative.satisfied_informed_supporter_count" },
   7.165 +  { name = "issue_vote_now",            field = "issue.vote_now" },
   7.166 +  { name = "issue_vote_later",          field = "issue.vote_later" },
   7.167 +  { name = "issue_voter_count",         field = "issue.voter_count" },
   7.168 +  { name = "positive_votes",            field = "initiative.positive_votes" },
   7.169 +  { name = "negative_votes",            field = "initiative.negative_votes" },
   7.170 +  { name = "agreed",                    field = "initiative.agreed" },
   7.171 +  { name = "rank",                      field = "initiative.rank" },
   7.172 +  {
   7.173 +    name = "current_draft_created",
   7.174 +    func = function(record)
   7.175 +      return format.timestamp(record.current_draft.created)
   7.176 +    end
   7.177 +  },
   7.178 +  {
   7.179 +    name = "current_draft_formatting_engine",
   7.180 +    func = function(record)
   7.181 +      return record.current_draft.formatting_engine
   7.182 +    end
   7.183 +  },
   7.184 +  {
   7.185 +    name = "current_draft_content",
   7.186 +    func = function(record)
   7.187 +      return record.current_draft.content
   7.188 +    end
   7.189 +  }
   7.190 +}
   7.191 +
   7.192 +util.autoapi{
   7.193 +  selector = initiatives_selector,
   7.194 +  fields = fields,
   7.195 +  api_engine = api_engine
   7.196 +}
   7.197 \ No newline at end of file
     8.1 --- a/app/main/area/_list.lua	Wed Mar 31 17:50:32 2010 +0200
     8.2 +++ b/app/main/area/_list.lua	Sun Apr 04 22:05:11 2010 +0200
     8.3 @@ -10,11 +10,17 @@
     8.4    :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL)", "issues_discussion_count")
     8.5    :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL AND issue.closed ISNULL)", "issues_frozen_count")
     8.6    :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.fully_frozen NOTNULL AND issue.closed ISNULL)", "issues_voting_count")
     8.7 -  :add_field({ "(SELECT COUNT(*) FROM issue LEFT JOIN direct_voter ON direct_voter.issue_id = issue.id AND direct_voter.member_id = ? WHERE issue.area_id = area.id AND issue.fully_frozen NOTNULL AND issue.closed ISNULL AND direct_voter.member_id ISNULL)", app.session.member.id }, "issues_to_vote_count")
     8.8    :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.fully_frozen NOTNULL AND issue.closed NOTNULL)", "issues_finished_count")
     8.9    :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.fully_frozen ISNULL AND issue.closed NOTNULL)", "issues_cancelled_count")
    8.10 -  :left_join("membership", "_membership", { "_membership.area_id = area.id AND _membership.member_id = ?", app.session.member.id })
    8.11 -  :add_field("_membership.member_id NOTNULL", "is_member", { "grouped" })
    8.12 +
    8.13 +if app.session.member_id then
    8.14 +  areas_selector
    8.15 +    :add_field({ "(SELECT COUNT(*) FROM issue LEFT JOIN direct_voter ON direct_voter.issue_id = issue.id AND direct_voter.member_id = ? WHERE issue.area_id = area.id AND issue.fully_frozen NOTNULL AND issue.closed ISNULL AND direct_voter.member_id ISNULL)", app.session.member.id }, "issues_to_vote_count")
    8.16 +    :left_join("membership", "_membership", { "_membership.area_id = area.id AND _membership.member_id = ?", app.session.member.id })
    8.17 +    :add_field("_membership.member_id NOTNULL", "is_member", { "grouped" })
    8.18 +else
    8.19 +  areas_selector:add_field("0", "issues_to_vote_count")
    8.20 +end
    8.21  
    8.22  local label_attr = { style = "text-align: right; width: 4em;" }
    8.23  local field_attr = { style = "text-align: right; width: 4em;" }
    8.24 @@ -242,13 +248,15 @@
    8.25  slot.put("<br /> &nbsp; ")
    8.26  
    8.27  
    8.28 -ui.image{
    8.29 -  attr = { title = title, alt = title },
    8.30 -  static = "icons/16/user_gray.png"
    8.31 -}
    8.32 -slot.put(" ")
    8.33 -slot.put(_"Member of area")
    8.34 -slot.put(" &nbsp; ")
    8.35 +if app.session.member_id then
    8.36 +  ui.image{
    8.37 +    attr = { title = title, alt = title },
    8.38 +    static = "icons/16/user_gray.png"
    8.39 +  }
    8.40 +  slot.put(" ")
    8.41 +  slot.put(_"Member of area")
    8.42 +  slot.put(" &nbsp; ")
    8.43 +end
    8.44  
    8.45  ui.image{
    8.46    attr = { title = title, alt = title },
     9.1 --- a/app/main/area/list.lua	Wed Mar 31 17:50:32 2010 +0200
     9.2 +++ b/app/main/area/list.lua	Sun Apr 04 22:05:11 2010 +0200
     9.3 @@ -1,4 +1,24 @@
     9.4 -slot.put_into("title", _'Area list')
     9.5 +if app.session.member_id then
     9.6 +  slot.put_into("title", _'Area list')
     9.7 +else
     9.8 +  slot.put_into("title", encode.html(config.app_title))
     9.9 +end
    9.10 +
    9.11 +local lang = locale.get("lang")
    9.12 +local basepath = request.get_app_basepath() 
    9.13 +local file_name = basepath .. "/locale/motd/" .. lang .. "_public.txt"
    9.14 +local file = io.open(file_name)
    9.15 +if file ~= nil then
    9.16 +  local help_text = file:read("*a")
    9.17 +  if #help_text > 0 then
    9.18 +    ui.container{
    9.19 +      attr = { class = "motd wiki" },
    9.20 +      content = function()
    9.21 +        slot.put(format.wiki_text(help_text))
    9.22 +      end
    9.23 +    }
    9.24 +  end
    9.25 +end
    9.26  
    9.27  util.help("area.list", _"Area list")
    9.28  
    10.1 --- a/app/main/area/show.lua	Wed Mar 31 17:50:32 2010 +0200
    10.2 +++ b/app/main/area/show.lua	Sun Apr 04 22:05:11 2010 +0200
    10.3 @@ -9,32 +9,36 @@
    10.4    end
    10.5  }
    10.6  
    10.7 -
    10.8 -slot.select("actions", function()
    10.9 -  ui.link{
   10.10 -    content = function()
   10.11 -      ui.image{ static = "icons/16/folder_add.png" }
   10.12 -      slot.put(_"Create new issue")
   10.13 -    end,
   10.14 -    module = "initiative",
   10.15 -    view = "new",
   10.16 -    params = { area_id = area.id }
   10.17 -  }
   10.18 -end)
   10.19 +if app.session.member_id then
   10.20 +  slot.select("actions", function()
   10.21 +    ui.link{
   10.22 +      content = function()
   10.23 +        ui.image{ static = "icons/16/folder_add.png" }
   10.24 +        slot.put(_"Create new issue")
   10.25 +      end,
   10.26 +      module = "initiative",
   10.27 +      view = "new",
   10.28 +      params = { area_id = area.id }
   10.29 +    }
   10.30 +  end)
   10.31 +end
   10.32  
   10.33  util.help("area.show")
   10.34  
   10.35 -execute.view{
   10.36 -  module = "membership",
   10.37 -  view = "_show_box",
   10.38 -  params = { area = area }
   10.39 -}
   10.40 +if app.session.member_id then
   10.41 +  execute.view{
   10.42 +    module = "membership",
   10.43 +    view = "_show_box",
   10.44 +    params = { area = area }
   10.45 +  }
   10.46  
   10.47 -execute.view{
   10.48 -  module = "delegation",
   10.49 -  view = "_show_box",
   10.50 -  params = { area_id = area.id }
   10.51 -}
   10.52 +  execute.view{
   10.53 +    module = "delegation",
   10.54 +    view = "_show_box",
   10.55 +    params = { area_id = area.id }
   10.56 +  }
   10.57 +
   10.58 +end
   10.59  
   10.60  --[[
   10.61  for i, issue in ipairs(area.issues) do
    11.1 --- a/app/main/area/show_tab.lua	Wed Mar 31 17:50:32 2010 +0200
    11.2 +++ b/app/main/area/show_tab.lua	Sun Apr 04 22:05:11 2010 +0200
    11.3 @@ -4,10 +4,13 @@
    11.4  local members_selector = area:get_reference_selector("members")
    11.5  local delegations_selector = area:get_reference_selector("delegations")
    11.6  
    11.7 -ui.tabs{
    11.8 +local tabs = {
    11.9    module = "area",
   11.10    view = "show_tab",
   11.11    static_params = { area_id = area.id },
   11.12 +}
   11.13 +
   11.14 +tabs[#tabs+1] =
   11.15    {
   11.16      name = "issues",
   11.17      label = _"Issues" .. " (" .. tostring(issues_selector:count()) .. ")",
   11.18 @@ -19,22 +22,28 @@
   11.19        filter = cgi.params["filter"],
   11.20        filter_voting = param.get("filter_voting")
   11.21      }
   11.22 -  },
   11.23 -  {
   11.24 -    name = "members",
   11.25 -    label = _"Members" .. " (" .. tostring(members_selector:count()) .. ")",
   11.26 -    icon = { static = "icons/16/group.png" },
   11.27 -    module = "member",
   11.28 -    view = "_list",
   11.29 -    params = { members_selector = members_selector }
   11.30 -  },
   11.31 -  {
   11.32 -    name = "delegations",
   11.33 -    label = _"Delegations" .. " (" .. tostring(delegations_selector:count()) .. ")",
   11.34 -    icon = { static = "icons/16/table_go.png" },
   11.35 -    module = "delegation",
   11.36 -    view = "_list",
   11.37 -    params = { delegations_selector = delegations_selector }
   11.38 -  },
   11.39 -}
   11.40 +  }
   11.41 +
   11.42 +if app.session.member_id then
   11.43 +  tabs[#tabs+1] =
   11.44 +    {
   11.45 +      name = "members",
   11.46 +      label = _"Members" .. " (" .. tostring(members_selector:count()) .. ")",
   11.47 +      icon = { static = "icons/16/group.png" },
   11.48 +      module = "member",
   11.49 +      view = "_list",
   11.50 +      params = { members_selector = members_selector }
   11.51 +    }
   11.52  
   11.53 +  tabs[#tabs+1] =
   11.54 +    {
   11.55 +      name = "delegations",
   11.56 +      label = _"Delegations" .. " (" .. tostring(delegations_selector:count()) .. ")",
   11.57 +      icon = { static = "icons/16/table_go.png" },
   11.58 +      module = "delegation",
   11.59 +      view = "_list",
   11.60 +      params = { delegations_selector = delegations_selector }
   11.61 +    }
   11.62 +end
   11.63 +
   11.64 +ui.tabs(tabs)
    12.1 --- a/app/main/draft/_list.lua	Wed Mar 31 17:50:32 2010 +0200
    12.2 +++ b/app/main/draft/_list.lua	Sun Apr 04 22:05:11 2010 +0200
    12.3 @@ -15,7 +15,11 @@
    12.4          {
    12.5            label = _"Author",
    12.6            content = function(record)
    12.7 -            ui.field.text{ readonly = true, value = record.author.name }
    12.8 +            if app.session.member_id or config.public_access == "pseudonym" then
    12.9 +              ui.field.text{ readonly = true, value = record.author.name }
   12.10 +            else
   12.11 +              ui.field.text{ readonly = true, value = _"[not displayed public]" }
   12.12 +            end
   12.13            end
   12.14          },
   12.15          {
    13.1 --- a/app/main/draft/_show.lua	Wed Mar 31 17:50:32 2010 +0200
    13.2 +++ b/app/main/draft/_show.lua	Sun Apr 04 22:05:11 2010 +0200
    13.3 @@ -6,15 +6,28 @@
    13.4    readonly = true,
    13.5    content = function()
    13.6  
    13.7 -    ui.field.text{ 
    13.8 -      label = _"Last author",
    13.9 -      value = _(
   13.10 -        "#{author} at #{date}", {
   13.11 -          author = draft.author_name,
   13.12 -          date = format.timestamp(draft.created)
   13.13 -        }
   13.14 -      )
   13.15 -    }
   13.16 +    if app.session.member_id or config.public_access == "pseudonym" then
   13.17 +      ui.field.text{
   13.18 +        label = _"Last author",
   13.19 +        value = _(
   13.20 +          "#{author} at #{date}", {
   13.21 +            author = draft.author_name,
   13.22 +            date = format.timestamp(draft.created)
   13.23 +          }
   13.24 +        )
   13.25 +      }
   13.26 +    else
   13.27 +      ui.field.text{
   13.28 +        label = _"Last author",
   13.29 +        value = _(
   13.30 +          "#{author} at #{date}", {
   13.31 +            author = "[not displayed public]",
   13.32 +            date = format.timestamp(draft.created)
   13.33 +          }
   13.34 +        )
   13.35 +      }
   13.36 +    end
   13.37 +
   13.38      ui.container{
   13.39        attr = { class = "draft_content wiki" },
   13.40        content = function()
    14.1 --- a/app/main/index/login.lua	Wed Mar 31 17:50:32 2010 +0200
    14.2 +++ b/app/main/index/login.lua	Sun Apr 04 22:05:11 2010 +0200
    14.3 @@ -44,27 +44,9 @@
    14.4  end)
    14.5  
    14.6  
    14.7 -local lang = locale.get("lang")
    14.8 -local basepath = request.get_app_basepath() 
    14.9 -local file_name = basepath .. "/locale/motd/" .. lang .. "_public.txt"
   14.10 -local file = io.open(file_name)
   14.11 -if file ~= nil then
   14.12 -  local help_text = file:read("*a")
   14.13 -  if #help_text > 0 then
   14.14 -    ui.container{
   14.15 -      attr = { class = "motd wiki" },
   14.16 -      content = function()
   14.17 -        slot.put(format.wiki_text(help_text))
   14.18 -      end
   14.19 -    }
   14.20 -  end
   14.21 -end
   14.22 -
   14.23 -
   14.24 -
   14.25  ui.tag{
   14.26    tag = 'p',
   14.27 -  content = _'You need to be logged in, to use this system.'
   14.28 +  content = _'You need to be logged in, to use all features of this system.'
   14.29  }
   14.30  
   14.31  ui.form{
   14.32 @@ -74,8 +56,9 @@
   14.33    routing = {
   14.34      ok = {
   14.35        mode   = 'redirect',
   14.36 -      module = 'index',
   14.37 -      view   = 'index'
   14.38 +      module = param.get("redirect_module") or "index",
   14.39 +      view = param.get("redirect_view") or "index",
   14.40 +      id = param.get("redirect_id"),
   14.41      },
   14.42      error = {
   14.43        mode   = 'forward',
   14.44 @@ -102,3 +85,27 @@
   14.45    end
   14.46  }
   14.47  
   14.48 +if config.auth_openid_enabled then
   14.49 +  ui.form{
   14.50 +    attr = { class = "login" },
   14.51 +    module = 'openid',
   14.52 +    action = 'initiate',
   14.53 +    routing = {
   14.54 +      default = {
   14.55 +        mode   = 'forward',
   14.56 +        module = 'index',
   14.57 +        view   = 'login',
   14.58 +      }
   14.59 +    },
   14.60 +    content = function()
   14.61 +      ui.field.text{
   14.62 +        label     = _'OpenID',
   14.63 +        html_name = 'openid_identifier',
   14.64 +        value     = ''
   14.65 +      }
   14.66 +      ui.submit{
   14.67 +        text = _'OpenID Login'
   14.68 +      }
   14.69 +    end
   14.70 +  }
   14.71 +end
    15.1 --- a/app/main/initiative/_list.lua	Wed Mar 31 17:50:32 2010 +0200
    15.2 +++ b/app/main/initiative/_list.lua	Sun Apr 04 22:05:11 2010 +0200
    15.3 @@ -3,14 +3,19 @@
    15.4  local issue = param.get("issue", "table")
    15.5  
    15.6  local initiatives_selector = param.get("initiatives_selector", "table")
    15.7 +
    15.8  initiatives_selector
    15.9    :join("issue", nil, "issue.id = initiative.issue_id")
   15.10 -  :left_join("initiator", "_initiator", { "_initiator.initiative_id = initiative.id AND _initiator.member_id = ?", app.session.member.id} )
   15.11 -  :left_join("supporter", "_supporter", { "_supporter.initiative_id = initiative.id AND _supporter.member_id = ?", app.session.member.id} )
   15.12  
   15.13 -  :add_field("(_initiator.member_id NOTNULL)", "is_initiator")
   15.14 -  :add_field({"(_supporter.member_id NOTNULL) AND NOT EXISTS(SELECT 1 FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)))", app.session.member.id }, "is_supporter")
   15.15 -  :add_field({"EXISTS(SELECT 1 FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)))", app.session.member.id }, "is_potential_supporter")
   15.16 +if app.session.member_id then
   15.17 +  initiatives_selector
   15.18 +    :left_join("initiator", "_initiator", { "_initiator.initiative_id = initiative.id AND _initiator.member_id = ?", app.session.member.id} )
   15.19 +    :left_join("supporter", "_supporter", { "_supporter.initiative_id = initiative.id AND _supporter.member_id = ?", app.session.member.id} )
   15.20 +  
   15.21 +    :add_field("(_initiator.member_id NOTNULL)", "is_initiator")
   15.22 +    :add_field({"(_supporter.member_id NOTNULL) AND NOT EXISTS(SELECT 1 FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)))", app.session.member.id }, "is_supporter")
   15.23 +    :add_field({"EXISTS(SELECT 1 FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)))", app.session.member.id }, "is_potential_supporter")
   15.24 +end
   15.25  
   15.26  local initiatives_count = initiatives_selector:count()
   15.27  
   15.28 @@ -208,7 +213,7 @@
   15.29      }
   15.30    end
   15.31  
   15.32 -  if not (issue.fully_frozen or issue.closed) then
   15.33 +  if app.session.member_id and not (issue.fully_frozen or issue.closed) then
   15.34      slot.put(" ")
   15.35      ui.link{
   15.36        content = function()
    16.1 --- a/app/main/initiative/_show.lua	Wed Mar 31 17:50:32 2010 +0200
    16.2 +++ b/app/main/initiative/_show.lua	Sun Apr 04 22:05:11 2010 +0200
    16.3 @@ -120,10 +120,14 @@
    16.4  end
    16.5  
    16.6  
    16.7 -local supporter = app.session.member:get_reference_selector("supporters")
    16.8 -  :add_where{ "initiative_id = ?", initiative.id }
    16.9 -  :optional_object_mode()
   16.10 -  :exec()
   16.11 +local supporter
   16.12 +
   16.13 +if app.session.member_id then
   16.14 +  supporter = app.session.member:get_reference_selector("supporters")
   16.15 +    :add_where{ "initiative_id = ?", initiative.id }
   16.16 +    :optional_object_mode()
   16.17 +    :exec()
   16.18 +end
   16.19  
   16.20  if supporter and not initiative.issue.closed then
   16.21    local old_draft_id = supporter.draft_id
   16.22 @@ -164,21 +168,22 @@
   16.23  end
   16.24  
   16.25  
   16.26 -
   16.27 -ui.container{
   16.28 -  attr = {
   16.29 -    id = "initiative_" .. tostring(initiative.id) .. "_support"
   16.30 -  },
   16.31 -  content = function()
   16.32 -    execute.view{
   16.33 -      module = "initiative",
   16.34 -      view = "show_support",
   16.35 -      params = {
   16.36 -        initiative = initiative
   16.37 +if app.session.member_id then
   16.38 +  ui.container{
   16.39 +    attr = {
   16.40 +      id = "initiative_" .. tostring(initiative.id) .. "_support"
   16.41 +    },
   16.42 +    content = function()
   16.43 +      execute.view{
   16.44 +        module = "initiative",
   16.45 +        view = "show_support",
   16.46 +        params = {
   16.47 +          initiative = initiative
   16.48 +        }
   16.49        }
   16.50 -    }
   16.51 -  end
   16.52 -}
   16.53 +    end
   16.54 +  }
   16.55 +end
   16.56  
   16.57  if (initiative.discussion_url and #initiative.discussion_url > 0)
   16.58    or (initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked) then
    17.1 --- a/app/main/initiative/_suggestions.lua	Wed Mar 31 17:50:32 2010 +0200
    17.2 +++ b/app/main/initiative/_suggestions.lua	Sun Apr 04 22:05:11 2010 +0200
    17.3 @@ -1,6 +1,6 @@
    17.4  local initiative = param.get("initiative", "table")
    17.5  
    17.6 -if not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
    17.7 +if app.session.member_id and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
    17.8    ui.link{
    17.9      content = function()
   17.10        ui.image{ static = "icons/16/comment_add.png" }
    18.1 --- a/app/main/initiative/show_partial.lua	Wed Mar 31 17:50:32 2010 +0200
    18.2 +++ b/app/main/initiative/show_partial.lua	Sun Apr 04 22:05:11 2010 +0200
    18.3 @@ -7,7 +7,10 @@
    18.4  end
    18.5  
    18.6  -- TODO performance
    18.7 -local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
    18.8 +local initiator
    18.9 +if app.session.member_id then
   18.10 +  initiator = Initiator:by_pk(initiative.id, app.session.member.id)
   18.11 +end
   18.12  
   18.13  ui.partial{
   18.14    module = "initiative",
    19.1 --- a/app/main/initiative/show_static.lua	Wed Mar 31 17:50:32 2010 +0200
    19.2 +++ b/app/main/initiative/show_static.lua	Sun Apr 04 22:05:11 2010 +0200
    19.3 @@ -24,19 +24,20 @@
    19.4  
    19.5  --slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(initiative.id) .. '.rss" />')
    19.6  
    19.7 -
    19.8 -slot.select("actions", function()
    19.9 -  if not initiative.issue.fully_frozen and not initiative.issue.closed then
   19.10 -    ui.link{
   19.11 -      image  = { static = "icons/16/script_add.png" },
   19.12 -      attr   = { class = "action" },
   19.13 -      text   = _"Create alternative initiative",
   19.14 -      module = "initiative",
   19.15 -      view   = "new",
   19.16 -      params = { issue_id = initiative.issue.id }
   19.17 -    }
   19.18 -  end
   19.19 -end)
   19.20 +if app.session.member_id then
   19.21 +  slot.select("actions", function()
   19.22 +    if not initiative.issue.fully_frozen and not initiative.issue.closed then
   19.23 +      ui.link{
   19.24 +        image  = { static = "icons/16/script_add.png" },
   19.25 +        attr   = { class = "action" },
   19.26 +        text   = _"Create alternative initiative",
   19.27 +        module = "initiative",
   19.28 +        view   = "new",
   19.29 +        params = { issue_id = initiative.issue.id }
   19.30 +      }
   19.31 +    end
   19.32 +  end)
   19.33 +end
   19.34  
   19.35  slot.put_into("sub_title", encode.html(_("Initiative: '#{name}'", { name = initiative.name }) ))
   19.36  
    20.1 --- a/app/main/initiative/show_tab.lua	Wed Mar 31 17:50:32 2010 +0200
    20.2 +++ b/app/main/initiative/show_tab.lua	Sun Apr 04 22:05:11 2010 +0200
    20.3 @@ -5,7 +5,7 @@
    20.4    initiative = Initiative:by_id(param.get("initiative_id", atom.number))
    20.5  end
    20.6  
    20.7 -if not initiator then
    20.8 +if not initiator and app.session.member_id then
    20.9    initiator = Initiator:by_pk(initiative.id, app.session.member.id)
   20.10  end
   20.11  
   20.12 @@ -32,17 +32,19 @@
   20.13    }
   20.14  }
   20.15  
   20.16 -if initiative.issue.ranks_available then
   20.17 -  tabs[#tabs+1] = {
   20.18 -    name = "voting",
   20.19 -    label = _"Voting details",
   20.20 -    icon = { static = "icons/16/email_open.png" },
   20.21 -    module = "initiative",
   20.22 -    view = "_show_voting",
   20.23 -    params = {
   20.24 -      initiative = initiative
   20.25 +if app.session.member_id then
   20.26 +  if initiative.issue.ranks_available then
   20.27 +    tabs[#tabs+1] = {
   20.28 +      name = "voting",
   20.29 +      label = _"Voting details",
   20.30 +      icon = { static = "icons/16/email_open.png" },
   20.31 +      module = "initiative",
   20.32 +      view = "_show_voting",
   20.33 +      params = {
   20.34 +        initiative = initiative
   20.35 +      }
   20.36      }
   20.37 -  }
   20.38 +  end
   20.39  end
   20.40  
   20.41  local suggestion_count = initiative:get_reference_selector("suggestions"):count()
   20.42 @@ -58,90 +60,92 @@
   20.43    }
   20.44  }
   20.45  
   20.46 -local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
   20.47 -          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
   20.48 -          :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")
   20.49 -          :add_field("direct_interest_snapshot.weight")
   20.50 -          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
   20.51 -          :add_where("direct_supporter_snapshot.satisfied")
   20.52 -          :add_field("direct_supporter_snapshot.informed", "is_informed")
   20.53 -
   20.54 -local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
   20.55 -local direct_satisfied_supporter_count = tmp.count
   20.56 -local indirect_satisfied_supporter_count = (tmp.weight or 0) - tmp.count
   20.57 -
   20.58 -local count_string
   20.59 -if indirect_satisfied_supporter_count > 0 then
   20.60 -  count_string = "(" .. tostring(direct_satisfied_supporter_count) .. "+" .. tostring(indirect_satisfied_supporter_count) .. ")"
   20.61 -else
   20.62 -  count_string = "(" .. tostring(direct_satisfied_supporter_count) .. ")"
   20.63 -end
   20.64 -
   20.65 -tabs[#tabs+1] = {
   20.66 -  name = "satisfied_supporter",
   20.67 -  label = _"Supporter" .. " " .. count_string,
   20.68 -  icon = { static = "icons/16/thumb_up_green.png" },
   20.69 -  module = "member",
   20.70 -  view = "_list",
   20.71 -  params = {
   20.72 -    initiative = initiative,
   20.73 -    members_selector = members_selector
   20.74 +if app.session.member_id then
   20.75 +  local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
   20.76 +            :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
   20.77 +            :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")
   20.78 +            :add_field("direct_interest_snapshot.weight")
   20.79 +            :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
   20.80 +            :add_where("direct_supporter_snapshot.satisfied")
   20.81 +            :add_field("direct_supporter_snapshot.informed", "is_informed")
   20.82 +  
   20.83 +  local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
   20.84 +  local direct_satisfied_supporter_count = tmp.count
   20.85 +  local indirect_satisfied_supporter_count = (tmp.weight or 0) - tmp.count
   20.86 +  
   20.87 +  local count_string
   20.88 +  if indirect_satisfied_supporter_count > 0 then
   20.89 +    count_string = "(" .. tostring(direct_satisfied_supporter_count) .. "+" .. tostring(indirect_satisfied_supporter_count) .. ")"
   20.90 +  else
   20.91 +    count_string = "(" .. tostring(direct_satisfied_supporter_count) .. ")"
   20.92 +  end
   20.93 +  
   20.94 +  tabs[#tabs+1] = {
   20.95 +    name = "satisfied_supporter",
   20.96 +    label = _"Supporter" .. " " .. count_string,
   20.97 +    icon = { static = "icons/16/thumb_up_green.png" },
   20.98 +    module = "member",
   20.99 +    view = "_list",
  20.100 +    params = {
  20.101 +      initiative = initiative,
  20.102 +      members_selector = members_selector
  20.103 +    }
  20.104    }
  20.105 -}
  20.106 -
  20.107 -local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
  20.108 -          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
  20.109 -          :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")
  20.110 -          :add_field("direct_interest_snapshot.weight")
  20.111 -          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
  20.112 -          :add_where("NOT direct_supporter_snapshot.satisfied")
  20.113 -          :add_field("direct_supporter_snapshot.informed", "is_informed")
  20.114 -
  20.115 -local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
  20.116 -local direct_potential_supporter_count = tmp.count
  20.117 -local indirect_potential_supporter_count = (tmp.weight or 0) - tmp.count
  20.118 -
  20.119 -local count_string
  20.120 -if indirect_potential_supporter_count > 0 then
  20.121 -  count_string = "(" .. tostring(direct_potential_supporter_count) .. "+" .. tostring(indirect_potential_supporter_count) .. ")"
  20.122 -else
  20.123 -  count_string = "(" .. tostring(direct_potential_supporter_count) .. ")"
  20.124 +  
  20.125 +  local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
  20.126 +            :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
  20.127 +            :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")
  20.128 +            :add_field("direct_interest_snapshot.weight")
  20.129 +            :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
  20.130 +            :add_where("NOT direct_supporter_snapshot.satisfied")
  20.131 +            :add_field("direct_supporter_snapshot.informed", "is_informed")
  20.132 +  
  20.133 +  local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
  20.134 +  local direct_potential_supporter_count = tmp.count
  20.135 +  local indirect_potential_supporter_count = (tmp.weight or 0) - tmp.count
  20.136 +  
  20.137 +  local count_string
  20.138 +  if indirect_potential_supporter_count > 0 then
  20.139 +    count_string = "(" .. tostring(direct_potential_supporter_count) .. "+" .. tostring(indirect_potential_supporter_count) .. ")"
  20.140 +  else
  20.141 +    count_string = "(" .. tostring(direct_potential_supporter_count) .. ")"
  20.142 +  end
  20.143 +  
  20.144 +  tabs[#tabs+1] = {
  20.145 +    name = "supporter",
  20.146 +    label = _"Potential supporter" .. " " .. count_string,
  20.147 +    icon = { static = "icons/16/thumb_up.png" },
  20.148 +    module = "member",
  20.149 +    view = "_list",
  20.150 +    params = {
  20.151 +      initiative = initiative,
  20.152 +      members_selector = members_selector
  20.153 +    }
  20.154 +  }
  20.155 +  
  20.156 +  local initiators_members_selector = initiative:get_reference_selector("initiating_members")
  20.157 +    :add_field("initiator.accepted", "accepted")
  20.158 +  
  20.159 +  if not (initiator and initiator.accepted) then
  20.160 +    initiators_members_selector:add_where("initiator.accepted")
  20.161 +  end
  20.162 +  
  20.163 +  local initiator_count = initiators_members_selector:count()
  20.164 +  
  20.165 +  tabs[#tabs+1] = {
  20.166 +    name = "initiators",
  20.167 +    label = _"Initiators" .. " (" .. tostring(initiator_count) .. ")",
  20.168 +    icon = { static = "icons/16/user_edit.png" },
  20.169 +    module = "initiative",
  20.170 +    view = "_initiators",
  20.171 +    params = {
  20.172 +      initiative = initiative,
  20.173 +      initiator = initiator,
  20.174 +      initiators_members_selector = initiators_members_selector
  20.175 +    }
  20.176 +  }
  20.177  end
  20.178  
  20.179 -tabs[#tabs+1] = {
  20.180 -  name = "supporter",
  20.181 -  label = _"Potential supporter" .. " " .. count_string,
  20.182 -  icon = { static = "icons/16/thumb_up.png" },
  20.183 -  module = "member",
  20.184 -  view = "_list",
  20.185 -  params = {
  20.186 -    initiative = initiative,
  20.187 -    members_selector = members_selector
  20.188 -  }
  20.189 -}
  20.190 -
  20.191 -local initiators_members_selector = initiative:get_reference_selector("initiating_members")
  20.192 -  :add_field("initiator.accepted", "accepted")
  20.193 -
  20.194 -if not (initiator and initiator.accepted) then
  20.195 -  initiators_members_selector:add_where("initiator.accepted")
  20.196 -end
  20.197 -
  20.198 -local initiator_count = initiators_members_selector:count()
  20.199 -
  20.200 -tabs[#tabs+1] = {
  20.201 -  name = "initiators",
  20.202 -  label = _"Initiators" .. " (" .. tostring(initiator_count) .. ")",
  20.203 -  icon = { static = "icons/16/user_edit.png" },
  20.204 -  module = "initiative",
  20.205 -  view = "_initiators",
  20.206 -  params = {
  20.207 -    initiative = initiative,
  20.208 -    initiator = initiator,
  20.209 -    initiators_members_selector = initiators_members_selector
  20.210 -  }
  20.211 -}
  20.212 -
  20.213  local drafts_count = initiative:get_reference_selector("drafts"):count()
  20.214  
  20.215  tabs[#tabs+1] = {
    21.1 --- a/app/main/issue/_list.lua	Wed Mar 31 17:50:32 2010 +0200
    21.2 +++ b/app/main/issue/_list.lua	Sun Apr 04 22:05:11 2010 +0200
    21.3 @@ -1,8 +1,10 @@
    21.4  local issues_selector = param.get("issues_selector", "table")
    21.5  
    21.6 -issues_selector
    21.7 -  :left_join("interest", "_interest", { "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id} )
    21.8 -  :add_field("(_interest.member_id NOTNULL)", "is_interested")
    21.9 +if app.session.member_id then
   21.10 +  issues_selector
   21.11 +    :left_join("interest", "_interest", { "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id} )
   21.12 +    :add_field("(_interest.member_id NOTNULL)", "is_interested")
   21.13 +end
   21.14  
   21.15  ui.add_partial_param_names{
   21.16    "filter",
   21.17 @@ -265,9 +267,9 @@
   21.18                    issue = record,
   21.19                    initiatives_selector = initiatives_selector,
   21.20                    highlight_string = highlight_string,
   21.21 -                  per_page = tonumber(app.session.member:get_setting_value("initiatives_preview_limit") or 3),
   21.22 +                  per_page = app.session.member_id and tonumber(app.session.member:get_setting_value("initiatives_preview_limit") or 3) or 3,
   21.23                    no_sort = true,
   21.24 -                  limit = tonumber(app.session.member:get_setting_value("initiatives_preview_limit") or 3)
   21.25 +                  limit = app.session.member_id and tonumber(app.session.member:get_setting_value("initiatives_preview_limit") or 3) or 3
   21.26                  }
   21.27                }
   21.28              end
    22.1 --- a/app/main/issue/_show_head.lua	Wed Mar 31 17:50:32 2010 +0200
    22.2 +++ b/app/main/issue/_show_head.lua	Sun Apr 04 22:05:11 2010 +0200
    22.3 @@ -1,6 +1,10 @@
    22.4  local issue = param.get("issue", "table")
    22.5  
    22.6 -local direct_voter = DirectVoter:by_pk(issue.id, app.session.member.id)
    22.7 +local direct_voter
    22.8 +
    22.9 +if app.session.member_id then
   22.10 +  direct_voter = DirectVoter:by_pk(issue.id, app.session.member.id)
   22.11 +end
   22.12  
   22.13  slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(issue.id) .. '.rss" />')
   22.14  
   22.15 @@ -31,43 +35,47 @@
   22.16  
   22.17  slot.select("actions", function()
   22.18  
   22.19 -  if issue.state == 'voting' then
   22.20 -    local text
   22.21 -    if not direct_voter then
   22.22 -      text = _"Vote now"
   22.23 -    else
   22.24 -      text = _"Change vote"
   22.25 +  if app.session.member_id then
   22.26 +
   22.27 +    if issue.state == 'voting' then
   22.28 +      local text
   22.29 +      if not direct_voter then
   22.30 +        text = _"Vote now"
   22.31 +      else
   22.32 +        text = _"Change vote"
   22.33 +      end
   22.34 +      ui.link{
   22.35 +        content = function()
   22.36 +          ui.image{ static = "icons/16/email_open.png" }
   22.37 +          slot.put(text)
   22.38 +        end,
   22.39 +        module = "vote",
   22.40 +        view = "list",
   22.41 +        params = { issue_id = issue.id }
   22.42 +      }
   22.43      end
   22.44 -    ui.link{
   22.45 -      content = function()
   22.46 -        ui.image{ static = "icons/16/email_open.png" }
   22.47 -        slot.put(text)
   22.48 -      end,
   22.49 -      module = "vote",
   22.50 -      view = "list",
   22.51 -      params = { issue_id = issue.id }
   22.52 -    }
   22.53 -  end
   22.54  
   22.55 -  execute.view{
   22.56 -    module = "interest",
   22.57 -    view = "_show_box",
   22.58 -    params = { issue = issue }
   22.59 -  }
   22.60 -
   22.61 -  if not issue.closed then
   22.62      execute.view{
   22.63 -      module = "delegation",
   22.64 +      module = "interest",
   22.65        view = "_show_box",
   22.66 -      params = { issue_id = issue.id }
   22.67 +      params = { issue = issue }
   22.68      }
   22.69 -  end
   22.70  
   22.71 -  execute.view{
   22.72 -    module = "issue",
   22.73 -    view = "_show_vote_later_box",
   22.74 -    params = { issue = issue }
   22.75 -  }
   22.76 +    if not issue.closed then
   22.77 +      execute.view{
   22.78 +        module = "delegation",
   22.79 +        view = "_show_box",
   22.80 +        params = { issue_id = issue.id }
   22.81 +      }
   22.82 +    end
   22.83 +
   22.84 +    execute.view{
   22.85 +      module = "issue",
   22.86 +      view = "_show_vote_later_box",
   22.87 +      params = { issue = issue }
   22.88 +    }
   22.89 +
   22.90 +  end
   22.91  
   22.92    if config.issue_discussion_url_func then
   22.93      local url = config.issue_discussion_url_func(issue)
   22.94 @@ -98,14 +106,16 @@
   22.95      content = function()
   22.96        slot.put(_"Voting for this issue is currently running!")
   22.97        slot.put(" ")
   22.98 -      ui.link{
   22.99 -        content = function()
  22.100 -          slot.put(_"Vote now")
  22.101 -        end,
  22.102 -        module = "vote",
  22.103 -        view = "list",
  22.104 -        params = { issue_id = issue.id }
  22.105 -      }
  22.106 +      if app.session.member_id then
  22.107 +        ui.link{
  22.108 +          content = function()
  22.109 +            slot.put(_"Vote now")
  22.110 +          end,
  22.111 +          module = "vote",
  22.112 +          view = "list",
  22.113 +          params = { issue_id = issue.id }
  22.114 +        }
  22.115 +      end
  22.116      end
  22.117    }
  22.118    slot.put("<br />")
    23.1 --- a/app/main/issue/show_tab.lua	Wed Mar 31 17:50:32 2010 +0200
    23.2 +++ b/app/main/issue/show_tab.lua	Sun Apr 04 22:05:11 2010 +0200
    23.3 @@ -22,41 +22,51 @@
    23.4  
    23.5  local delegations_selector = issue:get_reference_selector("delegations")
    23.6  
    23.7 -
    23.8 -ui.tabs{
    23.9 +local tabs = {
   23.10    module = "issue",
   23.11    view = "show_tab",
   23.12    static_params = { issue_id = issue.id },
   23.13 -  {
   23.14 -    name = "interested_members",
   23.15 -    label = _"Interested members" .. " (" .. tostring(interested_members_selector:count()) .. ")" ,
   23.16 -    icon = { static = "icons/16/eye.png" },
   23.17 -    module = "member",
   23.18 -    view = "_list",
   23.19 -    params = {
   23.20 -      issue = issue,
   23.21 -      members_selector = interested_members_selector
   23.22 +}
   23.23 +
   23.24 +if app.session.member_id then
   23.25 +  tabs[#tabs+1] =
   23.26 +    {
   23.27 +      name = "interested_members",
   23.28 +      label = _"Interested members" .. " (" .. tostring(interested_members_selector:count()) .. ")" ,
   23.29 +      icon = { static = "icons/16/eye.png" },
   23.30 +      module = "member",
   23.31 +      view = "_list",
   23.32 +      params = {
   23.33 +        issue = issue,
   23.34 +        members_selector = interested_members_selector
   23.35 +      }
   23.36      }
   23.37 -  },
   23.38 -  {
   23.39 -    name = "voting_requests",
   23.40 -    label = _"Vote later requests" .. " (" .. tostring(voting_requests_selector:count()) .. ") (" .. tostring(voting_requested_percentage) ..  "%)",
   23.41 -    icon = { static = "icons/16/clock_play.png" },
   23.42 -    module = "member",
   23.43 -    view = "_list",
   23.44 -    params = {
   23.45 -      issue = issue,
   23.46 -      members_selector = voting_requests_selector
   23.47 +
   23.48 +  tabs[#tabs+1] =
   23.49 +    {
   23.50 +      name = "voting_requests",
   23.51 +      label = _"Vote later requests" .. " (" .. tostring(voting_requests_selector:count()) .. ") (" .. tostring(voting_requested_percentage) ..  "%)",
   23.52 +      icon = { static = "icons/16/clock_play.png" },
   23.53 +      module = "member",
   23.54 +      view = "_list",
   23.55 +      params = {
   23.56 +        issue = issue,
   23.57 +        members_selector = voting_requests_selector
   23.58 +      }
   23.59      }
   23.60 -  },
   23.61 -  {
   23.62 -    name = "delegations",
   23.63 -    label = _"Delegations" .. " (" .. tostring(delegations_selector:count()) .. ")" ,
   23.64 -    icon = { static = "icons/16/table_go.png" },
   23.65 -    module = "delegation",
   23.66 -    view = "_list",
   23.67 -    params = { delegations_selector = delegations_selector }
   23.68 -  },
   23.69 +
   23.70 +  tabs[#tabs+1] =
   23.71 +    {
   23.72 +      name = "delegations",
   23.73 +      label = _"Delegations" .. " (" .. tostring(delegations_selector:count()) .. ")" ,
   23.74 +      icon = { static = "icons/16/table_go.png" },
   23.75 +      module = "delegation",
   23.76 +      view = "_list",
   23.77 +      params = { delegations_selector = delegations_selector }
   23.78 +    }
   23.79 +end
   23.80 +
   23.81 +tabs[#tabs+1] =
   23.82    {
   23.83      name = "details",
   23.84      label = _"Details",
   23.85 @@ -64,7 +74,8 @@
   23.86      module = "issue",
   23.87      view = "_details",
   23.88      params = { issue = issue }
   23.89 -  },
   23.90 -}
   23.91 +  }
   23.92 +
   23.93 +ui.tabs(tabs)
   23.94  
   23.95  
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/app/main/member/_action/update_api_key.lua	Sun Apr 04 22:05:11 2010 +0200
    24.3 @@ -0,0 +1,54 @@
    24.4 +
    24.5 +local setting_key = "liquidfeedback_frontend_api_key"
    24.6 +local setting = Setting:by_pk(app.session.member.id, setting_key)
    24.7 +
    24.8 +local api_key
    24.9 +
   24.10 +if param.get("delete", atom.boolean) then
   24.11 +
   24.12 +  if setting then
   24.13 +    setting:destroy()
   24.14 +  end
   24.15 +
   24.16 +else
   24.17 +
   24.18 +  if not setting then
   24.19 +    setting = Setting:new()
   24.20 +    setting.member_id = app.session.member.id
   24.21 +    setting.key = setting_key
   24.22 +  end
   24.23 +
   24.24 +  api_key = multirand.string(
   24.25 +    20,
   24.26 +    '23456789BCDFGHJKLMNPQRSTVWXYZbcdfghjkmnpqrstvwxyz'
   24.27 +  )
   24.28 +
   24.29 +  setting.value = api_key
   24.30 +
   24.31 +  setting:save()
   24.32 +end
   24.33 +
   24.34 +
   24.35 +local setting_key = "liquidfeedback_frontend_api_key_history"
   24.36 +
   24.37 +setting = SettingMap:new()
   24.38 +setting.member_id = app.session.member.id
   24.39 +setting.key = setting_key
   24.40 +setting.subkey = db:query("SELECT now()")[1].now
   24.41 +setting.value = api_key or ""
   24.42 +local dberr = setting:try_save()
   24.43 +
   24.44 +if dberr then
   24.45 +  if dberr:is_kind_of("IntegrityConstraintViolation.UniqueViolation") then
   24.46 +    slot.put_into("error", _"The API key has been changed too fast.")
   24.47 +    return
   24.48 +  else
   24.49 +    dberr:escalate()
   24.50 +  end
   24.51 +end
   24.52 +
   24.53 +if not api_key then
   24.54 +  slot.put_into("notice", _"API key has been deleted")
   24.55 +else
   24.56 +  slot.put_into("notice", _"API key has been updated")
   24.57 +end
    25.1 --- a/app/main/member/_show_thumb.lua	Wed Mar 31 17:50:32 2010 +0200
    25.2 +++ b/app/main/member/_show_thumb.lua	Sun Apr 04 22:05:11 2010 +0200
    25.3 @@ -124,15 +124,17 @@
    25.4          end
    25.5  
    25.6          -- TODO performance
    25.7 -        local contact = Contact:by_pk(app.session.member.id, member.id)
    25.8 -        if contact then
    25.9 -          ui.image{
   25.10 -            attr = { 
   25.11 -              alt   = _"You have saved this member as contact",
   25.12 -              title = _"You have saved this member as contact"
   25.13 -            },
   25.14 -            static = "icons/16/bullet_disk.png"
   25.15 -          }
   25.16 +        if app.session.member_id then
   25.17 +          local contact = Contact:by_pk(app.session.member.id, member.id)
   25.18 +          if contact then
   25.19 +            ui.image{
   25.20 +              attr = { 
   25.21 +                alt   = _"You have saved this member as contact",
   25.22 +                title = _"You have saved this member as contact"
   25.23 +              },
   25.24 +              static = "icons/16/bullet_disk.png"
   25.25 +            }
   25.26 +          end
   25.27          end
   25.28        end
   25.29      }
    26.1 --- a/app/main/member/developer_settings.lua	Wed Mar 31 17:50:32 2010 +0200
    26.2 +++ b/app/main/member/developer_settings.lua	Sun Apr 04 22:05:11 2010 +0200
    26.3 @@ -11,26 +11,89 @@
    26.4    }
    26.5  end)
    26.6  
    26.7 -ui.form{
    26.8 -  attr = { class = "vertical" },
    26.9 -  module = "member",
   26.10 -  action = "update_stylesheet_url",
   26.11 -  routing = {
   26.12 -    ok = {
   26.13 -      mode = "redirect",
   26.14 -      module = "index",
   26.15 -      view = "index"
   26.16 +  local setting_key = "liquidfeedback_frontend_developer_features"
   26.17 +  local setting = Setting:by_pk(app.session.member.id, setting_key)
   26.18 +
   26.19 +  if setting then
   26.20 +    ui.form{
   26.21 +      attr = { class = "vertical" },
   26.22 +      module = "member",
   26.23 +      action = "update_stylesheet_url",
   26.24 +      routing = {
   26.25 +        ok = {
   26.26 +          mode = "redirect",
   26.27 +          module = "index",
   26.28 +          view = "index"
   26.29 +        }
   26.30 +      },
   26.31 +      content = function()
   26.32 +        local setting_key = "liquidfeedback_frontend_stylesheet_url"
   26.33 +        local setting = Setting:by_pk(app.session.member.id, setting_key)
   26.34 +        local value = setting and setting.value
   26.35 +        ui.field.text{ 
   26.36 +          label = _"Stylesheet URL",
   26.37 +          name = "stylesheet_url",
   26.38 +          value = value
   26.39 +        }
   26.40 +        ui.submit{ value = _"Set URL" }
   26.41 +      end
   26.42      }
   26.43 -  },
   26.44 -  content = function()
   26.45 -    local setting_key = "liquidfeedback_frontend_stylesheet_url"
   26.46 -    local setting = Setting:by_pk(app.session.member.id, setting_key)
   26.47 -    local value = setting and setting.value
   26.48 -    ui.field.text{ 
   26.49 -      label = _"Stylesheet URL",
   26.50 -      name = "stylesheet_url",
   26.51 -      value = value
   26.52 +  end
   26.53 +
   26.54 +  local setting_key = "liquidfeedback_frontend_api_key"
   26.55 +  local setting = Setting:by_pk(app.session.member.id, setting_key)
   26.56 +  local api_key
   26.57 +  if setting then
   26.58 +    api_key = setting.value
   26.59 +  end
   26.60 +
   26.61 +  ui.heading{ content = _"Generate / change API key" }
   26.62 +  util.help("member.developer_settings.api_key", _"API key")
   26.63 +
   26.64 +  if api_key then
   26.65 +    slot.put(_"Your API key:")
   26.66 +    slot.put(" ")
   26.67 +    slot.put("<tt>", api_key, "</tt>")
   26.68 +    slot.put(" ")
   26.69 +    ui.link{
   26.70 +      text = _"Change API key",
   26.71 +      module = "member",
   26.72 +      action = "update_api_key",
   26.73 +      routing = {
   26.74 +        default = {
   26.75 +          mode = "redirect",
   26.76 +          module = "member",
   26.77 +          view = "developer_settings"
   26.78 +        }
   26.79 +      }
   26.80      }
   26.81 -    ui.submit{ value = _"Set URL" }
   26.82 +    slot.put(" ")
   26.83 +    ui.link{
   26.84 +      text = _"Delete API key",
   26.85 +      module = "member",
   26.86 +      action = "update_api_key",
   26.87 +      params = { delete = true },
   26.88 +      routing = {
   26.89 +        default = {
   26.90 +          mode = "redirect",
   26.91 +          module = "member",
   26.92 +          view = "developer_settings",
   26.93 +        }
   26.94 +      }
   26.95 +    }
   26.96 +  else
   26.97 +    slot.put(_"Currently no API key is set.")
   26.98 +    slot.put(" ")
   26.99 +    ui.link{
  26.100 +      text = _"Generate API key",
  26.101 +      module = "member",
  26.102 +      action = "update_api_key",
  26.103 +      routing = {
  26.104 +        default = {
  26.105 +          mode = "redirect",
  26.106 +          module = "member",
  26.107 +          view = "developer_settings"
  26.108 +        }
  26.109 +      }
  26.110 +    }
  26.111    end
  26.112 -}
    27.1 --- a/app/main/member/settings.lua	Wed Mar 31 17:50:32 2010 +0200
    27.2 +++ b/app/main/member/settings.lua	Sun Apr 04 22:05:11 2010 +0200
    27.3 @@ -11,19 +11,15 @@
    27.4      view = "index"
    27.5    }
    27.6  
    27.7 -  local setting_key = "liquidfeedback_frontend_developer_features"
    27.8 -  local setting = Setting:by_pk(app.session.member.id, setting_key)
    27.9 +  ui.link{
   27.10 +    content = function()
   27.11 +        ui.image{ static = "icons/16/wrench.png" }
   27.12 +        slot.put(_"Developer features")
   27.13 +    end,
   27.14 +    module = "member",
   27.15 +    view = "developer_settings"
   27.16 +  }
   27.17  
   27.18 -  if setting then
   27.19 -    ui.link{
   27.20 -      content = function()
   27.21 -          ui.image{ static = "icons/16/wrench.png" }
   27.22 -          slot.put(_"Developer features")
   27.23 -      end,
   27.24 -      module = "member",
   27.25 -      view = "developer_settings"
   27.26 -    }
   27.27 -  end
   27.28  end)
   27.29  
   27.30  ui.heading{ content = _"Display settings" }
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/app/main/openid/_action/initiate.lua	Sun Apr 04 22:05:11 2010 +0200
    28.3 @@ -0,0 +1,20 @@
    28.4 +local user_supplied_identifier = param.get("openid_identifier")
    28.5 +
    28.6 +if not config.auth_openid_identifier_check_func(user_supplied_identifier) then
    28.7 +  slot.put_into("error", _"This identifier is not allowed for this instance.")
    28.8 +  return
    28.9 +end
   28.10 +
   28.11 +local success,errmsg = auth.openid.initiate{
   28.12 +  user_supplied_identifier = user_supplied_identifier,
   28.13 +  https_as_default         = config.auth_openid_https_as_default,
   28.14 +  curl_options             = config.auth_openid_curl_options,
   28.15 +  realm                    = request.get_absolute_baseurl(),
   28.16 +  return_to_module         = "openid",
   28.17 +  return_to_view           = "verify"
   28.18 +}
   28.19 +
   28.20 +if not success then
   28.21 +  slot.put_into("error", encode.html(_("Error while resolving openid. Internal message: '#{errmsg}'", { errmsg = errmsg })))
   28.22 +  return false
   28.23 +end
   28.24 \ No newline at end of file
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/app/main/openid/_filter/00_openid.lua	Sun Apr 04 22:05:11 2010 +0200
    29.3 @@ -0,0 +1,5 @@
    29.4 +if not config.auth_openid_enabled then
    29.5 +  error("OpenID is not enabled.")
    29.6 +end
    29.7 +
    29.8 +execute.inner()
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/app/main/openid/announce.xrds.lua	Sun Apr 04 22:05:11 2010 +0200
    30.3 @@ -0,0 +1,4 @@
    30.4 +auth.openid.xrds_document{
    30.5 +  return_to_module = "openid",
    30.6 +  return_to_view = "verify"
    30.7 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/app/main/openid/verify.lua	Sun Apr 04 22:05:11 2010 +0200
    31.3 @@ -0,0 +1,17 @@
    31.4 +local claimed_identifier, errmsg = auth.openid.verify{
    31.5 +  force_https              = config.auth_openid_force_https,
    31.6 +  curl_options             = config.auth_openid_curl_options
    31.7 +}
    31.8 +
    31.9 +if not claimed_identifier then
   31.10 +  slot.put_into("error", _"Sorry, it was not possible to verify your OpenID.")
   31.11 +  return
   31.12 +end
   31.13 +
   31.14 +if not config.auth_openid_identifier_check_func(claimed_identifier) then
   31.15 +  slot.put_into("error", _"This identifier is not allowed for this instance.")
   31.16 +  return
   31.17 +end
   31.18 +
   31.19 +slot.put("validated as: ", encode.html(claimed_identifier), "<br />")
   31.20 +
    32.1 --- a/app/main/suggestion/_list.lua	Wed Mar 31 17:50:32 2010 +0200
    32.2 +++ b/app/main/suggestion/_list.lua	Sun Apr 04 22:05:11 2010 +0200
    32.3 @@ -108,104 +108,111 @@
    32.4                label = _"My opinion",
    32.5                content = function(record)
    32.6                  local degree
    32.7 -                local opinion = Opinion:by_pk(app.session.member.id, record.id)
    32.8 +                local opinion
    32.9 +                if app.session.member_id then
   32.10 +                  opinion = Opinion:by_pk(app.session.member.id, record.id)
   32.11 +                end
   32.12                  if opinion then
   32.13                    degree = opinion.degree
   32.14                  end
   32.15                  ui.container{
   32.16                    attr = { class = "suggestion_my_opinion" },
   32.17                    content = function()
   32.18 -                    if initiative.issue.state == "voting" or initiative.issue.state == "closed" then
   32.19 -                      ui.tag{
   32.20 -                        tag = "span",
   32.21 -                        attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
   32.22 -                        content = _"must not"
   32.23 -                      }
   32.24 -                      ui.tag{
   32.25 -                        tag = "span",
   32.26 -                        attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
   32.27 -                        content = _"should not"
   32.28 -                      }
   32.29 -                      ui.tag{
   32.30 -                        tag = "span",
   32.31 -                        attr = { class = "action" .. (degree == nil and " active" or "") },
   32.32 -                        content = _"neutral"
   32.33 -                      }
   32.34 -                      ui.tag{
   32.35 -                        tag = "span",
   32.36 -                        attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
   32.37 -                        content = _"should"
   32.38 -                      }
   32.39 -                      ui.tag{
   32.40 -                        tag = "span",
   32.41 -                        attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
   32.42 -                        content = _"must"
   32.43 -                      }
   32.44 +                    if app.session.member_id then
   32.45 +                      if initiative.issue.state == "voting" or initiative.issue.state == "closed" then
   32.46 +                        ui.tag{
   32.47 +                          tag = "span",
   32.48 +                          attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
   32.49 +                          content = _"must not"
   32.50 +                        }
   32.51 +                        ui.tag{
   32.52 +                          tag = "span",
   32.53 +                          attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
   32.54 +                          content = _"should not"
   32.55 +                        }
   32.56 +                        ui.tag{
   32.57 +                          tag = "span",
   32.58 +                          attr = { class = "action" .. (degree == nil and " active" or "") },
   32.59 +                          content = _"neutral"
   32.60 +                        }
   32.61 +                        ui.tag{
   32.62 +                          tag = "span",
   32.63 +                          attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
   32.64 +                          content = _"should"
   32.65 +                        }
   32.66 +                        ui.tag{
   32.67 +                          tag = "span",
   32.68 +                          attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
   32.69 +                          content = _"must"
   32.70 +                        }
   32.71 +                      else
   32.72 +                        ui.link{
   32.73 +                          attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
   32.74 +                          text = _"must not",
   32.75 +                          module = "opinion",
   32.76 +                          action = "update",
   32.77 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
   32.78 +                          params = {
   32.79 +                            suggestion_id = record.id,
   32.80 +                            degree = -2
   32.81 +                          },
   32.82 +                          partial = partial
   32.83 +                        }
   32.84 +                        slot.put(" ")
   32.85 +                        ui.link{
   32.86 +                          attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
   32.87 +                          text = _"should not",
   32.88 +                          module = "opinion",
   32.89 +                          action = "update",
   32.90 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
   32.91 +                          params = {
   32.92 +                            suggestion_id = record.id,
   32.93 +                            degree = -1
   32.94 +                          },
   32.95 +                          partial = partial
   32.96 +                        }
   32.97 +                        slot.put(" ")
   32.98 +                        ui.link{
   32.99 +                          attr = { class = "action" .. (degree == nil and " active" or "") },
  32.100 +                          text = _"neutral",
  32.101 +                          module = "opinion",
  32.102 +                          action = "update",
  32.103 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  32.104 +                          params = {
  32.105 +                            suggestion_id = record.id,
  32.106 +                            delete = true
  32.107 +                          },
  32.108 +                          partial = partial
  32.109 +                        }
  32.110 +                        slot.put(" ")
  32.111 +                        ui.link{
  32.112 +                          attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
  32.113 +                          text = _"should",
  32.114 +                          module = "opinion",
  32.115 +                          action = "update",
  32.116 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  32.117 +                          params = {
  32.118 +                            suggestion_id = record.id,
  32.119 +                            degree = 1
  32.120 +                          },
  32.121 +                          partial = partial
  32.122 +                        }
  32.123 +                        slot.put(" ")
  32.124 +                        ui.link{
  32.125 +                          attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
  32.126 +                          text = _"must",
  32.127 +                          module = "opinion",
  32.128 +                          action = "update",
  32.129 +                          routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  32.130 +                          params = {
  32.131 +                            suggestion_id = record.id,
  32.132 +                            degree = 2
  32.133 +                          },
  32.134 +                          partial = partial
  32.135 +                        }
  32.136 +                      end
  32.137                      else
  32.138 -                      ui.link{
  32.139 -                        attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
  32.140 -                        text = _"must not",
  32.141 -                        module = "opinion",
  32.142 -                        action = "update",
  32.143 -                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  32.144 -                        params = {
  32.145 -                          suggestion_id = record.id,
  32.146 -                          degree = -2
  32.147 -                        },
  32.148 -                        partial = partial
  32.149 -                      }
  32.150 -                      slot.put(" ")
  32.151 -                      ui.link{
  32.152 -                        attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
  32.153 -                        text = _"should not",
  32.154 -                        module = "opinion",
  32.155 -                        action = "update",
  32.156 -                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  32.157 -                        params = {
  32.158 -                          suggestion_id = record.id,
  32.159 -                          degree = -1
  32.160 -                        },
  32.161 -                        partial = partial
  32.162 -                      }
  32.163 -                      slot.put(" ")
  32.164 -                      ui.link{
  32.165 -                        attr = { class = "action" .. (degree == nil and " active" or "") },
  32.166 -                        text = _"neutral",
  32.167 -                        module = "opinion",
  32.168 -                        action = "update",
  32.169 -                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  32.170 -                        params = {
  32.171 -                          suggestion_id = record.id,
  32.172 -                          delete = true
  32.173 -                        },
  32.174 -                        partial = partial
  32.175 -                      }
  32.176 -                      slot.put(" ")
  32.177 -                      ui.link{
  32.178 -                        attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
  32.179 -                        text = _"should",
  32.180 -                        module = "opinion",
  32.181 -                        action = "update",
  32.182 -                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  32.183 -                        params = {
  32.184 -                          suggestion_id = record.id,
  32.185 -                          degree = 1
  32.186 -                        },
  32.187 -                        partial = partial
  32.188 -                      }
  32.189 -                      slot.put(" ")
  32.190 -                      ui.link{
  32.191 -                        attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
  32.192 -                        text = _"must",
  32.193 -                        module = "opinion",
  32.194 -                        action = "update",
  32.195 -                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  32.196 -                        params = {
  32.197 -                          suggestion_id = record.id,
  32.198 -                          degree = 2
  32.199 -                        },
  32.200 -                        partial = partial
  32.201 -                      }
  32.202 +                      ui.field.text{ value = _"[Registered members only]" }
  32.203                      end
  32.204                    end
  32.205                  }
  32.206 @@ -213,7 +220,10 @@
  32.207              },
  32.208              {
  32.209                content = function(record)
  32.210 -                local opinion = Opinion:by_pk(app.session.member.id, record.id)
  32.211 +                local opinion
  32.212 +                if app.session.member_id then
  32.213 +                  opinion = Opinion:by_pk(app.session.member.id, record.id)
  32.214 +                end
  32.215                  if opinion and not opinion.fulfilled then
  32.216                    ui.image{ static = "icons/16/cross.png" }
  32.217                  end
  32.218 @@ -242,7 +252,10 @@
  32.219              },
  32.220              {
  32.221                content = function(record)
  32.222 -                local opinion = Opinion:by_pk(app.session.member.id, record.id)
  32.223 +                local opinion
  32.224 +                if app.session.member_id then
  32.225 +                  opinion = Opinion:by_pk(app.session.member.id, record.id)
  32.226 +                end
  32.227                  if opinion and opinion.fulfilled then
  32.228                      ui.image{ static = "icons/16/tick.png" }
  32.229                  end
  32.230 @@ -273,7 +286,10 @@
  32.231                label_attr = { style = "width: 200px;" },
  32.232                content = function(record)
  32.233                  local degree
  32.234 -                local opinion = Opinion:by_pk(app.session.member.id, record.id)
  32.235 +                local opinion
  32.236 +                if app.session.member_id then
  32.237 +                  opinion = Opinion:by_pk(app.session.member.id, record.id)
  32.238 +                end
  32.239                  if opinion then
  32.240                    degree = opinion.degree
  32.241                  end
  32.242 @@ -321,7 +337,10 @@
  32.243              },
  32.244              {
  32.245                content = function(record)
  32.246 -                local opinion = Opinion:by_pk(app.session.member.id, record.id)
  32.247 +                local opinion
  32.248 +                if app.session.member_id then
  32.249 +                  opinion = Opinion:by_pk(app.session.member.id, record.id)
  32.250 +                end
  32.251                  if opinion then
  32.252                    if (opinion.fulfilled and opinion.degree > 0) or (not opinion.fulfilled and opinion.degree < 0) then
  32.253                      ui.image{ static = "icons/16/thumb_up_green.png" }
    33.1 --- a/app/main/suggestion/_suggestion.lua	Wed Mar 31 17:50:32 2010 +0200
    33.2 +++ b/app/main/suggestion/_suggestion.lua	Sun Apr 04 22:05:11 2010 +0200
    33.3 @@ -5,7 +5,11 @@
    33.4    record = suggestion,
    33.5    readonly = true,
    33.6    content = function()
    33.7 -    ui.field.text{ label = _"Author",      value = suggestion.author.name }
    33.8 +    if app.session.member_id or config.public_access == "pseudonym" then
    33.9 +      ui.field.text{ label = _"Author",      value = suggestion.author.name }
   33.10 +    else
   33.11 +      ui.field.text{ label = _"Author",      value = _"[not displayed public]" }
   33.12 +    end
   33.13      ui.field.text{ label = _"Title",        name = "name" }
   33.14      ui.container{
   33.15        attr = { class = "suggestion_content wiki" },
    34.1 --- a/app/main/suggestion/show_tab.lua	Wed Mar 31 17:50:32 2010 +0200
    34.2 +++ b/app/main/suggestion/show_tab.lua	Sun Apr 04 22:05:11 2010 +0200
    34.3 @@ -1,11 +1,14 @@
    34.4  local suggestion = param.get("suggestion", "table") or Suggestion:by_id(param.get("suggestion_id"))
    34.5  
    34.6 -ui.tabs{
    34.7 +local tabs = {
    34.8    module = "suggestion",
    34.9    view = "show_tab",
   34.10    static_params = {
   34.11      suggestion_id = suggestion.id
   34.12    },
   34.13 +}
   34.14 +
   34.15 +tabs[#tabs+1] =
   34.16    {
   34.17      name = "description",
   34.18      label = _"Suggestion",
   34.19 @@ -14,15 +17,19 @@
   34.20      params = {
   34.21        suggestion = suggestion
   34.22      }
   34.23 -  },
   34.24 -  {
   34.25 -    name = "opinions",
   34.26 -    label = _"Opinions",
   34.27 -    module = "suggestion",
   34.28 -    view = "_opinions",
   34.29 -    params = {
   34.30 -      suggestion = suggestion
   34.31 +  }
   34.32 +
   34.33 +if app.session.member_id then
   34.34 +  tabs[#tabs+1] =
   34.35 +    {
   34.36 +      name = "opinions",
   34.37 +      label = _"Opinions",
   34.38 +      module = "suggestion",
   34.39 +      view = "_opinions",
   34.40 +      params = {
   34.41 +        suggestion = suggestion
   34.42 +      }
   34.43      }
   34.44 -  }
   34.45 -}
   34.46 +end
   34.47  
   34.48 +ui.tabs(tabs)
   34.49 \ No newline at end of file
    35.1 --- a/app/main/timeline/_filter/29_filter.lua	Wed Mar 31 17:50:32 2010 +0200
    35.2 +++ b/app/main/timeline/_filter/29_filter.lua	Sun Apr 04 22:05:11 2010 +0200
    35.3 @@ -1,6 +1,9 @@
    35.4  if request.get_view() == "index" and not param.get("date") then
    35.5 +  local setting
    35.6    local setting_key = "liquidfeedback_frontend_timeline_current_options"
    35.7 -  local setting = Setting:by_pk(app.session.member.id, setting_key)
    35.8 +  if app.session.member_id then
    35.9 +    setting = Setting:by_pk(app.session.member.id, setting_key)
   35.10 +  end
   35.11  
   35.12    local timeline_params = {}
   35.13    if setting and setting.value then
   35.14 @@ -14,8 +17,11 @@
   35.15      end
   35.16    end
   35.17  
   35.18 +  local setting
   35.19    local setting_key = "liquidfeedback_frontend_timeline_current_date"
   35.20 -  local setting = Setting:by_pk(app.session.member.id, setting_key)
   35.21 +  if app.session.member_id then
   35.22 +    setting = Setting:by_pk(app.session.member.id, setting_key)
   35.23 +  end
   35.24  
   35.25    if setting then
   35.26      timeline_params.date = setting.value
    36.1 --- a/config/default.lua	Wed Mar 31 17:50:32 2010 +0200
    36.2 +++ b/config/default.lua	Sun Apr 04 22:05:11 2010 +0200
    36.3 @@ -27,8 +27,18 @@
    36.4  
    36.5  config.download_use_terms = "=== Nutzungsbedingungen ===\nAlles ist verboten"
    36.6  
    36.7 +config.public_access = false  -- Available options: "anonymous", "pseudonym"
    36.8 +
    36.9 +config.api_enabled = false
   36.10 +
   36.11 +-- OpenID authentication is not fully implemented yet, DO NOT USE BEFORE THIS NOTICE HAS BEEN REMOVED!
   36.12 +config.auth_openid_enabled = false
   36.13 +config.auth_openid_https_as_default = true
   36.14 +config.auth_openid_identifier_check_func = function(uri) return false end
   36.15 +
   36.16  request.set_allowed_json_request_slots{ "title", "actions", "support", "default", "trace", "system_error" }
   36.17  
   36.18 +
   36.19  if request.get_json_request_slots() then
   36.20    request.force_absolute_baseurl()
   36.21  end
    37.1 --- a/config/development.lua	Wed Mar 31 17:50:32 2010 +0200
    37.2 +++ b/config/development.lua	Sun Apr 04 22:05:11 2010 +0200
    37.3 @@ -10,4 +10,19 @@
    37.4  config.mail_from = "LiquidFeedback"
    37.5  config.mail_reply_to = "liquid-support@localhost"
    37.6  
    37.7 -config.issue_discussion_url_func = function(issue) return "http://example.com/issue_" .. tostring(issue.id) end
    37.8 \ No newline at end of file
    37.9 +config.issue_discussion_url_func = function(issue) return "http://example.com/issue_" .. tostring(issue.id) end
   37.10 +
   37.11 +config.auth_openid_enabled = true
   37.12 +config.auth_openid_https_as_default = true
   37.13 +
   37.14 +config.auth_openid_identifier_check_func = function(uri)
   37.15 +  local uri = uri:lower()
   37.16 +  if uri:find("^https://") then
   37.17 +    uri = uri:match("^https://(.*)")
   37.18 +  end
   37.19 +  if uri:find("^[0-9A-Za-z_-]+%.example%.com/?$") then
   37.20 +    return true
   37.21 +  else
   37.22 +    return false
   37.23 +  end
   37.24 +end
   37.25 \ No newline at end of file
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/env/util/autoapi.lua	Sun Apr 04 22:05:11 2010 +0200
    38.3 @@ -0,0 +1,76 @@
    38.4 +function util.autoapi_xml(args)
    38.5 +  local selector = assert(args.selector)
    38.6 +  local fields = assert(args.fields)
    38.7 +  local rows = selector:exec()
    38.8 +  slot.set_layout("xml")
    38.9 +  slot.put("<initiative_list>\n")
   38.10 +  for i_row, row in ipairs(rows) do
   38.11 +    slot.put("  <initiative>\n")
   38.12 +    for i_field, field in ipairs(fields) do
   38.13 +      slot.put("    <", field.name, ">")
   38.14 +      local value
   38.15 +      if field.func then
   38.16 +        value = field.func(row)
   38.17 +      elseif field.field then
   38.18 +        value = row[field.name]
   38.19 +      end
   38.20 +      if value then
   38.21 +        slot.put(encode.html(tostring(value)))
   38.22 +      end
   38.23 +      slot.put("</", field.name, ">\n")
   38.24 +    end
   38.25 +    slot.put("  </initiative>\n")
   38.26 +  end
   38.27 +  slot.put("</initiative_list>\n")
   38.28 +end
   38.29 +
   38.30 +function util.autoapi_json(args)
   38.31 +  slot.set_layout("blank")
   38.32 +  local selector = assert(args.selector)
   38.33 +  local fields = assert(args.fields)
   38.34 +  local rows = selector:exec()
   38.35 +  slot.put("{\n")
   38.36 +  for i_row, row in ipairs(rows) do
   38.37 +    slot.put("  {\n")
   38.38 +    for i_field, field in ipairs(fields) do
   38.39 +      slot.put("    ", field.name, ": ")
   38.40 +      local value
   38.41 +      if field.func then
   38.42 +        value = field.func(row)
   38.43 +      elseif field.field then
   38.44 +        value = row[field.name]
   38.45 +      end
   38.46 +        slot.put(encode.json(value))
   38.47 +      slot.put(",\n")
   38.48 +    end
   38.49 +    slot.put("  },\n")
   38.50 +  end
   38.51 +  slot.put("}\n")
   38.52 +end
   38.53 +
   38.54 +function util.autoapi(args)
   38.55 +  local selector = assert(args.selector)
   38.56 +  local fields = assert(args.fields)
   38.57 +  local api_engine = assert(args.api_engine)
   38.58 +
   38.59 +  selector:reset_fields()
   38.60 +
   38.61 +  for i_field, field in ipairs(fields) do
   38.62 +    if field.field then
   38.63 +      selector:add_field(field.field, field.name)
   38.64 +    end
   38.65 +  end
   38.66 +
   38.67 +  if api_engine == "xml" then
   38.68 +    util.autoapi_xml{
   38.69 +      selector = selector,
   38.70 +      fields = fields
   38.71 +    }
   38.72 +  elseif api_engine == "json" then
   38.73 +    util.autoapi_json{
   38.74 +      selector = selector,
   38.75 +      fields = fields
   38.76 +    }
   38.77 +  end
   38.78 +
   38.79 +end
   38.80 \ No newline at end of file
    39.1 --- a/env/util/help.lua	Wed Mar 31 17:50:32 2010 +0200
    39.2 +++ b/env/util/help.lua	Sun Apr 04 22:05:11 2010 +0200
    39.3 @@ -1,4 +1,7 @@
    39.4  function util.help(id, title)
    39.5 +  if not app.session.member_id then
    39.6 +    return
    39.7 +  end
    39.8    local setting_key = "liquidfeedback_frontend_hidden_help_" .. id
    39.9    local setting = Setting:by_pk(app.session.member.id, setting_key)
   39.10    if not setting then
    40.1 --- a/locale/translations.de.lua	Wed Mar 31 17:50:32 2010 +0200
    40.2 +++ b/locale/translations.de.lua	Sun Apr 04 22:05:11 2010 +0200
    40.3 @@ -11,6 +11,9 @@
    40.4  ["(new window)"] = "(neues Fenster)";
    40.5  ["+ #{weight}"] = "+ #{weight}";
    40.6  ["A-Z"] = "A-Z";
    40.7 +["API key"] = false;
    40.8 +["API key has been deleted"] = false;
    40.9 +["API key has been updated"] = false;
   40.10  ["About"] = "About";
   40.11  ["About / Impressum"] = false;
   40.12  ["About LiquidFeedback"] = "Über LiquidFeedback";
   40.13 @@ -71,6 +74,7 @@
   40.14  ["Cancel refuse of invitation"] = "Ablehnung der Einladung aufheben";
   40.15  ["Cancel registration"] = "Registration abbrechen";
   40.16  ["Cancelled"] = "Abgebrochen";
   40.17 +["Change API key"] = false;
   40.18  ["Change area delegation"] = "Delegation für Themenbereich ändern";
   40.19  ["Change display settings"] = "Anzeige-Einstellungen ändern";
   40.20  ["Change filters and order"] = "Filter und Sortierung ändern";
   40.21 @@ -103,9 +107,11 @@
   40.22  ["Created at"] = "Erzeugt am/um";
   40.23  ["Current draft"] = "Aktueller Entwurf";
   40.24  ["Current votings in areas you are member of and issues you are interested in:"] = "Jetzt laufende Abstimmungen zu Themen aus Deinen Themenbereichen oder solchen an denen Du interessiert bist:";
   40.25 +["Currently no API key is set."] = false;
   40.26  ["Date"] = "Datum";
   40.27  ["Degree"] = "Grad";
   40.28  ["Delegations"] = "Delegationen";
   40.29 +["Delete API key"] = false;
   40.30  ["Delete filter"] = "Filter löschen";
   40.31  ["Description"] = "Beschreibung";
   40.32  ["Details"] = "Details";
   40.33 @@ -144,6 +150,7 @@
   40.34  ["Email address too short!"] = "E-Mail-Adresse ist zu kurz!";
   40.35  ["Email confirmation request"] = "Bestätigung Deiner E-Mail-Adresse";
   40.36  ["Empty help text: #{id}.#{lang}.txt"] = "Leerer Hilfe-Text: #{id}.#{lang}.txt";
   40.37 +["Error while resolving openid. Internal message: '#{errmsg}'"] = false;
   40.38  ["Error while updating member, database reported:<br /><br /> (#{errormessage})"] = "Fehler beim aktualisieren des Mitglieds, die Datenbank berichtet folgenden Fehler:<br /><br /> (#{errormessage})";
   40.39  ["External memberships"] = "Externe Mitgliedschaften";
   40.40  ["External posts"] = "Externe Ämter";
   40.41 @@ -153,6 +160,8 @@
   40.42  ["Friday"] = "Freitag";
   40.43  ["Frozen"] = "Eingefroren";
   40.44  ["Fully frozen at"] = "Ganz eingefroren am/um";
   40.45 +["Generate / change API key"] = false;
   40.46 +["Generate API key"] = false;
   40.47  ["Global delegation"] = "Globale Delegation";
   40.48  ["Global delegation active"] = "Globale Delegation aktiv";
   40.49  ["Go up"] = "Nach oben";
   40.50 @@ -297,6 +306,8 @@
   40.51  ["One issue you are interested in"] = "Ein Thema, das Dich interessiert";
   40.52  ["One step back"] = "Ein Schritt zurück";
   40.53  ["Open"] = "Offen";
   40.54 +["OpenID"] = false;
   40.55 +["OpenID Login"] = false;
   40.56  ["Opinions"] = "Meinungen";
   40.57  ["Order by"] = "Sortieren nach";
   40.58  ["Organizational unit"] = "Organisationseinheit";
   40.59 @@ -397,6 +408,7 @@
   40.60  ["Some JavaScript based functions (voting in particular) will not work.\nFor this beta, please use a current version of Firefox, Safari, Opera(?), Konqueror or another (more) standard compliant browser.\nAlternative access without JavaScript will be available soon."] = "Einige auf JavaScript basierende Funktionen (insbesondere der Abstimmung) sind nicht benutzbar.\nFür diese Beta verwende bitte eine aktuelle Version von Firefox, Safari, Opera(?), Konqueror oder einen anderen (mehr) den Standards entsprechenden Browser.\nEin alternativer Zugriff ohne JavaScript wird bald zur Verfügung stehen.";
   40.61  ["Sorry, but there is not confirmed email address for your account. Please contact the administrator or support."] = "Sorry, aber für diesen Account ist keine bestätigte E-Mail-Adresse hinterlegt. Bitte wende Dich an den Administrator oder den Support.";
   40.62  ["Sorry, but you are currently not invited"] = "Sorry, aber Du bist zur Zeit nicht eingeladen";
   40.63 +["Sorry, it was not possible to verify your OpenID."] = false;
   40.64  ["Sorry, you have reached your personal flood limit. Please be slower..."] = "Sorry, Du hast Dein persönliches Flood-Limit erreicht. Bitte sei langsamer...";
   40.65  ["Sorry, your contingent for creating initiatives has been used up. Please try again later."] = "Sorry, Dein Antragskontingent ist zur Zeit ausgeschöpft. Bitte versuche es später erneut!";
   40.66  ["State"] = "Zustand";
   40.67 @@ -424,12 +436,14 @@
   40.68  ["Tabs"] = "Registerkarten";
   40.69  ["Terms accepted"] = "Bedingungen akzeptiert";
   40.70  ["Terms of use"] = "Nutzungsbedingungen";
   40.71 +["The API key has been changed too fast."] = false;
   40.72  ["The code you've entered is invalid"] = "Der Code, den Du eingeben hast, ist nicht gültig!";
   40.73  ["The draft of this initiative has been updated!"] = "Der Entwurfstext der Initiative wurde aktualisiert!";
   40.74  ["The drafts do not differ"] = "Die Entwürfe unterscheiden sich nicht";
   40.75  ["The initiators suggest to support the following initiative:"] = "Die Initiatoren empfehlen folgende Initiative zu unterstützen:";
   40.76  ["There are no more alternative initiatives currently."] = "Es gibt zur Zeit keine weiteren alternative Initiative.";
   40.77  ["There were no more alternative initiatives."] = "Es gab keine weiteren alternativen Initiativen.";
   40.78 +["This identifier is not allowed for this instance."] = false;
   40.79  ["This initiative"] = "Diese Initiative";
   40.80  ["This initiative compared to alternative initiatives"] = "Diese Initiative im Vergleich zu alternativen Initiativen";
   40.81  ["This initiative has been revoked at #{revoked}"] = "Diese Initiative wurde am/um #{revoked} zurückgezogen";
   40.82 @@ -506,9 +520,10 @@
   40.83  ["You have saved this member as contact."] = "Du hast das Mitglied als Kontakt gespeichert.";
   40.84  ["You have to accept the terms of use to complete registration."] = "Du musst die Nutzungsbedingungen akzeptieren um die Registration abzuschliessen.";
   40.85  ["You have to mark 'Are you sure' to revoke!"] = "Zum Zurückziehen musst Du 'Sicher?' auswählen";
   40.86 -["You need to be logged in, to use this system."] = "Du musst eingeloggt sein, um das System zu benutzen";
   40.87 +["You need to be logged in, to use all features of this system."] = false;
   40.88  ["You want to vote later"] = "Du willst später abstimmen";
   40.89  ["You've successfully registered and you can login now with your login and password!"] = "Du hast Dich erfolgreich registriert und kannst Dich jetzt mit Deinen Benutzernamen und Kennwort anmelden!";
   40.90 +["Your API key:"] = false;
   40.91  ["Your are interested"] = "Du bist interessiert";
   40.92  ["Your are potential supporter"] = "Du bist potentieller Unterstützer";
   40.93  ["Your are supporter"] = "Du bist Unterstützer";
   40.94 @@ -532,6 +547,8 @@
   40.95  ["Your vote has been discarded. Delegation rules apply if set."] = "Deine Abstimmung wurde zurückgezogen. Delegationsregeln gelten sofern gesetzt.";
   40.96  ["Your web browser is not fully supported yet."] = "Dein Web-Browser wird noch nicht vollständig unterstützt.";
   40.97  ["Z-A"] = "Z-A";
   40.98 +["[Registered members only]"] = false;
   40.99 +["[not displayed public]"] = false;
  40.100  ["and #{count} more initiatives"] = "und #{count} weitere Initiativen";
  40.101  ["continuing"] = "andauernd";
  40.102  ["delete<br /><br />"] = "löschen<br /><br />";
    41.1 --- a/locale/translations.en.lua	Wed Mar 31 17:50:32 2010 +0200
    41.2 +++ b/locale/translations.en.lua	Sun Apr 04 22:05:11 2010 +0200
    41.3 @@ -11,6 +11,9 @@
    41.4  ["(new window)"] = false;
    41.5  ["+ #{weight}"] = false;
    41.6  ["A-Z"] = false;
    41.7 +["API key"] = false;
    41.8 +["API key has been deleted"] = false;
    41.9 +["API key has been updated"] = false;
   41.10  ["About"] = false;
   41.11  ["About / Impressum"] = false;
   41.12  ["About LiquidFeedback"] = false;
   41.13 @@ -71,6 +74,7 @@
   41.14  ["Cancel refuse of invitation"] = false;
   41.15  ["Cancel registration"] = false;
   41.16  ["Cancelled"] = false;
   41.17 +["Change API key"] = false;
   41.18  ["Change area delegation"] = false;
   41.19  ["Change display settings"] = false;
   41.20  ["Change filters and order"] = false;
   41.21 @@ -103,9 +107,11 @@
   41.22  ["Created at"] = false;
   41.23  ["Current draft"] = false;
   41.24  ["Current votings in areas you are member of and issues you are interested in:"] = false;
   41.25 +["Currently no API key is set."] = false;
   41.26  ["Date"] = false;
   41.27  ["Degree"] = false;
   41.28  ["Delegations"] = false;
   41.29 +["Delete API key"] = false;
   41.30  ["Delete filter"] = false;
   41.31  ["Description"] = false;
   41.32  ["Details"] = false;
   41.33 @@ -144,6 +150,7 @@
   41.34  ["Email address too short!"] = false;
   41.35  ["Email confirmation request"] = false;
   41.36  ["Empty help text: #{id}.#{lang}.txt"] = false;
   41.37 +["Error while resolving openid. Internal message: '#{errmsg}'"] = false;
   41.38  ["Error while updating member, database reported:<br /><br /> (#{errormessage})"] = false;
   41.39  ["External memberships"] = false;
   41.40  ["External posts"] = false;
   41.41 @@ -153,6 +160,8 @@
   41.42  ["Friday"] = false;
   41.43  ["Frozen"] = false;
   41.44  ["Fully frozen at"] = false;
   41.45 +["Generate / change API key"] = false;
   41.46 +["Generate API key"] = false;
   41.47  ["Global delegation"] = false;
   41.48  ["Global delegation active"] = false;
   41.49  ["Go up"] = false;
   41.50 @@ -297,6 +306,8 @@
   41.51  ["One issue you are interested in"] = false;
   41.52  ["One step back"] = false;
   41.53  ["Open"] = false;
   41.54 +["OpenID"] = false;
   41.55 +["OpenID Login"] = false;
   41.56  ["Opinions"] = false;
   41.57  ["Order by"] = false;
   41.58  ["Organizational unit"] = false;
   41.59 @@ -397,6 +408,7 @@
   41.60  ["Some JavaScript based functions (voting in particular) will not work.\nFor this beta, please use a current version of Firefox, Safari, Opera(?), Konqueror or another (more) standard compliant browser.\nAlternative access without JavaScript will be available soon."] = false;
   41.61  ["Sorry, but there is not confirmed email address for your account. Please contact the administrator or support."] = false;
   41.62  ["Sorry, but you are currently not invited"] = false;
   41.63 +["Sorry, it was not possible to verify your OpenID."] = false;
   41.64  ["Sorry, you have reached your personal flood limit. Please be slower..."] = false;
   41.65  ["Sorry, your contingent for creating initiatives has been used up. Please try again later."] = false;
   41.66  ["State"] = false;
   41.67 @@ -424,12 +436,14 @@
   41.68  ["Tabs"] = false;
   41.69  ["Terms accepted"] = false;
   41.70  ["Terms of use"] = false;
   41.71 +["The API key has been changed too fast."] = false;
   41.72  ["The code you've entered is invalid"] = false;
   41.73  ["The draft of this initiative has been updated!"] = false;
   41.74  ["The drafts do not differ"] = false;
   41.75  ["The initiators suggest to support the following initiative:"] = false;
   41.76  ["There are no more alternative initiatives currently."] = false;
   41.77  ["There were no more alternative initiatives."] = false;
   41.78 +["This identifier is not allowed for this instance."] = false;
   41.79  ["This initiative"] = false;
   41.80  ["This initiative compared to alternative initiatives"] = false;
   41.81  ["This initiative has been revoked at #{revoked}"] = false;
   41.82 @@ -506,9 +520,10 @@
   41.83  ["You have saved this member as contact."] = false;
   41.84  ["You have to accept the terms of use to complete registration."] = false;
   41.85  ["You have to mark 'Are you sure' to revoke!"] = false;
   41.86 -["You need to be logged in, to use this system."] = false;
   41.87 +["You need to be logged in, to use all features of this system."] = false;
   41.88  ["You want to vote later"] = false;
   41.89  ["You've successfully registered and you can login now with your login and password!"] = false;
   41.90 +["Your API key:"] = false;
   41.91  ["Your are interested"] = false;
   41.92  ["Your are potential supporter"] = false;
   41.93  ["Your are supporter"] = false;
   41.94 @@ -532,6 +547,8 @@
   41.95  ["Your vote has been discarded. Delegation rules apply if set."] = false;
   41.96  ["Your web browser is not fully supported yet."] = false;
   41.97  ["Z-A"] = false;
   41.98 +["[Registered members only]"] = false;
   41.99 +["[not displayed public]"] = false;
  41.100  ["and #{count} more initiatives"] = false;
  41.101  ["continuing"] = false;
  41.102  ["delete<br /><br />"] = false;
    42.1 --- a/locale/translations.eo.lua	Wed Mar 31 17:50:32 2010 +0200
    42.2 +++ b/locale/translations.eo.lua	Sun Apr 04 22:05:11 2010 +0200
    42.3 @@ -11,6 +11,9 @@
    42.4  ["(new window)"] = "(nova fenestro)";
    42.5  ["+ #{weight}"] = "+ #{weight}";
    42.6  ["A-Z"] = "A-Z";
    42.7 +["API key"] = false;
    42.8 +["API key has been deleted"] = false;
    42.9 +["API key has been updated"] = false;
   42.10  ["About"] = "Pri";
   42.11  ["About / Impressum"] = "Pri / Pres-indikaĵoj";
   42.12  ["About LiquidFeedback"] = "Pri LiquidFeedback";
   42.13 @@ -71,6 +74,7 @@
   42.14  ["Cancel refuse of invitation"] = "Nuligi rifuzon de la invito";
   42.15  ["Cancel registration"] = "Nuligi registradon";
   42.16  ["Cancelled"] = "Abolita";
   42.17 +["Change API key"] = false;
   42.18  ["Change area delegation"] = "Ŝanĝi delegacion por temaro";
   42.19  ["Change display settings"] = "Sangi afiŝajn agordojn";
   42.20  ["Change filters and order"] = "Ŝanĝi filtrojn kaj ordon";
   42.21 @@ -103,9 +107,11 @@
   42.22  ["Created at"] = "Kreita je";
   42.23  ["Current draft"] = "Aktuala skizo";
   42.24  ["Current votings in areas you are member of and issues you are interested in:"] = "Aktualaj voĉdonoj pri temoj en kiuj vi membraa kaj kiuj vin interesas:";
   42.25 +["Currently no API key is set."] = false;
   42.26  ["Date"] = "Dato";
   42.27  ["Degree"] = "Grado";
   42.28  ["Delegations"] = "Delegacioj";
   42.29 +["Delete API key"] = false;
   42.30  ["Delete filter"] = "Forvisi filtron";
   42.31  ["Description"] = "Priskribo";
   42.32  ["Details"] = "Detaloj";
   42.33 @@ -144,6 +150,7 @@
   42.34  ["Email address too short!"] = "Retadreso estas tro mallonga!";
   42.35  ["Email confirmation request"] = "Konfirmopeto de via retadreso";
   42.36  ["Empty help text: #{id}.#{lang}.txt"] = "Malplena helpoteksto: #{id}.#{lang}.txt";
   42.37 +["Error while resolving openid. Internal message: '#{errmsg}'"] = false;
   42.38  ["Error while updating member, database reported:<br /><br /> (#{errormessage})"] = "Eraro dum ĝisdatigo de la membro, la datumbazo raportas sekvan eraron:<br /><br /> (#{errormessage})";
   42.39  ["External memberships"] = "Eksteraj membrecoj";
   42.40  ["External posts"] = "Eksteraj postenoj";
   42.41 @@ -153,6 +160,8 @@
   42.42  ["Friday"] = "Vendredo";
   42.43  ["Frozen"] = "Ĝelita";
   42.44  ["Fully frozen at"] = "Tute ĝelita je";
   42.45 +["Generate / change API key"] = false;
   42.46 +["Generate API key"] = false;
   42.47  ["Global delegation"] = "Ĝenerala delegacio";
   42.48  ["Global delegation active"] = "Ĝenerala delegacio estas aktiva";
   42.49  ["Go up"] = "Movi supren";
   42.50 @@ -297,6 +306,8 @@
   42.51  ["One issue you are interested in"] = "Unu temo, kiu vin interesas";
   42.52  ["One step back"] = "Unu paŝo reen";
   42.53  ["Open"] = "Malferma";
   42.54 +["OpenID"] = false;
   42.55 +["OpenID Login"] = false;
   42.56  ["Opinions"] = "Opinioj";
   42.57  ["Order by"] = "Ordigi laŭ";
   42.58  ["Organizational unit"] = "Organiza unuo";
   42.59 @@ -397,6 +408,7 @@
   42.60  ["Some JavaScript based functions (voting in particular) will not work.\nFor this beta, please use a current version of Firefox, Safari, Opera(?), Konqueror or another (more) standard compliant browser.\nAlternative access without JavaScript will be available soon."] = "Kelkaj funkcioj bazitaj je JavaScript (precipe la voĉdono) ne funkcios.\nBonvolu, uzi por tiu betaversio aktualan version de Firefox, Safari, Opera(?), Konqueror aŭ alian (pli) normokonforman retumilon.\nAlternativa atingo sen JavaScript estos baldaŭ disponeble.";
   42.61  ["Sorry, but there is not confirmed email address for your account. Please contact the administrator or support."] = "Pardonu, por tiu konto ne ekzistas konfirmita retadreson. Bonvolu vin turni al administranto aŭ al la helpantaro.";
   42.62  ["Sorry, but you are currently not invited"] = "Pardonu, sed aktuale vi ne estas invitita";
   42.63 +["Sorry, it was not possible to verify your OpenID."] = false;
   42.64  ["Sorry, you have reached your personal flood limit. Please be slower..."] = "Pardonu, vi atingis vian propran inundolimigon. Bonvolu esti pli malrapida...";
   42.65  ["Sorry, your contingent for creating initiatives has been used up. Please try again later."] = "Pardonu, via kontingento por krei iniciatojn estas aktuale elĉerpita. Bonvolu provi pli malfrue denove!";
   42.66  ["State"] = "Stato";
   42.67 @@ -424,12 +436,14 @@
   42.68  ["Tabs"] = "Langetoj";
   42.69  ["Terms accepted"] = "Kondiĉoj akceptitaj";
   42.70  ["Terms of use"] = "Uzokondiĉoj";
   42.71 +["The API key has been changed too fast."] = false;
   42.72  ["The code you've entered is invalid"] = "La kodo, kiun vi enigis ne estas valida!";
   42.73  ["The draft of this initiative has been updated!"] = "La skizo de tiu ĉi iniciato estas ĝisdatigita";
   42.74  ["The drafts do not differ"] = "La skizoj ne estas malsamaj";
   42.75  ["The initiators suggest to support the following initiative:"] = "La iniciatantoj rekomendas subteni sekvan iniciaton:";
   42.76  ["There are no more alternative initiatives currently."] = "Aktuale ne eksistas pliajn alternativajn iniciatojn.";
   42.77  ["There were no more alternative initiatives."] = "Ne eksistis pliajn alternativajn iniciatojn.";
   42.78 +["This identifier is not allowed for this instance."] = false;
   42.79  ["This initiative"] = "Tiu iniciato";
   42.80  ["This initiative compared to alternative initiatives"] = "Tiu iniciato komparata al la alternativajn iniciatojn";
   42.81  ["This initiative has been revoked at #{revoked}"] = "Tiu iniciato estis nuligita je #{revoked}";
   42.82 @@ -506,9 +520,10 @@
   42.83  ["You have saved this member as contact."] = "Vi ne jam storis membron kiel kontakton.";
   42.84  ["You have to accept the terms of use to complete registration."] = "Vi devas akcepti la uzokondiĉojn por fini la registradon.";
   42.85  ["You have to mark 'Are you sure' to revoke!"] = "Por nuligi vi devas elekti 'Certa?'";
   42.86 -["You need to be logged in, to use this system."] = "Vi devas esti ensalutinta, por uzi la sistemon";
   42.87 +["You need to be logged in, to use all features of this system."] = false;
   42.88  ["You want to vote later"] = "Vi volas baloti pli malfrue";
   42.89  ["You've successfully registered and you can login now with your login and password!"] = "Vi sukcese registriĝis kaj povas nun ensaluti per via salutnomo kaj pasvorto!";
   42.90 +["Your API key:"] = false;
   42.91  ["Your are interested"] = "Vi estas interesita";
   42.92  ["Your are potential supporter"] = "Vi estas eventuala subtenanto";
   42.93  ["Your are supporter"] = "Vi estas subtenanto";
   42.94 @@ -532,6 +547,8 @@
   42.95  ["Your vote has been discarded. Delegation rules apply if set."] = "Via voĉo estas retirata. La delegacioregularo aplikas se metita.";
   42.96  ["Your web browser is not fully supported yet."] = "Via retumilo ne estas jam komplete subtenita.";
   42.97  ["Z-A"] = "Z-A";
   42.98 +["[Registered members only]"] = false;
   42.99 +["[not displayed public]"] = false;
  42.100  ["and #{count} more initiatives"] = "kaj #{count} pliaj iniciatoj";
  42.101  ["continuing"] = "kontinue";
  42.102  ["delete<br /><br />"] = "forviŝi<br /><br />";
    43.1 --- a/locale/translations.fr.lua	Wed Mar 31 17:50:32 2010 +0200
    43.2 +++ b/locale/translations.fr.lua	Sun Apr 04 22:05:11 2010 +0200
    43.3 @@ -11,6 +11,9 @@
    43.4  ["(new window)"] = false;
    43.5  ["+ #{weight}"] = false;
    43.6  ["A-Z"] = false;
    43.7 +["API key"] = false;
    43.8 +["API key has been deleted"] = false;
    43.9 +["API key has been updated"] = false;
   43.10  ["About"] = false;
   43.11  ["About / Impressum"] = false;
   43.12  ["About LiquidFeedback"] = false;
   43.13 @@ -71,6 +74,7 @@
   43.14  ["Cancel refuse of invitation"] = false;
   43.15  ["Cancel registration"] = false;
   43.16  ["Cancelled"] = false;
   43.17 +["Change API key"] = false;
   43.18  ["Change area delegation"] = false;
   43.19  ["Change display settings"] = false;
   43.20  ["Change filters and order"] = false;
   43.21 @@ -103,9 +107,11 @@
   43.22  ["Created at"] = false;
   43.23  ["Current draft"] = false;
   43.24  ["Current votings in areas you are member of and issues you are interested in:"] = false;
   43.25 +["Currently no API key is set."] = false;
   43.26  ["Date"] = false;
   43.27  ["Degree"] = false;
   43.28  ["Delegations"] = false;
   43.29 +["Delete API key"] = false;
   43.30  ["Delete filter"] = false;
   43.31  ["Description"] = false;
   43.32  ["Details"] = false;
   43.33 @@ -144,6 +150,7 @@
   43.34  ["Email address too short!"] = false;
   43.35  ["Email confirmation request"] = false;
   43.36  ["Empty help text: #{id}.#{lang}.txt"] = false;
   43.37 +["Error while resolving openid. Internal message: '#{errmsg}'"] = false;
   43.38  ["Error while updating member, database reported:<br /><br /> (#{errormessage})"] = false;
   43.39  ["External memberships"] = false;
   43.40  ["External posts"] = false;
   43.41 @@ -153,6 +160,8 @@
   43.42  ["Friday"] = false;
   43.43  ["Frozen"] = false;
   43.44  ["Fully frozen at"] = false;
   43.45 +["Generate / change API key"] = false;
   43.46 +["Generate API key"] = false;
   43.47  ["Global delegation"] = false;
   43.48  ["Global delegation active"] = false;
   43.49  ["Go up"] = false;
   43.50 @@ -297,6 +306,8 @@
   43.51  ["One issue you are interested in"] = false;
   43.52  ["One step back"] = false;
   43.53  ["Open"] = false;
   43.54 +["OpenID"] = false;
   43.55 +["OpenID Login"] = false;
   43.56  ["Opinions"] = false;
   43.57  ["Order by"] = false;
   43.58  ["Organizational unit"] = false;
   43.59 @@ -397,6 +408,7 @@
   43.60  ["Some JavaScript based functions (voting in particular) will not work.\nFor this beta, please use a current version of Firefox, Safari, Opera(?), Konqueror or another (more) standard compliant browser.\nAlternative access without JavaScript will be available soon."] = false;
   43.61  ["Sorry, but there is not confirmed email address for your account. Please contact the administrator or support."] = false;
   43.62  ["Sorry, but you are currently not invited"] = false;
   43.63 +["Sorry, it was not possible to verify your OpenID."] = false;
   43.64  ["Sorry, you have reached your personal flood limit. Please be slower..."] = false;
   43.65  ["Sorry, your contingent for creating initiatives has been used up. Please try again later."] = false;
   43.66  ["State"] = false;
   43.67 @@ -424,12 +436,14 @@
   43.68  ["Tabs"] = false;
   43.69  ["Terms accepted"] = false;
   43.70  ["Terms of use"] = false;
   43.71 +["The API key has been changed too fast."] = false;
   43.72  ["The code you've entered is invalid"] = false;
   43.73  ["The draft of this initiative has been updated!"] = false;
   43.74  ["The drafts do not differ"] = false;
   43.75  ["The initiators suggest to support the following initiative:"] = false;
   43.76  ["There are no more alternative initiatives currently."] = false;
   43.77  ["There were no more alternative initiatives."] = false;
   43.78 +["This identifier is not allowed for this instance."] = false;
   43.79  ["This initiative"] = false;
   43.80  ["This initiative compared to alternative initiatives"] = false;
   43.81  ["This initiative has been revoked at #{revoked}"] = false;
   43.82 @@ -506,9 +520,10 @@
   43.83  ["You have saved this member as contact."] = false;
   43.84  ["You have to accept the terms of use to complete registration."] = false;
   43.85  ["You have to mark 'Are you sure' to revoke!"] = false;
   43.86 -["You need to be logged in, to use this system."] = false;
   43.87 +["You need to be logged in, to use all features of this system."] = false;
   43.88  ["You want to vote later"] = false;
   43.89  ["You've successfully registered and you can login now with your login and password!"] = false;
   43.90 +["Your API key:"] = false;
   43.91  ["Your are interested"] = false;
   43.92  ["Your are potential supporter"] = false;
   43.93  ["Your are supporter"] = false;
   43.94 @@ -532,6 +547,8 @@
   43.95  ["Your vote has been discarded. Delegation rules apply if set."] = false;
   43.96  ["Your web browser is not fully supported yet."] = false;
   43.97  ["Z-A"] = false;
   43.98 +["[Registered members only]"] = false;
   43.99 +["[not displayed public]"] = false;
  43.100  ["and #{count} more initiatives"] = false;
  43.101  ["continuing"] = false;
  43.102  ["delete<br /><br />"] = false;
    44.1 --- a/model/initiative.lua	Wed Mar 31 17:50:32 2010 +0200
    44.2 +++ b/model/initiative.lua	Sun Apr 04 22:05:11 2010 +0200
    44.3 @@ -136,10 +136,10 @@
    44.4      :add_group_by("_supporter.member_id")
    44.5  end
    44.6  
    44.7 -function Member:get_search_selector(search_string)
    44.8 -  return self:new_selector()
    44.9 -    :add_where("active")
   44.10 -end
   44.11 +--function Member:get_search_selector(search_string)
   44.12 +--  return self:new_selector()
   44.13 +--    :add_where("active")
   44.14 +--end
   44.15  
   44.16  
   44.17  function Initiative.object_get:current_draft()
    45.1 --- a/model/issue.lua	Wed Mar 31 17:50:32 2010 +0200
    45.2 +++ b/model/issue.lua	Sun Apr 04 22:05:11 2010 +0200
    45.3 @@ -146,6 +146,22 @@
    45.4      --:set_distinct()
    45.5  end
    45.6  
    45.7 +function Issue:modify_selector_for_state(state)
    45.8 +  if state == "new" then
    45.9 +    initiatives_selector:add_where("issue.accepted ISNULL AND issue.cancelled ISNULL")
   45.10 +  elseif state == "accepted" then
   45.11 +    initiatives_selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.cancelled ISNULL")
   45.12 +  elseif state == "frozen" then
   45.13 +    initiatives_selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL AND cancelled ISNULL")
   45.14 +  elseif state == "voting" then
   45.15 +    initiatives_selector:add_where("issue.fully_frozen NOTNULL AND issue.finished ISNULL AND issue.cancelled ISNULL")
   45.16 +  elseif state == "finished" then
   45.17 +    initiatives_selector:add_where("issue.finished NOTNULL")
   45.18 +  elseif state == "cancelled" then
   45.19 +    initiatives_selector:add_where("issue.cancelled NOTNULL")
   45.20 +  end
   45.21 +end
   45.22 +
   45.23  function Issue.object_get:state()
   45.24    if self.accepted then
   45.25      if self.closed then

Impressum / About Us