liquid_feedback_frontend

changeset 19:00d1004545f1

Dynamic interface using XMLHttpRequests, and many other changes

Bugfixes:
- Only allow voting on admitted initiatives
- Repaired issue search
- Don't display delegations for closed issues on member page
- Don't show revoke link in initiative, when issue is already half_frozen
- Localization for voting JavaScript
- Display author of suggestions

Disclosure of voting data after voting is finished:
- Possibility to inspect every ballot including preferences
- Show number of voters preferring one initiative to another initiative

Interface behaviour changes:
- Reversed default order of drafts
- Default order of suggestions changed
- Show new drafts of initiatives only once per day in timeline

Accessibility:
- Barrier-free voting implemented
- POST links are now accessible without JavaScript
- Changed gray for unsatisfied supporters in bar graph to a lighter gray

Other interface improvements:
- Optical enhancements
- Dynamic interface using XMLHttpRequests
- Show usage terms in about section
- Show own membership in area listing
- Show uninformed supporters greyed out and marked with yellow question mark
- Warning box in non-admitted initiatives
- When voted, don't display voting notice and change label of voting link
- Show object counts in more tabulator heads
- Enlarged member statement input field

Miscellaneous:
- Code cleanup
- Added README file containing installation instructions
- Use new WebMCP function ui.filters{...} instead of own ui.filter and ui.order functions
author bsw/jbe
date Sat Feb 20 22:10:31 2010 +0100 (2010-02-20)
parents fc9e748660c8
children 0a23f39b3e21
files Makefile README app/main/_filter_view/30_navigation.lua app/main/_filter_view/31_logout_button.lua app/main/_filter_view/33_help_hidden.lua app/main/_filter_view/34_stylesheet.lua app/main/_layout/atom.html app/main/_layout/blank.html app/main/_layout/default.html app/main/_layout/system_error.html app/main/area/_list.lua app/main/area/show.lua app/main/area/show_tab.lua app/main/delegation/_show_box.lua app/main/draft/_show.lua app/main/index/about.lua app/main/index/index.lua app/main/index/login.lua app/main/index/search.lua app/main/index/usage_terms.lua app/main/initiative/_current_draft.lua app/main/initiative/_details.lua app/main/initiative/_initiators.lua app/main/initiative/_list.lua app/main/initiative/_list_element.lua app/main/initiative/_show.lua app/main/initiative/_show_voting.lua app/main/initiative/_suggestions.lua app/main/initiative/list_rss.lua app/main/initiative/new.lua app/main/initiative/show.lua app/main/initiative/show_partial.lua app/main/initiative/show_static.lua app/main/initiative/show_support.lua app/main/initiative/show_tab.lua app/main/interest/_show_box.lua app/main/issue/_details.lua app/main/issue/_list.lua app/main/issue/_list_initiatives.lua app/main/issue/_show_box.lua app/main/issue/_show_head.lua app/main/issue/_show_vote_later_box.lua app/main/issue/show.lua app/main/issue/show_tab.lua app/main/member/_action/update_display.lua app/main/member/_list.lua app/main/member/_profile.lua app/main/member/_show.lua app/main/member/_show_thumb.lua app/main/member/edit.lua app/main/member/settings.lua app/main/member/show.lua app/main/member/show_tab.lua app/main/membership/_show_box.lua app/main/suggestion/_list.lua app/main/suggestion/_opinions.lua app/main/suggestion/_suggestion.lua app/main/suggestion/new.lua app/main/suggestion/show.lua app/main/suggestion/show_tab.lua app/main/supporter/_show_box.lua app/main/timeline/_action/update.lua app/main/timeline/_filter/29_filter.lua app/main/timeline/_list.lua app/main/timeline/index.lua app/main/timeline/list_filter.lua app/main/vote/_action/update.lua app/main/vote/list.lua config/default.lua env/ui/bargraph.lua env/ui/field/rank.lua env/ui/filter.lua env/ui/is_for_partial_load.lua env/ui/order.lua env/ui/partial_load.lua env/ui/partial_set_param_names.lua env/ui/set_for_partial_load.lua env/ui/tabs.lua env/util/help.lua locale/help/member.settings.display.de.txt locale/translations.de.lua locale/translations.en.lua locale/translations.eo.lua model/initiative.lua model/issue.lua model/member.lua static/icons/16/bullet_blue.png static/icons/16/bullet_toggle_minus.png static/icons/16/bullet_toggle_plus.png static/icons/16/connect.png static/icons/16/help_yellow.png static/icons/16/lock.png static/icons/16/resultset_next.png static/icons/move_down.png static/icons/move_up.png static/js/partialload.js static/js/voting.js static/style.css
line diff
     1.1 --- a/Makefile	Tue Feb 02 00:31:06 2010 +0100
     1.2 +++ b/Makefile	Sat Feb 20 22:10:31 2010 +0100
     1.3 @@ -1,14 +1,6 @@
     1.4  default:
     1.5  
     1.6  
     1.7 -db:
     1.8 -	create_db liquid_feedback
     1.9 -	psql liquid_feedback -f db/core.sql
    1.10 -
    1.11 -demo-db: db
    1.12 -	psql liquid_feedback -f db/demo.sql
    1.13 -
    1.14 -
    1.15  translations-de:
    1.16  	cd ../webmcp/framework/bin/ && ./langtool.lua ~/workspace/liquid_feedback/locale/translations.de.lua ~/workspace/liquid_feedback/app ~/workspace/liquid_feedback/locale/translations.de.lua
    1.17  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/README	Sat Feb 20 22:10:31 2010 +0100
     2.3 @@ -0,0 +1,61 @@
     2.4 +
     2.5 +################
     2.6 +# Installation #
     2.7 +################
     2.8 +
     2.9 +
    2.10 +1. Choose a directory where to install the software, e.g. /opt :
    2.11 +
    2.12 +$ cd /opt
    2.13 +
    2.14 +
    2.15 +2. Get the repositories of the core, the frondend and the web application
    2.16 +   framework WebMCP:
    2.17 +
    2.18 +$ hg clone http://www.public-software-group.org/mercurial/liquid_feedback_core
    2.19 +$ hg clone http://www.public-software-group.org/mercurial/liquid_feedback_frontend
    2.20 +$ hg clone http://www.public-software-group.org/mercurial/webmcp
    2.21 +
    2.22 +
    2.23 +3. Install LiquidFeedback Core:
    2.24 +
    2.25 +$ cd /opt/liquid_feedback_core
    2.26 +$ make
    2.27 +$ createdb liquid_feedback
    2.28 +$ psql -v ON_ERROR_STOP=1 -f core.sql liquid_feedback
    2.29 +
    2.30 +You should initiatize your database using the command
    2.31 +"psql liquid_feedback" and the examples shown in file "init.sql".
    2.32 +
    2.33 +
    2.34 +4. Compile WebMCP
    2.35 +
    2.36 +$ cd /opt/webmcp
    2.37 +$ make
    2.38 +
    2.39 +If you experience trouble during compilation, you might want to edit the
    2.40 +file "Makefile.options" (i.e. to add -fPIC to compiler options) and then
    2.41 +retry:
    2.42 +
    2.43 +$ vi Makefile.options
    2.44 +$ make clean
    2.45 +$ make
    2.46 +
    2.47 +
    2.48 +5. Install Wiki-to-HTML converters
    2.49 +
    2.50 +Download latest LiquidFeedback Edition of RocketWiki from
    2.51 +http://www.public-software-group.org/pub/projects/rocketwiki/liquid_feedback_edition/
    2.52 +
    2.53 +Compile the binaries by calling make, and copy them to a place of your
    2.54 +choice, e.g. /opt/rocketwiki-lqfb/
    2.55 +
    2.56 +
    2.57 +6. Configure the webserver and the LiquidFeedback Frontend application:
    2.58 +
    2.59 +Edit the configuration files in /opt/liquid_feedback_frontend/config/
    2.60 +
    2.61 +Use /opt/webmcp/doc/lighttpd.example.conf (or apache.sample.conf) to setup
    2.62 +your webserver appropriatly.
    2.63 +
    2.64 +
     3.1 --- a/app/main/_filter_view/30_navigation.lua	Tue Feb 02 00:31:06 2010 +0100
     3.2 +++ b/app/main/_filter_view/30_navigation.lua	Sat Feb 20 22:10:31 2010 +0100
     3.3 @@ -4,36 +4,28 @@
     3.4  if app.session.member == nil then
     3.5    slot.select('navigation', function()
     3.6      ui.link{
     3.7 -      content = function()
     3.8 -        ui.image{ static = "icons/16/key.png" }
     3.9 -        slot.put(_"Login")
    3.10 -      end,
    3.11 +      image  = { static = "icons/16/key.png" },
    3.12 +      text   = _"Login",
    3.13        module = 'index',
    3.14 -      view = 'login'
    3.15 +      view   = 'login'
    3.16      }
    3.17      ui.link{
    3.18 -      content = function()
    3.19 -        ui.image{ static = "icons/16/book_edit.png" }
    3.20 -        slot.put(_"Registration")
    3.21 -      end,
    3.22 +      image  = { static = "icons/16/book_edit.png" },
    3.23 +      text   = _"Registration",
    3.24        module = 'index',
    3.25 -      view = 'register'
    3.26 +      view   = 'register'
    3.27      }
    3.28      ui.link{
    3.29 -      content = function()
    3.30 -        ui.image{ static = "icons/16/key_forgot.png" }
    3.31 -        slot.put(_"Reset password")
    3.32 -      end,
    3.33 +      image  = { static = "icons/16/key_forgot.png" },
    3.34 +      text   = _"Reset password",
    3.35        module = 'index',
    3.36 -      view = 'reset_password'
    3.37 +      view   = 'reset_password'
    3.38      }
    3.39      ui.link{
    3.40 -      content = function()
    3.41 -        ui.image{ static = "icons/16/information.png" }
    3.42 -        slot.put('About / Impressum')
    3.43 -      end,
    3.44 +      image  = { static = "icons/16/information.png" },
    3.45 +      text   = _"About / Impressum",
    3.46        module = 'index',
    3.47 -      view = 'about'
    3.48 +      view   = 'about'
    3.49      }
    3.50    end)
    3.51    execute.inner()
    3.52 @@ -43,75 +35,46 @@
    3.53  slot.select('navigation', function()
    3.54  
    3.55    ui.link{
    3.56 -    content = function()
    3.57 -      ui.image{ static = "icons/16/house.png" }
    3.58 -      slot.put(_"Home")
    3.59 -    end,
    3.60 +    image  = { static = "icons/16/house.png" },
    3.61 +    text   = _"Home",
    3.62      module = 'index',
    3.63 -    view = 'index'
    3.64 +    view   = 'index'
    3.65    }
    3.66  
    3.67 -  local setting_key = "liquidfeedback_frontend_timeline_current_options"
    3.68 -  local setting = Setting:by_pk(app.session.member.id, setting_key)
    3.69 -
    3.70 -  timeline_params = {}
    3.71 -  if setting then
    3.72 -    for event_ident, filter_idents in setting.value:gmatch("(%S+):(%S+)") do
    3.73 -      timeline_params["option_" .. event_ident] = true
    3.74 -      if filter_idents ~= "*" then
    3.75 -        for filter_ident in filter_idents:gmatch("([^\|]+)") do
    3.76 -          timeline_params["option_" .. event_ident .. "_" .. filter_ident] = true
    3.77 -        end
    3.78 -      end
    3.79 -    end
    3.80 -  end
    3.81 -
    3.82 -  timeline_params.date = param.get("date") or today
    3.83 -
    3.84    ui.link{
    3.85 -    content = function()
    3.86 -      ui.image{ static = "icons/16/time.png" }
    3.87 -      slot.put(_"Timeline")
    3.88 -    end,
    3.89 +    image  = { static = "icons/16/time.png" },
    3.90 +    text   = _"Timeline",
    3.91      module = "timeline",
    3.92 -    action = "update"
    3.93 ---    params = timeline_params
    3.94 +    view   = "index"
    3.95    }
    3.96  
    3.97    ui.link{
    3.98 -    content = function()
    3.99 -      ui.image{ static = "icons/16/package.png" }
   3.100 -      slot.put(_"Areas")
   3.101 -    end,
   3.102 +    image  = { static = "icons/16/package.png" },
   3.103 +    text   = _"Areas",
   3.104      module = 'area',
   3.105 -    view = 'list'
   3.106 +    view   = 'list'
   3.107    }
   3.108  
   3.109    ui.link{
   3.110 -    content = function()
   3.111 -      ui.image{ static = "icons/16/group.png" }
   3.112 -      slot.put(_"Members")
   3.113 -    end,
   3.114 +    image  = { static = "icons/16/group.png" },
   3.115 +    text   = _"Members",
   3.116      module = 'member',
   3.117 -    view = 'list'
   3.118 +    view   = 'list',
   3.119 +    params = { member_list = "newest" }
   3.120    }
   3.121  
   3.122    ui.link{
   3.123 -    content = function()
   3.124 -      ui.image{ static = "icons/16/book_edit.png" }
   3.125 -      slot.put(_"Contacts")
   3.126 -    end,
   3.127 +    image  = { static = "icons/16/book_edit.png" },
   3.128 +    text   = _"Contacts",
   3.129      module = 'contact',
   3.130 -    view = 'list'
   3.131 +    view   = 'list'
   3.132    }
   3.133  
   3.134    ui.link{
   3.135 -    content = function()
   3.136 -      ui.image{ static = "icons/16/information.png" }
   3.137 -      slot.put(_"About")
   3.138 -    end,
   3.139 +    image  = { static = "icons/16/information.png" },
   3.140 +    text   = _"About",
   3.141      module = 'index',
   3.142 -    view = 'about'
   3.143 +    view   = 'about'
   3.144    }
   3.145  
   3.146    if app.session.member.admin then
   3.147 @@ -119,13 +82,11 @@
   3.148      slot.put(" ")
   3.149  
   3.150      ui.link{
   3.151 -      attr = { class = { "admin_only" } },
   3.152 -      content = function()
   3.153 -        ui.image{ static = "icons/16/cog.png" }
   3.154 -        slot.put(_'Admin')
   3.155 -      end,
   3.156 +      attr   = { class = { "admin_only" } },
   3.157 +      image  = { static = "icons/16/cog.png" },
   3.158 +      text   = _"Admin",
   3.159        module = 'admin',
   3.160 -      view = 'index'
   3.161 +      view   = 'index'
   3.162      }
   3.163  
   3.164    end
   3.165 @@ -139,5 +100,3 @@
   3.166  end
   3.167  
   3.168  execute.inner()
   3.169 -
   3.170 -
     4.1 --- a/app/main/_filter_view/31_logout_button.lua	Tue Feb 02 00:31:06 2010 +0100
     4.2 +++ b/app/main/_filter_view/31_logout_button.lua	Sat Feb 20 22:10:31 2010 +0100
     4.3 @@ -5,10 +5,8 @@
     4.4  
     4.5  slot.select('logout_button', function()
     4.6    ui.link{
     4.7 -    content = function()
     4.8 -      ui.image{ static = "icons/16/stop.png" }
     4.9 -      slot.put(_'Logout')
    4.10 -    end,
    4.11 +    image  = { static = "icons/16/stop.png" },
    4.12 +    text   = _"Logout",
    4.13      module = 'index',
    4.14      action = 'logout'
    4.15    }
     5.1 --- a/app/main/_filter_view/33_help_hidden.lua	Tue Feb 02 00:31:06 2010 +0100
     5.2 +++ b/app/main/_filter_view/33_help_hidden.lua	Sat Feb 20 22:10:31 2010 +0100
     5.3 @@ -28,9 +28,9 @@
     5.4              attr = { class = "help_icon" },
     5.5              static = "icons/16/help.png"
     5.6            }
     5.7 -        end
     5.8 +        end,
     5.9 +        text = _"Show help text"
    5.10        }
    5.11      end
    5.12    end)
    5.13  end
    5.14 -
     6.1 --- a/app/main/_filter_view/34_stylesheet.lua	Tue Feb 02 00:31:06 2010 +0100
     6.2 +++ b/app/main/_filter_view/34_stylesheet.lua	Sat Feb 20 22:10:31 2010 +0100
     6.3 @@ -11,4 +11,40 @@
     6.4    slot.put_into("stylesheet_url", config.absolute_base_url .. "static/style.css")
     6.5  end
     6.6  
     6.7 -execute.inner()
     6.8 \ No newline at end of file
     6.9 +if os.getenv("HTTP_USER_AGENT"):find("Android.*AppleWebKit.*Mobile Safari") then
    6.10 +  slot.select("html_head", function()
    6.11 +    ui.tag{
    6.12 +      tag = "style",
    6.13 +      content = "body, td, th { font-size: 16px; };"
    6.14 +    }
    6.15 +  end)
    6.16 +end
    6.17 +
    6.18 +if app.session.member then
    6.19 +  local tab_mode = app.session.member:get_setting_value("tab_mode")
    6.20 +  if tab_mode then
    6.21 +    config.user_tab_mode = tab_mode
    6.22 +  end
    6.23 +end
    6.24 +
    6.25 +local web20 = config.user_tab_mode == "accordeon"
    6.26 +  or config.user_tab_mode == "accordeon_first_expanded"
    6.27 +  or config.user_tab_mode == "accordeon_all_expanded"
    6.28 +
    6.29 +if web20 then
    6.30 +  ui.enable_partial_loading()
    6.31 +end
    6.32 +
    6.33 +if request.get_json_request_slots() then
    6.34 +  slot.set_layout("blank")
    6.35 +end
    6.36 +
    6.37 +
    6.38 +ui.container{
    6.39 +  attr = {
    6.40 +    class = web20 and "web20" or "web10"
    6.41 +  },
    6.42 +  content = function()
    6.43 +    execute.inner()
    6.44 +  end
    6.45 +}
    6.46 \ No newline at end of file
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/app/main/_layout/atom.html	Sat Feb 20 22:10:31 2010 +0100
     7.3 @@ -0,0 +1,12 @@
     7.4 +<?xml version="1.0" encoding="utf-8"?>
     7.5 +
     7.6 +<feed xmlns="http://www.w3.org/2005/Atom">
     7.7 +  <author>
     7.8 +    <name>foo</name>
     7.9 +  </author>
    7.10 +  <title>LiquidFeedback</title>
    7.11 +  <subtitle>Initiatives</subtitle>
    7.12 +  <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
    7.13 +  <updated>2003-12-14T10:20:09Z</updated>
    7.14 +  <!-- WEBMCP SLOTNODIV default -->
    7.15 +</feed>
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/app/main/_layout/blank.html	Sat Feb 20 22:10:31 2010 +0100
     8.3 @@ -0,0 +1,1 @@
     8.4 +<!-- WEBMCP SLOTNODIV default -->
     8.5 \ No newline at end of file
     9.1 --- a/app/main/_layout/default.html	Tue Feb 02 00:31:06 2010 +0100
     9.2 +++ b/app/main/_layout/default.html	Sat Feb 20 22:10:31 2010 +0100
     9.3 @@ -6,6 +6,8 @@
     9.4      <link rel="stylesheet" type="text/css" media="screen" href="__BASEURL__/static/gregor.js/gregor.css" />
     9.5      <link rel="stylesheet" type="text/css" media="screen" href="<!-- WEBMCP SLOTNODIV stylesheet_url -->" />
     9.6      <!-- WEBMCP SLOTNODIV html_head -->
     9.7 +    <script type="text/javascript" src="__BASEURL__/static/js/partialload.js"></script>
     9.8 +    <script type="text/javascript">var ui_tabs_active = {};</script>
     9.9    </head>
    9.10    <body>
    9.11      <div class="topbar">
    9.12 @@ -67,7 +69,9 @@
    9.13      <div class="layout_trace" id="layout_trace" style="xdisplay: none">
    9.14        <div id="trace_show" onclick="document.getElementById('trace_content').style.display='block';this.style.display='none';">TRACE</div>
    9.15          <div id="trace_content" style="display: none;">
    9.16 -          <!-- WEBMCP SLOT trace -->
    9.17 +            <tt id="system_error"><!-- WEBMCP SLOT system_error --></tt>
    9.18 +            <div id="trace">&nbsp;</div><hr />
    9.19 +            <!-- WEBMCP SLOT trace -->
    9.20            <div class="trace_close" onclick="document.getElementById('trace_show').style.display='block';document.getElementById('trace_content').style.display='none';">
    9.21              close
    9.22            </div>
    10.1 --- a/app/main/_layout/system_error.html	Tue Feb 02 00:31:06 2010 +0100
    10.2 +++ b/app/main/_layout/system_error.html	Sat Feb 20 22:10:31 2010 +0100
    10.3 @@ -1,7 +1,7 @@
    10.4  <html>
    10.5    <head>
    10.6      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    10.7 -    <title>Liquid Democracy System Error</title>
    10.8 +    <title>LiquidFeedback Error</title>
    10.9      <link rel="stylesheet" type="text/css" media="screen" href="__BASEURL__/static/trace.css" />
   10.10      <style>
   10.11        body {
    11.1 --- a/app/main/area/_list.lua	Tue Feb 02 00:31:06 2010 +0100
    11.2 +++ b/app/main/area/_list.lua	Sat Feb 20 22:10:31 2010 +0100
    11.3 @@ -13,38 +13,56 @@
    11.4    :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")
    11.5    :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.fully_frozen NOTNULL AND issue.closed NOTNULL)", "issues_finished_count")
    11.6    :add_field("(SELECT COUNT(*) FROM issue WHERE issue.area_id = area.id AND issue.fully_frozen ISNULL AND issue.closed NOTNULL)", "issues_cancelled_count")
    11.7 +  :left_join("membership", "_membership", { "_membership.area_id = area.id AND _membership.member_id = ?", app.session.member.id })
    11.8 +  :add_field("_membership.member_id NOTNULL", "is_member", { "grouped" })
    11.9  
   11.10 -ui.order{
   11.11 -  name = name,
   11.12 +local label_attr = { style = "text-align: right; width: 4em;" }
   11.13 +local field_attr = { style = "text-align: right; width: 4em;" }
   11.14 +
   11.15 +ui.filters{
   11.16 +  label = _"Change order",
   11.17    selector = areas_selector,
   11.18 -  options = {
   11.19 +  {
   11.20 +    label = _"Order by",
   11.21      {
   11.22        name = "member_weight",
   11.23        label = _"Population",
   11.24 -      order_by = "area.member_weight DESC"
   11.25 +      selector_modifier = function(selector) selector:add_order_by("area.member_weight DESC") end
   11.26      },
   11.27      {
   11.28        name = "direct_member_count",
   11.29        label = _"Direct member count",
   11.30 -      order_by = "area.direct_member_count DESC"
   11.31 +      selector_modifier = function(selector) selector:add_order_by("area.direct_member_count DESC") end
   11.32      },
   11.33      {
   11.34        name = "az",
   11.35        label = _"A-Z",
   11.36 -      order_by = "area.name"
   11.37 +      selector_modifier = function(selector) selector:add_order_by("area.name") end
   11.38      },
   11.39      {
   11.40        name = "za",
   11.41        label = _"Z-A",
   11.42 -      order_by = "area.name DESC"
   11.43 +      selector_modifier = function(selector) selector:add_order_by("area.name DESC") end
   11.44      }
   11.45    },
   11.46    content = function()
   11.47      ui.list{
   11.48 +      attr = { class = "area_list" },
   11.49        records = areas_selector:exec(),
   11.50        columns = {
   11.51          {
   11.52            content = function(record)
   11.53 +            if record.is_member then
   11.54 +              local text = _"Member of area"
   11.55 +              ui.image{
   11.56 +                attr = { title = text, alt = text, style = "vertical-align: middle;" },
   11.57 +                static = "icons/16/user_gray.png",
   11.58 +              }
   11.59 +            end
   11.60 +          end
   11.61 +        },
   11.62 +        {
   11.63 +          content = function(record)
   11.64              if record.member_weight and record.direct_member_count then
   11.65                local max_value = MemberCount:get()
   11.66                ui.bargraph{
   11.67 @@ -70,97 +88,143 @@
   11.68            end
   11.69          },
   11.70          {
   11.71 -          label = _"New",
   11.72 -          field_attr = { style = "text-align: right;" },
   11.73 +          label = function()
   11.74 +            local title = _"New"
   11.75 +            ui.image{
   11.76 +              attr = { title = title, alt = title },
   11.77 +              static = "icons/16/new.png"
   11.78 +            }
   11.79 +          end,
   11.80 +          field_attr = field_attr,
   11.81 +          label_attr = label_attr,
   11.82            content = function(record)
   11.83              ui.link{
   11.84                text = tostring(record.issues_new_count),
   11.85                module = "area",
   11.86                view = "show",
   11.87                id = record.id,
   11.88 -              params = { filter = "new" }
   11.89 +              params = { filter = "new", tab = "issues" }
   11.90              }
   11.91            end
   11.92          },
   11.93          {
   11.94 -          label = _"Discussion",
   11.95 -          field_attr = { style = "text-align: right;" },
   11.96 +          label = function()
   11.97 +            local title = _"Discussion"
   11.98 +            ui.image{
   11.99 +              attr = { title = title, alt = title },
  11.100 +              static = "icons/16/comments.png"
  11.101 +            }
  11.102 +          end,
  11.103 +          field_attr = field_attr,
  11.104 +          label_attr = label_attr,
  11.105            content = function(record)
  11.106              ui.link{
  11.107                text = tostring(record.issues_discussion_count),
  11.108                module = "area",
  11.109                view = "show",
  11.110                id = record.id,
  11.111 -              params = { filter = "accepted" }
  11.112 +              params = { filter = "accepted", tab = "issues" }
  11.113              }
  11.114            end
  11.115          },
  11.116          {
  11.117 -          label = _"Frozen",
  11.118 -          field_attr = { style = "text-align: right;" },
  11.119 +          label = function()
  11.120 +            local title = _"Frozen"
  11.121 +            ui.image{
  11.122 +              attr = { title = title, alt = title },
  11.123 +              static = "icons/16/lock.png"
  11.124 +            }
  11.125 +          end,
  11.126 +          field_attr = field_attr,
  11.127 +          label_attr = label_attr,
  11.128            content = function(record)
  11.129              ui.link{
  11.130                text = tostring(record.issues_frozen_count),
  11.131                module = "area",
  11.132                view = "show",
  11.133                id = record.id,
  11.134 -              params = { filter = "half_frozen" }
  11.135 +              params = { filter = "half_frozen", tab = "issues" }
  11.136              }
  11.137            end
  11.138          },
  11.139          {
  11.140 -          label = _"Voting",
  11.141 -          field_attr = { style = "text-align: right;" },
  11.142 +          label = function()
  11.143 +            local title = _"Voting"
  11.144 +            ui.image{
  11.145 +              attr = { title = title, alt = title },
  11.146 +              static = "icons/16/email_open.png"
  11.147 +            }
  11.148 +          end,
  11.149 +          field_attr = field_attr,
  11.150 +          label_attr = label_attr,
  11.151            content = function(record)
  11.152              ui.link{
  11.153                text = tostring(record.issues_voting_count),
  11.154                module = "area",
  11.155                view = "show",
  11.156                id = record.id,
  11.157 -              params = { filter = "frozen" }
  11.158 +              params = { filter = "frozen", tab = "issues" }
  11.159              }
  11.160            end
  11.161          },
  11.162          {
  11.163 -          label = _"Not yet voted",
  11.164 -          field_attr = { style = "text-align: right;" },
  11.165 -          content = function(record)
  11.166 -            ui.link{
  11.167 -              attr = { class = record.issues_to_vote_count > 0 and "not_voted" or nil },
  11.168 -              text = tostring(record.issues_to_vote_count),
  11.169 -              module = "area",
  11.170 -              view = "show",
  11.171 -              id = record.id,
  11.172 -              params = { filter = "frozen", filter_voting = "not_voted" }
  11.173 +          label = function()
  11.174 +            local title = _"Finished"
  11.175 +            ui.image{
  11.176 +              attr = { title = title, alt = title },
  11.177 +              static = "icons/16/tick.png"
  11.178              }
  11.179 -          end
  11.180 -        },
  11.181 -        {
  11.182 -          label = _"Finished",
  11.183 -          field_attr = { style = "text-align: right;" },
  11.184 +          end,
  11.185 +          field_attr = field_attr,
  11.186 +          label_attr = label_attr,
  11.187            content = function(record)
  11.188              ui.link{
  11.189                text = tostring(record.issues_finished_count),
  11.190                module = "area",
  11.191                view = "show",
  11.192                id = record.id,
  11.193 -              params = { filter = "finished", issue_list = "newest" }
  11.194 +              params = { filter = "finished", issue_list = "newest", tab = "issues" }
  11.195              }
  11.196            end
  11.197          },
  11.198          {
  11.199 -          label = _"Cancelled",
  11.200 -          field_attr = { style = "text-align: right;" },
  11.201 +          label = function()
  11.202 +            local title = _"Cancelled"
  11.203 +            ui.image{
  11.204 +              attr = { title = title, alt = title },
  11.205 +              static = "icons/16/cross.png"
  11.206 +            }
  11.207 +          end,
  11.208 +          field_attr = field_attr,
  11.209 +          label_attr = label_attr,
  11.210            content = function(record)
  11.211              ui.link{
  11.212                text = tostring(record.issues_cancelled_count),
  11.213                module = "area",
  11.214                view = "show",
  11.215                id = record.id,
  11.216 -              params = { filter = "cancelled", issue_list = "newest" }
  11.217 +              params = { filter = "cancelled", issue_list = "newest", tab = "issues" }
  11.218              }
  11.219            end
  11.220          },
  11.221 +        {
  11.222 +          content = function(record)
  11.223 +            if record.issues_to_vote_count > 0 then
  11.224 +              ui.link{
  11.225 +                attr = { class = "not_voted" },
  11.226 +                text = _"Not yet voted" .. ": " .. tostring(record.issues_to_vote_count),
  11.227 +                module = "area",
  11.228 +                view = "show",
  11.229 +                id = record.id,
  11.230 +                params = {
  11.231 +                  filter = "frozen",
  11.232 +                  filter_voting = "not_voted",
  11.233 +                  tab = "issues"
  11.234 +                }
  11.235 +              }
  11.236 +            end
  11.237 +          end
  11.238 +        },
  11.239        }
  11.240      }
  11.241    end
  11.242 @@ -175,3 +239,61 @@
  11.243    }
  11.244  }
  11.245  
  11.246 +slot.put("<br /> &nbsp; ")
  11.247 +
  11.248 +
  11.249 +ui.image{
  11.250 +  attr = { title = title, alt = title },
  11.251 +  static = "icons/16/user_gray.png"
  11.252 +}
  11.253 +slot.put(" ")
  11.254 +slot.put(_"Member of area")
  11.255 +slot.put(" &nbsp; ")
  11.256 +
  11.257 +ui.image{
  11.258 +  attr = { title = title, alt = title },
  11.259 +  static = "icons/16/new.png"
  11.260 +}
  11.261 +slot.put(" ")
  11.262 +slot.put(_"New")
  11.263 +slot.put(" &nbsp; ")
  11.264 +
  11.265 +ui.image{
  11.266 +  attr = { title = title, alt = title },
  11.267 +  static = "icons/16/comments.png"
  11.268 +}
  11.269 +slot.put(" ")
  11.270 +slot.put(_"Discussion")
  11.271 +slot.put(" &nbsp; ")
  11.272 +
  11.273 +ui.image{
  11.274 +  attr = { title = title, alt = title },
  11.275 +  static = "icons/16/lock.png"
  11.276 +}
  11.277 +slot.put(" ")
  11.278 +slot.put(_"Frozen")
  11.279 +slot.put(" &nbsp; ")
  11.280 +
  11.281 +ui.image{
  11.282 +  attr = { title = title, alt = title },
  11.283 +  static = "icons/16/email_open.png"
  11.284 +}
  11.285 +slot.put(" ")
  11.286 +slot.put(_"Voting")
  11.287 +slot.put(" &nbsp; ")
  11.288 +
  11.289 +ui.image{
  11.290 +  attr = { title = title, alt = title },
  11.291 +  static = "icons/16/tick.png"
  11.292 +}
  11.293 +slot.put(" ")
  11.294 +slot.put(_"Finished")
  11.295 +slot.put(" &nbsp; ")
  11.296 +
  11.297 +ui.image{
  11.298 +  attr = { title = title, alt = title },
  11.299 +  static = "icons/16/cross.png"
  11.300 +}
  11.301 +slot.put(" ")
  11.302 +slot.put(_"Cancelled")
  11.303 +
    12.1 --- a/app/main/area/show.lua	Tue Feb 02 00:31:06 2010 +0100
    12.2 +++ b/app/main/area/show.lua	Sat Feb 20 22:10:31 2010 +0100
    12.3 @@ -36,39 +36,104 @@
    12.4    params = { area_id = area.id }
    12.5  }
    12.6  
    12.7 -ui.tabs{
    12.8 -  {
    12.9 -    name = "issues",
   12.10 -    label = _"Issues",
   12.11 +--[[
   12.12 +for i, issue in ipairs(area.issues) do
   12.13 +  local head_name = "issue_head_content_" .. tostring(issue.id)
   12.14 +  local name = "issue_content_" .. tostring(issue.id)
   12.15 +  local icon_name = "issue_icon_" .. tostring(issue.id)
   12.16 +  ui.container{
   12.17 +    attr = { class = "ui_tabs" },
   12.18      content = function()
   12.19 -      execute.view{
   12.20 -        module = "issue",
   12.21 -        view = "_list",
   12.22 -        params = { issues_selector = area:get_reference_selector("issues"), for_area_list = true }
   12.23 +      local onclick = 
   12.24 +        'if (ui_tabs_active["' .. name .. '"]) {' ..
   12.25 +          'el=document.getElementById("' .. name .. '");' ..
   12.26 +          'el.innerHTML="";' ..
   12.27 +          'el.style.display="none";' ..
   12.28 +          'ui_tabs_active["' .. name .. '"]=false' ..
   12.29 +        '} else {' ..
   12.30 +          'ui_tabs_active["' .. name .. '"]=true;' ..
   12.31 +          'document.getElementById("' .. name .. '").style.display="block"; ' ..
   12.32 +          'var hourglass_el = document.getElementById("' .. icon_name .. '");' ..
   12.33 +          'var hourglass_src = hourglass_el.src;' ..
   12.34 +          'hourglass_el.src = "' .. encode.url{ static = "icons/16/connect.png" } .. '";' ..
   12.35 +          'partialMultiLoad(' ..
   12.36 +            '{ trace: "trace", system_error: "system_error", ' .. name .. '_title: "title", ' .. name .. '_actions: "actions", ' .. name .. '_content: "default" },' ..
   12.37 +            '{},' ..
   12.38 +            '"error",' ..
   12.39 +            '"' .. request.get_relative_baseurl() .. 'issue/show/' .. tostring(issue.id) .. '.html?&_webmcp_json_slots[]=title&_webmcp_json_slots[]=actions&_webmcp_json_slots[]=default&_webmcp_json_slots[]=trace&_webmcp_json_slots[]=system_error&dyn=1",' ..
   12.40 +            '{},' ..
   12.41 +            '{},' ..
   12.42 +            'function() {' ..
   12.43 +              'hourglass_el.src = hourglass_src;' ..
   12.44 +            '},' ..
   12.45 +            'function() {' ..
   12.46 +              'hourglass_el.src = hourglass_src;' ..
   12.47 +            '}' ..
   12.48 +          '); ' ..
   12.49 +        '}' ..
   12.50 +        'return(false);'
   12.51 +      ui.link{
   12.52 +        attr = {
   12.53 +          name = name,
   12.54 +          class = "ui_tabs_accordeon_head",
   12.55 +          id = head_name,
   12.56 +          onclick = onclick,
   12.57 +        },
   12.58 +        module  = "issue",
   12.59 +        view    = "show",
   12.60 +        id      = issue.id,
   12.61 +        params  = params,
   12.62 +        anchor  = name,
   12.63 +        content = function()
   12.64 +          ui.image{
   12.65 +            attr = { id = icon_name },
   12.66 +            static = "icons/16/script.png"
   12.67 +          }
   12.68 +          ui.container{
   12.69 +            attr = { style = "float: right;" },
   12.70 +            content = function()
   12.71 +              
   12.72 +            end
   12.73 +          }
   12.74 +          slot.put(tostring(issue.id))
   12.75 +        end
   12.76        }
   12.77      end
   12.78 -  },
   12.79 -  {
   12.80 -    name = "members",
   12.81 -    label = _"Members",
   12.82 +  }
   12.83 +
   12.84 +  ui.container{
   12.85 +    attr = {
   12.86 +      id = name,
   12.87 +      class = "ui_tabs_accordeon_content",
   12.88 +    },
   12.89      content = function()
   12.90 -      execute.view{
   12.91 -        module = "member",
   12.92 -        view = "_list",
   12.93 -        params = { members_selector = area:get_reference_selector("members") }
   12.94 -      }
   12.95 +      ui.container{ attr = { id = name .. "_title",   }, content = function() slot.put("&nbsp;") end }
   12.96 +      ui.container{ attr = { id = name .. "_actions", }, content = function() slot.put("&nbsp;") end }
   12.97 +      ui.container{ attr = { id = name .. "_content", }, content = function() 
   12.98 +        execute.view{
   12.99 +          module = "initiative",
  12.100 +          view = "_list",
  12.101 +          params = {
  12.102 +            issue = issue,
  12.103 +            initiatives_selector = issue:get_reference_selector("initiatives"),
  12.104 +            limit = 3,
  12.105 +            per_page = 3,
  12.106 +            no_sort = true,
  12.107 +          }
  12.108 +        }
  12.109 +      end }
  12.110      end
  12.111 -  },
  12.112 -  {
  12.113 -    name = "delegations",
  12.114 -    label = _"Delegations",
  12.115 -    content = function()
  12.116 -      execute.view{
  12.117 -        module = "delegation",
  12.118 -        view = "_list",
  12.119 -        params = { delegations_selector = area:get_reference_selector("delegations") }
  12.120 -      }
  12.121 -    end
  12.122 -  },
  12.123 +  }
  12.124 +
  12.125 +  if config.user_tab_mode == "accordeon_all_expanded" then
  12.126 +    ui.script{ script = 'document.getElementById("' .. head_name .. '").onclick();' }
  12.127 +  end
  12.128 +end
  12.129 +--]]
  12.130 +
  12.131 +execute.view{
  12.132 +  module = "area",
  12.133 +  view = "show_tab",
  12.134 +  params = { area = area }
  12.135  }
  12.136  
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/app/main/area/show_tab.lua	Sat Feb 20 22:10:31 2010 +0100
    13.3 @@ -0,0 +1,40 @@
    13.4 +local area = param.get("area", "table") or Area:by_id(param.get("area_id", atom.integer))
    13.5 +
    13.6 +local issues_selector = area:get_reference_selector("issues")
    13.7 +local members_selector = area:get_reference_selector("members")
    13.8 +local delegations_selector = area:get_reference_selector("delegations")
    13.9 +
   13.10 +ui.tabs{
   13.11 +  module = "area",
   13.12 +  view = "show_tab",
   13.13 +  static_params = { area_id = area.id },
   13.14 +  {
   13.15 +    name = "issues",
   13.16 +    label = _"Issues" .. " (" .. tostring(issues_selector:count()) .. ")",
   13.17 +    icon = { static = "icons/16/folder.png" },
   13.18 +    module = "issue",
   13.19 +    view = "_list",
   13.20 +    params = {
   13.21 +      issues_selector = issues_selector,
   13.22 +      filter = cgi.params["filter"],
   13.23 +      filter_voting = param.get("filter_voting")
   13.24 +    }
   13.25 +  },
   13.26 +  {
   13.27 +    name = "members",
   13.28 +    label = _"Members" .. " (" .. tostring(members_selector:count()) .. ")",
   13.29 +    icon = { static = "icons/16/group.png" },
   13.30 +    module = "member",
   13.31 +    view = "_list",
   13.32 +    params = { members_selector = members_selector }
   13.33 +  },
   13.34 +  {
   13.35 +    name = "delegations",
   13.36 +    label = _"Delegations" .. " (" .. tostring(delegations_selector:count()) .. ")",
   13.37 +    icon = { static = "icons/16/table_go.png" },
   13.38 +    module = "delegation",
   13.39 +    view = "_list",
   13.40 +    params = { delegations_selector = delegations_selector }
   13.41 +  },
   13.42 +}
   13.43 +
    14.1 --- a/app/main/delegation/_show_box.lua	Tue Feb 02 00:31:06 2010 +0100
    14.2 +++ b/app/main/delegation/_show_box.lua	Sat Feb 20 22:10:31 2010 +0100
    14.3 @@ -1,43 +1,106 @@
    14.4 -slot.select("actions", function()
    14.5 -
    14.6 -  local delegation
    14.7 -  local area_id
    14.8 -  local issue_id
    14.9 -
   14.10 -  local scope = "global"
   14.11 +function change_delegation(scope, area_id, issue, delegation)
   14.12 +  local image
   14.13 +  local text
   14.14 +  if scope == "global" and delegation then
   14.15 +    image = { static = "icons/16/table_go.png" }
   14.16 +    text = _"Change global delegation"
   14.17 +  elseif scope == "global" and not delegation then
   14.18 +    image = { static = "icons/16/table_go.png" }
   14.19 +    text = _"Set global delegation"
   14.20 +  elseif scope == "area" and delegation and delegation.area_id then
   14.21 +    image = { static = "icons/16/table_go.png" }
   14.22 +    text = _"Change area delegation"
   14.23 +  elseif scope == "area" and not (delegation and delegation.area_id) then
   14.24 +    image = { static = "icons/16/table_go.png" }
   14.25 +    text = _"Set area delegation"
   14.26 +  elseif scope == "issue" then
   14.27 +    if delegation and delegation.issue_id then
   14.28 +      image = { static = "icons/16/table_go.png" }
   14.29 +      text = _"Change issue delegation"
   14.30 +    elseif issue.state ~= "finished" and issue.state ~= "cancelled" then
   14.31 +      image = { static = "icons/16/table_go.png" }
   14.32 +      text = _"Set issue delegation"
   14.33 +    end
   14.34 +  end
   14.35 +  ui.container{
   14.36 +    attr = {
   14.37 +      class = "change_delegation",
   14.38 +    },
   14.39 +    content = function()
   14.40 +      ui.link{
   14.41 +        image  = image,
   14.42 +        text   = text,
   14.43 +        module = "delegation",
   14.44 +        view = "new",
   14.45 +        params = {
   14.46 +          issue_id = issue and issue.id or nil,
   14.47 +          area_id = area_id
   14.48 +        },
   14.49 +      }
   14.50 +      if delegation then
   14.51 +        ui.link{
   14.52 +          image  = { static = "icons/16/delete.png" },
   14.53 +          text   = _"Revoke",
   14.54 +          module = "delegation",
   14.55 +          action = "update",
   14.56 +          params = { issue_id = delegation.issue_id, area_id = delegation.area_id, delete = true },
   14.57 +          routing = {
   14.58 +            default = {
   14.59 +              mode = "redirect",
   14.60 +              module = request.get_module(),
   14.61 +              view = request.get_view(),
   14.62 +              id = param.get_id_cgi(),
   14.63 +              params = param.get_all_cgi()
   14.64 +            }
   14.65 +          }
   14.66 +        }
   14.67 +      end
   14.68 +    end
   14.69 +  }
   14.70 +end
   14.71  
   14.72 -  if param.get("initiative_id", atom.integer) then
   14.73 -    issue_id = Initiative:by_id(param.get("initiative_id", atom.integer)).issue_id
   14.74 -    scope = "issue"
   14.75 -  end
   14.76 +local delegation
   14.77 +local area_id
   14.78 +local issue_id
   14.79 +
   14.80 +local scope = "global"
   14.81  
   14.82 -  if param.get("issue_id", atom.integer) then
   14.83 -    issue_id = param.get("issue_id", atom.integer)
   14.84 -    scope = "issue"
   14.85 -  end
   14.86 +if param.get("initiative_id", atom.integer) then
   14.87 +  issue_id = Initiative:by_id(param.get("initiative_id", atom.integer)).issue_id
   14.88 +  scope = "issue"
   14.89 +end
   14.90  
   14.91 -  if param.get("area_id", atom.integer) then
   14.92 -    area_id = param.get("area_id", atom.integer)
   14.93 -    scope = "area"
   14.94 -  end
   14.95 +if param.get("issue_id", atom.integer) then
   14.96 +  issue_id = param.get("issue_id", atom.integer)
   14.97 +  scope = "issue"
   14.98 +end
   14.99 +
  14.100 +if param.get("area_id", atom.integer) then
  14.101 +  area_id = param.get("area_id", atom.integer)
  14.102 +  scope = "area"
  14.103 +end
  14.104  
  14.105  
  14.106  
  14.107 -  local delegation
  14.108 -  local issue
  14.109 -  if issue_id then
  14.110 -    issue = Issue:by_id(issue_id)
  14.111 -    delegation = Delegation:by_pk(app.session.member.id, nil, issue_id)
  14.112 -    if not delegation then
  14.113 -      delegation = Delegation:by_pk(app.session.member.id, issue.area_id)
  14.114 -    end
  14.115 -  elseif area_id then
  14.116 -    delegation = Delegation:by_pk(app.session.member.id, area_id)
  14.117 +local delegation
  14.118 +local issue
  14.119 +if issue_id then
  14.120 +  issue = Issue:by_id(issue_id)
  14.121 +  delegation = Delegation:by_pk(app.session.member.id, nil, issue_id)
  14.122 +  if not delegation then
  14.123 +    delegation = Delegation:by_pk(app.session.member.id, issue.area_id)
  14.124    end
  14.125 +elseif area_id then
  14.126 +  delegation = Delegation:by_pk(app.session.member.id, area_id)
  14.127 +end
  14.128  
  14.129 -  if not delegation then
  14.130 -    delegation = Delegation:by_pk(app.session.member.id)
  14.131 -  end
  14.132 +if not delegation then
  14.133 +  delegation = Delegation:by_pk(app.session.member.id)
  14.134 +end
  14.135 +
  14.136 +
  14.137 +slot.select("actions", function()
  14.138 +
  14.139    if delegation then
  14.140      ui.container{
  14.141        attr = { class = "delegation vote_info"},
  14.142 @@ -85,6 +148,10 @@
  14.143                :add_order_by("index")
  14.144                :exec()
  14.145      
  14.146 +            if not issue or (issue.state ~= "finished" and issue.state ~= "cancelled") then
  14.147 +              change_delegation(scope, area_id, issue, delegation)
  14.148 +            end
  14.149 +
  14.150              for i, record in ipairs(delegation_chain) do
  14.151                local style
  14.152                local overridden = record.overridden
  14.153 @@ -115,29 +182,6 @@
  14.154                          end
  14.155                        end
  14.156                      }
  14.157 -                    if i == 2 then
  14.158 -                      if not issue or (issue.state ~= "finished" and issue.state ~= "cancelled") then
  14.159 -                        ui.link{
  14.160 -                          attr = { class = "revoke" },
  14.161 -                          content = function()
  14.162 -                            ui.image{ static = "icons/16/delete.png" }
  14.163 -                            slot.put(_"Revoke")
  14.164 -                          end,
  14.165 -                          module = "delegation",
  14.166 -                          action = "update",
  14.167 -                          params = { issue_id = delegation.issue_id, area_id = delegation.area_id, delete = true },
  14.168 -                          routing = {
  14.169 -                            default = {
  14.170 -                              mode = "redirect",
  14.171 -                              module = request.get_module(),
  14.172 -                              view = request.get_view(),
  14.173 -                              id = param.get_id_cgi(),
  14.174 -                              params = param.get_all_cgi()
  14.175 -                            }
  14.176 -                          }
  14.177 -                        }
  14.178 -                      end
  14.179 -                    end
  14.180                    end
  14.181                  }
  14.182                end
  14.183 @@ -155,7 +199,7 @@
  14.184                  ui.container{
  14.185                    attr = { class = "delegation_participation" },
  14.186                    content = function()
  14.187 -                    slot.put("<br /><br />-----> Participation<br />")
  14.188 +                    slot.put(_"This member is participating, the rest of delegation chain is suspended while discussing")
  14.189                    end
  14.190                  }
  14.191                end
  14.192 @@ -165,38 +209,7 @@
  14.193          }
  14.194        end
  14.195      }
  14.196 -
  14.197 -
  14.198 +  else
  14.199 +    change_delegation(scope, area_id, issue)
  14.200    end
  14.201 -  ui.link{
  14.202 -    content = function()
  14.203 -      if scope == "global" and delegation then
  14.204 -        ui.image{ static = "icons/16/table_go.png" }
  14.205 -        slot.put(_"Change global delegation")
  14.206 -      elseif scope == "global" and not delegation then
  14.207 -        ui.image{ static = "icons/16/table_go.png" }
  14.208 -        slot.put(_"Set global delegation")
  14.209 -      elseif scope == "area" and delegation and delegation.area_id then
  14.210 -        ui.image{ static = "icons/16/table_go.png" }
  14.211 -        slot.put(_"Change area delegation")
  14.212 -      elseif scope == "area" and not (delegation and delegation.area_id) then
  14.213 -        ui.image{ static = "icons/16/table_go.png" }
  14.214 -        slot.put(_"Set area delegation")
  14.215 -      elseif scope == "issue" then
  14.216 -        if delegation and delegation.issue_id then
  14.217 -          ui.image{ static = "icons/16/table_go.png" }
  14.218 -          slot.put(_"Change issue delegation")
  14.219 -        elseif issue.state ~= "finished" and issue.state ~= "cancelled" then
  14.220 -          ui.image{ static = "icons/16/table_go.png" }
  14.221 -          slot.put(_"Set issue delegation")
  14.222 -        end
  14.223 -      end
  14.224 -    end,
  14.225 -    module = "delegation",
  14.226 -    view = "new",
  14.227 -    params = {
  14.228 -      area_id = area_id,
  14.229 -      issue_id = issue_id 
  14.230 -    }
  14.231 -  }
  14.232  end)
    15.1 --- a/app/main/draft/_show.lua	Tue Feb 02 00:31:06 2010 +0100
    15.2 +++ b/app/main/draft/_show.lua	Sat Feb 20 22:10:31 2010 +0100
    15.3 @@ -6,8 +6,15 @@
    15.4    readonly = true,
    15.5    content = function()
    15.6  
    15.7 -    ui.field.text{ label = _"Last author", name = "author_name" }
    15.8 -    ui.field.timestamp{ label = _"Created at", name = "created" }
    15.9 +    ui.field.text{ 
   15.10 +      label = _"Last author",
   15.11 +      value = _(
   15.12 +        "#{author} at #{date}", {
   15.13 +          author = draft.author_name,
   15.14 +          date = format.timestamp(draft.created)
   15.15 +        }
   15.16 +      )
   15.17 +    }
   15.18      ui.container{
   15.19        attr = { class = "draft_content wiki" },
   15.20        content = function()
    16.1 --- a/app/main/index/about.lua	Tue Feb 02 00:31:06 2010 +0100
    16.2 +++ b/app/main/index/about.lua	Sat Feb 20 22:10:31 2010 +0100
    16.3 @@ -1,5 +1,18 @@
    16.4  slot.put_into("title", encode.html(_"About LiquidFeedback"))
    16.5  
    16.6 +if app.session.member_id then
    16.7 +  slot.select("actions", function()
    16.8 +    ui.link{
    16.9 +      module = "index",
   16.10 +      view = "usage_terms",
   16.11 +      content = function()
   16.12 +        ui.image{ static = "icons/16/script.png" }
   16.13 +        slot.put(_"Terms of use")
   16.14 +      end
   16.15 +    }
   16.16 +  end)
   16.17 +end
   16.18 +
   16.19  
   16.20  slot.put("<br />")
   16.21  ui.field.text{ attr = { style = "font-weight: bold;" }, value = "Diensteanbieter:" }
    17.1 --- a/app/main/index/index.lua	Tue Feb 02 00:31:06 2010 +0100
    17.2 +++ b/app/main/index/index.lua	Sat Feb 20 22:10:31 2010 +0100
    17.3 @@ -23,6 +23,7 @@
    17.4                attr = { style = "margin-left: 0.5em;", alt = lang }
    17.5              }
    17.6            end,
    17.7 +          text = _('Select language "#{langcode}"', { langcode = lang }),
    17.8            module = "index",
    17.9            action = "set_lang",
   17.10            params = { lang = lang },
    18.1 --- a/app/main/index/login.lua	Tue Feb 02 00:31:06 2010 +0100
    18.2 +++ b/app/main/index/login.lua	Sat Feb 20 22:10:31 2010 +0100
    18.3 @@ -24,6 +24,7 @@
    18.4                attr = { style = "margin-left: 0.5em;", alt = lang }
    18.5              }
    18.6            end,
    18.7 +          text = _('Select language "#{langcode}"', { langcode = lang }),
    18.8            module = "index",
    18.9            action = "set_lang",
   18.10            params = { lang = lang },
    19.1 --- a/app/main/index/search.lua	Tue Feb 02 00:31:06 2010 +0100
    19.2 +++ b/app/main/index/search.lua	Sat Feb 20 22:10:31 2010 +0100
    19.3 @@ -1,44 +1,41 @@
    19.4 -local search_for = param.get("search_for", atom.string)
    19.5 +local search_for = param.get("search_for", atom.string) or "global"
    19.6  local search_string = param.get("search", atom.string)
    19.7  
    19.8 -search_for = search_for or "global"
    19.9 -
   19.10  slot.put_into("title", _("Search results for: '#{search}'", { search  = search_string }))
   19.11  
   19.12 +
   19.13  if search_for == "global" or search_for == "member" then
   19.14 -  members_selector = Member:get_search_selector(search_string)
   19.15 ---if #members > 0 then
   19.16 +  local members_selector = Member:get_search_selector(search_string)
   19.17    ui.heading{ content = _"Members" }
   19.18    execute.view{
   19.19      module = "member",
   19.20      view = "_list",
   19.21      params = { members_selector = members_selector },
   19.22    }
   19.23 ---end
   19.24  end
   19.25  
   19.26 -if search_for == "global" or search_for == "issue" then
   19.27 -  issues_selector = Issue:get_search_selector(search_string)
   19.28 ---if #issues > 0 then
   19.29 -  ui.heading{ content = _"Issues" }
   19.30 -  execute.view{
   19.31 -    module = "issue",
   19.32 -    view = "_list",
   19.33 -    params = { issues_selector = issues_selector, highlight_string = search_string },
   19.34 -  }
   19.35 ---end
   19.36 -end
   19.37 -
   19.38 -if search_for == "initiative" then
   19.39 -  initiatives_selector = Initiative:get_search_selector(search_string)
   19.40 ---if #initiatives > 0 then
   19.41 +if search_for == "global" or search_for == "initiative" then
   19.42 +  local initiatives_selector = Initiative:get_search_selector(search_string)
   19.43    ui.heading{ content = _"Initiatives" }
   19.44    execute.view{
   19.45      module = "initiative",
   19.46      view = "_list",
   19.47      params = { initiatives_selector = initiatives_selector },
   19.48    }
   19.49 ---end
   19.50 +end
   19.51 +
   19.52 +if search_for == "issue" then
   19.53 +  local issues_selector = Issue:get_search_selector(search_string)
   19.54 +  ui.heading{ content = _"Issues" }
   19.55 +  execute.view{
   19.56 +    module = "issue",
   19.57 +    view = "_list",
   19.58 +    params = {
   19.59 +      issues_selector = issues_selector,
   19.60 +      highlight_string = search_string,
   19.61 +      no_filter = true
   19.62 +    },
   19.63 +  }
   19.64  end
   19.65  
   19.66  
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/app/main/index/usage_terms.lua	Sat Feb 20 22:10:31 2010 +0100
    20.3 @@ -0,0 +1,17 @@
    20.4 +slot.select("actions", function()
    20.5 +  ui.link{
    20.6 +    module = "index",
    20.7 +    view = "about",
    20.8 +    content = function()
    20.9 +      ui.image{ static = "icons/16/cancel.png" }
   20.10 +      slot.put(_"Back")
   20.11 +    end
   20.12 +  }
   20.13 +end)
   20.14 +
   20.15 +ui.container{
   20.16 +  attr = { class = "wiki use_terms" },
   20.17 +  content = function()
   20.18 +    slot.put(format.wiki_text(config.use_terms))
   20.19 +  end
   20.20 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/app/main/initiative/_current_draft.lua	Sat Feb 20 22:10:31 2010 +0100
    21.3 @@ -0,0 +1,16 @@
    21.4 +local initiator = param.get("initiator", "table")
    21.5 +local initiative = param.get("initiative", "table")
    21.6 +
    21.7 +if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
    21.8 +  ui.link{
    21.9 +    attr = { style = "float: right;" },
   21.10 +    content = function()
   21.11 +      ui.image{ static = "icons/16/script_add.png" }
   21.12 +      slot.put(_"Edit draft")
   21.13 +    end,
   21.14 +    module = "draft",
   21.15 +    view = "new",
   21.16 +    params = { initiative_id = initiative.id }
   21.17 +  }
   21.18 +end
   21.19 +execute.view{ module = "draft", view = "_show", params = { draft = initiative.current_draft } }
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/app/main/initiative/_details.lua	Sat Feb 20 22:10:31 2010 +0100
    22.3 @@ -0,0 +1,20 @@
    22.4 +local initiative = param.get("initiative", "table")
    22.5 +
    22.6 +ui.form{
    22.7 +  attr = { class = "vertical" },
    22.8 +  record = initiative,
    22.9 +  readonly = true,
   22.10 +  content = function()
   22.11 +    ui.field.text{ label = _"Issue policy", value = initiative.issue.policy.name }
   22.12 +    ui.field.text{
   22.13 +      label = _"Created at",
   22.14 +      value = tostring(initiative.created)
   22.15 +    }
   22.16 +    ui.field.text{
   22.17 +      label = _"Created at",
   22.18 +      value = format.timestamp(initiative.created)
   22.19 +    }
   22.20 +  -- ui.field.date{ label = _"Revoked at", name = "revoked" }
   22.21 +    ui.field.boolean{ label = _"Admitted", name = "admitted" }
   22.22 +  end
   22.23 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/app/main/initiative/_initiators.lua	Sat Feb 20 22:10:31 2010 +0100
    23.3 @@ -0,0 +1,58 @@
    23.4 +local initiative = param.get("initiative", "table")
    23.5 +local initiator = param.get("initiator", "table")
    23.6 +local initiators_members_selector = param.get("initiators_members_selector", "table")
    23.7 +
    23.8 +local initiator_count = initiators_members_selector:count()
    23.9 +
   23.10 +if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
   23.11 +  ui.link{
   23.12 +    attr = { class = "action" },
   23.13 +    content = function()
   23.14 +      ui.image{ static = "icons/16/user_add.png" }
   23.15 +      slot.put(_"Invite initiator")
   23.16 +    end,
   23.17 +    module = "initiative",
   23.18 +    view = "add_initiator",
   23.19 +    params = { initiative_id = initiative.id }
   23.20 +  }
   23.21 +  if initiator_count > 1 then
   23.22 +    ui.link{
   23.23 +      content = function()
   23.24 +        ui.image{ static = "icons/16/user_delete.png" }
   23.25 +        slot.put(_"Remove initiator")
   23.26 +      end,
   23.27 +      module = "initiative",
   23.28 +      view = "remove_initiator",
   23.29 +      params = { initiative_id = initiative.id }
   23.30 +    }
   23.31 +  end
   23.32 +end
   23.33 +if initiator and initiator.accepted == false then
   23.34 +    ui.link{
   23.35 +      image  = { static = "icons/16/user_delete.png" },
   23.36 +      text   = _"Cancel refuse of invitation",
   23.37 +      module = "initiative",
   23.38 +      action = "remove_initiator",
   23.39 +      params = {
   23.40 +        initiative_id = initiative.id,
   23.41 +        member_id = app.session.member.id
   23.42 +      },
   23.43 +      routing = {
   23.44 +        ok = {
   23.45 +          mode = "redirect",
   23.46 +          module = "initiative",
   23.47 +          view = "show",
   23.48 +          id = initiative.id
   23.49 +        }
   23.50 +      }
   23.51 +    }
   23.52 +end
   23.53 +
   23.54 +execute.view{
   23.55 +  module = "member",
   23.56 +  view = "_list",
   23.57 +  params = {
   23.58 +    members_selector = initiators_members_selector,
   23.59 +    initiator = initiator
   23.60 +  }
   23.61 +}
    24.1 --- a/app/main/initiative/_list.lua	Tue Feb 02 00:31:06 2010 +0100
    24.2 +++ b/app/main/initiative/_list.lua	Sat Feb 20 22:10:31 2010 +0100
    24.3 @@ -1,71 +1,10 @@
    24.4 -local initiatives_selector = param.get("initiatives_selector", "table")
    24.5 -initiatives_selector:join("issue", nil, "issue.id = initiative.issue_id")
    24.6 -
    24.7 -local limit = param.get("limit", atom.number)
    24.8 -
    24.9 -local more_initiatives_count
   24.10 -if limit then
   24.11 -  local initiatives_count = initiatives_selector:count()
   24.12 -  if initiatives_count > limit then
   24.13 -    more_initiatives_count = initiatives_count - limit
   24.14 -  end
   24.15 -  initiatives_selector:limit(limit)
   24.16 -end
   24.17 -
   24.18 +ui.script{ script = "lf_initiative_expanded = {};" }
   24.19  
   24.20  local issue = param.get("issue", "table")
   24.21  
   24.22 -local order_options = {}
   24.23 -
   24.24 -if issue and issue.ranks_available then
   24.25 -  order_options[#order_options+1] = {
   24.26 -    name = "rank",
   24.27 -    label = _"Rank",
   24.28 -    order_by = "initiative.rank, initiative.admitted DESC, vote_ratio(initiative.positive_votes, initiative.negative_votes) DESC, initiative.id"
   24.29 -  }
   24.30 -end
   24.31 -
   24.32 -order_options[#order_options+1] = {
   24.33 -  name = "potential_support",
   24.34 -  label = _"Potential support",
   24.35 -  order_by = "initiative.supporter_count::float / issue.population::float DESC, initiative.id"
   24.36 -}
   24.37 -
   24.38 -order_options[#order_options+1] = {
   24.39 -  name = "support",
   24.40 -  label = _"Support",
   24.41 -  order_by = "initiative.satisfied_supporter_count::float / issue.population::float DESC, initiative.id"
   24.42 -}
   24.43 -
   24.44 -order_options[#order_options+1] = {
   24.45 -  name = "newest",
   24.46 -  label = _"Newest",
   24.47 -  order_by = "initiative.created DESC, initiative.id"
   24.48 -}
   24.49 -
   24.50 -order_options[#order_options+1] = {
   24.51 -  name = "oldest",
   24.52 -  label = _"Oldest",
   24.53 -  order_by = "initiative.created, initiative.id"
   24.54 -}
   24.55 -
   24.56 -local name = "initiative_list"
   24.57 -if issue then
   24.58 -  name = "issue_" .. tostring(issue.id) ..  "_initiative_list"
   24.59 -end
   24.60 -
   24.61 -ui_order = ui.order
   24.62 -
   24.63 -if param.get("no_sort", atom.boolean) then
   24.64 -  ui_order = function(args) args.content() end
   24.65 -  if issue.ranks_available then
   24.66 -    initiatives_selector:add_order_by("initiative.rank, initiative.admitted DESC, vote_ratio(initiative.positive_votes, initiative.negative_votes) DESC, initiative.id")
   24.67 -  else
   24.68 -    initiatives_selector:add_order_by("initiative.supporter_count::float / issue.population::float DESC, initiative.id")
   24.69 -  end
   24.70 -end
   24.71 -
   24.72 +local initiatives_selector = param.get("initiatives_selector", "table")
   24.73  initiatives_selector
   24.74 +  :join("issue", nil, "issue.id = initiative.issue_id")
   24.75    :left_join("initiator", "_initiator", { "_initiator.initiative_id = initiative.id AND _initiator.member_id = ?", app.session.member.id} )
   24.76    :left_join("supporter", "_supporter", { "_supporter.initiative_id = initiative.id AND _supporter.member_id = ?", app.session.member.id} )
   24.77  
   24.78 @@ -73,128 +12,213 @@
   24.79    :add_field({"(_supporter.member_id NOTNULL) AND NOT EXISTS(SELECT 1 FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)))", app.session.member.id }, "is_supporter")
   24.80    :add_field({"EXISTS(SELECT 1 FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)))", app.session.member.id }, "is_potential_supporter")
   24.81  
   24.82 +local initiatives_count = initiatives_selector:count()
   24.83  
   24.84 -ui_order{
   24.85 -  name = name,
   24.86 -  selector = initiatives_selector,
   24.87 -  options = order_options,
   24.88 -  content = function()
   24.89 -    ui.paginate{
   24.90 -      name = issue and "issue_" .. tostring(issue.id) .. "_page" or nil,
   24.91 -      selector = initiatives_selector,
   24.92 -      per_page = param.get("per_page", atom.number),
   24.93 +local limit = param.get("limit", atom.number)
   24.94 +local no_sort = param.get("no_sort", atom.boolean)
   24.95 +
   24.96 +local show_for_issue = param.get("show_for_issue", atom.boolean)
   24.97 +
   24.98 +local show_for_initiative
   24.99 +
  24.100 +local show_for_initiative_id = param.get("for_initiative_id", atom.number)
  24.101 +
  24.102 +if show_for_initiative_id then
  24.103 +  show_for_initiative = Initiative:by_id(show_for_initiative_id)
  24.104 +
  24.105 +elseif not show_for_initiative_id and show_for_issue and issue and issue.ranks_available then
  24.106 +  winning_initiative = Initiative:new_selector()
  24.107 +    :add_where{ "issue_id = ?", issue.id }
  24.108 +    :add_where("rank = 1")
  24.109 +    :single_object_mode()
  24.110 +    :exec()
  24.111 +  if winning_initiative then
  24.112 +    show_for_initiative = winning_initiative
  24.113 +    ui.container{
  24.114 +      attr = { class = "admitted_info" },
  24.115 +      content = _"This issue has been finished with the following winning initiative:"
  24.116 +    }
  24.117 +  else
  24.118 +    ui.container{
  24.119 +      attr = { class = "not_admitted_info" },
  24.120 +      content = _"This issue has been finished without any winning initiative."
  24.121 +    }
  24.122 +  end
  24.123 +end
  24.124 +
  24.125 +
  24.126 +if show_for_initiative then
  24.127 +  ui.script{ script = "lf_initiative_expanded['initiative_content_" .. tostring(show_for_initiative.id) .. "'] = true;" }
  24.128 +  initiatives_selector:add_where{ "initiative.id != ?", show_for_initiative.id }
  24.129 +
  24.130 +  execute.view{
  24.131 +    module = "initiative",
  24.132 +    view = "_list_element",
  24.133 +    params = {
  24.134 +      initiative = show_for_initiative,
  24.135 +      expanded = true,
  24.136 +      expandable = true
  24.137 +    }
  24.138 +  }
  24.139 +  if show_for_issue then
  24.140 +    slot.put("<br />")
  24.141 +    ui.container{
  24.142 +      attr = { style = "font-weight: bold;" },
  24.143        content = function()
  24.144 -        local initiatives = initiatives_selector:exec()
  24.145 -        local columns = {}
  24.146 -        columns[#columns+1] = {
  24.147 -          content = function(record)
  24.148 -            if record.issue.accepted and record.issue.closed and record.issue.ranks_available then 
  24.149 -              ui.field.rank{ attr = { class = "rank" }, value = record.rank }
  24.150 -            end
  24.151 -          end
  24.152 -        }
  24.153 -        columns[#columns+1] = {
  24.154 -          content = function(record)
  24.155 -            if record.issue.accepted and record.issue.closed then
  24.156 -              if record.issue.ranks_available then 
  24.157 -                if record.negative_votes and record.positive_votes then
  24.158 -                  local max_value = record.issue.voter_count
  24.159 -                  ui.bargraph{
  24.160 -                    max_value = max_value,
  24.161 -                    width = 100,
  24.162 -                    bars = {
  24.163 -                      { color = "#0a0", value = record.positive_votes },
  24.164 -                      { color = "#aaa", value = max_value - record.negative_votes - record.positive_votes },
  24.165 -                      { color = "#a00", value = record.negative_votes },
  24.166 -                    }
  24.167 -                  }
  24.168 -                end
  24.169 -              else
  24.170 -                slot.put(_"Counting of votes")
  24.171 -              end
  24.172 -            else
  24.173 -              local max_value = (record.issue.population or 0)
  24.174 -              ui.bargraph{
  24.175 -                max_value = max_value,
  24.176 -                width = 100,
  24.177 -                bars = {
  24.178 -                  { color = "#0a0", value = (record.satisfied_supporter_count or 0) },
  24.179 -                  { color = "#777", value = (record.supporter_count or 0) - (record.satisfied_supporter_count or 0) },
  24.180 -                  { color = "#ddd", value = max_value - (record.supporter_count or 0) },
  24.181 -                }
  24.182 -              }
  24.183 -            end
  24.184 -          end
  24.185 -        }
  24.186 -        columns[#columns+1] = {
  24.187 -          content = function(record)
  24.188 -            local link_class
  24.189 -            if record.revoked then
  24.190 -              link_class = "revoked"
  24.191 -            end
  24.192 -            ui.link{
  24.193 -              attr = { class = link_class },
  24.194 -              content = function()
  24.195 -                local name
  24.196 -                if record.name_highlighted then
  24.197 -                  name = encode.highlight(record.name_highlighted)
  24.198 -                else
  24.199 -                  name = encode.html(record.name)
  24.200 -                end
  24.201 -                slot.put(name)
  24.202 -              end,
  24.203 -              module = "initiative",
  24.204 -              view = "show",
  24.205 -              id = record.id
  24.206 -            }
  24.207 -            if record.issue.state == "new" then
  24.208 -              ui.image{
  24.209 -                static = "icons/16/new.png"
  24.210 -              }
  24.211 -            end
  24.212 -            if record.is_supporter then
  24.213 -              slot.put("&nbsp;")
  24.214 -              local label = _"You are supporting this initiative"
  24.215 -              ui.image{
  24.216 -                attr = { alt = label, title = label },
  24.217 -                static = "icons/16/thumb_up_green.png"
  24.218 -              }
  24.219 -            end
  24.220 -            if record.is_potential_supporter then
  24.221 -              slot.put("&nbsp;")
  24.222 -              local label = _"You are potential supporter of this initiative"
  24.223 -              ui.image{
  24.224 -                attr = { alt = label, title = label },
  24.225 -                static = "icons/16/thumb_up.png"
  24.226 -              }
  24.227 -            end
  24.228 -            if record.is_initiator then
  24.229 -              slot.put("&nbsp;")
  24.230 -              local label = _"You are iniator of this initiative"
  24.231 -              ui.image{
  24.232 -                attr = { alt = label, title = label },
  24.233 -                static = "icons/16/user_edit.png"
  24.234 -              }
  24.235 -            end
  24.236 -          end
  24.237 -        }
  24.238 -
  24.239 -        ui.list{
  24.240 -          attr = { class = "initiatives" },
  24.241 -          records = initiatives,
  24.242 -          columns = columns
  24.243 -        }
  24.244 +        slot.put(_"Alternative initiatives")
  24.245        end
  24.246      }
  24.247    end
  24.248 -}
  24.249 -
  24.250 -if more_initiatives_count then
  24.251 -  ui.link{
  24.252 -    attr = { style = "font-size: 75%; font-style: italic;" },
  24.253 -    content = _("#{count} more initiatives", { count = more_initiatives_count }),
  24.254 -    module = "issue",
  24.255 -    view = "show",
  24.256 -    id = issue.id,
  24.257 +elseif show_for_issue then
  24.258 +  ui.container{
  24.259 +    attr = { style = "font-weight: bold;" },
  24.260 +    content = function()
  24.261 +      slot.put(_"Alternative initiatives")
  24.262 +    end
  24.263    }
  24.264  end
  24.265 +
  24.266 +if not show_for_initiative or initiatives_count > 1 then
  24.267 +
  24.268 +
  24.269 +  local more_initiatives_count
  24.270 +  if limit then
  24.271 +    limit = limit - (show_for_initiative and 1 or 0)
  24.272 +    if initiatives_count > limit then
  24.273 +      more_initiatives_count = initiatives_count - limit
  24.274 +    end
  24.275 +    initiatives_selector:limit(limit)
  24.276 +  end
  24.277 +
  24.278 +  local expandable = param.get("expandable", atom.boolean)
  24.279 +
  24.280 +  local issue = param.get("issue", "table")
  24.281 +
  24.282 +  local name = "initiative_list"
  24.283 +  if issue then
  24.284 +    name = "issue_" .. tostring(issue.id) ..  "_initiative_list"
  24.285 +  end
  24.286 +
  24.287 +  ui.add_partial_param_names{ name }
  24.288 +
  24.289 +  local order_filter = {
  24.290 +    name = name,
  24.291 +    label = _"Order by"
  24.292 +  }
  24.293 +
  24.294 +  if issue and issue.ranks_available then
  24.295 +    order_filter[#order_filter+1] = {
  24.296 +      name = "rank",
  24.297 +      label = _"Rank",
  24.298 +      selector_modifier = function(selector) selector:add_order_by("initiative.rank, initiative.admitted DESC, vote_ratio(initiative.positive_votes, initiative.negative_votes) DESC, initiative.id") end
  24.299 +    }
  24.300 +  end
  24.301 +
  24.302 +  order_filter[#order_filter+1] = {
  24.303 +    name = "potential_support",
  24.304 +    label = _"Potential support",
  24.305 +    selector_modifier = function(selector) selector:add_order_by("initiative.supporter_count::float / issue.population::float DESC, initiative.id") end
  24.306 +  }
  24.307 +
  24.308 +  order_filter[#order_filter+1] = {
  24.309 +    name = "support",
  24.310 +    label = _"Support",
  24.311 +    selector_modifier = function(selector) selector:add_order_by("initiative.satisfied_supporter_count::float / issue.population::float DESC, initiative.id") end
  24.312 +  }
  24.313 +
  24.314 +  order_filter[#order_filter+1] = {
  24.315 +    name = "newest",
  24.316 +    label = _"Newest",
  24.317 +    selector_modifier = function(selector) selector:add_order_by("initiative.created DESC, initiative.id") end
  24.318 +  }
  24.319 +
  24.320 +  order_filter[#order_filter+1] = {
  24.321 +    name = "oldest",
  24.322 +    label = _"Oldest",
  24.323 +    selector_modifier = function(selector) selector:add_order_by("initiative.created, initiative.id") end
  24.324 +  }
  24.325 +
  24.326 +  ui_filters = ui.filters
  24.327 +
  24.328 +  if no_sort then
  24.329 +    ui_filters = function(args) args.content() end
  24.330 +    if issue.ranks_available then
  24.331 +      initiatives_selector:add_order_by("initiative.rank, initiative.admitted DESC, vote_ratio(initiative.positive_votes, initiative.negative_votes) DESC, initiative.id")
  24.332 +    else
  24.333 +      initiatives_selector:add_order_by("initiative.supporter_count::float / issue.population::float DESC, initiative.id")
  24.334 +    end
  24.335 +  end
  24.336 +
  24.337 +  ui_filters{
  24.338 +    label = _"Change order",
  24.339 +    order_filter,
  24.340 +    selector = initiatives_selector,
  24.341 +    content = function()
  24.342 +      ui.paginate{
  24.343 +        name = issue and "issue_" .. tostring(issue.id) .. "_page" or nil,
  24.344 +        selector = initiatives_selector,
  24.345 +        per_page = param.get("per_page", atom.number),
  24.346 +        content = function()
  24.347 +          local initiatives = initiatives_selector:exec()
  24.348 +          for i, initiative in ipairs(initiatives) do
  24.349 +            local expanded = config.user_tab_mode == "accordeon_all_expanded" and expandable or
  24.350 +              show_for_initiative and initiative.id == show_for_initiative.id
  24.351 +            if expanded then
  24.352 +              ui.script{ script = "lf_initiative_expanded['initiative_content_" .. tostring(initiative.id) .. "'] = true;" }
  24.353 +            end
  24.354 +            execute.view{
  24.355 +              module = "initiative",
  24.356 +              view = "_list_element",
  24.357 +              params = {
  24.358 +                initiative = initiative,
  24.359 +                expanded = expanded,
  24.360 +                expandable = expandable
  24.361 +              }
  24.362 +            }
  24.363 +          end
  24.364 +        end
  24.365 +      }
  24.366 +    end
  24.367 +  }
  24.368 +
  24.369 +  if more_initiatives_count then
  24.370 +    ui.link{
  24.371 +      attr = { style = "font-size: 75%; font-style: italic;" },
  24.372 +      content = _("and #{count} more initiatives", { count = more_initiatives_count }),
  24.373 +      module = "issue",
  24.374 +      view = "show",
  24.375 +      id = issue.id,
  24.376 +    }
  24.377 +  end
  24.378 +
  24.379 +end
  24.380 +
  24.381 +if show_for_issue then
  24.382 +  slot.put("<br />")
  24.383 +  
  24.384 +  if issue and initiatives_count == 1 then
  24.385 +    ui.container{
  24.386 +      content = function()
  24.387 +        if issue.fully_frozen or issue.closed then
  24.388 +          slot.put(_"There were no more alternative initiatives.")
  24.389 +        else
  24.390 +          slot.put(_"There are no more alternative initiatives currently.")
  24.391 +        end
  24.392 +      end
  24.393 +    }
  24.394 +  end
  24.395 +
  24.396 +  if not (issue.fully_frozen or issue.closed) then
  24.397 +    slot.put(" ")
  24.398 +    ui.link{
  24.399 +      content = function()
  24.400 +        ui.image{ static = "icons/16/script_add.png" }
  24.401 +        slot.put(" ")
  24.402 +        slot.put(_"Create alternative initiative")
  24.403 +      end,
  24.404 +      module = "initiative",
  24.405 +      view = "new",
  24.406 +      params = { issue_id = issue.id }
  24.407 +    }
  24.408 +  end
  24.409 +end
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/app/main/initiative/_list_element.lua	Sat Feb 20 22:10:31 2010 +0100
    25.3 @@ -0,0 +1,208 @@
    25.4 +local initiative = param.get("initiative", "table")
    25.5 +local expanded = param.get("expanded", atom.boolean)
    25.6 +local expandable = param.get("expandable", atom.boolean)
    25.7 +
    25.8 +local head_name = "initiative_head_" ..    tostring(initiative.id)
    25.9 +local link_name = "initiative_link_" ..    tostring(initiative.id)
   25.10 +local name      = "initiative_content_" .. tostring(initiative.id)
   25.11 +local icon_name = "initiative_icon_" ..    tostring(initiative.id)
   25.12 +
   25.13 +ui.container{
   25.14 +  attr = { class = "ui_tabs" .. (initiative.id == for_initiative_id and " active" or "") },
   25.15 +  content = function()
   25.16 +    local web20 = config.user_tab_mode == "accordeon"
   25.17 +      or config.user_tab_mode == "accordeon_first_expanded"
   25.18 +      or config.user_tab_mode == "accordeon_all_expanded"
   25.19 +    local onclick
   25.20 +    if web20 then
   25.21 +      if expandable then
   25.22 +      onclick = 
   25.23 +        'if (lf_initiative_expanded["' .. name .. '"]) {' ..
   25.24 +          'lf_initiative_expanded["' .. name .. '"]=false;' ..
   25.25 +          'document.getElementById("' .. name .. '_content").innerHTML="&nbsp;";' ..
   25.26 +          'document.getElementById("' .. name .. '").style.display="none";' ..
   25.27 +        '} else {' ..
   25.28 +          'lf_initiative_expanded["' .. name .. '"] = true;' ..
   25.29 +          'document.getElementById("' .. name .. '").style.display="block"; ' ..
   25.30 +          'var hourglass_el = document.getElementById("' .. icon_name .. '");' ..
   25.31 +          'var hourglass_src = hourglass_el.src;' ..
   25.32 +          'hourglass_el.src = "' .. encode.url{ static = "icons/16/connect.png" } .. '";' ..
   25.33 +          'partialMultiLoad(' ..
   25.34 +            '{ trace: "trace", system_error: "system_error", ' .. name .. '_content: "default" },' ..
   25.35 +            '{},' ..
   25.36 +            '"error",' ..
   25.37 +            '"' .. request.get_relative_baseurl() .. 'initiative/show_partial/' .. tostring(initiative.id) .. '.html?&_webmcp_json_slots[]=default&_webmcp_json_slots[]=support&_webmcp_json_slots[]=trace&_webmcp_json_slots[]=system_error",' ..
   25.38 +            '{},' ..
   25.39 +            '{},' ..
   25.40 +            'function() {' ..
   25.41 +              'hourglass_el.src = hourglass_src;' ..
   25.42 +            '},' ..
   25.43 +            'function() {' ..
   25.44 +              'hourglass_el.src = hourglass_src;' ..
   25.45 +            '}' ..
   25.46 +          '); ' ..
   25.47 +        '}' ..
   25.48 +        'return(false);'
   25.49 +      else
   25.50 +        onclick = "document.location.href = document.getElementById('" .. link_name .. "').href;"
   25.51 +      end
   25.52 +    end
   25.53 +    local module = "initiative"
   25.54 +    local view = "show"
   25.55 +    local id = initiative.id
   25.56 +    local params = {}
   25.57 +    ui.container{
   25.58 +      attr = {
   25.59 +        name = name,
   25.60 +        class = "ui_tabs_accordeon_head",
   25.61 +        id = head_name,
   25.62 +        onclick = onclick,
   25.63 +      },
   25.64 +      content = function()
   25.65 +
   25.66 +        ui.container{
   25.67 +          attr = { style = "float: left; width: 4em;"},
   25.68 +          content = function()
   25.69 +            if initiative.issue.accepted and initiative.issue.closed and initiative.issue.ranks_available or initiative.admitted == false then 
   25.70 +              ui.field.rank{ image_attr = { id = icon_name }, attr = { class = "rank" }, value = initiative.rank }
   25.71 +            elseif web20 then
   25.72 +              ui.image{
   25.73 +                attr = {
   25.74 +                  width = 16,
   25.75 +                  height = 16,
   25.76 +                  id = icon_name,
   25.77 +                  style = "float: left;"
   25.78 +                },
   25.79 +                static = "icons/16/script.png"
   25.80 +              }
   25.81 +            else
   25.82 +              slot.put("&nbsp;")
   25.83 +            end
   25.84 +          end
   25.85 +        }
   25.86 +
   25.87 +        ui.container{
   25.88 +          attr = { style = "float: left; width: 110px;"},
   25.89 +          content = function()
   25.90 +            if initiative.issue.accepted and initiative.issue.closed then
   25.91 +              if initiative.issue.ranks_available then 
   25.92 +                if initiative.negative_votes and initiative.positive_votes then
   25.93 +                  local max_value = initiative.issue.voter_count
   25.94 +                  ui.bargraph{
   25.95 +                    max_value = max_value,
   25.96 +                    width = 100,
   25.97 +                    bars = {
   25.98 +                      { color = "#0a0", value = initiative.positive_votes },
   25.99 +                      { color = "#aaa", value = max_value - initiative.negative_votes - initiative.positive_votes },
  25.100 +                      { color = "#a00", value = initiative.negative_votes },
  25.101 +                    }
  25.102 +                  }
  25.103 +                else
  25.104 +                  slot.put("&nbsp;")
  25.105 +                end
  25.106 +              else
  25.107 +                slot.put(_"Counting of votes")
  25.108 +              end
  25.109 +            elseif initiative.issue.population then
  25.110 +              local max_value = initiative.issue.population
  25.111 +              ui.bargraph{
  25.112 +                max_value = max_value,
  25.113 +                width = 100,
  25.114 +                bars = {
  25.115 +                  { color = "#0a0", value = (initiative.satisfied_supporter_count or 0) },
  25.116 +                  { color = "#bbb", value = (initiative.supporter_count or 0) - (initiative.satisfied_supporter_count or 0) },
  25.117 +                  { color = "#eee", value = max_value - (initiative.supporter_count or 0) },
  25.118 +                }
  25.119 +              }
  25.120 +            else
  25.121 +              slot.put("&nbsp;")
  25.122 +            end
  25.123 +          end
  25.124 +        }
  25.125 +
  25.126 +        ui.container{
  25.127 +          attr = { style = "float: left;"},
  25.128 +          content = function()
  25.129 +            local link_class
  25.130 +            if initiative.revoked then
  25.131 +              link_class = "revoked"
  25.132 +            end
  25.133 +            ui.link{
  25.134 +              attr = { id = link_name, class = link_class },
  25.135 +              content = function()
  25.136 +                local name
  25.137 +                if initiative.name_highlighted then
  25.138 +                  name = encode.highlight(initiative.name_highlighted)
  25.139 +                else
  25.140 +                  name = encode.html(initiative.name)
  25.141 +                end
  25.142 +                slot.put(name)
  25.143 +              end,
  25.144 +              module  = module,
  25.145 +              view    = view,
  25.146 +              id      = id,
  25.147 +              params  = params,
  25.148 +            }
  25.149 +          end
  25.150 +        }
  25.151 +
  25.152 +        if initiative.issue.state == "new" then
  25.153 +          ui.image{
  25.154 +            static = "icons/16/new.png"
  25.155 +          }
  25.156 +        end
  25.157 +        if initiative.is_supporter then
  25.158 +          slot.put("&nbsp;")
  25.159 +          local label = _"You are supporting this initiative"
  25.160 +          ui.image{
  25.161 +            attr = { alt = label, title = label },
  25.162 +            static = "icons/16/thumb_up_green.png"
  25.163 +          }
  25.164 +        end
  25.165 +        if initiative.is_potential_supporter then
  25.166 +          slot.put("&nbsp;")
  25.167 +          local label = _"You are potential supporter of this initiative"
  25.168 +          ui.image{
  25.169 +            attr = { alt = label, title = label },
  25.170 +            static = "icons/16/thumb_up.png"
  25.171 +          }
  25.172 +        end
  25.173 +        if initiative.is_initiator then
  25.174 +          slot.put("&nbsp;")
  25.175 +          local label = _"You are iniator of this initiative"
  25.176 +          ui.image{
  25.177 +            attr = { alt = label, title = label },
  25.178 +            static = "icons/16/user_edit.png"
  25.179 +          }
  25.180 +        end
  25.181 +
  25.182 +        slot.put("<br style='clear: left' />")
  25.183 +      end
  25.184 +    }
  25.185 +  end
  25.186 +}
  25.187 +
  25.188 +if ui.is_partial_loading_enabled() then
  25.189 +  ui.container{
  25.190 +    attr = {
  25.191 +      id = name,
  25.192 +      class = "ui_tabs_accordeon_content",
  25.193 +      style = not expanded and "display: none;" or nil
  25.194 +    },
  25.195 +    content = function()
  25.196 +      ui.container{
  25.197 +        attr = { id = name .. "_content", style = "clear: left;" },
  25.198 +        content = function()
  25.199 +          execute.view{
  25.200 +            module = "initiative",
  25.201 +            view = "show_partial",
  25.202 +            params = {
  25.203 +              initiative = initiative,
  25.204 +              expanded = expanded
  25.205 +            }
  25.206 +          }
  25.207 +        end
  25.208 +      }
  25.209 +    end
  25.210 +  }
  25.211 +end
  25.212 \ No newline at end of file
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/app/main/initiative/_show.lua	Sat Feb 20 22:10:31 2010 +0100
    26.3 @@ -0,0 +1,236 @@
    26.4 +local initiative = param.get("initiative", "table")
    26.5 +local initiator = param.get("initiator", "table")
    26.6 +
    26.7 +util.help("initiative.show")
    26.8 +
    26.9 +if initiative.issue.ranks_available and initiative.admitted then
   26.10 +  local class = initiative.rank == 1 and "admitted_info" or "not_admitted_info"
   26.11 +  ui.container{
   26.12 +    attr = { class = class },
   26.13 +    content = function()
   26.14 +      local max_value = initiative.issue.voter_count
   26.15 +      slot.put("&nbsp;")
   26.16 +      local positive_votes = initiative.positive_votes
   26.17 +      local negative_votes = initiative.negative_votes
   26.18 +      slot.put(_"Yes" .. ": <b>" .. tostring(positive_votes) .. "</b>")
   26.19 +      slot.put(" &middot; ")
   26.20 +      slot.put(_"Abstention" .. ": <b>" .. tostring(max_value - initiative.negative_votes - initiative.positive_votes)  .. "</b>")
   26.21 +      slot.put(" &middot; ")
   26.22 +      slot.put(_"No" .. ": <b>" .. tostring(initiative.negative_votes) .. "</b>")
   26.23 +      slot.put(" &middot; ")
   26.24 +      slot.put("<b>")
   26.25 +      if initiative.rank == 1 then
   26.26 +        slot.put(_"Approved")
   26.27 +      elseif initiative.rank then
   26.28 +        slot.put(_("Not approved (rank #{rank})", { rank = initiative.rank }))
   26.29 +      end
   26.30 +      slot.put("</b>")
   26.31 +    end
   26.32 +  }
   26.33 +end
   26.34 +
   26.35 +if initiative.admitted == false then
   26.36 +  local policy = initiative.issue.policy
   26.37 +  ui.container{
   26.38 +    attr = { class = "not_admitted_info" },
   26.39 +    content = _("This initiative has not been admitted! It failed the quorum of #{quorum}.", { quorum = format.percentage(policy.initiative_quorum_num / policy.initiative_quorum_den) })
   26.40 +  }
   26.41 +end
   26.42 +
   26.43 +local web20 = config.user_tab_mode == "accordeon"
   26.44 +  or config.user_tab_mode == "accordeon_first_expanded"
   26.45 +  or config.user_tab_mode == "accordeon_all_expanded"
   26.46 +
   26.47 +if not web20 and initiative.issue.state == "cancelled" then
   26.48 +  local policy = initiative.issue.policy
   26.49 +  ui.container{
   26.50 +    attr = { class = "not_admitted_info" },
   26.51 +    content = _("This issue has been cancelled. It failed the quorum of #{quorum}.", { quorum = format.percentage(policy.issue_quorum_num / policy.issue_quorum_den) })
   26.52 +  }
   26.53 +end
   26.54 +
   26.55 +if initiative.revoked then
   26.56 +  ui.container{
   26.57 +    attr = { class = "revoked_info" },
   26.58 +    content = function()
   26.59 +      slot.put(_("This initiative has been revoked at #{revoked}", { revoked = format.timestamp(initiative.revoked) }))
   26.60 +      local suggested_initiative = initiative.suggested_initiative
   26.61 +      if suggested_initiative then
   26.62 +        slot.put("<br /><br />")
   26.63 +        slot.put(_("The initiators suggest to support the following initiative:"))
   26.64 +        slot.put(" ")
   26.65 +        ui.link{
   26.66 +          content = _("Issue ##{id}", { id = suggested_initiative.issue.id } ) .. ": " .. encode.html(suggested_initiative.name),
   26.67 +          module = "initiative",
   26.68 +          view = "show",
   26.69 +          id = suggested_initiative.id
   26.70 +        }
   26.71 +      end
   26.72 +    end
   26.73 +  }
   26.74 +end
   26.75 +
   26.76 +if initiator and initiator.accepted == nil then
   26.77 +  ui.container{
   26.78 +    attr = { class = "initiator_invite_info" },
   26.79 +    content = function()
   26.80 +      slot.put(_"You are invited to become initiator of this initiative.")
   26.81 +      slot.put(" ")
   26.82 +      ui.link{
   26.83 +        image  = { static = "icons/16/tick.png" },
   26.84 +        text   = _"Accept invitation",
   26.85 +        module = "initiative",
   26.86 +        action = "accept_invitation",
   26.87 +        id     = initiative.id,
   26.88 +        routing = {
   26.89 +          default = {
   26.90 +            mode = "redirect",
   26.91 +            module = request.get_module(),
   26.92 +            view = request.get_view(),
   26.93 +            id = param.get_id_cgi(),
   26.94 +            params = param.get_all_cgi()
   26.95 +          }
   26.96 +        }
   26.97 +      }
   26.98 +      slot.put(" ")
   26.99 +      ui.link{
  26.100 +        image  = { static = "icons/16/cross.png" },
  26.101 +        text   = _"Refuse invitation",
  26.102 +        module = "initiative",
  26.103 +        action = "reject_initiator_invitation",
  26.104 +        params = {
  26.105 +          initiative_id = initiative.id,
  26.106 +          member_id = app.session.member.id
  26.107 +        },
  26.108 +        routing = {
  26.109 +          default = {
  26.110 +            mode = "redirect",
  26.111 +            module = request.get_module(),
  26.112 +            view = request.get_view(),
  26.113 +            id = param.get_id_cgi(),
  26.114 +            params = param.get_all_cgi()
  26.115 +          }
  26.116 +        }
  26.117 +      }
  26.118 +    end
  26.119 +  }
  26.120 +  slot.put("<br />")
  26.121 +end
  26.122 +
  26.123 +
  26.124 +local supporter = app.session.member:get_reference_selector("supporters")
  26.125 +  :add_where{ "initiative_id = ?", initiative.id }
  26.126 +  :optional_object_mode()
  26.127 +  :exec()
  26.128 +
  26.129 +if supporter and not initiative.issue.closed then
  26.130 +  local old_draft_id = supporter.draft_id
  26.131 +  local new_draft_id = initiative.current_draft.id
  26.132 +  if old_draft_id ~= new_draft_id then
  26.133 +    ui.container{
  26.134 +      attr = { class = "draft_updated_info" },
  26.135 +      content = function()
  26.136 +        slot.put(_"The draft of this initiative has been updated!")
  26.137 +        slot.put(" ")
  26.138 +        ui.link{
  26.139 +          content = _"Show diff",
  26.140 +          module = "draft",
  26.141 +          view = "diff",
  26.142 +          params = {
  26.143 +            old_draft_id = old_draft_id,
  26.144 +            new_draft_id = new_draft_id
  26.145 +          }
  26.146 +        }
  26.147 +        slot.put(" ")
  26.148 +        ui.link{
  26.149 +          text   = _"Refresh support to current draft",
  26.150 +          module = "initiative",
  26.151 +          action = "add_support",
  26.152 +          id     = initiative.id,
  26.153 +          routing = {
  26.154 +            default = {
  26.155 +              mode = "redirect",
  26.156 +              module = "initiative",
  26.157 +              view = "show",
  26.158 +              id = initiative.id
  26.159 +            }
  26.160 +          }
  26.161 +        }
  26.162 +      end
  26.163 +    }
  26.164 +  end
  26.165 +end
  26.166 +
  26.167 +
  26.168 +
  26.169 +ui.container{
  26.170 +  attr = {
  26.171 +    id = "initiative_" .. tostring(initiative.id) .. "_support"
  26.172 +  },
  26.173 +  content = function()
  26.174 +    execute.view{
  26.175 +      module = "initiative",
  26.176 +      view = "show_support",
  26.177 +      params = {
  26.178 +        initiative = initiative
  26.179 +      }
  26.180 +    }
  26.181 +  end
  26.182 +}
  26.183 +
  26.184 +if (initiative.discussion_url and #initiative.discussion_url > 0)
  26.185 +  or (initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked) then
  26.186 +  ui.container{
  26.187 +    attr = { class = "vertical" },
  26.188 +    content = function()
  26.189 +      ui.container{
  26.190 +        attr = { class = "ui_field_label" },
  26.191 +        content = _"Discussion with initiators"
  26.192 +      }
  26.193 +      ui.tag{
  26.194 +        tag = "span",
  26.195 +        content = function()
  26.196 +          if initiative.discussion_url:find("^https?://") then
  26.197 +            if initiative.discussion_url and #initiative.discussion_url > 0 then
  26.198 +              ui.link{
  26.199 +                attr = {
  26.200 +                  class = "actions",
  26.201 +                  target = "_blank",
  26.202 +                  title = initiative.discussion_url
  26.203 +                },
  26.204 +                content = function()
  26.205 +                  slot.put(encode.html(initiative.discussion_url))
  26.206 +                end,
  26.207 +                external = initiative.discussion_url
  26.208 +              }
  26.209 +            end
  26.210 +          else
  26.211 +            slot.put(encode.html(initiative.discussion_url))
  26.212 +          end
  26.213 +          slot.put(" ")
  26.214 +          if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
  26.215 +            ui.link{
  26.216 +              attr   = { class = "actions" },
  26.217 +              text   = _"(change URL)",
  26.218 +              module = "initiative",
  26.219 +              view   = "edit",
  26.220 +              id     = initiative.id
  26.221 +            }
  26.222 +          end
  26.223 +        end
  26.224 +      }
  26.225 +    end
  26.226 +  }
  26.227 +end
  26.228 +
  26.229 +
  26.230 +
  26.231 +execute.view{
  26.232 +  module = "initiative",
  26.233 +  view = "show_tab",
  26.234 +  params = {
  26.235 +    initiative = initiative,
  26.236 +    initiator = initiator
  26.237 +  }
  26.238 +}
  26.239 +
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/app/main/initiative/_show_voting.lua	Sat Feb 20 22:10:31 2010 +0100
    27.3 @@ -0,0 +1,112 @@
    27.4 +local initiative = param.get("initiative", "table")
    27.5 +
    27.6 +
    27.7 +local battled_initiatives = Initiative:new_selector()
    27.8 +  :add_field("winning_battle.count", "winning_count")
    27.9 +  :add_field("losing_battle.count", "losing_count")
   27.10 +  :join("battle", "winning_battle", { "winning_battle.winning_initiative_id = ? AND winning_battle.losing_initiative_id = initiative.id", initiative.id })
   27.11 +  :join("battle", "losing_battle", { "losing_battle.losing_initiative_id = ? AND losing_battle.winning_initiative_id = initiative.id", initiative.id })
   27.12 +  :add_order_by("rank")
   27.13 +  :exec()
   27.14 +
   27.15 +local number_of_initiatives = Initiative:new_selector()
   27.16 +  :add_where{ "issue_id = ?", initiative.issue_id }
   27.17 +  :add_where("admitted")
   27.18 +  :count()
   27.19 +
   27.20 +if initiative.revoked then
   27.21 +  slot.put(_"Not voted (revoked from initiator)")
   27.22 +elseif initiative.admitted == false then
   27.23 +  slot.put(_"Not voted (not admitted)")
   27.24 +else
   27.25 +  if number_of_initiatives > 1 then
   27.26 +    ui.container{
   27.27 +      attr = { class = "heading first" },
   27.28 +      content = _"This initiative compared to alternative initiatives"
   27.29 +    }
   27.30 +
   27.31 +    ui.list{
   27.32 +      records = battled_initiatives,
   27.33 +      columns = {
   27.34 +        {
   27.35 +          content = function()
   27.36 +            slot.put(_"This initiative")
   27.37 +          end
   27.38 +        },
   27.39 +        {
   27.40 +          content = function(record)
   27.41 +            local population = initiative.issue.voter_count
   27.42 +            local value = record.winning_count
   27.43 +            ui.bargraph{
   27.44 +              class = "bargraph bargraph50",
   27.45 +              max_value = population,
   27.46 +              width = 50,
   27.47 +              bars = {
   27.48 +                { color = "#aaa", value = population - value },
   27.49 +                { color = "#444", value = value },
   27.50 +              }
   27.51 +            }
   27.52 +          end
   27.53 +        },
   27.54 +        {
   27.55 +          content = function(record)
   27.56 +            slot.put(record.winning_count)
   27.57 +          end
   27.58 +        },
   27.59 +        {
   27.60 +          content = function(record)
   27.61 +            if record.winning_count == record.losing_count then
   27.62 +              ui.image{ static = "icons/16/bullet_blue.png" }
   27.63 +            elseif record.winning_count > record.losing_count then
   27.64 +              ui.image{ static = "icons/16/resultset_previous.png" }
   27.65 +            else
   27.66 +              ui.image{ static = "icons/16/resultset_next.png" }
   27.67 +            end
   27.68 +          end
   27.69 +        },
   27.70 +        {
   27.71 +          field_attr = { style = "text-align: right;" },
   27.72 +          content = function(record)
   27.73 +            slot.put(record.losing_count)
   27.74 +          end
   27.75 +        },
   27.76 +        {
   27.77 +          content = function(record)
   27.78 +            local population = initiative.issue.voter_count
   27.79 +            local value = record.losing_count
   27.80 +            ui.bargraph{
   27.81 +              class = "bargraph bargraph50",
   27.82 +              max_value = population,
   27.83 +              width = 50,
   27.84 +              bars = {
   27.85 +                { color = "#444", value = value },
   27.86 +                { color = "#aaa", value = population - value },
   27.87 +              }
   27.88 +            }
   27.89 +          end
   27.90 +        },
   27.91 +        {
   27.92 +          name = "name"
   27.93 +        }
   27.94 +      }
   27.95 +    }
   27.96 +  end
   27.97 +
   27.98 +  ui.container{
   27.99 +    attr = { class = "heading" },
  27.100 +    content = _"Member voting"
  27.101 +  }
  27.102 +
  27.103 +  execute.view{
  27.104 +    module = "member",
  27.105 +    view = "_list",
  27.106 +    params = {
  27.107 +      initiative = initiative,
  27.108 +      members_selector =  initiative.issue:get_reference_selector("direct_voters")
  27.109 +        :left_join("vote", nil, { "vote.initiative_id = ? AND vote.member_id = member.id", initiative.id })
  27.110 +        :add_field("direct_voter.weight as voter_weight")
  27.111 +        :add_field("coalesce(vote.grade, 0) as grade")
  27.112 +    }
  27.113 +  }
  27.114 +
  27.115 +end
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/app/main/initiative/_suggestions.lua	Sat Feb 20 22:10:31 2010 +0100
    28.3 @@ -0,0 +1,26 @@
    28.4 +local initiative = param.get("initiative", "table")
    28.5 +
    28.6 +if not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
    28.7 +  ui.link{
    28.8 +    content = function()
    28.9 +      ui.image{ static = "icons/16/comment_add.png" }
   28.10 +      slot.put(_"Add new suggestion")
   28.11 +    end,
   28.12 +    module = "suggestion",
   28.13 +    view = "new",
   28.14 +    params = {
   28.15 +      initiative_id = initiative.id
   28.16 +    }
   28.17 +  }
   28.18 +end
   28.19 +
   28.20 +execute.view{
   28.21 +  module = "suggestion",
   28.22 +  view = "_list",
   28.23 +  params = {
   28.24 +    initiative = initiative,
   28.25 +    suggestions_selector = initiative:get_reference_selector("suggestions"),
   28.26 +    tab_id = param.get("tab_id")
   28.27 +  }
   28.28 +}
   28.29 +
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/app/main/initiative/list_rss.lua	Sat Feb 20 22:10:31 2010 +0100
    29.3 @@ -0,0 +1,29 @@
    29.4 +slot.set_layout("atom")
    29.5 +
    29.6 +request.force_absolute_baseurl()
    29.7 +
    29.8 +local initiatives = Initiative:new_selector()
    29.9 +  :add_order_by("id DESC")
   29.10 +  :limit(25)
   29.11 +  :exec()
   29.12 +
   29.13 +for i, initiative in ipairs(initiatives) do
   29.14 +  ui.tag{
   29.15 +    tag = "entry",
   29.16 +    content = function()
   29.17 +      ui.tag{ tag = "category", attr = { term = initiative.issue.area.name } }
   29.18 +      ui.tag{ tag = "author", content = initiative.current_draft.author.name }
   29.19 +      ui.tag{ tag = "title", content = initiative.name }
   29.20 +      ui.tag{ tag = "link", attr = { 
   29.21 +        href = encode.url{
   29.22 +          module = "initiative",
   29.23 +          view = "show",
   29.24 +          id = initiative.id
   29.25 +        }
   29.26 +      } }
   29.27 +      ui.tag{ tag = "id",  content = "initiative_" .. tostring(initiative_id) }
   29.28 +      ui.tag{ tag = "updated",  content = tostring(initiative.created) }
   29.29 +      ui.tag{ tag = "content",  content = initiative.current_draft.draft }
   29.30 +    end
   29.31 +  }
   29.32 +end
   29.33 \ No newline at end of file
    30.1 --- a/app/main/initiative/new.lua	Tue Feb 02 00:31:06 2010 +0100
    30.2 +++ b/app/main/initiative/new.lua	Sat Feb 20 22:10:31 2010 +0100
    30.3 @@ -12,7 +12,7 @@
    30.4  end
    30.5  
    30.6  if issue_id then
    30.7 -  slot.put_into("title", _"Add new initiative to issue")
    30.8 +  slot.put_into("title", _"Add alternative initiative to issue")
    30.9  else
   30.10    slot.put_into("title", _"Create new issue")
   30.11  end
    31.1 --- a/app/main/initiative/show.lua	Tue Feb 02 00:31:06 2010 +0100
    31.2 +++ b/app/main/initiative/show.lua	Sat Feb 20 22:10:31 2010 +0100
    31.3 @@ -1,535 +1,36 @@
    31.4 -local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
    31.5 -
    31.6 -slot.select("actions", function()
    31.7 -  ui.link{
    31.8 -    content = function()
    31.9 -      ui.image{ static = "icons/16/script.png" }
   31.10 -      slot.put(_"Show all initiatives")
   31.11 -    end,
   31.12 -    module = "issue",
   31.13 -    view = "show",
   31.14 -    id = initiative.issue.id
   31.15 -  }
   31.16 -end)
   31.17 -
   31.18 -execute.view{
   31.19 -  module = "issue",
   31.20 -  view = "_show_head",
   31.21 -  params = { issue = initiative.issue }
   31.22 -}
   31.23 -
   31.24 -if initiative.revoked then
   31.25 -  ui.container{
   31.26 -    attr = { class = "revoked_info" },
   31.27 -    content = function()
   31.28 -      slot.put(_("This initiative has been revoked at #{revoked}", { revoked = format.timestamp(initiative.revoked) }))
   31.29 -      local suggested_initiative = initiative.suggested_initiative
   31.30 -      if suggested_initiative then
   31.31 -        slot.put("<br /><br />")
   31.32 -        slot.put(_("The initiators suggest to support the following initiative:"))
   31.33 -        slot.put("<br />")
   31.34 -        ui.link{
   31.35 -          content = _("Issue ##{id}", { id = suggested_initiative.issue.id } ) .. ": " .. encode.html(suggested_initiative.name),
   31.36 -          module = "initiative",
   31.37 -          view = "show",
   31.38 -          id = suggested_initiative.id
   31.39 -        }
   31.40 -      end
   31.41 -    end
   31.42 -  }
   31.43 -end
   31.44 -
   31.45 -local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
   31.46 -
   31.47 ---slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(initiative.id) .. '.rss" />')
   31.48 -
   31.49 -
   31.50 -slot.select("actions", function()
   31.51 -  if not initiative.issue.fully_frozen and not initiative.issue.closed then
   31.52 -    ui.link{
   31.53 -      attr = { class = "action" },
   31.54 -      content = function()
   31.55 -        ui.image{ static = "icons/16/script_add.png" }
   31.56 -        slot.put(_"Create alternative initiative")
   31.57 -      end,
   31.58 -      module = "initiative",
   31.59 -      view = "new",
   31.60 -      params = { issue_id = initiative.issue.id }
   31.61 -    }
   31.62 -  end
   31.63 -end)
   31.64 -
   31.65 -slot.put_into("sub_title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) ))
   31.66 -
   31.67 -slot.select("support", function()
   31.68 -  ui.container{
   31.69 -    attr = { class = "actions" },
   31.70 -    content = function()
   31.71 -      execute.view{
   31.72 -        module = "supporter",
   31.73 -        view = "_show_box",
   31.74 -        params = { initiative = initiative }
   31.75 -      }
   31.76 -      if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
   31.77 -        ui.link{
   31.78 -          attr = { class = "action", style = "float: left;" },
   31.79 -          content = function()
   31.80 -            ui.image{ static = "icons/16/script_delete.png" }
   31.81 -            slot.put(_"Revoke initiative")
   31.82 -          end,
   31.83 -          module = "initiative",
   31.84 -          view = "revoke",
   31.85 -          id = initiative.id
   31.86 -        }
   31.87 -      end
   31.88 -    end
   31.89 -  }
   31.90 -end)
   31.91 -
   31.92 -util.help("initiative.show")
   31.93 +local initiative = param.get("initiative", "table")
   31.94  
   31.95 -if initiator and initiator.accepted == nil then
   31.96 -  ui.container{
   31.97 -    attr = { class = "initiator_invite_info" },
   31.98 -    content = function()
   31.99 -      slot.put(_"You are invited to become initiator of this initiative.")
  31.100 -      slot.put(" ")
  31.101 -      ui.link{
  31.102 -        content = function()
  31.103 -          ui.image{ static = "icons/16/tick.png" }
  31.104 -          slot.put(_"Accept invitation")
  31.105 -        end,
  31.106 -        module = "initiative",
  31.107 -        action = "accept_invitation",
  31.108 -        id = initiative.id,
  31.109 -        routing = {
  31.110 -          default = {
  31.111 -            mode = "redirect",
  31.112 -            module = request.get_module(),
  31.113 -            view = request.get_view(),
  31.114 -            id = param.get_id_cgi(),
  31.115 -            params = param.get_all_cgi()
  31.116 -          }
  31.117 -        }
  31.118 -      }
  31.119 -      slot.put(" ")
  31.120 -      ui.link{
  31.121 -        content = function()
  31.122 -          ui.image{ static = "icons/16/cross.png" }
  31.123 -          slot.put(_"Refuse invitation")
  31.124 -        end,
  31.125 -        module = "initiative",
  31.126 -        action = "reject_initiator_invitation",
  31.127 -        params = {
  31.128 -          initiative_id = initiative.id,
  31.129 -          member_id = app.session.member.id
  31.130 -        },
  31.131 -        routing = {
  31.132 -          default = {
  31.133 -            mode = "redirect",
  31.134 -            module = request.get_module(),
  31.135 -            view = request.get_view(),
  31.136 -            id = param.get_id_cgi(),
  31.137 -            params = param.get_all_cgi()
  31.138 -          }
  31.139 -        }
  31.140 -      }
  31.141 -    end
  31.142 -  }
  31.143 -  slot.put("<br />")
  31.144 -end
  31.145 -
  31.146 -if (initiative.discussion_url and #initiative.discussion_url > 0)
  31.147 -  or (initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked) then
  31.148 -  ui.container{
  31.149 -    attr = { class = "vertical" },
  31.150 -    content = function()
  31.151 -      ui.container{
  31.152 -        attr = { class = "ui_field_label" },
  31.153 -        content = _"Discussion with initiators"
  31.154 -      }
  31.155 -      ui.tag{
  31.156 -        tag = "span",
  31.157 -        content = function()
  31.158 -          if initiative.discussion_url:find("^https?://") then
  31.159 -            if initiative.discussion_url and #initiative.discussion_url > 0 then
  31.160 -              ui.link{
  31.161 -                attr = {
  31.162 -                  class = "actions",
  31.163 -                  target = "_blank",
  31.164 -                  title = initiative.discussion_url
  31.165 -                },
  31.166 -                content = function()
  31.167 -                  slot.put(encode.html(initiative.discussion_url))
  31.168 -                end,
  31.169 -                external = initiative.discussion_url
  31.170 -              }
  31.171 -            end
  31.172 -          else
  31.173 -            slot.put(encode.html(initiative.discussion_url))
  31.174 -          end
  31.175 -          slot.put(" ")
  31.176 -          if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
  31.177 -            ui.link{
  31.178 -              attr = { class = "actions" },
  31.179 -              content = _"(change URL)",
  31.180 -              module = "initiative",
  31.181 -              view = "edit",
  31.182 -              id = initiative.id
  31.183 -            }
  31.184 -          end
  31.185 -        end
  31.186 -      }
  31.187 -    end
  31.188 -  }
  31.189 +if not initiative then
  31.190 +  initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
  31.191  end
  31.192  
  31.193 -
  31.194 -ui.container{
  31.195 -  attr = {  id = "add_suggestion_form", class = "hidden_inline_form" },
  31.196 -  content = function()
  31.197 -
  31.198 -    ui.link{
  31.199 -      content = _"Close",
  31.200 -      attr = {
  31.201 -        onclick = "document.getElementById('add_suggestion_form').style.display='none';return(false)",
  31.202 -        style = "float: right;"
  31.203 -      }
  31.204 -    }
  31.205 -
  31.206 -    ui.field.text{ attr = { class = "head" }, value = _"Add new suggestion" }
  31.207 -
  31.208 -
  31.209 -    ui.form{
  31.210 -      module = "suggestion",
  31.211 -      action = "add",
  31.212 -      params = { initiative_id = initiative.id },
  31.213 -      routing = {
  31.214 -        default = {
  31.215 -          mode = "redirect",
  31.216 -          module = "initiative",
  31.217 -          view = "show",
  31.218 -          id = initiative.id,
  31.219 -          params = { tab = "suggestion" }
  31.220 -        }
  31.221 -      },
  31.222 -      attr = { class = "vertical" },
  31.223 -      content = function()
  31.224 -        local supported = Supporter:by_pk(initiative.id, app.session.member.id) and true or false
  31.225 -        if not supported then
  31.226 -          ui.field.text{
  31.227 -            attr = { class = "warning" },
  31.228 -            value = _"You are currently not supporting this initiative. By adding suggestions to this initiative you will automatically become a potential supporter."
  31.229 -          }
  31.230 -        end
  31.231 -        ui.field.text{ label = _"Title (80 chars max)",        name = "name" }
  31.232 -        ui.field.text{ label = _"Description", name = "description", multiline = true }
  31.233 -        ui.field.select{ 
  31.234 -          label = _"Degree", 
  31.235 -          name = "degree",
  31.236 -          foreign_records = { 
  31.237 -            { id =  1, name = _"should"},
  31.238 -            { id =  2, name = _"must"},
  31.239 -          },
  31.240 -          foreign_id = "id",
  31.241 -          foreign_name = "name"
  31.242 -        }
  31.243 -        ui.submit{ text = _"Commit suggestion" }
  31.244 -      end
  31.245 -    }
  31.246 -  end
  31.247 -}
  31.248 -
  31.249 -local supporter = app.session.member:get_reference_selector("supporters")
  31.250 -  :add_where{ "initiative_id = ?", initiative.id }
  31.251 -  :optional_object_mode()
  31.252 -  :exec()
  31.253 -
  31.254 -if supporter then
  31.255 -  local old_draft_id = supporter.draft_id
  31.256 -  local new_draft_id = initiative.current_draft.id
  31.257 -  if old_draft_id ~= new_draft_id then
  31.258 -    ui.container{
  31.259 -      attr = { class = "draft_updated_info" },
  31.260 -      content = function()
  31.261 -        slot.put(_"The draft of this initiative has been updated!")
  31.262 -        slot.put(" ")
  31.263 -        ui.link{
  31.264 -          content = _"Show diff",
  31.265 -          module = "draft",
  31.266 -          view = "diff",
  31.267 -          params = {
  31.268 -            old_draft_id = old_draft_id,
  31.269 -            new_draft_id = new_draft_id
  31.270 -          }
  31.271 -        }
  31.272 -        slot.put(" ")
  31.273 -        ui.link{
  31.274 -          content = _"Refresh support to current draft",
  31.275 -          module = "initiative",
  31.276 -          action = "add_support",
  31.277 -          id = initiative.id,
  31.278 -          routing = {
  31.279 -            default = {
  31.280 -              mode = "redirect",
  31.281 -              module = "initiative",
  31.282 -              view = "show",
  31.283 -              id = initiative.id
  31.284 -            }
  31.285 -          }
  31.286 -        }
  31.287 -      end
  31.288 -    }
  31.289 -  end
  31.290 -end
  31.291 -
  31.292 -
  31.293 -local current_draft_name = _"Current draft"
  31.294 -if initiative.issue.half_frozen then
  31.295 -  current_draft_name = _"Voting proposal"
  31.296 -end
  31.297 -
  31.298 -if initiative.issue.state == "finished" then
  31.299 -  current_draft_name = _"Voted proposal"
  31.300 -end
  31.301 -
  31.302 -local tabs = {
  31.303 -  {
  31.304 -    name = "current_draft",
  31.305 -    label = current_draft_name,
  31.306 -    content = function()
  31.307 -      if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
  31.308 -        ui.link{
  31.309 -          content = function()
  31.310 -            ui.image{ static = "icons/16/script_add.png" }
  31.311 -            slot.put(_"Edit draft")
  31.312 -          end,
  31.313 -          module = "draft",
  31.314 -          view = "new",
  31.315 -          params = { initiative_id = initiative.id }
  31.316 -        }
  31.317 -      end
  31.318 -      execute.view{ module = "draft", view = "_show", params = { draft = initiative.current_draft } }
  31.319 -    end
  31.320 -  }
  31.321 -}
  31.322 -
  31.323 -if initiative.issue.ranks_available then
  31.324 -  tabs[#tabs+1] = {
  31.325 -    name = "voter",
  31.326 -    label = _"Voter",
  31.327 -    content = function()
  31.328 -      execute.view{
  31.329 -        module = "member",
  31.330 -        view = "_list",
  31.331 -        params = {
  31.332 -          initiative = initiative,
  31.333 -          members_selector =  initiative.issue:get_reference_selector("direct_voters")
  31.334 -            :left_join("vote", nil, { "vote.initiative_id = ? AND vote.member_id = member.id", initiative.id })
  31.335 -            :add_field("direct_voter.weight as voter_weight")
  31.336 -            :add_field("coalesce(vote.grade, 0) as grade")
  31.337 -        }
  31.338 -      }
  31.339 -    end
  31.340 -  }
  31.341 -end
  31.342 -
  31.343 -local suggestion_count = initiative:get_reference_selector("suggestions"):count()
  31.344 -
  31.345 -tabs[#tabs+1] = {
  31.346 -  name = "suggestion",
  31.347 -  label = _"Suggestions" .. " (" .. tostring(suggestion_count) .. ")",
  31.348 -  content = function()
  31.349 -    execute.view{
  31.350 -      module = "suggestion",
  31.351 -      view = "_list",
  31.352 -      params = {
  31.353 -        initiative = initiative,
  31.354 -        suggestions_selector = initiative:get_reference_selector("suggestions")
  31.355 -      }
  31.356 +if request.get_json_request_slots() then
  31.357 +  execute.view{
  31.358 +    module = "initiative",
  31.359 +    view   = "show_partial",
  31.360 +    params = {
  31.361 +      initiative = initiative
  31.362      }
  31.363 -    slot.put("<br />")
  31.364 -    if not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
  31.365 -      ui.link{
  31.366 -        content = function()
  31.367 -          ui.image{ static = "icons/16/comment_add.png" }
  31.368 -          slot.put(_"Add new suggestion")
  31.369 -        end,
  31.370 -        attr = { onclick = "document.getElementById('add_suggestion_form').style.display='block';return(false)" },
  31.371 -        static = "#"
  31.372 -      }
  31.373 -    end
  31.374 -  end
  31.375 -}
  31.376 -
  31.377 -local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
  31.378 -          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
  31.379 -          :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")
  31.380 -          :add_field("direct_interest_snapshot.weight")
  31.381 -          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
  31.382 -          :add_where("direct_supporter_snapshot.satisfied")
  31.383 -
  31.384 -local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
  31.385 -local direct_satisfied_supporter_count = tmp.count
  31.386 -local indirect_satisfied_supporter_count = (tmp.weight or 0) - tmp.count
  31.387 -
  31.388 -local count_string
  31.389 -if indirect_satisfied_supporter_count > 0 then
  31.390 -  count_string = "(" .. tostring(direct_satisfied_supporter_count) .. "+" .. tostring(indirect_satisfied_supporter_count) .. ")"
  31.391 -else
  31.392 -  count_string = "(" .. tostring(direct_satisfied_supporter_count) .. ")"
  31.393 -end
  31.394 -
  31.395 -tabs[#tabs+1] = {
  31.396 -  name = "satisfied_supporter",
  31.397 -  label = _"Supporter" .. " " .. count_string,
  31.398 -  content = function()
  31.399 -    execute.view{
  31.400 -      module = "member",
  31.401 -      view = "_list",
  31.402 -      params = {
  31.403 -        initiative = initiative,
  31.404 -        members_selector = members_selector
  31.405 -      }
  31.406 -    }
  31.407 -  end
  31.408 -}
  31.409 -
  31.410 -local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
  31.411 -          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
  31.412 -          :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")
  31.413 -          :add_field("direct_interest_snapshot.weight")
  31.414 -          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
  31.415 -          :add_where("NOT direct_supporter_snapshot.satisfied")
  31.416 -
  31.417 -local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
  31.418 -local direct_potential_supporter_count = tmp.count
  31.419 -local indirect_potential_supporter_count = (tmp.weight or 0) - tmp.count
  31.420 -
  31.421 -local count_string
  31.422 -if indirect_potential_supporter_count > 0 then
  31.423 -  count_string = "(" .. tostring(direct_potential_supporter_count) .. "+" .. tostring(indirect_potential_supporter_count) .. ")"
  31.424 -else
  31.425 -  count_string = "(" .. tostring(direct_potential_supporter_count) .. ")"
  31.426 -end
  31.427 -
  31.428 -tabs[#tabs+1] = {
  31.429 -  name = "supporter",
  31.430 -  label = _"Potential supporter" .. " " .. count_string,
  31.431 -  content = function()
  31.432 -    execute.view{
  31.433 -      module = "member",
  31.434 -      view = "_list",
  31.435 -      params = {
  31.436 -        initiative = initiative,
  31.437 -        members_selector = members_selector
  31.438 -      }
  31.439 +  }
  31.440 +elseif
  31.441 +  config.user_tab_mode == "accordeon" or
  31.442 +  config.user_tab_mode == "accordeon_first_expanded" or
  31.443 +  config.user_tab_mode == "accordeon_all_expanded"
  31.444 +then
  31.445 +  execute.view{
  31.446 +    module = "issue",
  31.447 +    view   = "show",
  31.448 +    id     = initiative.issue_id,
  31.449 +    params = {
  31.450 +      for_initiative_id = initiative.id
  31.451      }
  31.452 -  end
  31.453 -}
  31.454 -
  31.455 -local initiator_count = initiative:get_reference_selector("initiators"):add_where("accepted"):count()
  31.456 -
  31.457 -tabs[#tabs+1] = {
  31.458 -  name = "initiators",
  31.459 -  label = _"Initiators" .. " (" .. tostring(initiator_count) .. ")",
  31.460 -  content = function()
  31.461 -     if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
  31.462 -      ui.link{
  31.463 -        attr = { class = "action" },
  31.464 -        content = function()
  31.465 -          ui.image{ static = "icons/16/user_add.png" }
  31.466 -          slot.put(_"Invite initiator")
  31.467 -        end,
  31.468 -        module = "initiative",
  31.469 -        view = "add_initiator",
  31.470 -        params = { initiative_id = initiative.id }
  31.471 -      }
  31.472 -      if initiator_count > 1 then
  31.473 -        ui.link{
  31.474 -          content = function()
  31.475 -            ui.image{ static = "icons/16/user_delete.png" }
  31.476 -            slot.put(_"Remove initiator")
  31.477 -          end,
  31.478 -          module = "initiative",
  31.479 -          view = "remove_initiator",
  31.480 -          params = { initiative_id = initiative.id }
  31.481 -        }
  31.482 -      end
  31.483 -    end
  31.484 -    if initiator and initiator.accepted == false then
  31.485 -        ui.link{
  31.486 -          content = function()
  31.487 -            ui.image{ static = "icons/16/user_delete.png" }
  31.488 -            slot.put(_"Cancel refuse of invitation")
  31.489 -          end,
  31.490 -          module = "initiative",
  31.491 -          action = "remove_initiator",
  31.492 -          params = {
  31.493 -            initiative_id = initiative.id,
  31.494 -            member_id = app.session.member.id
  31.495 -          },
  31.496 -          routing = {
  31.497 -            ok = {
  31.498 -              mode = "redirect",
  31.499 -              module = "initiative",
  31.500 -              view = "show",
  31.501 -              id = initiative.id
  31.502 -            }
  31.503 -          }
  31.504 -        }
  31.505 -    end
  31.506 -    local members_selector = initiative:get_reference_selector("initiating_members")
  31.507 -      :add_field("initiator.accepted", "accepted")
  31.508 -    if not (initiator and initiator.accepted) then
  31.509 -      members_selector:add_where("accepted")
  31.510 -    end
  31.511 -    execute.view{
  31.512 -      module = "member",
  31.513 -      view = "_list",
  31.514 -      params = {
  31.515 -        members_selector = members_selector,
  31.516 -        initiator = initiator
  31.517 -      }
  31.518 +  }
  31.519 +else
  31.520 +  execute.view{
  31.521 +    module = "initiative",
  31.522 +    view   = "show_static",
  31.523 +    params = {
  31.524 +      initiative = initiative
  31.525      }
  31.526 -  end
  31.527 -}
  31.528 -
  31.529 -local drafts_count = initiative:get_reference_selector("drafts"):count()
  31.530 -
  31.531 -tabs[#tabs+1] = {
  31.532 -  name = "drafts",
  31.533 -  label = _"Draft history" .. " (" .. tostring(drafts_count) .. ")",
  31.534 -  content = function()
  31.535 -    execute.view{ module = "draft", view = "_list", params = { drafts = initiative.drafts } }
  31.536 -  end
  31.537 -}
  31.538 -
  31.539 -tabs[#tabs+1] = {
  31.540 -  name = "details",
  31.541 -  label = _"Details",
  31.542 -  content = function()
  31.543 -    ui.form{
  31.544 -      attr = { class = "vertical" },
  31.545 -      record = initiative,
  31.546 -      readonly = true,
  31.547 -      content = function()
  31.548 -        ui.field.text{ label = _"Issue policy", value = initiative.issue.policy.name }
  31.549 -        ui.field.text{
  31.550 -          label = _"Created at",
  31.551 -          value = tostring(initiative.created)
  31.552 -        }
  31.553 -        ui.field.text{
  31.554 -          label = _"Created at",
  31.555 -          value = format.timestamp(initiative.created)
  31.556 -        }
  31.557 ---         ui.field.date{ label = _"Revoked at", name = "revoked" }
  31.558 -        ui.field.boolean{ label = _"Admitted", name = "admitted" }
  31.559 -      end
  31.560 -    }
  31.561 -  end
  31.562 -}
  31.563 -
  31.564 -
  31.565 -ui.tabs(tabs)
  31.566 -
  31.567 +  }
  31.568 +end
  31.569 \ No newline at end of file
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/app/main/initiative/show_partial.lua	Sat Feb 20 22:10:31 2010 +0100
    32.3 @@ -0,0 +1,31 @@
    32.4 +local initiative = param.get("initiative", "table")
    32.5 +local expanded = param.get("expanded", atom.boolean)
    32.6 +
    32.7 +if not initiative then
    32.8 +  initiative = Initiative:by_id(param.get_id())
    32.9 +  expanded = true
   32.10 +end
   32.11 +
   32.12 +-- TODO performance
   32.13 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
   32.14 +
   32.15 +ui.partial{
   32.16 +  module = "initiative",
   32.17 +  view = "show",
   32.18 +  id = initiative.id,
   32.19 +  target = "initiative_content_" .. tostring(initiative.id) .. "_content",
   32.20 +  content = function()
   32.21 +    if expanded then
   32.22 +      execute.view{
   32.23 +        module = "initiative",
   32.24 +        view = "_show",
   32.25 +        params = {
   32.26 +          initiative = initiative,
   32.27 +          initiator = initiator
   32.28 +        }
   32.29 +      }
   32.30 +    else
   32.31 +      slot.put("&nbsp;")
   32.32 +    end
   32.33 +  end
   32.34 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/app/main/initiative/show_static.lua	Sat Feb 20 22:10:31 2010 +0100
    33.3 @@ -0,0 +1,49 @@
    33.4 +local initiative = param.get("initiative", "table")
    33.5 +
    33.6 +if not initiative then
    33.7 +  initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
    33.8 +end
    33.9 +
   33.10 +slot.select("actions", function()
   33.11 +  ui.link{
   33.12 +    content = function()
   33.13 +      ui.image{ static = "icons/16/script.png" }
   33.14 +      slot.put(_"Show alternative initiatives")
   33.15 +    end,
   33.16 +    module = "issue",
   33.17 +    view = "show",
   33.18 +    id = initiative.issue.id
   33.19 +  }
   33.20 +end)
   33.21 +
   33.22 +execute.view{
   33.23 +  module = "issue",
   33.24 +  view = "_show_head",
   33.25 +  params = { issue = initiative.issue }
   33.26 +}
   33.27 +
   33.28 +--slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(initiative.id) .. '.rss" />')
   33.29 +
   33.30 +
   33.31 +slot.select("actions", function()
   33.32 +  if not initiative.issue.fully_frozen and not initiative.issue.closed then
   33.33 +    ui.link{
   33.34 +      image  = { static = "icons/16/script_add.png" },
   33.35 +      attr   = { class = "action" },
   33.36 +      text   = _"Create alternative initiative",
   33.37 +      module = "initiative",
   33.38 +      view   = "new",
   33.39 +      params = { issue_id = initiative.issue.id }
   33.40 +    }
   33.41 +  end
   33.42 +end)
   33.43 +
   33.44 +slot.put_into("sub_title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) ))
   33.45 +
   33.46 +execute.view{
   33.47 +  module = "initiative",
   33.48 +  view = "show_partial",
   33.49 +  params = {
   33.50 +    initiative = initiative
   33.51 +  }
   33.52 +}
   33.53 \ No newline at end of file
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/app/main/initiative/show_support.lua	Sat Feb 20 22:10:31 2010 +0100
    34.3 @@ -0,0 +1,43 @@
    34.4 +local initiative = param.get("initiative", "table") or Initiative:by_id(param.get_id())
    34.5 +
    34.6 +-- TODO performance
    34.7 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
    34.8 +
    34.9 +ui.partial{
   34.10 +  module = "initiative",
   34.11 +  view = "show_support",
   34.12 +  id = initiative.id,
   34.13 +  target = "initiative_" .. tostring(initiative.id) .. "_support",
   34.14 +  content = function()
   34.15 +    ui.container{
   34.16 +      attr = {
   34.17 +        class = "slot_support vote_info",
   34.18 +      },
   34.19 +      content = function()
   34.20 +        ui.container{
   34.21 +          attr = { class = "actions" },
   34.22 +          content = function()
   34.23 +            execute.view{
   34.24 +              module = "supporter",
   34.25 +              view = "_show_box",
   34.26 +              params = { initiative = initiative }
   34.27 +            }
   34.28 +            if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
   34.29 +              ui.link{
   34.30 +                attr = { class = "action", style = "float: left;" },
   34.31 +                content = function()
   34.32 +                  ui.image{ static = "icons/16/script_delete.png" }
   34.33 +                  slot.put(_"Revoke initiative")
   34.34 +                end,
   34.35 +                module = "initiative",
   34.36 +                view = "revoke",
   34.37 +                id = initiative.id
   34.38 +              }
   34.39 +            end
   34.40 +          end
   34.41 +        }
   34.42 +      end
   34.43 +    }
   34.44 +    slot.put("<div style='clear: left;'></div>")
   34.45 +  end
   34.46 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/app/main/initiative/show_tab.lua	Sat Feb 20 22:10:31 2010 +0100
    35.3 @@ -0,0 +1,175 @@
    35.4 +local initiative = param.get("initiative", "table")
    35.5 +local initiator = param.get("initiator", "table")
    35.6 +
    35.7 +if not initiative then
    35.8 +  initiative = Initiative:by_id(param.get("initiative_id", atom.number))
    35.9 +end
   35.10 +
   35.11 +if not initiator then
   35.12 +  initiator = Initiator:by_pk(initiative.id, app.session.member.id)
   35.13 +end
   35.14 +
   35.15 +local current_draft_name = _"Current draft"
   35.16 +if initiative.issue.half_frozen then
   35.17 +  current_draft_name = _"Voting proposal"
   35.18 +end
   35.19 +
   35.20 +if initiative.issue.state == "finished" then
   35.21 +  current_draft_name = _"Voted proposal"
   35.22 +end
   35.23 +
   35.24 +local tabs = {
   35.25 +  {
   35.26 +    name = "current_draft",
   35.27 +    label = current_draft_name,
   35.28 +    icon = { static = "icons/16/script.png" },
   35.29 +    module = "initiative",
   35.30 +    view = "_current_draft",
   35.31 +    params = {
   35.32 +      initiative = initiative,
   35.33 +      initiator = initiator
   35.34 +    }
   35.35 +  }
   35.36 +}
   35.37 +
   35.38 +if initiative.issue.ranks_available then
   35.39 +  tabs[#tabs+1] = {
   35.40 +    name = "voting",
   35.41 +    label = _"Voting details",
   35.42 +    icon = { static = "icons/16/email_open.png" },
   35.43 +    module = "initiative",
   35.44 +    view = "_show_voting",
   35.45 +    params = {
   35.46 +      initiative = initiative
   35.47 +    }
   35.48 +  }
   35.49 +end
   35.50 +
   35.51 +local suggestion_count = initiative:get_reference_selector("suggestions"):count()
   35.52 +
   35.53 +tabs[#tabs+1] = {
   35.54 +  name = "suggestions",
   35.55 +  label = _"Suggestions" .. " (" .. tostring(suggestion_count) .. ")",
   35.56 +  icon = { static = "icons/16/comments.png" },
   35.57 +  module = "initiative",
   35.58 +  view = "_suggestions",
   35.59 +  params = {
   35.60 +    initiative = initiative
   35.61 +  }
   35.62 +}
   35.63 +
   35.64 +local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
   35.65 +          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
   35.66 +          :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")
   35.67 +          :add_field("direct_interest_snapshot.weight")
   35.68 +          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
   35.69 +          :add_where("direct_supporter_snapshot.satisfied")
   35.70 +          :add_field("direct_supporter_snapshot.informed", "is_informed")
   35.71 +
   35.72 +local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
   35.73 +local direct_satisfied_supporter_count = tmp.count
   35.74 +local indirect_satisfied_supporter_count = (tmp.weight or 0) - tmp.count
   35.75 +
   35.76 +local count_string
   35.77 +if indirect_satisfied_supporter_count > 0 then
   35.78 +  count_string = "(" .. tostring(direct_satisfied_supporter_count) .. "+" .. tostring(indirect_satisfied_supporter_count) .. ")"
   35.79 +else
   35.80 +  count_string = "(" .. tostring(direct_satisfied_supporter_count) .. ")"
   35.81 +end
   35.82 +
   35.83 +tabs[#tabs+1] = {
   35.84 +  name = "satisfied_supporter",
   35.85 +  label = _"Supporter" .. " " .. count_string,
   35.86 +  icon = { static = "icons/16/thumb_up_green.png" },
   35.87 +  module = "member",
   35.88 +  view = "_list",
   35.89 +  params = {
   35.90 +    initiative = initiative,
   35.91 +    members_selector = members_selector
   35.92 +  }
   35.93 +}
   35.94 +
   35.95 +local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
   35.96 +          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
   35.97 +          :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")
   35.98 +          :add_field("direct_interest_snapshot.weight")
   35.99 +          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
  35.100 +          :add_where("NOT direct_supporter_snapshot.satisfied")
  35.101 +          :add_field("direct_supporter_snapshot.informed", "is_informed")
  35.102 +
  35.103 +local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
  35.104 +local direct_potential_supporter_count = tmp.count
  35.105 +local indirect_potential_supporter_count = (tmp.weight or 0) - tmp.count
  35.106 +
  35.107 +local count_string
  35.108 +if indirect_potential_supporter_count > 0 then
  35.109 +  count_string = "(" .. tostring(direct_potential_supporter_count) .. "+" .. tostring(indirect_potential_supporter_count) .. ")"
  35.110 +else
  35.111 +  count_string = "(" .. tostring(direct_potential_supporter_count) .. ")"
  35.112 +end
  35.113 +
  35.114 +tabs[#tabs+1] = {
  35.115 +  name = "supporter",
  35.116 +  label = _"Potential supporter" .. " " .. count_string,
  35.117 +  icon = { static = "icons/16/thumb_up.png" },
  35.118 +  module = "member",
  35.119 +  view = "_list",
  35.120 +  params = {
  35.121 +    initiative = initiative,
  35.122 +    members_selector = members_selector
  35.123 +  }
  35.124 +}
  35.125 +
  35.126 +local initiators_members_selector = initiative:get_reference_selector("initiating_members")
  35.127 +  :add_field("initiator.accepted", "accepted")
  35.128 +
  35.129 +if not (initiator and initiator.accepted) then
  35.130 +  initiators_members_selector:add_where("initiator.accepted")
  35.131 +end
  35.132 +
  35.133 +local initiator_count = initiators_members_selector:count()
  35.134 +
  35.135 +tabs[#tabs+1] = {
  35.136 +  name = "initiators",
  35.137 +  label = _"Initiators" .. " (" .. tostring(initiator_count) .. ")",
  35.138 +  icon = { static = "icons/16/user_edit.png" },
  35.139 +  module = "initiative",
  35.140 +  view = "_initiators",
  35.141 +  params = {
  35.142 +    initiative = initiative,
  35.143 +    initiator = initiator,
  35.144 +    initiators_members_selector = initiators_members_selector
  35.145 +  }
  35.146 +}
  35.147 +
  35.148 +local drafts_count = initiative:get_reference_selector("drafts"):count()
  35.149 +
  35.150 +tabs[#tabs+1] = {
  35.151 +  name = "drafts",
  35.152 +  label = _"Draft history" .. " (" .. tostring(drafts_count) .. ")",
  35.153 +  icon = { static = "icons/16/script.png" },
  35.154 +  module = "draft",
  35.155 +  view = "_list",
  35.156 +  params = { drafts = initiative.drafts }
  35.157 +}
  35.158 +
  35.159 +tabs[#tabs+1] = {
  35.160 +  name = "details",
  35.161 +  label = _"Details",
  35.162 +  icon = { static = "icons/16/magnifier.png" },
  35.163 +  module = "initiative",
  35.164 +  view = "_details",
  35.165 +  params = {
  35.166 +    initiative = initiative,
  35.167 +    members_selector = members_selector
  35.168 +  }
  35.169 +}
  35.170 +
  35.171 +tabs.module = "initiative"
  35.172 +tabs.view = "show_tab"
  35.173 +tabs.static_params = {
  35.174 +  initiative_id = initiative.id
  35.175 +}
  35.176 +
  35.177 +ui.tabs(tabs)
  35.178 +
    36.1 --- a/app/main/interest/_show_box.lua	Tue Feb 02 00:31:06 2010 +0100
    36.2 +++ b/app/main/interest/_show_box.lua	Sat Feb 20 22:10:31 2010 +0100
    36.3 @@ -11,7 +11,7 @@
    36.4      content = function()
    36.5          ui.container{
    36.6            attr = { 
    36.7 -            class = "head head_active",
    36.8 +            class = "head head_active" .. (interest.autoreject and " head_autoreject" or ""),
    36.9              onclick = "document.getElementById('interest_content').style.display = 'block';"
   36.10            },
   36.11            content = function()
   36.12 @@ -19,6 +19,13 @@
   36.13                static = "icons/16/eye.png"
   36.14              }
   36.15              slot.put(_"Your are interested")
   36.16 +
   36.17 +            if interest.autoreject then
   36.18 +              ui.image{
   36.19 +                static = "icons/16/thumb_down_red.png"
   36.20 +              }
   36.21 +            end
   36.22 +
   36.23              ui.image{
   36.24                static = "icons/16/dropdown.png"
   36.25              }
   36.26 @@ -40,10 +47,10 @@
   36.27              }
   36.28              if issue.state ~= "finished" and issue.state ~= "cancelled" and issue.state ~= "voting" then
   36.29                ui.link{
   36.30 -                content = _"Remove my interest",
   36.31 -                module = "interest",
   36.32 -                action = "update",
   36.33 -                params = { issue_id = issue.id, delete = true },
   36.34 +                text    = _"Remove my interest",
   36.35 +                module  = "interest",
   36.36 +                action  = "update",
   36.37 +                params  = { issue_id = issue.id, delete = true },
   36.38                  routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
   36.39                }
   36.40                slot.put("<br />")
   36.41 @@ -53,10 +60,10 @@
   36.42                ui.field.text{ value = _"Autoreject is on." }
   36.43                if issue.state ~= "finished" and issue.state ~= "cancelled" then
   36.44                  ui.link{
   36.45 -                  content = _"Remove autoreject",
   36.46 -                  module = "interest",
   36.47 -                  action = "update",
   36.48 -                  params = { issue_id = issue.id, autoreject = false },
   36.49 +                  text    = _"Remove autoreject",
   36.50 +                  module  = "interest",
   36.51 +                  action  = "update",
   36.52 +                  params  = { issue_id = issue.id, autoreject = false },
   36.53                    routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
   36.54                  }
   36.55                end
   36.56 @@ -64,10 +71,10 @@
   36.57                ui.field.text{ value = _"Autoreject is off." }
   36.58                if issue.state ~= "finished" and issue.state ~= "cancelled" then
   36.59                  ui.link{
   36.60 -                  content = _"Set autoreject",
   36.61 -                  module = "interest",
   36.62 -                  action = "update",
   36.63 -                  params = { issue_id = issue.id, autoreject = true },
   36.64 +                  text    = _"Set autoreject",
   36.65 +                  module  = "interest",
   36.66 +                  action  = "update",
   36.67 +                  params  = { issue_id = issue.id, autoreject = true },
   36.68                    routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
   36.69                  }
   36.70                end
   36.71 @@ -80,13 +87,11 @@
   36.72  else
   36.73    if not issue.closed and not issue.fully_frozen then
   36.74      ui.link{
   36.75 -      content = function()
   36.76 -        ui.image{ static = "icons/16/user_add.png" }
   36.77 -        slot.put(_"Add my interest")
   36.78 -      end,
   36.79 -      module = "interest",
   36.80 -      action = "update",
   36.81 -      params = { issue_id = issue.id },
   36.82 +      image   = { static = "icons/16/user_add.png" },
   36.83 +      text    = _"Add my interest",
   36.84 +      module  = "interest",
   36.85 +      action  = "update",
   36.86 +      params  = { issue_id = issue.id },
   36.87        routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
   36.88      }
   36.89    end
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/app/main/issue/_details.lua	Sat Feb 20 22:10:31 2010 +0100
    37.3 @@ -0,0 +1,37 @@
    37.4 +local issue = param.get("issue", "table")
    37.5 +
    37.6 +local policy = issue.policy
    37.7 +ui.form{
    37.8 +  record = issue,
    37.9 +  readonly = true,
   37.10 +  attr = { class = "vertical" },
   37.11 +  content = function()
   37.12 +    ui.field.text{ label = _"Population", name = "population" }
   37.13 +    ui.field.text{ label = _"State", name = "state" }
   37.14 +    ui.field.timestamp{ label = _"Created at",            name = "created" }
   37.15 +    ui.field.text{      label = _"Admission time",        value = policy.admission_time }
   37.16 +    ui.field.text{
   37.17 +      label = _"Issue quorum",
   37.18 +      value = format.percentage(policy.issue_quorum_num / policy.issue_quorum_den)
   37.19 +    }
   37.20 +    ui.field.timestamp{ label = _"Accepted at",              name = "accepted" }
   37.21 +    ui.field.text{      label = _"Discussion time",       value = policy.discussion_time }
   37.22 +    ui.field.vote_now{   label = _"Vote now", name = "vote_now" }
   37.23 +    ui.field.vote_later{ label = _"Vote later", name = "vote_later" }
   37.24 +    ui.field.timestamp{ label = _"Half frozen at",           name = "half_frozen" }
   37.25 +    ui.field.text{      label = _"Verification time",     value = policy.verification_time }
   37.26 +    ui.field.text{
   37.27 +      label   = _"Initiative quorum",
   37.28 +      value = format.percentage(policy.initiative_quorum_num / policy.initiative_quorum_den)
   37.29 +    }
   37.30 +    ui.field.timestamp{ label = _"Fully frozen at",          name = "fully_frozen" }
   37.31 +    ui.field.text{      label = _"Voting time",           value = policy.voting_time }
   37.32 +    ui.field.timestamp{ label = _"Closed",                name = "closed" }
   37.33 +  end
   37.34 +}
   37.35 +ui.form{
   37.36 +  record = issue.policy,
   37.37 +  readonly = true,
   37.38 +  content = function()
   37.39 +  end
   37.40 +}
    38.1 --- a/app/main/issue/_list.lua	Tue Feb 02 00:31:06 2010 +0100
    38.2 +++ b/app/main/issue/_list.lua	Sat Feb 20 22:10:31 2010 +0100
    38.3 @@ -4,347 +4,310 @@
    38.4    :left_join("interest", "_interest", { "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id} )
    38.5    :add_field("(_interest.member_id NOTNULL)", "is_interested")
    38.6  
    38.7 -local ui_filter = ui.filter
    38.8 -if param.get("filter", atom.boolean) == false then
    38.9 -  ui_filter = function(args) args.content() end
   38.10 -end
   38.11 +ui.add_partial_param_names{
   38.12 +  "filter",
   38.13 +  "filter_open",
   38.14 +  "filter_voting",
   38.15 +  "filter_interest",
   38.16 +  "issue_list" 
   38.17 +}
   38.18  
   38.19 -if param.get("no_filter", atom.boolean) then
   38.20 -  ui_filter = function(args) args.content() end
   38.21 -end
   38.22 +local filters = {}
   38.23  
   38.24 -local filter_voting = false
   38.25 -ui_filter{
   38.26 -  selector = issues_selector,
   38.27 -  filters = {
   38.28 +filters[#filters+1] = {
   38.29 +  label = _"Filter",
   38.30 +  {
   38.31 +    name = "open",
   38.32 +    label = _"Open",
   38.33 +    selector_modifier = function(selector)
   38.34 +        selector:add_where("issue.closed ISNULL")
   38.35 +    end
   38.36 +  },
   38.37 +  {
   38.38 +    name = "new",
   38.39 +    label = _"New",
   38.40 +    selector_modifier = function(selector)
   38.41 +      selector:add_where("issue.accepted ISNULL AND issue.closed ISNULL")
   38.42 +    end
   38.43 +  },
   38.44 +  {
   38.45 +    name = "accepted",
   38.46 +    label = _"In discussion",
   38.47 +    selector_modifier = function(selector)
   38.48 +      selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL")
   38.49 +    end
   38.50 +  },
   38.51 +  {
   38.52 +    name = "half_frozen",
   38.53 +    label = _"Frozen",
   38.54 +    selector_modifier = function(selector)
   38.55 +      selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL")
   38.56 +    end
   38.57 +  },
   38.58 +  {
   38.59 +    name = "frozen",
   38.60 +    label = _"Voting",
   38.61 +    selector_modifier = function(selector)
   38.62 +      selector:add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL")
   38.63 +      filter_voting = true
   38.64 +    end
   38.65 +  },
   38.66 +  {
   38.67 +    name = "finished",
   38.68 +    label = _"Finished",
   38.69 +    selector_modifier = function(selector)
   38.70 +      selector:add_where("issue.closed NOTNULL AND issue.fully_frozen NOTNULL")
   38.71 +    end
   38.72 +  },
   38.73 +  {
   38.74 +    name = "cancelled",
   38.75 +    label = _"Cancelled",
   38.76 +    selector_modifier = function(selector)
   38.77 +      selector:add_where("issue.closed NOTNULL AND issue.accepted ISNULL")
   38.78 +    end
   38.79 +  },
   38.80 +  {
   38.81 +    name = "any",
   38.82 +    label = _"Any",
   38.83 +    selector_modifier = function(selector) end
   38.84 +  },
   38.85 +}
   38.86 +
   38.87 +
   38.88 +if param.get("filter") == "frozen" then
   38.89 +  filters[#filters+1] = {
   38.90 +    label = _"Filter",
   38.91 +    name = "filter_voting",
   38.92      {
   38.93 -      type = "boolean",
   38.94 -      name = "open",
   38.95 -      label = _"Open",
   38.96 -      selector_modifier = function(selector, value)
   38.97 -        if value then
   38.98 -          selector:add_where("issue.closed ISNULL")
   38.99 -        end
  38.100 -      end
  38.101 +      name = "any",
  38.102 +      label = _"Any",
  38.103 +      selector_modifier = function()  end
  38.104      },
  38.105      {
  38.106 -      type = "boolean",
  38.107 -      name = "new",
  38.108 -      label = _"New",
  38.109 -      selector_modifier = function(selector, value)
  38.110 -        if value then
  38.111 -          selector:add_where("issue.accepted ISNULL AND issue.closed ISNULL")
  38.112 -        end
  38.113 +      name = "not_voted",
  38.114 +      label = _"Not voted",
  38.115 +      selector_modifier = function(selector)
  38.116 +        selector:left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
  38.117 +        selector:add_where("direct_voter.member_id ISNULL")
  38.118        end
  38.119      },
  38.120      {
  38.121 -      type = "boolean",
  38.122 -      name = "accepted",
  38.123 -      label = _"In discussion",
  38.124 -      selector_modifier = function(selector, value)
  38.125 -        if value then
  38.126 -          selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL")
  38.127 -        end
  38.128 -      end
  38.129 -    },
  38.130 -    {
  38.131 -      type = "boolean",
  38.132 -      name = "half_frozen",
  38.133 -      label = _"Frozen",
  38.134 -      selector_modifier = function(selector, value)
  38.135 -        if value then
  38.136 -          selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL")
  38.137 -        end
  38.138 +      name = "voted",
  38.139 +      label = _"Voted",
  38.140 +      selector_modifier = function(selector)
  38.141 +        selector:join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
  38.142        end
  38.143      },
  38.144 +  }
  38.145 +end
  38.146 +
  38.147 +
  38.148 +filters[#filters+1] = {
  38.149 +  label = _"Filter",
  38.150 +  name = "filter_interest",
  38.151 +  {
  38.152 +    name = "any",
  38.153 +    label = _"Any",
  38.154 +    selector_modifier = function()  end
  38.155 +  },
  38.156 +  {
  38.157 +    name = "my",
  38.158 +    label = _"Interested",
  38.159 +    selector_modifier = function(selector)
  38.160 +      selector:join("interest", "filter_interest", { "filter_interest.issue_id = issue.id AND filter_interest.member_id = ? ", app.session.member.id })
  38.161 +    end
  38.162 +  },
  38.163 +  {
  38.164 +    name = "supported",
  38.165 +    label = _"Supported",
  38.166 +    selector_modifier = function(selector)
  38.167 +      selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? LEFT JOIN opinion ON opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) WHERE initiative.issue_id = issue.id AND opinion.member_id ISNULL LIMIT 1)", app.session.member.id, app.session.member.id })
  38.168 +    end
  38.169 +  },
  38.170 +  {
  38.171 +    name = "potentially_supported",
  38.172 +    label = _"Potential supported",
  38.173 +    selector_modifier = function(selector)
  38.174 +      selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? JOIN opinion ON opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) WHERE initiative.issue_id = issue.id LIMIT 1)", app.session.member.id, app.session.member.id })
  38.175 +    end
  38.176 +  },
  38.177 +  {
  38.178 +    name = "initiated",
  38.179 +    label = _"Initiated",
  38.180 +    selector_modifier = function(selector)
  38.181 +      selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN initiator ON initiator.initiative_id = initiative.id AND initiator.member_id = ? WHERE initiative.issue_id = issue.id)", app.session.member.id })
  38.182 +    end
  38.183 +  },
  38.184 +}
  38.185 +
  38.186 +if not param.get("no_sort", atom.boolean) then
  38.187 +  filters[#filters+1] = {
  38.188 +    label = _"Order by",
  38.189 +    name = "issue_list",
  38.190      {
  38.191 -      type = "boolean",
  38.192 -      name = "frozen",
  38.193 -      label = _"Voting",
  38.194 -      selector_modifier = function(selector, value)
  38.195 -        if value then
  38.196 -          selector:add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL")
  38.197 -          filter_voting = true
  38.198 -        end
  38.199 -      end
  38.200 -    },
  38.201 -    {
  38.202 -      type = "boolean",
  38.203 -      name = "finished",
  38.204 -      label = _"Finished",
  38.205 -      selector_modifier = function(selector, value)
  38.206 -        if value then
  38.207 -          selector:add_where("issue.closed NOTNULL AND issue.fully_frozen NOTNULL")
  38.208 -        end
  38.209 +      name = "max_potential_support",
  38.210 +      label = _"Max potential support",
  38.211 +      selector_modifier = function(selector)
  38.212 +        selector:add_order_by("(SELECT max(supporter_count) FROM initiative WHERE initiative.issue_id = issue.id) DESC")
  38.213        end
  38.214      },
  38.215      {
  38.216 -      type = "boolean",
  38.217 -      name = "cancelled",
  38.218 -      label = _"Cancelled",
  38.219 -      selector_modifier = function(selector, value)
  38.220 -        if value then
  38.221 -          selector:add_where("issue.closed NOTNULL AND issue.accepted ISNULL")
  38.222 -        end
  38.223 +      name = "max_support",
  38.224 +      label = _"Max support",
  38.225 +      selector_modifier = function(selector)
  38.226 +        selector:add_order_by("(SELECT max(satisfied_supporter_count) FROM initiative WHERE initiative.issue_id = issue.id) DESC")
  38.227 +      end
  38.228 +    },
  38.229 +    {
  38.230 +      name = "population",
  38.231 +      label = _"Population",
  38.232 +      selector_modifier = function(selector)
  38.233 +        selector:add_order_by("issue.population DESC")
  38.234 +      end
  38.235 +    },
  38.236 +    {
  38.237 +      name = "newest",
  38.238 +      label = _"Newest",
  38.239 +      selector_modifier = function(selector)
  38.240 +        selector:add_order_by("issue.created DESC")
  38.241        end
  38.242      },
  38.243 -  },
  38.244 -  content = function()
  38.245 -    local ui_filter = ui.filter
  38.246 -    if not filter_voting then
  38.247 -      ui_filter = function(args) args.content() end
  38.248 -    end
  38.249 -    if param.get("no_filter", atom.boolean) then
  38.250 -      ui_filter = function(args) args.content() end
  38.251 -    end
  38.252 -    ui_filter{
  38.253 -      selector = issues_selector,
  38.254 -      name = "filter_voting",
  38.255 -      filters = {
  38.256 -        {
  38.257 -          type = "boolean",
  38.258 -          name = "any",
  38.259 -          label = _"Any",
  38.260 -          selector_modifier = function()  end
  38.261 -        },
  38.262 -        {
  38.263 -          type = "boolean",
  38.264 -          name = "not_voted",
  38.265 -          label = _"Not voted",
  38.266 -          selector_modifier = function(selector, value)
  38.267 -            if value then
  38.268 -              selector:left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
  38.269 -              selector:add_where("direct_voter.member_id ISNULL")
  38.270 -            end
  38.271 -          end
  38.272 -        },
  38.273 -        {
  38.274 -          type = "boolean",
  38.275 -          name = "voted",
  38.276 -          label = _"Voted",
  38.277 -          selector_modifier = function(selector, value)
  38.278 -            if value then
  38.279 -              selector:join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", app.session.member.id })
  38.280 -            end
  38.281 -          end
  38.282 -        },
  38.283 -      },
  38.284 -      content = function()
  38.285 -        local ui_filter = ui.filter
  38.286 -        if param.get("filter", atom.boolean) == false then
  38.287 -          ui_filter = function(args) args.content() end
  38.288 -        end
  38.289 -        ui_filter{
  38.290 -          selector = issues_selector,
  38.291 -          name = "filter_interest",
  38.292 -          filters = {
  38.293 -            {
  38.294 -              type = "boolean",
  38.295 -              name = "any",
  38.296 -              label = _"Any",
  38.297 -              selector_modifier = function()  end
  38.298 -            },
  38.299 -            {
  38.300 -              type = "boolean",
  38.301 -              name = "my",
  38.302 -              label = _"Interested",
  38.303 -              selector_modifier = function(selector, value)
  38.304 -                if value then
  38.305 -                  selector:join("interest", "filter_interest", { "filter_interest.issue_id = issue.id AND filter_interest.member_id = ? ", app.session.member.id })
  38.306 -                end
  38.307 -              end
  38.308 -            },
  38.309 -            {
  38.310 -              type = "boolean",
  38.311 -              name = "supported",
  38.312 -              label = _"Supported",
  38.313 -              selector_modifier = function(selector, value)
  38.314 -                if value then
  38.315 -                  selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? LEFT JOIN opinion ON opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) WHERE initiative.issue_id = issue.id AND opinion.member_id ISNULL LIMIT 1)", app.session.member.id, app.session.member.id })
  38.316 -                end
  38.317 -              end
  38.318 -            },
  38.319 -            {
  38.320 -              type = "boolean",
  38.321 -              name = "potentially_supported",
  38.322 -              label = _"Potential supported",
  38.323 -              selector_modifier = function(selector, value)
  38.324 -                if value then
  38.325 -                  selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN supporter ON supporter.initiative_id = initiative.id AND supporter.member_id = ? JOIN opinion ON opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) WHERE initiative.issue_id = issue.id LIMIT 1)", app.session.member.id, app.session.member.id })
  38.326 -                end
  38.327 -              end
  38.328 -            },
  38.329 -            {
  38.330 -              type = "boolean",
  38.331 -              name = "initiated",
  38.332 -              label = _"Initiated",
  38.333 -              selector_modifier = function(selector, value)
  38.334 -                if value then
  38.335 -                  selector:add_where({ "EXISTS (SELECT 1 FROM initiative JOIN initiator ON initiator.initiative_id = initiative.id AND initiator.member_id = ? WHERE initiative.issue_id = issue.id)", app.session.member.id })
  38.336 -                end
  38.337 +    {
  38.338 +      name = "oldest",
  38.339 +      label = _"Oldest",
  38.340 +      selector_modifier = function(selector)
  38.341 +        selector:add_order_by("issue.created")
  38.342 +      end
  38.343 +    }
  38.344 +  }
  38.345 +end
  38.346 +
  38.347 +filters.content = function()
  38.348 +  local ui_paginate = ui.paginate
  38.349 +  if param.get("per_page") == "all" then
  38.350 +    ui_paginate = function(args) args.content() end
  38.351 +  end
  38.352 +  ui_paginate{
  38.353 +    per_page = tonumber(param.get("per_page")),
  38.354 +    selector = issues_selector,
  38.355 +    content = function()
  38.356 +      local highlight_string = param.get("highlight_string", "string")
  38.357 +      local issues = issues or issues_selector:exec()
  38.358 +      -- issues:load(initiatives)
  38.359 +      ui.list{
  38.360 +        attr = { class = "issues" },
  38.361 +        records = issues,
  38.362 +        columns = {
  38.363 +          {
  38.364 +            label = _"Issue",
  38.365 +            content = function(record)
  38.366 +              if not param.get("for_area_list", atom.boolean) then
  38.367 +                ui.field.text{
  38.368 +                  value = record.area.name
  38.369 +                }
  38.370 +                slot.put("<br />")
  38.371                end
  38.372 -            },
  38.373 -          },
  38.374 -          content = function()
  38.375 -            local ui_order = ui.order
  38.376 -            if param.get("no_sort", atom.boolean) then
  38.377 -              ui_order = function(args) args.content() end
  38.378 -            end
  38.379 -            ui_order{
  38.380 -              name = "issue_list",
  38.381 -              selector = issues_selector,
  38.382 -              options = {
  38.383 -                {
  38.384 -                  name = "max_potential_support",
  38.385 -                  label = _"Max potential support",
  38.386 -                  selector_modifier = function(selector)
  38.387 -                    selector:add_order_by("(SELECT max(supporter_count) FROM initiative WHERE initiative.issue_id = issue.id) DESC")
  38.388 -                  end
  38.389 -                },
  38.390 -                {
  38.391 -                  name = "max_support",
  38.392 -                  label = _"Max support",
  38.393 -                  selector_modifier = function(selector)
  38.394 -                    selector:add_order_by("(SELECT max(satisfied_supporter_count) FROM initiative WHERE initiative.issue_id = issue.id) DESC")
  38.395 -                  end
  38.396 -                },
  38.397 -                {
  38.398 -                  name = "population",
  38.399 -                  label = _"Population",
  38.400 -                  order_by = "issue.population DESC"
  38.401 -                },
  38.402 -                {
  38.403 -                  name = "newest",
  38.404 -                  label = _"Newest",
  38.405 -                  order_by = "issue.created DESC"
  38.406 -                },
  38.407 -                {
  38.408 -                  name = "oldest",
  38.409 -                  label = _"Oldest",
  38.410 -                  order_by = "issue.created"
  38.411 +              if record.is_interested then
  38.412 +                local label = _"You are interested in this issue",
  38.413 +                ui.image{
  38.414 +                  attr = { alt = label, title = label },
  38.415 +                  static = "icons/16/eye.png"
  38.416                  }
  38.417 -              },
  38.418 -              content = function()
  38.419 -                local ui_paginate = ui.paginate
  38.420 -                if param.get("per_page") == "all" then
  38.421 -                  ui_paginate = function(args) args.content() end
  38.422 -                end
  38.423 -                ui_paginate{
  38.424 -                  per_page = tonumber(param.get("per_page")),
  38.425 -                  selector = issues_selector,
  38.426 -                  content = function()
  38.427 -                    local highlight_string = param.get("highlight_string", "string")
  38.428 -                    local issues = issues or issues_selector:exec()
  38.429 -        --            issues:load(initiatives)
  38.430 -                    ui.list{
  38.431 -                      attr = { class = "issues" },
  38.432 -                      records = issues,
  38.433 -                      columns = {
  38.434 -                        {
  38.435 -                          label = _"Issue",
  38.436 -                          content = function(record)
  38.437 -                            if not param.get("for_area_list", atom.boolean) then
  38.438 -                              ui.field.text{
  38.439 -                                value = record.area.name
  38.440 -                              }
  38.441 -                              slot.put("<br />")
  38.442 -                            end
  38.443 -                            if record.is_interested then
  38.444 -                              local label = _"You are interested in this issue",
  38.445 -                              ui.image{
  38.446 -                                attr = { alt = label, title = label },
  38.447 -                                static = "icons/16/eye.png"
  38.448 -                              }
  38.449 -                              slot.put("&nbsp;")
  38.450 -                            end
  38.451 -                            ui.link{
  38.452 -                              text = _("Issue ##{id}", { id = tostring(record.id) }),
  38.453 -                              module = "issue",
  38.454 -                              view = "show",
  38.455 -                              id = record.id
  38.456 -                            }
  38.457 -                            if record.state == "new" then
  38.458 -                              ui.image{
  38.459 -                                static = "icons/16/new.png"
  38.460 -                              }
  38.461 -                            end
  38.462 -                            slot.put("<br />")
  38.463 -                            slot.put("<br />")
  38.464 -                            if record.old_state then
  38.465 -                              ui.field.text{ value = format.time(record.sort) }
  38.466 -                              ui.field.text{ value = Issue:get_state_name_for_state(record.old_state) .. " > " .. Issue:get_state_name_for_state(record.new_state) }
  38.467 -                            else
  38.468 -                            end
  38.469 -                          end
  38.470 -                        },
  38.471 -                        {
  38.472 -                          label = _"State",
  38.473 -                          content = function(record)
  38.474 -                            if record.state == "voting" then
  38.475 -                              ui.link{
  38.476 -                                content = _"Voting",
  38.477 -                                module = "vote",
  38.478 -                                view = "list",
  38.479 -                                params = { issue_id = record.id }
  38.480 -                              }
  38.481 -                            else
  38.482 -                              ui.field.issue_state{ value = record.state }
  38.483 -                            end
  38.484 -                          end
  38.485 -                        },
  38.486 -                        {
  38.487 -                          label = _"Initiatives",
  38.488 -                          content = function(record)
  38.489 -                            local initiatives_selector = record:get_reference_selector("initiatives")
  38.490 -                            local highlight_string = param.get("highlight_string")
  38.491 -                            if highlight_string then
  38.492 -                              initiatives_selector:add_field( {'"highlight"("initiative"."name", ?)', highlight_string }, "name_highlighted")
  38.493 -                            end
  38.494 -                            execute.view{
  38.495 -                              module = "initiative",
  38.496 -                              view = "_list",
  38.497 -                              params = {
  38.498 -                                issue = record,
  38.499 -                                initiatives_selector = initiatives_selector,
  38.500 -                                highlight_string = highlight_string,
  38.501 -                                per_page = param.get("initiatives_per_page", atom.number),
  38.502 -                                no_sort = param.get("initiatives_no_sort", atom.boolean)
  38.503 -                              }
  38.504 -                            }
  38.505 -                          end
  38.506 -                        },
  38.507 -                      }
  38.508 -                    }
  38.509 -                  end
  38.510 +                slot.put("&nbsp;")
  38.511 +              end
  38.512 +              ui.link{
  38.513 +                text = _("Issue ##{id}", { id = tostring(record.id) }),
  38.514 +                module = "issue",
  38.515 +                view = "show",
  38.516 +                id = record.id
  38.517 +              }
  38.518 +              if record.state == "new" then
  38.519 +                ui.image{
  38.520 +                  static = "icons/16/new.png"
  38.521                  }
  38.522                end
  38.523 -            }
  38.524 -          end
  38.525 +              slot.put("<br />")
  38.526 +              slot.put("<br />")
  38.527 +              if record.old_state then
  38.528 +                ui.field.text{ value = format.time(record.sort) }
  38.529 +                ui.field.text{ value = Issue:get_state_name_for_state(record.old_state) .. " > " .. Issue:get_state_name_for_state(record.new_state) }
  38.530 +              else
  38.531 +              end
  38.532 +            end
  38.533 +          },
  38.534 +          {
  38.535 +            label = _"State",
  38.536 +            content = function(record)
  38.537 +              if record.state == "voting" then
  38.538 +                ui.link{
  38.539 +                  content = _"Voting",
  38.540 +                  module = "vote",
  38.541 +                  view = "list",
  38.542 +                  params = { issue_id = record.id }
  38.543 +                }
  38.544 +              else
  38.545 +                ui.field.issue_state{ value = record.state }
  38.546 +              end
  38.547 +            end
  38.548 +          },
  38.549 +          {
  38.550 +            label = _"Initiatives",
  38.551 +            content = function(record)
  38.552 +              local initiatives_selector = record:get_reference_selector("initiatives")
  38.553 +              local highlight_string = param.get("highlight_string")
  38.554 +              if highlight_string then
  38.555 +                initiatives_selector:add_field( {'"highlight"("initiative"."name", ?)', highlight_string }, "name_highlighted")
  38.556 +              end
  38.557 +              execute.view{
  38.558 +                module = "initiative",
  38.559 +                view = "_list",
  38.560 +                params = {
  38.561 +                  issue = record,
  38.562 +                  initiatives_selector = initiatives_selector,
  38.563 +                  highlight_string = highlight_string,
  38.564 +                  per_page = tonumber(app.session.member:get_setting_value("initiatives_preview_limit") or 3),
  38.565 +                  no_sort = true,
  38.566 +                  limit = tonumber(app.session.member:get_setting_value("initiatives_preview_limit") or 3)
  38.567 +                }
  38.568 +              }
  38.569 +            end
  38.570 +          },
  38.571          }
  38.572 -      end
  38.573 +      }
  38.574 +    end
  38.575 +  }
  38.576 +end
  38.577 +
  38.578 +filters.selector = issues_selector
  38.579 +filters.label = _"Change filters and order"
  38.580 +
  38.581 +if param.get("no_filter", atom.boolean) then
  38.582 +  filters.content()
  38.583 +else
  38.584 +  ui.filters(filters)
  38.585 +end
  38.586 +
  38.587 +if param.get("legend", atom.boolean) ~= false then
  38.588 +  local filter = param.get_all_cgi().filter
  38.589 +  if not filter or filter == "any" or filter ~= "finished" then
  38.590 +    ui.bargraph_legend{
  38.591 +      width = 25,
  38.592 +      bars = {
  38.593 +        { color = "#0a0", label = _"Supporter" },
  38.594 +        { color = "#777", label = _"Potential supporter" },
  38.595 +        { color = "#ddd", label = _"No support at all" },
  38.596 +      }
  38.597      }
  38.598 -    if param.get("legend", atom.boolean) ~= false then
  38.599 -      local filter = param.get_all_cgi().filter
  38.600 -      if not filter or filter == "any" or filter ~= "finished" then
  38.601 -        ui.bargraph_legend{
  38.602 -          width = 25,
  38.603 -          bars = {
  38.604 -            { color = "#0a0", label = _"Supporter" },
  38.605 -            { color = "#777", label = _"Potential supporter" },
  38.606 -            { color = "#ddd", label = _"No support at all" },
  38.607 -          }
  38.608 -        }
  38.609 -      end
  38.610 -      if not filter or filter == "any" or filter == "finished" then
  38.611 -        ui.bargraph_legend{
  38.612 -          width = 25,
  38.613 -          bars = {
  38.614 -            { color = "#0a0", label = _"Yes" },
  38.615 -            { color = "#aaa", label = _"Abstention" },
  38.616 -            { color = "#a00", label = _"No" },
  38.617 -          }
  38.618 -        }
  38.619 -      end
  38.620 -    end
  38.621    end
  38.622 -}
  38.623 +  if not filter or filter == "any" or filter == "finished" then
  38.624 +    ui.bargraph_legend{
  38.625 +      width = 25,
  38.626 +      bars = {
  38.627 +        { color = "#0a0", label = _"Yes" },
  38.628 +        { color = "#aaa", label = _"Abstention" },
  38.629 +        { color = "#a00", label = _"No" },
  38.630 +      }
  38.631 +    }
  38.632 +  end
  38.633 +end
  38.634 +
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/app/main/issue/_list_initiatives.lua	Sat Feb 20 22:10:31 2010 +0100
    39.3 @@ -0,0 +1,10 @@
    39.4 +local issue = param.get("issue", "table")
    39.5 +
    39.6 +execute.view{
    39.7 +  module = "initiative",
    39.8 +  view = "_list",
    39.9 +  params = { 
   39.10 +    issue = issue,
   39.11 +    initiatives_selector = issue:get_reference_selector("initiatives")
   39.12 +  }
   39.13 +}
    40.1 --- a/app/main/issue/_show_box.lua	Tue Feb 02 00:31:06 2010 +0100
    40.2 +++ b/app/main/issue/_show_box.lua	Sat Feb 20 22:10:31 2010 +0100
    40.3 @@ -2,6 +2,10 @@
    40.4  
    40.5  slot.select("issue_info", function()
    40.6    ui.field.text{ 
    40.7 +    label = _"Policy",
    40.8 +    value = issue.policy.name 
    40.9 +  }
   40.10 +  ui.field.text{ 
   40.11      label = _"State",
   40.12      value = issue.state_name 
   40.13    }
    41.1 --- a/app/main/issue/_show_head.lua	Tue Feb 02 00:31:06 2010 +0100
    41.2 +++ b/app/main/issue/_show_head.lua	Sat Feb 20 22:10:31 2010 +0100
    41.3 @@ -1,33 +1,47 @@
    41.4  local issue = param.get("issue", "table")
    41.5  
    41.6 +local direct_voter = DirectVoter:by_pk(issue.id, app.session.member.id)
    41.7 +
    41.8  slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(issue.id) .. '.rss" />')
    41.9  
   41.10  slot.select("path", function()
   41.11 +end)
   41.12 +
   41.13 +slot.select("title", function()
   41.14    ui.link{
   41.15 -    content = _"Area '#{name}'":gsub("#{name}", issue.area.name),
   41.16 +    content = issue.area.name,
   41.17      module = "area",
   41.18      view = "show",
   41.19      id = issue.area.id
   41.20    }
   41.21 -end)
   41.22 -
   41.23 -slot.select("title", function()
   41.24 +  slot.put(" &middot; ")
   41.25    ui.link{
   41.26 -    content = _"Issue ##{id} (#{policy_name})":gsub("#{id}", issue.id):gsub("#{policy_name}", issue.policy.name),
   41.27 +    content = _("Issue ##{id}", { id = issue.id }),
   41.28      module = "issue",
   41.29      view = "show",
   41.30      id = issue.id
   41.31    }
   41.32 +  slot.put(" &middot; ")
   41.33 +  ui.tag{
   41.34 +    tag = "span",
   41.35 +    content = issue.state_name,
   41.36 +  }
   41.37  end)
   41.38  
   41.39  
   41.40  slot.select("actions", function()
   41.41  
   41.42    if issue.state == 'voting' then
   41.43 +    local text
   41.44 +    if not direct_voter then
   41.45 +      text = _"Vote now"
   41.46 +    else
   41.47 +      text = _"Change vote"
   41.48 +    end
   41.49      ui.link{
   41.50        content = function()
   41.51          ui.image{ static = "icons/16/email_open.png" }
   41.52 -        slot.put(_"Vote now")
   41.53 +        slot.put(text)
   41.54        end,
   41.55        module = "vote",
   41.56        view = "list",
   41.57 @@ -78,7 +92,7 @@
   41.58  --  ui.twitter("http://example.com/t" .. tostring(issue.id))
   41.59  
   41.60  
   41.61 -if issue.state == 'voting' then
   41.62 +if issue.state == 'voting' and not direct_voter then
   41.63    ui.container{
   41.64      attr = { class = "voting_active_info" },
   41.65      content = function()
    42.1 --- a/app/main/issue/_show_vote_later_box.lua	Tue Feb 02 00:31:06 2010 +0100
    42.2 +++ b/app/main/issue/_show_vote_later_box.lua	Sat Feb 20 22:10:31 2010 +0100
    42.3 @@ -48,10 +48,10 @@
    42.4                end
    42.5              }
    42.6              ui.link{
    42.7 -              content = _"Remove my request to vote later",
    42.8 -              module = "interest",
    42.9 -              action = "update_voting_requested",
   42.10 -              params = { issue_id = issue.id, voting_requested = nil },
   42.11 +              text    = _"Remove my request to vote later",
   42.12 +              module  = "interest",
   42.13 +              action  = "update_voting_requested",
   42.14 +              params  = { issue_id = issue.id, voting_requested = nil },
   42.15                routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
   42.16              }
   42.17              slot.put("<br />")
   42.18 @@ -63,10 +63,8 @@
   42.19  else
   42.20    if not issue.closed and not issue.half_frozen then
   42.21      ui.link{
   42.22 -      content = function()
   42.23 -        ui.image{ static = "icons/16/clock_play.png" }
   42.24 -        slot.put(_"Vote later")
   42.25 -      end,
   42.26 +      image  = { static = "icons/16/clock_play.png" },
   42.27 +      text   = _"Vote later",
   42.28        module = "interest",
   42.29        action = "update_voting_requested",
   42.30        params = {
    43.1 --- a/app/main/issue/show.lua	Tue Feb 02 00:31:06 2010 +0100
    43.2 +++ b/app/main/issue/show.lua	Sat Feb 20 22:10:31 2010 +0100
    43.3 @@ -6,126 +6,59 @@
    43.4    params = { issue = issue }
    43.5  }
    43.6  
    43.7 +--[[
    43.8 +if not issue.fully_frozen and not issue.closed then
    43.9 +  slot.select("actions", function()
   43.10 +    ui.link{
   43.11 +      content = function()
   43.12 +        ui.image{ static = "icons/16/script_add.png" }
   43.13 +        slot.put(_"Create alternative initiative")
   43.14 +      end,
   43.15 +      module = "initiative",
   43.16 +      view = "new",
   43.17 +      params = { issue_id = issue.id }
   43.18 +    }
   43.19 +  end)
   43.20 +end
   43.21 +--]]
   43.22 +
   43.23  util.help("issue.show")
   43.24  
   43.25 -local voting_requested_percentage = 0
   43.26 -if issue.vote_later and issue.population and issue.population > 0 then
   43.27 -  voting_requested_percentage = math.ceil(issue.vote_later  / issue.population * 100)
   43.28 +if issue.state == "cancelled" then
   43.29 +  local policy = issue.policy
   43.30 +  ui.container{
   43.31 +    attr = { class = "not_admitted_info" },
   43.32 +    content = _("This issue has been cancelled. It failed the quorum of #{quorum}.", { quorum = format.percentage(policy.issue_quorum_num / policy.issue_quorum_den) })
   43.33 +  }
   43.34  end
   43.35 -local voting_requested_string = "(" .. tostring(voting_requested_percentage) .. "%)"
   43.36  
   43.37 -ui.tabs{
   43.38 -  {
   43.39 -    name = "initiatives",
   43.40 -    label = _"Initiatives",
   43.41 -    content = function()
   43.42 -      execute.view{
   43.43 -        module = "initiative",
   43.44 -        view = "_list",
   43.45 -        params = { 
   43.46 -          issue = issue,
   43.47 -          initiatives_selector = issue:get_reference_selector("initiatives")
   43.48 -        }
   43.49 -      }
   43.50 -      slot.put("<br />")
   43.51 -      if not issue.fully_frozen and not issue.closed then
   43.52 -        ui.link{
   43.53 -          attr = { class = "action" },
   43.54 -          content = function()
   43.55 -            ui.image{ static = "icons/16/script_add.png" }
   43.56 -            slot.put(_"Add new initiative to issue")
   43.57 -          end,
   43.58 -          module = "initiative",
   43.59 -          view = "new",
   43.60 -          params = { issue_id = issue.id }
   43.61 -        }
   43.62 -      end
   43.63 -    end
   43.64 -  },
   43.65 -  {
   43.66 -    name = "interested_members",
   43.67 -    label = _"Interested members",
   43.68 -    content = function()
   43.69 -      execute.view{
   43.70 -        module = "member",
   43.71 -        view = "_list",
   43.72 -        params = {
   43.73 -          issue = issue,
   43.74 -          members_selector =  issue:get_reference_selector("interested_members_snapshot")
   43.75 -            :join("issue", nil, "issue.id = direct_interest_snapshot.issue_id")
   43.76 -            :add_field("direct_interest_snapshot.weight")
   43.77 -            :add_where("direct_interest_snapshot.event = issue.latest_snapshot_event")
   43.78 -        }
   43.79 +ui.container{
   43.80 +  attr = { class = "issue_initiative_list" },
   43.81 +  content = function()
   43.82 +    execute.view{
   43.83 +      module = "initiative",
   43.84 +      view = "_list",
   43.85 +      params = {
   43.86 +        initiatives_selector = issue:get_reference_selector("initiatives"),
   43.87 +        issue = issue,
   43.88 +        expandable = true,
   43.89 +        for_initiative_id = param.get("for_initiative_id", atom.number),
   43.90 +        show_for_issue = true
   43.91        }
   43.92 -    end
   43.93 -  },
   43.94 -  {
   43.95 -    name = "delegations",
   43.96 -    label = _"Delegations",
   43.97 -    content = function()
   43.98 -      execute.view{
   43.99 -        module = "delegation",
  43.100 -        view = "_list",
  43.101 -        params = { delegations_selector = issue:get_reference_selector("delegations") }
  43.102 -      }
  43.103 -    end
  43.104 -  },
  43.105 -  {
  43.106 -    name = "voting_requests",
  43.107 -    label = _"Vote later requests" .. " " .. voting_requested_string,
  43.108 -    content = function()
  43.109 -      execute.view{
  43.110 -        module = "member",
  43.111 -        view = "_list",
  43.112 -        params = {
  43.113 -          issue = issue,
  43.114 -          members_selector =  issue:get_reference_selector("interested_members_snapshot")
  43.115 -            :join("issue", nil, "issue.id = direct_interest_snapshot.issue_id")
  43.116 -            :add_where("direct_interest_snapshot.voting_requested = false")
  43.117 -        }
  43.118 -      }
  43.119 -    end
  43.120 -  },
  43.121 -  {
  43.122 -    name = "details",
  43.123 -    label = _"Details",
  43.124 -    content = function()
  43.125 -      local policy = issue.policy
  43.126 -      ui.form{
  43.127 -        record = issue,
  43.128 -        readonly = true,
  43.129 -        attr = { class = "vertical" },
  43.130 -        content = function()
  43.131 -          ui.field.text{ label = _"State", name = "state" }
  43.132 -          ui.field.timestamp{ label = _"Created at",            name = "created" }
  43.133 -          ui.field.text{      label = _"Admission time",        value = policy.admission_time }
  43.134 -          ui.field.text{
  43.135 -            label = _"Issue quorum",
  43.136 -            value = format.percentage(policy.issue_quorum_num / policy.issue_quorum_den)
  43.137 -          }
  43.138 -          ui.field.timestamp{ label = _"Accepted at",              name = "accepted" }
  43.139 -          ui.field.text{      label = _"Discussion time",       value = policy.discussion_time }
  43.140 -          ui.field.vote_now{   label = _"Vote now", name = "vote_now" }
  43.141 -          ui.field.vote_later{ label = _"Vote later", name = "vote_later" }
  43.142 -          ui.field.timestamp{ label = _"Half frozen at",           name = "half_frozen" }
  43.143 -          ui.field.text{      label = _"Verification time",     value = policy.verification_time }
  43.144 -          ui.field.text{
  43.145 -            label   = _"Initiative quorum",
  43.146 -            value = format.percentage(policy.initiative_quorum_num / policy.initiative_quorum_den)
  43.147 -          }
  43.148 -          ui.field.timestamp{ label = _"Fully frozen at",          name = "fully_frozen" }
  43.149 -          ui.field.text{      label = _"Voting time",           value = policy.voting_time }
  43.150 -          ui.field.timestamp{ label = _"Closed",                name = "closed" }
  43.151 -        end
  43.152 -      }
  43.153 -      ui.form{
  43.154 -        record = issue.policy,
  43.155 -        readonly = true,
  43.156 -        content = function()
  43.157 -        end
  43.158 -      }
  43.159 -    end
  43.160 -  },
  43.161 +    }
  43.162 +  end
  43.163  }
  43.164  
  43.165 +slot.put("<br />")
  43.166  
  43.167 +execute.view{
  43.168 +  module = "issue",
  43.169 +  view = "show_tab",
  43.170 +  params = { issue = issue }
  43.171 +}
  43.172 +
  43.173 +if issue.snapshot then
  43.174 +  slot.put("<br />")
  43.175 +  ui.field.timestamp{ label = _"Last snapshot:", value = issue.snapshot }
  43.176 +end
  43.177 +
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/app/main/issue/show_tab.lua	Sat Feb 20 22:10:31 2010 +0100
    44.3 @@ -0,0 +1,69 @@
    44.4 +local issue
    44.5 +if request.get_json_request_slots() then
    44.6 +  issue = Issue:by_id(param.get("issue_id"))
    44.7 +else
    44.8 +  issue = param.get("issue", "table")
    44.9 +end
   44.10 +
   44.11 +local voting_requested_percentage = 0
   44.12 +if issue.vote_later and issue.population and issue.population > 0 then
   44.13 +  voting_requested_percentage = math.ceil(issue.vote_later  / issue.population * 100)
   44.14 +end
   44.15 +
   44.16 +local interested_members_selector = issue:get_reference_selector("interested_members_snapshot")
   44.17 +  :join("issue", nil, "issue.id = direct_interest_snapshot.issue_id")
   44.18 +  :add_field("direct_interest_snapshot.weight")
   44.19 +  :add_where("direct_interest_snapshot.event = issue.latest_snapshot_event")
   44.20 +
   44.21 +local voting_requests_selector = issue:get_reference_selector("interested_members_snapshot")
   44.22 +  :join("issue", nil, "issue.id = direct_interest_snapshot.issue_id")
   44.23 +  :add_where("direct_interest_snapshot.voting_requested = false")
   44.24 +
   44.25 +local delegations_selector = issue:get_reference_selector("delegations")
   44.26 +
   44.27 +
   44.28 +ui.tabs{
   44.29 +  module = "issue",
   44.30 +  view = "show_tab",
   44.31 +  static_params = { issue_id = issue.id },
   44.32 +  {
   44.33 +    name = "interested_members",
   44.34 +    label = _"Interested members" .. " (" .. tostring(interested_members_selector:count()) .. ")" ,
   44.35 +    icon = { static = "icons/16/eye.png" },
   44.36 +    module = "member",
   44.37 +    view = "_list",
   44.38 +    params = {
   44.39 +      issue = issue,
   44.40 +      members_selector = interested_members_selector
   44.41 +    }
   44.42 +  },
   44.43 +  {
   44.44 +    name = "voting_requests",
   44.45 +    label = _"Vote later requests" .. " (" .. tostring(voting_requests_selector:count()) .. ") (" .. tostring(voting_requested_percentage) ..  "%)",
   44.46 +    icon = { static = "icons/16/clock_play.png" },
   44.47 +    module = "member",
   44.48 +    view = "_list",
   44.49 +    params = {
   44.50 +      issue = issue,
   44.51 +      members_selector = voting_requests_selector
   44.52 +    }
   44.53 +  },
   44.54 +  {
   44.55 +    name = "delegations",
   44.56 +    label = _"Delegations" .. " (" .. tostring(delegations_selector:count()) .. ")" ,
   44.57 +    icon = { static = "icons/16/table_go.png" },
   44.58 +    module = "delegation",
   44.59 +    view = "_list",
   44.60 +    params = { delegations_selector = delegations_selector }
   44.61 +  },
   44.62 +  {
   44.63 +    name = "details",
   44.64 +    label = _"Details",
   44.65 +    icon = { static = "icons/16/magnifier.png" },
   44.66 +    module = "issue",
   44.67 +    view = "_details",
   44.68 +    params = { issue = issue }
   44.69 +  },
   44.70 +}
   44.71 +
   44.72 +
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/app/main/member/_action/update_display.lua	Sat Feb 20 22:10:31 2010 +0100
    45.3 @@ -0,0 +1,4 @@
    45.4 +app.session.member:set_setting("tab_mode", param.get("tab_mode"))
    45.5 +app.session.member:set_setting("initiatives_preview_limit", param.get("initiatives_preview_limit", atom.number))
    45.6 +
    45.7 +slot.put_into("notice", _"Your display settings have been updated")
    45.8 \ No newline at end of file
    46.1 --- a/app/main/member/_list.lua	Tue Feb 02 00:31:06 2010 +0100
    46.2 +++ b/app/main/member/_list.lua	Sat Feb 20 22:10:31 2010 +0100
    46.3 @@ -4,41 +4,45 @@
    46.4  local trustee = param.get("trustee", "table")
    46.5  local initiator = param.get("initiator", "table")
    46.6  
    46.7 -local options = {
    46.8 +ui.add_partial_param_names{ "member_list" }
    46.9 +
   46.10 +local filter = {
   46.11 +  label = _"Order by",
   46.12 +  name = "member_list",
   46.13 +  {
   46.14 +    name = "name",
   46.15 +    label = _"A-Z",
   46.16 +    selector_modifier = function(selector) selector:add_order_by("name") end
   46.17 +  },
   46.18 +  {
   46.19 +    name = "name_desc",
   46.20 +    label = _"Z-A",
   46.21 +    selector_modifier = function(selector) selector:add_order_by("name DESC") end
   46.22 +  },
   46.23    {
   46.24      name = "newest",
   46.25      label = _"Newest",
   46.26 -    order_by = "created DESC, id DESC"
   46.27 +    selector_modifier = function(selector) selector:add_order_by("created DESC, id DESC") end
   46.28    },
   46.29    {
   46.30      name = "oldest",
   46.31      label = _"Oldest",
   46.32 -    order_by = "created, id"
   46.33 -  },
   46.34 -  {
   46.35 -    name = "name",
   46.36 -    label = _"A-Z",
   46.37 -    order_by = "name"
   46.38 -  },
   46.39 -  {
   46.40 -    name = "name_desc",
   46.41 -    label = _"Z-A",
   46.42 -    order_by = "name DESC"
   46.43 +    selector_modifier = function(selector) selector:add_order_by("created, id") end
   46.44    },
   46.45  }
   46.46  
   46.47  if initiative then
   46.48 -  options[#options+1] = {
   46.49 +  filter[#filter] = {
   46.50      name = "delegations",
   46.51      label = _"Delegations",
   46.52 -    order_by = "weight DESC"
   46.53 +    selector_modifier = function(selector) selector:add_order_by("weight DESC") end
   46.54    }
   46.55  end
   46.56  
   46.57 -ui.order{
   46.58 -  name = "member_list",
   46.59 +ui.filters{
   46.60 +  label = _"Change order",
   46.61    selector = members_selector,
   46.62 -  options = options,
   46.63 +  filter,
   46.64    content = function()
   46.65      ui.paginate{
   46.66        selector = members_selector,
   46.67 @@ -118,12 +122,6 @@
   46.68                }
   46.69              end
   46.70  
   46.71 ---[[            ui.list{
   46.72 -              records = members,
   46.73 -              columns = columns
   46.74 -            }
   46.75 ---]]
   46.76 ----[[
   46.77              for i, member in ipairs(members) do
   46.78                execute.view{
   46.79                  module = "member",
   46.80 @@ -137,17 +135,11 @@
   46.81                  }
   46.82                }
   46.83              end
   46.84 ----]]
   46.85 +
   46.86            end
   46.87          }
   46.88          slot.put('<br style="clear: left;" />')
   46.89 -        if issue then
   46.90 -          ui.field.timestamp{ label = _"Last snapshot:", value = issue.snapshot }
   46.91 -        end
   46.92 -        if initiative then
   46.93 -          ui.field.timestamp{ label = _"Last snapshot:", value = initiative.issue.snapshot }
   46.94 -        end
   46.95        end
   46.96      }
   46.97    end
   46.98 -}
   46.99 \ No newline at end of file
  46.100 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/app/main/member/_profile.lua	Sat Feb 20 22:10:31 2010 +0100
    47.3 @@ -0,0 +1,114 @@
    47.4 +local member = param.get("member", "table")
    47.5 +
    47.6 +if not member then
    47.7 +  local member_id = param.get("member_id", atom.integer)
    47.8 +  if member_id then
    47.9 +    member = Member:by_id(member_id)
   47.10 +  end
   47.11 +end
   47.12 +
   47.13 +
   47.14 +ui.form{
   47.15 +  attr = { class = "member vertical" },
   47.16 +  record = member,
   47.17 +  readonly = true,
   47.18 +  content = function()
   47.19 +
   47.20 +    ui.container{
   47.21 +      attr = { class = "right" },
   47.22 +      content = function()
   47.23 +
   47.24 +      execute.view{
   47.25 +        module = "member_image",
   47.26 +        view = "_show",
   47.27 +        params = {
   47.28 +          member = member,
   47.29 +          image_type = "photo"
   47.30 +        }
   47.31 +      }
   47.32 +
   47.33 +      ui.container{
   47.34 +        attr = { class = "contact_data" },
   47.35 +        content = function()
   47.36 +        end
   47.37 +      }
   47.38 +
   47.39 +      end
   47.40 +    }
   47.41 +
   47.42 +    if member.admin then
   47.43 +      ui.field.boolean{ label = _"Admin?",       name = "admin" }
   47.44 +    end
   47.45 +    if member.locked then
   47.46 +      ui.field.boolean{ label = _"Locked?",      name = "locked" }
   47.47 +    end
   47.48 +    if member.ident_number then
   47.49 +      ui.field.text{    label = _"Ident number", name = "ident_number" }
   47.50 +    end
   47.51 +    ui.field.text{ label = _"Name", name = "name" }
   47.52 +
   47.53 +    if member.realname and #member.realname > 0 then
   47.54 +      ui.field.text{ label = _"Real name", name = "realname" }
   47.55 +    end
   47.56 +    if member.email and #member.email > 0 then
   47.57 +      ui.field.text{ label = _"email", name = "email" }
   47.58 +    end
   47.59 +    if member.xmpp_address and #member.xmpp_address > 0 then
   47.60 +      ui.field.text{ label = _"xmpp", name = "xmpp_address" }
   47.61 +    end
   47.62 +    if member.website and #member.website > 0 then
   47.63 +      ui.field.text{ label = _"Website", name = "website" }
   47.64 +    end
   47.65 +    if member.phone and #member.phone > 0 then
   47.66 +      ui.field.text{ label = _"Phone", name = "phone" }
   47.67 +    end
   47.68 +    if member.mobile_phone and #member.mobile_phone > 0 then
   47.69 +      ui.field.text{ label = _"Mobile phone", name = "mobile_phone" }
   47.70 +    end
   47.71 +    if member.address and #member.address > 0 then
   47.72 +      ui.container{
   47.73 +        content = function()
   47.74 +          ui.tag{
   47.75 +            tag = "label",
   47.76 +            attr = { class = "ui_field_label" },
   47.77 +            content = _"Address"
   47.78 +          }
   47.79 +          ui.tag{
   47.80 +            tag = "span",
   47.81 +            content = function()
   47.82 +              slot.put(encode.html_newlines(encode.html(member.address)))
   47.83 +            end
   47.84 +          }
   47.85 +        end
   47.86 +      }
   47.87 +    end
   47.88 +    if member.profession and #member.profession > 0 then
   47.89 +      ui.field.text{ label = _"Profession", name = "profession" }
   47.90 +    end
   47.91 +    if member.birthday and #member.birthday > 0 then
   47.92 +      ui.field.text{ label = _"Birthday", name = "birthday" }
   47.93 +    end
   47.94 +    if member.organizational_unit and #member.organizational_unit > 0 then
   47.95 +      ui.field.text{ label = _"Organizational unit", name = "organizational_unit" }
   47.96 +    end
   47.97 +    if member.internal_posts and #member.internal_posts > 0 then
   47.98 +      ui.field.text{ label = _"Internal posts", name = "internal_posts" }
   47.99 +    end
  47.100 +    if member.external_memberships and #member.external_memberships > 0 then
  47.101 +      ui.field.text{ label = _"Memberships", name = "external_memberships", multiline = true }
  47.102 +    end
  47.103 +    if member.external_posts and #member.external_posts > 0 then
  47.104 +      ui.field.text{ label = _"Posts", name = "external_posts", multiline = true }
  47.105 +    end
  47.106 +    slot.put('<br style="clear: right;" />')
  47.107 +
  47.108 +  end
  47.109 +}
  47.110 +if member.statement and #member.statement > 0 then
  47.111 +  ui.container{
  47.112 +    attr = { class = "member_statement wiki" },
  47.113 +    content = function()
  47.114 +      slot.put(format.wiki_text(member.statement))
  47.115 +    end
  47.116 +  }
  47.117 +end
    48.1 --- a/app/main/member/_show.lua	Tue Feb 02 00:31:06 2010 +0100
    48.2 +++ b/app/main/member/_show.lua	Sat Feb 20 22:10:31 2010 +0100
    48.3 @@ -1,191 +1,7 @@
    48.4 -local member = param.get("member", "table")
    48.5 -
    48.6 -ui.tabs{
    48.7 -  {
    48.8 -    name = "profile",
    48.9 -    label = _"Profile",
   48.10 -    content = function()
   48.11 -      ui.form{
   48.12 -        attr = { class = "member vertical" },
   48.13 -        record = member,
   48.14 -        readonly = true,
   48.15 -        content = function()
   48.16 -
   48.17 -          ui.container{
   48.18 -            attr = { class = "right" },
   48.19 -            content = function()
   48.20 -
   48.21 -            execute.view{
   48.22 -              module = "member_image",
   48.23 -              view = "_show",
   48.24 -              params = {
   48.25 -                member = member,
   48.26 -                image_type = "photo"
   48.27 -              }
   48.28 -            }
   48.29 -
   48.30 -            ui.container{
   48.31 -              attr = { class = "contact_data" },
   48.32 -              content = function()
   48.33 -              end
   48.34 -            }
   48.35 -
   48.36 -            end
   48.37 -          }
   48.38 -
   48.39 -          if member.admin then
   48.40 -            ui.field.boolean{ label = _"Admin?",       name = "admin" }
   48.41 -          end
   48.42 -          if member.locked then
   48.43 -            ui.field.boolean{ label = _"Locked?",      name = "locked" }
   48.44 -          end
   48.45 -          if member.ident_number then
   48.46 -            ui.field.text{    label = _"Ident number", name = "ident_number" }
   48.47 -          end
   48.48 -          ui.field.text{ label = _"Name", name = "name" }
   48.49 -
   48.50 -          if member.realname and #member.realname > 0 then
   48.51 -            ui.field.text{ label = _"Real name", name = "realname" }
   48.52 -          end
   48.53 -          if member.email and #member.email > 0 then
   48.54 -            ui.field.text{ label = _"email", name = "email" }
   48.55 -          end
   48.56 -          if member.xmpp_address and #member.xmpp_address > 0 then
   48.57 -            ui.field.text{ label = _"xmpp", name = "xmpp_address" }
   48.58 -          end
   48.59 -          if member.website and #member.website > 0 then
   48.60 -            ui.field.text{ label = _"Website", name = "website" }
   48.61 -          end
   48.62 -          if member.phone and #member.phone > 0 then
   48.63 -            ui.field.text{ label = _"Phone", name = "phone" }
   48.64 -          end
   48.65 -          if member.mobile_phone and #member.mobile_phone > 0 then
   48.66 -            ui.field.text{ label = _"Mobile phone", name = "mobile_phone" }
   48.67 -          end
   48.68 -          if member.address and #member.address > 0 then
   48.69 -            ui.container{
   48.70 -              content = function()
   48.71 -                ui.tag{
   48.72 -                  tag = "label",
   48.73 -                  attr = { class = "ui_field_label" },
   48.74 -                  content = _"Address"
   48.75 -                }
   48.76 -                ui.tag{
   48.77 -                  tag = "span",
   48.78 -                  content = function()
   48.79 -                    slot.put(encode.html_newlines(encode.html(member.address)))
   48.80 -                  end
   48.81 -                }
   48.82 -              end
   48.83 -            }
   48.84 -          end
   48.85 -          if member.profession and #member.profession > 0 then
   48.86 -            ui.field.text{ label = _"Profession", name = "profession" }
   48.87 -          end
   48.88 -          if member.birthday and #member.birthday > 0 then
   48.89 -            ui.field.text{ label = _"Birthday", name = "birthday" }
   48.90 -          end
   48.91 -          if member.organizational_unit and #member.organizational_unit > 0 then
   48.92 -            ui.field.text{ label = _"Organizational unit", name = "organizational_unit" }
   48.93 -          end
   48.94 -          if member.internal_posts and #member.internal_posts > 0 then
   48.95 -            ui.field.text{ label = _"Internal posts", name = "internal_posts" }
   48.96 -          end
   48.97 -          if member.external_memberships and #member.external_memberships > 0 then
   48.98 -            ui.field.text{ label = _"Memberships", name = "external_memberships", multiline = true }
   48.99 -          end
  48.100 -          if member.external_posts and #member.external_posts > 0 then
  48.101 -            ui.field.text{ label = _"Posts", name = "external_posts", multiline = true }
  48.102 -          end
  48.103 -          slot.put('<br style="clear: right;" />')
  48.104 -
  48.105 -        end
  48.106 -      }
  48.107 -      if member.statement and #member.statement > 0 then
  48.108 -        ui.container{
  48.109 -          attr = { class = "member_statement wiki" },
  48.110 -          content = function()
  48.111 -            slot.put(format.wiki_text(member.statement))
  48.112 -          end
  48.113 -        }
  48.114 -      end
  48.115 -    end
  48.116 -  },
  48.117 -  {
  48.118 -    name = "areas",
  48.119 -    label = _"Areas",
  48.120 -    content = function()
  48.121 -      execute.view{
  48.122 -        module = "area",
  48.123 -        view = "_list",
  48.124 -        params = { areas_selector = member:get_reference_selector("areas") }
  48.125 -      }
  48.126 -    end
  48.127 -  },
  48.128 -  {
  48.129 -    name = "issues",
  48.130 -    label = _"Issues",
  48.131 -    content = function()
  48.132 -      execute.view{
  48.133 -        module = "issue",
  48.134 -        view = "_list",
  48.135 -        params = { issues_selector = member:get_reference_selector("issues") }
  48.136 -      }
  48.137 -    end
  48.138 -  },
  48.139 -  {
  48.140 -    name = "supported_initiatives",
  48.141 -    label = _"Supported initiatives",
  48.142 -    content = function()
  48.143 -      execute.view{
  48.144 -        module = "initiative",
  48.145 -        view = "_list",
  48.146 -        params = { initiatives_selector = member:get_reference_selector("supported_initiatives") }
  48.147 -      }
  48.148 -    end
  48.149 -  },
  48.150 -  {
  48.151 -    name = "initiatied_initiatives",
  48.152 -    label = _"Initiated initiatives",
  48.153 -    content = function()
  48.154 -      execute.view{
  48.155 -        module = "initiative",
  48.156 -        view = "_list",
  48.157 -        params = { initiatives_selector = member:get_reference_selector("initiated_initiatives"):add_where("initiator.accepted = true") }
  48.158 -      }
  48.159 -    end
  48.160 -  },
  48.161 -  {
  48.162 -    name = "incoming_delegations",
  48.163 -    label = _"Incoming delegations",
  48.164 -    content = function()
  48.165 -      execute.view{
  48.166 -        module = "delegation",
  48.167 -        view = "_list",
  48.168 -        params = { delegations_selector = member:get_reference_selector("incoming_delegations"), incoming = true }
  48.169 -      }
  48.170 -    end
  48.171 -  },
  48.172 -  {
  48.173 -    name = "Outgoing delegations",
  48.174 -    label = _"Outgoing delegations",
  48.175 -    content = function()
  48.176 -      execute.view{
  48.177 -        module = "delegation",
  48.178 -        view = "_list",
  48.179 -        params = { delegations_selector = member:get_reference_selector("outgoing_delegations"), outgoing = true }
  48.180 -      }
  48.181 -    end
  48.182 -  },
  48.183 -  {
  48.184 -    name = "contacts",
  48.185 -    label = _"Published contacts",
  48.186 -    content = function()
  48.187 -      execute.view{
  48.188 -        module = "member",
  48.189 -        view = "_list",
  48.190 -        params = { members_selector = member:get_reference_selector("saved_members"):add_where("public") }
  48.191 -      }
  48.192 -    end
  48.193 -  },
  48.194 -}
  48.195 +execute.view{
  48.196 +  module = "member",
  48.197 +  view = "show_tab",
  48.198 +  params = { 
  48.199 +    member = param.get("member", "table")
  48.200 +  }
  48.201 +}
  48.202 \ No newline at end of file
    49.1 --- a/app/main/member/_show_thumb.lua	Tue Feb 02 00:31:06 2010 +0100
    49.2 +++ b/app/main/member/_show_thumb.lua	Sat Feb 20 22:10:31 2010 +0100
    49.3 @@ -17,12 +17,55 @@
    49.4    container_class = container_class .. " not_accepted"
    49.5  end
    49.6  
    49.7 +if member.is_informed == false then
    49.8 +  container_class = container_class .. " not_informed"
    49.9 +end
   49.10 +
   49.11  ui.container{
   49.12    attr = { class = container_class },
   49.13    content = function()
   49.14      ui.container{
   49.15        attr = { class = "flags" },
   49.16        content = function()
   49.17 +
   49.18 +        if member.grade then
   49.19 +          ui.link{
   49.20 +            module = "vote",
   49.21 +            view = "list",
   49.22 +            params = {
   49.23 +              issue_id = initiative.issue.id,
   49.24 +              member_id = member.id,
   49.25 +            },
   49.26 +            content = function()
   49.27 +              if member.grade > 0 then
   49.28 +                ui.image{
   49.29 +                  attr = { 
   49.30 +                    alt   = _"Voted yes",
   49.31 +                    title = _"Voted yes"
   49.32 +                  },
   49.33 +                  static = "icons/16/thumb_up_green.png"
   49.34 +                }
   49.35 +              elseif member.grade < 0 then
   49.36 +                ui.image{
   49.37 +                  attr = { 
   49.38 +                    alt   = _"Voted no",
   49.39 +                    title = _"Voted no"
   49.40 +                  },
   49.41 +                  static = "icons/16/thumb_down_red.png"
   49.42 +                }
   49.43 +              else
   49.44 +                ui.image{
   49.45 +                  attr = { 
   49.46 +                    alt   = _"Abstention",
   49.47 +                    title = _"Abstention"
   49.48 +                  },
   49.49 +                  static = "icons/16/bullet_yellow.png"
   49.50 +                }
   49.51 +              end
   49.52 +            end
   49.53 +          }
   49.54 +        end
   49.55 +
   49.56          local weight = 0
   49.57          if member.weight then
   49.58            weight = member.weight
   49.59 @@ -52,9 +95,8 @@
   49.60                issue_id = issue and issue.id or nil
   49.61              }
   49.62            }
   49.63 -        else
   49.64 -          slot.put("&nbsp;")
   49.65          end
   49.66 +
   49.67          if initiator and initiator.accepted then
   49.68            if member.accepted == nil then
   49.69              slot.put(_"Invited")
   49.70 @@ -62,37 +104,15 @@
   49.71              slot.put(_"Rejected")
   49.72            end
   49.73          end
   49.74 -        if member.grade then
   49.75 -          ui.container{
   49.76 -            content = function()
   49.77 -              if member.grade > 0 then
   49.78 -                ui.image{
   49.79 -                  attr = { 
   49.80 -                    alt   = _"Voted yes",
   49.81 -                    title = _"Voted yes"
   49.82 -                  },
   49.83 -                  static = "icons/16/thumb_up_green.png"
   49.84 -                }
   49.85 -              elseif member.grade < 0 then
   49.86 -                ui.image{
   49.87 -                  attr = { 
   49.88 -                    alt   = _"Voted no",
   49.89 -                    title = _"Voted no"
   49.90 -                  },
   49.91 -                  static = "icons/16/thumb_down_red.png"
   49.92 -                }
   49.93 -              else
   49.94 -                ui.image{
   49.95 -                  attr = { 
   49.96 -                    alt   = _"Abstention",
   49.97 -                    title = _"Abstention"
   49.98 -                  },
   49.99 -                  static = "icons/16/bullet_yellow.png"
  49.100 -                }
  49.101 -              end
  49.102 -            end
  49.103 +
  49.104 +        if member.is_informed == false then
  49.105 +          local text = _"Member has not approved latest draft"
  49.106 +          ui.image{
  49.107 +            attr = { alt = text, title = text },
  49.108 +            static = "icons/16/help_yellow.png"
  49.109            }
  49.110          end
  49.111 +
  49.112          if member.admin then
  49.113            ui.image{
  49.114              attr = { 
  49.115 @@ -102,6 +122,7 @@
  49.116              static = "icons/16/cog.png"
  49.117            }
  49.118          end
  49.119 +
  49.120          -- TODO performance
  49.121          local contact = Contact:by_pk(app.session.member.id, member.id)
  49.122          if contact then
    50.1 --- a/app/main/member/edit.lua	Tue Feb 02 00:31:06 2010 +0100
    50.2 +++ b/app/main/member/edit.lua	Sat Feb 20 22:10:31 2010 +0100
    50.3 @@ -39,7 +39,7 @@
    50.4      ui.field.text{ label = _"Profession", name = "profession" }
    50.5      ui.field.text{ label = _"External memberships", name = "external_memberships", multiline = true }
    50.6      ui.field.text{ label = _"External posts", name = "external_posts", multiline = true }
    50.7 -    ui.field.text{ label = _"Statement", name = "statement", multiline = true }
    50.8 +    ui.field.text{ label = _"Statement", name = "statement", multiline = true, attr = { style = "height: 10em;" } }
    50.9      ui.submit{ value = _"Save" }
   50.10    end
   50.11  }
   50.12 \ No newline at end of file
    51.1 --- a/app/main/member/settings.lua	Tue Feb 02 00:31:06 2010 +0100
    51.2 +++ b/app/main/member/settings.lua	Sat Feb 20 22:10:31 2010 +0100
    51.3 @@ -26,6 +26,55 @@
    51.4    end
    51.5  end)
    51.6  
    51.7 +ui.heading{ content = _"Display settings" }
    51.8 +util.help("member.settings.display", _"Display settings")
    51.9 +
   51.10 +ui.form{
   51.11 +  attr = { class = "vertical" },
   51.12 +  module = "member",
   51.13 +  action = "update_display",
   51.14 +  routing = {
   51.15 +    ok = {
   51.16 +      mode = "redirect",
   51.17 +      module = "index",
   51.18 +      view = "index"
   51.19 +    }
   51.20 +  },
   51.21 +  content = function()
   51.22 +    ui.field.select{
   51.23 +      label = _"Type of tabs",
   51.24 +      foreign_records = {
   51.25 +        { id = "tabs",                     name = _"Tabs" },
   51.26 +        { id = "accordeon",                name = _"Accordion (none expanded)" .. " === " .. _"EXPERIMENTAL FEATURE" .. " ===" },
   51.27 +        { id = "accordeon_first_expanded", name = _"Accordion (first expanded)" .. " === " .. _"EXPERIMENTAL FEATURE" .. " ===" },
   51.28 +--        { id = "accordeon_all_expanded",   name = _"Accordion (all expanded)" }
   51.29 +      },
   51.30 +      foreign_id = "id",
   51.31 +      foreign_name = "name",
   51.32 +      name = "tab_mode",
   51.33 +      value = app.session.member:get_setting_value("tab_mode")
   51.34 +    }
   51.35 +    ui.field.select{
   51.36 +      label = _"Number of initiatives to preview",
   51.37 +      foreign_records = {
   51.38 +        { id =  3, name = "3" },
   51.39 +        { id =  4, name = "4" },
   51.40 +        { id =  5, name = "5" },
   51.41 +        { id =  6, name = "6" },
   51.42 +        { id =  7, name = "7" },
   51.43 +        { id =  8, name = "8" },
   51.44 +        { id =  9, name = "9" },
   51.45 +        { id = 10, name = "10" },
   51.46 +      },
   51.47 +      foreign_id = "id",
   51.48 +      foreign_name = "name",
   51.49 +      name = "initiatives_preview_limit",
   51.50 +      value = app.session.member:get_setting_value("initiatives_preview_limit")
   51.51 +    }
   51.52 +    ui.submit{ value = _"Change display settings" }
   51.53 +  end
   51.54 +}
   51.55 +
   51.56  ui.heading{ content = _"Change your name" }
   51.57  util.help("member.settings.name", _"Change name")
   51.58  
    52.1 --- a/app/main/member/show.lua	Tue Feb 02 00:31:06 2010 +0100
    52.2 +++ b/app/main/member/show.lua	Sat Feb 20 22:10:31 2010 +0100
    52.3 @@ -23,13 +23,11 @@
    52.4          content = _"You have saved this member as contact."
    52.5        }
    52.6        ui.link{
    52.7 -        content = function()
    52.8 -          ui.image{ static = "icons/16/book_delete.png" }
    52.9 -          slot.put(encode.html(_"Remove from contacts"))
   52.10 -        end,
   52.11 +        image  = { static = "icons/16/book_delete.png" },
   52.12 +        text   = _"Remove from contacts",
   52.13          module = "contact",
   52.14          action = "remove_member",
   52.15 -        id = contact.other_member_id,
   52.16 +        id     = contact.other_member_id,
   52.17          routing = {
   52.18            default = {
   52.19              mode = "redirect",
   52.20 @@ -44,10 +42,8 @@
   52.21    else
   52.22      slot.select("actions", function()
   52.23        ui.link{
   52.24 -        content = function()
   52.25 -          ui.image{ static = "icons/16/book_add.png" }
   52.26 -          slot.put(encode.html(_"Add to my contacts"))
   52.27 -        end,
   52.28 +        image   = { static = "icons/16/book_add.png" },
   52.29 +        text    = _"Add to my contacts",
   52.30          module  = "contact",
   52.31          action  = "add_member",
   52.32          id      = member.id,
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/app/main/member/show_tab.lua	Sat Feb 20 22:10:31 2010 +0100
    53.3 @@ -0,0 +1,89 @@
    53.4 +local member
    53.5 +
    53.6 +if request.get_json_request_slots() then
    53.7 +  member = Member:by_id(param.get("member_id"))
    53.8 +else
    53.9 +  member = param.get("member", "table")
   53.10 +end
   53.11 +
   53.12 +local areas_selector = member:get_reference_selector("areas")
   53.13 +local issues_selector = member:get_reference_selector("issues")
   53.14 +local supported_initiatives_selector = member:get_reference_selector("supported_initiatives")
   53.15 +local initiated_initiatives_selector = member:get_reference_selector("initiated_initiatives"):add_where("initiator.accepted = true")
   53.16 +local incoming_delegations_selector = member:get_reference_selector("incoming_delegations")
   53.17 +  :left_join("issue", "_member_showtab_issue", "_member_showtab_issue.id = delegation.issue_id")
   53.18 +  :add_where("_member_showtab_issue.closed ISNULL")
   53.19 +local outgoing_delegations_selector = member:get_reference_selector("outgoing_delegations")
   53.20 +  :left_join("issue", "_member_showtab_issue", "_member_showtab_issue.id = delegation.issue_id")
   53.21 +  :add_where("_member_showtab_issue.closed ISNULL")
   53.22 +local contacts_selector = member:get_reference_selector("saved_members"):add_where("public")
   53.23 +
   53.24 +ui.tabs{
   53.25 +  module = "member",
   53.26 +  view = "show_tab",
   53.27 +  static_params = { member_id = member.id },
   53.28 +  {
   53.29 +    name = "profile",
   53.30 +    label = _"Profile",
   53.31 +    icon = { static = "icons/16/application_form.png" },
   53.32 +    module = "member",
   53.33 +    view = "_profile",
   53.34 +    params = { member = member },
   53.35 +  },
   53.36 +  {
   53.37 +    name = "areas",
   53.38 +    label = _"Areas" .. " (" .. tostring(areas_selector:count()) .. ")",
   53.39 +    icon = { static = "icons/16/package.png" },
   53.40 +    module = "area",
   53.41 +    view = "_list",
   53.42 +    params = { areas_selector = areas_selector },
   53.43 +  },
   53.44 +  {
   53.45 +    name = "issues",
   53.46 +    label = _"Issues" .. " (" .. tostring(issues_selector:count()) .. ")",
   53.47 +    icon = { static = "icons/16/folder.png" },
   53.48 +    module = "issue",
   53.49 +    view = "_list",
   53.50 +    params = { issues_selector = issues_selector },
   53.51 +  },
   53.52 +  {
   53.53 +    name = "supported_initiatives",
   53.54 +    label = _"Supported initiatives" .. " (" .. tostring(supported_initiatives_selector:count()) .. ")",
   53.55 +    icon = { static = "icons/16/thumb_up_green.png" },
   53.56 +    module = "initiative",
   53.57 +    view = "_list",
   53.58 +    params = { initiatives_selector = supported_initiatives_selector },
   53.59 +  },
   53.60 +  {
   53.61 +    name = "initiatied_initiatives",
   53.62 +    label = _"Initiated initiatives" .. " (" .. tostring(initiated_initiatives_selector:count()) .. ")",
   53.63 +    icon = { static = "icons/16/user_edit.png" },
   53.64 +    module = "initiative",
   53.65 +    view = "_list",
   53.66 +    params = { initiatives_selector = initiated_initiatives_selector },
   53.67 +  },
   53.68 +  {
   53.69 +    name = "incoming_delegations",
   53.70 +    label = _"Incoming delegations" .. " (" .. tostring(incoming_delegations_selector:count()) .. ")",
   53.71 +    icon = { static = "icons/16/table_go.png" },
   53.72 +    module = "delegation",
   53.73 +    view = "_list",
   53.74 +    params = { delegations_selector = incoming_delegations_selector, incoming = true },
   53.75 +  },
   53.76 +  {
   53.77 +    name = "outgoing_delegations",
   53.78 +    label = _"Outgoing delegations" .. " (" .. tostring(outgoing_delegations_selector:count()) .. ")",
   53.79 +    icon = { static = "icons/16/table_go.png" },
   53.80 +    module = "delegation",
   53.81 +    view = "_list",
   53.82 +    params = { delegations_selector = outgoing_delegations_selector },
   53.83 +  },
   53.84 +  {
   53.85 +    name = "contacts",
   53.86 +    label = _"Contacts" .. " (" .. tostring(contacts_selector:count()) .. ")",
   53.87 +    icon = { static = "icons/16/book_edit.png" },
   53.88 +    module = "member",
   53.89 +    view = "_list",
   53.90 +    params = { members_selector = contacts_selector },
   53.91 +  }
   53.92 +}
    54.1 --- a/app/main/membership/_show_box.lua	Tue Feb 02 00:31:06 2010 +0100
    54.2 +++ b/app/main/membership/_show_box.lua	Sat Feb 20 22:10:31 2010 +0100
    54.3 @@ -36,28 +36,28 @@
    54.4            end
    54.5          }
    54.6          ui.link{
    54.7 -          content = _"Remove my membership",
    54.8 -          module = "membership",
    54.9 -          action = "update",
   54.10 -          params = { area_id = area.id, delete = true },
   54.11 +          text    = _"Remove my membership",
   54.12 +          module  = "membership",
   54.13 +          action  = "update",
   54.14 +          params  = { area_id = area.id, delete = true },
   54.15            routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
   54.16          }
   54.17          if membership.autoreject then
   54.18            ui.field.text{ value = _"Autoreject is on." }
   54.19            ui.link{
   54.20 -            content = _"Remove autoreject",
   54.21 -            module = "membership",
   54.22 -            action = "update",
   54.23 -            params = { area_id = area.id, autoreject = false },
   54.24 +            text    = _"Remove autoreject",
   54.25 +            module  = "membership",
   54.26 +            action  = "update",
   54.27 +            params  = { area_id = area.id, autoreject = false },
   54.28              routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
   54.29            }
   54.30          else
   54.31            ui.field.text{ value = _"Autoreject is off." }
   54.32            ui.link{
   54.33 -            content = _"Set autoreject",
   54.34 -            module = "membership",
   54.35 -            action = "update",
   54.36 -            params = { area_id = area.id, autoreject = true },
   54.37 +            text    = _"Set autoreject",
   54.38 +            module  = "membership",
   54.39 +            action  = "update",
   54.40 +            params  = { area_id = area.id, autoreject = true },
   54.41              routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
   54.42            }
   54.43          end
   54.44 @@ -65,10 +65,8 @@
   54.45      }
   54.46    else
   54.47      ui.link{
   54.48 -    content = function()
   54.49 -      ui.image{ static = "icons/16/user_add.png" }
   54.50 -      slot.put(_"Become a member")
   54.51 -    end,
   54.52 +      image  = { static = "icons/16/user_add.png" },
   54.53 +      text   = _"Become a member",
   54.54        module = "membership",
   54.55        action = "update",
   54.56        params = { area_id = area.id },
    55.1 --- a/app/main/suggestion/_list.lua	Tue Feb 02 00:31:06 2010 +0100
    55.2 +++ b/app/main/suggestion/_list.lua	Sat Feb 20 22:10:31 2010 +0100
    55.3 @@ -1,61 +1,66 @@
    55.4  
    55.5  local initiative = param.get("initiative", "table")
    55.6  local suggestions_selector = param.get("suggestions_selector", "table")
    55.7 +local tab_id = param.get("tab_id")
    55.8 +local show_name = param.get("show_name", atom.boolean)
    55.9 +if show_name == nil then
   55.10 +  show_name = true
   55.11 +end
   55.12 +local show_filter = param.get("show_filter", atom.boolean)
   55.13 +if show_filter == nil then
   55.14 +  show_filter = true
   55.15 +end
   55.16  
   55.17 -ui.order{
   55.18 -  name = name,
   55.19 +local partial = {
   55.20 +  routing = {
   55.21 +    default = {
   55.22 +      mode = "redirect",
   55.23 +      module = "initiative",
   55.24 +      view = "show_tab",
   55.25 +      params = {
   55.26 +        initiative_id = initiative.id,
   55.27 +        tab = "suggestions",
   55.28 +        tab_id = tab_id
   55.29 +      },
   55.30 +    }
   55.31 +  }
   55.32 +}
   55.33 +
   55.34 +local ui_filters = ui.filters
   55.35 +if not show_filter then
   55.36 +  ui_filters = function(args) args.content() end
   55.37 +end
   55.38 +
   55.39 +ui_filters{
   55.40 +  label = _"Show filter",
   55.41    selector = suggestions_selector,
   55.42 -  options = {
   55.43 +  {
   55.44 +    label = _"Order by",
   55.45      {
   55.46 -      name = "all",
   55.47 -      label = _"all",
   55.48 -      order_by = "minus2_unfulfilled_count + minus1_unfulfilled_count + minus2_fulfilled_count + minus1_fulfilled_count + plus2_unfulfilled_count + plus1_unfulfilled_count + plus2_fulfilled_count + plus1_fulfilled_count DESC, id"
   55.49 +      name = "plus_unfulfilled",
   55.50 +      label = _"requested",
   55.51 +      selector_modifier = function(selector) selector:add_order_by("plus2_unfulfilled_count + plus1_unfulfilled_count DESC, id") end
   55.52      },
   55.53      {
   55.54        name = "plus2",
   55.55        label = _"must",
   55.56 -      order_by = "plus2_unfulfilled_count + plus2_fulfilled_count DESC, id"
   55.57 +      selector_modifier = function(selector) selector:add_order_by("plus2_unfulfilled_count + plus2_fulfilled_count DESC, id") end
   55.58      },
   55.59      {
   55.60        name = "plus",
   55.61        label = _"must/should",
   55.62 -      order_by = "plus2_unfulfilled_count + plus1_unfulfilled_count + plus2_fulfilled_count + plus1_fulfilled_count DESC, id"
   55.63 +      selector_modifier = function(selector) selector:add_order_by("plus2_unfulfilled_count + plus1_unfulfilled_count + plus2_fulfilled_count + plus1_fulfilled_count DESC, id") end
   55.64      },
   55.65      {
   55.66        name = "minus",
   55.67        label = _"must/should not",
   55.68 -      order_by = "minus2_unfulfilled_count + minus1_unfulfilled_count + minus2_fulfilled_count + minus1_fulfilled_count DESC, id"
   55.69 +      selector_modifier = function(selector) selector:add_order_by("minus2_unfulfilled_count + minus1_unfulfilled_count + minus2_fulfilled_count + minus1_fulfilled_count DESC, id") end
   55.70      },
   55.71      {
   55.72        name = "minus2",
   55.73        label = _"must not",
   55.74 -      order_by = "minus2_unfulfilled_count + minus2_fulfilled_count DESC, id"
   55.75 -    },
   55.76 -    {
   55.77 -      name = "unfulfilled",
   55.78 -      label = _"not implemented",
   55.79 -      order_by = "minus2_unfulfilled_count + minus1_unfulfilled_count + plus2_unfulfilled_count + plus1_unfulfilled_count DESC, id"
   55.80 -    },
   55.81 -    {
   55.82 -      name = "plus2_unfulfilled",
   55.83 -      label = _"must",
   55.84 -      order_by = "plus2_unfulfilled_count DESC, id"
   55.85 -    },
   55.86 -    {
   55.87 -      name = "plus_unfulfilled",
   55.88 -      label = _"must/should",
   55.89 -      order_by = "plus2_unfulfilled_count + plus1_unfulfilled_count DESC, id"
   55.90 -    },
   55.91 -    {
   55.92 -      name = "minus_unfulfilled",
   55.93 -      label = _"must/should not",
   55.94 -      order_by = "minus2_unfulfilled_count + minus1_unfulfilled_count DESC, id"
   55.95 -    },
   55.96 -    {
   55.97 -      name = "minus2_unfulfilled",
   55.98 -      label = _"must not",
   55.99 -      order_by = "minus2_unfulfilled_count DESC, id"
  55.100 -    },
  55.101 +      selector_modifier = function(selector) selector:add_order_by("minus2_unfulfilled_count + minus2_fulfilled_count DESC, id") end
  55.102 +    }
  55.103    },
  55.104    content = function()
  55.105      ui.paginate{
  55.106 @@ -66,14 +71,16 @@
  55.107            records = suggestions_selector:exec(),
  55.108            columns = {
  55.109              {
  55.110 -              label = _"Suggestion",
  55.111 +              label = show_name and _"Suggestion" or nil,
  55.112                content = function(record)
  55.113 -                ui.link{
  55.114 -                  text = record.name,
  55.115 -                  module = "suggestion",
  55.116 -                  view = "show",
  55.117 -                  id = record.id
  55.118 -                }
  55.119 +                if show_name then
  55.120 +                  ui.link{
  55.121 +                    text = record.name,
  55.122 +                    module = "suggestion",
  55.123 +                    view = "show",
  55.124 +                    id = record.id
  55.125 +                  }
  55.126 +                end
  55.127                end
  55.128              },
  55.129              {
  55.130 @@ -108,65 +115,98 @@
  55.131                  ui.container{
  55.132                    attr = { class = "suggestion_my_opinion" },
  55.133                    content = function()
  55.134 -                    ui.link{
  55.135 -                      attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
  55.136 -                      text = _"must not",
  55.137 -                      module = "opinion",
  55.138 -                      action = "update",
  55.139 -                      routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.140 -                      params = {
  55.141 -                        suggestion_id = record.id,
  55.142 -                        degree = -2
  55.143 +                    if initiative.issue.state == "voting" or initiative.issue.state == "closed" then
  55.144 +                      ui.tag{
  55.145 +                        tag = "span",
  55.146 +                        attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
  55.147 +                        content = _"must not"
  55.148 +                      }
  55.149 +                      ui.tag{
  55.150 +                        tag = "span",
  55.151 +                        attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
  55.152 +                        content = _"should not"
  55.153 +                      }
  55.154 +                      ui.tag{
  55.155 +                        tag = "span",
  55.156 +                        attr = { class = "action" .. (degree == nil and " active" or "") },
  55.157 +                        content = _"neutral"
  55.158                        }
  55.159 -                    }
  55.160 -                    slot.put(" ")
  55.161 -                    ui.link{
  55.162 -                      attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
  55.163 -                      text = _"should not",
  55.164 -                      module = "opinion",
  55.165 -                      action = "update",
  55.166 -                      routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.167 -                      params = {
  55.168 -                        suggestion_id = record.id,
  55.169 -                        degree = -1
  55.170 +                      ui.tag{
  55.171 +                        tag = "span",
  55.172 +                        attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
  55.173 +                        content = _"should"
  55.174 +                      }
  55.175 +                      ui.tag{
  55.176 +                        tag = "span",
  55.177 +                        attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
  55.178 +                        content = _"must"
  55.179 +                      }
  55.180 +                    else
  55.181 +                      ui.link{
  55.182 +                        attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
  55.183 +                        text = _"must not",
  55.184 +                        module = "opinion",
  55.185 +                        action = "update",
  55.186 +                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.187 +                        params = {
  55.188 +                          suggestion_id = record.id,
  55.189 +                          degree = -2
  55.190 +                        },
  55.191 +                        partial = partial
  55.192                        }
  55.193 -                    }
  55.194 -                    slot.put(" ")
  55.195 -                    ui.link{
  55.196 -                      attr = { class = "action" .. (degree == nil and " active" or "") },
  55.197 -                      text = _"neutral",
  55.198 -                      module = "opinion",
  55.199 -                      action = "update",
  55.200 -                      routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.201 -                      params = {
  55.202 -                        suggestion_id = record.id,
  55.203 -                        delete = true
  55.204 +                      slot.put(" ")
  55.205 +                      ui.link{
  55.206 +                        attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
  55.207 +                        text = _"should not",
  55.208 +                        module = "opinion",
  55.209 +                        action = "update",
  55.210 +                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.211 +                        params = {
  55.212 +                          suggestion_id = record.id,
  55.213 +                          degree = -1
  55.214 +                        },
  55.215 +                        partial = partial
  55.216 +                      }
  55.217 +                      slot.put(" ")
  55.218 +                      ui.link{
  55.219 +                        attr = { class = "action" .. (degree == nil and " active" or "") },
  55.220 +                        text = _"neutral",
  55.221 +                        module = "opinion",
  55.222 +                        action = "update",
  55.223 +                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.224 +                        params = {
  55.225 +                          suggestion_id = record.id,
  55.226 +                          delete = true
  55.227 +                        },
  55.228 +                        partial = partial
  55.229                        }
  55.230 -                    }
  55.231 -                    slot.put(" ")
  55.232 -                    ui.link{
  55.233 -                      attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
  55.234 -                      text = _"should",
  55.235 -                      module = "opinion",
  55.236 -                      action = "update",
  55.237 -                      routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.238 -                      params = {
  55.239 -                        suggestion_id = record.id,
  55.240 -                        degree = 1
  55.241 +                      slot.put(" ")
  55.242 +                      ui.link{
  55.243 +                        attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
  55.244 +                        text = _"should",
  55.245 +                        module = "opinion",
  55.246 +                        action = "update",
  55.247 +                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.248 +                        params = {
  55.249 +                          suggestion_id = record.id,
  55.250 +                          degree = 1
  55.251 +                        },
  55.252 +                        partial = partial
  55.253                        }
  55.254 -                    }
  55.255 -                    slot.put(" ")
  55.256 -                    ui.link{
  55.257 -                      attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
  55.258 -                      text = _"must",
  55.259 -                      module = "opinion",
  55.260 -                      action = "update",
  55.261 -                      routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.262 -                      params = {
  55.263 -                        suggestion_id = record.id,
  55.264 -                        degree = 2
  55.265 +                      slot.put(" ")
  55.266 +                      ui.link{
  55.267 +                        attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
  55.268 +                        text = _"must",
  55.269 +                        module = "opinion",
  55.270 +                        action = "update",
  55.271 +                        routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  55.272 +                        params = {
  55.273 +                          suggestion_id = record.id,
  55.274 +                          degree = 2
  55.275 +                        },
  55.276 +                        partial = partial
  55.277                        }
  55.278 -                    }
  55.279 +                    end
  55.280                    end
  55.281                  }
  55.282                end
  55.283 @@ -254,7 +294,8 @@
  55.284                        params = {
  55.285                          suggestion_id = record.id,
  55.286                          fulfilled = true
  55.287 -                      }
  55.288 +                      },
  55.289 +                      partial = partial
  55.290                      }
  55.291                    else
  55.292                      if opinion.degree > 0 then
  55.293 @@ -271,7 +312,8 @@
  55.294                        params = {
  55.295                          suggestion_id = record.id,
  55.296                          fulfilled = false
  55.297 -                      }
  55.298 +                      },
  55.299 +                      partial = partial
  55.300                      }
  55.301                    end
  55.302                  end
  55.303 @@ -295,7 +337,3 @@
  55.304      }
  55.305    end
  55.306  }
  55.307 -
  55.308 -if initiative then
  55.309 -  ui.field.timestamp{ label = _"Last snapshot:", value = initiative.issue.snapshot }
  55.310 -end
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/app/main/suggestion/_opinions.lua	Sat Feb 20 22:10:31 2010 +0100
    56.3 @@ -0,0 +1,13 @@
    56.4 +local suggestion = param.get("suggestion", "table")
    56.5 +
    56.6 +execute.view{
    56.7 +  module = "opinion",
    56.8 +  view = "_list",
    56.9 +  params = { 
   56.10 +    opinions_selector = Opinion:new_selector()
   56.11 +      :add_field("member.name", "member_name")
   56.12 +      :add_where{ "suggestion_id = ?", suggestion.id }
   56.13 +      :join("member", nil, "member.id = opinion.member_id")
   56.14 +      :add_order_by("member.id DESC")
   56.15 +  }
   56.16 +}
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/app/main/suggestion/_suggestion.lua	Sat Feb 20 22:10:31 2010 +0100
    57.3 @@ -0,0 +1,30 @@
    57.4 +local suggestion = param.get("suggestion", "table")
    57.5 +
    57.6 +ui.form{
    57.7 +  attr = { class = "vertical" },
    57.8 +  record = suggestion,
    57.9 +  readonly = true,
   57.10 +  content = function()
   57.11 +    ui.field.text{ label = _"Author",      value = suggestion.author.name }
   57.12 +    ui.field.text{ label = _"Title",        name = "name" }
   57.13 +    ui.container{
   57.14 +      attr = { class = "suggestion_content wiki" },
   57.15 +      content = function()
   57.16 +        ui.tag{
   57.17 +          tag = "p",
   57.18 +          content = suggestion.description
   57.19 +        }
   57.20 +      end
   57.21 +    }
   57.22 +  end
   57.23 +}
   57.24 +execute.view{
   57.25 +  module = "suggestion",
   57.26 +  view = "_list",
   57.27 +  params = {
   57.28 +    suggestions_selector = Suggestion:new_selector():add_where{ "id = ?", suggestion.id },
   57.29 +    initiative = suggestion.initiative,
   57.30 +    show_name = false,
   57.31 +    show_filter = false
   57.32 +  }
   57.33 +}
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/app/main/suggestion/new.lua	Sat Feb 20 22:10:31 2010 +0100
    58.3 @@ -0,0 +1,54 @@
    58.4 +local initiative_id = param.get("initiative_id")
    58.5 +
    58.6 +slot.put_into("title", _"Add new suggestion")
    58.7 +
    58.8 +slot.select("actions", function()
    58.9 +  ui.link{
   58.10 +    content = function()
   58.11 +        ui.image{ static = "icons/16/cancel.png" }
   58.12 +        slot.put(_"Cancel")
   58.13 +    end,
   58.14 +    module = "initiative",
   58.15 +    view = "show",
   58.16 +    id = initiative_id,
   58.17 +    params = { tab = "suggestions" }
   58.18 +  }
   58.19 +end)
   58.20 +
   58.21 +ui.form{
   58.22 +  module = "suggestion",
   58.23 +  action = "add",
   58.24 +  params = { initiative_id = initiative_id },
   58.25 +  routing = {
   58.26 +    default = {
   58.27 +      mode = "redirect",
   58.28 +      module = "initiative",
   58.29 +      view = "show",
   58.30 +      id = initiative_id,
   58.31 +      params = { tab = "suggestions" }
   58.32 +    }
   58.33 +  },
   58.34 +  attr = { class = "vertical" },
   58.35 +  content = function()
   58.36 +    local supported = Supporter:by_pk(initiative_id, app.session.member.id) and true or false
   58.37 +    if not supported then
   58.38 +      ui.field.text{
   58.39 +        attr = { class = "warning" },
   58.40 +        value = _"You are currently not supporting this initiative. By adding suggestions to this initiative you will automatically become a potential supporter."
   58.41 +      }
   58.42 +    end
   58.43 +    ui.field.text{ label = _"Title (80 chars max)",        name = "name" }
   58.44 +    ui.field.text{ label = _"Description", name = "description", multiline = true }
   58.45 +    ui.field.select{
   58.46 +      label = _"Degree",
   58.47 +      name = "degree",
   58.48 +      foreign_records = {
   58.49 +        { id =  1, name = _"should"},
   58.50 +        { id =  2, name = _"must"},
   58.51 +      },
   58.52 +      foreign_id = "id",
   58.53 +      foreign_name = "name"
   58.54 +    }
   58.55 +    ui.submit{ text = _"Commit suggestion" }
   58.56 +  end
   58.57 +}
    59.1 --- a/app/main/suggestion/show.lua	Tue Feb 02 00:31:06 2010 +0100
    59.2 +++ b/app/main/suggestion/show.lua	Sat Feb 20 22:10:31 2010 +0100
    59.3 @@ -11,34 +11,14 @@
    59.4      module = "initiative",
    59.5      view = "show",
    59.6      id = suggestion.initiative.id,
    59.7 -    params = { tab = "suggestion" }
    59.8 +    params = { tab = "suggestions" }
    59.9    }
   59.10  end)
   59.11  
   59.12 -ui.form{
   59.13 -  attr = { class = "vertical" },
   59.14 -  record = suggestion,
   59.15 -  readonly = true,
   59.16 -  content = function()
   59.17 -    ui.field.text{ label = _"Name",        name = "name" }
   59.18 -    ui.field.text{ label = _"Description", name = "description" }
   59.19 -  end
   59.20 -}
   59.21 -
   59.22  execute.view{
   59.23    module = "suggestion",
   59.24 -  view = "_list",
   59.25 -  params = { suggestions_selector = Suggestion:new_selector():add_where{ "id = ?", suggestion.id } }
   59.26 -}
   59.27 -
   59.28 -execute.view{
   59.29 -  module = "opinion",
   59.30 -  view = "_list",
   59.31 -  params = { 
   59.32 -    opinions_selector = Opinion:new_selector()
   59.33 -      :add_field("member.name", "member_name")
   59.34 -      :add_where{ "suggestion_id = ?", suggestion.id }
   59.35 -      :join("member", nil, "member.id = opinion.member_id")
   59.36 -      :add_order_by("member.id DESC")
   59.37 +  view = "show_tab",
   59.38 +  params = {
   59.39 +    suggestion = suggestion
   59.40    }
   59.41 -}
   59.42 +}
   59.43 \ No newline at end of file
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/app/main/suggestion/show_tab.lua	Sat Feb 20 22:10:31 2010 +0100
    60.3 @@ -0,0 +1,28 @@
    60.4 +local suggestion = param.get("suggestion", "table") or Suggestion:by_id(param.get("suggestion_id"))
    60.5 +
    60.6 +ui.tabs{
    60.7 +  module = "suggestion",
    60.8 +  view = "show_tab",
    60.9 +  static_params = {
   60.10 +    suggestion_id = suggestion.id
   60.11 +  },
   60.12 +  {
   60.13 +    name = "description",
   60.14 +    label = _"Suggestion",
   60.15 +    module = "suggestion",
   60.16 +    view = "_suggestion",
   60.17 +    params = {
   60.18 +      suggestion = suggestion
   60.19 +    }
   60.20 +  },
   60.21 +  {
   60.22 +    name = "opinions",
   60.23 +    label = _"Opinions",
   60.24 +    module = "suggestion",
   60.25 +    view = "_opinions",
   60.26 +    params = {
   60.27 +      suggestion = suggestion
   60.28 +    }
   60.29 +  }
   60.30 +}
   60.31 +
    61.1 --- a/app/main/supporter/_show_box.lua	Tue Feb 02 00:31:06 2010 +0100
    61.2 +++ b/app/main/supporter/_show_box.lua	Sat Feb 20 22:10:31 2010 +0100
    61.3 @@ -1,103 +1,109 @@
    61.4  
    61.5 -slot.select("support", function()
    61.6 -  local initiative = param.get("initiative", "table")
    61.7 -  local supporter = Supporter:by_pk(initiative.id, app.session.member.id)
    61.8 +local initiative = param.get("initiative", "table")
    61.9 +local supporter = Supporter:by_pk(initiative.id, app.session.member.id)
   61.10 +
   61.11 +local unique_string = multirand.string(16, '0123456789abcdef')
   61.12 +
   61.13 +
   61.14 +local partial = {
   61.15 +  routing = {
   61.16 +    default = {
   61.17 +      mode = "redirect",
   61.18 +      module = "initiative",
   61.19 +      view = "show_support",
   61.20 +      id = initiative.id
   61.21 +    }
   61.22 +  }
   61.23 +}
   61.24  
   61.25 -  if not initiative.issue.fully_frozen and not initiative.issue.closed then
   61.26 -    if supporter then
   61.27 -      if not supporter:has_critical_opinion() then
   61.28 -        ui.container{
   61.29 -          attr = {
   61.30 -            class = "head head_supporter",
   61.31 -            style = "cursor: pointer;",
   61.32 -            onclick = "document.getElementById('support_content').style.display = 'block';"
   61.33 -          },
   61.34 -          content = function()
   61.35 -            ui.image{
   61.36 -              static = "icons/16/thumb_up_green.png"
   61.37 -            }
   61.38 -            slot.put(_"Your are supporter")
   61.39 -            ui.image{
   61.40 -              static = "icons/16/dropdown.png"
   61.41 -            }
   61.42 -          end
   61.43 -        }
   61.44 -      else
   61.45 -        ui.container{
   61.46 -          attr = {
   61.47 -            class = "head head_potential_supporter",
   61.48 -            style = "cursor: pointer;",
   61.49 -            onclick = "document.getElementById('support_content').style.display = 'block';"
   61.50 -          },
   61.51 -          content = function()
   61.52 -            ui.image{
   61.53 -              static = "icons/16/thumb_up.png"
   61.54 -            }
   61.55 -            slot.put(_"Your are potential supporter")
   61.56 -            ui.image{
   61.57 -              static = "icons/16/dropdown.png"
   61.58 -            }
   61.59 -          end
   61.60 -        }
   61.61 -      end
   61.62 +local routing = {
   61.63 +  default = {
   61.64 +    mode = "redirect",
   61.65 +    module = request.get_module(),
   61.66 +    view = request.get_view(),
   61.67 +    id = param.get_id_cgi(),
   61.68 +    params = param.get_all_cgi()
   61.69 +  }
   61.70 +}
   61.71 +
   61.72 +if not initiative.issue.fully_frozen and not initiative.issue.closed then
   61.73 +  if supporter then
   61.74 +    if not supporter:has_critical_opinion() then
   61.75        ui.container{
   61.76 -        attr = { class = "content", id = "support_content" },
   61.77 +        attr = {
   61.78 +          class = "head head_supporter",
   61.79 +          style = "cursor: pointer;",
   61.80 +          onclick = "document.getElementById('support_content_" .. unique_string .. "').style.display = 'block';"
   61.81 +        },
   61.82          content = function()
   61.83 -          ui.container{
   61.84 -            attr = {
   61.85 -              class = "close",
   61.86 -              style = "cursor: pointer;",
   61.87 -              onclick = "document.getElementById('support_content').style.display = 'none';"
   61.88 -            },
   61.89 -            content = function()
   61.90 -              ui.image{ static = "icons/16/cross.png" }
   61.91 -            end
   61.92 +          ui.image{
   61.93 +            static = "icons/16/thumb_up_green.png"
   61.94            }
   61.95 -          if supporter then
   61.96 -            ui.link{
   61.97 -              content = function()
   61.98 -                ui.image{ static = "icons/16/thumb_down_red.png" }
   61.99 -                slot.put(_"Remove my support from this initiative")
  61.100 -              end,
  61.101 -              module = "initiative",
  61.102 -              action = "remove_support",
  61.103 -              id = initiative.id,
  61.104 -              routing = {
  61.105 -                default = {
  61.106 -                  mode = "redirect",
  61.107 -                  module = request.get_module(),
  61.108 -                  view = request.get_view(),
  61.109 -                  id = param.get_id_cgi(),
  61.110 -                  params = param.get_all_cgi()
  61.111 -                }
  61.112 -              }
  61.113 -            }
  61.114 -          else
  61.115 -          end
  61.116 +          slot.put(_"Your are supporter")
  61.117 +          ui.image{
  61.118 +            static = "icons/16/dropdown.png"
  61.119 +          }
  61.120          end
  61.121        }
  61.122      else
  61.123 -      if not initiative.revoked then
  61.124 -        ui.link{
  61.125 +      ui.container{
  61.126 +        attr = {
  61.127 +          class = "head head_potential_supporter",
  61.128 +          style = "cursor: pointer;",
  61.129 +          onclick = "document.getElementById('support_content_" .. unique_string .. "').style.display = 'block';"
  61.130 +        },
  61.131 +        content = function()
  61.132 +          ui.image{
  61.133 +            static = "icons/16/thumb_up.png"
  61.134 +          }
  61.135 +          slot.put(_"Your are potential supporter")
  61.136 +          ui.image{
  61.137 +            static = "icons/16/dropdown.png"
  61.138 +          }
  61.139 +        end
  61.140 +      }
  61.141 +    end
  61.142 +    ui.container{
  61.143 +      attr = { class = "content", id = "support_content_" .. unique_string .. "" },
  61.144 +      content = function()
  61.145 +        ui.container{
  61.146 +          attr = {
  61.147 +            class = "close",
  61.148 +            style = "cursor: pointer;",
  61.149 +            onclick = "document.getElementById('support_content_" .. unique_string .. "').style.display = 'none';"
  61.150 +          },
  61.151            content = function()
  61.152 -            ui.image{ static = "icons/16/thumb_up_green.png" }
  61.153 -            slot.put(_"Support this initiative")
  61.154 -          end,
  61.155 -          module = "initiative",
  61.156 -          action = "add_support",
  61.157 -          id = initiative.id,
  61.158 -          routing = {
  61.159 -            default = {
  61.160 -              mode = "redirect",
  61.161 -              module = request.get_module(),
  61.162 -              view = request.get_view(),
  61.163 -              id = param.get_id_cgi(),
  61.164 -              params = param.get_all_cgi()
  61.165 -            }
  61.166 +            ui.image{ static = "icons/16/cross.png" }
  61.167 +          end
  61.168 +        }
  61.169 +        if supporter then
  61.170 +          ui.link{
  61.171 +            image   = { static = "icons/16/thumb_down_red.png" },
  61.172 +            text    = _"Remove my support from this initiative",
  61.173 +            module  = "initiative",
  61.174 +            action  = "remove_support",
  61.175 +            id      = initiative.id,
  61.176 +            routing = routing,
  61.177 +            partial = partial
  61.178            }
  61.179 -        }
  61.180 +        else
  61.181 +        end
  61.182        end
  61.183 +    }
  61.184 +  else
  61.185 +    if not initiative.revoked then
  61.186 +      local params = param.get_all_cgi()
  61.187 +      params.dyn = nil
  61.188 +      ui.link{
  61.189 +        image   = { static = "icons/16/thumb_up_green.png" },
  61.190 +        text    = _"Support this initiative",
  61.191 +        module  = "initiative",
  61.192 +        action  = "add_support",
  61.193 +        id      = initiative.id,
  61.194 +        routing = routing,
  61.195 +        partial = partial
  61.196 +      }
  61.197      end
  61.198    end
  61.199 +end
  61.200  
  61.201 -end)
    62.1 --- a/app/main/timeline/_action/update.lua	Tue Feb 02 00:31:06 2010 +0100
    62.2 +++ b/app/main/timeline/_action/update.lua	Sat Feb 20 22:10:31 2010 +0100
    62.3 @@ -48,6 +48,11 @@
    62.4  end
    62.5  
    62.6  local date = param.get("date")
    62.7 +trace.debug(param.get("search_from"))
    62.8 +
    62.9 +if param.get("search_from") == "last_24h" then
   62.10 +  date = "last_24h"
   62.11 +end
   62.12  
   62.13  if date and #date > 0 then
   62.14    local setting_key = "liquidfeedback_frontend_timeline_current_date"
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/app/main/timeline/_filter/29_filter.lua	Sat Feb 20 22:10:31 2010 +0100
    63.3 @@ -0,0 +1,36 @@
    63.4 +if request.get_view() == "index" and not param.get("date") then
    63.5 +  local setting_key = "liquidfeedback_frontend_timeline_current_options"
    63.6 +  local setting = Setting:by_pk(app.session.member.id, setting_key)
    63.7 +
    63.8 +  local timeline_params = {}
    63.9 +  if setting and setting.value then
   63.10 +    for event_ident, filter_idents in setting.value:gmatch("(%S+):(%S+)") do
   63.11 +      timeline_params["option_" .. event_ident] = true
   63.12 +      if filter_idents ~= "*" then
   63.13 +        for filter_ident in filter_idents:gmatch("([^\|]+)") do
   63.14 +          timeline_params["option_" .. event_ident .. "_" .. filter_ident] = true
   63.15 +        end
   63.16 +      end
   63.17 +    end
   63.18 +  end
   63.19 +
   63.20 +  local setting_key = "liquidfeedback_frontend_timeline_current_date"
   63.21 +  local setting = Setting:by_pk(app.session.member.id, setting_key)
   63.22 +
   63.23 +  if setting then
   63.24 +    timeline_params.date = setting.value
   63.25 +  else
   63.26 +    timeline_params.date = "last_24h"
   63.27 +  end
   63.28 +
   63.29 +  timeline_params.show_options = param.get("show_options", atom.boolean)
   63.30 +
   63.31 +  request.redirect{
   63.32 +    module = "timeline",
   63.33 +    view = "index",
   63.34 +    params = timeline_params
   63.35 +  }
   63.36 +else
   63.37 +  execute.inner()
   63.38 +end
   63.39 +
    64.1 --- a/app/main/timeline/_list.lua	Tue Feb 02 00:31:06 2010 +0100
    64.2 +++ b/app/main/timeline/_list.lua	Sat Feb 20 22:10:31 2010 +0100
    64.3 @@ -21,10 +21,17 @@
    64.4                attr = { style = "font-size: 75%; font-weight: bold; background-color: #ccc; display: block; margin-bottom: 1ex;"},
    64.5                value = format.time(timeline.occurrence)
    64.6              }
    64.7 +
    64.8              ui.field.text{
    64.9                attr = { style = "font-size: 75%; font-weight: bold;"},
   64.10                value = event_names[timeline.event] or timeline.event
   64.11              }
   64.12 +            if timeline.event == "draft_created" and timeline.count > 1 then
   64.13 +              ui.field.text{
   64.14 +                attr = { style = "font-size: 75%;"},
   64.15 +                value = _("(#{more_count} duplicates removed)", { more_count = timeline.count - 1 })
   64.16 +              }
   64.17 +            end
   64.18            end
   64.19          },
   64.20          {
    65.1 --- a/app/main/timeline/index.lua	Tue Feb 02 00:31:06 2010 +0100
    65.2 +++ b/app/main/timeline/index.lua	Sat Feb 20 22:10:31 2010 +0100
    65.3 @@ -37,13 +37,10 @@
    65.4      if options_string == current_options then
    65.5        active = true
    65.6      end
    65.7 -    timeline_params.date = param.get("date")
    65.8      ui.link{
    65.9 -      attr = { class = active and "action_active" or nil },
   65.10 -      content = function()
   65.11 -        ui.image{ static = "icons/16/time.png" }
   65.12 -        slot.put(encode.html(name))
   65.13 -      end,
   65.14 +      image  = { static = "icons/16/time.png" },
   65.15 +      attr   = { class = active and "action_active" or nil },
   65.16 +      text   = name,
   65.17        module = 'timeline',
   65.18        action = 'update',
   65.19        params = {
   65.20 @@ -81,68 +78,100 @@
   65.21    action = "update",
   65.22    content = function()
   65.23  
   65.24 +    ui.container{
   65.25  
   65.26 -    ui.tag{
   65.27 -      tag = "label",
   65.28 -      attr = { style = "font-size: 130%;" },
   65.29 -      content = _"Date" .. ":"
   65.30 -    }
   65.31 -    slot.put(" ")
   65.32 -    local date = param.get("date")
   65.33 -    if not date or #date == 0 then
   65.34 -      date = tostring(db:query("select now()::date as date")[1].date)
   65.35 -    end
   65.36 -    ui.tag{
   65.37 -      tag = "input",
   65.38 -      attr = {
   65.39 -        type = "text",
   65.40 -        id = "timeline_search_date",
   65.41 -        style = "width: 10em;",
   65.42 -        onchange = "this.form.submit();",
   65.43 -        name = "date",
   65.44 -        value = date
   65.45 -      },
   65.46 -      content = function() end
   65.47 -    }
   65.48 -
   65.49 -    ui.script{ static = "gregor.js/gregor.js" }
   65.50 -    util.gregor("timeline_search_date", "document.getElementById('timeline_search_date').form.submit();")
   65.51 -
   65.52 -
   65.53 -    ui.link{
   65.54 -      attr = { style = "margin-left: 1em; font-size: 130%; font-weight: bold;", onclick = "document.getElementById('timeline_search_date').form.submit();return(false);" },
   65.55        content = function()
   65.56 -        ui.image{
   65.57 -          attr = { style = "margin-right: 0.25em;" },
   65.58 -          static = "icons/16/magnifier.png"
   65.59 +
   65.60 +        ui.tag{
   65.61 +          tag = "input",
   65.62 +          attr = {
   65.63 +            type = "radio",
   65.64 +            id = "timeline_search_last_24h",
   65.65 +            name = "search_from",
   65.66 +            value = "last_24h",
   65.67 +            checked = param.get("date") == "last_24h" and "checked" or nil
   65.68 +          },
   65.69          }
   65.70 -        slot.put(_"Search")
   65.71 -      end,
   65.72 -      external = "#",
   65.73 -    }
   65.74 -    local show_options = param.get("show_options", atom.boolean)
   65.75 -    ui.link{
   65.76 -      attr = { style = "margin-left: 1em; font-size: 130%;", onclick = "el=document.getElementById('timeline_show_options');el.checked=" .. tostring(not show_options) .. ";el.form.submit();return(false);" },
   65.77 -      content = function()
   65.78 -        ui.image{
   65.79 -          attr = { style = "margin-right: 0.25em;" },
   65.80 -          static = "icons/16/text_list_bullets.png"
   65.81 +
   65.82 +        ui.tag{
   65.83 +          tag = "label",
   65.84 +          attr = {
   65.85 +            ["for"] = "timeline_search_last_24h" 
   65.86 +          },
   65.87 +          content = " " .. _"last 24 hours" .. " "
   65.88 +        }
   65.89 +
   65.90 +        ui.tag{
   65.91 +          tag = "input",
   65.92 +          attr = {
   65.93 +            type = "radio",
   65.94 +            id = "timeline_search_from_date",
   65.95 +            name = "search_from",
   65.96 +            value = "date",
   65.97 +            checked = not (param.get("date") == "last_24h") and "checked" or nil
   65.98 +          },
   65.99          }
  65.100 -        slot.put(not show_options and _"Show filter details" or _"Hide filter details")
  65.101 -      end,
  65.102 -      external = "#",
  65.103 -    }
  65.104  
  65.105 -    ui.field.boolean{
  65.106 -      attr = { id = "timeline_show_options", style = "display: none;", onchange="this.form.submit();" },
  65.107 -      name = "show_options",
  65.108 -      value = param.get("show_options", atom.boolean)
  65.109 -    }
  65.110 +        slot.put(" ")
  65.111 +        local current_date = param.get("date")
  65.112 +        if not current_date or #current_date == 0 or current_date == "last_24h" then
  65.113 +          current_date = tostring(db:query("select now()::date as date")[1].date)
  65.114 +        end
  65.115 +        ui.tag{
  65.116 +          tag = "input",
  65.117 +          attr = {
  65.118 +            type = "text",
  65.119 +            id = "timeline_search_date",
  65.120 +            style = "width: 10em;",
  65.121 +            onchange = "this.form.submit();",
  65.122 +            onclick = "document.getElementById('timeline_search_from_date').checked = true;",
  65.123 +            name = "date",
  65.124 +            value = current_date
  65.125 +          },
  65.126 +          content = function() end
  65.127 +        }
  65.128 +    
  65.129 +        ui.script{ static = "gregor.js/gregor.js" }
  65.130 +        util.gregor("timeline_search_date", "document.getElementById('timeline_search_date').form.submit();")
  65.131 +    
  65.132 +    
  65.133 +        ui.link{
  65.134 +          attr = { style = "margin-left: 1em; font-weight: bold;", onclick = "document.getElementById('timeline_search_date').form.submit();return(false);" },
  65.135 +          content = function()
  65.136 +            ui.image{
  65.137 +              attr = { style = "margin-right: 0.25em;" },
  65.138 +              static = "icons/16/magnifier.png"
  65.139 +            }
  65.140 +            slot.put(_"Search")
  65.141 +          end,
  65.142 +          external = "#",
  65.143 +        }
  65.144 +        local show_options = param.get("show_options", atom.boolean)
  65.145 +        ui.link{
  65.146 +          attr = { style = "margin-left: 1em;", onclick = "el=document.getElementById('timeline_show_options');el.checked=" .. tostring(not show_options) .. ";el.form.submit();return(false);" },
  65.147 +          content = function()
  65.148 +            ui.image{
  65.149 +              attr = { style = "margin-right: 0.25em;" },
  65.150 +              static = "icons/16/text_list_bullets.png"
  65.151 +            }
  65.152 +            slot.put(not show_options and _"Show filter details" or _"Hide filter details")
  65.153 +          end,
  65.154 +          external = "#",
  65.155 +        }
  65.156  
  65.157 -    ui.field.boolean{
  65.158 -      attr = { id = "timeline_save", style = "display: none;", onchange="this.form.submit();" },
  65.159 -      name = "save",
  65.160 -      value = false
  65.161 +        ui.field.boolean{
  65.162 +          attr = { id = "timeline_show_options", style = "display: none;", onchange="this.form.submit();" },
  65.163 +          name = "show_options",
  65.164 +          value = param.get("show_options", atom.boolean)
  65.165 +        }
  65.166 +
  65.167 +        ui.field.boolean{
  65.168 +          attr = { id = "timeline_save", style = "display: none;", onchange="this.form.submit();" },
  65.169 +          name = "save",
  65.170 +          value = false
  65.171 +        }
  65.172 +
  65.173 +      end
  65.174      }
  65.175  
  65.176      ui.container{
  65.177 @@ -219,8 +248,6 @@
  65.178            }
  65.179          }
  65.180  
  65.181 -        slot.put("<br />")
  65.182 -
  65.183          slot.put("<table>")
  65.184  
  65.185          for i_event_group, event_group in ipairs(event_groups) do
  65.186 @@ -255,6 +282,7 @@
  65.187  }
  65.188  
  65.189  local date = param.get("date")
  65.190 +
  65.191  if not date or #date == 0 then
  65.192    date = "today"
  65.193  end
  65.194 @@ -266,24 +294,50 @@
  65.195    if param.get("option_" .. event, atom.boolean) then
  65.196  
  65.197      local tmp = Timeline:new_selector()
  65.198 -      :add_where{ "occurrence::date = ?", date }
  65.199 -
  65.200 -      :left_join("draft", nil, "draft.id = timeline.draft_id")
  65.201 -      :left_join("suggestion", nil, "suggestion.id = timeline.suggestion_id")
  65.202 -      :left_join("initiative", nil, "initiative.id = timeline.initiative_id or initiative.id = draft.initiative_id or initiative.id = suggestion.initiative_id")
  65.203 -      :left_join("issue", nil, "issue.id = timeline.issue_id or issue.id = initiative.issue_id")
  65.204 -      :left_join("area", nil, "area.id = issue.area_id")
  65.205 +      if event == "draft_created" then
  65.206 +        tmp
  65.207 +          :reset_fields()
  65.208 +          :add_field("max(timeline.occurrence)", "occurrence")
  65.209 +          :add_field("timeline.event", nil,  { "grouped" })
  65.210 +          :add_field("timeline.issue_id", nil, { "grouped" })
  65.211 +          :add_field("timeline.initiative_id", nil, { "grouped" })
  65.212 +          :add_field("max(timeline.draft_id)", "draft_id")
  65.213 +          :add_field("timeline.suggestion_id", nil, { "grouped" })
  65.214 +          :add_field("COUNT(*)", "count")
  65.215 +      else
  65.216 +        tmp
  65.217 +          :add_field("1", "count")
  65.218 +      end
  65.219  
  65.220 -      :left_join("interest", "_interest", { "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id} )
  65.221 -      :left_join("membership", "_membership", { "_membership.area_id = area.id AND _membership.member_id = ?", app.session.member.id} )
  65.222 -      :left_join("initiator", "_initiator", { "_initiator.initiative_id = initiative.id AND _initiator.member_id = ?", app.session.member.id} )
  65.223 -      :left_join("supporter", "_supporter", { "_supporter.initiative_id = initiative.id AND _supporter.member_id = ?", app.session.member.id} )
  65.224 +      if date == "last_24h" then
  65.225 +        tmp:add_where{ "occurrence > now() - '24 hours'::interval" }
  65.226 +      else
  65.227 +        tmp:add_where{ "occurrence::date = ?::date", date }
  65.228 +      end
  65.229 +      tmp
  65.230 +        :left_join("draft", nil, "draft.id = timeline.draft_id")
  65.231 +        :left_join("suggestion", nil, "suggestion.id = timeline.suggestion_id")
  65.232 +        :left_join("initiative", nil, "initiative.id = timeline.initiative_id or initiative.id = draft.initiative_id or initiative.id = suggestion.initiative_id")
  65.233 +        :left_join("issue", nil, "issue.id = timeline.issue_id or issue.id = initiative.issue_id")
  65.234 +        :left_join("area", nil, "area.id = issue.area_id")
  65.235  
  65.236 -      :add_field("(_interest.member_id NOTNULL)", "is_interested")
  65.237 -      :add_field("(_initiator.member_id NOTNULL)", "is_initiator")
  65.238 -      :add_field({"(_supporter.member_id NOTNULL) AND NOT EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1)", app.session.member.id }, "is_supporter")
  65.239 -      :add_field({"EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1)", app.session.member.id }, "is_potential_supporter")
  65.240 -  --    :left_join("member", nil, "member.id = timeline.member_id")
  65.241 +        :left_join("interest", "_interest", { "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id} )
  65.242 +        :left_join("initiator", "_initiator", { "_initiator.initiative_id = initiative.id AND _initiator.member_id = ?", app.session.member.id} )
  65.243 +        :left_join("membership", "_membership", { "_membership.area_id = area.id AND _membership.member_id = ?", app.session.member.id} )
  65.244 +        :left_join("supporter", "_supporter", { "_supporter.initiative_id = initiative.id AND _supporter.member_id = ?", app.session.member.id} )
  65.245 +
  65.246 +      local group
  65.247 +      if event == "draft_created" then
  65.248 +        group = { "grouped" }
  65.249 +      end
  65.250 +
  65.251 +      tmp
  65.252 +        :add_field("(_interest.member_id NOTNULL)", "is_interested", group)
  65.253 +        :add_field("(_initiator.member_id NOTNULL)", "is_initiator", group)
  65.254 +        :add_field({"(_supporter.member_id NOTNULL) AND NOT EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1)", app.session.member.id }, "is_supporter", group)
  65.255 +        :add_field({"EXISTS(SELECT NULL FROM opinion WHERE opinion.initiative_id = initiative.id AND opinion.member_id = ? AND ((opinion.degree = 2 AND NOT fulfilled) OR (opinion.degree = -2 AND fulfilled)) LIMIT 1)", app.session.member.id }, "is_potential_supporter", group)
  65.256 +  --    :left_join("member", nil, "member.id = timeline.member_id", group)
  65.257 +
  65.258  
  65.259      tmp:add_where{ "event = ?", event }
  65.260  
  65.261 @@ -310,7 +364,7 @@
  65.262  
  65.263      if #filters > 0 then
  65.264        local filter_string = "(" .. table.concat(filters, ") OR (") .. ")"
  65.265 -      tmp:add_where{ filter_string, app.session.member.id }
  65.266 +      tmp:add_where{ filter_string, app.session.member.id, app.session.member.id }
  65.267      end
  65.268    
  65.269      if not timeline_selector then
  65.270 @@ -327,10 +381,11 @@
  65.271    
  65.272    local outer_timeline_selector = db:new_selector()
  65.273    outer_timeline_selector._class = Timeline
  65.274 -  outer_timeline_selector:add_field{ "timeline.*" }
  65.275 -  outer_timeline_selector:from({"($)", { timeline_selector }}, "timeline" )
  65.276 -  outer_timeline_selector:add_order_by("occurrence DESC")
  65.277 -  
  65.278 +  outer_timeline_selector
  65.279 +    :add_field{ "timeline.*" }
  65.280 +    :from({"($)", { timeline_selector }}, "timeline" )
  65.281 +    :add_order_by("occurrence DESC")
  65.282 +
  65.283    slot.put("<br />")
  65.284    execute.view{
  65.285      module = "timeline",
    66.1 --- a/app/main/timeline/list_filter.lua	Tue Feb 02 00:31:06 2010 +0100
    66.2 +++ b/app/main/timeline/list_filter.lua	Sat Feb 20 22:10:31 2010 +0100
    66.3 @@ -2,10 +2,8 @@
    66.4  
    66.5  slot.select("actions", function()
    66.6    ui.link{
    66.7 -    content = function()
    66.8 -        ui.image{ static = "icons/16/cancel.png" }
    66.9 -        slot.put(_"Back to timeline")
   66.10 -    end,
   66.11 +    image  = { static = "icons/16/cancel.png" },
   66.12 +    text   = _"Back to timeline",
   66.13      module = "timeline",
   66.14      action = "update"
   66.15    }
   66.16 @@ -22,10 +20,8 @@
   66.17      {
   66.18        content = function(timeline_filter)
   66.19          ui.link{
   66.20 -          attr = { class = "action" },
   66.21 -          content = function()
   66.22 -              slot.put(_"Delete filter")
   66.23 -          end,
   66.24 +          attr   = { class = "action" },
   66.25 +          text   = _"Delete filter",
   66.26            module = "timeline",
   66.27            action = "delete_filter",
   66.28            params = { 
    67.1 --- a/app/main/vote/_action/update.lua	Tue Feb 02 00:31:06 2010 +0100
    67.2 +++ b/app/main/vote/_action/update.lua	Sat Feb 20 22:10:31 2010 +0100
    67.3 @@ -10,38 +10,145 @@
    67.4    return false
    67.5  end
    67.6  
    67.7 -local direct_voter = DirectVoter:by_pk(issue.id, app.session.member_id)
    67.8 +local move_up = param.get("move_up", atom.integer)
    67.9 +local move_down = param.get("move_down", atom.integer)
   67.10 +
   67.11 +if not move_down and not move_up then
   67.12 +  local direct_voter = DirectVoter:by_pk(issue.id, app.session.member_id)
   67.13 +
   67.14 +  if not direct_voter then
   67.15 +    direct_voter = DirectVoter:new()
   67.16 +    direct_voter.issue_id = issue.id
   67.17 +    direct_voter.member_id = app.session.member_id
   67.18 +  end
   67.19 +
   67.20 +  direct_voter.autoreject = false
   67.21 +  direct_voter:save()
   67.22 +
   67.23 +  local scoring = param.get("scoring")
   67.24  
   67.25 -if not direct_voter then
   67.26 -  direct_voter = DirectVoter:new()
   67.27 -  direct_voter.issue_id = issue.id
   67.28 -  direct_voter.member_id = app.session.member_id
   67.29 -end
   67.30 +  for initiative_id, grade in scoring:gmatch("([^:;]+):([^:;]+)") do
   67.31 +    local initiative_id = tonumber(initiative_id)
   67.32 +    local grade = tonumber(grade)
   67.33 +    local initiative = Initiative:by_id(initiative_id)
   67.34 +    if initiative.issue.id ~= issue.id then
   67.35 +      error("initiative from wrong issue")
   67.36 +    end
   67.37 +    local vote = Vote:by_pk(initiative_id, app.session.member.id)
   67.38 +    if not vote then
   67.39 +      vote = Vote:new()
   67.40 +      vote.issue_id = issue.id
   67.41 +      vote.initiative_id = initiative.id
   67.42 +      vote.member_id = app.session.member.id
   67.43 +    end
   67.44 +    vote.grade = grade
   67.45 +    vote:save()
   67.46 +  end
   67.47 +
   67.48 +else
   67.49 +
   67.50 +  local tempvoting_string = param.get("scoring")
   67.51  
   67.52 -direct_voter.autoreject = false
   67.53 +  local tempvotings = {}
   67.54 +  for match in tempvoting_string:gmatch("([^;]+)") do
   67.55 +    for initiative_id, grade in match:gmatch("([^:;]+):([^:;]+)") do
   67.56 +      tempvotings[tonumber(initiative_id)] = tonumber(grade)
   67.57 +    end
   67.58 +  end
   67.59 +
   67.60 +  local current_initiative_id = move_up or move_down
   67.61  
   67.62 -direct_voter:save()
   67.63 +  local current_grade = tempvotings[current_initiative_id] or 0
   67.64 +  local is_alone = true
   67.65 +  if current_grade == 0 then
   67.66 +    is_alone = false
   67.67 +  else
   67.68 +    for initiative_id, grade in pairs(tempvotings) do
   67.69 +      if current_initiative_id ~= initiative_id and grade == current_grade then
   67.70 +        is_alone = false
   67.71 +        break
   67.72 +      end
   67.73 +    end
   67.74 +  end
   67.75  
   67.76 -
   67.77 -local scoring = param.get("scoring")
   67.78 +  if     move_up   and current_grade >= 0 and     is_alone then
   67.79 +    for initiative_id, grade in pairs(tempvotings) do
   67.80 +      if grade > current_grade then
   67.81 +        tempvotings[initiative_id] = grade - 1
   67.82 +      end
   67.83 +    end
   67.84  
   67.85 -for initiative_id, grade in scoring:gmatch("([^:;]+):([^:;]+)") do
   67.86 -  local initiative_id = tonumber(initiative_id)
   67.87 -  local grade = tonumber(grade)
   67.88 -  local initiative = Initiative:by_id(initiative_id)
   67.89 -  if initiative.issue.id ~= issue.id then
   67.90 -    error("initiative from wrong issue")
   67.91 +  elseif move_up   and current_grade >= 0 and not is_alone then
   67.92 +    for initiative_id, grade in pairs(tempvotings) do
   67.93 +      if grade > current_grade then
   67.94 +        tempvotings[initiative_id] = grade + 1
   67.95 +      end
   67.96 +    end
   67.97 +    tempvotings[current_initiative_id] = current_grade + 1
   67.98 +
   67.99 +  elseif move_up   and current_grade  < 0 and     is_alone then
  67.100 +    tempvotings[current_initiative_id] = current_grade + 1
  67.101 +    for initiative_id, grade in pairs(tempvotings) do
  67.102 +      if grade < current_grade then
  67.103 +        tempvotings[initiative_id] = grade + 1
  67.104 +      end
  67.105 +    end
  67.106 +
  67.107 +  elseif move_up   and current_grade  < 0 and not is_alone then
  67.108 +    for initiative_id, grade in pairs(tempvotings) do
  67.109 +      if grade <= current_grade then
  67.110 +        tempvotings[initiative_id] = grade - 1
  67.111 +      end
  67.112 +    end
  67.113 +    tempvotings[current_initiative_id] = current_grade
  67.114 +
  67.115 +  elseif move_down and current_grade <= 0 and     is_alone then
  67.116 +    for initiative_id, grade in pairs(tempvotings) do
  67.117 +      if grade < current_grade then
  67.118 +        tempvotings[initiative_id] = grade + 1
  67.119 +      end
  67.120 +    end
  67.121 +
  67.122 +  elseif move_down and current_grade <= 0 and not is_alone then
  67.123 +    for initiative_id, grade in pairs(tempvotings) do
  67.124 +      if grade < current_grade then
  67.125 +        tempvotings[initiative_id] = grade - 1
  67.126 +      end
  67.127 +    end
  67.128 +    tempvotings[current_initiative_id] = current_grade - 1
  67.129 +
  67.130 +  elseif move_down and current_grade  > 0 and     is_alone then
  67.131 +    tempvotings[current_initiative_id] = current_grade - 1
  67.132 +    for initiative_id, grade in pairs(tempvotings) do
  67.133 +      if grade > current_grade then
  67.134 +        tempvotings[initiative_id] = grade - 1
  67.135 +      end
  67.136 +    end
  67.137 +
  67.138 +  elseif move_down and current_grade  > 0 and not is_alone then
  67.139 +    for initiative_id, grade in pairs(tempvotings) do
  67.140 +      if grade >= current_grade then
  67.141 +        tempvotings[initiative_id] = grade + 1
  67.142 +      end
  67.143 +    end
  67.144 +    tempvotings[current_initiative_id] = current_grade
  67.145 +
  67.146    end
  67.147 -  local vote = Vote:by_pk(initiative_id, app.session.member.id)
  67.148 -  if not vote then
  67.149 -    vote = Vote:new()
  67.150 -    vote.issue_id = issue.id
  67.151 -    vote.initiative_id = initiative.id
  67.152 -    vote.member_id = app.session.member.id
  67.153 +
  67.154 +  local tempvotings_list = {}
  67.155 +  for key, val in pairs(tempvotings) do
  67.156 +    tempvotings_list[#tempvotings_list+1] = tostring(key) .. ":" .. tostring(val)
  67.157    end
  67.158 -  vote.grade = grade
  67.159 -  vote:save()
  67.160 +
  67.161 +  tempvoting_string = table.concat(tempvotings_list, ";")
  67.162 +
  67.163 +  request.redirect{
  67.164 +    module = "vote",
  67.165 +    view = "list",
  67.166 +    params = {
  67.167 +      issue_id = issue.id,
  67.168 +      scoring = tempvoting_string
  67.169 +    }
  67.170 +  }
  67.171 +
  67.172  end
  67.173 -
  67.174 -trace.debug(scoring)
  67.175 -
    68.1 --- a/app/main/vote/list.lua	Tue Feb 02 00:31:06 2010 +0100
    68.2 +++ b/app/main/vote/list.lua	Sat Feb 20 22:10:31 2010 +0100
    68.3 @@ -1,26 +1,70 @@
    68.4 +local issue = Issue:by_id(param.get("issue_id"), atom.integer)
    68.5 +
    68.6 +local member_id = param.get("member_id", atom.integer)
    68.7 +local member
    68.8 +
    68.9 +local readonly = false
   68.10 +if member_id then
   68.11 +  if not issue.closed then
   68.12 +    error("access denied")
   68.13 +  end
   68.14 +  member = Member:by_id(member_id)
   68.15 +  readonly = true
   68.16 +end
   68.17 +
   68.18 +if member then
   68.19 +  slot.put_into("title", _("Ballot of '#{member_name}' for issue ##{issue_id}", {
   68.20 +    member_name = member.name,
   68.21 +    issue_id = issue.id
   68.22 +  }))
   68.23 +else
   68.24 +  member = app.session.member
   68.25 +  slot.put_into("title", _"Voting")
   68.26 +
   68.27 +  slot.select("actions", function()
   68.28 +    ui.link{
   68.29 +      content = function()
   68.30 +          ui.image{ static = "icons/16/cancel.png" }
   68.31 +          slot.put(_"Cancel")
   68.32 +      end,
   68.33 +      module = "issue",
   68.34 +      view = "show",
   68.35 +      id = issue.id
   68.36 +    }
   68.37 +  end)
   68.38 +  
   68.39 +end
   68.40 +
   68.41 +
   68.42  local warning_text = _"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."
   68.43  
   68.44  ui.script{ static = "js/browser_warning.js" }
   68.45  ui.script{ script = "checkBrowser(" .. encode.json(_"Your web browser is not fully supported yet." .. " " .. warning_text:gsub("\n", "\n\n")) .. ");" }
   68.46  
   68.47 -ui.tag{
   68.48 -  tag = "noscript",
   68.49 -  content = function()
   68.50 -    slot.put(_"JavaScript is disabled or not available." .. " " .. encode.html_newlines(warning_text))
   68.51 +
   68.52 +local tempvoting_string = param.get("scoring")
   68.53 +
   68.54 +local tempvotings = {}
   68.55 +if tempvoting_string then
   68.56 +  for match in tempvoting_string:gmatch("([^;]+)") do
   68.57 +    for initiative_id, grade in match:gmatch("([^:;]+):([^:;]+)") do
   68.58 +      tempvotings[tonumber(initiative_id)] = tonumber(grade)
   68.59 +    end
   68.60    end
   68.61 -}
   68.62 -
   68.63 +end
   68.64  
   68.65 -local issue = Issue:by_id(param.get("issue_id"), atom.integer)
   68.66 -
   68.67 -local initiatives = issue.initiatives
   68.68 +local initiatives = issue:get_reference_selector("initiatives"):add_where("initiative.admitted"):exec()
   68.69  
   68.70  local min_grade = -1;
   68.71  local max_grade = 1;
   68.72  
   68.73  for i, initiative in ipairs(initiatives) do
   68.74    -- TODO performance
   68.75 -  initiative.vote = Vote:by_pk(initiative.id, app.session.member.id)
   68.76 +  initiative.vote = Vote:by_pk(initiative.id, member.id)
   68.77 +  if tempvotings[initiative.id] then
   68.78 +    initiative.vote = {}
   68.79 +    initiative.vote.grade = tempvotings[initiative.id]
   68.80 +  end
   68.81    if initiative.vote then
   68.82      if initiative.vote.grade > max_grade then
   68.83        max_grade = initiative.vote.grade
   68.84 @@ -41,28 +85,59 @@
   68.85    end
   68.86  end
   68.87  
   68.88 -slot.put_into("title", _"Voting")
   68.89 +local approval_count, disapproval_count = 0, 0
   68.90 +for i = min_grade, -1 do
   68.91 +  if #sections[i] > 0 then
   68.92 +    disapproval_count = disapproval_count + 1
   68.93 +  end
   68.94 +end
   68.95 +local approval_count = 0
   68.96 +for i = 1, max_grade do
   68.97 +  if #sections[i] > 0 then
   68.98 +    approval_count = approval_count + 1
   68.99 +  end
  68.100 +end
  68.101  
  68.102 -slot.select("actions", function()
  68.103 -  ui.link{
  68.104 -    content = function()
  68.105 -        ui.image{ static = "icons/16/cancel.png" }
  68.106 -        slot.put(_"Cancel")
  68.107 -    end,
  68.108 -    module = "issue",
  68.109 -    view = "show",
  68.110 -    id = issue.id
  68.111 -  }
  68.112 -end)
  68.113 -
  68.114 -util.help("vote.list", _"Voting")
  68.115  
  68.116  
  68.117 -slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/dragdrop.js"></script>')
  68.118 -slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/voting.js"></script>')
  68.119 +if not readonly then
  68.120 +  util.help("vote.list", _"Voting")
  68.121 +  slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/dragdrop.js"></script>')
  68.122 +  slot.put('<script src="' .. request.get_relative_baseurl() .. 'static/js/voting.js"></script>')
  68.123 +end
  68.124 +
  68.125 +ui.script{
  68.126 +  script = function()
  68.127 +    slot.put(
  68.128 +      "voting_text_approval_single               = ", encode.json(_"Approval [single entry]"), ";\n",
  68.129 +      "voting_text_approval_multi                = ", encode.json(_"Approval [many entries]"), ";\n",
  68.130 +      "voting_text_first_preference_single       = ", encode.json(_"Approval (first preference) [single entry]"), ";\n",
  68.131 +      "voting_text_first_preference_multi        = ", encode.json(_"Approval (first preference) [many entries]"), ";\n",
  68.132 +      "voting_text_second_preference_single      = ", encode.json(_"Approval (second preference) [single entry]"), ";\n",
  68.133 +      "voting_text_second_preference_multi       = ", encode.json(_"Approval (second preference) [many entries]"), ";\n",
  68.134 +      "voting_text_third_preference_single       = ", encode.json(_"Approval (third preference) [single entry]"), ";\n",
  68.135 +      "voting_text_third_preference_multi        = ", encode.json(_"Approval (third preference) [many entries]"), ";\n",
  68.136 +      "voting_text_numeric_preference_single     = ", encode.json(_"Approval (#th preference) [single entry]"), ";\n",
  68.137 +      "voting_text_numeric_preference_multi      = ", encode.json(_"Approval (#th preference) [many entries]"), ";\n",
  68.138 +      "voting_text_abstention_single             = ", encode.json(_"Abstention [single entry]"), ";\n",
  68.139 +      "voting_text_abstention_multi              = ", encode.json(_"Abstention [many entries]"), ";\n",
  68.140 +      "voting_text_disapproval_above_one_single  = ", encode.json(_"Disapproval (prefer to lower block) [single entry]"), ";\n",
  68.141 +      "voting_text_disapproval_above_one_multi   = ", encode.json(_"Disapproval (prefer to lower block) [many entries]"), ";\n",
  68.142 +      "voting_text_disapproval_above_many_single = ", encode.json(_"Disapproval (prefer to lower blocks) [single entry]"), ";\n",
  68.143 +      "voting_text_disapproval_above_many_multi  = ", encode.json(_"Disapproval (prefer to lower blocks) [many entries]"), ";\n",
  68.144 +      "voting_text_disapproval_above_last_single = ", encode.json(_"Disapproval (prefer to last block) [single entry]"), ";\n",
  68.145 +      "voting_text_disapproval_above_last_multi  = ", encode.json(_"Disapproval (prefer to last block) [many entries]"), ";\n",
  68.146 +      "voting_text_disapproval_single            = ", encode.json(_"Disapproval [single entry]"), ";\n",
  68.147 +      "voting_text_disapproval_multi             = ", encode.json(_"Disapproval [many entries]"), ";\n"
  68.148 +    )
  68.149 +  end
  68.150 +}
  68.151  
  68.152  ui.form{
  68.153 -  attr = { id = "voting_form" },
  68.154 +  attr = {
  68.155 +    id = "voting_form",
  68.156 +    class = readonly and "voting_form_readonly" or "voting_form_active"
  68.157 +  },
  68.158    module = "vote",
  68.159    action = "update",
  68.160    params = { issue_id = issue.id },
  68.161 @@ -75,21 +150,42 @@
  68.162      }
  68.163    },
  68.164    content = function()
  68.165 -    slot.put('<input type="hidden" name="scoring" value=""/>')
  68.166 -    -- TODO abstrahieren
  68.167 -    ui.tag{
  68.168 -      tag = "input",
  68.169 -      attr = {
  68.170 -        type = "button",
  68.171 -        class = "voting_done",
  68.172 -        value = _"Finish voting"
  68.173 +    if not readonly then
  68.174 +      local scoring = param.get("scoring")
  68.175 +      if not scoring then
  68.176 +        for i, initiative in ipairs(initiatives) do
  68.177 +          local vote = initiative.vote
  68.178 +          if vote then
  68.179 +            tempvotings[initiative.id] = vote.grade
  68.180 +          end
  68.181 +        end
  68.182 +        local tempvotings_list = {}
  68.183 +        for key, val in pairs(tempvotings) do
  68.184 +          tempvotings_list[#tempvotings_list+1] = tostring(key) .. ":" .. tostring(val)
  68.185 +        end
  68.186 +        if #tempvotings_list > 0 then
  68.187 +          scoring = table.concat(tempvotings_list, ";")
  68.188 +        else
  68.189 +          scoring = ""
  68.190 +        end
  68.191 +      end
  68.192 +      slot.put('<input type="hidden" name="scoring" value="' .. scoring .. '"/>')
  68.193 +      -- TODO abstrahieren
  68.194 +      ui.tag{
  68.195 +        tag = "input",
  68.196 +        attr = {
  68.197 +          type = "button",
  68.198 +          class = "voting_done",
  68.199 +          value = _"Finish voting"
  68.200 +        }
  68.201        }
  68.202 -    }
  68.203 +    end
  68.204      ui.container{
  68.205        attr = { id = "voting" },
  68.206        content = function()
  68.207 +        local approval_index, disapproval_index = 0, 0
  68.208          for grade = max_grade, min_grade, -1 do 
  68.209 -          local section = sections[grade]
  68.210 +          local entries = sections[grade]
  68.211            local class
  68.212            if grade > 0 then
  68.213              class = "approval"
  68.214 @@ -98,75 +194,199 @@
  68.215            else
  68.216              class = "abstention"
  68.217            end
  68.218 -          ui.container{
  68.219 -            attr = { class = class },
  68.220 -            content = function()
  68.221 -              slot.put('<div class="cathead"></div>')
  68.222 -              for i, initiative in ipairs(section) do
  68.223 -                ui.container{
  68.224 -                  attr = {
  68.225 -                    class = "movable",
  68.226 -                    id = "entry_" .. tostring(initiative.id)
  68.227 -                  },
  68.228 -                  content = function()
  68.229 -                    local initiators_selector = initiative:get_reference_selector("initiating_members")
  68.230 -                      :add_where("accepted")
  68.231 -                    local initiators = initiators_selector:exec()
  68.232 -                    local initiator_names = {}
  68.233 -                    for i, initiator in ipairs(initiators) do
  68.234 -                      initiator_names[#initiator_names+1] = initiator.name
  68.235 +          if
  68.236 +            #entries > 0 or
  68.237 +            (grade == 1 and not approval_used) or
  68.238 +            (grade == -1 and not disapproval_used) or
  68.239 +            grade == 0
  68.240 +          then
  68.241 +            ui.container{
  68.242 +              attr = { class = class },
  68.243 +              content = function()
  68.244 +                local heading
  68.245 +                if class == "approval" then
  68.246 +                  approval_used = true
  68.247 +                  approval_index = approval_index + 1
  68.248 +                  if approval_count > 1 then
  68.249 +                    if approval_index == 1 then
  68.250 +                      if #entries == 1 then
  68.251 +                        heading = _"Approval (first preference) [single entry]"
  68.252 +                      else
  68.253 +                        heading = _"Approval (first preference) [many entries]"
  68.254 +                      end
  68.255 +                    elseif approval_index == 2 then
  68.256 +                      if #entries == 1 then
  68.257 +                        heading = _"Approval (second preference) [single entry]"
  68.258 +                      else
  68.259 +                        heading = _"Approval (second preference) [many entries]"
  68.260 +                      end
  68.261 +                    elseif approval_index == 3 then
  68.262 +                      if #entries == 1 then
  68.263 +                        heading = _"Approval (third preference) [single entry]"
  68.264 +                      else
  68.265 +                        heading = _"Approval (third preference) [many entries]"
  68.266 +                      end
  68.267 +                    else
  68.268 +                      if #entries == 1 then
  68.269 +                        heading = _"Approval (#th preference) [single entry]"
  68.270 +                      else
  68.271 +                        heading = _"Approval (#th preference) [many entries]"
  68.272 +                      end
  68.273 +                    end
  68.274 +                  else
  68.275 +                    if #entries == 1 then
  68.276 +                      heading = _"Approval [single entry]"
  68.277 +                    else
  68.278 +                      heading = _"Approval [many entries]"
  68.279 +                    end
  68.280 +                  end
  68.281 +                elseif class == "abstention" then
  68.282 +                    if #entries == 1 then
  68.283 +                      heading = _"Abstention [single entry]"
  68.284 +                    else
  68.285 +                      heading = _"Abstention [many entries]"
  68.286 +                    end
  68.287 +                elseif class == "disapproval" then
  68.288 +                  disapproval_used = true
  68.289 +                  disapproval_index = disapproval_index + 1
  68.290 +                  if disapproval_count > disapproval_index + 1 then
  68.291 +                    if #entries == 1 then
  68.292 +                      heading = _"Disapproval (prefer to lower blocks) [single entry]"
  68.293 +                    else
  68.294 +                      heading = _"Disapproval (prefer to lower blocks) [many entries]"
  68.295 +                    end
  68.296 +                  elseif disapproval_count == 2 and disapproval_index == 1 then
  68.297 +                    if #entries == 1 then
  68.298 +                      heading = _"Disapproval (prefer to lower block) [single entry]"
  68.299 +                    else
  68.300 +                      heading = _"Disapproval (prefer to lower block) [many entries]"
  68.301 +                    end
  68.302 +                  elseif disapproval_index == disapproval_count - 1 then
  68.303 +                    if #entries == 1 then
  68.304 +                      heading = _"Disapproval (prefer to last block) [single entry]"
  68.305 +                    else
  68.306 +                      heading = _"Disapproval (prefer to last block) [many entries]"
  68.307 +                    end
  68.308 +                  else
  68.309 +                    if #entries == 1 then
  68.310 +                      heading = _"Disapproval [single entry]"
  68.311 +                    else
  68.312 +                      heading = _"Disapproval [many entries]"
  68.313                      end
  68.314 -                    local initiator_names_string = table.concat(initiator_names, ", ")
  68.315 -                    ui.container{
  68.316 -                      attr = { style = "float: right;" },
  68.317 -                      content = function()
  68.318 -                        ui.link{
  68.319 -                          attr = { class = "clickable" },
  68.320 -                          content = _"Show",
  68.321 -                          module = "initiative",
  68.322 -                          view = "show",
  68.323 -                          id = initiative.id
  68.324 +                  end
  68.325 +                end
  68.326 +                ui.tag {
  68.327 +                  tag     = "div",
  68.328 +                  attr    = { class = "cathead" },
  68.329 +                  content = heading
  68.330 +                }
  68.331 +                for i, initiative in ipairs(entries) do
  68.332 +                  ui.container{
  68.333 +                    attr = {
  68.334 +                      class = "movable",
  68.335 +                      id = "entry_" .. tostring(initiative.id)
  68.336 +                    },
  68.337 +                    content = function()
  68.338 +                      local initiators_selector = initiative:get_reference_selector("initiating_members")
  68.339 +                        :add_where("accepted")
  68.340 +                      local initiators = initiators_selector:exec()
  68.341 +                      local initiator_names = {}
  68.342 +                      for i, initiator in ipairs(initiators) do
  68.343 +                        initiator_names[#initiator_names+1] = initiator.name
  68.344 +                      end
  68.345 +                      local initiator_names_string = table.concat(initiator_names, ", ")
  68.346 +                      ui.container{
  68.347 +                        attr = { style = "float: right;" },
  68.348 +                        content = function()
  68.349 +                          ui.link{
  68.350 +                            attr = { class = "clickable" },
  68.351 +                            content = _"Show",
  68.352 +                            module = "initiative",
  68.353 +                            view = "show",
  68.354 +                            id = initiative.id
  68.355 +                          }
  68.356 +                          slot.put(" ")
  68.357 +                          ui.link{
  68.358 +                            attr = { class = "clickable", target = "_blank" },
  68.359 +                            content = _"(new window)",
  68.360 +                            module = "initiative",
  68.361 +                            view = "show",
  68.362 +                            id = initiative.id
  68.363 +                          }
  68.364 +                          if not readonly then
  68.365 +                            slot.put(" ")
  68.366 +                            ui.image{ attr = { class = "grabber" }, static = "icons/grabber.png" }
  68.367 +                          end
  68.368 +                        end
  68.369 +                      }
  68.370 +                      if not readonly then
  68.371 +                        ui.container{
  68.372 +                          attr = { style = "float: left;" },
  68.373 +                          content = function()
  68.374 +                            ui.tag{
  68.375 +                              tag = "input",
  68.376 +                              attr = {
  68.377 +                                onclick = "voting_moveUp(this.parentNode.parentNode); return(false);",
  68.378 +                                name = "move_up",
  68.379 +                                value = initiative.id,
  68.380 +                                class = not disabled and "clickable" or nil,
  68.381 +                                type = "image",
  68.382 +                                src = encode.url{ static = "icons/move_up.png" },
  68.383 +                                alt = _"Move up"
  68.384 +                              }
  68.385 +                            }
  68.386 +                            slot.put("&nbsp;")
  68.387 +                            ui.tag{
  68.388 +                              tag = "input",
  68.389 +                              attr = {
  68.390 +                                onclick = "voting_moveDown(this.parentNode.parentNode); return(false);",
  68.391 +                                name = "move_down",
  68.392 +                                value = initiative.id,
  68.393 +                                class = not disabled and "clickable" or nil,
  68.394 +                                type = "image",
  68.395 +                                src = encode.url{ static = "icons/move_down.png" },
  68.396 +                                alt = _"Move down"
  68.397 +                              }
  68.398 +                            }
  68.399 +                            slot.put("&nbsp;")
  68.400 +                          end
  68.401                          }
  68.402 -                        slot.put(" ")
  68.403 -                        ui.link{
  68.404 -                          attr = { class = "clickable", target = "_blank" },
  68.405 -                          content = _"(new window)",
  68.406 -                          module = "initiative",
  68.407 -                          view = "show",
  68.408 -                          id = initiative.id
  68.409 -                        }
  68.410 -                        slot.put(" ")
  68.411 -                        ui.image{ attr = { class = "grabber" }, static = "icons/grabber.png" }
  68.412                        end
  68.413 -                    }
  68.414 -                    slot.put(encode.html(initiative.shortened_name))
  68.415 -                    if #initiators > 1 then
  68.416                        ui.container{
  68.417 -                        attr = { style = "font-size: 80%;" },
  68.418 -                        content = _"Initiators" .. ": " .. initiator_names_string
  68.419 -                      }
  68.420 -                    else
  68.421 -                      ui.container{
  68.422 -                        attr = { style = "font-size: 80%;" },
  68.423 -                        content = _"Initiator" .. ": " .. initiator_names_string
  68.424 +                        content = function()
  68.425 +                          slot.put(encode.html(initiative.shortened_name))
  68.426 +                          if #initiators > 1 then
  68.427 +                            ui.container{
  68.428 +                              attr = { style = "font-size: 80%;" },
  68.429 +                              content = _"Initiators" .. ": " .. initiator_names_string
  68.430 +                            }
  68.431 +                          else
  68.432 +                            ui.container{
  68.433 +                              attr = { style = "font-size: 80%;" },
  68.434 +                              content = _"Initiator" .. ": " .. initiator_names_string
  68.435 +                            }
  68.436 +                          end
  68.437 +                        end
  68.438                        }
  68.439                      end
  68.440 -                  end
  68.441 -                }
  68.442 +                  }
  68.443 +                end
  68.444                end
  68.445 -            end
  68.446 -          }
  68.447 +            }
  68.448 +          end
  68.449          end
  68.450        end
  68.451      }
  68.452 -    ui.tag{
  68.453 -      tag = "input",
  68.454 -      attr = {
  68.455 -        type = "button",
  68.456 -        class = "voting_done",
  68.457 -        value = _"Finish voting"
  68.458 +    if not readonly then
  68.459 +      ui.tag{
  68.460 +        tag = "input",
  68.461 +        attr = {
  68.462 +          type = "button",
  68.463 +          class = "voting_done",
  68.464 +          value = _"Finish voting"
  68.465 +        }
  68.466        }
  68.467 -    }
  68.468 +    end
  68.469    end
  68.470  }
  68.471  
    69.1 --- a/config/default.lua	Tue Feb 02 00:31:06 2010 +0100
    69.2 +++ b/config/default.lua	Sat Feb 20 22:10:31 2010 +0100
    69.3 @@ -1,5 +1,5 @@
    69.4  config.app_name = "LiquidFeedback"
    69.5 -config.app_version = "beta9"
    69.6 +config.app_version = "beta10"
    69.7  
    69.8  config.app_title = config.app_name .. " (" .. request.get_config_name() .. " environment)"
    69.9  
   69.10 @@ -27,6 +27,11 @@
   69.11  
   69.12  config.download_use_terms = "=== Nutzungsbedingungen ===\nAlles ist verboten"
   69.13  
   69.14 +request.set_allowed_json_request_slots{ "title", "actions", "support", "default", "trace", "system_error" }
   69.15 +
   69.16 +if request.get_json_request_slots() then
   69.17 +  request.force_absolute_baseurl()
   69.18 +end
   69.19  
   69.20  request.set_404_route{ module = 'index', view = '404' }
   69.21  
    70.1 --- a/env/ui/bargraph.lua	Tue Feb 02 00:31:06 2010 +0100
    70.2 +++ b/env/ui/bargraph.lua	Sat Feb 20 22:10:31 2010 +0100
    70.3 @@ -1,21 +1,33 @@
    70.4  function ui.bargraph(args)
    70.5 +  local text = ""
    70.6 +  for i, bar in ipairs(args.bars) do
    70.7 +    if #text > 0 then
    70.8 +      text = text .. " / "
    70.9 +    end
   70.10 +    text = text .. tostring(bar.value)
   70.11 +  end
   70.12    ui.container{
   70.13      attr = {
   70.14 -      class = "bargraph",
   70.15 +      class = args.class or "bargraph",
   70.16 +      title = tostring(text)
   70.17      },
   70.18      content = function()
   70.19 +      local at_least_one_bar = false
   70.20        for i, bar in ipairs(args.bars) do
   70.21          if bar.value > 0 then
   70.22 +          at_least_one_bar = true
   70.23            local value = bar.value * args.width / args.max_value
   70.24            ui.container{
   70.25              attr = {
   70.26                style = "width: " .. tostring(value) .. "px; background-color: " .. bar.color .. ";",
   70.27 -              title = tostring(bar.value)
   70.28              },
   70.29              content = function() slot.put("&nbsp;") end
   70.30            }
   70.31          end
   70.32        end
   70.33 +      if not at_least_one_bar then
   70.34 +        slot.put("&nbsp;")
   70.35 +      end
   70.36      end
   70.37    }
   70.38  end
    71.1 --- a/env/ui/field/rank.lua	Tue Feb 02 00:31:06 2010 +0100
    71.2 +++ b/env/ui/field/rank.lua	Sat Feb 20 22:10:31 2010 +0100
    71.3 @@ -5,11 +5,11 @@
    71.4        attr = { class = "rank" },
    71.5        content = function()
    71.6          if value == 1 then
    71.7 -            ui.image{ static = "icons/16/award_star_gold_2.png" }
    71.8 +            ui.image{ attr = args.image_attr, static = "icons/16/award_star_gold_2.png" }
    71.9          elseif value then
   71.10 -            ui.image{ static = "icons/16/award_star_silver_2.png" }
   71.11 +            ui.image{ attr = args.image_attr, static = "icons/16/award_star_silver_2.png" }
   71.12          else
   71.13 -            ui.image{ static = "icons/16/cross.png" }
   71.14 +            ui.image{ attr = args.image_attr, static = "icons/16/cross.png" }
   71.15          end
   71.16          if value then
   71.17            ui.tag{
    72.1 --- a/env/ui/filter.lua	Tue Feb 02 00:31:06 2010 +0100
    72.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.3 @@ -1,40 +0,0 @@
    72.4 -function ui.filter(args)
    72.5 -  local name = args.name or "filter"
    72.6 -  local current_filter = atom.string:load(cgi.params[name]) or args.filters[1].name
    72.7 -  local id     = param.get_id_cgi()
    72.8 -  local params = param.get_all_cgi()
    72.9 -  ui.container{
   72.10 -    attr = { class = "ui_filter" },
   72.11 -    content = function()
   72.12 -      ui.container{
   72.13 -        attr = { class = "ui_filter_head" },
   72.14 -        content = function()
   72.15 -          slot.put(_"Filter")
   72.16 -          slot.put(": ")
   72.17 -          for i, filter in ipairs(args.filters) do
   72.18 -            params[name] = filter.name
   72.19 -            local attr = {}
   72.20 -            if current_filter == filter.name then
   72.21 -              attr.class = "active"
   72.22 -              filter.selector_modifier(args.selector, true)
   72.23 -            end
   72.24 -            ui.link{
   72.25 -              attr    = attr,
   72.26 -              module  = request.get_module(),
   72.27 -              view    = request.get_view(),
   72.28 -              id      = id,
   72.29 -              params  = params,
   72.30 -              content = filter.label
   72.31 -            }
   72.32 -          end
   72.33 -        end
   72.34 -      }
   72.35 -      ui.container{
   72.36 -        attr = { class = "ui_filter_content" },
   72.37 -        content = function()
   72.38 -          args.content()
   72.39 -        end
   72.40 -      }
   72.41 -    end
   72.42 -  }
   72.43 -end
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/env/ui/is_for_partial_load.lua	Sat Feb 20 22:10:31 2010 +0100
    73.3 @@ -0,0 +1,3 @@
    73.4 +function ui.is_for_partial_load()
    73.5 +  return ui._partial_load
    73.6 +end
    73.7 \ No newline at end of file
    74.1 --- a/env/ui/order.lua	Tue Feb 02 00:31:06 2010 +0100
    74.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.3 @@ -1,44 +0,0 @@
    74.4 -function ui.order(args)
    74.5 -  local name = args.name or "order"
    74.6 -  local current_order = atom.string:load(cgi.params[name]) or args.options[1].name
    74.7 -  local id     = param.get_id_cgi()
    74.8 -  local params = param.get_all_cgi()
    74.9 -  ui.container{
   74.10 -    attr = { class = "ui_order" },
   74.11 -    content = function()
   74.12 -      ui.container{
   74.13 -        attr = { class = "ui_order_head" },
   74.14 -        content = function()
   74.15 -          slot.put(_"Order by")
   74.16 -          slot.put(": ")
   74.17 -          for i, option in ipairs(args.options) do
   74.18 -            params[name] = option.name
   74.19 -            local attr = {}
   74.20 -            if current_order == option.name then
   74.21 -              attr.class = "active"
   74.22 -              if option.selector_modifier then
   74.23 -                option.selector_modifier(args.selector)
   74.24 -              else
   74.25 -                args.selector:add_order_by(option.order_by)
   74.26 -              end
   74.27 -            end
   74.28 -            ui.link{
   74.29 -              attr    = attr,
   74.30 -              module  = request.get_module(),
   74.31 -              view    = request.get_view(),
   74.32 -              id      = id,
   74.33 -              params  = params,
   74.34 -              content = option.label
   74.35 -            }
   74.36 -          end
   74.37 -        end
   74.38 -      }
   74.39 -      ui.container{
   74.40 -        attr = { class = "ui_order_content" },
   74.41 -        content = function()
   74.42 -          args.content()
   74.43 -        end
   74.44 -      }
   74.45 -    end
   74.46 -  }
   74.47 -end
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/env/ui/partial_load.lua	Sat Feb 20 22:10:31 2010 +0100
    75.3 @@ -0,0 +1,55 @@
    75.4 +function ui.partial_load(args)
    75.5 +  local hourglass_target = ui._partial.hourglass_target
    75.6 +  local target           = ui._partial.target
    75.7 +  local id               = param.get_id_cgi()
    75.8 +  local module           = ui._partial.module
    75.9 +  local view             = ui._partial.view
   75.10 +  local cgi_params       = cgi.params
   75.11 +
   75.12 +  local params = {
   75.13 +  }
   75.14 +
   75.15 +  if ui._partial and ui._partial.static_params then
   75.16 +    for key, value in pairs(ui._partial.static_params) do
   75.17 +      params[key] = value
   75.18 +    end
   75.19 +  end
   75.20 +  if ui._partial and ui._partial.params then
   75.21 +    for i, param_name in ipairs(ui._partial.params) do
   75.22 +      params[param_name] = cgi_params[param_name]
   75.23 +    end
   75.24 +  end
   75.25 +  if args.params then
   75.26 +    for key, value in pairs(args.params) do
   75.27 +      params[key] = value
   75.28 +    end
   75.29 +  end
   75.30 +
   75.31 +  request.force_absolute_baseurl()
   75.32 +
   75.33 +  return
   75.34 +    'var hourglass_el = document.getElementById("' .. hourglass_target .. '");' ..
   75.35 +    'var hourglass_src = hourglass_el.src;' ..
   75.36 +    'hourglass_el.src = "' .. encode.url{ static = "icons/16/connect.png" } .. '";' ..
   75.37 +    'partialMultiLoad(' ..
   75.38 +      '{ trace: "trace", system_error: "system_error", ' .. target .. ': "default" },' ..
   75.39 +    '{},' ..
   75.40 +    '"error",' ..
   75.41 +    '"' .. encode.url{
   75.42 +      module = module,
   75.43 +      view = view,
   75.44 +      id = id,
   75.45 +      params = params
   75.46 +      } .. '&_webmcp_json_slots[]=default&_webmcp_json_slots[]=trace&_webmcp_json_slots[]=system_error",' ..
   75.47 +    '{},' ..
   75.48 +    '{},' ..
   75.49 +    'function() {' ..
   75.50 +      'hourglass_el.src = hourglass_src;' ..
   75.51 +    '},' ..
   75.52 +    'function() {' ..
   75.53 +      'hourglass_el.src = hourglass_src;' ..
   75.54 +    '}' ..
   75.55 +  '); ' ..
   75.56 +  'return(false);'
   75.57 +end
   75.58 +
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/env/ui/partial_set_param_names.lua	Sat Feb 20 22:10:31 2010 +0100
    76.3 @@ -0,0 +1,6 @@
    76.4 +function ui.partial_set_param_names(args)
    76.5 +  if not ui._partial then
    76.6 +    ui._partial = {}
    76.7 +  end
    76.8 +  ui._partial.params = args
    76.9 +end
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/env/ui/set_for_partial_load.lua	Sat Feb 20 22:10:31 2010 +0100
    77.3 @@ -0,0 +1,3 @@
    77.4 +function ui.set_for_partial_load()
    77.5 +  ui._partial_load = true
    77.6 +end
    77.7 \ No newline at end of file
    78.1 --- a/env/ui/tabs.lua	Tue Feb 02 00:31:06 2010 +0100
    78.2 +++ b/env/ui/tabs.lua	Sat Feb 20 22:10:31 2010 +0100
    78.3 @@ -1,41 +1,239 @@
    78.4 -function ui.tabs(tabs)
    78.5 -  ui.container{
    78.6 -    attr = { class = "ui_tabs" },
    78.7 -    content = function()
    78.8 +if config.user_tab_mode == "accordeon" or config.user_tab_mode == "accordeon_first_expanded" or config.user_tab_mode == "accordeon_all_expanded" then
    78.9 +
   78.10 +  function ui.tabs(tabs)
   78.11 +    local params = param.get_all_cgi()
   78.12 +    local current_tabs_string = params["tab"]
   78.13 +    local current_tabs = {}
   78.14 +    if current_tabs_string then
   78.15 +      for current_tab in current_tabs_string:gmatch("([^%|]+)") do
   78.16 +        current_tabs[current_tab] = current_tab
   78.17 +      end
   78.18 +    end
   78.19 +
   78.20 +    local unique_string = param.get("tab_id") or multirand.string(16, '0123456789abcdef')
   78.21 +
   78.22 +    function render_tab(tab, first)
   78.23        local params = param.get_all_cgi()
   78.24 -      local current_tab = params["tab"]
   78.25 -      ui.container{
   78.26 -        attr = { class = "ui_tabs_links" },
   78.27 +      local active = false
   78.28 +      for current_tab in pairs(current_tabs) do
   78.29 +        if tab.name == current_tab then
   78.30 +          active = true
   78.31 +        end
   78.32 +      end
   78.33 +      if config.user_tab_mode == "accordeon_first_expanded" then
   78.34 +        if first and current_tabs_string == nil then
   78.35 +          active = true
   78.36 +        end
   78.37 +      end
   78.38 +      local link_tabs = {}
   78.39 +      if config.user_tab_mode == "accordeon" 
   78.40 +        or config.user_tab_mode == "accordeon_first_expanded"
   78.41 +        or config.user_tab_mode == "accordeon_all_expanded" and current_tabs_string
   78.42 +      then
   78.43 +        if not current_tabs_string and not first then
   78.44 +          link_tabs[tabs[1].name] = true
   78.45 +        end
   78.46 +        for current_tab in pairs(current_tabs) do
   78.47 +          if current_tab ~= tab.name then
   78.48 +            link_tabs[current_tab] = true
   78.49 +          end
   78.50 +        end
   78.51 +      elseif config.user_tab_mode == "accordeon_all_expanded" and not current_tabs_string then
   78.52 +        for i, current_tab in ipairs(tabs) do
   78.53 +          if current_tab.name ~= tab.name then
   78.54 +            link_tabs[current_tab.name] = true
   78.55 +          end
   78.56 +        end
   78.57 +      end
   78.58 +      if not active then
   78.59 +        link_tabs[tab.name] = true
   78.60 +      end
   78.61 +      local link_tab_string = ""
   78.62 +      for link_tab in pairs(link_tabs) do
   78.63 +        if #link_tab_string > 0 then
   78.64 +          link_tab_string = link_tab_string .. "|"
   78.65 +        end
   78.66 +        link_tab_string = link_tab_string .. link_tab
   78.67 +      end
   78.68 +      params["tab"] = link_tab_string
   78.69 +      local onclick
   78.70 +      if not tab.content then
   78.71 +        onclick =
   78.72 +          'if (ui_tabs_active["' .. unique_string .. '"]["' .. tab.name .. '"]) {' ..
   78.73 +            'el=document.getElementById("tab' .. unique_string .. '_content_' .. tab.name .. '");' ..
   78.74 +            'el.innerHTML="";' ..
   78.75 +            'el.style.display="none";' ..
   78.76 +            'ui_tabs_active["' .. unique_string .. '"]["' .. tab.name .. '"]=false' ..
   78.77 +          '} else {' ..
   78.78 +            'ui_tabs_active["' .. unique_string .. '"]["' .. tab.name .. '"]=true;' ..
   78.79 +            'document.getElementById("tab' .. unique_string .. '_content_' .. tab.name .. '").style.display="block"; ' ..
   78.80 +            ui._partial_load_js{
   78.81 +              params = { tab = tab.name }
   78.82 +            } ..
   78.83 +          '};' ..
   78.84 +          'return(false);'
   78.85 +      end
   78.86 +      ui.link{
   78.87 +        attr = {
   78.88 +          name = "tab_" .. tab.name,
   78.89 +          class = (
   78.90 +            tab.name == current_tab and "ui_tabs_accordeon_head selected" or
   78.91 +            not current_tab and i == 1 and "ui_tabs_accordeon_head selected" or
   78.92 +            "ui_tabs_accordeon_head"
   78.93 +          ),
   78.94 +          id = "tab" .. unique_string .. "_head_" .. tab.name,
   78.95 +          onclick = onclick,
   78.96 +        },
   78.97 +        module  = request.get_module(),
   78.98 +        view    = request.get_view(),
   78.99 +        id      = param.get_id_cgi(),
  78.100 +        params  = params,
  78.101 +        anchor  = "tab" .. unique_string .. "_" .. tab.name,
  78.102          content = function()
  78.103 -          for i, tab in ipairs(tabs) do
  78.104 -            params["tab"] = i > 1 and tab.name or nil
  78.105 -            ui.link{
  78.106 -              attr = { 
  78.107 -                class = (
  78.108 -                  tab.name == current_tab and "selected" or
  78.109 -                  not current_tab and i == 1 and "selected" or
  78.110 -                  ""
  78.111 -                )
  78.112 -              },
  78.113 -              module = request.get_module(),
  78.114 -              view = request.get_view(),
  78.115 -              id = param.get_id_cgi(),
  78.116 -              text = tab.label,
  78.117 -              params = params
  78.118 +          if tab.icon then
  78.119 +            if not tab.icon.attr then
  78.120 +              tab.icon.attr = {}
  78.121 +            end
  78.122 +            tab.icon.attr.id = "tab" .. unique_string .. "_icon_" .. tab.name
  78.123 +            tab.icon.attr.width = 16
  78.124 +            tab.icon.attr.height = 16
  78.125 +            ui.image(tab.icon)
  78.126 +          end
  78.127 +          slot.put(tab.label)
  78.128 +        end
  78.129 +      }
  78.130 +      local expanded = active or not request.get_json_request_slots() and config.user_tab_mode == "accordeon_all_expanded" and not current_tabs_string
  78.131 +      ui.container{
  78.132 +        attr = {
  78.133 +          class = "ui_tabs_accordeon_content",
  78.134 +          style = not expanded and "display: none;" or nil,
  78.135 +          id = "tab" .. unique_string .. "_content_" .. tab.name
  78.136 +        },
  78.137 +        content = function()
  78.138 +          if expanded then
  78.139 +            ui.script{ script = 'ui_tabs_active["' .. unique_string .. '"]["' .. tab.name .. '"] = true;' }
  78.140 +            execute.view{
  78.141 +              module = tab.module,
  78.142 +              view = tab.view,
  78.143 +              id = tab.id,
  78.144 +              params = tab.params
  78.145              }
  78.146 -            slot.put(" ")
  78.147 +          else
  78.148 +            slot.put("&nbsp;")
  78.149            end
  78.150          end
  78.151        }
  78.152 +    end
  78.153 +
  78.154 +    if not request.get_json_request_slots() or not current_tabs_string then
  78.155 +      ui.script{ script = "ui_tabs_active['" .. unique_string .. "'] = {};" }
  78.156 +      ui.container{
  78.157 +        attr = { class = "ui_tabs" },
  78.158 +        content = function()
  78.159 +          for i, tab in ipairs(tabs) do
  78.160 +            local static_params = tabs.static_params or {}
  78.161 +            static_params.tab = tab.name
  78.162 +            static_params.tab_id = unique_string
  78.163 +            ui.partial{
  78.164 +              module           = tabs.module,
  78.165 +              view             = tabs.view,
  78.166 +              id               = tabs.id,
  78.167 +              params           = static_params,
  78.168 +              param_names      = { "page" },
  78.169 +              hourglass_target = "tab" .. unique_string .. "_icon_" .. tab.name,
  78.170 +              target           = "tab" .. unique_string .. "_content_" .. tab.name,
  78.171 +              content = function()
  78.172 +                render_tab(tab, i == 1)
  78.173 +              end
  78.174 +            }
  78.175 +          end
  78.176 +        end
  78.177 +      }
  78.178 +    else
  78.179 +      local dyntab
  78.180        for i, tab in ipairs(tabs) do
  78.181 -        if tab.name == current_tab or not current_tab and i == 1 then
  78.182 -          ui.container{
  78.183 -            attr = { class = "ui_tabs_content" },
  78.184 -            content = tab.content
  78.185 -          }
  78.186 +        if tab.name == current_tabs_string then
  78.187 +          dyntab = tab
  78.188          end
  78.189        end
  78.190 +      if dyntab then
  78.191 +        local static_params = tabs.static_params or {}
  78.192 +        static_params.tab = dyntab.name
  78.193 +        static_params.tab_id = unique_string
  78.194 +        dyntab.params.tab_id = unique_string
  78.195 +        ui.partial{
  78.196 +          module           = tabs.module,
  78.197 +          view             = tabs.view,
  78.198 +          id               = tabs.id,
  78.199 +          params           = static_params,
  78.200 +          param_names      = { "page" },
  78.201 +          hourglass_target = "tab" .. unique_string .. "_icon_" .. dyntab.name,
  78.202 +          target           = "tab" .. unique_string .. "_content_" .. dyntab.name,
  78.203 +          content = function()
  78.204 +            execute.view{
  78.205 +              module = dyntab.module,
  78.206 +              view   = dyntab.view,
  78.207 +              id     = dyntab.id,
  78.208 +              params = dyntab.params,
  78.209 +            }
  78.210 +          end
  78.211 +        }
  78.212 +      end
  78.213      end
  78.214 -  }
  78.215 -end
  78.216 +  end
  78.217 +
  78.218 +else -- 'classic tab'
  78.219  
  78.220 +  function ui.tabs(tabs)
  78.221 +    ui.container{
  78.222 +      attr = { class = "ui_tabs" },
  78.223 +      content = function()
  78.224 +        local params = param.get_all_cgi()
  78.225 +        local current_tab = params["tab"]
  78.226 +        ui.container{
  78.227 +          attr = { class = "ui_tabs_links" },
  78.228 +          content = function()
  78.229 +            for i, tab in ipairs(tabs) do
  78.230 +              params["tab"] = i > 1 and tab.name or nil
  78.231 +              ui.link{
  78.232 +                attr = { 
  78.233 +                  class = (
  78.234 +                    tab.name == current_tab and "selected" or
  78.235 +                    not current_tab and i == 1 and "selected" or
  78.236 +                    ""
  78.237 +                  )
  78.238 +                },
  78.239 +                module  = request.get_module(),
  78.240 +                view    = request.get_view(),
  78.241 +                id      = param.get_id_cgi(),
  78.242 +                content = tab.label,
  78.243 +                params  = params
  78.244 +              }
  78.245 +              slot.put(" ")
  78.246 +            end
  78.247 +          end
  78.248 +        }
  78.249 +        for i, tab in ipairs(tabs) do
  78.250 +          if tab.name == current_tab or not current_tab and i == 1 then
  78.251 +            ui.container{
  78.252 +              attr = { class = "ui_tabs_content" },
  78.253 +              content = function()
  78.254 +                if tab.content then
  78.255 +                  tab.content()
  78.256 +                else
  78.257 +                  execute.view{
  78.258 +                    module = tab.module,
  78.259 +                    view   = tab.view,
  78.260 +                    id     = tab.id,
  78.261 +                    params = tab.params,
  78.262 +                  }
  78.263 +                end
  78.264 +              end
  78.265 +            }
  78.266 +          end
  78.267 +        end
  78.268 +      end
  78.269 +    }
  78.270 +  end
  78.271 +
  78.272 +end
  78.273 \ No newline at end of file
    79.1 --- a/env/util/help.lua	Tue Feb 02 00:31:06 2010 +0100
    79.2 +++ b/env/util/help.lua	Sat Feb 20 22:10:31 2010 +0100
    79.3 @@ -13,7 +13,7 @@
    79.4            attr = { class = "help_actions" },
    79.5            content = function()
    79.6              ui.link{
    79.7 -              content = _"Hide this help message",
    79.8 +              text   = _"Hide this help message",
    79.9                module = "help",
   79.10                action = "update",
   79.11                params = {
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/locale/help/member.settings.display.de.txt	Sat Feb 20 22:10:31 2010 +0100
    80.3 @@ -0,0 +1,1 @@
    80.4 +Hier kannst du persönliche Einstellungen in Bezug auf die optische Darstellung der Bedienoberfläche von LiquidFeedback tätigen.
    81.1 --- a/locale/translations.de.lua	Tue Feb 02 00:31:06 2010 +0100
    81.2 +++ b/locale/translations.de.lua	Sat Feb 20 22:10:31 2010 +0100
    81.3 @@ -1,22 +1,28 @@
    81.4  #!/usr/bin/env lua
    81.5  return {
    81.6 -["#{count} more initiatives"] = "#{count} weitere Initiativen";
    81.7  ["#{interested_issues_to_vote_count} issue(s) you are interested in"] = "#{interested_issues_to_vote_count} Themen, die Dich interessieren";
    81.8  ["#{issues_to_vote_count} issue(s)"] = "#{issues_to_vote_count} Themen";
    81.9  ["#{number} Image(s) has been deleted"] = "Es wurde(n) #{number} Bild(er) gelöscht";
   81.10  ["#{number} Image(s) has been updated"] = "Es wurde(n) #{number} Bild(er) aktualisiert";
   81.11 +["(#{more_count} duplicates removed)"] = "(#{more_count} Duplikate entfernt)";
   81.12  ["(change URL)"] = "(URL ändern)";
   81.13  ["(new window)"] = "(neues Fenster)";
   81.14  ["+ #{weight}"] = "+ #{weight}";
   81.15  ["A-Z"] = "A-Z";
   81.16  ["About"] = "About";
   81.17 +["About / Impressum"] = false;
   81.18  ["About LiquidFeedback"] = "Über LiquidFeedback";
   81.19  ["Abstention"] = "Enthaltung";
   81.20 +["Abstention [many entries]"] = "Enthaltung";
   81.21 +["Abstention [single entry]"] = "Enthaltung";
   81.22  ["Accept invitation"] = "Einladung annehmen";
   81.23  ["Accepted at"] = "Angenommen am/um";
   81.24 +["Accordion (all expanded)"] = "Akkordeon (alle offen)";
   81.25 +["Accordion (first expanded)"] = "Akkordeon (erstes offen)";
   81.26 +["Accordion (none expanded)"] = "Akkordeon (keins offen)";
   81.27  ["Active?"] = "Aktiv?";
   81.28 +["Add alternative initiative to issue"] = "Alternative Initiative zum Thema hinzufügen";
   81.29  ["Add my interest"] = "Mein Interesse anmelden";
   81.30 -["Add new initiative to issue"] = "Neue Initiative zum Thema hinzufügen";
   81.31  ["Add new suggestion"] = "Neue Anregung hinzufügen";
   81.32  ["Add to my contacts"] = "Zu meinen Kontakten hinzufügen";
   81.33  ["Address"] = "Anschrift";
   81.34 @@ -26,14 +32,26 @@
   81.35  ["Administrator"] = "Administrator";
   81.36  ["Admission time"] = "Zeit für die Zulassung";
   81.37  ["Admitted"] = "zugelassen";
   81.38 +["Alternative initiatives"] = "Alternative Initiativen";
   81.39  ["Any"] = "Alle";
   81.40 +["Approval (#th preference) [many entries]"] = "Zustimmung (#.-Wünsche)";
   81.41 +["Approval (#th preference) [single entry]"] = "Zustimmung (#.-Wunsch)";
   81.42 +["Approval (first preference) [many entries]"] = "Zustimmung (Erstwünsche)";
   81.43 +["Approval (first preference) [single entry]"] = "Zustimmung (Erstwunsch)";
   81.44 +["Approval (second preference) [many entries]"] = "Zustimmung (Zweitwünsche)";
   81.45 +["Approval (second preference) [single entry]"] = "Zustimmung (Zweitwunsch)";
   81.46 +["Approval (third preference) [many entries]"] = "Zustimmung (Drittwünsche)";
   81.47 +["Approval (third preference) [single entry]"] = "Zustimmung (Drittwunsch)";
   81.48 +["Approval [many entries]"] = "Zustimmung";
   81.49 +["Approval [single entry]"] = "Zustimmung";
   81.50 +["Approved"] = "Angenommen";
   81.51  ["Are you sure?"] = "Sicher?";
   81.52  ["Area"] = "Themenbereich";
   81.53  ["Area '#{name}'"] = "Themenbereich '#{name}'";
   81.54 -["Area delegation"] = "Area-Delegation";
   81.55 +["Area delegation"] = "Delegation für Themenbereich";
   81.56  ["Area list"] = "Liste der Themenbereiche";
   81.57  ["Area successfully updated"] = "Themenbereich erfolgreich aktualisiert";
   81.58 -["Area wide delegation active"] = "Delegation für Themengebiet aktiv";
   81.59 +["Area wide delegation active"] = "Delegation für Themenbereich aktiv";
   81.60  ["Areas"] = "Themenbereiche";
   81.61  ["Author"] = "Autor";
   81.62  ["Autoreject is off."] = "Auto-Ablehnen ist aus";
   81.63 @@ -41,6 +59,7 @@
   81.64  ["Avatar"] = "Avatar";
   81.65  ["Back"] = "Zurück";
   81.66  ["Back to timeline"] = "Zurück zur Zeitachse";
   81.67 +["Ballot of '#{member_name}' for issue ##{issue_id}"] = "Stimmzettel von '#{member_name}' für Thema ##{issue_id}";
   81.68  ["Become a member"] = "Mitglied werden";
   81.69  ["Birthday"] = "Geburtstag";
   81.70  ["Can't remove last initiator"] = "Der letzte Initiator kann nicht entfernt werden";
   81.71 @@ -50,19 +69,22 @@
   81.72  ["Cancel refuse of invitation"] = "Ablehnung der Einladung aufheben";
   81.73  ["Cancel registration"] = "Registration abbrechen";
   81.74  ["Cancelled"] = "Abgebrochen";
   81.75 -["Change area delegation"] = "Delegation für Themengebiet ändern";
   81.76 +["Change area delegation"] = "Delegation für Themenbereich ändern";
   81.77 +["Change display settings"] = "Anzeige-Einstellungen ändern";
   81.78 +["Change filters and order"] = "Filter und Sortierung ändern";
   81.79  ["Change global delegation"] = "Globale Delegation ändern";
   81.80  ["Change issue delegation"] = "Delegation für Thema ändern";
   81.81  ["Change login"] = "Login ändern";
   81.82  ["Change name"] = "Name ändern";
   81.83 +["Change order"] = "Sortierung ändern";
   81.84  ["Change password"] = "Kennwort ändern";
   81.85 +["Change vote"] = "Wahl ändern";
   81.86  ["Change your login"] = "Deinen Anmeldenamen ändern";
   81.87  ["Change your name"] = "Deinen Namen ändern";
   81.88  ["Change your password"] = "Dein Kennwort ändern";
   81.89  ["Choose initiator"] = "Initiator auswählen";
   81.90  ["Choose member"] = "Mitglied auswählen";
   81.91  ["Click for details"] = "Klicke für Details";
   81.92 -["Close"] = "Schließen";
   81.93  ["Closed"] = "geschlossen";
   81.94  ["Collective opinion"] = "Meinungsbild";
   81.95  ["Commit suggestion"] = "Anregung speichern";
   81.96 @@ -79,7 +101,6 @@
   81.97  ["Created at"] = "Erzeugt am/um";
   81.98  ["Current draft"] = "Aktueller Entwurf";
   81.99  ["Current votings in areas you are member of and issues you are interested in:"] = "Jetzt laufende Abstimmungen zu Themen aus Deinen Themenbereichen oder solchen an denen Du interessiert bist:";
  81.100 -["Date"] = "Datum";
  81.101  ["Degree"] = "Grad";
  81.102  ["Delegations"] = "Delegationen";
  81.103  ["Delete filter"] = "Filter löschen";
  81.104 @@ -89,15 +110,25 @@
  81.105  ["Diff"] = "Differenz";
  81.106  ["Direct member count"] = "Anzahl Direktmitglieder";
  81.107  ["Direct membership"] = "Direkte Mitgliedschaft";
  81.108 +["Disapproval (prefer to last block) [many entries]"] = "Ablehnung (jedoch Bevorzugung gegenüber letztem Ablehnungsblock)";
  81.109 +["Disapproval (prefer to last block) [single entry]"] = "Ablehnung (jedoch Bevorzugung gegenüber letztem Ablehnungsblock)";
  81.110 +["Disapproval (prefer to lower block) [many entries]"] = "Ablehnung (jedoch Bevorzugung gegenüber unterem Ablehnungsblock)";
  81.111 +["Disapproval (prefer to lower block) [single entry]"] = "Ablehnung (jedoch Bevorzugung gegenüber unterem Ablehnungsblock)";
  81.112 +["Disapproval (prefer to lower blocks) [many entries]"] = "Ablehnung (jedoch Bevorzugung gegenüber unteren Ablehnungsblöcken)";
  81.113 +["Disapproval (prefer to lower blocks) [single entry]"] = "Ablehnung (jedoch Bevorzugung gegenüber unteren Ablehnungsblöcken)";
  81.114 +["Disapproval [many entries]"] = "Ablehnung";
  81.115 +["Disapproval [single entry]"] = "Ablehnung";
  81.116  ["Discussion"] = "Diskussion";
  81.117  ["Discussion URL"] = "Diskussions-URL";
  81.118  ["Discussion on issue"] = "Diskussion zum Thema";
  81.119  ["Discussion time"] = "Zeit für die Diskussions";
  81.120  ["Discussion with initiators"] = "Diskussion mit den Initiatoren";
  81.121 +["Display settings"] = "Anzeige-Einstellungen";
  81.122  ["Download"] = "Download";
  81.123  ["Download database export"] = "Datenbankexport herunterladen";
  81.124  ["Draft"] = "Entwurf";
  81.125  ["Draft history"] = "Entwurfshistorie";
  81.126 +["EXPERIMENTAL FEATURE"] = "EXPERIMENTELLE FUNKTION";
  81.127  ["Edit"] = "Bearbeiten";
  81.128  ["Edit draft"] = "Entwurf bearbeiten";
  81.129  ["Edit initiative"] = "Initiative bearbeiten";
  81.130 @@ -161,7 +192,6 @@
  81.131  ["Invited"] = "Eingeladen";
  81.132  ["Issue"] = "Thema";
  81.133  ["Issue ##{id}"] = "Thema ##{id}";
  81.134 -["Issue ##{id} (#{policy_name})"] = "Thema ##{id} (#{policy_name})";
  81.135  ["Issue accepted"] = "Thema akzeptiert";
  81.136  ["Issue canceled"] = "Thema abgebrochen";
  81.137  ["Issue delegation"] = "Issue-Delegation";
  81.138 @@ -196,6 +226,7 @@
  81.139  ["Member '#{member}'"] = "Mitglied '#{member}'";
  81.140  ["Member has been removed from initiators"] = "Mitglied wurde von den Initiatoren entfernt";
  81.141  ["Member has been removed from your contacts"] = "Mitglied wurde aus Deinen Kontakten entfernt";
  81.142 +["Member has not approved latest draft"] = "Mitglied hat den letzten Entwurf noch nicht angenommen";
  81.143  ["Member is administrator"] = "Mitglied ist Administrator";
  81.144  ["Member is already saved in your contacts!"] = "Mitglied ist schon in Deinen Kontakten!";
  81.145  ["Member is now invited to be initiator"] = "Mitglied ist jetzt als Initiator eingeladen";
  81.146 @@ -206,6 +237,7 @@
  81.147  ["Member page"] = "Mitgliederseite";
  81.148  ["Member successfully registered"] = "Mitglied erfolgreich registriert";
  81.149  ["Member successfully updated"] = "Mitglied erfolgreich aktualisert";
  81.150 +["Member voting"] = false;
  81.151  ["Member: '#{login}' (#{name})"] = "Mitlied: '#{login}' (#{name})";
  81.152  ["Members"] = "Mitglieder";
  81.153  ["Membership by delegation"] = "Mitgliedschaft durch Delegation";
  81.154 @@ -216,6 +248,8 @@
  81.155  ["Missing help text: #{id}.#{lang}.txt"] = "Fehlender Hilfe-Text: #{id}.#{lang}.txt";
  81.156  ["Mobile phone"] = "Mobiltelefon";
  81.157  ["Monday"] = "Montag";
  81.158 +["Move down"] = "Runter schieben";
  81.159 +["Move up"] = "Hoch schieben";
  81.160  ["My opinion"] = "Meine Meinung";
  81.161  ["Name"] = "Name";
  81.162  ["New"] = "Neu";
  81.163 @@ -237,9 +271,13 @@
  81.164  ["No membership at all"] = "Gar keine Mitgliedschaft";
  81.165  ["No support at all"] = "Gar keine Unterstützung";
  81.166  ["Not a member"] = "Kein Mitglied";
  81.167 +["Not approved (rank #{rank})"] = "Nicht angenommen (Rang #{rank})";
  81.168  ["Not voted"] = "Nicht abgestimmt";
  81.169 +["Not voted (not admitted)"] = "Nicht abgestimmt (nicht zugelassen)";
  81.170 +["Not voted (revoked from initiator)"] = "Nicht abgestimmt (durch Initiator zurückgezogen)";
  81.171  ["Not yet voted"] = "Noch abzustimmen";
  81.172  ["Number of incoming delegations, follow link to see more details"] = "Anzahl eingehender Delegationen, Link folgen für mehr Details";
  81.173 +["Number of initiatives to preview"] = "Anzahl der Initiativen in der Vorschau";
  81.174  ["OK"] = "OK";
  81.175  ["Old draft revision"] = "Alte Revision des Entwurfs";
  81.176  ["Old password"] = "Altes Kennwort";
  81.177 @@ -251,6 +289,7 @@
  81.178  ["One issue you are interested in"] = "Ein Thema, das Dich interessiert";
  81.179  ["One step back"] = "Ein Schritt zurück";
  81.180  ["Open"] = "Offen";
  81.181 +["Opinions"] = "Meinungen";
  81.182  ["Order by"] = "Sortieren nach";
  81.183  ["Organizational unit"] = "Organisationseinheit";
  81.184  ["Outgoing delegations"] = "Ausgehende Delegationen";
  81.185 @@ -285,7 +324,6 @@
  81.186  ["Profile"] = "Profil";
  81.187  ["Publish"] = "Veröffentlichen";
  81.188  ["Published"] = "veröffentlicht";
  81.189 -["Published contacts"] = "Veröffentlichte Kontakte";
  81.190  ["Rank"] = "Rang";
  81.191  ["Real name"] = "Realname";
  81.192  ["Refresh support to current draft"] = "Unterstützung auf aktuellen Entwurf aktualisieren";
  81.193 @@ -322,10 +360,11 @@
  81.194  ["Search issues"] = "Suche Themen";
  81.195  ["Search members"] = "Suche Mitglieder";
  81.196  ["Search results for: '#{search}'"] = "Suchergebnisse für: '#{search}'";
  81.197 +["Select language \"#{langcode}\""] = false;
  81.198  ["Set URL"] = "URL setzen";
  81.199 -["Set area delegation"] = "Delegation für Themengebiet festlegen";
  81.200 +["Set area delegation"] = "Delegation für Themenbereich festlegen";
  81.201  ["Set autoreject"] = "Auto-Ablehnen anschalten";
  81.202 -["Set delegation for Area '#{name}'"] = "Delegation für Themengebiet '#{name}' festlegen";
  81.203 +["Set delegation for Area '#{name}'"] = "Delegation für Themenbereich '#{name}' festlegen";
  81.204  ["Set delegation for Issue ##{number} in Area '#{area_name}'"] = "Delegation für Thema ##{number} im Themenbereich '#{area_name}' festlegen";
  81.205  ["Set global delegation"] = "Globale Delegation festlegen";
  81.206  ["Set issue delegation"] = "Delegation für Thema festlegen";
  81.207 @@ -333,11 +372,13 @@
  81.208  ["Settings"] = "Einstellungen";
  81.209  ["Show"] = "Zeige";
  81.210  ["Show active members"] = "Zeige aktive Mitglieder";
  81.211 -["Show all initiatives"] = "Zeige alle Initiativen";
  81.212 +["Show alternative initiatives"] = "Zeige alternative Initiativen";
  81.213  ["Show areas in use"] = "Zeige verwendete Themenbereiche";
  81.214  ["Show areas not in use"] = "Zeige nicht verwendente Themenbereiche";
  81.215  ["Show diff"] = "Änderungen anzeigen";
  81.216 +["Show filter"] = "Zeige Filter";
  81.217  ["Show filter details"] = "Zeige Filter-Details";
  81.218 +["Show help text"] = "Zeige Hilfe-Text";
  81.219  ["Show locked members"] = "Zeige gesperrte Mitglieder";
  81.220  ["Show member"] = "Mitglied anzeigen";
  81.221  ["Show name history"] = "Namenshistorie zeigen";
  81.222 @@ -370,14 +411,24 @@
  81.223  ["Supported"] = "Unterstützt";
  81.224  ["Supported initiatives"] = "Unterstützte Initiativen";
  81.225  ["Supporter"] = "Unterstützer";
  81.226 +["Tabs"] = "Registerkarten";
  81.227  ["Terms accepted"] = "Bedingungen akzeptiert";
  81.228 +["Terms of use"] = "Nutzungsbedingungen";
  81.229  ["The code you've entered is invalid"] = "Der Code, den Du eingeben hast, ist nicht gültig!";
  81.230  ["The draft of this initiative has been updated!"] = "Der Entwurfstext der Initiative wurde aktualisiert!";
  81.231  ["The drafts do not differ"] = "Die Entwürfe unterscheiden sich nicht";
  81.232  ["The initiators suggest to support the following initiative:"] = "Die Initiatoren empfehlen folgende Initiative zu unterstützen:";
  81.233 +["There are no more alternative initiatives currently."] = "Es gibt zur Zeit keine weiteren alternative Initiative.";
  81.234 +["There were no more alternative initiatives."] = "Es gab keine weiteren alternativen Initiativen.";
  81.235 +["This initiative"] = "Diese Initiative";
  81.236 +["This initiative compared to alternative initiatives"] = "Diese Initiative im Vergleich zu alternativen Initiativen";
  81.237  ["This initiative has been revoked at #{revoked}"] = "Diese Initiative wurde am/um #{revoked} zurückgezogen";
  81.238 +["This initiative has not been admitted! It failed the quorum of #{quorum}."] = "Diese Initiative wurde nicht zugelassen. Sie hat das Quorum von #{quorum} nicht erreicht.";
  81.239  ["This initiative is already revoked"] = "Diese Initiative ist schon zurückgezogen";
  81.240  ["This initiative is revoked"] = "Diese Initiative wurde zurückgezogen";
  81.241 +["This issue has been cancelled. It failed the quorum of #{quorum}."] = "Dieses Thema wurde abgebrochen. Es hat das Quorum von #{quorum} nicht erfüllt.";
  81.242 +["This issue has been finished with the following winning initiative:"] = "Diese Thema wurde mit folgender Initiative als Gewinner abgeschlossen:";
  81.243 +["This issue has been finished without any winning initiative."] = "Das Thema wurde ohne Gewinner abgeschlossen.";
  81.244  ["This issue is already closed."] = "Das Thema ist schon geschlossen.";
  81.245  ["This issue is already frozen."] = "Das Thema ist schon eingefroren";
  81.246  ["This login is already taken, please choose another one!"] = "Dieser Anmeldename ist bereits vergeben, bitte wähle einen anderen!";
  81.247 @@ -386,6 +437,7 @@
  81.248  ["This member has rejected to become initiator of this initiative"] = "Dieses Mitglied hat die Einladung, Initiator zu werden, abgelehnt";
  81.249  ["This member is already initiator of this initiative"] = "Dieses Mitglied ist bereits Initiator dieser Initiative";
  81.250  ["This member is already invited to become initiator of this initiative"] = "Dieses Mitglied ist bereits eingeladen Initiator dieser Initiative zu werden";
  81.251 +["This member is participating, the rest of delegation chain is suspended while discussing"] = "Dieses Mitglied partizipiert, Rest der Delegationskette ausgesetzt.";
  81.252  ["This name is already taken, please choose another one!"] = "Dieser Name ist bereits vergeben, bitte wähle einen anderen!";
  81.253  ["This name is really too short!"] = "Dieser Name ist wirklich zu kurz!";
  81.254  ["This name is too short!"] = "Dieser Name ist zu kurz!";
  81.255 @@ -395,10 +447,12 @@
  81.256  ["Thursday"] = "Donnerstag";
  81.257  ["Time left"] = "Restzeit";
  81.258  ["Timeline"] = "Zeitachse";
  81.259 -["Title (80 chars max)"] = "Title (max. 80 Zeichen)";
  81.260 -["Traditional wiki syntax"] = "Traditionaller Wiki-Syntax";
  81.261 +["Title"] = "Titel";
  81.262 +["Title (80 chars max)"] = "Titel (max. 80 Zeichen)";
  81.263 +["Traditional wiki syntax"] = "Traditionelle Wiki-Syntax";
  81.264  ["Trustee"] = "Bevollmächtigter";
  81.265  ["Tuesday"] = "Dienstag";
  81.266 +["Type of tabs"] = "Tabulatortyp";
  81.267  ["Unknown author"] = "Unbekannter Autor";
  81.268  ["Upload images"] = "Bilder hochladen";
  81.269  ["Used until"] = "Benutzt bis";
  81.270 @@ -411,8 +465,8 @@
  81.271  ["Voted no"] = "Mit Nein gestimmt";
  81.272  ["Voted proposal"] = "Abgestimmte Vorlage";
  81.273  ["Voted yes"] = "Mit Ja gestimmt";
  81.274 -["Voter"] = "Abstimmende";
  81.275  ["Voting"] = "Abstimmung";
  81.276 +["Voting details"] = "Abstimmdetails";
  81.277  ["Voting for this issue has already begun."] = "Die Abstimmung für dieses Thema hat schon begonnen.";
  81.278  ["Voting for this issue is currently running!"] = "Über dieses Thema wird gerade abgestimmt!";
  81.279  ["Voting has not started yet."] = "Die Abstimmung hat noch nicht begonnen.";
  81.280 @@ -447,10 +501,11 @@
  81.281  ["Your are interested"] = "Du bist interessiert";
  81.282  ["Your are potential supporter"] = "Du bist potentieller Unterstützer";
  81.283  ["Your are supporter"] = "Du bist Unterstützer";
  81.284 -["Your delegation for this area has been deleted."] = "Deine Delegation für dieses Themengebiet wurde gelöscht";
  81.285 -["Your delegation for this area has been updated."] = "Deine Delegation für dieses Themengebiet wurde geändert";
  81.286 +["Your delegation for this area has been deleted."] = "Deine Delegation für dieses Themenbereich wurde gelöscht";
  81.287 +["Your delegation for this area has been updated."] = "Deine Delegation für dieses Themenbereich wurde geändert";
  81.288  ["Your delegation for this issue has been deleted."] = "Deine Delegation für dieses Thema wurde gelöscht";
  81.289  ["Your delegation for this issue has been updated."] = "Deine Delegation für dieses Thema wurde geändert";
  81.290 +["Your display settings have been updated"] = "Deine Anzeige-Einstellungen wurden aktualisiert";
  81.291  ["Your global delegation has been deleted."] = "Deine globale Delegation wurde gelöscht";
  81.292  ["Your global delegation has been updated."] = "Deine globale Delegation wurde geändert";
  81.293  ["Your login has been changed to '#{login}'"] = "Dein Anmeldename wurde auf '#{login}' geändert";
  81.294 @@ -465,17 +520,18 @@
  81.295  ["Your support has been updated to the latest draft"] = "Deine Unterstützung wurde auf den neuesten Entwurf aktualisiert";
  81.296  ["Your web browser is not fully supported yet."] = "Dein Web-Browser wird noch nicht vollständig unterstützt.";
  81.297  ["Z-A"] = "Z-A";
  81.298 -["all"] = "Alle";
  81.299 +["and #{count} more initiatives"] = "und #{count} weitere Initiativen";
  81.300  ["continuing"] = "andauernd";
  81.301  ["delete<br /><br />"] = "löschen<br /><br />";
  81.302  ["email"] = "E-Mail";
  81.303 +["last 24 hours"] = "letzte 24 Stunden";
  81.304  ["login name"] = "Anmeldename";
  81.305  ["must"] = "muss";
  81.306  ["must not"] = "darf nicht";
  81.307  ["must/should"] = "muss/soll";
  81.308  ["must/should not"] = "muss/soll nicht";
  81.309  ["neutral"] = "neutral";
  81.310 -["not implemented"] = "nicht umgesetzt";
  81.311 +["requested"] = "angefragt";
  81.312  ["should"] = "soll";
  81.313  ["should not"] = "soll nicht";
  81.314  ["to reset your password please click on the following link:\n\n"] = "um Dein Kennwort zurückzusetzen klicke bitte den folgenden Link an:\n\n";
    82.1 --- a/locale/translations.en.lua	Tue Feb 02 00:31:06 2010 +0100
    82.2 +++ b/locale/translations.en.lua	Sat Feb 20 22:10:31 2010 +0100
    82.3 @@ -1,15 +1,517 @@
    82.4  #!/usr/bin/env lua
    82.5  return {
    82.6 -["Error compile"] = false;
    82.7 -["Error no file"] = false;
    82.8 -["Error runtime"] = false;
    82.9 +["#{interested_issues_to_vote_count} issue(s) you are interested in"] = false;
   82.10 +["#{issues_to_vote_count} issue(s)"] = false;
   82.11 +["#{number} Image(s) has been deleted"] = false;
   82.12 +["#{number} Image(s) has been updated"] = false;
   82.13 +["(#{more_count} duplicates removed)"] = false;
   82.14 +["(change URL)"] = false;
   82.15 +["(new window)"] = false;
   82.16 +["+ #{weight}"] = false;
   82.17 +["A-Z"] = false;
   82.18 +["About"] = false;
   82.19 +["About LiquidFeedback"] = false;
   82.20 +["Abstention"] = false;
   82.21 +["Abstention [many entries]"] = "Abstention";
   82.22 +["Abstention [single entry]"] = "Abstention";
   82.23 +["Accept invitation"] = false;
   82.24 +["Accepted at"] = false;
   82.25 +["Accordion (all expanded)"] = false;
   82.26 +["Accordion (first expanded)"] = false;
   82.27 +["Accordion (none expanded)"] = false;
   82.28 +["Active?"] = false;
   82.29 +["Add my interest"] = false;
   82.30 +["Add new initiative"] = false;
   82.31 +["Add new initiative to issue"] = false;
   82.32 +["Add new suggestion"] = false;
   82.33 +["Add to my contacts"] = false;
   82.34 +["Address"] = false;
   82.35 +["Admin"] = false;
   82.36 +["Admin menu"] = false;
   82.37 +["Admin?"] = false;
   82.38 +["Administrator"] = false;
   82.39 +["Admission time"] = false;
   82.40 +["Admitted"] = false;
   82.41 +["Any"] = false;
   82.42 +["Approval (#th preference) [many entries]"] = "Approval (#th preference)";
   82.43 +["Approval (#th preference) [single entry]"] = "Approval (#th preference)";
   82.44 +["Approval (first preference) [many entries]"] = "Approval (first preference)";
   82.45 +["Approval (first preference) [single entry]"] = "Approval (first preference)";
   82.46 +["Approval (second preference) [many entries]"] = "Approval (second preference)";
   82.47 +["Approval (second preference) [single entry]"] = "Approval (second preference)";
   82.48 +["Approval (third preference) [many entries]"] = "Approval (third preference)";
   82.49 +["Approval (third preference) [single entry]"] = "Approval (third preference)";
   82.50 +["Approval [many entries]"] = "Approval";
   82.51 +["Approval [single entry]"] = "Approval";
   82.52 +["Are you sure?"] = false;
   82.53 +["Area"] = false;
   82.54 +["Area '#{name}'"] = false;
   82.55 +["Area delegation"] = false;
   82.56 +["Area list"] = false;
   82.57 +["Area successfully updated"] = false;
   82.58 +["Area wide delegation active"] = false;
   82.59 +["Areas"] = false;
   82.60 +["Author"] = false;
   82.61 +["Autoreject is off."] = false;
   82.62 +["Autoreject is on."] = false;
   82.63 +["Avatar"] = false;
   82.64 +["Back"] = false;
   82.65 +["Back to timeline"] = false;
   82.66 +["Become a member"] = false;
   82.67 +["Birthday"] = false;
   82.68 +["Can't remove last initiator"] = false;
   82.69 +["Can't send confirmation email"] = false;
   82.70 +["Cancel"] = false;
   82.71 +["Cancel password reset"] = false;
   82.72 +["Cancel refuse of invitation"] = false;
   82.73 +["Cancel registration"] = false;
   82.74 +["Cancelled"] = false;
   82.75 +["Change area delegation"] = false;
   82.76 +["Change display settings"] = false;
   82.77 +["Change global delegation"] = false;
   82.78 +["Change issue delegation"] = false;
   82.79 +["Change login"] = false;
   82.80 +["Change name"] = false;
   82.81 +["Change password"] = false;
   82.82 +["Change vote"] = false;
   82.83 +["Change your login"] = false;
   82.84 +["Change your name"] = false;
   82.85 +["Change your password"] = false;
   82.86 +["Choose initiator"] = false;
   82.87 +["Choose member"] = false;
   82.88 +["Click for details"] = false;
   82.89 +["Close"] = false;
   82.90 +["Closed"] = false;
   82.91 +["Collective opinion"] = false;
   82.92 +["Commit suggestion"] = false;
   82.93 +["Compare"] = false;
   82.94 +["Confirm"] = false;
   82.95 +["Confirmation code"] = false;
   82.96 +["Confirmation code invalid!"] = false;
   82.97 +["Contacts"] = false;
   82.98 +["Content"] = false;
   82.99 +["Counting of votes"] = false;
  82.100 +["Create alternative initiative"] = false;
  82.101 +["Create new area"] = false;
  82.102 +["Create new issue"] = false;
  82.103 +["Created at"] = false;
  82.104 +["Current draft"] = false;
  82.105 +["Current votings in areas you are member of and issues you are interested in:"] = false;
  82.106 +["Degree"] = false;
  82.107 +["Delegations"] = false;
  82.108 +["Delete filter"] = false;
  82.109 +["Description"] = false;
  82.110 +["Details"] = false;
  82.111 +["Developer features"] = false;
  82.112 +["Diff"] = false;
  82.113 +["Direct member count"] = false;
  82.114 +["Direct membership"] = false;
  82.115 +["Disapproval (prefer to last block) [many entries]"] = "Disapproval (prefer to last block)";
  82.116 +["Disapproval (prefer to last block) [single entry]"] = "Disapproval (prefer to last block)";
  82.117 +["Disapproval (prefer to lower block) [many entries]"] = "Disapproval (prefer to lower block)";
  82.118 +["Disapproval (prefer to lower block) [single entry]"] = "Disapproval (prefer to lower block)";
  82.119 +["Disapproval (prefer to lower blocks) [many entries]"] = "Disapproval (prefer to lower blocks)";
  82.120 +["Disapproval (prefer to lower blocks) [single entry]"] = "Disapproval (prefer to lower blocks)";
  82.121 +["Disapproval [many entries]"] = "Disapproval";
  82.122 +["Disapproval [single entry]"] = "Disapproval";
  82.123 +["Discussion"] = false;
  82.124 +["Discussion URL"] = false;
  82.125 +["Discussion on issue"] = false;
  82.126 +["Discussion time"] = false;
  82.127 +["Discussion with initiators"] = false;
  82.128 +["Display settings"] = false;
  82.129 +["Display starting from"] = false;
  82.130 +["Download"] = false;
  82.131 +["Download database export"] = false;
  82.132 +["Draft"] = false;
  82.133 +["Draft history"] = false;
  82.134 +["Edit"] = false;
  82.135 +["Edit draft"] = false;
  82.136 +["Edit initiative"] = false;
  82.137 +["Edit my page"] = false;
  82.138 +["Edit my profile"] = false;
  82.139 +["Email address"] = false;
  82.140 +["Email address confirmation"] = false;
  82.141 +["Email address is confirmed now"] = false;
  82.142 +["Email address too short!"] = false;
  82.143 +["Email confirmation request"] = false;
  82.144 +["Empty help text: #{id}.#{lang}.txt"] = false;
  82.145 +["Error while updating member, database reported:<br /><br /> (#{errormessage})"] = false;
  82.146 +["External memberships"] = false;
  82.147 +["External posts"] = false;
  82.148 +["Filter"] = false;
  82.149 +["Finish voting"] = false;
  82.150 +["Finished"] = false;
  82.151 +["Friday"] = false;
  82.152 +["Frozen"] = false;
  82.153 +["Fully frozen at"] = false;
  82.154 +["Global delegation"] = false;
  82.155 +["Global delegation active"] = false;
  82.156 +["Half frozen at"] = false;
  82.157 +["Hello "] = false;
  82.158 +["Help for: #{text}"] = false;
  82.159 +["Hide"] = false;
  82.160 +["Hide filter details"] = false;
  82.161 +["Hide this help message"] = false;
  82.162  ["Home"] = false;
  82.163 +["I accept the terms of use by checking the following checkbox:"] = false;
  82.164 +["Id"] = false;
  82.165 +["Ident number"] = false;
  82.166 +["If this link is not working, please open following url in your web browser:\n\n"] = false;
  82.167 +["Images"] = false;
  82.168 +["In discussion"] = false;
  82.169 +["Incoming delegations"] = false;
  82.170 +["Initiated"] = false;
  82.171 +["Initiated initiatives"] = false;
  82.172 +["Initiative events"] = false;
  82.173 +["Initiative is revoked now"] = false;
  82.174 +["Initiative quorum"] = false;
  82.175 +["Initiative revoked"] = false;
  82.176 +["Initiative successfully created"] = false;
  82.177 +["Initiative successfully updated"] = false;
  82.178 +["Initiative: '#{name}'"] = false;
  82.179 +["Initiatives"] = false;
  82.180 +["Initiatives that invited you to become initiator:"] = false;
  82.181 +["Initiator"] = false;
  82.182 +["Initiators"] = false;
  82.183 +["Interest not existant"] = false;
  82.184 +["Interest removed"] = false;
  82.185 +["Interest updated"] = false;
  82.186 +["Interested"] = false;
  82.187 +["Interested members"] = false;
  82.188 +["Internal posts"] = false;
  82.189  ["Invalid username or password!"] = false;
  82.190 +["Invitation has been refused"] = false;
  82.191 +["Invite an initiator to initiative"] = false;
  82.192 +["Invite code"] = false;
  82.193 +["Invite initiator"] = false;
  82.194 +["Invited"] = false;
  82.195 +["Issue"] = false;
  82.196 +["Issue ##{id}"] = false;
  82.197 +["Issue ##{id} (#{policy_name})"] = false;
  82.198 +["Issue accepted"] = false;
  82.199 +["Issue canceled"] = false;
  82.200 +["Issue delegation"] = false;
  82.201 +["Issue delegation active"] = false;
  82.202 +["Issue events"] = false;
  82.203 +["Issue finished"] = false;
  82.204 +["Issue finished without voting"] = false;
  82.205 +["Issue frozen"] = false;
  82.206 +["Issue policy"] = false;
  82.207 +["Issue quorum"] = false;
  82.208 +["Issues"] = false;
  82.209 +["JavaScript is disabled or not available."] = false;
  82.210 +["Last author"] = false;
  82.211 +["Last snapshot:"] = false;
  82.212 +["Legend:"] = false;
  82.213 +["License"] = false;
  82.214 +["Locked?"] = false;
  82.215  ["Login"] = false;
  82.216 +["Login name"] = false;
  82.217  ["Login successful!"] = false;
  82.218  ["Logout"] = false;
  82.219  ["Logout successful"] = false;
  82.220 +["Manage filter"] = false;
  82.221 +["Manage timeline filters"] = false;
  82.222 +["Mark suggestion as implemented and express dissatisfaction"] = false;
  82.223 +["Mark suggestion as implemented and express satisfaction"] = false;
  82.224 +["Mark suggestion as not implemented and express dissatisfaction"] = false;
  82.225 +["Mark suggestion as not implemented and express satisfaction"] = false;
  82.226 +["Max potential support"] = false;
  82.227 +["Max support"] = false;
  82.228 +["Member"] = false;
  82.229 +["Member '#{member}'"] = false;
  82.230 +["Member has been removed from initiators"] = false;
  82.231 +["Member has been removed from your contacts"] = false;
  82.232 +["Member is administrator"] = false;
  82.233 +["Member is already saved in your contacts!"] = false;
  82.234 +["Member is now invited to be initiator"] = false;
  82.235 +["Member list"] = false;
  82.236 +["Member name"] = false;
  82.237 +["Member name history for '#{name}'"] = false;
  82.238 +["Member of area"] = false;
  82.239 +["Member page"] = false;
  82.240 +["Member successfully registered"] = false;
  82.241 +["Member successfully updated"] = false;
  82.242 +["Member: '#{login}' (#{name})"] = false;
  82.243 +["Members"] = false;
  82.244 +["Membership by delegation"] = false;
  82.245 +["Membership not existant"] = false;
  82.246 +["Membership removed"] = false;
  82.247 +["Membership updated"] = false;
  82.248 +["Memberships"] = false;
  82.249 +["Missing help text: #{id}.#{lang}.txt"] = false;
  82.250 +["Mobile phone"] = false;
  82.251 +["Monday"] = false;
  82.252 +["My opinion"] = false;
  82.253 +["Name"] = false;
  82.254 +["New"] = false;
  82.255 +["New draft"] = false;
  82.256 +["New draft has been added to initiative"] = false;
  82.257 +["New draft revision"] = false;
  82.258 +["New initiative"] = false;
  82.259 +["New issue"] = false;
  82.260 +["New password"] = false;
  82.261 +["New passwords does not match."] = false;
  82.262 +["New passwords is too short."] = false;
  82.263 +["New suggestion"] = false;
  82.264 +["Newest"] = false;
  82.265 +["Next state"] = false;
  82.266 +["No"] = false;
  82.267 +["No changes to your images were made"] = false;
  82.268 +["No delegation"] = false;
  82.269 +["No events selected to list"] = false;
  82.270 +["No membership at all"] = false;
  82.271 +["No support at all"] = false;
  82.272 +["Not a member"] = false;
  82.273 +["Not voted"] = false;
  82.274 +["Not yet voted"] = false;
  82.275 +["Number of incoming delegations, follow link to see more details"] = false;
  82.276 +["Number of initiatives to preview"] = false;
  82.277 +["OK"] = false;
  82.278 +["Old draft revision"] = false;
  82.279 +["Old password"] = false;
  82.280 +["Old password is wrong"] = false;
  82.281 +["Oldest"] = false;
  82.282 +["On that page please enter the confirmation code:\n\n"] = false;
  82.283 +["On that page please enter the reset code:\n\n"] = false;
  82.284 +["One issue"] = false;
  82.285 +["One issue you are interested in"] = false;
  82.286 +["One step back"] = false;
  82.287 +["Open"] = false;
  82.288 +["Order by"] = false;
  82.289 +["Organizational unit"] = false;
  82.290 +["Outgoing delegations"] = false;
  82.291  ["Password"] = false;
  82.292 -["Password login"] = false;
  82.293 -["Username"] = false;
  82.294 +["Password (repeat)"] = false;
  82.295 +["Password has been reset successfully"] = false;
  82.296 +["Password reset request"] = false;
  82.297 +["Passwords don't match!"] = false;
  82.298 +["Passwords must consist of at least 8 characters!"] = false;
  82.299 +["Phone"] = false;
  82.300 +["Photo"] = false;
  82.301 +["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."] = false;
  82.302 +["Please choose a member"] = false;
  82.303 +["Please choose a name, i.e. your real name or your nick name. This name will be shown to others to identify you."] = false;
  82.304 +["Please choose a password and enter it twice. The password is case sensitive."] = false;
  82.305 +["Please choose a policy"] = false;
  82.306 +["Please choose two different versions of the draft to compare"] = false;
  82.307 +["Please choose two versions of the draft to compare"] = false;
  82.308 +["Please confirm your email address by clicking the following link:\n\n"] = false;
  82.309 +["Please enter the email reset code you have received:"] = false;
  82.310 +["Please enter the invite code you've received."] = false;
  82.311 +["Please enter your email address. This address will be used for automatic notifications (if you request them) and in case you've lost your password. This address will not be published. After registration you will receive an email with a confirmation link."] = false;
  82.312 +["Please enter your login name. You will receive an email with a link to reset your password."] = false;
  82.313 +["Please enter your new password twice."] = false;
  82.314 +["Policy"] = false;
  82.315 +["Population"] = false;
  82.316 +["Posts"] = false;
  82.317 +["Potential support"] = false;
  82.318 +["Potential supported"] = false;
  82.319 +["Potential supporter"] = false;
  82.320 +["Profession"] = false;
  82.321 +["Profile"] = false;
  82.322 +["Publish"] = false;
  82.323 +["Published"] = false;
  82.324 +["Published contacts"] = false;
  82.325 +["Rank"] = false;
  82.326 +["Real name"] = false;
  82.327 +["Refresh support to current draft"] = false;
  82.328 +["Refuse invitation"] = false;
  82.329 +["Register"] = false;
  82.330 +["Register new member"] = false;
  82.331 +["Registration"] = false;
  82.332 +["Rejected"] = false;
  82.333 +["Remove"] = false;
  82.334 +["Remove autoreject"] = false;
  82.335 +["Remove from contacts"] = false;
  82.336 +["Remove initiator"] = false;
  82.337 +["Remove initiator from initiative"] = false;
  82.338 +["Remove my interest"] = false;
  82.339 +["Remove my membership"] = false;
  82.340 +["Remove my request to vote later"] = false;
  82.341 +["Remove my support from this initiative"] = false;
  82.342 +["Repeat new password"] = false;
  82.343 +["Request password reset link"] = false;
  82.344 +["Reset code"] = false;
  82.345 +["Reset code is invalid!"] = false;
  82.346 +["Reset link has been send for this member"] = false;
  82.347 +["Reset password"] = false;
  82.348 +["Revoke"] = false;
  82.349 +["Revoke initiative"] = false;
  82.350 +["Revoked at"] = false;
  82.351 +["Saturday"] = false;
  82.352 +["Save"] = false;
  82.353 +["Save current filter"] = false;
  82.354 +["Save timeline filters"] = false;
  82.355 +["Saved as contact"] = false;
  82.356 +["Search"] = false;
  82.357 +["Search initiatives"] = false;
  82.358 +["Search issues"] = false;
  82.359 +["Search members"] = false;
  82.360 +["Search results for: '#{search}'"] = false;
  82.361 +["Set URL"] = false;
  82.362 +["Set area delegation"] = false;
  82.363 +["Set autoreject"] = false;
  82.364 +["Set delegation for Area '#{name}'"] = false;
  82.365 +["Set delegation for Issue ##{number} in Area '#{area_name}'"] = false;
  82.366 +["Set global delegation"] = false;
  82.367 +["Set issue delegation"] = false;
  82.368 +["Set new password"] = false;
  82.369 +["Settings"] = false;
  82.370 +["Show"] = false;
  82.371 +["Show active members"] = false;
  82.372 +["Show all initiatives"] = false;
  82.373 +["Show areas in use"] = false;
  82.374 +["Show areas not in use"] = false;
  82.375 +["Show diff"] = false;
  82.376 +["Show filter details"] = false;
  82.377 +["Show locked members"] = false;
  82.378 +["Show member"] = false;
  82.379 +["Show name history"] = false;
  82.380 +["Show only events which match... (or associtated)"] = false;
  82.381 +["Software"] = false;
  82.382 +["Some JavaScript based functions (voting in particular) will not work.\nFor this beta, please use a current version of Firefox, Safari, Opera(?), Konqueror or another (more) standard compliant browser.\nAlternative access without JavaScript will be available soon."] = false;
  82.383 +["Sorry, but there is not confirmed email address for your account. Please contact the administrator or support."] = false;
  82.384 +["Sorry, but you are currently not invited"] = false;
  82.385 +["Sorry, you have reached your personal flood limit. Please be slower..."] = false;
  82.386 +["Sorry, your contingent for creating initiatives has been used up. Please try again later."] = false;
  82.387 +["State"] = false;
  82.388 +["Statement"] = false;
  82.389 +["Step 1/5: Invite code"] = false;
  82.390 +["Step 2/5: Email address"] = false;
  82.391 +["Step 3/5: Username"] = false;
  82.392 +["Step 4/5: Login name"] = false;
  82.393 +["Step 5/5: Terms of use and password"] = false;
  82.394 +["Stylesheet URL"] = false;
  82.395 +["Stylesheet URL has been updated"] = false;
  82.396 +["Suggest no initiative"] = false;
  82.397 +["Suggested initiative"] = false;
  82.398 +["Suggestion"] = false;
  82.399 +["Suggestion currently implemented"] = false;
  82.400 +["Suggestion currently not implemented"] = false;
  82.401 +["Suggestion for initiative: '#{name}'"] = false;
  82.402 +["Suggestions"] = false;
  82.403 +["Sunday"] = false;
  82.404 +["Support"] = false;
  82.405 +["Support this initiative"] = false;
  82.406 +["Supported"] = false;
  82.407 +["Supported initiatives"] = false;
  82.408 +["Supporter"] = false;
  82.409 +["Tabs"] = false;
  82.410 +["Terms accepted"] = false;
  82.411 +["The code you've entered is invalid"] = false;
  82.412 +["The draft of this initiative has been updated!"] = false;
  82.413 +["The drafts do not differ"] = false;
  82.414 +["The initiators suggest to support the following initiative:"] = false;
  82.415 +["This initiative has been revoked at #{revoked}"] = false;
  82.416 +["This initiative has not been admitted! It failed the quorum of #{quorum}."] = false;
  82.417 +["This initiative is already revoked"] = false;
  82.418 +["This initiative is revoked"] = false;
  82.419 +["This issue is already closed."] = false;
  82.420 +["This issue is already frozen."] = false;
  82.421 +["This login is already taken, please choose another one!"] = false;
  82.422 +["This login is too short!"] = false;
  82.423 +["This member account has been created at #{created}"] = false;
  82.424 +["This member has rejected to become initiator of this initiative"] = false;
  82.425 +["This member is already initiator of this initiative"] = false;
  82.426 +["This member is already invited to become initiator of this initiative"] = false;
  82.427 +["This name is already taken, please choose another one!"] = false;
  82.428 +["This name is really too short!"] = false;
  82.429 +["This name is too short!"] = false;
  82.430 +["This suggestion has been meanwhile deleted"] = false;
  82.431 +["This title is really too short!"] = false;
  82.432 +["This username is too short!"] = false;
  82.433 +["Thursday"] = false;
  82.434 +["Time left"] = false;
  82.435 +["Timeline"] = false;
  82.436 +["Title (80 chars max)"] = false;
  82.437 +["Traditional wiki syntax"] = false;
  82.438 +["Trustee"] = false;
  82.439 +["Tuesday"] = false;
  82.440 +["Type of tabs"] = false;
  82.441 +["Unknown author"] = false;
  82.442 +["Upload images"] = false;
  82.443 +["Used until"] = false;
  82.444 +["Verification time"] = false;
  82.445 +["Version"] = false;
  82.446 +["Vote later"] = false;
  82.447 +["Vote later requests"] = false;
  82.448 +["Vote now"] = false;
  82.449 +["Voted"] = false;
  82.450 +["Voted no"] = false;
  82.451 +["Voted proposal"] = false;
  82.452 +["Voted yes"] = false;
  82.453 +["Voter"] = false;
  82.454 +["Voting"] = false;
  82.455 +["Voting for this issue has already begun."] = false;
  82.456 +["Voting for this issue is currently running!"] = false;
  82.457 +["Voting has not started yet."] = false;
  82.458 +["Voting proposal"] = false;
  82.459 +["Voting request updated"] = false;
  82.460 +["Voting started"] = false;
  82.461 +["Voting time"] = false;
  82.462 +["Website"] = false;
  82.463 +["Wednesday"] = false;
  82.464 +["Wiki engine"] = false;
  82.465 +["Yes"] = false;
  82.466 +["You are already initator"] = false;
  82.467 +["You are already not supporting this initiative"] = false;
  82.468 +["You are already supporting the latest draft"] = false;
  82.469 +["You are currently not supporting this initiative. By adding suggestions to this initiative you will automatically become a potential supporter."] = false;
  82.470 +["You are iniator of this initiative"] = false;
  82.471 +["You are interested in this issue"] = false;
  82.472 +["You are invited to become initiator of this initiative."] = false;
  82.473 +["You are member"] = false;
  82.474 +["You are now initiator of this initiative"] = false;
  82.475 +["You are potential supporter of this initiative"] = false;
  82.476 +["You are supporting this initiative"] = false;
  82.477 +["You can't suggest the initiative you are revoking"] = false;
  82.478 +["You didn't saved any member as contact yet."] = false;
  82.479 +["You have saved this member as contact"] = false;
  82.480 +["You have saved this member as contact."] = false;
  82.481 +["You have to accept the terms of use to complete registration."] = false;
  82.482 +["You have to mark 'Are you sure' to revoke!"] = false;
  82.483 +["You need to be logged in, to use this system."] = false;
  82.484 +["You want to vote later"] = false;
  82.485 +["You've successfully registered and you can login now with your login and password!"] = false;
  82.486 +["Your are interested"] = false;
  82.487 +["Your are potential supporter"] = false;
  82.488 +["Your are supporter"] = false;
  82.489 +["Your delegation for this area has been deleted."] = false;
  82.490 +["Your delegation for this area has been updated."] = false;
  82.491 +["Your delegation for this issue has been deleted."] = false;
  82.492 +["Your delegation for this issue has been updated."] = false;
  82.493 +["Your display settings have been updated"] = false;
  82.494 +["Your global delegation has been deleted."] = false;
  82.495 +["Your global delegation has been updated."] = false;
  82.496 +["Your login has been changed to '#{login}'"] = false;
  82.497 +["Your name has been changed"] = false;
  82.498 +["Your opinion has been deleted"] = false;
  82.499 +["Your opinion has been updated"] = false;
  82.500 +["Your page has been updated"] = false;
  82.501 +["Your password has been updated successfully"] = false;
  82.502 +["Your suggestion has been added"] = false;
  82.503 +["Your support has been added to this initiative"] = false;
  82.504 +["Your support has been removed from this initiative"] = false;
  82.505 +["Your support has been updated to the latest draft"] = false;
  82.506 +["Your web browser is not fully supported yet."] = false;
  82.507 +["Z-A"] = false;
  82.508 +["all"] = false;
  82.509 +["and #{count} more initiatives"] = false;
  82.510 +["continuing"] = false;
  82.511 +["delete<br /><br />"] = false;
  82.512 +["email"] = false;
  82.513 +["login name"] = false;
  82.514 +["must"] = false;
  82.515 +["must not"] = false;
  82.516 +["must/should"] = false;
  82.517 +["must/should not"] = false;
  82.518 +["neutral"] = false;
  82.519 +["not implemented"] = false;
  82.520 +["now"] = false;
  82.521 +["should"] = false;
  82.522 +["should not"] = false;
  82.523 +["to reset your password please click on the following link:\n\n"] = false;
  82.524 +["xmpp"] = false;
  82.525  }
    83.1 --- a/locale/translations.eo.lua	Tue Feb 02 00:31:06 2010 +0100
    83.2 +++ b/locale/translations.eo.lua	Sat Feb 20 22:10:31 2010 +0100
    83.3 @@ -4,18 +4,25 @@
    83.4  ["#{issues_to_vote_count} issue(s)"] = "#{issues_to_vote_count} temoj";
    83.5  ["#{number} Image(s) has been deleted"] = "Estas viŝita(j) #{number} bildo(j)";
    83.6  ["#{number} Image(s) has been updated"] = "Estas ĝisdatigita(j) #{number} bildo(j)";
    83.7 +["(#{more_count} duplicates removed)"] = false;
    83.8  ["(change URL)"] = "(ŝanĝi URL)";
    83.9  ["(new window)"] = "(nova fenestro)";
   83.10  ["+ #{weight}"] = "+ #{weight}";
   83.11  ["A-Z"] = "A-Z";
   83.12  ["About"] = "Pri";
   83.13 +["About / Impressum"] = false;
   83.14  ["About LiquidFeedback"] = "Pri LiquidFeedback";
   83.15  ["Abstention"] = "Sindeteno";
   83.16 +["Abstention [many entries]"] = false;
   83.17 +["Abstention [single entry]"] = false;
   83.18  ["Accept invitation"] = "Akcepti inviton";
   83.19  ["Accepted at"] = "Akceptita je";
   83.20 +["Accordion (all expanded)"] = false;
   83.21 +["Accordion (first expanded)"] = false;
   83.22 +["Accordion (none expanded)"] = false;
   83.23  ["Active?"] = "Ĉu aktiva?";
   83.24 +["Add alternative initiative to issue"] = false;
   83.25  ["Add my interest"] = "Anonci mian intereson";
   83.26 -["Add new initiative to issue"] = "Aldoni novan iniciaton al la temon";
   83.27  ["Add new suggestion"] = "Aldoni novan sugeston";
   83.28  ["Add to my contacts"] = "Aldoni al miaj kontaktoj";
   83.29  ["Address"] = "Adreso";
   83.30 @@ -25,8 +32,19 @@
   83.31  ["Administrator"] = "Administranto";
   83.32  ["Admission time"] = "Aprobotempo";
   83.33  ["Admitted"] = "Aprobita";
   83.34 -["All"] = "Ĉiuj";
   83.35 +["Alternative initiatives"] = false;
   83.36  ["Any"] = "Kelkaj";
   83.37 +["Approval (#th preference) [many entries]"] = false;
   83.38 +["Approval (#th preference) [single entry]"] = false;
   83.39 +["Approval (first preference) [many entries]"] = false;
   83.40 +["Approval (first preference) [single entry]"] = false;
   83.41 +["Approval (second preference) [many entries]"] = false;
   83.42 +["Approval (second preference) [single entry]"] = false;
   83.43 +["Approval (third preference) [many entries]"] = false;
   83.44 +["Approval (third preference) [single entry]"] = false;
   83.45 +["Approval [many entries]"] = false;
   83.46 +["Approval [single entry]"] = false;
   83.47 +["Approved"] = false;
   83.48  ["Are you sure?"] = "Ĉu vi estas certa?";
   83.49  ["Area"] = "Temaro";
   83.50  ["Area '#{name}'"] = "Temaro '#{name}'";
   83.51 @@ -39,7 +57,9 @@
   83.52  ["Autoreject is off."] = "Aŭtomata rifuzo estas malŝaltita.";
   83.53  ["Autoreject is on."] = "Aŭtomata rifuzo estas ŝaltita.";
   83.54  ["Avatar"] = "Avataro";
   83.55 -["Back"] = "Reen"; 
   83.56 +["Back"] = "Reen";
   83.57 +["Back to timeline"] = false;
   83.58 +["Ballot of '#{member_name}' for issue ##{issue_id}"] = false;
   83.59  ["Become a member"] = "Iĝi membro";
   83.60  ["Birthday"] = "Naskiĝtago";
   83.61  ["Can't remove last initiator"] = "Ne povas forigi la lastan iniciatinton";
   83.62 @@ -50,18 +70,21 @@
   83.63  ["Cancel registration"] = "Nuligi registradon";
   83.64  ["Cancelled"] = "Abolita";
   83.65  ["Change area delegation"] = "Ŝanĝi delegacion por temaro";
   83.66 +["Change display settings"] = false;
   83.67 +["Change filters and order"] = false;
   83.68  ["Change global delegation"] = "Ŝanĝi ĝeneralan delegacion";
   83.69  ["Change issue delegation"] = "Ŝanĝi delegacion por la temo";
   83.70  ["Change login"] = "Ŝanĝi salutnomon";
   83.71  ["Change name"] = "Ŝanĝi nomon";
   83.72 +["Change order"] = false;
   83.73  ["Change password"] = "Ŝanĝi pasvorton";
   83.74 +["Change vote"] = false;
   83.75  ["Change your login"] = "Ŝanĝi vian salutnomon";
   83.76  ["Change your name"] = "Ŝanĝi vian nomon";
   83.77  ["Change your password"] = "Ŝanĝi vian pasvorton";
   83.78  ["Choose initiator"] = "Elekti iniciatanton";
   83.79  ["Choose member"] = "Elekti membron";
   83.80  ["Click for details"] = "Klaki por detaloj";
   83.81 -["Close"] = "Fermi";
   83.82  ["Closed"] = "Fermita";
   83.83  ["Collective opinion"] = "Opinioresumo";
   83.84  ["Commit suggestion"] = "Stori sugeston";
   83.85 @@ -80,21 +103,32 @@
   83.86  ["Current votings in areas you are member of and issues you are interested in:"] = "Aktualaj voĉdonoj pri temoj en kiuj vi membraa kaj kiuj vin interesas:";
   83.87  ["Degree"] = "Grado";
   83.88  ["Delegations"] = "Delegacioj";
   83.89 +["Delete filter"] = false;
   83.90  ["Description"] = "Priskribo";
   83.91  ["Details"] = "Detaloj";
   83.92 -["Developer features"] = "Porprogramistaj funkcioj"; 
   83.93 +["Developer features"] = "Porprogramistaj funkcioj";
   83.94  ["Diff"] = "Diferenco";
   83.95  ["Direct member count"] = "Nombro de la rektaj membroj";
   83.96  ["Direct membership"] = "Rekta membreco";
   83.97 +["Disapproval (prefer to last block) [many entries]"] = false;
   83.98 +["Disapproval (prefer to last block) [single entry]"] = false;
   83.99 +["Disapproval (prefer to lower block) [many entries]"] = false;
  83.100 +["Disapproval (prefer to lower block) [single entry]"] = false;
  83.101 +["Disapproval (prefer to lower blocks) [many entries]"] = false;
  83.102 +["Disapproval (prefer to lower blocks) [single entry]"] = false;
  83.103 +["Disapproval [many entries]"] = false;
  83.104 +["Disapproval [single entry]"] = false;
  83.105  ["Discussion"] = "Diskuto";
  83.106  ["Discussion URL"] = "Diskuto-URL";
  83.107  ["Discussion on issue"] = "Diskuto pri la temo";
  83.108  ["Discussion time"] = "Tempo de la diskuto";
  83.109  ["Discussion with initiators"] = "Diskuto kun la iniciatintoj";
  83.110 +["Display settings"] = false;
  83.111  ["Download"] = "Elŝuti";
  83.112  ["Download database export"] = "Elŝuti datumbazoeksporton";
  83.113  ["Draft"] = "Skizo";
  83.114  ["Draft history"] = "Skizohistorio";
  83.115 +["EXPERIMENTAL FEATURE"] = false;
  83.116  ["Edit"] = "Redakti";
  83.117  ["Edit draft"] = "Redakti skizon";
  83.118  ["Edit initiative"] = "Redakti iniciaton";
  83.119 @@ -115,30 +149,32 @@
  83.120  ["Friday"] = "Vendredo";
  83.121  ["Frozen"] = "Ĝelita";
  83.122  ["Fully frozen at"] = "Tute ĝelita je";
  83.123 -["Global delegation"] = "Ĝenerala delegacio"; 
  83.124 -["Global delegation active"] = "Ĝenerala delegacio estas aktiva";  
  83.125 -["Global timeline"] = "Ĝenerala tempolineo";  
  83.126 +["Global delegation"] = "Ĝenerala delegacio";
  83.127 +["Global delegation active"] = "Ĝenerala delegacio estas aktiva";
  83.128  ["Half frozen at"] = "Duone ĝelita je";
  83.129  ["Hello "] = "Saluton ";
  83.130  ["Help for: #{text}"] = "Helpo por: #{text}";
  83.131  ["Hide"] = "Kaŝi";
  83.132 +["Hide filter details"] = false;
  83.133  ["Hide this help message"] = "Kaŝi tiun helpotekston";
  83.134  ["Home"] = "Ĉefpaĝo";
  83.135  ["I accept the terms of use by checking the following checkbox:"] = "Mi akceptas la uzokondiĉojn per la selekto de la sekva krucosignokesteto:";
  83.136 -["Id"] = "Identigilo"; 
  83.137 -["Ident number"] = "Identonumero"; 
  83.138 +["Id"] = "Identigilo";
  83.139 +["Ident number"] = "Identonumero";
  83.140  ["If this link is not working, please open following url in your web browser:\n\n"] = "Se tiu ligilo ne funkcias, bonvolu malfermi la sekvan URL per via retumilo:\n\n";
  83.141  ["Images"] = "Bildoj";
  83.142  ["In discussion"] = "En diskuton";
  83.143  ["Incoming delegations"] = "Alvenantaj delegacioj";
  83.144 -["Initiated initiatives"] = "Lanĉitaj iniciatoj ";
  83.145 +["Initiated"] = false;
  83.146 +["Initiated initiatives"] = "Lanĉitaj iniciatoj";
  83.147 +["Initiative events"] = false;
  83.148  ["Initiative is revoked now"] = "Iniciato nun estas retirita";
  83.149  ["Initiative quorum"] = "Kvorumo de la iniciato";
  83.150 +["Initiative revoked"] = false;
  83.151  ["Initiative successfully created"] = "Iniciato sukcese kreita";
  83.152  ["Initiative successfully updated"] = "Iniciato sukcese ĝisdatigita";
  83.153  ["Initiative: '#{name}'"] = "Iniciato: '#{name}'";
  83.154  ["Initiatives"] = "Iniciatoj";
  83.155 -["Initiatives per page"] = "Iniciatoj po paĝo";
  83.156  ["Initiatives that invited you to become initiator:"] = "Iniciatoj, kiuj vin invitis esti iniciatinto:";
  83.157  ["Initiator"] = "Iniciatinto";
  83.158  ["Initiators"] = "Iniciatintoj";
  83.159 @@ -154,16 +190,19 @@
  83.160  ["Invite code"] = "Invitokodo";
  83.161  ["Invite initiator"] = "Inviti iniciatanton";
  83.162  ["Invited"] = "Invitita";
  83.163 -["Inviting initiator"] = "Invitanta iniciatinto";
  83.164  ["Issue"] = "Temo";
  83.165  ["Issue ##{id}"] = "Temo ##{id}";
  83.166 -["Issue ##{id} (#{policy_name})"] = "Temo ##{id} (#{policy_name})";
  83.167 +["Issue accepted"] = false;
  83.168 +["Issue canceled"] = false;
  83.169  ["Issue delegation"] = "Temodelegacio";
  83.170  ["Issue delegation active"] = "Delegacio por temo aktiva";
  83.171 +["Issue events"] = false;
  83.172 +["Issue finished"] = false;
  83.173 +["Issue finished without voting"] = false;
  83.174 +["Issue frozen"] = false;
  83.175  ["Issue policy"] = "Regularo por temo";
  83.176  ["Issue quorum"] = "Kvorumo per temo";
  83.177  ["Issues"] = "Temoj";
  83.178 -["Issues per page"] = "Temoj po paĝo";
  83.179  ["JavaScript is disabled or not available."] = "JavaScript ne estas ŝaltita aŭ disponebla.";
  83.180  ["Last author"] = "Lasta aŭtoro";
  83.181  ["Last snapshot:"] = "Lasta fulmrigardo:";
  83.182 @@ -175,6 +214,8 @@
  83.183  ["Login successful!"] = "Saluto sukcesa!";
  83.184  ["Logout"] = "Adiaŭi";
  83.185  ["Logout successful"] = "Adiaŭo sukcesa";
  83.186 +["Manage filter"] = false;
  83.187 +["Manage timeline filters"] = false;
  83.188  ["Mark suggestion as implemented and express dissatisfaction"] = "Marki sugeston kiel realigitan kaj esprimi malkontentecon";
  83.189  ["Mark suggestion as implemented and express satisfaction"] = "Marki sugeston kiel realigitan kaj esprimi kontentecon";
  83.190  ["Mark suggestion as not implemented and express dissatisfaction"] = "Marki sugeston kiel ne realigitan kaj esprimi malkontentecon";
  83.191 @@ -185,15 +226,18 @@
  83.192  ["Member '#{member}'"] = "Membro '#{member}'";
  83.193  ["Member has been removed from initiators"] = "La membro estas forigita de la iniciatantaro";
  83.194  ["Member has been removed from your contacts"] = "La membro estas forigita de viaj kontaktoj";
  83.195 +["Member has not approved latest draft"] = false;
  83.196  ["Member is administrator"] = "La membro estas administranto";
  83.197  ["Member is already saved in your contacts!"] = "La membro estas jam konservita en viaj kontaktoj!";
  83.198  ["Member is now invited to be initiator"] = "La membro nun estas invitita kiel iniciatanto";
  83.199  ["Member list"] = "Membrolisto";
  83.200  ["Member name"] = "Membronomo";
  83.201  ["Member name history for '#{name}'"] = "Nomohistorio por '#{name}'";
  83.202 +["Member of area"] = false;
  83.203  ["Member page"] = "Membropaĝo";
  83.204  ["Member successfully registered"] = "Membro sukcese registrita";
  83.205  ["Member successfully updated"] = "Membro sukcese ĝisdatigita";
  83.206 +["Member voting"] = false;
  83.207  ["Member: '#{login}' (#{name})"] = "Membro: '#{login}' (#{name})";
  83.208  ["Members"] = "Membroj";
  83.209  ["Membership by delegation"] = "Membreco laŭ delegacio";
  83.210 @@ -204,25 +248,36 @@
  83.211  ["Missing help text: #{id}.#{lang}.txt"] = "Mankas helpoteksto: #{id}.#{lang}.txt";
  83.212  ["Mobile phone"] = "Poŝtelefono";
  83.213  ["Monday"] = "Lundo";
  83.214 +["Move down"] = false;
  83.215 +["Move up"] = false;
  83.216  ["My opinion"] = "Mia opinio";
  83.217  ["Name"] = "Nomo";
  83.218  ["New"] = "Nova";
  83.219 +["New draft"] = false;
  83.220  ["New draft has been added to initiative"] = "La nova skizo estas aldonita al la iniciato";
  83.221  ["New draft revision"] = "Nova revizio de la skizon";
  83.222 +["New initiative"] = false;
  83.223 +["New issue"] = false;
  83.224  ["New password"] = "Nova pasvorto";
  83.225  ["New passwords does not match."] = "Vi ne enigis dufoje la saman pasvorton";
  83.226  ["New passwords is too short."] = "La nova pasvorto estas tro mallonga";
  83.227 +["New suggestion"] = false;
  83.228  ["Newest"] = "Plej nova";
  83.229  ["Next state"] = "Sekva stato";
  83.230  ["No"] = "Ne";
  83.231  ["No changes to your images were made"] = "Viaj bildoj ne estas ŝanĝitaj";
  83.232  ["No delegation"] = "Neniu delegacio";
  83.233 +["No events selected to list"] = false;
  83.234  ["No membership at all"] = "Tute sen membreco";
  83.235  ["No support at all"] = "Tute sen subteno";
  83.236  ["Not a member"] = "Ne estas membro";
  83.237 +["Not approved (rank #{rank})"] = false;
  83.238  ["Not voted"] = "Ne balotinta";
  83.239 +["Not voted (not admitted)"] = false;
  83.240 +["Not voted (revoked from initiator)"] = false;
  83.241  ["Not yet voted"] = "Ankoraŭ ne balotinta";
  83.242  ["Number of incoming delegations, follow link to see more details"] = "Nombro de alvenantaj delegacioj, sekvi ligilon por pli da detaloj";
  83.243 +["Number of initiatives to preview"] = false;
  83.244  ["OK"] = "Bone";
  83.245  ["Old draft revision"] = "Malnova revizio de la skizo";
  83.246  ["Old password"] = "Malnova pasvorto";
  83.247 @@ -234,6 +289,7 @@
  83.248  ["One issue you are interested in"] = "Unu temo, kiu vin interesas";
  83.249  ["One step back"] = "Unu paŝo reen";
  83.250  ["Open"] = "Malferma";
  83.251 +["Opinions"] = false;
  83.252  ["Order by"] = "Ordigi laŭ";
  83.253  ["Organizational unit"] = "Organiza unuo";
  83.254  ["Outgoing delegations"] = "Elirantaj delegacioj";
  83.255 @@ -247,7 +303,7 @@
  83.256  ["Photo"] = "Foto";
  83.257  ["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."] = "Bonvolu elekti salutonomon! Tiu nomo ne estas montrita al aliaj kaj nur vi uzas tiun nomon por la saluto. La uskleco (granda/malgranda) gravas";
  83.258  ["Please choose a member"] = "Bonvolu elekti membron";
  83.259 -["Please choose a name, i.e. your real name or your nick name. This name will be shown to others to identify you."] = "Bonvolu elekti nomon, ekzemple vian veran nomon aŭ kromnomon. Tiu nomo estas montrita al aliaj por vin identecigi."; 
  83.260 +["Please choose a name, i.e. your real name or your nick name. This name will be shown to others to identify you."] = "Bonvolu elekti nomon, ekzemple vian veran nomon aŭ kromnomon. Tiu nomo estas montrita al aliaj por vin identecigi.";
  83.261  ["Please choose a password and enter it twice. The password is case sensitive."] = "Bonvolu elekti pasvorton kaj enigi tiun pasvorton dufoje! La uskleco (granda/malgranda) gravas.";
  83.262  ["Please choose a policy"] = "Bonvolu elekti regularon";
  83.263  ["Please choose two different versions of the draft to compare"] = "Bonvolu elekti du malsamajn versiojn de la skizo por kompari ilin.";
  83.264 @@ -260,14 +316,14 @@
  83.265  ["Please enter your new password twice."] = "Bonvolu enigi dufoje vian novan pasvorton:";
  83.266  ["Policy"] = "Regularo";
  83.267  ["Population"] = "Loĝantaro";
  83.268 -["Posts"] = "Postenoj"; -- im Sinne von Posten oder im Sinne von Einträge? Letzeres wäre "Enskriboj"
  83.269 +["Posts"] = "Postenoj";
  83.270  ["Potential support"] = "Eventuala subteno";
  83.271 +["Potential supported"] = false;
  83.272  ["Potential supporter"] = "Eventuala subtenanto";
  83.273  ["Profession"] = "Profesio";
  83.274  ["Profile"] = "Profilo";
  83.275  ["Publish"] = "Publikigi";
  83.276  ["Published"] = "Publikigita";
  83.277 -["Published contacts"] = "Kontaktoj publikigitaj";
  83.278  ["Rank"] = "Rango";
  83.279  ["Real name"] = "Vera nomo";
  83.280  ["Refresh support to current draft"] = "Refreŝigi subtenon por la aktuala skizo";
  83.281 @@ -283,6 +339,7 @@
  83.282  ["Remove initiator from initiative"] = "Ĉu forigi iniciatinton de la iniciato?";
  83.283  ["Remove my interest"] = "Forigi mian intereson";
  83.284  ["Remove my membership"] = "Forigi mian membrecon";
  83.285 +["Remove my request to vote later"] = false;
  83.286  ["Remove my support from this initiative"] = "Forigi mian subtenon de la iniciato";
  83.287  ["Repeat new password"] = "Ripeti novan pasvorton";
  83.288  ["Request password reset link"] = "Demandi ligilon por remeti la pasvorton";
  83.289 @@ -295,12 +352,15 @@
  83.290  ["Revoked at"] = "Nuligita je";
  83.291  ["Saturday"] = "Sabato";
  83.292  ["Save"] = "Konservi";
  83.293 +["Save current filter"] = false;
  83.294 +["Save timeline filters"] = false;
  83.295  ["Saved as contact"] = "Konservi kiel kontakton";
  83.296  ["Search"] = "Serĉi";
  83.297  ["Search initiatives"] = "Serĉi iniciatojn";
  83.298  ["Search issues"] = "Serĉi temojn";
  83.299  ["Search members"] = "Serĉi membrojn";
  83.300  ["Search results for: '#{search}'"] = "Serĉorezultoj por: '#{search}'";
  83.301 +["Select language \"#{langcode}\""] = false;
  83.302  ["Set URL"] = "Meti URL";
  83.303  ["Set area delegation"] = "Meti delegacion por temaro";
  83.304  ["Set autoreject"] = "Meti aŭtorifuzo";
  83.305 @@ -309,16 +369,20 @@
  83.306  ["Set global delegation"] = "Meti ĝeneralan delegacion";
  83.307  ["Set issue delegation"] = "Meti delegacion por temo";
  83.308  ["Set new password"] = "Meti novan pasvorton";
  83.309 -["Settings"] = "Agordoj"; 
  83.310 +["Settings"] = "Agordoj";
  83.311  ["Show"] = "Montri";
  83.312  ["Show active members"] = "Montri aktivajn membrojn";
  83.313 -["Show all initiatives"] = "Montri ĉiujn iniciatojn";
  83.314 +["Show alternative initiatives"] = false;
  83.315  ["Show areas in use"] = "Montri uzatajn temarojn";
  83.316  ["Show areas not in use"] = "Montri ne uzatajn temarojn";
  83.317  ["Show diff"] = "Montri diferencojn";
  83.318 +["Show filter"] = false;
  83.319 +["Show filter details"] = false;
  83.320 +["Show help text"] = false;
  83.321  ["Show locked members"] = "Montri blokitajn membrojn";
  83.322  ["Show member"] = "Montri membron";
  83.323  ["Show name history"] = "Montri nomohistorion";
  83.324 +["Show only events which match... (or associtated)"] = false;
  83.325  ["Software"] = "Programaro";
  83.326  ["Some JavaScript based functions (voting in particular) will not work.\nFor this beta, please use a current version of Firefox, Safari, Opera(?), Konqueror or another (more) standard compliant browser.\nAlternative access without JavaScript will be available soon."] = "Kelkaj funkcioj bazitaj je JavaScript (precipe la voĉdono) ne funkcios.\nBonvolu, uzi por tiu betaversio aktualan version de Firefox, Safari, Opera(?), Konqueror aŭ alian (pli) normokonforman retumilon.\nAlternativa atingo sen JavaScript estos baldaŭ disponeble.";
  83.327  ["Sorry, but there is not confirmed email address for your account. Please contact the administrator or support."] = "Pardonu, por tiu konto ne ekzistas konfirmita retadreson. Bonvolu vin turni al administranto aŭ al la helpantaro.";
  83.328 @@ -344,15 +408,27 @@
  83.329  ["Sunday"] = "Dimanĉo";
  83.330  ["Support"] = "Subteno";
  83.331  ["Support this initiative"] = "Subteni tiun iniciaton";
  83.332 +["Supported"] = false;
  83.333  ["Supported initiatives"] = "Iniciatoj subtenitaj";
  83.334  ["Supporter"] = "Subtenantoj";
  83.335 +["Tabs"] = false;
  83.336  ["Terms accepted"] = "Kondiĉoj akceptitaj";
  83.337 +["Terms of use"] = false;
  83.338  ["The code you've entered is invalid"] = "La kodo, kiun vi enigis ne estas valida!";
  83.339 +["The draft of this initiative has been updated!"] = false;
  83.340  ["The drafts do not differ"] = "La skizoj ne estas malsamaj";
  83.341  ["The initiators suggest to support the following initiative:"] = "La iniciatantoj rekomendas subteni sekvan iniciaton:";
  83.342 +["There are no more alternative initiatives currently."] = false;
  83.343 +["There were no more alternative initiatives."] = false;
  83.344 +["This initiative"] = false;
  83.345 +["This initiative compared to alternative initiatives"] = false;
  83.346  ["This initiative has been revoked at #{revoked}"] = "Tiu iniciato estis nuligita je #{revoked}";
  83.347 +["This initiative has not been admitted! It failed the quorum of #{quorum}."] = false;
  83.348  ["This initiative is already revoked"] = "Tiu iniciato estas jam nuligita";
  83.349  ["This initiative is revoked"] = "Tiu iniciato estas nuligita";
  83.350 +["This issue has been cancelled. It failed the quorum of #{quorum}."] = false;
  83.351 +["This issue has been finished with the following winning initiative:"] = false;
  83.352 +["This issue has been finished without any winning initiative."] = false;
  83.353  ["This issue is already closed."] = "La temo estas jam fermita.";
  83.354  ["This issue is already frozen."] = "La temo estas jam ĝelita";
  83.355  ["This login is already taken, please choose another one!"] = "Tiu salutnomo estas jam fordonita, bonvolu elekti alian!";
  83.356 @@ -361,6 +437,7 @@
  83.357  ["This member has rejected to become initiator of this initiative"] = "Tiu membro rifuzis inviton por esti iniciatanto";
  83.358  ["This member is already initiator of this initiative"] = "Tiu membro estas jam iniciatanto de tiu iniciato";
  83.359  ["This member is already invited to become initiator of this initiative"] = "Tiu membro estis jam invitita por esti iniciatanto de tiu iniciato";
  83.360 +["This member is participating, the rest of delegation chain is suspended while discussing"] = false;
  83.361  ["This name is already taken, please choose another one!"] = "Tiu nomo estas jam fordonita, bonvolu elekti alian!";
  83.362  ["This name is really too short!"] = "Tiu nomo estas vere tro mallonga!";
  83.363  ["This name is too short!"] = "Tiu nomo estas tro mallonga!";
  83.364 @@ -369,43 +446,49 @@
  83.365  ["This username is too short!"] = "Tiu salutonomo estas tro mallonga!";
  83.366  ["Thursday"] = "Ĵaŭdo";
  83.367  ["Time left"] = "Restanta tempo";
  83.368 +["Timeline"] = false;
  83.369 +["Title"] = false;
  83.370  ["Title (80 chars max)"] = "Titolo (maksimume 80 literoj)";
  83.371 -["Today"] = "Hodiaŭ";
  83.372  ["Traditional wiki syntax"] = "Tradicia Viki-sintakso";
  83.373 -["Trustee"] = "Fidulo mastrumanta"; -- kommt stark auf den Sinn an, ist ohne Kontext schwierig
  83.374 +["Trustee"] = "Fidulo mastrumanta";
  83.375  ["Tuesday"] = "Mardo";
  83.376 +["Type of tabs"] = false;
  83.377  ["Unknown author"] = "Aŭtoro nekonata";
  83.378  ["Upload images"] = "Alŝuti bildojn";
  83.379  ["Used until"] = "Uzita ĝis";
  83.380  ["Verification time"] = "Tempo por la kontrolo";
  83.381  ["Version"] = "Versio";
  83.382  ["Vote later"] = "Baloti pli malfrue";
  83.383 +["Vote later requests"] = false;
  83.384  ["Vote now"] = "Baloti nun";
  83.385 -["Vote now/later"] = "Baloti nun/pli malfrue";
  83.386  ["Voted"] = "Balotita";
  83.387  ["Voted no"] = "Balotita nee";
  83.388  ["Voted proposal"] = "Propono balotita";
  83.389  ["Voted yes"] = "Balotita jese";
  83.390 -["Voter"] = "Voĉdonantoj";
  83.391  ["Voting"] = "Voĉdono";
  83.392 +["Voting details"] = false;
  83.393  ["Voting for this issue has already begun."] = "Voĉdono pri tiu temo jam komenciĝis.";
  83.394  ["Voting for this issue is currently running!"] = "Voĉdono pri tiu temo okazas nun!";
  83.395  ["Voting has not started yet."] = "Voĉdono por tiu temo ankoraŭ ne komenciĝis.";
  83.396  ["Voting proposal"] = "Privoĉdonendaj proponoj";
  83.397 -["Voting requests"] = "Voĉdonopetoj";
  83.398 +["Voting request updated"] = false;
  83.399 +["Voting started"] = false;
  83.400  ["Voting time"] = "Tempo por la voĉdono";
  83.401  ["Website"] = "Retpaĝo";
  83.402  ["Wednesday"] = "Merkredo";
  83.403  ["Wiki engine"] = "Viki-motoro";
  83.404  ["Yes"] = "Jes";
  83.405 -["Yesterday"] = "Hieraŭ";
  83.406  ["You are already initator"] = "Vi estas jam iniciatanto";
  83.407  ["You are already not supporting this initiative"] = "Vi jam ne subtenas tiun iniciaton";
  83.408  ["You are already supporting the latest draft"] = "Vi jam subtenas la plej novan skizon";
  83.409  ["You are currently not supporting this initiative. By adding suggestions to this initiative you will automatically become a potential supporter."] = "Vi aktuale ne subtenas tiun iniciaton. Se vi aldonas sugeston al tiu iniciato vi estos aŭtomate eventuala subtenanto!";
  83.410 +["You are iniator of this initiative"] = false;
  83.411 +["You are interested in this issue"] = false;
  83.412  ["You are invited to become initiator of this initiative."] = "Vi estas invitita por esti iniciatanto de tiu iniciato.";
  83.413  ["You are member"] = "Vi estas membro";
  83.414  ["You are now initiator of this initiative"] = "Vi nun estas iniciatanto de tiu iniciato";
  83.415 +["You are potential supporter of this initiative"] = false;
  83.416 +["You are supporting this initiative"] = false;
  83.417  ["You can't suggest the initiative you are revoking"] = "Vi ne povas rekomendi la iniciaton, kiun vi nuligas";
  83.418  ["You didn't saved any member as contact yet."] = "Vi ankoraŭ ne storis membron kiel kontakton!";
  83.419  ["You have saved this member as contact"] = "Vi storis membron kiel kontakton";
  83.420 @@ -413,6 +496,7 @@
  83.421  ["You have to accept the terms of use to complete registration."] = "Vi devas akcepti la uzokondiĉojn por fini la registradon.";
  83.422  ["You have to mark 'Are you sure' to revoke!"] = "Por nuligi vi devas elekti 'Certa?'";
  83.423  ["You need to be logged in, to use this system."] = "Vi devas esti ensalutinta, por uzi la sistemon";
  83.424 +["You want to vote later"] = false;
  83.425  ["You've successfully registered and you can login now with your login and password!"] = "Vi sukcese registriĝis kaj povas nun ensaluti per via salutnomo kaj pasvorto!";
  83.426  ["Your are interested"] = "Vi estas interesita";
  83.427  ["Your are potential supporter"] = "Vi estas eventuala subtenanto";
  83.428 @@ -421,6 +505,7 @@
  83.429  ["Your delegation for this area has been updated."] = "Via delegacio por tiu temaro estas ĝisdatigita";
  83.430  ["Your delegation for this issue has been deleted."] = "Via delegacio por tiu temaro estas viŝita";
  83.431  ["Your delegation for this issue has been updated."] = "Via delegacio por tiu temaro estas ĝisdatigita";
  83.432 +["Your display settings have been updated"] = false;
  83.433  ["Your global delegation has been deleted."] = "Via ĝenerala delegacio estas viŝita";
  83.434  ["Your global delegation has been updated."] = "Via ĝenerala delegacio estas ĝisdatigita";
  83.435  ["Your login has been changed to '#{login}'"] = "Via salutnomo estas ĝisdatigita al '#{login}'";
  83.436 @@ -435,17 +520,18 @@
  83.437  ["Your support has been updated to the latest draft"] = "Via subteno estas ĝisdatigita al la plej nova skizo";
  83.438  ["Your web browser is not fully supported yet."] = "Via retumilo ne estas jam komplete subtenita.";
  83.439  ["Z-A"] = "Z-A";
  83.440 -["all"] = "ĉiuj";
  83.441 +["and #{count} more initiatives"] = false;
  83.442  ["continuing"] = "kontinue";
  83.443  ["delete<br /><br />"] = "forviŝi<br /><br />";
  83.444  ["email"] = "Retpoŝto";
  83.445 +["last 24 hours"] = false;
  83.446  ["login name"] = "Salutnomo";
  83.447  ["must"] = "devas";
  83.448  ["must not"] = "ne rajtas";
  83.449  ["must/should"] = "devus";
  83.450  ["must/should not"] = "ne devus";
  83.451  ["neutral"] = "neŭtrala";
  83.452 -["not implemented"] = "ne realigita";
  83.453 +["requested"] = false;
  83.454  ["should"] = "devus";
  83.455  ["should not"] = "ne devus";
  83.456  ["to reset your password please click on the following link:\n\n"] = "por remeti vian pasvorton bonvolu klaki sekvan ligilon:\n\n";
    84.1 --- a/model/initiative.lua	Tue Feb 02 00:31:06 2010 +0100
    84.2 +++ b/model/initiative.lua	Sat Feb 20 22:10:31 2010 +0100
    84.3 @@ -16,7 +16,7 @@
    84.4    that_key      = 'initiative_id',
    84.5    ref           = 'drafts',
    84.6    back_ref      = 'initiative',
    84.7 -  default_order = '"id"'
    84.8 +  default_order = '"id" DESC'
    84.9  }
   84.10  
   84.11  Initiative:add_reference{
   84.12 @@ -129,8 +129,11 @@
   84.13      :add_group_by('"initiative"."negative_votes"')
   84.14      :add_group_by('"initiative"."agreed"')
   84.15      :add_group_by('"initiative"."rank"')
   84.16 +    :add_group_by('"initiative"."suggested_initiative_id"')
   84.17      :add_group_by('"initiative"."text_search_data"')
   84.18      :add_group_by('"issue"."population"')
   84.19 +    :add_group_by("_initiator.member_id")
   84.20 +    :add_group_by("_supporter.member_id")
   84.21  end
   84.22  
   84.23  function Member:get_search_selector(search_string)
    85.1 --- a/model/issue.lua	Tue Feb 02 00:31:06 2010 +0100
    85.2 +++ b/model/issue.lua	Sat Feb 20 22:10:31 2010 +0100
    85.3 @@ -142,6 +142,7 @@
    85.4      :add_group_by('"issue"."vote_now"')
    85.5      :add_group_by('"issue"."vote_later"')
    85.6      :add_group_by('"issue"."voter_count"')
    85.7 +    :add_group_by('"_interest"."member_id"')
    85.8      --:set_distinct()
    85.9  end
   85.10  
    86.1 --- a/model/member.lua	Tue Feb 02 00:31:06 2010 +0100
    86.2 +++ b/model/member.lua	Sat Feb 20 22:10:31 2010 +0100
    86.3 @@ -311,10 +311,26 @@
    86.4    return success
    86.5  end
    86.6  
    86.7 -function Member.object:get_setting_by_key(key)
    86.8 +function Member.object:get_setting(key)
    86.9 +  return Setting:by_pk(app.session.member.id, key)
   86.10 +end
   86.11 +
   86.12 +function Member.object:get_setting_value(key)
   86.13 +  local setting = Setting:by_pk(app.session.member.id, key)
   86.14 +  if setting then
   86.15 +    return setting.value
   86.16 +  end
   86.17  end
   86.18  
   86.19  function Member.object:set_setting(key, value)
   86.20 +  local setting = self:get_setting(key)
   86.21 +  if not setting then
   86.22 +    setting = Setting:new()
   86.23 +    setting.member_id = app.session.member_id
   86.24 +    setting.key = key
   86.25 +  end
   86.26 +  setting.value = value
   86.27 +  setting:save()
   86.28  end
   86.29  
   86.30  function Member.object:get_setting_maps_by_key(key)
    87.1 Binary file static/icons/16/bullet_blue.png has changed
    88.1 Binary file static/icons/16/bullet_toggle_minus.png has changed
    89.1 Binary file static/icons/16/bullet_toggle_plus.png has changed
    90.1 Binary file static/icons/16/connect.png has changed
    91.1 Binary file static/icons/16/help_yellow.png has changed
    92.1 Binary file static/icons/16/lock.png has changed
    93.1 Binary file static/icons/16/resultset_next.png has changed
    94.1 Binary file static/icons/move_down.png has changed
    95.1 Binary file static/icons/move_up.png has changed
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/static/js/partialload.js	Sat Feb 20 22:10:31 2010 +0100
    96.3 @@ -0,0 +1,271 @@
    96.4 +
    96.5 +partialload_queue = [];
    96.6 +partialload_queueRPos = 0;
    96.7 +partialload_queueWPos = 0;
    96.8 +
    96.9 +function partialload_getFormKeyValuePairs(form) {
   96.10 +  var result = {};
   96.11 +  for (var i=0; i<form.elements.length; i++) {
   96.12 +    var inputElement = form.elements[i];
   96.13 +    var key = inputElement.name;
   96.14 +    var value = inputElement.value;
   96.15 +    if (result[key] == null) result[key] = value;
   96.16 +    else if (typeof(result[key]) == "object") {
   96.17 +      result[key][result[key].length] = value;
   96.18 +    } else {
   96.19 +      result[key] = [result[key], value];
   96.20 +    }
   96.21 +  }
   96.22 +  return result;
   96.23 +}
   96.24 +
   96.25 +function partialload_encodeFormData(params) {
   96.26 +  var result = "";
   96.27 +  for (var key in params) {
   96.28 +    var value = params[key];
   96.29 +    if (typeof(value) == "string") {
   96.30 +      if (result != "") result += "&";
   96.31 +      result += encodeURIComponent(key) + "=" + encodeURIComponent(value);
   96.32 +    } else if (typeof(value) == "object") {
   96.33 +      var i;
   96.34 +      for (i=0; i<value.length; i++) {
   96.35 +        if (result != "") result += "&";
   96.36 +        result += encodeURIComponent(key) + "=" + encodeURIComponent(value[i]);
   96.37 +      }
   96.38 +    }
   96.39 +  }
   96.40 +  return result;
   96.41 +}
   96.42 +
   96.43 +function partialload_addFormDataToUrl(url, params) {
   96.44 +  if (params != null && typeof(params) != "string") {
   96.45 +    params = partialload_encodeFormData(params);
   96.46 +  }
   96.47 +  if (params != null) {
   96.48 +    if (url.search(/\?/) >= 0) {
   96.49 +      if (url.search(/&$/) >= 0) {
   96.50 +        url = url + params;
   96.51 +      } else {
   96.52 +        url = url + "&" + params;
   96.53 +      }
   96.54 +    } else {
   96.55 +      url = url + "?" + params;
   96.56 +    }
   96.57 +  }
   96.58 +  return url;
   96.59 +}
   96.60 +
   96.61 +function partialload_mergeEncodedFormData(data1, data2) {
   96.62 +  if (data2 == null || data2 == "") return data1;
   96.63 +  if (data1 == null || data1 == "") return data2;
   96.64 +  return data1 + "&" + data2;
   96.65 +}
   96.66 +
   96.67 +function partialload_startNextRequest() {
   96.68 +  var entry = partialload_queue[partialload_queueRPos++];
   96.69 +  var req = new XMLHttpRequest();
   96.70 +  req.open(entry.method, entry.url, true);
   96.71 +  req.onreadystatechange = function() {
   96.72 +    if (req.readyState == 4) {
   96.73 +      if (req.status == 200) {
   96.74 +        if (entry.successHandler != null) entry.successHandler(req.responseText);
   96.75 +      } else {
   96.76 +        if (entry.failureHandler != null) entry.failureHandler();
   96.77 +      }
   96.78 +      if (partialload_queue[partialload_queueRPos]) {
   96.79 +        partialload_startNextRequest();
   96.80 +      } else {
   96.81 +        partialload_queue = [];
   96.82 +        partialload_queueRPos = 0;
   96.83 +        partialload_queueWPos = 0;
   96.84 +      }
   96.85 +    }
   96.86 +  }
   96.87 +  if (entry.data) {
   96.88 +    req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
   96.89 +  }
   96.90 +  req.send(entry.data);
   96.91 +}
   96.92 +
   96.93 +function queuedHttpRequest(
   96.94 +  url_or_form,
   96.95 +  urlParams,
   96.96 +  postParams,
   96.97 +  successHandler,
   96.98 +  failureHandler
   96.99 +) {
  96.100 +  var method;
  96.101 +  var data = null;
  96.102 +  if (typeof(postParams) == "string") {
  96.103 +    data = postParams;
  96.104 +  } else if (postParams != null) {
  96.105 +    data = partialload_encodeFormData(postParams);
  96.106 +  }
  96.107 +  var url;
  96.108 +  if (typeof(url_or_form) == "object") {
  96.109 +    // form element given
  96.110 +    var form = url_or_form;
  96.111 +    url = partialload_addFormDataToUrl(form.action, urlParams);
  96.112 +    var dataFromForm = partialload_encodeFormData(
  96.113 +      partialload_getFormKeyValuePairs(form)
  96.114 +    );
  96.115 +    if (form.method != null && form.method.search(/^POST$/i) >= 0) {
  96.116 +      method = "POST";
  96.117 +      data = partialload_mergeEncodedFormData(data, dataFromForm);
  96.118 +    } else {
  96.119 +      method = (postParams == NULL) ? "GET" : "POST";
  96.120 +      url = partialload_addFormDataToUrl(url, dataFromForm);
  96.121 +    }
  96.122 +  } else {
  96.123 +    // URL given
  96.124 +    url = partialload_addFormDataToUrl(url_or_form, urlParams);
  96.125 +    if (postParams == null) {
  96.126 +      method = "GET";
  96.127 +    } else {
  96.128 +      method = "POST";
  96.129 +      if (typeof(postParams) == "string") {
  96.130 +	data = postParams;
  96.131 +      } else {
  96.132 +	data = partialload_encodeFormData(postParams);
  96.133 +      }
  96.134 +    }
  96.135 +  }
  96.136 +  partialload_queue[partialload_queueWPos++] = {
  96.137 +    method:         method,
  96.138 +    url:            url,
  96.139 +    data:           data,
  96.140 +    successHandler: successHandler,
  96.141 +    failureHandler: failureHandler
  96.142 +  };
  96.143 +  if (partialload_queueRPos == 0) {
  96.144 +    partialload_startNextRequest();
  96.145 +  }
  96.146 +}
  96.147 +
  96.148 +function setHtmlContent(node, htmlWithScripts) {
  96.149 +  var uniquePrefix = "placeholder" + Math.floor(Math.random()*10e16) + "_";
  96.150 +  var i = 0;
  96.151 +  var scripts = [];
  96.152 +  var htmlWithPlaceholders = "";
  96.153 +  // NOTE: This function can not handle CDATA blocks at random positions.
  96.154 +  htmlWithPlaceholders = htmlWithScripts.replace(
  96.155 +    /<script[^>]*>(.*?)<\/script>/ig,
  96.156 +    function(all, inside) {
  96.157 +      scripts[i] = inside;
  96.158 +      var placeholder = '<span id="' + uniquePrefix + i + '"></span>';
  96.159 +      i++;
  96.160 +      return placeholder;
  96.161 +    }
  96.162 +  )
  96.163 +  node.innerHTML = htmlWithPlaceholders;
  96.164 +  var documentWriteBackup   = document.write;
  96.165 +  var documentWritelnBackup = document.writeln;
  96.166 +  var output;
  96.167 +  document.write   = function(str) { output += str; }
  96.168 +  document.writeln = function(str) { output += str + "\n"; }
  96.169 +  for (i=0; i<scripts.length; i++) {
  96.170 +    var placeholderNode = document.getElementById(uniquePrefix + i);
  96.171 +    output = "";
  96.172 +    eval(scripts[i]);
  96.173 +    if (output != "") {
  96.174 +      placeholderNode.innerHTML = output;
  96.175 +      while (placeholderNode.childNodes.length > 0) {
  96.176 +        var childNode = placeholderNode.childNodes[0];
  96.177 +        placeholderNode.removeChild(childNode);
  96.178 +        placeholderNode.parentNode.insertBefore(childNode, placeholderNode);
  96.179 +      }
  96.180 +    }
  96.181 +    placeholderNode.parentNode.removeChild(placeholderNode);
  96.182 +  }
  96.183 +  document.write   = documentWriteBackup;
  96.184 +  document.writeln = documentWritelnBackup;
  96.185 +}
  96.186 +
  96.187 +function partialLoad(
  96.188 +  node,
  96.189 +  tempLoadingContent,
  96.190 +  failureContent,
  96.191 +  url_or_form,
  96.192 +  urlParams,
  96.193 +  postParams,
  96.194 +  successHandler,
  96.195 +  failureHandler
  96.196 +) {
  96.197 +  if (typeof(node) == "string") node = document.getElementById(node);
  96.198 +  if (tempLoadingContent != null) setHtmlContent(node, tempLoadingContent);
  96.199 +  queuedHttpRequest(
  96.200 +    url_or_form,
  96.201 +    urlParams,
  96.202 +    postParams,
  96.203 +    function(response) {
  96.204 +      setHtmlContent(node, response);
  96.205 +      if (successHandler != null) successHandler();
  96.206 +    },
  96.207 +    function() {
  96.208 +      if (failureContent != null) setHtmlContent(node, failureContent);
  96.209 +      if (failureHandler != null) failureHandler();
  96.210 +    }
  96.211 +  );
  96.212 +}
  96.213 +
  96.214 +function partialMultiLoad(
  96.215 +  mapping,
  96.216 +  tempLoadingContents,
  96.217 +  failureContents,
  96.218 +  url_or_form,
  96.219 +  urlParams,
  96.220 +  postParams,
  96.221 +  successHandler,
  96.222 +  failureHandler
  96.223 +) {
  96.224 +  if (mapping instanceof Array) {
  96.225 +    var mappingHash = {}
  96.226 +    for (var i=0; i<mapping.length; i++) {
  96.227 +      mappingHash[mapping[i]] = mapping[i];
  96.228 +    }
  96.229 +    mapping = mappingHash;
  96.230 +  }
  96.231 +  if (typeof(tempLoadingContents) == "string") {
  96.232 +    for (var key in mapping) {
  96.233 +      var node = key;
  96.234 +      if (typeof(node) == "string") node = document.getElementById(node);
  96.235 +      setHtmlContent(node, tempLoadingContents);
  96.236 +    }
  96.237 +  } else if (tempLoadingContents != null) {
  96.238 +    for (var key in tempLoadingContents) {
  96.239 +      var node = key;
  96.240 +      if (typeof(node) == "string") node = document.getElementById(node);
  96.241 +      setHtmlContent(node, tempLoadingContents[key]);
  96.242 +    }
  96.243 +  }
  96.244 +  queuedHttpRequest(
  96.245 +    url_or_form,
  96.246 +    urlParams,
  96.247 +    postParams,
  96.248 +    function(response) {
  96.249 +      var data = eval("(" + response + ")");
  96.250 +      for (var key in mapping) {
  96.251 +        var node = key;
  96.252 +        if (typeof(node) == "string") node = document.getElementById(node);
  96.253 +        setHtmlContent(node, data[mapping[key]]);
  96.254 +      }
  96.255 +      if (successHandler != null) successHandler();
  96.256 +    },
  96.257 +    function() {
  96.258 +      if (typeof(failureContents) == "string") {
  96.259 +        for (var key in mapping) {
  96.260 +          var node = key;
  96.261 +          if (typeof(node) == "string") node = document.getElementById(node);
  96.262 +          setHtmlContent(node, failureContents);
  96.263 +        }
  96.264 +      } else if (failureContents != null) {
  96.265 +        for (var key in failureContents) {
  96.266 +          var node = key;
  96.267 +          if (typeof(node) == "string") node = document.getElementById(node);
  96.268 +          setHtmlContent(node, failureContents[key]);
  96.269 +        }
  96.270 +      }
  96.271 +      if (failureHandler != null) failureHandler();
  96.272 +    }
  96.273 +  );
  96.274 +}
    97.1 --- a/static/js/voting.js	Tue Feb 02 00:31:06 2010 +0100
    97.2 +++ b/static/js/voting.js	Sat Feb 20 22:10:31 2010 +0100
    97.3 @@ -1,4 +1,25 @@
    97.4 -function setCategoryHeadings() {
    97.5 +voting_text_approval_single               = "Approval"
    97.6 +voting_text_approval_multi                = "Approval"
    97.7 +voting_text_first_preference_single       = "Approval (first preference)"
    97.8 +voting_text_first_preference_multi        = "Approval (first preference)"
    97.9 +voting_text_second_preference_single      = "Approval (second preference)"
   97.10 +voting_text_second_preference_multi       = "Approval (second preference)"
   97.11 +voting_text_third_preference_single       = "Approval (third preference)"
   97.12 +voting_text_third_preference_multi        = "Approval (third preference)"
   97.13 +voting_text_numeric_preference_single     = "Approval (#th preference)"
   97.14 +voting_text_numeric_preference_multi      = "Approval (#th preference)"
   97.15 +voting_text_abstention_single             = "Abstention"
   97.16 +voting_text_abstention_multi              = "Abstention"
   97.17 +voting_text_disapproval_above_one_single  = "Disapproval (prefer to lower block)"
   97.18 +voting_text_disapproval_above_one_multi   = "Disapproval (prefer to lower block)"
   97.19 +voting_text_disapproval_above_many_single = "Disapproval (prefer to lower blocks)"
   97.20 +voting_text_disapproval_above_many_multi  = "Disapproval (prefer to lower blocks)"
   97.21 +voting_text_disapproval_above_last_single = "Disapproval (prefer to last block)"
   97.22 +voting_text_disapproval_above_last_multi  = "Disapproval (prefer to last block)"
   97.23 +voting_text_disapproval_single            = "Disapproval"
   97.24 +voting_text_disapproval_multi             = "Disapproval"
   97.25 +
   97.26 +function voting_setCategoryHeadings() {
   97.27    var approvalCount = 0;
   97.28    var disapprovalCount = 0;
   97.29    var sections = document.getElementById("voting").childNodes;
   97.30 @@ -34,42 +55,53 @@
   97.31        if (section.className == "approval") {
   97.32          if (approvalCount > 1) {
   97.33            if (approvalIndex == 0) {
   97.34 -            if (count == 1) setHeading("Zustimmung (Erstwunsch)");
   97.35 -            else setHeading("Zustimmung (Erstwünsche)");
   97.36 +            if (count == 1) setHeading(voting_text_first_preference_single);
   97.37 +            else setHeading(voting_text_first_preference_multi);
   97.38            } else if (approvalIndex == 1) {
   97.39 -            if (count == 1) setHeading("Zustimmung (Zweitwunsch)");
   97.40 -            else setHeading("Zustimmung (Zweitwünsche)");
   97.41 +            if (count == 1) setHeading(voting_text_second_preference_single);
   97.42 +            else setHeading(voting_text_second_preference_multi);
   97.43            } else if (approvalIndex == 2) {
   97.44 -            if (count == 1) setHeading("Zustimmung (Drittwunsch)");
   97.45 -            else setHeading("Zustimmung (Drittwünsche)");
   97.46 +            if (count == 1) setHeading(voting_text_third_preference_single);
   97.47 +            else setHeading(voting_text_third_preference_multi);
   97.48            } else {
   97.49 -            if (count == 1) setHeading("Zustimmung (" + (approvalIndex+1) + ".-Wunsch)");
   97.50 -            else setHeading("Zustimmung (" + (approvalIndex+1) + ".-Wünsche)");
   97.51 +            var text;
   97.52 +            if (count == 1) text = voting_text_numeric_preference_single;
   97.53 +            else text = voting_text_numeric_preference_multi;
   97.54 +            text = text.replace(/#/, "" + (approvalIndex + 1))
   97.55 +            setHeading(text);
   97.56            }
   97.57          } else {
   97.58 -          setHeading("Zustimmung");
   97.59 +          if (count == 1) setHeading(voting_text_approval_single);
   97.60 +          else setHeading(voting_text_approval_multi);
   97.61          }
   97.62          approvalIndex++;
   97.63        } else if (section.className == "abstention") {
   97.64 -        setHeading("Enthaltung");
   97.65 +        if (count == 1) setHeading(voting_text_abstention_single);
   97.66 +        else setHeading(voting_text_abstention_multi);
   97.67        } else if (section.className == "disapproval") {
   97.68          if (disapprovalCount > disapprovalIndex + 2) {
   97.69 -          setHeading("Ablehnung (jedoch Bevorzugung gegenüber unteren Ablehnungsblöcken)")
   97.70 +          if (count == 1) setHeading(voting_text_disapproval_above_many_single);
   97.71 +          else setHeading(voting_text_disapproval_above_many_multi);
   97.72          } else if (disapprovalCount == 2 && disapprovalIndex == 0) {
   97.73 -          setHeading("Ablehnung (jedoch Bevorzugung gegenüber unterem Ablehnungsblock)")
   97.74 +          if (count == 1) setHeading(voting_text_disapproval_above_one_single);
   97.75 +          else setHeading(voting_text_disapproval_above_one_multi);
   97.76          } else if (disapprovalIndex == disapprovalCount - 2) {
   97.77 -          setHeading("Ablehnung (jedoch Bevorzugung gegenüber letztem Ablehnungsblock)")
   97.78 +          if (count == 1) setHeading(voting_text_disapproval_above_last_single);
   97.79 +          else setHeading(voting_text_disapproval_above_last_multi);
   97.80          } else {
   97.81 -          setHeading("Ablehnung");
   97.82 +          if (count == 1) setHeading(voting_text_disapproval_single);
   97.83 +          else setHeading(voting_text_disapproval_multi);
   97.84          }
   97.85          disapprovalIndex++;
   97.86        }
   97.87      }
   97.88    }
   97.89  }
   97.90 -function elementDropped(element, dropX, dropY) {
   97.91 +function voting_move(element, up, dropX, dropY) {
   97.92 +  if (typeof(element) == "string") element = document.getElementById(element);
   97.93 +  var mouse = (up == null);
   97.94    var oldParent = element.parentNode;
   97.95 -  var centerY = dropY + element.clientHeight / 2
   97.96 +  if (mouse) var centerY = dropY + element.clientHeight / 2;
   97.97    var approvalCount = 0;
   97.98    var disapprovalCount = 0;
   97.99    var mainDiv = document.getElementById("voting");
  97.100 @@ -79,43 +111,7 @@
  97.101      if (section.className == "approval")       approvalCount++;
  97.102      if (section.className == "disapproval") disapprovalCount++;
  97.103    }
  97.104 -  for (var i=0; i<sections.length; i++) {
  97.105 -    var section = sections[i];
  97.106 -    if (
  97.107 -      section.className == "approval" ||
  97.108 -      section.className == "abstention" ||
  97.109 -      section.className == "disapproval"
  97.110 -    ) {
  97.111 -      if (
  97.112 -        centerY >= section.offsetTop &&
  97.113 -        centerY <  section.offsetTop + section.clientHeight
  97.114 -      ) {
  97.115 -        var entries = section.childNodes;
  97.116 -        for (var j=0; j<entries.length; j++) {
  97.117 -          var entry = entries[j];
  97.118 -          if (entry.className == "movable") {
  97.119 -            if (centerY < entry.offsetTop + entry.clientHeight / 2) {
  97.120 -              if (element != entry) {
  97.121 -                oldParent.removeChild(element);
  97.122 -                section.insertBefore(element, entry);
  97.123 -              }
  97.124 -              break;
  97.125 -            }
  97.126 -          }
  97.127 -        }
  97.128 -        if (j == entries.length) {
  97.129 -          oldParent.removeChild(element);
  97.130 -          section.appendChild(element);
  97.131 -        }
  97.132 -        break;
  97.133 -      }
  97.134 -    }
  97.135 -  }
  97.136 -  if (i == sections.length) {
  97.137 -    var newSection = document.createElement("div");
  97.138 -    var cathead = document.createElement("div");
  97.139 -    cathead.setAttribute("class", "cathead");
  97.140 -    newSection.appendChild(cathead);
  97.141 +  if (mouse) {
  97.142      for (var i=0; i<sections.length; i++) {
  97.143        var section = sections[i];
  97.144        if (
  97.145 @@ -123,28 +119,145 @@
  97.146          section.className == "abstention" ||
  97.147          section.className == "disapproval"
  97.148        ) {
  97.149 -        if (centerY < section.offsetTop + section.clientHeight / 2) {
  97.150 -          if (section.className == "disapproval") {
  97.151 -            newSection.setAttribute("class", "disapproval");
  97.152 -            disapprovalCount++;
  97.153 -          } else {
  97.154 -            newSection.setAttribute("class", "approval");
  97.155 -            approvalCount++;
  97.156 +        if (
  97.157 +          centerY >= section.offsetTop &&
  97.158 +          centerY <  section.offsetTop + section.clientHeight
  97.159 +        ) {
  97.160 +          var entries = section.childNodes;
  97.161 +          for (var j=0; j<entries.length; j++) {
  97.162 +            var entry = entries[j];
  97.163 +            if (entry.className == "movable") {
  97.164 +              if (centerY < entry.offsetTop + entry.clientHeight / 2) {
  97.165 +                if (element != entry) {
  97.166 +                  oldParent.removeChild(element);
  97.167 +                  section.insertBefore(element, entry);
  97.168 +                }
  97.169 +                break;
  97.170 +              }
  97.171 +            }
  97.172            }
  97.173 -          mainDiv.insertBefore(newSection, section);
  97.174 +          if (j == entries.length) {
  97.175 +            oldParent.removeChild(element);
  97.176 +            section.appendChild(element);
  97.177 +          }
  97.178            break;
  97.179          }
  97.180        }
  97.181      }
  97.182      if (i == sections.length) {
  97.183 -      newSection.setAttribute("class", "disapproval");
  97.184 -      disapprovalCount++;
  97.185 -      mainDiv.appendChild(newSection);
  97.186 +      var newSection = document.createElement("div");
  97.187 +      var cathead = document.createElement("div");
  97.188 +      cathead.setAttribute("class", "cathead");
  97.189 +      newSection.appendChild(cathead);
  97.190 +      for (var i=0; i<sections.length; i++) {
  97.191 +        var section = sections[i];
  97.192 +        if (
  97.193 +          section.className == "approval" ||
  97.194 +          section.className == "abstention" ||
  97.195 +          section.className == "disapproval"
  97.196 +        ) {
  97.197 +          if (centerY < section.offsetTop + section.clientHeight / 2) {
  97.198 +            if (section.className == "disapproval") {
  97.199 +              newSection.setAttribute("class", "disapproval");
  97.200 +              disapprovalCount++;
  97.201 +            } else {
  97.202 +              newSection.setAttribute("class", "approval");
  97.203 +              approvalCount++;
  97.204 +            }
  97.205 +            mainDiv.insertBefore(newSection, section);
  97.206 +            break;
  97.207 +          }
  97.208 +        }
  97.209 +      }
  97.210 +      if (i == sections.length) {
  97.211 +        newSection.setAttribute("class", "disapproval");
  97.212 +        disapprovalCount++;
  97.213 +        mainDiv.appendChild(newSection);
  97.214 +      }
  97.215 +      oldParent.removeChild(element);
  97.216 +      newSection.appendChild(element);
  97.217 +    }
  97.218 +  } else {
  97.219 +    var oldFound = false;
  97.220 +    var prevSection = null;
  97.221 +    var nextSection = null;
  97.222 +    for (var i=0; i<sections.length; i++) {
  97.223 +      var section = sections[i];
  97.224 +      if (
  97.225 +        section.className == "approval" ||
  97.226 +        section.className == "abstention" ||
  97.227 +        section.className == "disapproval"
  97.228 +      ) {
  97.229 +        if (oldFound) {
  97.230 +          nextSection = section;
  97.231 +          break;
  97.232 +        } else if (section == oldParent) {
  97.233 +          oldFound = true;
  97.234 +        } else {
  97.235 +          prevSection = section;
  97.236 +        }
  97.237 +      }
  97.238      }
  97.239 -    oldParent.removeChild(element);
  97.240 -    newSection.appendChild(element);
  97.241 +    var create;
  97.242 +    if (oldParent.className == "abstention") {
  97.243 +      create = true;
  97.244 +    } else {
  97.245 +      create = false;
  97.246 +      for (var i=0; i<oldParent.childNodes.length; i++) {
  97.247 +        var entry = oldParent.childNodes[i];
  97.248 +        if (entry.className == "movable") {
  97.249 +          if (entry != element) {
  97.250 +            create = true;
  97.251 +            break;
  97.252 +          }
  97.253 +        }
  97.254 +      }
  97.255 +    }
  97.256 +    var newSection;
  97.257 +    if (create) {
  97.258 +      newSection = document.createElement("div");
  97.259 +      var cathead = document.createElement("div");
  97.260 +      cathead.setAttribute("class", "cathead");
  97.261 +      newSection.appendChild(cathead);
  97.262 +      if (
  97.263 +        oldParent.className == "approval" ||
  97.264 +        (oldParent.className == "abstention" && up)
  97.265 +      ) {
  97.266 +        newSection.setAttribute("class", "approval");
  97.267 +        approvalCount++;
  97.268 +      } else {
  97.269 +        newSection.setAttribute("class", "disapproval");
  97.270 +        disapprovalCount++;
  97.271 +      }
  97.272 +      if (up) {
  97.273 +        mainDiv.insertBefore(newSection, oldParent);
  97.274 +      } else {
  97.275 +        if (nextSection) mainDiv.insertBefore(newSection, nextSection);
  97.276 +        else mainDiv.appendChild(newSection);
  97.277 +      }
  97.278 +    } else {
  97.279 +      if (up) newSection = prevSection;
  97.280 +      else newSection = nextSection;
  97.281 +    }
  97.282 +    if (newSection) {
  97.283 +      oldParent.removeChild(element);
  97.284 +      if (create || up) {
  97.285 +        newSection.appendChild(element);
  97.286 +      } else {
  97.287 +        var inserted = false;
  97.288 +        for (var i=0; i<newSection.childNodes.length; i++) {
  97.289 +          var entry = newSection.childNodes[i];
  97.290 +          if (entry.className == "movable") {
  97.291 +            newSection.insertBefore(element, entry);
  97.292 +            inserted = true;
  97.293 +            break;
  97.294 +          }
  97.295 +        }
  97.296 +        if (!inserted) newSection.appendChild(element);
  97.297 +      }
  97.298 +    }
  97.299    }
  97.300 -  sections = mainDiv.childNodes;
  97.301 +  // sections = mainDiv.childNodes;
  97.302    for (i=0; i<sections.length; i++) {
  97.303      var section = sections[i];
  97.304      if (
  97.305 @@ -161,10 +274,13 @@
  97.306        }
  97.307      }
  97.308    }
  97.309 -  setCategoryHeadings();
  97.310 +  voting_setCategoryHeadings();
  97.311 +}
  97.312 +function elementDropped(element, dropX, dropY) {
  97.313 +  voting_move(element, null, dropX, dropY);
  97.314  }
  97.315  window.addEventListener("load", function(event) {
  97.316 -  setCategoryHeadings();
  97.317 +  voting_setCategoryHeadings();
  97.318    var mainDiv = document.getElementById("voting");
  97.319    var form = document.getElementById("voting_form");
  97.320    var elements = document.getElementsByTagName("input");
  97.321 @@ -225,3 +341,9 @@
  97.322      }
  97.323    }
  97.324  }, false);
  97.325 +function voting_moveUp(element) {
  97.326 +  return voting_move(element, true);
  97.327 +}
  97.328 +function voting_moveDown(element) {
  97.329 +  return voting_move(element, false);
  97.330 +}
    98.1 --- a/static/style.css	Tue Feb 02 00:31:06 2010 +0100
    98.2 +++ b/static/style.css	Sat Feb 20 22:10:31 2010 +0100
    98.3 @@ -4,11 +4,16 @@
    98.4  
    98.5  body, th, td {
    98.6    font-family: sans-serif;
    98.7 +  font-size: 15px;
    98.8    font-size: 14px;
    98.9    padding: 0;
   98.10    margin: 0;
   98.11  }
   98.12  
   98.13 +.area_list {
   98.14 +  line-height: 170%;
   98.15 +}
   98.16 +
   98.17  body, a {
   98.18    color: #000;
   98.19  }
   98.20 @@ -54,7 +59,7 @@
   98.21  }
   98.22  
   98.23  a {
   98.24 -  vertical-align: middle;
   98.25 +  xvertical-align: middle;
   98.26  }
   98.27  
   98.28  h1 {
   98.29 @@ -104,6 +109,8 @@
   98.30    background-color: #444;
   98.31    color: #fff;
   98.32    font-size: 75%;
   98.33 +  line-height: 140%;
   98.34 +  margin-bottom: 1.8ex;
   98.35  }
   98.36  
   98.37  .topbar a {
   98.38 @@ -137,11 +144,16 @@
   98.39  }
   98.40  
   98.41  .searchbox {
   98.42 -  padding: 0.5ex 1em 0ex 1em;
   98.43 +  margin: 0;
   98.44 +  padding: 0.1ex 1em 0ex 1em;
   98.45    float: right;
   98.46    line-height: 250%;
   98.47  }
   98.48  
   98.49 +.searchbox form {
   98.50 +  float: left;
   98.51 +}
   98.52 +
   98.53  .searchbox div {
   98.54    display: inline;
   98.55  }
   98.56 @@ -162,7 +174,6 @@
   98.57  
   98.58  .searchbox input[type=submit] {
   98.59    font-size: 100%;
   98.60 -  width: 2.5em;
   98.61  }
   98.62  
   98.63  /*************************************************************************
   98.64 @@ -264,6 +275,7 @@
   98.65  .voting_requested {
   98.66    float: left;
   98.67    position: relative;
   98.68 +  z-index: 1;
   98.69  }
   98.70  
   98.71  .interest img,
   98.72 @@ -284,6 +296,11 @@
   98.73    border: 1px solid #b96;
   98.74  }
   98.75  
   98.76 +.interest .head_autoreject {
   98.77 +  background-color: #fdd;
   98.78 +  border: 1px solid #b77;
   98.79 +}
   98.80 +
   98.81  .slot_support .head_supporter {
   98.82    background-color: #dfc;
   98.83    border: 1px solid #8b8;
   98.84 @@ -299,6 +316,23 @@
   98.85    border: 1px solid #88b;
   98.86  }
   98.87  
   98.88 +.delegation .change_delegation {
   98.89 +  margin-bottom: 2ex;
   98.90 +}
   98.91 +
   98.92 +.delegation .change_delegation a {
   98.93 +  display: inline;
   98.94 +  float: none;
   98.95 +  padding: 1ex;
   98.96 +}
   98.97 +
   98.98 +.delegation .delegation_participation {
   98.99 +  margin-left: 20.5em;
  98.100 +  margin-top: 3ex;
  98.101 +  font-style: italic;
  98.102 +  font-size: 80%;
  98.103 +}
  98.104 +
  98.105  .voting_requested .head_active {
  98.106    background-color: #fdd;
  98.107    border: 1px solid #b77;
  98.108 @@ -322,7 +356,7 @@
  98.109    background-color: #fff;
  98.110    border: 1px solid #999;
  98.111    padding: 1em;
  98.112 -  width: 25em;
  98.113 +  width: 35em;
  98.114  }
  98.115  
  98.116  .vote_info .delegation_arrow {
  98.117 @@ -365,7 +399,6 @@
  98.118  
  98.119  
  98.120  .sub_title div {
  98.121 -  border-top: 1px solid #444;
  98.122    padding-top: 1ex;
  98.123    margin-top: 1ex;
  98.124    font-weight: bold;
  98.125 @@ -415,27 +448,81 @@
  98.126    padding: 1ex 1ex 1ex 1ex;
  98.127  }
  98.128  
  98.129 +.web10 .ui_tabs_accordeon_head {
  98.130 +  margin-bottom: 1ex;
  98.131 +}
  98.132 +
  98.133 +.web20 .ui_tabs_accordeon_head {
  98.134 +  font-size: 80%;
  98.135 +  font-weight: bold;
  98.136 +  display: block;
  98.137 +  background: #eee;
  98.138 +  border: 1px solid #bbb;
  98.139 +  color: #000;
  98.140 +  padding: 0.75ex;
  98.141 +  margin-top: 2ex;
  98.142 +  cursor: pointer;
  98.143 +}
  98.144 +
  98.145 +.web20 .ui_tabs_accordeon_head img {
  98.146 +  vertical-align: middle;
  98.147 +  margin-right: 0.5em;
  98.148 +}
  98.149 +
  98.150 +.web20 .ui_tabs_accordeon_head .bargraph {
  98.151 +  margin-right: 0.5em;
  98.152 +}
  98.153 +
  98.154 +.web20 .ui_tabs_accordeon_content {
  98.155 +  border: 1px solid #aaa;
  98.156 +  border-top: none;
  98.157 +  padding: 2ex 1em 2ex 1em;
  98.158 +  margin-bottom: 3ex;
  98.159 +}
  98.160 +
  98.161 +.web20 .issue_initiative_list .ui_tabs_accordeon_head {
  98.162 +  background-color: #e5e5ff;
  98.163 +}
  98.164 +
  98.165 +.web20 .issue_initiative_list .ui_tabs_accordeon_head,
  98.166 +.web20 .issue_initiative_list .ui_tabs_accordeon_content {
  98.167 +  border-color: #aad;
  98.168 +}
  98.169 +
  98.170 +.web20 .issue_initiative_list .ui_tabs_accordeon_content .ui_tabs_accordeon_content {
  98.171 +  border-color: #bbb;
  98.172 +  border-width: 1px;
  98.173 +}
  98.174 +
  98.175 +.web20 .issue_initiative_list .ui_tabs_accordeon_content .ui_tabs_accordeon_head {
  98.176 +  background-color: #eee;
  98.177 +  border: 1px solid #bbb;
  98.178 +}
  98.179 +
  98.180 +.web20 .issue_initiative_list .ui_tabs_accordeon_head a {
  98.181 +  font-size: 125%;
  98.182 +}
  98.183 +
  98.184 +
  98.185 +
  98.186  /*************************************************************************
  98.187 - * ui.filter
  98.188 - * ui.order
  98.189 + * ui.filters
  98.190   */
  98.191  
  98.192 -.ui_filter_head,
  98.193 -.ui_order_head {
  98.194 +.ui_filter_closed_head,
  98.195 +.ui_filter_head {
  98.196    color: #777;
  98.197    margin-top: 1ex;
  98.198    margin-bottom: 1.5ex;
  98.199    font-size: 75%;
  98.200  }
  98.201  
  98.202 -.ui_filter_head a,
  98.203 -.ui_order_head a {
  98.204 +.ui_filter_head a {
  98.205    color: #777;
  98.206    padding: 0.5ex;
  98.207  }
  98.208  
  98.209 -.ui_filter_head a.active,
  98.210 -.ui_order_head a.active {
  98.211 +.ui_filter_head a.active {
  98.212    color: #fff;
  98.213    background-color: #777;
  98.214    padding: 0.5ex;
  98.215 @@ -462,7 +549,11 @@
  98.216   */
  98.217  
  98.218  .bargraph {
  98.219 -  width: 101px;
  98.220 +  width: 103px;
  98.221 +}
  98.222 +
  98.223 +.bargraph50 {
  98.224 +  width: 52px;
  98.225  }
  98.226  
  98.227  .bargraph div {
  98.228 @@ -627,6 +718,7 @@
  98.229    background-color: #fff;
  98.230    left: 5em;
  98.231    top: 5ex;
  98.232 +z-index: 2;
  98.233  }
  98.234  
  98.235  .hidden_inline_form a {
  98.236 @@ -673,7 +765,8 @@
  98.237    padding: 0.3ex 0.5em 0.3ex 0.5em;
  98.238  }
  98.239  
  98.240 -.suggestion_my_opinion a {
  98.241 +.suggestion_my_opinion a,
  98.242 +.suggestion_my_opinion span {
  98.243    white-space: nowrap;
  98.244    padding-left: 0.2ex !important;
  98.245    padding-right: 0.2ex !important;
  98.246 @@ -737,7 +830,7 @@
  98.247  
  98.248  .member_thumb {
  98.249    text-decoration: none;
  98.250 -  width: 18em;
  98.251 +  width: 15.5em;
  98.252    height: 48px;
  98.253    display: block;
  98.254    float: left;
  98.255 @@ -781,13 +874,15 @@
  98.256  }
  98.257  
  98.258  .member_thumb .flags {
  98.259 -  float: right;
  98.260 +  text-align: right;
  98.261    font-size: 75%;
  98.262  }
  98.263  
  98.264 -.member_thumb .flags a{
  98.265 +.member_thumb .flags a,
  98.266 +.member_thumb .flags img {
  98.267    position: static;
  98.268    float: right;
  98.269 +  margin-left: 0.5em;
  98.270  }
  98.271  
  98.272  
  98.273 @@ -795,12 +890,14 @@
  98.274    float: right;
  98.275  }
  98.276  
  98.277 -.member_thumb.not_accepted {
  98.278 +.member_thumb.not_accepted,
  98.279 +.member_thumb.not_informed {
  98.280    opacity: 0.5;
  98.281  }
  98.282  
  98.283 +.member_statement,
  98.284  .draft_content,
  98.285 -.member_statement {
  98.286 +.suggestion_content {
  98.287    background-color: #eee;
  98.288    border: 1px solid #ccc;
  98.289    padding-left: 1ex;
  98.290 @@ -842,14 +939,27 @@
  98.291    margin-right: 0.7em;
  98.292  }
  98.293  
  98.294 +.admitted_info {
  98.295 +  background-color: #dfd;
  98.296 +  padding: 1ex;
  98.297 +  margin-bottom: 2ex;
  98.298 +}
  98.299 +
  98.300 +.not_admitted_info,
  98.301 +.revoked_info {
  98.302 +  background-color: #fdd;
  98.303 +  padding: 1ex;
  98.304 +  margin-bottom: 2ex;
  98.305 +}
  98.306 +
  98.307  .draft_updated_info,
  98.308  .voting_active_info,
  98.309 -.revoked_info,
  98.310  .initiator_invite_info,
  98.311  .motd {
  98.312    background-color: #fec;
  98.313 -  border: 2px solid #b96;
  98.314 +  border: 1px solid #b96;
  98.315    padding: 1ex;
  98.316 +  margin-bottom: 2ex;
  98.317  }
  98.318  
  98.319  .suggestion_fulfilled {
  98.320 @@ -934,6 +1044,17 @@
  98.321    background-color: #fec;
  98.322  }
  98.323  
  98.324 +.heading {
  98.325 +  font-size: 120%;
  98.326 +  font-weight: bold;
  98.327 +  margin-top: 2ex;
  98.328 +  margin-bottom: 1ex;
  98.329 +}
  98.330 +
  98.331 +.heading.first {
  98.332 +  margin-top: 0;
  98.333 +}
  98.334 +
  98.335  /*************************************************************************
  98.336   * Voting
  98.337   */
  98.338 @@ -974,16 +1095,20 @@
  98.339    border: 1px black solid;
  98.340    margin: 1ex;
  98.341    padding: 0.5ex;
  98.342 +}
  98.343 +#voting .voting_form_active .movable {
  98.344    cursor: pointer;
  98.345  }
  98.346 -#voting .clickable {
  98.347 +#voting .voting_form_active .clickable {
  98.348    cursor: auto;
  98.349  }
  98.350 -#voting a.clickable {
  98.351 +#voting .voting_form_active a.clickable {
  98.352    cursor: pointer;
  98.353  }
  98.354  
  98.355  #voting .grabber {
  98.356    vertical-align: middle;
  98.357    cursor: move;
  98.358 -}
  98.359 \ No newline at end of file
  98.360 +}
  98.361 +
  98.362 +

Impressum / About Us