liquid_feedback_frontend

changeset 10:72c5e0ee7c98 beta6

Version beta6

Bugfixes:
- Security fix: Every user was able to change the discussion URL of an initiative
- Creation of new issues in areas without default policies is now possible
- Members can now be sorted in different ways
- No error when trying to compare a draft with itself
- Added missing local statement to variable initialization in app/main/delegation/new.lua
- CSS flaw in initiative action bar fixed

New features:
- Possiblity to invite other users to become initiator
- Revokation of initiatives implemented
- Number of suggestions, supporters, etc. is shown on corresponding tabs of initiative view
- Members can now be sorted by account creation (default sorting is "newest first")
- Configuration option to create an automatic discussion link for all issues
- First draft of global timeline feature (not accessible via link yet)
- Custom stylesheet URL for users marked as developers

In area listing the number of closed issues is shown too

Renamed "author" field of initiative to "last author"

Removed wrongly included file app/main/member/_show_thumb.lua.orig in the distribution

Help texts updated
author bsw
date Sun Jan 10 12:00:00 2010 +0100 (2010-01-10)
parents 0ee1e0c42d4c
children 77d58efe99fd
files app/main/_filter_view/34_stylesheet.lua app/main/_layout/default.html app/main/area/_list.lua app/main/delegation/new.lua app/main/draft/_action/add.lua app/main/draft/_show.lua app/main/draft/diff.lua app/main/index/index.lua app/main/initiative/_action/accept_invitation.lua app/main/initiative/_action/add_initiator.lua app/main/initiative/_action/add_support.lua app/main/initiative/_action/create.lua app/main/initiative/_action/reject_initiator_invitation.lua app/main/initiative/_action/remove_initiator.lua app/main/initiative/_action/revoke.lua app/main/initiative/_action/update.lua app/main/initiative/_list.lua app/main/initiative/add_initiator.lua app/main/initiative/new.lua app/main/initiative/remove_initiator.lua app/main/initiative/revoke.lua app/main/initiative/show.lua app/main/issue/_list.lua app/main/issue/_show_head.lua app/main/member/_action/update_stylesheet_url.lua app/main/member/_list.lua app/main/member/_show.lua app/main/member/_show_thumb.lua app/main/member/_show_thumb.lua.orig app/main/member/developer_settings.lua app/main/member/list.lua app/main/member/settings.lua app/main/supporter/_show_box.lua app/main/timeline/index.lua config/default.lua config/development.lua locale/help/initiative.add_initiator.de.txt locale/help/initiative.remove_initiator.de.txt locale/help/initiative.revoke.de.txt locale/help/initiative.show.de.txt locale/translations.de.lua model/area.lua model/initiative.lua model/issue.lua model/member.lua static/icons/16/script_delete.png static/icons/16/user_delete.png static/style.css
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/app/main/_filter_view/34_stylesheet.lua	Sun Jan 10 12:00:00 2010 +0100
     1.3 @@ -0,0 +1,14 @@
     1.4 +local value
     1.5 +if app.session.member then
     1.6 +  local setting_key = "liquidfeedback_frontend_stylesheet_url"
     1.7 +  local setting = Setting:by_pk(app.session.member.id, setting_key)
     1.8 +  value = setting and setting.value
     1.9 +end
    1.10 +
    1.11 +if value then
    1.12 +  slot.put_into("stylesheet_url", value)
    1.13 +else
    1.14 +  slot.put_into("stylesheet_url", config.absolute_base_url .. "static/style.css")
    1.15 +end
    1.16 +
    1.17 +execute.inner()
    1.18 \ No newline at end of file
     2.1 --- a/app/main/_layout/default.html	Mon Jan 04 12:00:00 2010 +0100
     2.2 +++ b/app/main/_layout/default.html	Sun Jan 10 12:00:00 2010 +0100
     2.3 @@ -3,7 +3,7 @@
     2.4      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
     2.5      <title><!-- WEBMCP SLOTNODIV app_name --></title>
     2.6      <link rel="stylesheet" type="text/css" media="screen" href="__BASEURL__/static/trace.css" />
     2.7 -    <link rel="stylesheet" type="text/css" media="screen" href="__BASEURL__/static/style.css" />
     2.8 +    <link rel="stylesheet" type="text/css" media="screen" href="<!-- WEBMCP SLOTNODIV stylesheet_url -->" />
     2.9      <!-- WEBMCP SLOTNODIV html_head -->
    2.10    </head>
    2.11    <body>
     3.1 --- a/app/main/area/_list.lua	Mon Jan 04 12:00:00 2010 +0100
     3.2 +++ b/app/main/area/_list.lua	Sun Jan 10 12:00:00 2010 +0100
     3.3 @@ -11,6 +11,8 @@
     3.4    :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")
     3.5    :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.fully_frozen NOTNULL AND issue.closed ISNULL)", "issues_voting_count")
     3.6    :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")
     3.7 +  :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.fully_frozen NOTNULL AND issue.closed NOTNULL)", "issues_finished_count")
     3.8 +  :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.fully_frozen ISNULL AND issue.closed NOTNULL)", "issues_cancelled_count")
     3.9  
    3.10  ui.order{
    3.11    name = name,
    3.12 @@ -132,7 +134,33 @@
    3.13                params = { filter = "frozen", filter_voting = "not_voted" }
    3.14              }
    3.15            end
    3.16 -        }
    3.17 +        },
    3.18 +        {
    3.19 +          label = _"Finished",
    3.20 +          field_attr = { style = "text-align: right;" },
    3.21 +          content = function(record)
    3.22 +            ui.link{
    3.23 +              text = tostring(record.issues_finished_count),
    3.24 +              module = "area",
    3.25 +              view = "show",
    3.26 +              id = record.id,
    3.27 +              params = { filter = "finished", issue_list = "newest" }
    3.28 +            }
    3.29 +          end
    3.30 +        },
    3.31 +        {
    3.32 +          label = _"Cancelled",
    3.33 +          field_attr = { style = "text-align: right;" },
    3.34 +          content = function(record)
    3.35 +            ui.link{
    3.36 +              text = tostring(record.issues_cancelled_count),
    3.37 +              module = "area",
    3.38 +              view = "show",
    3.39 +              id = record.id,
    3.40 +              params = { filter = "cancelled", issue_list = "newest" }
    3.41 +            }
    3.42 +          end
    3.43 +        },
    3.44        }
    3.45      }
    3.46    end
     4.1 --- a/app/main/delegation/new.lua	Mon Jan 04 12:00:00 2010 +0100
     4.2 +++ b/app/main/delegation/new.lua	Sun Jan 10 12:00:00 2010 +0100
     4.3 @@ -74,7 +74,7 @@
     4.4      }
     4.5    },
     4.6    content = function()
     4.7 -    records = {
     4.8 +    local records = {
     4.9        {
    4.10          id = "-1",
    4.11          name = _"No delegation"
     5.1 --- a/app/main/draft/_action/add.lua	Mon Jan 04 12:00:00 2010 +0100
     5.2 +++ b/app/main/draft/_action/add.lua	Sun Jan 10 12:00:00 2010 +0100
     5.3 @@ -17,26 +17,27 @@
     5.4    return false
     5.5  end
     5.6  
     5.7 -if Initiator:by_pk(initiative.id, app.session.member.id) then
     5.8 -  local draft = Draft:new()
     5.9 -  draft.author_id = app.session.member.id
    5.10 -  draft.initiative_id = initiative.id
    5.11 -  local formatting_engine = param.get("formatting_engine")
    5.12 -  local formatting_engine_valid = false
    5.13 -  for fe, dummy in pairs(config.formatting_engine_executeables) do
    5.14 -    if formatting_engine == fe then
    5.15 -      formatting_engine_valid = true
    5.16 -    end
    5.17 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
    5.18 +if not initiator or not initiator.accepted then
    5.19 +  error("access denied")
    5.20 +end
    5.21 +
    5.22 +local draft = Draft:new()
    5.23 +draft.author_id = app.session.member.id
    5.24 +draft.initiative_id = initiative.id
    5.25 +local formatting_engine = param.get("formatting_engine")
    5.26 +local formatting_engine_valid = false
    5.27 +for fe, dummy in pairs(config.formatting_engine_executeables) do
    5.28 +  if formatting_engine == fe then
    5.29 +    formatting_engine_valid = true
    5.30    end
    5.31 -  if not formatting_engine_valid then
    5.32 -    error("invalid formatting engine!")
    5.33 -  end
    5.34 -  draft.formatting_engine = formatting_engine
    5.35 -  draft.content = param.get("content")
    5.36 -  draft:save()
    5.37 +end
    5.38 +if not formatting_engine_valid then
    5.39 +  error("invalid formatting engine!")
    5.40 +end
    5.41 +draft.formatting_engine = formatting_engine
    5.42 +draft.content = param.get("content")
    5.43 +draft:save()
    5.44  
    5.45 -  slot.put_into("notice", _"New draft has been added to initiative")
    5.46 +slot.put_into("notice", _"New draft has been added to initiative")
    5.47  
    5.48 -else
    5.49 -  error('access denied')
    5.50 -end
     6.1 --- a/app/main/draft/_show.lua	Mon Jan 04 12:00:00 2010 +0100
     6.2 +++ b/app/main/draft/_show.lua	Sun Jan 10 12:00:00 2010 +0100
     6.3 @@ -6,7 +6,7 @@
     6.4    readonly = true,
     6.5    content = function()
     6.6  
     6.7 -    ui.field.text{ label = _"Author", name = "author_name" }
     6.8 +    ui.field.text{ label = _"Last author", name = "author_name" }
     6.9      ui.field.timestamp{ label = _"Created at", name = "created" }
    6.10      ui.container{
    6.11        attr = { class = "draft_content wiki" },
     7.1 --- a/app/main/draft/diff.lua	Mon Jan 04 12:00:00 2010 +0100
     7.2 +++ b/app/main/draft/diff.lua	Sun Jan 10 12:00:00 2010 +0100
     7.3 @@ -3,6 +3,16 @@
     7.4  local old_draft_id = param.get("old_draft_id", atom.integer)
     7.5  local new_draft_id = param.get("new_draft_id", atom.integer)
     7.6  
     7.7 +if not old_draft_id or not new_draft_id then
     7.8 +  slot.put( _"Please choose two versions of the draft to compare")
     7.9 +  return
    7.10 +end
    7.11 +
    7.12 +if old_draft_id == new_draft_id then
    7.13 +  slot.put( _"Please choose two different versions of the draft to compare")
    7.14 +  return
    7.15 +end
    7.16 +
    7.17  if old_draft_id > new_draft_id then
    7.18    local tmp = old_draft_id
    7.19    old_draft_id = new_draft_id
     8.1 --- a/app/main/index/index.lua	Mon Jan 04 12:00:00 2010 +0100
     8.2 +++ b/app/main/index/index.lua	Sun Jan 10 12:00:00 2010 +0100
     8.3 @@ -1,12 +1,14 @@
     8.4  slot.select("title", function()
     8.5 -  execute.view{
     8.6 -    module = "member_image",
     8.7 -    view = "_show",
     8.8 -    params = {
     8.9 -      member = app.session.member, 
    8.10 -      image_type = "avatar"
    8.11 +  if app.session.member then
    8.12 +    execute.view{
    8.13 +      module = "member_image",
    8.14 +      view = "_show",
    8.15 +      params = {
    8.16 +        member = app.session.member,
    8.17 +        image_type = "avatar"
    8.18 +      }
    8.19      }
    8.20 -  }
    8.21 +  end
    8.22  end)
    8.23  
    8.24  slot.select("title", function()
    8.25 @@ -43,48 +45,50 @@
    8.26  
    8.27  slot.select("actions", function()
    8.28  
    8.29 -  ui.link{
    8.30 -    content = function()
    8.31 -        ui.image{ static = "icons/16/application_form.png" }
    8.32 -        slot.put(_"Edit my profile")
    8.33 -    end,
    8.34 -    module = "member",
    8.35 -    view = "edit"
    8.36 -  }
    8.37 -
    8.38 -  ui.link{
    8.39 -    content = function()
    8.40 -        ui.image{ static = "icons/16/user_gray.png" }
    8.41 -        slot.put(_"Upload images")
    8.42 -    end,
    8.43 -    module = "member",
    8.44 -    view = "edit_images"
    8.45 -  }
    8.46 -
    8.47 -  execute.view{
    8.48 -    module = "delegation",
    8.49 -    view = "_show_box"
    8.50 -  }
    8.51 -
    8.52 -  ui.link{
    8.53 -    content = function()
    8.54 -        ui.image{ static = "icons/16/wrench.png" }
    8.55 -        slot.put(_"Settings")
    8.56 -    end,
    8.57 -    module = "member",
    8.58 -    view = "settings"
    8.59 -  }
    8.60 -
    8.61 -  if config.download_dir then
    8.62 +  if app.session.member then
    8.63 +    ui.link{
    8.64 +      content = function()
    8.65 +          ui.image{ static = "icons/16/application_form.png" }
    8.66 +          slot.put(_"Edit my profile")
    8.67 +      end,
    8.68 +      module = "member",
    8.69 +      view = "edit"
    8.70 +    }
    8.71 +  
    8.72      ui.link{
    8.73        content = function()
    8.74 -          ui.image{ static = "icons/16/database_save.png" }
    8.75 -          slot.put(_"Download")
    8.76 +          ui.image{ static = "icons/16/user_gray.png" }
    8.77 +          slot.put(_"Upload images")
    8.78        end,
    8.79 -      module = "index",
    8.80 -      view = "download"
    8.81 +      module = "member",
    8.82 +      view = "edit_images"
    8.83 +    }
    8.84 +  
    8.85 +    execute.view{
    8.86 +      module = "delegation",
    8.87 +      view = "_show_box"
    8.88      }
    8.89 -  end 
    8.90 +  
    8.91 +    ui.link{
    8.92 +      content = function()
    8.93 +          ui.image{ static = "icons/16/wrench.png" }
    8.94 +          slot.put(_"Settings")
    8.95 +      end,
    8.96 +      module = "member",
    8.97 +      view = "settings"
    8.98 +    }
    8.99 +  
   8.100 +    if config.download_dir then
   8.101 +      ui.link{
   8.102 +        content = function()
   8.103 +            ui.image{ static = "icons/16/database_save.png" }
   8.104 +            slot.put(_"Download")
   8.105 +        end,
   8.106 +        module = "index",
   8.107 +        view = "download"
   8.108 +      }
   8.109 +    end 
   8.110 +  end
   8.111  end)
   8.112  
   8.113  local lang = locale.get("lang")
   8.114 @@ -106,24 +110,25 @@
   8.115  
   8.116  util.help("index.index", _"Home")
   8.117  
   8.118 -
   8.119 -local selector = Area:new_selector()
   8.120 -  :reset_fields()
   8.121 -  :add_field("area.id", nil, { "grouped" })
   8.122 -  :add_field("area.name", nil, { "grouped" })
   8.123 -  :add_field("membership.member_id NOTNULL", "is_member", { "grouped" })
   8.124 -  :add_field("count(issue.id)", "issues_to_vote_count")
   8.125 -  :add_field("count(interest.member_id)", "interested_issues_to_vote_count")
   8.126 -  :join("issue", nil, "issue.area_id = area.id AND issue.fully_frozen NOTNULL AND issue.closed ISNULL")
   8.127 -  :left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
   8.128 -  :add_where{ "direct_voter.member_id ISNULL" }
   8.129 -  :left_join("interest", nil, { "interest.issue_id = issue.id AND interest.member_id = ?", app.session.member.id })
   8.130 -  :left_join("membership", nil, { "membership.area_id = area.id AND membership.member_id = ? ", app.session.member.id })
   8.131 -
   8.132  local areas = {}
   8.133 -for i, area in ipairs(selector:exec()) do
   8.134 -  if area.is_member or area.interested_issues_to_vote_count > 0 then
   8.135 -    areas[#areas+1] = area
   8.136 +if app.session.member then
   8.137 +  local selector = Area:new_selector()
   8.138 +    :reset_fields()
   8.139 +    :add_field("area.id", nil, { "grouped" })
   8.140 +    :add_field("area.name", nil, { "grouped" })
   8.141 +    :add_field("membership.member_id NOTNULL", "is_member", { "grouped" })
   8.142 +    :add_field("count(issue.id)", "issues_to_vote_count")
   8.143 +    :add_field("count(interest.member_id)", "interested_issues_to_vote_count")
   8.144 +    :join("issue", nil, "issue.area_id = area.id AND issue.fully_frozen NOTNULL AND issue.closed ISNULL")
   8.145 +    :left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
   8.146 +    :add_where{ "direct_voter.member_id ISNULL" }
   8.147 +    :left_join("interest", nil, { "interest.issue_id = issue.id AND interest.member_id = ?", app.session.member.id })
   8.148 +    :left_join("membership", nil, { "membership.area_id = area.id AND membership.member_id = ? ", app.session.member.id })
   8.149 +  
   8.150 +  for i, area in ipairs(selector:exec()) do
   8.151 +    if area.is_member or area.interested_issues_to_vote_count > 0 then
   8.152 +      areas[#areas+1] = area
   8.153 +    end
   8.154    end
   8.155  end
   8.156  
   8.157 @@ -190,9 +195,27 @@
   8.158    }
   8.159  end
   8.160  
   8.161 -execute.view{
   8.162 -  module = "member",
   8.163 -  view = "_show",
   8.164 -  params = { member = app.session.member }
   8.165 -}
   8.166 +local initiatives_selector = Initiative:new_selector()
   8.167 +  :join("initiator", nil, { "initiator.initiative_id = initiative.id AND initiator.member_id = ? AND initiator.accepted ISNULL", app.session.member.id })
   8.168 +
   8.169 +if initiatives_selector:count() > 0 then
   8.170 +  ui.container{
   8.171 +    attr = { style = "font-weight: bold;" },
   8.172 +    content = _"Initiatives that invited you to become initiator:"
   8.173 +  }
   8.174  
   8.175 +  execute.view{
   8.176 +    module = "initiative",
   8.177 +    view = "_list",
   8.178 +    params = { initiatives_selector = initiatives_selector }
   8.179 +  }
   8.180 +end
   8.181 +
   8.182 +
   8.183 +if app.session.member then
   8.184 +  execute.view{
   8.185 +    module = "member",
   8.186 +    view = "_show",
   8.187 +    params = { member = app.session.member }
   8.188 +  }
   8.189 +end
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/app/main/initiative/_action/accept_invitation.lua	Sun Jan 10 12:00:00 2010 +0100
     9.3 @@ -0,0 +1,32 @@
     9.4 +local initiator = Initiator:by_pk(param.get_id(), app.session.member.id)
     9.5 +
     9.6 +if not initiator then
     9.7 +  slot.put_into("error", _"Sorry, but you are currently not invited")
     9.8 +  return
     9.9 +end
    9.10 +
    9.11 +-- TODO important m1 selectors returning result _SET_!
    9.12 +local issue = initiator.initiative:get_reference_selector("issue"):for_share():single_object_mode():exec()
    9.13 +
    9.14 +if issue.closed then
    9.15 +  slot.put_into("error", _"This issue is already closed.")
    9.16 +  return false
    9.17 +elseif issue.half_frozen then 
    9.18 +  slot.put_into("error", _"This issue is already frozen.")
    9.19 +  return false
    9.20 +end
    9.21 +
    9.22 +if initiator.initiative.revoked then
    9.23 +  slot.put_into("error", _"This initiative is revoked")
    9.24 +  return false
    9.25 +end
    9.26 +
    9.27 +if initiator.accepted then
    9.28 +  slot.put_into("error", _"You are already initator")
    9.29 +  return
    9.30 +end
    9.31 +
    9.32 +initiator.accepted = true
    9.33 +initiator:save()
    9.34 +
    9.35 +slot.put_into("notice", _"You are now initiator of this initiative")
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/app/main/initiative/_action/add_initiator.lua	Sun Jan 10 12:00:00 2010 +0100
    10.3 @@ -0,0 +1,49 @@
    10.4 +local initiative = Initiative:by_id(param.get("initiative_id"))
    10.5 +local member = Member:by_id(param.get("member_id"))
    10.6 +
    10.7 +if not member then
    10.8 +  slot.put_into("error", _"Please choose a member")
    10.9 +  return false
   10.10 +end
   10.11 +
   10.12 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
   10.13 +if not initiator or initiator.accepted ~= true then
   10.14 +  error("access denied")
   10.15 +end
   10.16 +
   10.17 +-- TODO important m1 selectors returning result _SET_!
   10.18 +local issue = initiative:get_reference_selector("issue"):for_share():single_object_mode():exec()
   10.19 +
   10.20 +if issue.closed then
   10.21 +  slot.put_into("error", _"This issue is already closed.")
   10.22 +  return false
   10.23 +elseif issue.half_frozen then 
   10.24 +  slot.put_into("error", _"This issue is already frozen.")
   10.25 +  return false
   10.26 +end
   10.27 +
   10.28 +if initiative.revoked then
   10.29 +  slot.put_into("error", _"This initiative is revoked")
   10.30 +  return false
   10.31 +end
   10.32 +
   10.33 +local initiator = Initiator:by_pk(initiative.id, member.id)
   10.34 +if initiator then
   10.35 +  if initiator.accepted == true then
   10.36 +    slot.put_into("error", _"This member is already initiator of this initiative")
   10.37 +  elseif initiator.accepted == false then
   10.38 +    slot.put_into("error", _"This member has rejected to become initiator of this initiative")
   10.39 +  elseif initiator.accepted == nil then
   10.40 +    slot.put_into("error", _"This member is already invited to become initiator of this initiative")
   10.41 +  end
   10.42 +  return false
   10.43 +end
   10.44 +
   10.45 +local initiator = Initiator:new()
   10.46 +initiator.initiative_id = initiative.id
   10.47 +initiator.member_id = member.id
   10.48 +initiator.accepted = nil
   10.49 +initiator:save()
   10.50 +
   10.51 +slot.put_into("notice", _"Member is now invited to be initiator")
   10.52 +
    11.1 --- a/app/main/initiative/_action/add_support.lua	Mon Jan 04 12:00:00 2010 +0100
    11.2 +++ b/app/main/initiative/_action/add_support.lua	Sun Jan 10 12:00:00 2010 +0100
    11.3 @@ -11,6 +11,11 @@
    11.4    return false
    11.5  end
    11.6  
    11.7 +if initiative.revoked then
    11.8 +  slot.put_into("error", _"This initiative is revoked")
    11.9 +  return false
   11.10 +end
   11.11 +
   11.12  local member = app.session.member
   11.13  
   11.14  local supporter = Supporter:by_pk(initiative.id, member.id)
    12.1 --- a/app/main/initiative/_action/create.lua	Mon Jan 04 12:00:00 2010 +0100
    12.2 +++ b/app/main/initiative/_action/create.lua	Sun Jan 10 12:00:00 2010 +0100
    12.3 @@ -29,6 +29,13 @@
    12.4    area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
    12.5  end
    12.6  
    12.7 +local policy_id = param.get("policy_id", atom.integer)
    12.8 +
    12.9 +if policy_id == -1 then
   12.10 +  slot.put_into("error", _"Please choose a policy")
   12.11 +  return false
   12.12 +end
   12.13 +
   12.14  local name = param.get("name")
   12.15  
   12.16  local name = util.trim(name)
   12.17 @@ -41,7 +48,6 @@
   12.18  local initiative = Initiative:new()
   12.19  
   12.20  if not issue then
   12.21 -  local policy_id = param.get("policy_id", atom.integer)
   12.22    if not area:get_reference_selector("allowed_policies")
   12.23      :add_where{ "policy.id = ?", policy_id }
   12.24      :optional_object_mode()
   12.25 @@ -80,6 +86,7 @@
   12.26  local initiator = Initiator:new()
   12.27  initiator.initiative_id = initiative.id
   12.28  initiator.member_id = app.session.member.id
   12.29 +initiator.accepted = true
   12.30  initiator:save()
   12.31  
   12.32  local supporter = Supporter:new()
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/app/main/initiative/_action/reject_initiator_invitation.lua	Sun Jan 10 12:00:00 2010 +0100
    13.3 @@ -0,0 +1,24 @@
    13.4 +local initiative = Initiative:by_id(param.get("initiative_id"))
    13.5 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
    13.6 +
    13.7 +-- TODO important m1 selectors returning result _SET_!
    13.8 +local issue = initiative:get_reference_selector("issue"):for_share():single_object_mode():exec()
    13.9 +
   13.10 +if issue.closed then
   13.11 +  slot.put_into("error", _"This issue is already closed.")
   13.12 +  return false
   13.13 +elseif issue.half_frozen then 
   13.14 +  slot.put_into("error", _"This issue is already frozen.")
   13.15 +  return false
   13.16 +end
   13.17 +
   13.18 +if initiator.accepted ~= nil then
   13.19 +  error("access denied")
   13.20 +end
   13.21 +
   13.22 +initiator.accepted = false
   13.23 +initiator:save()
   13.24 +
   13.25 +slot.put_into("notice", _"Invitation has been refused")
   13.26 +
   13.27 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/app/main/initiative/_action/remove_initiator.lua	Sun Jan 10 12:00:00 2010 +0100
    14.3 @@ -0,0 +1,44 @@
    14.4 +local initiative = Initiative:by_id(param.get("initiative_id"))
    14.5 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
    14.6 +
    14.7 +-- TODO important m1 selectors returning result _SET_!
    14.8 +local issue = initiative:get_reference_selector("issue"):for_share():single_object_mode():exec()
    14.9 +
   14.10 +if issue.closed then
   14.11 +  slot.put_into("error", _"This issue is already closed.")
   14.12 +  return false
   14.13 +elseif issue.half_frozen then 
   14.14 +  slot.put_into("error", _"This issue is already frozen.")
   14.15 +  return false
   14.16 +end
   14.17 +
   14.18 +if initiative.revoked then
   14.19 +  slot.put_into("error", _"This initiative is revoked")
   14.20 +  return false
   14.21 +end
   14.22 +
   14.23 +local initiator_todelete = Initiator:by_pk(initiative.id, param.get("member_id", atom.integer))
   14.24 +
   14.25 +if not (initiator and initiator.accepted) and not (initiator.member_id == initiator_todelete.member_id) then
   14.26 +  error("access denied")
   14.27 +end
   14.28 +
   14.29 +if initiator_todelete.accepted == false and initiator.member_id ~= initiator_todelete.member_id then
   14.30 +  error("access denied")
   14.31 +end
   14.32 +
   14.33 +local initiators = initiative
   14.34 +  :get_reference_selector("initiators")
   14.35 +  :add_where("accepted")
   14.36 +  :for_update()
   14.37 +  :exec()
   14.38 +
   14.39 +if #initiators > 1 or initiator_todelete.accepted ~= true then
   14.40 +  initiator_todelete:destroy()
   14.41 +  slot.put_into("notice", _"Member has been removed from initiators")
   14.42 +else
   14.43 +  slot.put_into("error", _"Can't remove last initiator")
   14.44 +  return false
   14.45 +end
   14.46 +
   14.47 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/app/main/initiative/_action/revoke.lua	Sun Jan 10 12:00:00 2010 +0100
    15.3 @@ -0,0 +1,47 @@
    15.4 +local initiative = Initiative:by_id(param.get_id())
    15.5 +
    15.6 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
    15.7 +if not initiator or initiator.accepted ~= true then
    15.8 +  error("access denied")
    15.9 +end
   15.10 +
   15.11 +-- TODO important m1 selectors returning result _SET_!
   15.12 +local issue = initiative:get_reference_selector("issue"):for_share():single_object_mode():exec()
   15.13 +
   15.14 +if issue.closed then
   15.15 +  slot.put_into("error", _"This issue is already closed.")
   15.16 +  return false
   15.17 +elseif issue.half_frozen then 
   15.18 +  slot.put_into("error", _"This issue is already frozen.")
   15.19 +  return false
   15.20 +end
   15.21 +
   15.22 +if initiative.revoked then
   15.23 +  slot.put_into("error", _"This initiative is already revoked")
   15.24 +  return false
   15.25 +end
   15.26 +
   15.27 +local suggested_initiative_id = param.get("suggested_initiative_id", atom.integer)
   15.28 +
   15.29 +if suggested_initiative_id ~= -1 then
   15.30 +  local suggested_initiative = Initiative:by_id(suggested_initiative_id)
   15.31 +  if not suggested_initiative then
   15.32 +    error("object not found")
   15.33 +  end
   15.34 +  if initiative.id == suggested_initiative.id then
   15.35 +    slot.put_into("error", _"You can't suggest the initiative you are revoking")
   15.36 +    return false
   15.37 +  end
   15.38 +  initiative.suggested_initiative_id = suggested_initiative.id
   15.39 +end
   15.40 +
   15.41 +if not param.get("are_you_sure", atom.boolean) then
   15.42 +  slot.put_into("error", _"You have to mark 'Are you sure' to revoke!")
   15.43 +  return false
   15.44 +end
   15.45 +
   15.46 +initiative.revoked = "now"
   15.47 +initiative:save()
   15.48 +
   15.49 +slot.put_into("notice", _"Initiative is revoked now")
   15.50 +
    16.1 --- a/app/main/initiative/_action/update.lua	Mon Jan 04 12:00:00 2010 +0100
    16.2 +++ b/app/main/initiative/_action/update.lua	Sun Jan 10 12:00:00 2010 +0100
    16.3 @@ -1,4 +1,26 @@
    16.4  local initiative = Initiative:by_id(param.get_id())
    16.5 +
    16.6 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
    16.7 +if not initiator or not initiator.accepted then
    16.8 +  error("access denied")
    16.9 +end
   16.10 +
   16.11 +-- TODO important m1 selectors returning result _SET_!
   16.12 +local issue = initiative:get_reference_selector("issue"):for_share():single_object_mode():exec()
   16.13 +
   16.14 +if issue.closed then
   16.15 +  slot.put_into("error", _"This issue is already closed.")
   16.16 +  return false
   16.17 +elseif issue.half_frozen then 
   16.18 +  slot.put_into("error", _"This issue is already frozen.")
   16.19 +  return false
   16.20 +end
   16.21 +
   16.22 +if initiative.revoked then
   16.23 +  slot.put_into("error", _"This initiative is revoked")
   16.24 +  return false
   16.25 +end
   16.26 +
   16.27  param.update(initiative, "discussion_url")
   16.28  initiative:save()
   16.29  
    17.1 --- a/app/main/initiative/_list.lua	Mon Jan 04 12:00:00 2010 +0100
    17.2 +++ b/app/main/initiative/_list.lua	Sun Jan 10 12:00:00 2010 +0100
    17.3 @@ -42,13 +42,25 @@
    17.4    name = "issue_" .. tostring(issue.id) ..  "_initiative_list"
    17.5  end
    17.6  
    17.7 -ui.order{
    17.8 +ui_order = ui.order
    17.9 +
   17.10 +if param.get("no_sort", atom.boolean) then
   17.11 +  ui_order = function(args) args.content() end
   17.12 +  if issue.ranks_available then
   17.13 +    initiatives_selector:add_order_by("initiative.rank, initiative.admitted DESC, vote_ratio(initiative.positive_votes, initiative.negative_votes) DESC, initiative.id")
   17.14 +  else
   17.15 +    initiatives_selector:add_order_by("initiative.supporter_count::float / issue.population::float DESC, initiative.id")
   17.16 +  end
   17.17 +end
   17.18 +
   17.19 +ui_order{
   17.20    name = name,
   17.21    selector = initiatives_selector,
   17.22    options = order_options,
   17.23    content = function()
   17.24      ui.paginate{
   17.25        selector = initiatives_selector,
   17.26 +      per_page = param.get("per_page", atom.number),
   17.27        content = function()
   17.28          local initiatives = initiatives_selector:exec()
   17.29          local columns = {}
   17.30 @@ -94,7 +106,12 @@
   17.31          }
   17.32          columns[#columns+1] = {
   17.33            content = function(record)
   17.34 +            local link_class
   17.35 +            if record.revoked then
   17.36 +              link_class = "revoked"
   17.37 +            end
   17.38              ui.link{
   17.39 +              attr = { class = link_class },
   17.40                content = function()
   17.41                  local name
   17.42                  if record.name_highlighted then
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/app/main/initiative/add_initiator.lua	Sun Jan 10 12:00:00 2010 +0100
    18.3 @@ -0,0 +1,60 @@
    18.4 +local initiative = Initiative:by_id(param.get("initiative_id"))
    18.5 +
    18.6 +slot.put_into("title", _"Invite an initiator to initiative")
    18.7 +
    18.8 +slot.select("actions", function()
    18.9 +  ui.link{
   18.10 +    content = function()
   18.11 +        ui.image{ static = "icons/16/cancel.png" }
   18.12 +        slot.put(_"Cancel")
   18.13 +    end,
   18.14 +    module = "initiative",
   18.15 +    view = "show",
   18.16 +    id = initiative.id,
   18.17 +    params = {
   18.18 +      tab = "initiators"
   18.19 +    }
   18.20 +  }
   18.21 +end)
   18.22 +
   18.23 +util.help("initiative.add_initiator", _"Invite an initiator to initiative")
   18.24 +
   18.25 +ui.form{
   18.26 +  attr = { class = "vertical" },
   18.27 +  module = "initiative",
   18.28 +  action = "add_initiator",
   18.29 +  params = {
   18.30 +    initiative_id = initiative.id,
   18.31 +  },
   18.32 +  routing = {
   18.33 +    ok = {
   18.34 +      mode = "redirect",
   18.35 +      module = "initiative",
   18.36 +      view = "show",
   18.37 +      id = initiative.id,
   18.38 +      params = {
   18.39 +        tab = "initiators",
   18.40 +      }
   18.41 +    }
   18.42 +  },
   18.43 +  content = function()
   18.44 +    local records = {
   18.45 +      {
   18.46 +        id = "-1",
   18.47 +        name = _"Choose member"
   18.48 +      }
   18.49 +    }
   18.50 +    local contact_members = app.session.member:get_reference_selector("saved_members"):add_order_by("name"):exec()
   18.51 +    for i, record in ipairs(contact_members) do
   18.52 +      records[#records+1] = record
   18.53 +    end
   18.54 +    ui.field.select{
   18.55 +      label = _"Member",
   18.56 +      name = "member_id",
   18.57 +      foreign_records = records,
   18.58 +      foreign_id = "id",
   18.59 +      foreign_name = "name"
   18.60 +    }
   18.61 +    ui.submit{ text = _"Save" }
   18.62 +  end
   18.63 +}
   18.64 \ No newline at end of file
    19.1 --- a/app/main/initiative/new.lua	Mon Jan 04 12:00:00 2010 +0100
    19.2 +++ b/app/main/initiative/new.lua	Sun Jan 10 12:00:00 2010 +0100
    19.3 @@ -30,14 +30,17 @@
    19.4      if issue_id then
    19.5        ui.field.text{ label = _"Issue",  value = issue_id }
    19.6      else
    19.7 -      local value
    19.8 +      tmp = { { id = -1, name = _"Please choose a policy" } }
    19.9 +      for i, allowed_policy in ipairs(area.allowed_policies) do
   19.10 +        tmp[#tmp+1] = allowed_policy
   19.11 +      end
   19.12        ui.field.select{
   19.13          label = _"Policy",
   19.14          name = "policy_id",
   19.15 -        foreign_records = area.allowed_policies,
   19.16 +        foreign_records = tmp,
   19.17          foreign_id = "id",
   19.18          foreign_name = "name",
   19.19 -        value = area.default_policy.id
   19.20 +        value = (area.default_policy or {}).id
   19.21        }
   19.22      end
   19.23      ui.field.text{ label = _"Name", name = "name" }
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/app/main/initiative/remove_initiator.lua	Sun Jan 10 12:00:00 2010 +0100
    20.3 @@ -0,0 +1,65 @@
    20.4 +local initiative = Initiative:by_id(param.get("initiative_id"))
    20.5 +
    20.6 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
    20.7 +if not initiator or initiator.accepted ~= true then
    20.8 +  error("access denied")
    20.9 +end
   20.10 +
   20.11 +slot.put_into("title", _"Remove initiator from initiative")
   20.12 +
   20.13 +slot.select("actions", function()
   20.14 +  ui.link{
   20.15 +    content = function()
   20.16 +        ui.image{ static = "icons/16/cancel.png" }
   20.17 +        slot.put(_"Cancel")
   20.18 +    end,
   20.19 +    module = "initiative",
   20.20 +    view = "show",
   20.21 +    id = initiative.id,
   20.22 +    params = {
   20.23 +      tab = "initiators"
   20.24 +    }
   20.25 +  }
   20.26 +end)
   20.27 +
   20.28 +util.help("initiative.remove_initiator", _"Remove initiator from initiative")
   20.29 +
   20.30 +ui.form{
   20.31 +  attr = { class = "vertical" },
   20.32 +  module = "initiative",
   20.33 +  action = "remove_initiator",
   20.34 +  params = {
   20.35 +    initiative_id = initiative.id,
   20.36 +  },
   20.37 +  routing = {
   20.38 +    ok = {
   20.39 +      mode = "redirect",
   20.40 +      module = "initiative",
   20.41 +      view = "show",
   20.42 +      id = initiative.id,
   20.43 +      params = {
   20.44 +        tab = "initiators",
   20.45 +      }
   20.46 +    }
   20.47 +  },
   20.48 +  content = function()
   20.49 +    local records = {
   20.50 +      {
   20.51 +        id = "-1",
   20.52 +        name = _"Choose initiator"
   20.53 +      }
   20.54 +    }
   20.55 +    local members = initiative:get_reference_selector("initiating_members"):add_where("accepted OR accepted ISNULL"):exec()
   20.56 +    for i, record in ipairs(members) do
   20.57 +      records[#records+1] = record
   20.58 +    end
   20.59 +    ui.field.select{
   20.60 +      label = _"Member",
   20.61 +      name = "member_id",
   20.62 +      foreign_records = records,
   20.63 +      foreign_id = "id",
   20.64 +      foreign_name = "name"
   20.65 +    }
   20.66 +    ui.submit{ text = _"Save" }
   20.67 +  end
   20.68 +}
   20.69 \ No newline at end of file
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/app/main/initiative/revoke.lua	Sun Jan 10 12:00:00 2010 +0100
    21.3 @@ -0,0 +1,62 @@
    21.4 +local initiative = Initiative:by_id(param.get_id())
    21.5 +
    21.6 +slot.put_into("title", _"Revoke initiative")
    21.7 +
    21.8 +slot.select("actions", function()
    21.9 +  ui.link{
   21.10 +    content = function()
   21.11 +        ui.image{ static = "icons/16/cancel.png" }
   21.12 +        slot.put(_"Cancel")
   21.13 +    end,
   21.14 +    module = "initiative",
   21.15 +    view = "show",
   21.16 +    id = initiative.id,
   21.17 +    params = {
   21.18 +      tab = "initiators"
   21.19 +    }
   21.20 +  }
   21.21 +end)
   21.22 +
   21.23 +util.help("initiative.revoke")
   21.24 +
   21.25 +ui.form{
   21.26 +  attr = { class = "vertical" },
   21.27 +  module = "initiative",
   21.28 +  action = "revoke",
   21.29 +  id = initiative.id,
   21.30 +  routing = {
   21.31 +    ok = {
   21.32 +      mode = "redirect",
   21.33 +      module = "initiative",
   21.34 +      view = "show",
   21.35 +      id = initiative.id
   21.36 +    }
   21.37 +  },
   21.38 +  content = function()
   21.39 +    local initiatives = app.session.member
   21.40 +      :get_reference_selector("supported_initiatives")
   21.41 +      :join("issue", nil, "issue.id = initiative.issue_id")
   21.42 +      :add_field("'Issue #' || issue.id || ': ' || initiative.name", "myname")
   21.43 +      :exec()
   21.44 +
   21.45 +    local tmp = { { id = -1, myname = _"Suggest no initiative" }}
   21.46 +    for i, initiative in ipairs(initiatives) do
   21.47 +      tmp[#tmp+1] = initiative
   21.48 +    end
   21.49 +    ui.field.select{
   21.50 +      label = _"Suggested initiative",
   21.51 +      name = "suggested_initiative_id",
   21.52 +      foreign_records = tmp,
   21.53 +      foreign_id = "id",
   21.54 +      foreign_name = "myname",
   21.55 +      value = param.get("suggested_initiative_id", atom.integer)
   21.56 +    }
   21.57 +    slot.put("")
   21.58 +    ui.field.boolean{
   21.59 +      label = _"Are you sure?",
   21.60 +      name = "are_you_sure",
   21.61 +    }
   21.62 +
   21.63 +    ui.submit{ text = _"Revoke initiative" }
   21.64 +  end
   21.65 +}
   21.66 \ No newline at end of file
    22.1 --- a/app/main/initiative/show.lua	Mon Jan 04 12:00:00 2010 +0100
    22.2 +++ b/app/main/initiative/show.lua	Sun Jan 10 12:00:00 2010 +0100
    22.3 @@ -18,17 +18,31 @@
    22.4    params = { issue = initiative.issue }
    22.5  }
    22.6  
    22.7 +if initiative.revoked then
    22.8 +  ui.container{
    22.9 +    attr = { class = "revoked_info" },
   22.10 +    content = function()
   22.11 +      slot.put(_("This initiative has been revoked at #{revoked}", { revoked = format.timestamp(initiative.revoked) }))
   22.12 +      local suggested_initiative = initiative.suggested_initiative
   22.13 +      if suggested_initiative then
   22.14 +        slot.put("<br /><br />")
   22.15 +        slot.put(_("The initiators suggest to support the following initiative:"))
   22.16 +        slot.put("<br />")
   22.17 +        ui.link{
   22.18 +          content = _("Issue ##{id}", { id = suggested_initiative.issue.id } ) .. ": " .. encode.html(suggested_initiative.name),
   22.19 +          module = "initiative",
   22.20 +          view = "show",
   22.21 +          id = suggested_initiative.id
   22.22 +        }
   22.23 +      end
   22.24 +    end
   22.25 +  }
   22.26 +end
   22.27 +
   22.28  local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
   22.29  
   22.30  --slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(initiative.id) .. '.rss" />')
   22.31  
   22.32 -execute.view{
   22.33 -  module = "supporter",
   22.34 -  view = "_show_box",
   22.35 -  params = { initiative = initiative }
   22.36 -}
   22.37 -
   22.38 -slot.put_into("sub_title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) ))
   22.39  
   22.40  slot.select("actions", function()
   22.41    if not initiative.issue.fully_frozen and not initiative.issue.closed then
   22.42 @@ -45,48 +59,126 @@
   22.43    end
   22.44  end)
   22.45  
   22.46 +slot.put_into("sub_title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) ))
   22.47 +
   22.48 +slot.select("support", function()
   22.49 +  ui.container{
   22.50 +    attr = { class = "actions" },
   22.51 +    content = function()
   22.52 +      execute.view{
   22.53 +        module = "supporter",
   22.54 +        view = "_show_box",
   22.55 +        params = { initiative = initiative }
   22.56 +      }
   22.57 +      if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
   22.58 +        ui.link{
   22.59 +          attr = { class = "action", style = "float: left;" },
   22.60 +          content = function()
   22.61 +            ui.image{ static = "icons/16/script_delete.png" }
   22.62 +            slot.put(_"Revoke initiative")
   22.63 +          end,
   22.64 +          module = "initiative",
   22.65 +          view = "revoke",
   22.66 +          id = initiative.id
   22.67 +        }
   22.68 +      end
   22.69 +    end
   22.70 +  }
   22.71 +end)
   22.72  
   22.73  util.help("initiative.show")
   22.74  
   22.75 +if initiator and initiator.accepted == nil then
   22.76 +  ui.container{
   22.77 +    attr = { class = "initiator_invite_info" },
   22.78 +    content = function()
   22.79 +      slot.put(_"You are invited to become initiator of this initiative.")
   22.80 +      slot.put(" ")
   22.81 +      ui.link{
   22.82 +        content = function()
   22.83 +          ui.image{ static = "icons/16/tick.png" }
   22.84 +          slot.put(_"Accept invitation")
   22.85 +        end,
   22.86 +        module = "initiative",
   22.87 +        action = "accept_invitation",
   22.88 +        id = initiative.id,
   22.89 +        routing = {
   22.90 +          default = {
   22.91 +            mode = "redirect",
   22.92 +            module = request.get_module(),
   22.93 +            view = request.get_view(),
   22.94 +            id = param.get_id_cgi(),
   22.95 +            params = param.get_all_cgi()
   22.96 +          }
   22.97 +        }
   22.98 +      }
   22.99 +      slot.put(" ")
  22.100 +      ui.link{
  22.101 +        content = function()
  22.102 +          ui.image{ static = "icons/16/cross.png" }
  22.103 +          slot.put(_"Refuse invitation")
  22.104 +        end,
  22.105 +        module = "initiative",
  22.106 +        action = "reject_initiator_invitation",
  22.107 +        params = {
  22.108 +          initiative_id = initiative.id,
  22.109 +          member_id = app.session.member.id
  22.110 +        },
  22.111 +        routing = {
  22.112 +          default = {
  22.113 +            mode = "redirect",
  22.114 +            module = request.get_module(),
  22.115 +            view = request.get_view(),
  22.116 +            id = param.get_id_cgi(),
  22.117 +            params = param.get_all_cgi()
  22.118 +          }
  22.119 +        }
  22.120 +      }
  22.121 +    end
  22.122 +  }
  22.123 +  slot.put("<br />")
  22.124 +end
  22.125  
  22.126 -ui.container{
  22.127 -  attr = { class = "vertical" },
  22.128 -  content = function()
  22.129 -    ui.container{
  22.130 -      attr = { class = "ui_field_label" },
  22.131 -      content = _"Discussion URL"
  22.132 -    }
  22.133 -    ui.tag{
  22.134 -      tag = "span",
  22.135 -      content = function()
  22.136 -        if initiative.discussion_url and #initiative.discussion_url > 0 then
  22.137 -          ui.link{
  22.138 -            attr = {
  22.139 -              class = "actions",
  22.140 -              target = "_blank",
  22.141 -              title = initiative.discussion_url
  22.142 -            },
  22.143 -            content = function()
  22.144 -              slot.put(encode.html(initiative.discussion_url))
  22.145 -            end,
  22.146 -            external = initiative.discussion_url
  22.147 -          }
  22.148 +if (initiative.discussion_url and #initiative.discussion_url > 0)
  22.149 +  or (initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked) then
  22.150 +  ui.container{
  22.151 +    attr = { class = "vertical" },
  22.152 +    content = function()
  22.153 +      ui.container{
  22.154 +        attr = { class = "ui_field_label" },
  22.155 +        content = _"Discussion with initiators"
  22.156 +      }
  22.157 +      ui.tag{
  22.158 +        tag = "span",
  22.159 +        content = function()
  22.160 +          if initiative.discussion_url and #initiative.discussion_url > 0 then
  22.161 +            ui.link{
  22.162 +              attr = {
  22.163 +                class = "actions",
  22.164 +                target = "_blank",
  22.165 +                title = initiative.discussion_url
  22.166 +              },
  22.167 +              content = function()
  22.168 +                slot.put(encode.html(initiative.discussion_url))
  22.169 +              end,
  22.170 +              external = initiative.discussion_url
  22.171 +            }
  22.172 +          end
  22.173 +          slot.put(" ")
  22.174 +          if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
  22.175 +            ui.link{
  22.176 +              attr = { class = "actions" },
  22.177 +              content = _"(change URL)",
  22.178 +              module = "initiative",
  22.179 +              view = "edit",
  22.180 +              id = initiative.id
  22.181 +            }
  22.182 +          end
  22.183          end
  22.184 -        slot.put(" ")
  22.185 -        if initiator then
  22.186 -          ui.link{
  22.187 -            attr = { class = "actions" },
  22.188 -            content = _"(change URL)",
  22.189 -            module = "initiative",
  22.190 -            view = "edit",
  22.191 -            id = initiative.id
  22.192 -          }
  22.193 -        end
  22.194 -      end
  22.195 -    }
  22.196 -  end
  22.197 -}
  22.198 -
  22.199 +      }
  22.200 +    end
  22.201 +  }
  22.202 +end
  22.203  
  22.204  
  22.205  ui.container{
  22.206 @@ -202,7 +294,7 @@
  22.207      name = "current_draft",
  22.208      label = current_draft_name,
  22.209      content = function()
  22.210 -      if initiator then
  22.211 +      if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
  22.212          ui.link{
  22.213            content = function()
  22.214              ui.image{ static = "icons/16/script_add.png" }
  22.215 @@ -238,9 +330,11 @@
  22.216    }
  22.217  end
  22.218  
  22.219 +local suggestion_count = initiative:get_reference_selector("suggestions"):count()
  22.220 +
  22.221  tabs[#tabs+1] = {
  22.222    name = "suggestion",
  22.223 -  label = _"Suggestions",
  22.224 +  label = _"Suggestions" .. " (" .. tostring(suggestion_count) .. ")",
  22.225    content = function()
  22.226      execute.view{
  22.227        module = "suggestion",
  22.228 @@ -251,7 +345,7 @@
  22.229        }
  22.230      }
  22.231      slot.put("<br />")
  22.232 -    if not initiative.issue.fully_frozen and not initiative.issue.closed then
  22.233 +    if not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
  22.234        ui.link{
  22.235          content = function()
  22.236            ui.image{ static = "icons/16/comment_add.png" }
  22.237 @@ -264,57 +358,126 @@
  22.238    end
  22.239  }
  22.240  
  22.241 +local members_selector =  initiative:get_reference_selector("supporting_members_snapshot")
  22.242 +          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
  22.243 +          :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")
  22.244 +          :add_field("direct_interest_snapshot.weight")
  22.245 +          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
  22.246 +          :add_where("direct_supporter_snapshot.satisfied")
  22.247 +
  22.248 +local satisfied_supporter_count = members_selector:count()
  22.249 +
  22.250  tabs[#tabs+1] = {
  22.251    name = "satisfied_supporter",
  22.252 -  label = _"Supporter",
  22.253 +  label = _"Supporter" .. " (" .. tostring(satisfied_supporter_count) .. ")",
  22.254 +  content = function()
  22.255 +    execute.view{
  22.256 +      module = "member",
  22.257 +      view = "_list",
  22.258 +      params = {
  22.259 +        initiative = initiative,
  22.260 +        members_selector = members_selector
  22.261 +      }
  22.262 +    }
  22.263 +  end
  22.264 +}
  22.265 +
  22.266 +local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
  22.267 +          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
  22.268 +          :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")
  22.269 +          :add_field("direct_interest_snapshot.weight")
  22.270 +          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
  22.271 +          :add_where("NOT direct_supporter_snapshot.satisfied")
  22.272 +
  22.273 +local potential_supporter_count = members_selector:count()
  22.274 +
  22.275 +tabs[#tabs+1] = {
  22.276 +  name = "supporter",
  22.277 +  label = _"Potential supporter" .. " (" .. tostring(potential_supporter_count) .. ")",
  22.278    content = function()
  22.279      execute.view{
  22.280        module = "member",
  22.281        view = "_list",
  22.282        params = {
  22.283          initiative = initiative,
  22.284 -        members_selector =  initiative:get_reference_selector("supporting_members_snapshot")
  22.285 -          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
  22.286 -          :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")
  22.287 -          :add_field("direct_interest_snapshot.weight")
  22.288 -          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
  22.289 -          :add_where("direct_supporter_snapshot.satisfied")
  22.290 +        members_selector = members_selector
  22.291        }
  22.292      }
  22.293    end
  22.294  }
  22.295  
  22.296 +local initiator_count = initiative:get_reference_selector("initiators"):add_where("accepted"):count()
  22.297 +
  22.298  tabs[#tabs+1] = {
  22.299 -  name = "supporter",
  22.300 -  label = _"Potential supporter",
  22.301 +  name = "initiators",
  22.302 +  label = _"Initiators" .. " (" .. tostring(initiator_count) .. ")",
  22.303    content = function()
  22.304 +     if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
  22.305 +      ui.link{
  22.306 +        attr = { class = "action" },
  22.307 +        content = function()
  22.308 +          ui.image{ static = "icons/16/user_add.png" }
  22.309 +          slot.put(_"Invite initiator")
  22.310 +        end,
  22.311 +        module = "initiative",
  22.312 +        view = "add_initiator",
  22.313 +        params = { initiative_id = initiative.id }
  22.314 +      }
  22.315 +      if initiator_count > 1 then
  22.316 +        ui.link{
  22.317 +          content = function()
  22.318 +            ui.image{ static = "icons/16/user_delete.png" }
  22.319 +            slot.put(_"Remove initiator")
  22.320 +          end,
  22.321 +          module = "initiative",
  22.322 +          view = "remove_initiator",
  22.323 +          params = { initiative_id = initiative.id }
  22.324 +        }
  22.325 +      end
  22.326 +    end
  22.327 +    if initiator and initiator.accepted == false then
  22.328 +        ui.link{
  22.329 +          content = function()
  22.330 +            ui.image{ static = "icons/16/user_delete.png" }
  22.331 +            slot.put(_"Cancel refuse of invitation")
  22.332 +          end,
  22.333 +          module = "initiative",
  22.334 +          action = "remove_initiator",
  22.335 +          params = {
  22.336 +            initiative_id = initiative.id,
  22.337 +            member_id = app.session.member.id
  22.338 +          },
  22.339 +          routing = {
  22.340 +            ok = {
  22.341 +              mode = "redirect",
  22.342 +              module = "initiative",
  22.343 +              view = "show",
  22.344 +              id = initiative.id
  22.345 +            }
  22.346 +          }
  22.347 +        }
  22.348 +    end
  22.349 +    local members_selector = initiative:get_reference_selector("initiating_members")
  22.350 +      :add_field("initiator.accepted", "accepted")
  22.351 +    if not (initiator and initiator.accepted) then
  22.352 +      members_selector:add_where("accepted")
  22.353 +    end
  22.354      execute.view{
  22.355        module = "member",
  22.356        view = "_list",
  22.357        params = {
  22.358 -        initiative = initiative,
  22.359 -        members_selector =  initiative:get_reference_selector("supporting_members_snapshot")
  22.360 -          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
  22.361 -          :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")
  22.362 -          :add_field("direct_interest_snapshot.weight")
  22.363 -          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
  22.364 -          :add_where("NOT direct_supporter_snapshot.satisfied")
  22.365 +        members_selector = members_selector,
  22.366 +        initiator = initiator
  22.367        }
  22.368      }
  22.369    end
  22.370  }
  22.371  
  22.372 -tabs[#tabs+1] = {
  22.373 -  name = "initiators",
  22.374 -  label = _"Initiators",
  22.375 -  content = function()
  22.376 -    execute.view{ module = "member", view = "_list", params = { members_selector = initiative:get_reference_selector("initiating_members") } }
  22.377 -  end
  22.378 -}
  22.379 +local drafts_count = initiative:get_reference_selector("drafts"):count()
  22.380  
  22.381  tabs[#tabs+1] = {
  22.382    name = "drafts",
  22.383 -  label = _"Old drafts",
  22.384 +  label = _"Draft history" .. " (" .. tostring(drafts_count) .. ")",
  22.385    content = function()
  22.386      execute.view{ module = "draft", view = "_list", params = { drafts = initiative.drafts } }
  22.387    end
  22.388 @@ -338,7 +501,7 @@
  22.389            label = _"Created at",
  22.390            value = format.timestamp(initiative.created)
  22.391          }
  22.392 -        ui.field.date{ label = _"Revoked at", name = "revoked" }
  22.393 +--         ui.field.date{ label = _"Revoked at", name = "revoked" }
  22.394          ui.field.boolean{ label = _"Admitted", name = "admitted" }
  22.395        end
  22.396      }
    23.1 --- a/app/main/issue/_list.lua	Mon Jan 04 12:00:00 2010 +0100
    23.2 +++ b/app/main/issue/_list.lua	Sun Jan 10 12:00:00 2010 +0100
    23.3 @@ -5,6 +5,10 @@
    23.4    ui_filter = function(args) args.content() end
    23.5  end
    23.6  
    23.7 +if param.get("no_filter", atom.boolean) then
    23.8 +  ui_filter = function(args) args.content() end
    23.9 +end
   23.10 +
   23.11  local filter_voting = false
   23.12  ui_filter{
   23.13    selector = issues_selector,
   23.14 @@ -86,6 +90,9 @@
   23.15      if not filter_voting then
   23.16        ui_filter = function(args) args.content() end
   23.17      end
   23.18 +    if param.get("no_filter", atom.boolean) then
   23.19 +      ui_filter = function(args) args.content() end
   23.20 +    end
   23.21      ui_filter{
   23.22        selector = issues_selector,
   23.23        name = "filter_voting",
   23.24 @@ -145,8 +152,11 @@
   23.25              },
   23.26            },
   23.27            content = function()
   23.28 -
   23.29 -            ui.order{
   23.30 +            local ui_order = ui.order
   23.31 +            if param.get("no_sort", atom.boolean) then
   23.32 +              ui_order = function(args) args.content() end
   23.33 +            end
   23.34 +            ui_order{
   23.35                name = "issue_list",
   23.36                selector = issues_selector,
   23.37                options = {
   23.38 @@ -181,7 +191,12 @@
   23.39                  }
   23.40                },
   23.41                content = function()
   23.42 -                ui.paginate{
   23.43 +                local ui_paginate = ui.paginate
   23.44 +                if param.get("per_page") == "all" then
   23.45 +                  ui_paginate = function(args) args.content() end
   23.46 +                end
   23.47 +                ui_paginate{
   23.48 +                  per_page = tonumber(param.get("per_page")),
   23.49                    selector = issues_selector,
   23.50                    content = function()
   23.51                      local highlight_string = param.get("highlight_string", "string")
   23.52 @@ -201,7 +216,7 @@
   23.53                                slot.put("<br />")
   23.54                              end
   23.55                              ui.link{
   23.56 -                              text = _"Issue ##{id}":gsub("#{id}", tostring(record.id)),
   23.57 +                              text = _("Issue ##{id}", { id = tostring(record.id) }),
   23.58                                module = "issue",
   23.59                                view = "show",
   23.60                                id = record.id
   23.61 @@ -213,6 +228,11 @@
   23.62                              end
   23.63                              slot.put("<br />")
   23.64                              slot.put("<br />")
   23.65 +                            if record.old_state then
   23.66 +                              ui.field.text{ value = format.time(record.sort) }
   23.67 +                              ui.field.text{ value = Issue:get_state_name_for_state(record.old_state) .. " > " .. Issue:get_state_name_for_state(record.new_state) }
   23.68 +                            else
   23.69 +                            end
   23.70                            end
   23.71                          },
   23.72                          {
   23.73 @@ -245,7 +265,9 @@
   23.74                                  issue = record,
   23.75                                  initiatives_selector = initiatives_selector,
   23.76                                  highlight_string = highlight_string,
   23.77 -                                limit = 3
   23.78 +                                limit = 3,
   23.79 +                                per_page = param.get("initiatives_per_page", atom.number),
   23.80 +                                no_sort = param.get("initiatives_no_sort", atom.boolean)
   23.81                                }
   23.82                              }
   23.83                            end
    24.1 --- a/app/main/issue/_show_head.lua	Mon Jan 04 12:00:00 2010 +0100
    24.2 +++ b/app/main/issue/_show_head.lua	Sun Jan 10 12:00:00 2010 +0100
    24.3 @@ -77,6 +77,17 @@
    24.4    end
    24.5  --]]
    24.6  
    24.7 +  if config.issue_discussion_url_func then
    24.8 +    local url = config.issue_discussion_url_func(issue)
    24.9 +    ui.link{
   24.10 +      attr = { target = "_blank" },
   24.11 +      external = url,
   24.12 +      content = function()
   24.13 +        ui.image{ static = "icons/16/comments.png" }
   24.14 +        slot.put(_"Discussion on issue")
   24.15 +      end,
   24.16 +    }
   24.17 +  end
   24.18  end)
   24.19  
   24.20  
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/app/main/member/_action/update_stylesheet_url.lua	Sun Jan 10 12:00:00 2010 +0100
    25.3 @@ -0,0 +1,25 @@
    25.4 +
    25.5 +local setting_key = "liquidfeedback_frontend_developer_features"
    25.6 +local setting = Setting:by_pk(app.session.member.id, setting_key)
    25.7 +
    25.8 +if not setting then
    25.9 +  error("access denied")
   25.10 +end
   25.11 +
   25.12 +local stylesheet_url = util.trim(param.get("stylesheet_url"))
   25.13 +local setting_key = "liquidfeedback_frontend_stylesheet_url"
   25.14 +local setting = Setting:by_pk(app.session.member.id, setting_key)
   25.15 +
   25.16 +if stylesheet_url and #stylesheet_url > 0 then
   25.17 +  if not setting then
   25.18 +    setting = Setting:new()
   25.19 +    setting.member_id = app.session.member.id
   25.20 +    setting.key = setting_key
   25.21 +  end
   25.22 +  setting.value = stylesheet_url
   25.23 +  setting:save()
   25.24 +elseif setting then
   25.25 +  setting:destroy()
   25.26 +end
   25.27 +
   25.28 +slot.put_into("notice", _"Stylesheet URL has been updated")
    26.1 --- a/app/main/member/_list.lua	Mon Jan 04 12:00:00 2010 +0100
    26.2 +++ b/app/main/member/_list.lua	Sun Jan 10 12:00:00 2010 +0100
    26.3 @@ -2,9 +2,20 @@
    26.4  local initiative = param.get("initiative", "table")
    26.5  local issue = param.get("issue", "table")
    26.6  local trustee = param.get("trustee", "table")
    26.7 +local initiator = param.get("initiator", "table")
    26.8  
    26.9  local options = {
   26.10    {
   26.11 +    name = "newest",
   26.12 +    label = _"Newest",
   26.13 +    order_by = "created DESC, id DESC"
   26.14 +  },
   26.15 +  {
   26.16 +    name = "oldest",
   26.17 +    label = _"Oldest",
   26.18 +    order_by = "created, id"
   26.19 +  },
   26.20 +  {
   26.21      name = "name",
   26.22      label = _"A-Z",
   26.23      order_by = "name"
   26.24 @@ -117,7 +128,13 @@
   26.25                execute.view{
   26.26                  module = "member",
   26.27                  view = "_show_thumb",
   26.28 -                params = { member = member, initiative = initiative, issue = issue, trustee = trustee }
   26.29 +                params = {
   26.30 +                  member = member,
   26.31 +                  initiative = initiative,
   26.32 +                  issue = issue,
   26.33 +                  trustee = trustee,
   26.34 +                  initiator = initiator
   26.35 +                }
   26.36                }
   26.37              end
   26.38  ---]]
    27.1 --- a/app/main/member/_show.lua	Mon Jan 04 12:00:00 2010 +0100
    27.2 +++ b/app/main/member/_show.lua	Sun Jan 10 12:00:00 2010 +0100
    27.3 @@ -151,7 +151,7 @@
    27.4        execute.view{
    27.5          module = "initiative",
    27.6          view = "_list",
    27.7 -        params = { initiatives_selector = member:get_reference_selector("initiated_initiatives") }
    27.8 +        params = { initiatives_selector = member:get_reference_selector("initiated_initiatives"):add_where("initiator.accepted = true") }
    27.9        }
   27.10      end
   27.11    },
    28.1 --- a/app/main/member/_show_thumb.lua	Mon Jan 04 12:00:00 2010 +0100
    28.2 +++ b/app/main/member/_show_thumb.lua	Sun Jan 10 12:00:00 2010 +0100
    28.3 @@ -1,3 +1,4 @@
    28.4 +local initiator = param.get("initiator", "table")
    28.5  local member = param.get("member", "table")
    28.6  
    28.7  local issue = param.get("issue", "table")
    28.8 @@ -11,8 +12,13 @@
    28.9    name = encode.html(member.name)
   28.10  end
   28.11  
   28.12 +local container_class = "member_thumb"
   28.13 +if initiator and member.accepted ~= true then
   28.14 +  container_class = container_class .. " not_accepted"
   28.15 +end
   28.16 +
   28.17  ui.container{
   28.18 -  attr = { class = "member_thumb" },
   28.19 +  attr = { class = container_class },
   28.20    content = function()
   28.21      ui.container{
   28.22        attr = { class = "flags" },
   28.23 @@ -49,6 +55,13 @@
   28.24          else
   28.25            slot.put("&nbsp;")
   28.26          end
   28.27 +        if initiator and initiator.accepted then
   28.28 +          if member.accepted == nil then
   28.29 +            slot.put(_"Invited")
   28.30 +          elseif member.accepted == false then
   28.31 +            slot.put(_"Rejected")
   28.32 +          end
   28.33 +        end
   28.34          if member.grade then
   28.35            ui.container{
   28.36              content = function()
    29.1 --- a/app/main/member/_show_thumb.lua.orig	Mon Jan 04 12:00:00 2010 +0100
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,86 +0,0 @@
    29.4 -local member = param.get("member", "table")
    29.5 -
    29.6 -local issue = param.get("issue", "table")
    29.7 -local initiative = param.get("initiative", "table")
    29.8 -local trustee = param.get("trustee", "table")
    29.9 -
   29.10 -local name
   29.11 -if member.name_highlighted then
   29.12 -  name = encode.highlight(member.name_highlighted)
   29.13 -else
   29.14 -  name = encode.html(member.name)
   29.15 -end
   29.16 -
   29.17 -ui.container{
   29.18 -  attr = { class = "member_thumb" },
   29.19 -  content = function()
   29.20 -    ui.container{
   29.21 -      attr = { class = "flags" },
   29.22 -      content = function()
   29.23 -        if (issue or initiative) and member.weight > 1 then
   29.24 -          local module
   29.25 -          if issue then
   29.26 -            module = "interest"
   29.27 -          elseif initiative then
   29.28 -            module = "supporter"
   29.29 -          end
   29.30 -          ui.link{
   29.31 -            attr = { title = _"Number of incoming delegations, follow link to see more details" },
   29.32 -            content = _("+ #{weight}", { weight = member.weight - 1 }),
   29.33 -            module = module,
   29.34 -            view = "show_incoming",
   29.35 -            params = { 
   29.36 -              member_id = member.id, 
   29.37 -              initiative_id = initiative and initiative.id or nil,
   29.38 -              issue_id = issue and issue.id or nil
   29.39 -            }
   29.40 -          }
   29.41 -        end
   29.42 -        -- TODO performance
   29.43 -        local contact = Contact:by_pk(app.session.member.id, member.id)
   29.44 -        if contact then
   29.45 -          ui.image{
   29.46 -            attr = { 
   29.47 -              alt   = _"You have saved this member as contact",
   29.48 -              title = _"You have saved this member as contact"
   29.49 -            },
   29.50 -            static = "icons/16/bullet_disk.png"
   29.51 -          }
   29.52 -        end
   29.53 -      end
   29.54 -    }
   29.55 -
   29.56 -    ui.link{
   29.57 -      attr = { title = _"Show member" },
   29.58 -      module = "member",
   29.59 -      view = "show",
   29.60 -      id = member.id,
   29.61 -      content = function()
   29.62 -        execute.view{
   29.63 -          module = "member_image",
   29.64 -          view = "_show",
   29.65 -          params = {
   29.66 -            member = member,
   29.67 -            image_type = "avatar",
   29.68 -            show_dummy = true
   29.69 -          }
   29.70 -        }
   29.71 -      end
   29.72 -    }
   29.73 -
   29.74 -    ui.link{
   29.75 -      attr = { title = _"Show member" },
   29.76 -      module = "member",
   29.77 -      view = "show",
   29.78 -      id = member.id,
   29.79 -      content = function()
   29.80 -        ui.container{
   29.81 -          attr = { class = "member_name" },
   29.82 -          content = function()
   29.83 -            slot.put(name)
   29.84 -          end
   29.85 -        }
   29.86 -      end
   29.87 -    }
   29.88 -  end
   29.89 -}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/app/main/member/developer_settings.lua	Sun Jan 10 12:00:00 2010 +0100
    30.3 @@ -0,0 +1,36 @@
    30.4 +slot.put_into("title", _"Developer features")
    30.5 +
    30.6 +slot.select("actions", function()
    30.7 +  ui.link{
    30.8 +    content = function()
    30.9 +        ui.image{ static = "icons/16/cancel.png" }
   30.10 +        slot.put(_"Cancel")
   30.11 +    end,
   30.12 +    module = "member",
   30.13 +    view = "settings"
   30.14 +  }
   30.15 +end)
   30.16 +
   30.17 +ui.form{
   30.18 +  attr = { class = "vertical" },
   30.19 +  module = "member",
   30.20 +  action = "update_stylesheet_url",
   30.21 +  routing = {
   30.22 +    ok = {
   30.23 +      mode = "redirect",
   30.24 +      module = "index",
   30.25 +      view = "index"
   30.26 +    }
   30.27 +  },
   30.28 +  content = function()
   30.29 +    local setting_key = "liquidfeedback_frontend_stylesheet_url"
   30.30 +    local setting = Setting:by_pk(app.session.member.id, setting_key)
   30.31 +    local value = setting and setting.value
   30.32 +    ui.field.text{ 
   30.33 +      label = _"Stylesheet URL",
   30.34 +      name = "stylesheet_url",
   30.35 +      value = value
   30.36 +    }
   30.37 +    ui.submit{ value = _"Set URL" }
   30.38 +  end
   30.39 +}
    31.1 --- a/app/main/member/list.lua	Mon Jan 04 12:00:00 2010 +0100
    31.2 +++ b/app/main/member/list.lua	Sun Jan 10 12:00:00 2010 +0100
    31.3 @@ -5,5 +5,5 @@
    31.4  execute.view{
    31.5    module = "member",
    31.6    view = "_list",
    31.7 -  params = { members_selector = Member:new_selector():add_order_by("name") }
    31.8 +  params = { members_selector = Member:new_selector() }
    31.9  }
    32.1 --- a/app/main/member/settings.lua	Mon Jan 04 12:00:00 2010 +0100
    32.2 +++ b/app/main/member/settings.lua	Sun Jan 10 12:00:00 2010 +0100
    32.3 @@ -10,6 +10,20 @@
    32.4      module = "index",
    32.5      view = "index"
    32.6    }
    32.7 +
    32.8 +  local setting_key = "liquidfeedback_frontend_developer_features"
    32.9 +  local setting = Setting:by_pk(app.session.member.id, setting_key)
   32.10 +
   32.11 +  if setting then
   32.12 +    ui.link{
   32.13 +      content = function()
   32.14 +          ui.image{ static = "icons/16/wrench.png" }
   32.15 +          slot.put(_"Developer features")
   32.16 +      end,
   32.17 +      module = "member",
   32.18 +      view = "developer_settings"
   32.19 +    }
   32.20 +  end
   32.21  end)
   32.22  
   32.23  ui.heading{ content = _"Change your name" }
   32.24 @@ -72,4 +86,4 @@
   32.25      ui.field.password{ label = _"Repeat new password", name = "new_password2" }
   32.26      ui.submit{ value = _"Change password" }
   32.27    end
   32.28 -}
   32.29 +}
   32.30 \ No newline at end of file
    33.1 --- a/app/main/supporter/_show_box.lua	Mon Jan 04 12:00:00 2010 +0100
    33.2 +++ b/app/main/supporter/_show_box.lua	Sun Jan 10 12:00:00 2010 +0100
    33.3 @@ -3,103 +3,101 @@
    33.4    local initiative = param.get("initiative", "table")
    33.5    local supporter = Supporter:by_pk(initiative.id, app.session.member.id)
    33.6  
    33.7 -  ui.container{
    33.8 -    attr = { class = "actions" },
    33.9 -    content = function()
   33.10 -      if not initiative.issue.fully_frozen and not initiative.issue.closed then
   33.11 -        if supporter then
   33.12 -          if not supporter:has_critical_opinion() then
   33.13 -            ui.container{
   33.14 -              attr = {
   33.15 -                class = "head head_supporter",
   33.16 -                style = "cursor: pointer;",
   33.17 -                onclick = "document.getElementById('support_content').style.display = 'block';"
   33.18 -              },
   33.19 -              content = function()
   33.20 -                ui.image{
   33.21 -                  static = "icons/16/thumb_up_green.png"
   33.22 -                }
   33.23 -                slot.put(_"Your are supporter")
   33.24 -                ui.image{
   33.25 -                  static = "icons/16/dropdown.png"
   33.26 -                }
   33.27 -              end
   33.28 +  if not initiative.issue.fully_frozen and not initiative.issue.closed then
   33.29 +    if supporter then
   33.30 +      if not supporter:has_critical_opinion() then
   33.31 +        ui.container{
   33.32 +          attr = {
   33.33 +            class = "head head_supporter",
   33.34 +            style = "cursor: pointer;",
   33.35 +            onclick = "document.getElementById('support_content').style.display = 'block';"
   33.36 +          },
   33.37 +          content = function()
   33.38 +            ui.image{
   33.39 +              static = "icons/16/thumb_up_green.png"
   33.40 +            }
   33.41 +            slot.put(_"Your are supporter")
   33.42 +            ui.image{
   33.43 +              static = "icons/16/dropdown.png"
   33.44              }
   33.45 -          else
   33.46 -            ui.container{
   33.47 -              attr = {
   33.48 -                class = "head head_potential_supporter",
   33.49 -                style = "cursor: pointer;",
   33.50 -                onclick = "document.getElementById('support_content').style.display = 'block';"
   33.51 -              },
   33.52 -              content = function()
   33.53 -                ui.image{
   33.54 -                  static = "icons/16/thumb_up.png"
   33.55 -                }
   33.56 -                slot.put(_"Your are potential supporter")
   33.57 -                ui.image{
   33.58 -                  static = "icons/16/dropdown.png"
   33.59 -                }
   33.60 -              end
   33.61 +          end
   33.62 +        }
   33.63 +      else
   33.64 +        ui.container{
   33.65 +          attr = {
   33.66 +            class = "head head_potential_supporter",
   33.67 +            style = "cursor: pointer;",
   33.68 +            onclick = "document.getElementById('support_content').style.display = 'block';"
   33.69 +          },
   33.70 +          content = function()
   33.71 +            ui.image{
   33.72 +              static = "icons/16/thumb_up.png"
   33.73 +            }
   33.74 +            slot.put(_"Your are potential supporter")
   33.75 +            ui.image{
   33.76 +              static = "icons/16/dropdown.png"
   33.77              }
   33.78            end
   33.79 +        }
   33.80 +      end
   33.81 +      ui.container{
   33.82 +        attr = { class = "content", id = "support_content" },
   33.83 +        content = function()
   33.84            ui.container{
   33.85 -            attr = { class = "content", id = "support_content" },
   33.86 +            attr = {
   33.87 +              class = "close",
   33.88 +              style = "cursor: pointer;",
   33.89 +              onclick = "document.getElementById('support_content').style.display = 'none';"
   33.90 +            },
   33.91              content = function()
   33.92 -              ui.container{
   33.93 -                attr = {
   33.94 -                  class = "close",
   33.95 -                  style = "cursor: pointer;",
   33.96 -                  onclick = "document.getElementById('support_content').style.display = 'none';"
   33.97 -                },
   33.98 -                content = function()
   33.99 -                  ui.image{ static = "icons/16/cross.png" }
  33.100 -                end
  33.101 -              }
  33.102 -              if supporter then
  33.103 -                ui.link{
  33.104 -                  content = function()
  33.105 -                    ui.image{ static = "icons/16/thumb_down_red.png" }
  33.106 -                    slot.put(_"Remove my support from this initiative")
  33.107 -                  end,
  33.108 -                  module = "initiative",
  33.109 -                  action = "remove_support",
  33.110 -                  id = initiative.id,
  33.111 -                  routing = {
  33.112 -                    default = {
  33.113 -                      mode = "redirect",
  33.114 -                      module = request.get_module(),
  33.115 -                      view = request.get_view(),
  33.116 -                      id = param.get_id_cgi(),
  33.117 -                      params = param.get_all_cgi()
  33.118 -                    }
  33.119 -                  }
  33.120 -                }
  33.121 -              else
  33.122 -              end
  33.123 +              ui.image{ static = "icons/16/cross.png" }
  33.124              end
  33.125            }
  33.126 -        else
  33.127 -          ui.link{
  33.128 -            content = function()
  33.129 -              ui.image{ static = "icons/16/thumb_up_green.png" }
  33.130 -              slot.put(_"Support this initiative")
  33.131 -            end,
  33.132 -            module = "initiative",
  33.133 -            action = "add_support",
  33.134 -            id = initiative.id,
  33.135 -            routing = {
  33.136 -              default = {
  33.137 -                mode = "redirect",
  33.138 -                module = request.get_module(),
  33.139 -                view = request.get_view(),
  33.140 -                id = param.get_id_cgi(),
  33.141 -                params = param.get_all_cgi()
  33.142 +          if supporter then
  33.143 +            ui.link{
  33.144 +              content = function()
  33.145 +                ui.image{ static = "icons/16/thumb_down_red.png" }
  33.146 +                slot.put(_"Remove my support from this initiative")
  33.147 +              end,
  33.148 +              module = "initiative",
  33.149 +              action = "remove_support",
  33.150 +              id = initiative.id,
  33.151 +              routing = {
  33.152 +                default = {
  33.153 +                  mode = "redirect",
  33.154 +                  module = request.get_module(),
  33.155 +                  view = request.get_view(),
  33.156 +                  id = param.get_id_cgi(),
  33.157 +                  params = param.get_all_cgi()
  33.158 +                }
  33.159                }
  33.160              }
  33.161 +          else
  33.162 +          end
  33.163 +        end
  33.164 +      }
  33.165 +    else
  33.166 +      if not initiative.revoked then
  33.167 +        ui.link{
  33.168 +          content = function()
  33.169 +            ui.image{ static = "icons/16/thumb_up_green.png" }
  33.170 +            slot.put(_"Support this initiative")
  33.171 +          end,
  33.172 +          module = "initiative",
  33.173 +          action = "add_support",
  33.174 +          id = initiative.id,
  33.175 +          routing = {
  33.176 +            default = {
  33.177 +              mode = "redirect",
  33.178 +              module = request.get_module(),
  33.179 +              view = request.get_view(),
  33.180 +              id = param.get_id_cgi(),
  33.181 +              params = param.get_all_cgi()
  33.182 +            }
  33.183            }
  33.184 -        end
  33.185 +        }
  33.186        end
  33.187      end
  33.188 -  }
  33.189 +  end
  33.190 +
  33.191  end)
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/app/main/timeline/index.lua	Sun Jan 10 12:00:00 2010 +0100
    34.3 @@ -0,0 +1,151 @@
    34.4 +
    34.5 +local function format_dow(dow)
    34.6 +  local dows = {
    34.7 +    _"Monday",
    34.8 +    _"Tuesday",
    34.9 +    _"Wednesday",
   34.10 +    _"Thursday",
   34.11 +    _"Friday",
   34.12 +    _"Saturday",
   34.13 +    _"Sunday"
   34.14 +  }
   34.15 +  return dows[dow+1]
   34.16 +end
   34.17 +
   34.18 +slot.put_into("title", _"Global timeline")
   34.19 +
   34.20 +
   34.21 +ui.form{
   34.22 +  attr = { class = "vertical" },
   34.23 +  module = "timeline",
   34.24 +  view = "index",
   34.25 +  method = "get",
   34.26 +  content = function()
   34.27 +    local tmp = db:query("select EXTRACT(DOW FROM date) as dow, date FROM (SELECT (now() - (to_char(days_before, '0') || ' days')::interval)::date as date from (select generate_series(0,7) as days_before) as series) as date; ")
   34.28 +    local today = tmp[1].date
   34.29 +    for i, record in ipairs(tmp) do
   34.30 +      local content
   34.31 +      if i == 1 then
   34.32 +        content = _"Today"
   34.33 +      elseif i == 2 then
   34.34 +        content = _"Yesterday"
   34.35 +      else
   34.36 +        content = format_dow(record.dow)
   34.37 +      end
   34.38 +      ui.link{
   34.39 +        content = content,
   34.40 +        attr = { onclick = "el = document.getElementById('timeline_search_date'); el.value = '" .. tostring(record.date) .. "'; el.form.submit(); return(false);" },
   34.41 +        module = "timeline",
   34.42 +        view = "index",
   34.43 +        params = { date = record.date }
   34.44 +      }
   34.45 +      slot.put(" ")
   34.46 +    end
   34.47 +    ui.field.hidden{
   34.48 +      attr = { id = "timeline_search_date" },
   34.49 +      name = "date",
   34.50 +      value = param.get("date") or today
   34.51 +    }
   34.52 +    ui.field.select{
   34.53 +      attr = { onchange = "this.form.submit();" },
   34.54 +      name = "per_page",
   34.55 +      label = _"Issues per page",
   34.56 +      foreign_records = {
   34.57 +        { id = "10",  name = "10"   },
   34.58 +        { id = "25",  name = "25"   },
   34.59 +        { id = "50",  name = "50"   },
   34.60 +        { id = "100", name = "100"  },
   34.61 +        { id = "250", name = "250"  },
   34.62 +        { id = "all", name = _"All" },
   34.63 +      },
   34.64 +      foreign_id = "id",
   34.65 +      foreign_name = "name",
   34.66 +      value = param.get("per_page")
   34.67 +    }
   34.68 +    local initiatives_per_page = param.get("initiatives_per_page", atom.integer) or 3
   34.69 +
   34.70 +    ui.field.select{
   34.71 +      attr = { onchange = "this.form.submit();" },
   34.72 +      name = "initiatives_per_page",
   34.73 +      label = _"Initiatives per page",
   34.74 +      foreign_records = {
   34.75 +        { id = 1,   name = "1"  },
   34.76 +        { id = 3,   name = "3"  },
   34.77 +        { id = 5,   name = "5"  },
   34.78 +        { id = 10,  name = "10" },
   34.79 +        { id = 25,  name = "25" },
   34.80 +        { id = 50,  name = "50" },
   34.81 +      },
   34.82 +      foreign_id = "id",
   34.83 +      foreign_name = "name",
   34.84 +      value = initiatives_per_page
   34.85 +    }
   34.86 +  end
   34.87 +}
   34.88 +
   34.89 +local date = param.get("date")
   34.90 +if not date then
   34.91 +  date = "today"
   34.92 +end
   34.93 +local issues_selector = db:new_selector()
   34.94 +issues_selector._class = Issue
   34.95 +
   34.96 +issues_selector
   34.97 +  :add_field("*")
   34.98 +  :add_where{ "sort::date = ?", date }
   34.99 +  :add_from{ "($) as issue", {
  34.100 +    Issue:new_selector()
  34.101 +      :add_field("''", "old_state")
  34.102 +      :add_field("'new'", "new_state")
  34.103 +      :add_field("created", "sort")
  34.104 +    :union(Issue:new_selector()
  34.105 +      :add_field("'new'", "old_state")
  34.106 +      :add_field("'accepted'", "new_state")
  34.107 +      :add_field("accepted", "sort")
  34.108 +      :add_where("accepted NOTNULL")
  34.109 +    ):union(Issue:new_selector()
  34.110 +      :add_field("'accepted'", "old_state")
  34.111 +      :add_field("'frozen'", "new_state")
  34.112 +      :add_field("half_frozen", "sort")
  34.113 +      :add_where("half_frozen NOTNULL")
  34.114 +    ):union(Issue:new_selector()
  34.115 +      :add_field("'frozen'", "old_state")
  34.116 +      :add_field("'voting'", "new_state")
  34.117 +      :add_field("fully_frozen", "sort")
  34.118 +      :add_where("fully_frozen NOTNULL")
  34.119 +    ):union(Issue:new_selector()
  34.120 +      :add_field("'new'", "old_state")
  34.121 +      :add_field("'cancelled'", "new_state")
  34.122 +      :add_field("closed", "sort")
  34.123 +      :add_where("closed NOTNULL AND accepted ISNULL")
  34.124 +    ):union(Issue:new_selector()
  34.125 +      :add_field("'accepted'", "old_state")
  34.126 +      :add_field("'cancelled'", "new_state")
  34.127 +      :add_field("closed", "sort")
  34.128 +      :add_where("closed NOTNULL AND half_frozen ISNULL AND accepted NOTNULL")
  34.129 +    ):union(Issue:new_selector()
  34.130 +      :add_field("'frozen'", "old_state")
  34.131 +      :add_field("'cancelled'", "new_state")
  34.132 +      :add_field("closed", "sort")
  34.133 +      :add_where("closed NOTNULL AND fully_frozen ISNULL AND half_frozen NOTNULL")
  34.134 +    ):union(Issue:new_selector()
  34.135 +      :add_field("'voting'", "old_state")
  34.136 +      :add_field("'finished'", "new_state")
  34.137 +      :add_field("closed", "sort")
  34.138 +      :add_where("closed NOTNULL AND fully_frozen NOTNULL AND half_frozen ISNULL")
  34.139 +    )
  34.140 +  }
  34.141 +}
  34.142 +
  34.143 +execute.view{
  34.144 +  module = "issue",
  34.145 +  view = "_list",
  34.146 +  params = {
  34.147 +    issues_selector = issues_selector,
  34.148 +    initiatives_per_page = param.get("initiatives_per_page", atom.number),
  34.149 +    initiatives_no_sort = true,
  34.150 +    no_filter = true,
  34.151 +    no_sort = true,
  34.152 +    per_page = param.get("per_page"),
  34.153 +  }
  34.154 +}
    35.1 --- a/config/default.lua	Mon Jan 04 12:00:00 2010 +0100
    35.2 +++ b/config/default.lua	Sun Jan 10 12:00:00 2010 +0100
    35.3 @@ -1,5 +1,5 @@
    35.4  config.app_name = "LiquidFeedback"
    35.5 -config.app_version = "beta5"
    35.6 +config.app_version = "beta6"
    35.7  
    35.8  config.app_title = config.app_name .. " (" .. request.get_config_name() .. " environment)"
    35.9  
    36.1 --- a/config/development.lua	Mon Jan 04 12:00:00 2010 +0100
    36.2 +++ b/config/development.lua	Sun Jan 10 12:00:00 2010 +0100
    36.3 @@ -9,3 +9,5 @@
    36.4  
    36.5  config.mail_from = "LiquidFeedback"
    36.6  config.mail_reply_to = "liquid-support@localhost"
    36.7 +
    36.8 +config.issue_discussion_url_func = function(issue) return "http://example.com/issue_" .. tostring(issue.id) end
    36.9 \ No newline at end of file
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/locale/help/initiative.add_initiator.de.txt	Sun Jan 10 12:00:00 2010 +0100
    37.3 @@ -0,0 +1,2 @@
    37.4 +=Initiator einladen=
    37.5 +Hier kannst du eine Person aus deiner Kontaktliste zur gleichberechtigten Mitarbeit am Entwurf einladen. Der eingeladene muss die Einladung erst akzeptieren, bevor er als weiterer Initiator gilt (und angezeigt wird). **Vorsicht:** Alle Initiatoren haben die gleichen Rechte und können andere Initiatoren entfernen.
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/locale/help/initiative.remove_initiator.de.txt	Sun Jan 10 12:00:00 2010 +0100
    38.3 @@ -0,0 +1,2 @@
    38.4 +=Initiator entfernen=
    38.5 +Du kannst dich oder einen anderen Initiator entfernen, sofern nach dem Entfernen noch mindestens ein Initiator existiert. Um die Initiative insgesamt aufzugeben, wähle bitte ,,Initiative zurückziehen''.
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/locale/help/initiative.revoke.de.txt	Sun Jan 10 12:00:00 2010 +0100
    39.3 @@ -0,0 +1,2 @@
    39.4 +=Initiative zurückziehen=
    39.5 +Du kannst diese Initiative zurückziehen. Dies kann nicht rückgängig gemacht werden. Natürlich hast du jederzeit die Möglichkeit, eine neue Initiative zu starten. Den Unterstützern kannst du eine alternative Initiative empfehlen.
    40.1 --- a/locale/help/initiative.show.de.txt	Mon Jan 04 12:00:00 2010 +0100
    40.2 +++ b/locale/help/initiative.show.de.txt	Sun Jan 10 12:00:00 2010 +0100
    40.3 @@ -2,9 +2,11 @@
    40.4  Während der Diskussionsphase kannst du diese Initiative unterstützen und gibst damit den Initiatoren eine wichtige Rückmeldung, inwieweit der aktuelle Entwurf auf Zustimmung stößt. Darüber hinaus kannst du durch Anregungen (Änderungsvorschläge) mitteilen, was noch verbessert werden kann bzw. unter welchen Bedingungen du dir eine Unterstützung vorstellen kannst. 
    40.5  
    40.6  Du kannst dich den Anregungen anderer Mitglieder anschließen (und damit das Gewicht dieser Anregungen erhöhen) und eigene (zusätzliche) Anregungen einbringen. Anregungen, die aus deiner Sicht unbedingt eingearbeitet werden müssen, damit du zustimmst, kennzeichnest du mit ,,muss'', wünschenswerte mit ,,soll''. Du kannst Anregungen auch kritisch gegenüber stehen und sie mit ,,soll nicht'' kennzeichnen. Eine Anregung, die bei Umsetzung zum Entzug deiner Zustimmung führen würde, kennzeichnest du mit ,,darf nicht''. 
    40.7 -=überarbeiteter Entwurf, Umsetzungsvermerk=
    40.8 +=überarbeiteter Entwurf, Umsetzungsvermerkn=
    40.9  Anhand der (klassifizierten und quantifizierten) Anregungen entscheiden die Initiatoren, was sie in einem neuen Entwurf besser dargestellen, ergänzen oder ändern. Der geänderte Entwurf wird den Unterstützern zur Bestätigung vorgelegt. Unterstützer können Anregungen als umgesetzt markieren, wenn die Anregung aus ihrer Sicht (hinreichend) umgesetzt wurde. Die einzelnen Unterstützer können diese Frage durchaus unterschiedlich beurteilen.
   40.10 +=weitere Initiatoren einladen, Zurückziehen einer Initiative=
   40.11 +Ein Initiator kann weitere Initiatoren einladen und verleiht ihnen damit gleiche Rechte für die Bearbeitung des Entwurfs. Jeder Initiator einer Initiative kann die Initiative zurückziehen und auf Wunsch den Unterstützern eine andere Initiative als Alternative empfehlen.
   40.12  =wenn du nicht gehört wirst=
   40.13  Wenn die Initiatoren deine Anregungen aus für dich nicht nachvollziehbaren Gründen nicht berücksichtigen, kannst du natürlich jederzeit eine eigene Initiative starten.
   40.14  =wenn du diese Initiative ablehnst=
   40.15 -Wenn du diese Initiative grundsätzlich ablehnst, solltest du auf dieser Seite gar nichts machen, sondern die Initiative(n), der/denen du positiv gegenüber stehst, unterstützen und/oder deine eigene Initiative zu diesem Thema starten.
   40.16 +Wenn du diese Initiative grundsätzlich ablehnst, solltest du auf dieser Seite gar nichts machen, sondern die Initiative(n), der/denen du positiv gegenüber stehst, unterstützen und/oder deine eigene Initiative zu diesem Thema starten. Sofern du nicht ohnehin schon Mitglied des Themenbereichs bist, kannst du durch eine Mitgliedschaft im Themenbereich oder durch Anmeldung von Interesse am Thema die den erforderlichen Unterstützerquorum zugrundeliegende Grundgesamtheit erhöhen. Den gleichen Effekt erreichst du auch, wenn du an ein Mitglied des Themenbereichs oder einen Interessenten am Thema delegierst. **Nur bei Status ,,Neu'':** Falls das Thema, zu dem diese Initiative gehört, noch im Zustand ,,Neu'' ist und du dieses Thema eigentlich gar nicht diskutieren möchtest, solltest du zunächst nur Mitglied des Themenbereichs werden oder Interesse am Thema anmelden und keine Anregungen eingeben, die dich zum (potentiellen) Unterstützer machen würden. Ebenso solltest du noch keine Gegeninitiative starten, die das Thema über die Zulassungshürde heben könnte.
    41.1 --- a/locale/translations.de.lua	Mon Jan 04 12:00:00 2010 +0100
    41.2 +++ b/locale/translations.de.lua	Sun Jan 10 12:00:00 2010 +0100
    41.3 @@ -1,4 +1,4 @@
    41.4 --- #!/usr/bin/env lua
    41.5 +#!/usr/bin/env lua
    41.6  return {
    41.7  ["#{interested_issues_to_vote_count} issue(s) you are interested in"] = "#{interested_issues_to_vote_count} Themen, die Dich interessieren";
    41.8  ["#{issues_to_vote_count} issue(s)"] = "#{issues_to_vote_count} Themen";
    41.9 @@ -11,6 +11,7 @@
   41.10  ["About"] = "About";
   41.11  ["About LiquidFeedback"] = "Über LiquidFeedback";
   41.12  ["Abstention"] = "Enthaltung";
   41.13 +["Accept invitation"] = "Einladung annehmen";
   41.14  ["Accepted at"] = "Angenommen am/um";
   41.15  ["Active?"] = "Aktiv?";
   41.16  ["Add my interest"] = "Mein Interesse anmelden";
   41.17 @@ -24,7 +25,9 @@
   41.18  ["Administrator"] = "Administrator";
   41.19  ["Admission time"] = "Zeit für die Zulassung";
   41.20  ["Admitted"] = "zugelassen";
   41.21 +["All"] = "Alle";
   41.22  ["Any"] = "Alle";
   41.23 +["Are you sure?"] = "Sicher?";
   41.24  ["Area"] = "Themenbereich";
   41.25  ["Area '#{name}'"] = "Themenbereich '#{name}'";
   41.26  ["Area delegation"] = "Area-Delegation";
   41.27 @@ -39,9 +42,11 @@
   41.28  ["Back"] = "Zurück";
   41.29  ["Become a member"] = "Mitglied werden";
   41.30  ["Birthday"] = "Geburtstag";
   41.31 +["Can't remove last initiator"] = "Der letzte Initiator kann nicht entfernt werden";
   41.32  ["Can't send confirmation email"] = "Bestätigungs-E-Mail kann nicht versendet werden.";
   41.33  ["Cancel"] = "Abbrechen";
   41.34  ["Cancel password reset"] = "Kennwort-Rücksetzung abbrechen";
   41.35 +["Cancel refuse of invitation"] = "Ablehnung der Einladung aufheben";
   41.36  ["Cancel registration"] = "Registration abbrechen";
   41.37  ["Cancelled"] = "Abgebrochen";
   41.38  ["Change area delegation"] = "Delegation für Themengebiet ändern";
   41.39 @@ -53,6 +58,8 @@
   41.40  ["Change your login"] = "Deinen Anmeldenamen ändern";
   41.41  ["Change your name"] = "Deinen Namen ändern";
   41.42  ["Change your password"] = "Dein Kennwort ändern";
   41.43 +["Choose initiator"] = "Initiator auswählen";
   41.44 +["Choose member"] = "Mitglied auswählen";
   41.45  ["Click for details"] = "Klicke für Details";
   41.46  ["Close"] = "Schließen";
   41.47  ["Closed"] = "geschlossen";
   41.48 @@ -75,15 +82,19 @@
   41.49  ["Delegations"] = "Delegationen";
   41.50  ["Description"] = "Beschreibung";
   41.51  ["Details"] = "Details";
   41.52 +["Developer features"] = "Entwicklerfunktionen";
   41.53  ["Diff"] = "Differenz";
   41.54  ["Direct member count"] = "Anzahl Direktmitglieder";
   41.55  ["Direct membership"] = "Direkte Mitgliedschaft";
   41.56  ["Discussion"] = "Diskussion";
   41.57  ["Discussion URL"] = "Diskussions-URL";
   41.58 +["Discussion on issue"] = "Diskussion zum Thema";
   41.59  ["Discussion time"] = "Zeit für die Diskussions";
   41.60 +["Discussion with initiators"] = "Diskussion mit den Initiatoren";
   41.61  ["Download"] = "Download";
   41.62  ["Download database export"] = "Datenbankexport herunterladen";
   41.63  ["Draft"] = "Entwurf";
   41.64 +["Draft history"] = "Entwurfshistorie";
   41.65  ["Edit"] = "Bearbeiten";
   41.66  ["Edit draft"] = "Entwurf bearbeiten";
   41.67  ["Edit initiative"] = "Initiative bearbeiten";
   41.68 @@ -101,10 +112,12 @@
   41.69  ["Filter"] = "Filter";
   41.70  ["Finish voting"] = "Stimmabgabe abschließen";
   41.71  ["Finished"] = "Abgeschlossen";
   41.72 +["Friday"] = "Freitag";
   41.73  ["Frozen"] = "Eingefroren";
   41.74  ["Fully frozen at"] = "Ganz eingefroren am/um";
   41.75  ["Global delegation"] = "Globale Delegation";
   41.76  ["Global delegation active"] = "Globale Delegation aktiv";
   41.77 +["Global timeline"] = "Globale Zeitlinie";
   41.78  ["Half frozen at"] = "Halb eingefroren am/um";
   41.79  ["Hello "] = "Hallo ";
   41.80  ["Help for: #{text}"] = "Hilfe zu: #{text}";
   41.81 @@ -119,11 +132,14 @@
   41.82  ["In discussion"] = "In Diskussion";
   41.83  ["Incoming delegations"] = "Eingehende Delegationen";
   41.84  ["Initiated initiatives"] = "Initierte Initiativen";
   41.85 +["Initiative is revoked now"] = "Initiative ist jetzt zurückgezogen";
   41.86  ["Initiative quorum"] = "Quorum Inititive";
   41.87  ["Initiative successfully created"] = "Initiative erfolgreich erzeugt";
   41.88  ["Initiative successfully updated"] = "Initiative erfolgreich aktualisiert";
   41.89  ["Initiative: '#{name}'"] = "Initiative: '#{name}'";
   41.90  ["Initiatives"] = "Initiativen";
   41.91 +["Initiatives per page"] = "Initiativen je Seite";
   41.92 +["Initiatives that invited you to become initiator:"] = "Initiative, die Dich eingeladen haben, Initiator zu werden:";
   41.93  ["Initiator"] = "Initiator";
   41.94  ["Initiators"] = "Initiatoren";
   41.95  ["Interest not existant"] = "Interesse existiert nicht";
   41.96 @@ -133,16 +149,23 @@
   41.97  ["Interested members"] = "Interessierte Mitglieder";
   41.98  ["Internal posts"] = "Interne Ämter";
   41.99  ["Invalid username or password!"] = "Ungültiger Benutzername oder Kennwort";
  41.100 +["Invitation has been refused"] = "Einladung wurde widerrufen";
  41.101 +["Invite an initiator to initiative"] = "Initiator zur Initiative einladen";
  41.102  ["Invite code"] = "Invite-Code";
  41.103 +["Invite initiator"] = "Initiator einladen";
  41.104 +["Invited"] = "Eingeladen";
  41.105 +["Inviting initiator"] = "Initiatoren einladen";
  41.106  ["Issue"] = "Thema";
  41.107 -["Issue ##{id}"] = "Issue ##{id}";
  41.108 +["Issue ##{id}"] = "Thema ##{id}";
  41.109  ["Issue ##{id} (#{policy_name})"] = "Thema ##{id} (#{policy_name})";
  41.110  ["Issue delegation"] = "Issue-Delegation";
  41.111  ["Issue delegation active"] = "Delegation für Thema aktiv";
  41.112  ["Issue policy"] = "Regelwerk für Thema";
  41.113  ["Issue quorum"] = "Quorum Thema";
  41.114  ["Issues"] = "Themen";
  41.115 +["Issues per page"] = "Themen je Seite";
  41.116  ["JavaScript is disabled or not available."] = "JavaScript ist abgeschaltet oder nicht verfügbar.";
  41.117 +["Last author"] = "Letzter Autor";
  41.118  ["Last snapshot:"] = "Letzte Auszählung:";
  41.119  ["Legend:"] = "Legende:";
  41.120  ["License"] = "Lizenz";
  41.121 @@ -158,10 +181,13 @@
  41.122  ["Mark suggestion as not implemented and express satisfaction"] = "Anregung als nicht umgesetzt markieren und Zufriedenheit ausdrücken";
  41.123  ["Max potential support"] = "Max. potentielle Unterstützer";
  41.124  ["Max support"] = "Max. Unterstützer";
  41.125 +["Member"] = "Mitglied";
  41.126  ["Member '#{member}'"] = "Mitglied '#{member}'";
  41.127 +["Member has been removed from initiators"] = "Mitglied wurde von den Initiatoren entfernt";
  41.128  ["Member has been removed from your contacts"] = "Mitglied wurde aus Deinen Kontakten entfernt";
  41.129  ["Member is administrator"] = "Mitglied ist Administrator";
  41.130  ["Member is already saved in your contacts!"] = "Mitglied ist schon in Deinen Kontakten!";
  41.131 +["Member is now invited to be initiator"] = "Mitglied ist jetzt als Initiator eingeladen";
  41.132  ["Member list"] = "Mitgliederliste";
  41.133  ["Member name"] = "Mitglied Name";
  41.134  ["Member name history for '#{name}'"] = "Namenshistorie für '#{name}'";
  41.135 @@ -177,6 +203,7 @@
  41.136  ["Memberships"] = "Mitgliedschaften";
  41.137  ["Missing help text: #{id}.#{lang}.txt"] = "Fehlender Hilfe-Text: #{id}.#{lang}.txt";
  41.138  ["Mobile phone"] = "Mobiltelefon";
  41.139 +["Monday"] = "Montag";
  41.140  ["My opinion"] = "Meine Meinung";
  41.141  ["Name"] = "Name";
  41.142  ["New"] = "Neu";
  41.143 @@ -198,7 +225,6 @@
  41.144  ["Number of incoming delegations, follow link to see more details"] = "Anzahl eingehender Delegationen, Link folgen für mehr Details";
  41.145  ["OK"] = "OK";
  41.146  ["Old draft revision"] = "Alte Revision des Entwurfs";
  41.147 -["Old drafts"] = "Alte Entwürfe";
  41.148  ["Old password"] = "Altes Kennwort";
  41.149  ["Old password is wrong"] = "Das alte Kennwort ist falsch";
  41.150  ["Oldest"] = "Älteste";
  41.151 @@ -220,8 +246,12 @@
  41.152  ["Phone"] = "Telefon";
  41.153  ["Photo"] = "Foto";
  41.154  ["Please choose a login name. This name will not be shown to others and is used only by you to login into the system. The login name is case sensitive."] = "Bitte wähle einen Anmeldenamen. Dieser wird anderen nicht gezeigt und nur von Dir zum Anmelden verwendet. Groß- und Kleinschreibung wird berücksichtigt.";
  41.155 +["Please choose a member"] = "Bitte wähle ein Mitglied";
  41.156  ["Please choose a name, i.e. your real name or your nick name. This name will be shown to others to identify you."] = "Wähle einen Namen, z. B. Deinen Real- oder Nicknamen. Dieser wird anderen angezeigt um Dich zu identifizieren.";
  41.157  ["Please choose a password and enter it twice. The password is case sensitive."] = "Bitte wähle ein Kennwort und gebe es zweimal ein. Groß- und Kleinschreibung wird berücksichtigt.";
  41.158 +["Please choose a policy"] = "Bitte wähle ein Regelwerk";
  41.159 +["Please choose two different versions of the draft to compare"] = "Bitte wähle zwei verschiedene Versionen des Drafts, um sie zu vergleichen.";
  41.160 +["Please choose two versions of the draft to compare"] = "Bitte wähle zwei Versionen des Drafts, um sie zu vergleichen.";
  41.161  ["Please confirm your email address by clicking the following link:\n\n"] = "Bitte bestätige Deine E-Mail-Adresse, indem Du den folgenden Link anklickst:\n\n";
  41.162  ["Please enter the email reset code you have received:"] = "Bitte gib den Rücksetzcode ein, den Du erhalten hast:";
  41.163  ["Please enter the invite code you've received."] = "Bitte gib den Invite-Code ein, den Du erhalten hast.";
  41.164 @@ -241,12 +271,16 @@
  41.165  ["Rank"] = "Rang";
  41.166  ["Real name"] = "Realname";
  41.167  ["Refresh support to current draft"] = "Unterstützung auf aktuellen Entwurf aktualisieren";
  41.168 +["Refuse invitation"] = "Einladung ablehnen";
  41.169  ["Register"] = "Registrieren";
  41.170  ["Register new member"] = "Neues Mitglied registrieren";
  41.171  ["Registration"] = "Registrierung";
  41.172 +["Rejected"] = "Abgelehnt";
  41.173  ["Remove"] = "Entfernen";
  41.174  ["Remove autoreject"] = "Auto-Ablehnen abschalten";
  41.175  ["Remove from contacts"] = "Aus den Kontakten entfernen";
  41.176 +["Remove initiator"] = "Initiator entfernen";
  41.177 +["Remove initiator from initiative"] = "Initiator von der Initiative entfernen";
  41.178  ["Remove my interest"] = "Interesse abmelden";
  41.179  ["Remove my membership"] = "Mitgliedschaft aufgeben";
  41.180  ["Remove my support from this initiative"] = "Meine Unterstützung der Initiative entziehen";
  41.181 @@ -257,7 +291,9 @@
  41.182  ["Reset link has been send for this member"] = "Rücksetz-Link wurde versendet";
  41.183  ["Reset password"] = "Kennwort zurücksetzen";
  41.184  ["Revoke"] = "Widerrufen";
  41.185 +["Revoke initiative"] = "Initiative zurückziehen";
  41.186  ["Revoked at"] = "Zurückgezogen am/um";
  41.187 +["Saturday"] = "Samstag";
  41.188  ["Save"] = "Speichern";
  41.189  ["Saved as contact"] = "Als Kontakt speichern";
  41.190  ["Search"] = "Suchen";
  41.191 @@ -265,6 +301,7 @@
  41.192  ["Search issues"] = "Suche Themen";
  41.193  ["Search members"] = "Suche Mitglieder";
  41.194  ["Search results for: '#{search}'"] = "Suchergebnisse für: '#{search}'";
  41.195 +["Set URL"] = "URL setzen";
  41.196  ["Set area delegation"] = "Delegation für Themengebiet festlegen";
  41.197  ["Set autoreject"] = "Auto-Ablehnen anschalten";
  41.198  ["Set delegation for Area '#{name}'"] = "Delegation für Themengebiet '#{name}' festlegen";
  41.199 @@ -285,6 +322,7 @@
  41.200  ["Software"] = "Software";
  41.201  ["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.";
  41.202  ["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.";
  41.203 +["Sorry, but you are currently not invited"] = "Sorry, aber Du bist zur Zeit nicht eingeladen";
  41.204  ["Sorry, you have reached your personal flood limit. Please be slower..."] = "Sorry, Du hast Dein persönliches Flood-Limit erreicht. Bitte sei langsamer...";
  41.205  ["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!";
  41.206  ["State"] = "Zustand";
  41.207 @@ -294,11 +332,16 @@
  41.208  ["Step 3/5: Username"] = "Schritt 3/5: Benutzername";
  41.209  ["Step 4/5: Login name"] = "Schritt 4/5: Anmeldename";
  41.210  ["Step 5/5: Terms of use and password"] = "Schritt 5/5: Nutzungsbedingungen und Kennwort";
  41.211 +["Stylesheet URL"] = "Stylesheet URL";
  41.212 +["Stylesheet URL has been updated"] = "Stylesheet URL wurde aktualisiert";
  41.213 +["Suggest no initiative"] = "Keine Initiative empfehlen";
  41.214 +["Suggested initiative"] = "Empfohlene Initiative";
  41.215  ["Suggestion"] = "Anregung";
  41.216  ["Suggestion currently implemented"] = "Anregung zur Zeit umgesetzt";
  41.217  ["Suggestion currently not implemented"] = "Anregung zur Zeit nicht umgesetzt";
  41.218  ["Suggestion for initiative: '#{name}'"] = "Anregung für Initiative '#{name}'";
  41.219  ["Suggestions"] = "Anregungen";
  41.220 +["Sunday"] = "Sonntag";
  41.221  ["Support"] = "Unterstützung";
  41.222  ["Support this initiative"] = "Diese Initiative unterstützen";
  41.223  ["Supported initiatives"] = "Unterstützte Initiativen";
  41.224 @@ -306,21 +349,31 @@
  41.225  ["Terms accepted"] = "Bedingungen akzeptiert";
  41.226  ["The code you've entered is invalid"] = "Der Code, den Du eingeben hast, ist nicht gültig!";
  41.227  ["The drafts do not differ"] = "Die Entwürfe unterscheiden sich nicht";
  41.228 +["The initiators suggest to support the following initiative:"] = "Die Initiatoren empfehlen folgende Initiative zu unterstützen:";
  41.229 +["This initiative has been revoked at #{revoked}"] = "Diese Initiative wurde am/um #{revoked} zurückgezogen";
  41.230 +["This initiative is already revoked"] = "Diese Initiative ist schon zurückgezogen";
  41.231 +["This initiative is revoked"] = "Diese Initiative wurde zurückgezogen";
  41.232  ["This issue is already closed."] = "Das Thema ist schon geschlossen.";
  41.233  ["This issue is already frozen."] = "Das Thema ist schon eingefroren";
  41.234  ["This login is already taken, please choose another one!"] = "Dieser Anmeldename ist bereits vergeben, bitte wähle einen anderen!";
  41.235  ["This login is too short!"] = "Dieser Anmeldename ist zu kurz!";
  41.236  ["This member account has been created at #{created}"] = "Dieser Mitgliedszugang wurde am/um #{created} angelegt.";
  41.237 +["This member has rejected to become initiator of this initiative"] = "Dieses Mitglied hat die Einladung, Initiator zu werden, abgelehnt";
  41.238 +["This member is already initiator of this initiative"] = "Dieses Mitglied ist bereits Initiator dieser Initiative";
  41.239 +["This member is already invited to become initiator of this initiative"] = "Dieses Mitglied ist bereits eingeladen Initiator dieser Initiative zu werden";
  41.240  ["This name is already taken, please choose another one!"] = "Dieser Name ist bereits vergeben, bitte wähle einen anderen!";
  41.241  ["This name is really too short!"] = "Dieser Name ist wirklich zu kurz!";
  41.242  ["This name is too short!"] = "Dieser Name ist zu kurz!";
  41.243  ["This suggestion has been meanwhile deleted"] = "Diese Anregung wurde zwischenzeitlich gelöscht";
  41.244  ["This title is really too short!"] = "Dieser Titel ist wirklich zu kurz!";
  41.245  ["This username is too short!"] = "Dieser Benutzername ist zu kurz!";
  41.246 +["Thursday"] = "Donnerstag";
  41.247  ["Time left"] = "Restzeit";
  41.248  ["Title (80 chars max)"] = "Title (max. 80 Zeichen)";
  41.249 +["Today"] = "Heute";
  41.250  ["Traditional wiki syntax"] = "Traditionaller Wiki-Syntax";
  41.251  ["Trustee"] = "Bevollmächtigter";
  41.252 +["Tuesday"] = "Dienstag";
  41.253  ["Unknown author"] = "Unbekannter Autor";
  41.254  ["Upload images"] = "Bilder hochladen";
  41.255  ["Used until"] = "Benutzt bis";
  41.256 @@ -342,16 +395,23 @@
  41.257  ["Voting requests"] = "Abstimmanträge";
  41.258  ["Voting time"] = "Zeit für die Abstimmung";
  41.259  ["Website"] = "Webseite";
  41.260 +["Wednesday"] = "Mittwoch";
  41.261  ["Wiki engine"] = "Wiki engine";
  41.262  ["Yes"] = "Ja";
  41.263 +["Yesterday"] = "Gestern";
  41.264 +["You are already initator"] = "Du bist bereits Initiator";
  41.265  ["You are already not supporting this initiative"] = "Diese Initiative hat bereits keine Unterstützung von Dir";
  41.266  ["You are already supporting the latest draft"] = "Du unterstützt bereits den neuesten Entwurf";
  41.267  ["You are currently not supporting this initiative. By adding suggestions to this initiative you will automatically become a potential supporter."] = "Du bist zur Zeit kein Unterstützer dieser Initiative. Wenn Du eine Anregung hinzufügst wirst Du automatisch potentieller Unterstützer!";
  41.268 +["You are invited to become initiator of this initiative."] = "Du bist eingeladen Initiator dieser Initiative zu werden.";
  41.269  ["You are member"] = "Du bist Mitglied";
  41.270 +["You are now initiator of this initiative"] = "Du bist jetzt Initiator dieser Initiative";
  41.271 +["You can't suggest the initiative you are revoking"] = "Du kannst nicht die Initiative empfehlen, die Du löschen möchtest";
  41.272  ["You didn't saved any member as contact yet."] = "Du hast noch kein Mitglied als Kontakt gespeichert!";
  41.273  ["You have saved this member as contact"] = "Du hast das Mitglied als Kontakt gespeichert";
  41.274  ["You have saved this member as contact."] = "Du hast das Mitglied als Kontakt gespeichert.";
  41.275  ["You have to accept the terms of use to complete registration."] = "Du musst die Nutzungsbedingungen akzeptieren um die Registration abzuschliessen.";
  41.276 +["You have to mark 'Are you sure' to revoke!"] = "Zum Zurückziehen musst Du 'Sicher?' auswählen";
  41.277  ["You need to be logged in, to use this system."] = "Du musst eingeloggt sein, um das System zu benutzen";
  41.278  ["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!";
  41.279  ["Your are interested"] = "Du bist interessiert";
    42.1 --- a/model/area.lua	Mon Jan 04 12:00:00 2010 +0100
    42.2 +++ b/model/area.lua	Sun Jan 10 12:00:00 2010 +0100
    42.3 @@ -54,7 +54,7 @@
    42.4    return Policy:new_selector()
    42.5      :join("allowed_policy", nil, "allowed_policy.policy_id = policy.id")
    42.6      :add_where{ "allowed_policy.area_id = ? AND allowed_policy.default_policy", self.id }
    42.7 -    :single_object_mode()
    42.8 +    :optional_object_mode()
    42.9      :exec()
   42.10  end
   42.11  
    43.1 --- a/model/initiative.lua	Mon Jan 04 12:00:00 2010 +0100
    43.2 +++ b/model/initiative.lua	Sun Jan 10 12:00:00 2010 +0100
    43.3 @@ -34,8 +34,7 @@
    43.4    this_key      = 'id',
    43.5    that_key      = 'initiative_id',
    43.6    ref           = 'initiators',
    43.7 -  back_ref      = 'initiative',
    43.8 -  default_order = '"id"'
    43.9 +  back_ref      = 'initiative'
   43.10  }
   43.11  
   43.12  Initiative:add_reference{
   43.13 @@ -69,6 +68,14 @@
   43.14  }
   43.15  
   43.16  Initiative:add_reference{
   43.17 +  mode          = 'm1',
   43.18 +  to            = "Initiative",
   43.19 +  this_key      = 'suggested_initiative_id',
   43.20 +  that_key      = 'id',
   43.21 +  ref           = 'suggested_initiative',
   43.22 +}
   43.23 +
   43.24 +Initiative:add_reference{
   43.25    mode                  = 'mm',
   43.26    to                    = "Member",
   43.27    this_key              = 'id',
    44.1 --- a/model/issue.lua	Mon Jan 04 12:00:00 2010 +0100
    44.2 +++ b/model/issue.lua	Sun Jan 10 12:00:00 2010 +0100
    44.3 @@ -119,7 +119,7 @@
    44.4      finished     = _"Finished",
    44.5      cancelled    = _"Cancelled"
    44.6    }
    44.7 -  return state_name_table[value] or value
    44.8 +  return state_name_table[value] or value or ''
    44.9  end
   44.10  
   44.11  function Issue:get_search_selector(search_string)
    45.1 --- a/model/member.lua	Mon Jan 04 12:00:00 2010 +0100
    45.2 +++ b/model/member.lua	Sun Jan 10 12:00:00 2010 +0100
    45.3 @@ -95,8 +95,7 @@
    45.4    this_key      = 'id',
    45.5    that_key      = 'member_id',
    45.6    ref           = 'initiators',
    45.7 -  back_ref      = 'member',
    45.8 -  default_order = '"id"'
    45.9 +  back_ref      = 'member'
   45.10  }
   45.11  
   45.12  Member:add_reference{
    46.1 Binary file static/icons/16/script_delete.png has changed
    47.1 Binary file static/icons/16/user_delete.png has changed
    48.1 --- a/static/style.css	Mon Jan 04 12:00:00 2010 +0100
    48.2 +++ b/static/style.css	Sun Jan 10 12:00:00 2010 +0100
    48.3 @@ -40,6 +40,10 @@
    48.4    color: #fff; 
    48.5  }
    48.6  
    48.7 +.revoked {
    48.8 +  text-decoration: line-through;
    48.9 +}
   48.10 +
   48.11  .highlighted {
   48.12    background-color: #fa7;
   48.13    color: #000;
   48.14 @@ -62,7 +66,6 @@
   48.15  }
   48.16  
   48.17  
   48.18 -
   48.19  /*************************************************************************
   48.20   * Notices, warnings and errors
   48.21   */
   48.22 @@ -274,7 +277,7 @@
   48.23  }
   48.24  
   48.25  .interest .head_active,
   48.26 -.slot_support .head_potential_supporter {
   48.27 +.slot_support .head_potential_supporter{
   48.28    background-color: #fec;
   48.29    border: 1px solid #b96;
   48.30  }
   48.31 @@ -284,6 +287,11 @@
   48.32    border: 1px solid #8b8;
   48.33  }
   48.34  
   48.35 +.slot_support .head_initiator {
   48.36 +  background-color: #eee;
   48.37 +  border: 1px solid #999;
   48.38 +}
   48.39 +
   48.40  .delegation .head_active {
   48.41    background-color: #ddf;
   48.42    border: 1px solid #88b;
   48.43 @@ -759,6 +767,10 @@
   48.44    float: right;
   48.45  }
   48.46  
   48.47 +.member_thumb.not_accepted {
   48.48 +  opacity: 0.5;
   48.49 +}
   48.50 +
   48.51  .draft_content,
   48.52  .member_statement {
   48.53    background-color: #eee;
   48.54 @@ -803,7 +815,9 @@
   48.55  }
   48.56  
   48.57  .draft_updated_info,
   48.58 -.voting_active_info {
   48.59 +.voting_active_info,
   48.60 +.revoked_info,
   48.61 +.initiator_invite_info {
   48.62    background-color: #fec;
   48.63    border: 2px solid #b96;
   48.64    padding: 1ex;

Impressum / About Us