liquid_feedback_frontend

changeset 0:3bfb2fcf7ab9 alpha1

Version alpha1
author bsw/jbe
date Wed Nov 18 12:00:00 2009 +0100 (2009-11-18)
parents
children dd0109e81922
files LICENSE Makefile app/main/_filter/20_session.lua app/main/_filter/21_auth.lua app/main/_filter_view/30_navigation.lua app/main/_filter_view/31_logout_button.lua app/main/_filter_view/32_searchbox.lua app/main/_layout/default.html app/main/_layout/rss.html app/main/_layout/system_error.html app/main/admin/_action/member_update.lua app/main/admin/area_list.lua app/main/admin/area_show.lua app/main/admin/index.lua app/main/admin/member_edit.lua app/main/admin/member_list.lua app/main/area/_action/update.lua app/main/area/_list.lua app/main/area/list.lua app/main/area/show.lua app/main/contact/_action/add_member.lua app/main/contact/_action/remove_member.lua app/main/contact/_list.lua app/main/contact/list.lua app/main/delegation/_action/update.lua app/main/delegation/_list.lua app/main/delegation/_show_box.lua app/main/delegation/new.lua app/main/draft/_action/add.lua app/main/draft/_list.lua app/main/draft/_show.lua app/main/draft/new.lua app/main/draft/show.lua app/main/index/_action/login.lua app/main/index/_action/logout.lua app/main/index/_action/set_lang.lua app/main/index/_action/update_password.lua app/main/index/about.lua app/main/index/change_password.lua app/main/index/index.lua app/main/index/login.lua app/main/index/search.lua app/main/initiative/_action/add_support.lua app/main/initiative/_action/create.lua app/main/initiative/_action/remove_support.lua app/main/initiative/_list.lua app/main/initiative/new.lua app/main/initiative/show.lua app/main/initiative/show.rss.lua app/main/interest/_action/update.lua app/main/interest/_show_box.lua app/main/issue/_list.lua app/main/issue/list.lua app/main/issue/show.lua app/main/issue/show.rss.lua app/main/member/_action/update.lua app/main/member/_action/update_avatar.lua app/main/member/_list.lua app/main/member/_show.lua app/main/member/avatar.lua app/main/member/edit.lua app/main/member/edit_avatar.lua app/main/member/list.lua app/main/member/show.lua app/main/membership/_action/update.lua app/main/membership/_show_box.lua app/main/opinion/_action/update.lua app/main/opinion/_list.lua app/main/suggestion/_action/add.lua app/main/suggestion/_list.lua app/main/suggestion/show.lua app/main/supporter/_show_box.lua config/default.lua config/development.lua config/testing.lua db/demodata.lua db/vote-test.sql doc/delegation.dia doc/delegation.png env/ui/bargraph.lua env/ui/field/image.lua env/ui/field/issue_state.lua env/ui/field/negative_votes.lua env/ui/field/positive_votes.lua env/ui/field/potential_initiative_weight.lua env/ui/field/potential_issue_weight.lua env/ui/field/rank.lua env/ui/field/satisfaction_informed.lua env/ui/field/satisfaction_total.lua env/ui/field/timestamp.lua env/ui/field/vote_later.lua env/ui/field/vote_now.lua env/ui/order.lua env/ui/tabs.lua env/ui/twitter.lua env/util/put_highlighted_string.lua locale/translations.de.lua locale/translations.en.lua model/area.lua model/contact.lua model/delegation.lua model/direct_voter.lua model/draft.lua model/initiative.lua model/initiator.lua model/interest.lua model/issue.lua model/member.lua model/member_count.lua model/membership.lua model/opinion.lua model/policy.lua model/session.lua model/suggestion.lua model/supporter.lua model/vote.lua static/icons/16/add.png static/icons/16/application_form.png static/icons/16/award_star_gold_2.png static/icons/16/award_star_silver_2.png static/icons/16/book_add.png static/icons/16/book_edit.png static/icons/16/cancel.png static/icons/16/cog.png static/icons/16/comment_add.png static/icons/16/cross.png static/icons/16/delete.png static/icons/16/folder.png static/icons/16/folder_add.png static/icons/16/group.png static/icons/16/house.png static/icons/16/information.png static/icons/16/key.png static/icons/16/package.png static/icons/16/page.png static/icons/16/page_add.png static/icons/16/script.png static/icons/16/script_add.png static/icons/16/stop.png static/icons/16/table_go.png static/icons/16/thumb_down_red.png static/icons/16/thumb_up_green.png static/icons/16/tick.png static/icons/16/user_comment.png static/icons/16/user_gray.png static/lang/de.png static/lang/en.png static/lang/es.png static/style.css static/trace.css tmp/.keep
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/LICENSE	Wed Nov 18 12:00:00 2009 +0100
     1.3 @@ -0,0 +1,27 @@
     1.4 +Copyright (c) 2009 Public Software Group e. V., Berlin, Germany
     1.5 +
     1.6 +Permission is hereby granted, free of charge, to any person obtaining a
     1.7 +copy of this software and associated documentation files (the "Software"),
     1.8 +to deal in the Software without restriction, including without limitation
     1.9 +the rights to use, copy, modify, merge, publish, distribute, sublicense,
    1.10 +and/or sell copies of the Software, and to permit persons to whom the
    1.11 +Software is furnished to do so, subject to the following conditions:
    1.12 +
    1.13 +The above copyright notice and this permission notice shall be included in
    1.14 +all copies or substantial portions of the Software.
    1.15 +
    1.16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    1.17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    1.18 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    1.19 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    1.20 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    1.21 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    1.22 +DEALINGS IN THE SOFTWARE.
    1.23 +
    1.24 +
    1.25 +3rd party license information:
    1.26 +
    1.27 +The icons used in Liquid Feedback (except national flags) are from Silk 
    1.28 +icon set 1.3 by Mark James. [ http://www.famfamfam.com/lab/icons/silk/ ]
    1.29 +His work is licensed under a Creative Commons Attribution 2.5 License.
    1.30 +[ http://creativecommons.org/licenses/by/2.5/ ]
    1.31 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile	Wed Nov 18 12:00:00 2009 +0100
     2.3 @@ -0,0 +1,14 @@
     2.4 +default:
     2.5 +
     2.6 +
     2.7 +db:
     2.8 +	create_db liquid_feedback
     2.9 +	psql liquid_feedback -f db/core.sql
    2.10 +
    2.11 +demo-db: db
    2.12 +	psql liquid_feedback -f db/demo.sql
    2.13 +
    2.14 +
    2.15 +translations-de:
    2.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
    2.17 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/app/main/_filter/20_session.lua	Wed Nov 18 12:00:00 2009 +0100
     3.3 @@ -0,0 +1,13 @@
     3.4 +if cgi.cookies.liquid_feedback_session then
     3.5 +  app.session = Session:by_ident(cgi.cookies.liquid_feedback_session)
     3.6 +end
     3.7 +if not app.session then
     3.8 +  app.session = Session:new()
     3.9 +  cgi.add_header('Set-Cookie: liquid_feedback_session=' .. app.session.ident .. '; path=/' )
    3.10 +end
    3.11 +
    3.12 +request.set_csrf_secret(app.session.additional_secret)
    3.13 +
    3.14 +locale.set{lang = app.session.lang or "en"}
    3.15 +
    3.16 +execute.inner()
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/app/main/_filter/21_auth.lua	Wed Nov 18 12:00:00 2009 +0100
     4.3 @@ -0,0 +1,33 @@
     4.4 +local auth_needed = not (
     4.5 +  request.get_module() == 'index'
     4.6 +  and (
     4.7 +    request.get_view() == 'login'
     4.8 +    or request.get_action() == 'login'
     4.9 +    or request.get_view() == "about"
    4.10 +  )
    4.11 +)
    4.12 +
    4.13 +-- if not app.session.user_id then
    4.14 +--   trace.debug("DEBUG: AUTHENTICATION BYPASS ENABLED")
    4.15 +--   app.session.user_id = 1
    4.16 +-- end
    4.17 +
    4.18 +if auth_needed and app.session.member == nil then
    4.19 +  trace.debug("Not authenticated yet.")
    4.20 +  request.redirect{ module = 'index', view = 'login' }
    4.21 +elseif auth_needed and app.session.member.locked then
    4.22 +  trace.debug("Member locked.")
    4.23 +  request.redirect{ module = 'index', view = 'login' }
    4.24 +else
    4.25 +  if auth_needed then
    4.26 +    trace.debug("Authentication accepted.")
    4.27 +  else
    4.28 +    trace.debug("No authentication needed.")
    4.29 +  end
    4.30 +
    4.31 +  --db:query("SELECT check_everything()")
    4.32 +
    4.33 +  execute.inner()
    4.34 +  trace.debug("End of authentication filter.")
    4.35 +end
    4.36 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/app/main/_filter_view/30_navigation.lua	Wed Nov 18 12:00:00 2009 +0100
     5.3 @@ -0,0 +1,94 @@
     5.4 +slot.put_into("app_name", config.app_title)
     5.5 +
     5.6 +-- display navigation only, if user is logged in
     5.7 +if app.session.member == nil then
     5.8 +  slot.select('navigation', function()
     5.9 +    ui.link{
    5.10 +      content = function()
    5.11 +        ui.image{ static = "icons/16/key.png" }
    5.12 +        slot.put('Login')
    5.13 +      end,
    5.14 +      module = 'index',
    5.15 +      view = 'login'
    5.16 +    }
    5.17 +    ui.link{
    5.18 +      content = function()
    5.19 +        ui.image{ static = "icons/16/information.png" }
    5.20 +        slot.put('About / Impressum')
    5.21 +      end,
    5.22 +      module = 'index',
    5.23 +      view = 'about'
    5.24 +    }
    5.25 +  end)
    5.26 +  execute.inner()
    5.27 +  return
    5.28 +end
    5.29 +
    5.30 +slot.select('navigation', function()
    5.31 +
    5.32 +    ui.link{
    5.33 +      content = function()
    5.34 +        ui.image{ static = "icons/16/house.png" }
    5.35 +        slot.put(_'Home')
    5.36 +      end,
    5.37 +      module = 'index',
    5.38 +      view = 'index'
    5.39 +    }
    5.40 +
    5.41 +    ui.link{
    5.42 +      content = function()
    5.43 +        ui.image{ static = "icons/16/package.png" }
    5.44 +        slot.put(_'Areas')
    5.45 +      end,
    5.46 +      module = 'area',
    5.47 +      view = 'list'
    5.48 +    }
    5.49 +
    5.50 +    ui.link{
    5.51 +      content = function()
    5.52 +        ui.image{ static = "icons/16/group.png" }
    5.53 +        slot.put(_'Members')
    5.54 +      end,
    5.55 +      module = 'member',
    5.56 +      view = 'list'
    5.57 +    }
    5.58 +
    5.59 +    ui.link{
    5.60 +      content = function()
    5.61 +        ui.image{ static = "icons/16/book_edit.png" }
    5.62 +        slot.put(_'Contacts')
    5.63 +      end,
    5.64 +      module = 'contact',
    5.65 +      view = 'list'
    5.66 +    }
    5.67 +
    5.68 +    ui.link{
    5.69 +      content = function()
    5.70 +        ui.image{ static = "icons/16/information.png" }
    5.71 +        slot.put(_'About')
    5.72 +      end,
    5.73 +      module = 'index',
    5.74 +      view = 'about'
    5.75 +    }
    5.76 +
    5.77 +  if app.session.member.admin then
    5.78 +
    5.79 +    slot.put(" ")
    5.80 +
    5.81 +    ui.link{
    5.82 +      attr = { class = { "admin_only" } },
    5.83 +      content = function()
    5.84 +        ui.image{ static = "icons/16/cog.png" }
    5.85 +        slot.put(_'Admin')
    5.86 +      end,
    5.87 +      module = 'admin',
    5.88 +      view = 'index'
    5.89 +    }
    5.90 +
    5.91 +  end
    5.92 +
    5.93 +end)
    5.94 +
    5.95 +execute.inner()
    5.96 +
    5.97 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/app/main/_filter_view/31_logout_button.lua	Wed Nov 18 12:00:00 2009 +0100
     6.3 @@ -0,0 +1,17 @@
     6.4 +if app.session.member == nil then
     6.5 +  execute.inner()
     6.6 +  return
     6.7 +end
     6.8 +
     6.9 +slot.select('logout_button', function()
    6.10 +  ui.link{
    6.11 +    content = function()
    6.12 +      ui.image{ static = "icons/16/stop.png" }
    6.13 +      slot.put(_'Logout')
    6.14 +    end,
    6.15 +    module = 'index',
    6.16 +    action = 'logout'
    6.17 +  }
    6.18 +end)
    6.19 +
    6.20 +execute.inner()
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/app/main/_filter_view/32_searchbox.lua	Wed Nov 18 12:00:00 2009 +0100
     7.3 @@ -0,0 +1,34 @@
     7.4 +if app.session.member == nil then
     7.5 +  execute.inner()
     7.6 +  return
     7.7 +end
     7.8 +
     7.9 +slot.select('searchbox', function()
    7.10 +
    7.11 +  ui.form{
    7.12 +    module = "index",
    7.13 +    view   = "search",
    7.14 +    method = "get",
    7.15 +    content = function()
    7.16 +
    7.17 +      ui.field.select{
    7.18 +        name = "search_for",
    7.19 +        foreign_records = {
    7.20 +          { key = "global", name = _"Search" },
    7.21 +          { key = "member", name = _"Search members" },
    7.22 +          { key = "initiative", name = _"Search initiatives" },
    7.23 +          { key = "issue", name = _"Search issues" },
    7.24 +        },
    7.25 +        foreign_id = "key",
    7.26 +        foreign_name = "name"
    7.27 +      }
    7.28 +
    7.29 +      ui.field.text{ name = "search", value = "" }
    7.30 +      ui.submit{ text = _"OK" }
    7.31 +
    7.32 +    end
    7.33 +  }
    7.34 +
    7.35 +end)
    7.36 +
    7.37 +execute.inner();
    7.38 \ No newline at end of file
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/app/main/_layout/default.html	Wed Nov 18 12:00:00 2009 +0100
     8.3 @@ -0,0 +1,68 @@
     8.4 +<html>
     8.5 +  <head>
     8.6 +    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
     8.7 +    <title><!-- WEBMCP SLOTNODIV app_name --></title>
     8.8 +    <link rel="stylesheet" type="text/css" media="screen" href="__BASEURL__/static/trace.css" />
     8.9 +    <link rel="stylesheet" type="text/css" media="screen" href="__BASEURL__/static/style.css" />
    8.10 +    <!-- WEBMCP SLOTNODIV html_head -->
    8.11 +  </head>
    8.12 +  <body>
    8.13 +    <div class="topbar">
    8.14 +      <div class="logout_button" id="logout_button">
    8.15 +        <!-- WEBMCP SLOT logout_button -->
    8.16 +      </div>
    8.17 +      <div class="searchbox" id="searchbox">
    8.18 +        <!-- WEBMCP SLOT searchbox -->
    8.19 +      </div>
    8.20 +      <div class="navigation" id="navigation">
    8.21 +        <!-- WEBMCP SLOT navigation -->
    8.22 +      </div>
    8.23 +    </div>
    8.24 +    <div class="infobox" id="infobox">
    8.25 +      <div class="interest" id="interest">
    8.26 +        <!-- WEBMCP SLOT interest -->
    8.27 +      </div>
    8.28 +      <div class="support" id="support">
    8.29 +        <!-- WEBMCP SLOT support -->
    8.30 +      </div>
    8.31 +      <div class="delegation" id="delegation">
    8.32 +        <!-- WEBMCP SLOT delegation -->
    8.33 +      </div>
    8.34 +    </div>
    8.35 +    <div class="title_bar">
    8.36 +      <div class="path" id="path">
    8.37 +        <!-- WEBMCP SLOT path -->
    8.38 +      </div>
    8.39 +      <div class="title" id="title">
    8.40 +        <!-- WEBMCP SLOT title -->
    8.41 +      </div>
    8.42 +      <div class="actions" id="actions">
    8.43 +        <!-- WEBMCP SLOT actions -->
    8.44 +      </div>
    8.45 +    </div>
    8.46 +    <div class="main" id="default">
    8.47 +      <!-- WEBMCP SLOT default -->
    8.48 +    </div>
    8.49 +    <div class="layout_trace" id="layout_trace" style="xdisplay: none">
    8.50 +      <div id="trace_show" onclick="document.getElementById('trace_content').style.display='block';this.style.display='none';">TRACE</div>
    8.51 +        <div id="trace_content" style="display: none;">
    8.52 +          <!-- WEBMCP SLOT trace -->
    8.53 +          <div class="trace_close" onclick="document.getElementById('trace_show').style.display='block';document.getElementById('trace_content').style.display='none';">
    8.54 +            close
    8.55 +          </div>
    8.56 +        </div>
    8.57 +      </div>
    8.58 +    </div>
    8.59 +    <div class="layout_notice" id="layout_notice" onclick="document.getElementById('layout_notice').style.display='none';">
    8.60 +      <!-- WEBMCP SLOT notice -->
    8.61 +    </div>
    8.62 +    <div class="layout_warning" id="layout_warning" onclick="document.getElementById('layout_warning').style.display='none';">
    8.63 +      <!-- WEBMCP SLOT warning -->
    8.64 +    </div>
    8.65 +    <div class="layout_error" id="layout_error" onclick="document.getElementById('layout_error').style.display='none';">
    8.66 +      <!-- WEBMCP SLOT error -->
    8.67 +    </div>
    8.68 +  </body>
    8.69 +  <script>
    8.70 +  </script>
    8.71 +</html>
    8.72 \ No newline at end of file
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/app/main/_layout/rss.html	Wed Nov 18 12:00:00 2009 +0100
     9.3 @@ -0,0 +1,7 @@
     9.4 +<?xml version="1.0" encoding="utf-8"?>
     9.5 +
     9.6 +<rss version="2.0">
     9.7 +  <channel>
     9.8 +    <!-- WEBMCP SLOTNODIV default -->
     9.9 +  </channel>
    9.10 +</rss>
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/app/main/_layout/system_error.html	Wed Nov 18 12:00:00 2009 +0100
    10.3 @@ -0,0 +1,41 @@
    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 +    <link rel="stylesheet" type="text/css" media="screen" href="__BASEURL__/static/trace.css" />
    10.9 +    <link rel="stylesheet" type="text/css" media="screen" href="__BASEURL__/static/style.css" />
   10.10 +  </head>
   10.11 +  <body class="system_error">
   10.12 +    <div class="layout_content">
   10.13 +      <div class="layout_title">
   10.14 +        <div class="title">
   10.15 +          <br />
   10.16 +          <br />
   10.17 +          System message
   10.18 +        </div>
   10.19 +      </div>
   10.20 +      <br style="clear: left;">
   10.21 +      <div class="layout_actions">
   10.22 +        &nbsp;
   10.23 +      </div>
   10.24 +      <div class="layout_main">
   10.25 +        <div class="main">
   10.26 +          <tt><!-- WEBMCP SLOT system_error --></tt>
   10.27 +          <br />
   10.28 +          <br />
   10.29 +          <br />
   10.30 +          <br />
   10.31 +          <button onclick="window.location.reload()">Retry request</button>
   10.32 +          <a href="__BASEURL__">index</a>
   10.33 +        </div>
   10.34 +      </div>
   10.35 +    </div>
   10.36 +      <div class="layout_trace" id="layout_trace" style="xdisplay: none">
   10.37 +	    <div id="trace_show" onclick="document.getElementById('trace_content').style.display='block';this.style.display='none';" style="display: none;">TRACE</div>
   10.38 +        <div id="trace_content">
   10.39 +	        <!-- WEBMCP SLOT trace -->
   10.40 +	        <div class="trace_close" onclick="document.getElementById('trace_show').style.display='block';document.getElementById('trace_content').style.display='none';">close</div>
   10.41 +	    </div>
   10.42 +      </div>
   10.43 +  </body>
   10.44 +</html>
   10.45 \ No newline at end of file
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/app/main/admin/_action/member_update.lua	Wed Nov 18 12:00:00 2009 +0100
    11.3 @@ -0,0 +1,37 @@
    11.4 +if not app.session.member.admin then
    11.5 +  error('access denied')
    11.6 +end
    11.7 +
    11.8 +local id = param.get_id()
    11.9 +
   11.10 +local member
   11.11 +
   11.12 +if id then
   11.13 +  member = Member:new_selector():add_where{"id = ?", id}:single_object_mode():exec()
   11.14 +else
   11.15 +  member = Member:new()
   11.16 +end
   11.17 +
   11.18 +param.update(member, "login", "admin", "name", "ident_number", "active")
   11.19 +
   11.20 +local password = param.get("password")
   11.21 +if password == "********" or #password == 0 then
   11.22 +  password = nil
   11.23 +end
   11.24 +
   11.25 +if password then
   11.26 +  member:set_password(password)
   11.27 +end
   11.28 +
   11.29 +local err = member:try_save()
   11.30 +
   11.31 +if err then
   11.32 +  slot.put_into("error", (_("Error while updating member, database reported:<br /><br /> (#{errormessage})"):gsub("#{errormessage}", tostring(err.message))))
   11.33 +  return false
   11.34 +else
   11.35 +  if id then
   11.36 +    slot.put_into("notice", _"Member successfully updated")
   11.37 +  else
   11.38 +    slot.put_into("notice", _"Member successfully registered")
   11.39 +  end
   11.40 +end
   11.41 \ No newline at end of file
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/app/main/admin/area_list.lua	Wed Nov 18 12:00:00 2009 +0100
    12.3 @@ -0,0 +1,62 @@
    12.4 +local show_not_in_use = param.get("show_not_in_use", atom.boolean)
    12.5 +
    12.6 +local selector = Area:new_selector()
    12.7 +if show_not_in_use then
    12.8 +  selector:add_where("NOT active")
    12.9 +else
   12.10 +  selector:add_where("active")
   12.11 +end
   12.12 +
   12.13 +local areas = selector:exec()
   12.14 +
   12.15 +slot.put_into("title", _"Area list")
   12.16 +
   12.17 +if app.session.member.admin then
   12.18 +  slot.select("actions", function()
   12.19 +    if show_not_in_use then
   12.20 +      ui.link{
   12.21 +        attr = { class = { "admin_only" } },
   12.22 +        text = _"Show areas in use",
   12.23 +        module = "admin",
   12.24 +        view = "area_list"
   12.25 +      }
   12.26 +    else
   12.27 +      ui.link{
   12.28 +        attr = { class = { "admin_only" } },
   12.29 +        text = _"Create new area",
   12.30 +        module = "admin",
   12.31 +        view = "area_show"
   12.32 +      }
   12.33 +      ui.link{
   12.34 +        attr = { class = { "admin_only" } },
   12.35 +        text = _"Show areas not in use",
   12.36 +        module = "admin",
   12.37 +        view = "area_list",
   12.38 +        params = { show_not_in_use = true }
   12.39 +      }
   12.40 +    end
   12.41 +  end)
   12.42 +end
   12.43 +
   12.44 +ui.list{
   12.45 +  records = areas,
   12.46 +  columns = {
   12.47 +    {
   12.48 +      label = _"Area",
   12.49 +      name = "name"
   12.50 +    },
   12.51 +    {
   12.52 +      content = function(record)
   12.53 +        if app.session.member.admin then
   12.54 +          ui.link{
   12.55 +            attr = { class = { "action admin_only" } },
   12.56 +            text = _"Edit",
   12.57 +            module = "admin",
   12.58 +            view = "area_show",
   12.59 +            id = record.id
   12.60 +          }
   12.61 +        end
   12.62 +      end
   12.63 +    }
   12.64 +  }
   12.65 +}
   12.66 \ No newline at end of file
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/app/main/admin/area_show.lua	Wed Nov 18 12:00:00 2009 +0100
    13.3 @@ -0,0 +1,29 @@
    13.4 +local id = param.get_id()
    13.5 +
    13.6 +local area
    13.7 +if id then
    13.8 +  area = Area:new_selector():add_where{ "id = ?", id }:single_object_mode():exec()
    13.9 +end
   13.10 +
   13.11 +slot.put_into("title", _"Create new area")
   13.12 +
   13.13 +ui.form{
   13.14 +  attr = { class = "vertical" },
   13.15 +  record = area,
   13.16 +  module = "area",
   13.17 +  action = "update",
   13.18 +  routing = {
   13.19 +    default = {
   13.20 +      mode = "redirect",
   13.21 +      module = "admin",
   13.22 +      view = "area_list"
   13.23 +    }
   13.24 +  },
   13.25 +  id = area and area.id or nil,
   13.26 +  content = function()
   13.27 +    ui.field.text{    label = _"Name",        name = "name" }
   13.28 +    ui.field.boolean{ label = _"Active?",     name = "active" }
   13.29 +    ui.field.text{    label = _"Description", name = "description", multiline = true }
   13.30 +    ui.submit{ text = _"Save" }
   13.31 +  end
   13.32 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/app/main/admin/index.lua	Wed Nov 18 12:00:00 2009 +0100
    14.3 @@ -0,0 +1,25 @@
    14.4 +slot.put_into("title", _"Admin menu")
    14.5 +
    14.6 +ui.link{
    14.7 +  text = "Members",
    14.8 +  module = "admin",
    14.9 +  view = "member_list",
   14.10 +}
   14.11 +
   14.12 +slot.put("<br />")
   14.13 +
   14.14 +ui.link{
   14.15 +  text = "Areas",
   14.16 +  module = "admin",
   14.17 +  view = "area_list",
   14.18 +}
   14.19 +
   14.20 +slot.put("<br />")
   14.21 +
   14.22 +
   14.23 +ui.link{
   14.24 +  text = "Policies",
   14.25 +  module = "admin",
   14.26 +  view = "policy_list",
   14.27 +}
   14.28 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/app/main/admin/member_edit.lua	Wed Nov 18 12:00:00 2009 +0100
    15.3 @@ -0,0 +1,34 @@
    15.4 +local id = param.get_id()
    15.5 +
    15.6 +local member
    15.7 +if id then
    15.8 +  member = Member:new_selector():add_where{"id = ?", id}:optional_object_mode():exec()
    15.9 +  slot.put_into("title", encode.html(_("Member: '#{login}' (#{name})", { login = member.login, name = member.name })))
   15.10 +else
   15.11 +  slot.put_into("title", encode.html(_"Register new member"))
   15.12 +end
   15.13 +
   15.14 +ui.form{
   15.15 +  attr = { class = "vertical" },
   15.16 +  module = "admin",
   15.17 +  action = "member_update",
   15.18 +  id = member and member.id,
   15.19 +  record = member,
   15.20 +  readonly = not app.session.member.admin,
   15.21 +  routing = {
   15.22 +    default = {
   15.23 +      mode = "redirect",
   15.24 +      modules = "admin",
   15.25 +      view = "member_list"
   15.26 +    }
   15.27 +  },
   15.28 +  content = function()
   15.29 +    ui.field.text{     label = _"Login",        name = "login" }
   15.30 +    ui.field.text{     label = _"Name",         name = "name" }
   15.31 +    ui.field.password{ label = _"Password",     name = "password", value = (member and member.password) and "********" or "" }
   15.32 +    ui.field.boolean{  label = _"Admin?",       name = "admin" }
   15.33 +    ui.field.boolean{  label = _"Active?",      name = "active" }
   15.34 +    ui.field.text{     label = _"Ident number", name = "ident_number" }
   15.35 +    ui.submit{         text  = _"Save" }
   15.36 +  end
   15.37 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/app/main/admin/member_list.lua	Wed Nov 18 12:00:00 2009 +0100
    16.3 @@ -0,0 +1,92 @@
    16.4 +slot.put_into("title", _"Member list")
    16.5 +
    16.6 +slot.select("actions", function()
    16.7 +  ui.link{
    16.8 +    attr = { class = { "admin_only" } },
    16.9 +    text = _"Register new member",
   16.10 +    module = "admin",
   16.11 +    view = "member_edit"
   16.12 +  }
   16.13 +  if param.get("show_locked") then
   16.14 +    ui.link{
   16.15 +      attr = { class = { "admin_only" } },
   16.16 +      text = _"Show active members",
   16.17 +      module = "admin",
   16.18 +      view = "member_list"
   16.19 +    }
   16.20 +  else
   16.21 +    ui.link{
   16.22 +      attr = { class = { "admin_only" } },
   16.23 +      text = _"Show locked members",
   16.24 +      module = "admin",
   16.25 +      view = "member_list",
   16.26 +      params = { show_locked = true }
   16.27 +    }
   16.28 +  end
   16.29 +end)
   16.30 +
   16.31 +local members_selector
   16.32 +
   16.33 +if param.get("show_locked", atom.boolean) then
   16.34 +  members_selector = Member:new_selector()
   16.35 +    :add_where("not active")
   16.36 +    :add_order_by("login")
   16.37 +else
   16.38 +  members_selector = Member:new_selector()
   16.39 +    :add_where("active")
   16.40 +    :add_order_by("login")
   16.41 +end
   16.42 +
   16.43 +ui.paginate{
   16.44 +  selector = members_selector,
   16.45 +  content = function() 
   16.46 +    ui.list{
   16.47 +      records = members_selector:exec(),
   16.48 +      columns = {
   16.49 +        {
   16.50 +          field_attr = { style = "text-align: right;" },
   16.51 +          label = _"Id",
   16.52 +          name = "id"
   16.53 +        },
   16.54 +        {
   16.55 +          label = _"Login",
   16.56 +          name = "login"
   16.57 +        },
   16.58 +        {
   16.59 +          label = _"Name",
   16.60 +          content = function(record)
   16.61 +            util.put_highlighted_string(record.name)
   16.62 +          end
   16.63 +        },
   16.64 +        {
   16.65 +          label = _"Ident number",
   16.66 +          name = "ident_number"
   16.67 +        },
   16.68 +        {
   16.69 +          label = _"Admin?",
   16.70 +          name = "admin"
   16.71 +        },
   16.72 +        {
   16.73 +          content = function(record)
   16.74 +            if app.session.member.admin and not record.active then
   16.75 +              ui.field.text{ value = "locked" }
   16.76 +            end
   16.77 +          end
   16.78 +        },
   16.79 +        {
   16.80 +          content = function(record)
   16.81 +            if app.session.member.admin then
   16.82 +              ui.link{
   16.83 +                attr = { class = "action admin_only" },
   16.84 +                text = _"Edit",
   16.85 +                module = "admin",
   16.86 +                view = "member_edit",
   16.87 +                id = record.id
   16.88 +              }
   16.89 +            end
   16.90 +          end
   16.91 +        }
   16.92 +      }
   16.93 +    }
   16.94 +  end
   16.95 +}
   16.96 \ No newline at end of file
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/app/main/area/_action/update.lua	Wed Nov 18 12:00:00 2009 +0100
    17.3 @@ -0,0 +1,15 @@
    17.4 +local id = param.get_id()
    17.5 +
    17.6 +local area
    17.7 +if id then
    17.8 +  area = Area:new_selector():add_where{ "id = ?", id }:single_object_mode():exec()
    17.9 +else
   17.10 +  area = Area:new()
   17.11 +end
   17.12 +
   17.13 +
   17.14 +param.update(area, "name", "description", "active")
   17.15 +
   17.16 +area:save()
   17.17 +
   17.18 +slot.put_into("notice", _"Area successfully updated")
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/app/main/area/_list.lua	Wed Nov 18 12:00:00 2009 +0100
    18.3 @@ -0,0 +1,61 @@
    18.4 +local areas_selector = param.get("areas_selector", "table")
    18.5 +
    18.6 +ui.order{
    18.7 +  name = name,
    18.8 +  selector = areas_selector,
    18.9 +  options = {
   18.10 +    {
   18.11 +      name = "member_weight",
   18.12 +      label = _"Population",
   18.13 +      order_by = "area.member_weight DESC"
   18.14 +    },
   18.15 +    {
   18.16 +      name = "direct_member_count",
   18.17 +      label = _"Direct member count",
   18.18 +      order_by = "area.direct_member_count DESC"
   18.19 +    },
   18.20 +    {
   18.21 +      name = "az",
   18.22 +      label = _"A-Z",
   18.23 +      order_by = "area.name"
   18.24 +    },
   18.25 +    {
   18.26 +      name = "za",
   18.27 +      label = _"Z-A",
   18.28 +      order_by = "area.name DESC"
   18.29 +    }
   18.30 +  },
   18.31 +  content = function()
   18.32 +    ui.list{
   18.33 +      records = areas_selector:exec(),
   18.34 +      columns = {
   18.35 +        {
   18.36 +          content = function(record)
   18.37 +            if record.member_weight and record.direct_member_count then
   18.38 +              local max_value = MemberCount:get()
   18.39 +              ui.bargraph{
   18.40 +                max_value = max_value,
   18.41 +                width = 100,
   18.42 +                bars = {
   18.43 +                  { color = "#444", value = record.direct_member_count },
   18.44 +                  { color = "#777", value = record.member_weight - record.direct_member_count },
   18.45 +                  { color = "#ddd", value = max_value - record.member_weight },
   18.46 +                }
   18.47 +              }
   18.48 +            end
   18.49 +          end
   18.50 +        },
   18.51 +        {
   18.52 +          content = function(record)
   18.53 +            ui.link{
   18.54 +              text = record.name,
   18.55 +              module = "area",
   18.56 +              view = "show",
   18.57 +              id = record.id
   18.58 +            }
   18.59 +          end
   18.60 +        }
   18.61 +      }
   18.62 +    }
   18.63 +  end
   18.64 +}
   18.65 \ No newline at end of file
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/app/main/area/list.lua	Wed Nov 18 12:00:00 2009 +0100
    19.3 @@ -0,0 +1,14 @@
    19.4 +slot.put_into("title", _'Area list')
    19.5 +
    19.6 +local areas_selector = Area:new_selector():add_where("active")
    19.7 +
    19.8 +execute.view{
    19.9 +  module = "area",
   19.10 +  view = "_list",
   19.11 +  params = { areas_selector = areas_selector }
   19.12 +}
   19.13 +
   19.14 +execute.view{
   19.15 +  module = "delegation",
   19.16 +  view = "_show_box"
   19.17 +}
   19.18 \ No newline at end of file
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/app/main/area/show.lua	Wed Nov 18 12:00:00 2009 +0100
    20.3 @@ -0,0 +1,114 @@
    20.4 +local area = Area:new_selector():add_where{ "id = ?", param.get_id() }:single_object_mode():exec()
    20.5 +
    20.6 +slot.put_into("title", encode.html(_"Area '#{name}'":gsub("#{name}", area.name)))
    20.7 +
    20.8 +ui.container{
    20.9 +  attr = { class = "vertical"},
   20.10 +  content = function()
   20.11 +    ui.field.text{ value = area.description }
   20.12 +  end
   20.13 +}
   20.14 +
   20.15 +
   20.16 +slot.select("actions", function()
   20.17 +  ui.link{
   20.18 +    content = function()
   20.19 +      ui.image{ static = "icons/16/folder_add.png" }
   20.20 +      slot.put(_"Create new issue")
   20.21 +    end,
   20.22 +    module = "initiative",
   20.23 +    view = "new",
   20.24 +    params = { area_id = area.id }
   20.25 +  }
   20.26 +  ui.link{
   20.27 +    content = function()
   20.28 +      ui.image{ static = "icons/16/table_go.png" }
   20.29 +      slot.put(_"Delegate")
   20.30 +    end,
   20.31 +    module = "delegation",
   20.32 +    view = "new",
   20.33 +    params = { area_id = area.id }
   20.34 +  }
   20.35 +end)
   20.36 +
   20.37 +execute.view{
   20.38 +  module = "membership",
   20.39 +  view = "_show_box",
   20.40 +  params = { area = area }
   20.41 +}
   20.42 +
   20.43 +execute.view{
   20.44 +  module = "delegation",
   20.45 +  view = "_show_box",
   20.46 +  params = { area_id = area.id }
   20.47 +}
   20.48 +
   20.49 +ui.tabs{
   20.50 +  {
   20.51 +    name = "new",
   20.52 +    label = _"New",
   20.53 +    content = function()
   20.54 +      execute.view{
   20.55 +        module = "issue",
   20.56 +        view = "_list",
   20.57 +        params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.accepted ISNULL AND issue.closed ISNULL"), for_area_list = true }
   20.58 +      }
   20.59 +    end
   20.60 +  },
   20.61 +  {
   20.62 +    name = "accepted",
   20.63 +    label = _"In discussion",
   20.64 +    content = function()
   20.65 +      execute.view{
   20.66 +        module = "issue",
   20.67 +        view = "_list",
   20.68 +        params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL"), for_area_list = true }
   20.69 +      }
   20.70 +    end
   20.71 +  },
   20.72 +  {
   20.73 +    name = "half_frozen",
   20.74 +    label = _"Frozen",
   20.75 +    content = function()
   20.76 +      execute.view{
   20.77 +        module = "issue",
   20.78 +        view = "_list",
   20.79 +        params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.half_frozen NOTNULL AND issue.closed ISNULL"), for_area_list = true }
   20.80 +      }
   20.81 +    end
   20.82 +  },
   20.83 +  {
   20.84 +    name = "frozen",
   20.85 +    label = _"Voting",
   20.86 +    content = function()
   20.87 +      execute.view{
   20.88 +        module = "issue",
   20.89 +        view = "_list",
   20.90 +        params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL"), for_area_list = true }
   20.91 +      }
   20.92 +    end
   20.93 +  },
   20.94 +  {
   20.95 +    name = "finished",
   20.96 +    label = _"Finished",
   20.97 +    content = function()
   20.98 +      execute.view{
   20.99 +        module = "issue",
  20.100 +        view = "_list",
  20.101 +        params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.closed NOTNULL AND ranks_available"), for_area_list = true }
  20.102 +      }
  20.103 +    end
  20.104 +  },
  20.105 +  {
  20.106 +    name = "cancelled",
  20.107 +    label = _"Cancelled",
  20.108 +    content = function()
  20.109 +      execute.view{
  20.110 +        module = "issue",
  20.111 +        view = "_list",
  20.112 +        params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.closed NOTNULL AND NOT ranks_available"), for_area_list = true }
  20.113 +      }
  20.114 +    end
  20.115 +  },
  20.116 +}
  20.117 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/app/main/contact/_action/add_member.lua	Wed Nov 18 12:00:00 2009 +0100
    21.3 @@ -0,0 +1,27 @@
    21.4 +local member = app.session.member
    21.5 +local other_member = Member:by_id(param.get_id())
    21.6 +
    21.7 +local public = param.get("public", atom.boolean)
    21.8 +
    21.9 +local contact = Contact:by_pk(member.id, other_member.id)
   21.10 +
   21.11 +if public == nil and contact then
   21.12 +  slot.put_into("error", _"Member is already saved in your contacts!")
   21.13 +  return false
   21.14 +end
   21.15 +
   21.16 +if contact then
   21.17 +  contact:destroy()
   21.18 +end
   21.19 +
   21.20 +contact = Contact:new()
   21.21 +contact.member_id = member.id
   21.22 +contact.other_member_id = other_member.id
   21.23 +contact.public = public or false
   21.24 +contact:save()
   21.25 +
   21.26 +if public then
   21.27 +  slot.put_into("notice", _"Member has been saved as public contact")
   21.28 +else
   21.29 +  slot.put_into("notice", _"Member has been saved as private contact")
   21.30 +end
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/app/main/contact/_action/remove_member.lua	Wed Nov 18 12:00:00 2009 +0100
    22.3 @@ -0,0 +1,7 @@
    22.4 +local member = app.session.member
    22.5 +local other_member = Member:by_id(param.get_id())
    22.6 +
    22.7 +local contact = Contact:by_pk(member.id, other_member.id)
    22.8 +contact:destroy()
    22.9 +
   22.10 +slot.put_into("notice", _"Member has been removed from your contacts")
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/app/main/contact/_list.lua	Wed Nov 18 12:00:00 2009 +0100
    23.3 @@ -0,0 +1,132 @@
    23.4 +
    23.5 +local contacts_selector = Contact:new_selector()
    23.6 +  :add_where{ "member_id = ?", app.session.member.id }
    23.7 +  :join("member", nil, "member.id = contact.other_member_id")
    23.8 +  :add_order_by("member.login")
    23.9 +
   23.10 +ui.paginate{
   23.11 +  selector = contacts_selector,
   23.12 +  content = function()
   23.13 +    local contacts = contacts_selector:exec()
   23.14 +    if #contacts == 0 then
   23.15 +      ui.field.text{ value = _"You didn't saved any member as contact yet." }
   23.16 +    else
   23.17 +      ui.list{
   23.18 +        records = contacts,
   23.19 +        columns = {
   23.20 +          {
   23.21 +            label = _"Login",
   23.22 +            content = function(record)
   23.23 +              ui.link{
   23.24 +                text = record.other_member.login,
   23.25 +                module = "member",
   23.26 +                view = "show",
   23.27 +                id = record.other_member_id
   23.28 +              }
   23.29 +            end
   23.30 +          },
   23.31 +          {
   23.32 +            label = _"Name",
   23.33 +            content = function(record)
   23.34 +              ui.link{
   23.35 +                text = record.other_member.name,
   23.36 +                module = "member",
   23.37 +                view = "show",
   23.38 +                id = record.other_member_id
   23.39 +              }
   23.40 +            end
   23.41 +          },
   23.42 +          {
   23.43 +            label = _"Published",
   23.44 +            content = function(record)
   23.45 +              ui.field.boolean{ value = record.public }
   23.46 +            end
   23.47 +          },
   23.48 +          {
   23.49 +            content = function(record)
   23.50 +              if record.public then
   23.51 +                ui.link{
   23.52 +                  attr = { class = "action" },
   23.53 +                  text = _"Hide",
   23.54 +                  module = "contact",
   23.55 +                  action = "add_member",
   23.56 +                  id = record.other_member_id,
   23.57 +                  params = { public = false },
   23.58 +                  routing = {
   23.59 +                    default = {
   23.60 +                      mode = "redirect",
   23.61 +                      module = request.get_module(),
   23.62 +                      view = request.get_view(),
   23.63 +                      id = param.get_id_cgi(),
   23.64 +                      params = param.get_all_cgi()
   23.65 +                    }
   23.66 +                  }
   23.67 +                }
   23.68 +              else
   23.69 +                ui.link{
   23.70 +                  attr = { class = "action" },
   23.71 +                  text = _"Publish",
   23.72 +                  module = "contact",
   23.73 +                  action = "add_member",
   23.74 +                  id = record.other_member_id,
   23.75 +                  params = { public = true },
   23.76 +                  routing = {
   23.77 +                    default = {
   23.78 +                      mode = "redirect",
   23.79 +                      module = request.get_module(),
   23.80 +                      view = request.get_view(),
   23.81 +                      id = param.get_id_cgi(),
   23.82 +                      params = param.get_all_cgi()
   23.83 +                    }
   23.84 +                  }
   23.85 +                }
   23.86 +              end
   23.87 +            end
   23.88 +          },
   23.89 +          {
   23.90 +            content = function(record)
   23.91 +              ui.link{
   23.92 +                attr = { class = "action" },
   23.93 +                text = _"Remove",
   23.94 +                module = "contact",
   23.95 +                action = "remove_member",
   23.96 +                id = record.other_member_id,
   23.97 +                routing = {
   23.98 +                  default = {
   23.99 +                    mode = "redirect",
  23.100 +                    module = request.get_module(),
  23.101 +                    view = request.get_view(),
  23.102 +                    id = param.get_id_cgi(),
  23.103 +                    params = param.get_all_cgi()
  23.104 +                  }
  23.105 +                }
  23.106 +              }
  23.107 +            end
  23.108 +          },
  23.109 +          {
  23.110 +            content = function(record)
  23.111 +              ui.link{
  23.112 +                attr = { class = "action" },
  23.113 +                text = _"Global delegation",
  23.114 +                module = "delegation",
  23.115 +                action = "update",
  23.116 +                params = { 
  23.117 +                  trustee_id = record.other_member_id,
  23.118 +                },
  23.119 +                routing = {
  23.120 +                  default = {
  23.121 +                    mode = "redirect",
  23.122 +                    module = request.get_module(),
  23.123 +                    view = request.get_view(),
  23.124 +                    id = param.get_id_cgi(),
  23.125 +                    params = param.get_all_cgi()
  23.126 +                  }
  23.127 +                }
  23.128 +              }
  23.129 +            end
  23.130 +          }
  23.131 +        }
  23.132 +      }
  23.133 +    end
  23.134 +  end
  23.135 +}
  23.136 \ No newline at end of file
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/app/main/contact/list.lua	Wed Nov 18 12:00:00 2009 +0100
    24.3 @@ -0,0 +1,7 @@
    24.4 +slot.put_into("title", _"Contacts")
    24.5 +
    24.6 +execute.view{
    24.7 +  module = "contact",
    24.8 +  view = "_list",
    24.9 +  params = { contacts_selector = app.session.member:get_reference_selector("contacts") }
   24.10 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/app/main/delegation/_action/update.lua	Wed Nov 18 12:00:00 2009 +0100
    25.3 @@ -0,0 +1,53 @@
    25.4 +local truster_id = app.session.member.id
    25.5 +
    25.6 +local trustee_id = param.get("trustee_id", atom.integer)
    25.7 +
    25.8 +local area_id = param.get("area_id", atom.integer)
    25.9 +
   25.10 +local issue_id = param.get("issue_id", atom.integer)
   25.11 +
   25.12 +if issue_id then 
   25.13 +  area_id = nil
   25.14 +end
   25.15 +
   25.16 +local delegation = Delegation:by_pk(truster_id, area_id, issue_id)
   25.17 +
   25.18 +if param.get("delete") then
   25.19 +
   25.20 +  if delegation then
   25.21 +  
   25.22 +    delegation:destroy()
   25.23 +  
   25.24 +    if issue_id then
   25.25 +      slot.put_into("notice", _"Your delegation for this issue has been deleted.")
   25.26 +    elseif area_id then
   25.27 +      slot.put_into("notice", _"Your delegation for this area has been deleted.")
   25.28 +    else
   25.29 +      slot.put_into("notice", _"Your global delegation has been deleted.")
   25.30 +    end
   25.31 +
   25.32 +  end
   25.33 +  
   25.34 +else
   25.35 +
   25.36 +  if not delegation then
   25.37 +    delegation = Delegation:new()
   25.38 +    delegation.truster_id = truster_id
   25.39 +    delegation.area_id    = area_id
   25.40 +    delegation.issue_id   = issue_id
   25.41 +  end
   25.42 +
   25.43 +  delegation.trustee_id = trustee_id
   25.44 +
   25.45 +  delegation:save()
   25.46 +
   25.47 +  if issue_id then
   25.48 +    slot.put_into("notice", _"Your delegation for this issue has been updated.")
   25.49 +  elseif area_id then
   25.50 +    slot.put_into("notice", _"Your delegation for this area has been updated.")
   25.51 +  else
   25.52 +    slot.put_into("notice", _"Your global delegation has been updated.")
   25.53 +  end
   25.54 +
   25.55 +end
   25.56 +
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/app/main/delegation/_list.lua	Wed Nov 18 12:00:00 2009 +0100
    26.3 @@ -0,0 +1,50 @@
    26.4 +local selector = param.get("selector", "table")
    26.5 +
    26.6 +ui.paginate{
    26.7 +  selector = selector,
    26.8 +  content = function()
    26.9 +    ui.list{
   26.10 +      records = selector:exec(),
   26.11 +      columns = {
   26.12 +        {
   26.13 +          label = _"Truster",
   26.14 +          content = function(record)
   26.15 +            ui.link{
   26.16 +              content = record.truster.name,
   26.17 +              module = "member",
   26.18 +              view = "show",
   26.19 +              id = record.truster.id
   26.20 +            }
   26.21 +          end
   26.22 +        },
   26.23 +        {
   26.24 +          label = _"Trustee",
   26.25 +          content = function(record)
   26.26 +            ui.link{
   26.27 +              content = record.trustee.name,
   26.28 +              module = "member",
   26.29 +              view = "show",
   26.30 +              id = record.trustee.id
   26.31 +            }
   26.32 +          end
   26.33 +        },
   26.34 +        {
   26.35 +          label = _"Area",
   26.36 +          content = function(record)
   26.37 +            if record.area then
   26.38 +              ui.field.text{ value = record.area.name }
   26.39 +            end
   26.40 +          end
   26.41 +        },
   26.42 +        {
   26.43 +          label = _"Issue",
   26.44 +          content = function(record)
   26.45 +            if record.issue then
   26.46 +              ui.field.text{ value = record.issue.id }
   26.47 +            end
   26.48 +          end
   26.49 +        },
   26.50 +      }
   26.51 +    }
   26.52 +  end
   26.53 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/app/main/delegation/_show_box.lua	Wed Nov 18 12:00:00 2009 +0100
    27.3 @@ -0,0 +1,114 @@
    27.4 +slot.select("delegation", function()
    27.5 +
    27.6 +  local delegation
    27.7 +  local area_id
    27.8 +  local issue_id
    27.9 +
   27.10 +  local scope = "global"
   27.11 +
   27.12 +  if param.get("initiative_id", atom.integer) then
   27.13 +    issue_id = Initiative:by_id(param.get("initiative_id", atom.integer)).issue_id
   27.14 +    scope = "issue"
   27.15 +  end
   27.16 +
   27.17 +  if param.get("issue_id", atom.integer) then
   27.18 +    issue_id = param.get("issue_id", atom.integer)
   27.19 +    scope = "issue"
   27.20 +  end
   27.21 +
   27.22 +  if param.get("area_id", atom.integer) then
   27.23 +    area_id = param.get("area_id", atom.integer)
   27.24 +    scope = "area"
   27.25 +  end
   27.26 +
   27.27 +
   27.28 +
   27.29 +  local delegation
   27.30 +
   27.31 +  if issue_id then
   27.32 +    delegation = Delegation:by_pk(app.session.member.id, nil, issue_id)
   27.33 +    if not delegation then
   27.34 +      local issue = Issue:by_id(issue_id)
   27.35 +      delegation = Delegation:by_pk(app.session.member.id, issue.area_id)
   27.36 +    end
   27.37 +  elseif area_id then
   27.38 +    delegation = Delegation:by_pk(app.session.member.id, area_id)
   27.39 +  end
   27.40 +
   27.41 +  if not delegation then
   27.42 +    delegation = Delegation:by_pk(app.session.member.id)
   27.43 +  end
   27.44 +  if delegation then
   27.45 +    ui.container{
   27.46 +      attr = {
   27.47 +        class = "head",
   27.48 +        style = "cursor: pointer;",
   27.49 +        onclick = "document.getElementById('delegation_content').style.display = 'block';"
   27.50 +      },
   27.51 +      content = _"Your vote is delegated. [more]"
   27.52 +    }
   27.53 +    ui.container{
   27.54 +      attr = { class = "content", id = "delegation_content" },
   27.55 +      content = function()
   27.56 +
   27.57 +        local delegation_chain = db:query{ "SELECT * FROM delegation_chain(?, ?, ?) JOIN member ON member.id = member_id ORDER BY index", app.session.member.id, area_id, issue_id }
   27.58 +
   27.59 +        for i, record in ipairs(delegation_chain) do
   27.60 +          local style
   27.61 +          if record.participation then
   27.62 +            style = "font-weight: bold;"
   27.63 +          end
   27.64 +          if record.overridden then
   27.65 +            style = "color: #777;"
   27.66 +          end
   27.67 +          if not record.active then
   27.68 +            style = "text-decoration: line-through;"
   27.69 +          end
   27.70 +          if record.scope_in then
   27.71 +            ui.field.text{
   27.72 +              value = " v " .. record.scope_in .. " v "
   27.73 +            }
   27.74 +          end
   27.75 +          local name = record.name
   27.76 +          if record.member_id == app.session.member.id then
   27.77 +            name = _"Me"
   27.78 +          end
   27.79 +          ui.field.text{
   27.80 +            attr = { style = style },
   27.81 +            value = name
   27.82 +          }
   27.83 +        end
   27.84 +
   27.85 +        ui.link{
   27.86 +          attr = { class = "revoke" },
   27.87 +          content = function()
   27.88 +            ui.image{ static = "icons/16/delete.png" }
   27.89 +            slot.put(_"Revoke")
   27.90 +          end,
   27.91 +          module = "delegation",
   27.92 +          action = "update",
   27.93 +          params = { issue_id = delegation.issue_id, area_id = delegation.area_id, delete = true },
   27.94 +          routing = {
   27.95 +            default = {
   27.96 +              mode = "redirect",
   27.97 +              module = request.get_module(),
   27.98 +              view = request.get_view(),
   27.99 +              id = param.get_id_cgi(),
  27.100 +              params = param.get_all_cgi()
  27.101 +            }
  27.102 +          }
  27.103 +        }
  27.104 +
  27.105 +        ui.container{
  27.106 +          attr = {
  27.107 +            class = "head",
  27.108 +            style = "cursor: pointer;",
  27.109 +            onclick = "document.getElementById('delegation_content').style.display = 'none';"
  27.110 +          },
  27.111 +          content = _"Click here to close."
  27.112 +        }
  27.113 +      end
  27.114 +    }
  27.115 +  end
  27.116 +
  27.117 +end)
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/app/main/delegation/new.lua	Wed Nov 18 12:00:00 2009 +0100
    28.3 @@ -0,0 +1,45 @@
    28.4 +local area = Area:by_id(param.get("area_id", atom.integer))
    28.5 +if area then
    28.6 +  slot.put_into("title", encode.html(_"Set delegation for Area '#{name}'":gsub("#{name}", area.name)))
    28.7 +end
    28.8 +
    28.9 +local issue = Issue:by_id(param.get("issue_id", atom.integer))
   28.10 +if issue then
   28.11 +  slot.put_into("title", encode.html(_"Set delegation for Issue ##{number} in Area '#{area_name}'":gsub("#{number}", issue.id):gsub("#{area_name}", issue.area.name)))
   28.12 +end
   28.13 +
   28.14 +
   28.15 +local contact_members = Member:new_selector()
   28.16 +  :add_where{ "contact.member_id = ?", app.session.member.id }
   28.17 +  :join("contact", nil, "member.id = contact.other_member_id")
   28.18 +  :add_order_by("member.login")
   28.19 +  :exec()
   28.20 +
   28.21 +
   28.22 +ui.form{
   28.23 +  attr = { class = "vertical" },
   28.24 +  module = "delegation",
   28.25 +  action = "update",
   28.26 +  params = {
   28.27 +    area_id = area and area.id or nil,
   28.28 +    issue_id = issue and issue.id or nil,
   28.29 +  },
   28.30 +  routing = {
   28.31 +    default = {
   28.32 +      mode = "redirect",
   28.33 +      module = area and "area" or "issue",
   28.34 +      view = "show",
   28.35 +      id = area and area.id or issue.id,
   28.36 +    }
   28.37 +  },
   28.38 +  content = function()
   28.39 +    ui.field.select{
   28.40 +      label = _"Trustee",
   28.41 +      name = "trustee_id",
   28.42 +      foreign_records = contact_members,
   28.43 +      foreign_id = "id",
   28.44 +      foreign_name = "name"
   28.45 +    }
   28.46 +    ui.submit{ text = _"Save" }
   28.47 +  end
   28.48 +}
   28.49 \ No newline at end of file
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/app/main/draft/_action/add.lua	Wed Nov 18 12:00:00 2009 +0100
    29.3 @@ -0,0 +1,14 @@
    29.4 +local initiative = Initiative:by_id(param.get("initiative_id", atom.integer))
    29.5 +
    29.6 +if Initiator:by_pk(initiative.id, app.session.member.id) then
    29.7 +  local draft = Draft:new()
    29.8 +  draft.author_id = app.session.member.id
    29.9 +  draft.initiative_id = initiative.id
   29.10 +  draft.content = param.get("content")
   29.11 +  draft:save()
   29.12 +
   29.13 +  slot.put_into("notice", _"New draft has been added to initiative")
   29.14 +
   29.15 +else
   29.16 +  error('access denied')
   29.17 +end
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/app/main/draft/_list.lua	Wed Nov 18 12:00:00 2009 +0100
    30.3 @@ -0,0 +1,30 @@
    30.4 +ui.list{
    30.5 +  records = param.get("drafts", "table"),
    30.6 +  columns = {
    30.7 +    {
    30.8 +      label = _"Id",
    30.9 +      name = "id"
   30.10 +    },
   30.11 +    {
   30.12 +      label = _"Created at",
   30.13 +      content = function(record)
   30.14 +        ui.field.text{ value = format.timestamp(record.created) }
   30.15 +      end
   30.16 +    },
   30.17 +    {
   30.18 +      label = _"Author",
   30.19 +      name = "author_name"
   30.20 +    },
   30.21 +    {
   30.22 +      content = function(record)
   30.23 +        ui.link{
   30.24 +          attr = { class = "action" },
   30.25 +          text = _"Show",
   30.26 +          module = "draft",
   30.27 +          view = "show",
   30.28 +          id = record.id
   30.29 +        }
   30.30 +      end
   30.31 +    }
   30.32 +  }
   30.33 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/app/main/draft/_show.lua	Wed Nov 18 12:00:00 2009 +0100
    31.3 @@ -0,0 +1,14 @@
    31.4 +local draft = param.get("draft", "table")
    31.5 +
    31.6 +ui.form{
    31.7 +  attr = { class = "vertical" },
    31.8 +  record = draft,
    31.9 +  readonly = true,
   31.10 +  content = function()
   31.11 +
   31.12 +    ui.field.text{ label = _"Initiative", value = draft.initiative.name }
   31.13 +    ui.field.text{ label = _"Author", name = "author_name" }
   31.14 +    ui.field.text{ label = _"Content", name = "content" }
   31.15 +
   31.16 +  end
   31.17 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/app/main/draft/new.lua	Wed Nov 18 12:00:00 2009 +0100
    32.3 @@ -0,0 +1,25 @@
    32.4 +slot.put_into("title", _"Add new draft")
    32.5 +
    32.6 +local initiative_id = param.get("initiative_id")
    32.7 +
    32.8 +ui.form{
    32.9 +  attr = { class = "vertical" },
   32.10 +  module = "draft",
   32.11 +  action = "add",
   32.12 +  params = { initiative_id = initiative_id },
   32.13 +  routing = {
   32.14 +    default = {
   32.15 +      mode = "redirect",
   32.16 +      module = "initiative",
   32.17 +      view = "show",
   32.18 +      id = initiative_id
   32.19 +    }
   32.20 +  },
   32.21 +  content = function()
   32.22 +
   32.23 +    ui.field.text{ label = _"Author", value = app.session.member.name, readonly = true }
   32.24 +    ui.field.text{ label = _"Content", name = "content", multiline = true }
   32.25 +
   32.26 +    ui.submit{ text = _"Save" }
   32.27 +  end
   32.28 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/app/main/draft/show.lua	Wed Nov 18 12:00:00 2009 +0100
    33.3 @@ -0,0 +1,7 @@
    33.4 +local draft = Draft:new_selector():add_where{ "id = ?", param.get_id() }:single_object_mode():exec()
    33.5 +
    33.6 +execute.view{
    33.7 +  module = "draft",
    33.8 +  view = "_show",
    33.9 +  params = { draft = draft }
   33.10 +}
   33.11 \ No newline at end of file
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/app/main/index/_action/login.lua	Wed Nov 18 12:00:00 2009 +0100
    34.3 @@ -0,0 +1,16 @@
    34.4 +local member = Member:by_login_and_password(param.get('login'), param.get('password'))
    34.5 +
    34.6 +if member then
    34.7 +  app.session.member = member
    34.8 +  app.session:save()
    34.9 +  slot.select("notice", function()
   34.10 +    ui.tag{ content = _'Login successful!' }
   34.11 +  end)
   34.12 +  trace.debug('User authenticated')
   34.13 +else
   34.14 +  slot.select("notice", function()
   34.15 +    ui.tag{ content = _'Invalid username or password!' }
   34.16 +  end)
   34.17 +  trace.debug('User NOT authenticated')
   34.18 +  return false
   34.19 +end
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/app/main/index/_action/logout.lua	Wed Nov 18 12:00:00 2009 +0100
    35.3 @@ -0,0 +1,4 @@
    35.4 +if app.session then
    35.5 +  app.session:destroy()
    35.6 +  slot.put_into("notice", _"Logout successful")
    35.7 +end
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/app/main/index/_action/set_lang.lua	Wed Nov 18 12:00:00 2009 +0100
    36.3 @@ -0,0 +1,3 @@
    36.4 +app.session.lang = param.get("lang")
    36.5 +
    36.6 +app.session:save()
    36.7 \ No newline at end of file
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/app/main/index/_action/update_password.lua	Wed Nov 18 12:00:00 2009 +0100
    37.3 @@ -0,0 +1,23 @@
    37.4 +local old_password = param.get("old_password")
    37.5 +local new_password1 = param.get("new_password1")
    37.6 +local new_password2 = param.get("new_password2")
    37.7 +
    37.8 +if not Member:by_login_and_password(app.session.member.login, old_password) then
    37.9 +  slot.put_into("error", _"Old password is wrong")
   37.10 +  return false
   37.11 +end
   37.12 +
   37.13 +if new_password1 ~= new_password2 then
   37.14 +  slot.put_into("error", _"New passwords does not match.")
   37.15 +  return false
   37.16 +end
   37.17 +
   37.18 +if #new_password1 < 8 then
   37.19 +  slot.put_into("error", _"New passwords is too short.")
   37.20 +  return false
   37.21 +end
   37.22 +
   37.23 +app.session.member:set_password(new_password1)
   37.24 +app.session.member:save()
   37.25 +
   37.26 +slot.put_into("notice", _"Your password has been updated successfully")
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/app/main/index/about.lua	Wed Nov 18 12:00:00 2009 +0100
    38.3 @@ -0,0 +1,92 @@
    38.4 +slot.put_into("title", encode.html(_"About LiquidFeedback"))
    38.5 +
    38.6 +
    38.7 +slot.put("<br />")
    38.8 +ui.field.text{ attr = { style = "font-weight: bold;" }, value = "Diensteanbieter:" }
    38.9 +slot.put("<br />")
   38.10 +
   38.11 +slot.put(config.app_service_provider)
   38.12 +
   38.13 +slot.put("<br />")
   38.14 +slot.put("<br />")
   38.15 +slot.put("<br />")
   38.16 +
   38.17 +
   38.18 +ui.field.text{ attr = { style = "font-weight: bold;" }, value = "Dieser Dienst ist mit folgender Software realisiert worden:" }
   38.19 +slot.put("<br />")
   38.20 +
   38.21 +local tmp = {
   38.22 +  {
   38.23 +    name = "LiquidFeedback Frontend",
   38.24 +    url = "http://www.public-software-group.org/liquid_feedback",
   38.25 +    version = config.app_version,
   38.26 +    license = "MIT/X11",
   38.27 +    license_url = "http://www.public-software-group.org/licenses"
   38.28 +  },
   38.29 +  {
   38.30 +    name = "LiquidFeedback Core",
   38.31 +    url = "http://www.public-software-group.org/liquid_feedback",
   38.32 +    version = db:query("SELECT * from liquid_feedback_version;")[1].string,
   38.33 +    license = "MIT/X11",
   38.34 +    license_url = "http://www.public-software-group.org/licenses"
   38.35 +  },
   38.36 +  {
   38.37 +    name = "WebMCP",
   38.38 +    url = "http://www.public-software-group.org/webmcp",
   38.39 +    version = _WEBMCP_VERSION,
   38.40 +    license = "MIT/X11",
   38.41 +    license_url = "http://www.public-software-group.org/licenses"
   38.42 +  },
   38.43 +  {
   38.44 +    name = "Lua",
   38.45 +    url = "http://www.lua.org",
   38.46 +    version = _VERSION:gsub("Lua ", ""),
   38.47 +    license = "MIT/X11",
   38.48 +    license_url = "http://www.lua.org/license.html"
   38.49 +  },
   38.50 +  {
   38.51 +    name = "PostgreSQL",
   38.52 +    url = "http://www.postgresql.org/",
   38.53 +    version = db:query("SELECT version();")[1].version:gsub("PostgreSQL ", ""):gsub("on.*", ""),
   38.54 +    license = "BSD",
   38.55 +    license_url = "http://www.postgresql.org/about/licence"
   38.56 +  },
   38.57 +}
   38.58 +
   38.59 +ui.list{
   38.60 +  records = tmp,
   38.61 +  columns = {
   38.62 +    {
   38.63 +      label = _"Software",
   38.64 +      content = function(record) 
   38.65 +        ui.link{
   38.66 +          content = record.name,
   38.67 +          external = record.url
   38.68 +        }
   38.69 +      end
   38.70 +    },
   38.71 +    {
   38.72 +      label = _"Version",
   38.73 +      content = function(record) ui.field.text{ value = record.version } end
   38.74 +    },
   38.75 +    {
   38.76 +      label = _"License",
   38.77 +      content = function(record) 
   38.78 +        ui.link{
   38.79 +          content = record.license,
   38.80 +          external = record.license_url
   38.81 +        }
   38.82 +      end
   38.83 +
   38.84 +    }
   38.85 +  }
   38.86 +}
   38.87 +
   38.88 +slot.put("<br />")
   38.89 +slot.put("<br />")
   38.90 +slot.put("<br />")
   38.91 +
   38.92 +ui.field.text{ attr = { style = "font-weight: bold;" }, value = "3rd party license information:" }
   38.93 +slot.put("<br />")
   38.94 +slot.put('The icons used in Liquid Feedback (except national flags) are from <a href="http://www.famfamfam.com/lab/icons/silk/">Silk icon set 1.3</a> by Mark James. His work is licensed under a <a href="http://creativecommons.org/licenses/by/2.5/">Creative Commons Attribution 2.5 License.</a>')
   38.95 +
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/app/main/index/change_password.lua	Wed Nov 18 12:00:00 2009 +0100
    39.3 @@ -0,0 +1,32 @@
    39.4 +
    39.5 +slot.put_into("title", _"Change password")
    39.6 +
    39.7 +slot.select("actions", function()
    39.8 +  ui.link{
    39.9 +    content = function()
   39.10 +        ui.image{ static = "icons/16/cancel.png" }
   39.11 +        slot.put(_"Cancel")
   39.12 +    end,
   39.13 +    module = "index",
   39.14 +    view = "index"
   39.15 +  }
   39.16 +end)
   39.17 +
   39.18 +ui.form{
   39.19 +  attr = { class = "vertical" },
   39.20 +  module = "index",
   39.21 +  action = "update_password",
   39.22 +  routing = {
   39.23 +    ok = {
   39.24 +      mode = "redirect",
   39.25 +      module = "index",
   39.26 +      view = "index"
   39.27 +    }
   39.28 +  },
   39.29 +  content = function()
   39.30 +    ui.field.password{ label = _"Old password", name = "old_password" }
   39.31 +    ui.field.password{ label = _"New password", name = "new_password1" }
   39.32 +    ui.field.password{ label = _"Repeat new password", name = "new_password2" }
   39.33 +    ui.submit{ value = _"Change password" }
   39.34 +  end
   39.35 +}
   39.36 \ No newline at end of file
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/app/main/index/index.lua	Wed Nov 18 12:00:00 2009 +0100
    40.3 @@ -0,0 +1,82 @@
    40.4 +slot.select("title", function()
    40.5 +  ui.image{
    40.6 +    attr = { class = "avatar" },
    40.7 +    module = "member",
    40.8 +    view = "avatar",
    40.9 +    extension = "jpg",
   40.10 +    id = app.session.member.id
   40.11 +  }
   40.12 +end)
   40.13 +
   40.14 +slot.select("title", function()
   40.15 +  ui.container{
   40.16 +    attr = { class = "lang_chooser" },
   40.17 +    content = function()
   40.18 +      for i, lang in ipairs{"en", "de"} do
   40.19 +        ui.link{
   40.20 +          content = function()
   40.21 +            ui.image{
   40.22 +              static = "lang/" .. lang .. ".png",
   40.23 +              attr = { style = "margin-left: 0.5em;", alt = lang }
   40.24 +            }
   40.25 +          end,
   40.26 +          module = "index",
   40.27 +          action = "set_lang",
   40.28 +          params = { lang = lang },
   40.29 +          routing = {
   40.30 +            default = {
   40.31 +              mode = "redirect",
   40.32 +              module = request.get_module(),
   40.33 +              view = request.get_view(),
   40.34 +              id = param.get_id_cgi(),
   40.35 +              params = param.get_all_cgi()
   40.36 +            }
   40.37 +          }
   40.38 +        }
   40.39 +      end
   40.40 +    end
   40.41 +  }
   40.42 +end)
   40.43 +
   40.44 +slot.put_into("title", encode.html(config.app_title))
   40.45 +
   40.46 +slot.select("actions", function()
   40.47 +  slot.put(_"Logged in as:")
   40.48 +  slot.put(" <b>")
   40.49 +  slot.put(app.session.member.login)
   40.50 +  slot.put("</b> | ")
   40.51 +
   40.52 +  ui.link{
   40.53 +    content = function()
   40.54 +        ui.image{ static = "icons/16/user_gray.png" }
   40.55 +        slot.put(_"Upload avatar")
   40.56 +    end,
   40.57 +    module = "member",
   40.58 +    view = "edit_avatar"
   40.59 +  }
   40.60 +
   40.61 +  ui.link{
   40.62 +    content = function()
   40.63 +        ui.image{ static = "icons/16/application_form.png" }
   40.64 +        slot.put(_"Edit my page")
   40.65 +    end,
   40.66 +    module = "member",
   40.67 +    view = "edit"
   40.68 +  }
   40.69 +
   40.70 +  ui.link{
   40.71 +    content = function()
   40.72 +        ui.image{ static = "icons/16/key.png" }
   40.73 +        slot.put(_"Change password")
   40.74 +    end,
   40.75 +    module = "index",
   40.76 +    view = "change_password"
   40.77 +  }
   40.78 +end)
   40.79 +
   40.80 +execute.view{
   40.81 +  module = "member",
   40.82 +  view = "_show",
   40.83 +  params = { member = app.session.member }
   40.84 +}
   40.85 +
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/app/main/index/login.lua	Wed Nov 18 12:00:00 2009 +0100
    41.3 @@ -0,0 +1,41 @@
    41.4 +slot.put_into("title", encode.html(config.app_title))
    41.5 +
    41.6 +ui.tag{
    41.7 +  tag = 'p',
    41.8 +  content = 'You need to be logged in, to use this system.'
    41.9 +}
   41.10 +
   41.11 +ui.form{
   41.12 +  attr = { class = "login" },
   41.13 +  module = 'index',
   41.14 +  action = 'login',
   41.15 +  routing = {
   41.16 +    ok = {
   41.17 +      mode   = 'redirect',
   41.18 +      module = 'index',
   41.19 +      view   = 'index'
   41.20 +    },
   41.21 +    error = {
   41.22 +      mode   = 'forward',
   41.23 +      module = 'index',
   41.24 +      view   = 'login',
   41.25 +    }
   41.26 +  },
   41.27 +  content = function()
   41.28 +    ui.field.text{
   41.29 +      attr = { id = "username_field" },
   41.30 +      label     = _'Username',
   41.31 +      html_name = 'login',
   41.32 +      value     = ''
   41.33 +    }
   41.34 +    ui.script{ script = 'document.getElementById("username_field").focus();' }
   41.35 +    ui.field.password{
   41.36 +      label     = _'Password',
   41.37 +      html_name = 'password',
   41.38 +      value     = ''
   41.39 +    }
   41.40 +    ui.submit{
   41.41 +      text = _'Login'
   41.42 +    }
   41.43 +  end
   41.44 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/app/main/index/search.lua	Wed Nov 18 12:00:00 2009 +0100
    42.3 @@ -0,0 +1,53 @@
    42.4 +local search_for = param.get("search_for", atom.string)
    42.5 +local search_string = param.get("search", atom.string)
    42.6 +
    42.7 +search_for = search_for or "global"
    42.8 +
    42.9 +slot.put_into("title", _("Search results for: '#{search}'", { search  = search_string }))
   42.10 +
   42.11 +
   42.12 +local members = {}
   42.13 +local issues = {}
   42.14 +local initiatives = {}
   42.15 +
   42.16 +
   42.17 +if search_for == "global" or search_for == "member" then
   42.18 +  members = Member:search(search_string)
   42.19 +end
   42.20 +
   42.21 +if search_for == "global" or search_for == "issue" then
   42.22 +  issues = Issue:search(search_string)
   42.23 +end
   42.24 +
   42.25 +if search_for == "initiative" then
   42.26 +  initiatives = Initiative:search(search_string)
   42.27 +end
   42.28 +
   42.29 +
   42.30 +if #members > 0 then
   42.31 +  ui.heading{ content = _"Members" }
   42.32 +  execute.view{
   42.33 +    module = "member",
   42.34 +    view = "_list",
   42.35 +    params = { members = members, highlight_string = search_string },
   42.36 +  }
   42.37 +end
   42.38 +
   42.39 +if #issues > 0 then
   42.40 +  ui.heading{ content = _"Issues" }
   42.41 +  execute.view{
   42.42 +    module = "issue",
   42.43 +    view = "_list",
   42.44 +    params = { issues = issues, highlight_string = search_string },
   42.45 +  }
   42.46 +end
   42.47 +
   42.48 +if #initiatives > 0 then
   42.49 +  ui.heading{ content = _"Initiatives" }
   42.50 +  execute.view{
   42.51 +    module = "initiative",
   42.52 +    view = "_list",
   42.53 +    params = { initiatives = initiatives, highlight_string = search_string },
   42.54 +  }
   42.55 +end
   42.56 +
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/app/main/initiative/_action/add_support.lua	Wed Nov 18 12:00:00 2009 +0100
    43.3 @@ -0,0 +1,27 @@
    43.4 +local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
    43.5 +
    43.6 +local member = app.session.member
    43.7 +
    43.8 +local supporter = Supporter:by_pk(initiative.id, member.id)
    43.9 +
   43.10 +local last_draft = Draft:new_selector()
   43.11 +  :add_where{ "initiative_id = ?", initiative.id }
   43.12 +  :add_order_by("id DESC")
   43.13 +  :limit(1)
   43.14 +  :single_object_mode()
   43.15 +  :exec()
   43.16 +
   43.17 +if not supporter then
   43.18 +  supporter = Supporter:new()
   43.19 +  supporter.member_id = member.id
   43.20 +  supporter.initiative_id = initiative.id
   43.21 +  supporter.draft_id = last_draft.id
   43.22 +  supporter:save()
   43.23 +  slot.put_into("notice", _"Your support has been added to this initiative")
   43.24 +elseif supporter.draft_id ~= last_draft.id then
   43.25 +  supporter.draft_id = last_draft.id
   43.26 +  supporter:save()
   43.27 +  slot.put_into("notice", _"Your support has been updated to the latest draft")
   43.28 +else
   43.29 +  slot.put_into("notice", _"You are already supporting the latest draft")
   43.30 +end
   43.31 \ No newline at end of file
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/app/main/initiative/_action/create.lua	Wed Nov 18 12:00:00 2009 +0100
    44.3 @@ -0,0 +1,54 @@
    44.4 +local issue
    44.5 +local area
    44.6 +
    44.7 +db:query("BEGIN")
    44.8 +
    44.9 +local issue_id = param.get("issue_id", atom.integer)
   44.10 +if issue_id then
   44.11 +  issue = Issue:new_selector():add_where{"id=?",issue_id}:single_object_mode():exec()
   44.12 +  area = issue.area
   44.13 +
   44.14 +else
   44.15 +  local area_id = param.get("area_id", atom.integer)
   44.16 +  area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
   44.17 +end
   44.18 +
   44.19 +local initiative = Initiative:new()
   44.20 +
   44.21 +if not issue then
   44.22 +  issue = Issue:new()
   44.23 +  issue.area_id = area.id
   44.24 +  issue.policy_id = param.get("policy_id", atom.integer)
   44.25 +  issue:save()
   44.26 +end
   44.27 +
   44.28 +initiative.issue_id = issue.id
   44.29 +param.update(initiative, "name")
   44.30 +initiative:save()
   44.31 +
   44.32 +local draft = Draft:new()
   44.33 +draft.initiative_id = initiative.id
   44.34 +draft.content = param.get("draft")
   44.35 +draft.author_id = app.session.member.id
   44.36 +draft:save()
   44.37 +
   44.38 +local initiator = Initiator:new()
   44.39 +initiator.initiative_id = initiative.id
   44.40 +initiator.member_id = app.session.member.id
   44.41 +initiator:save()
   44.42 +
   44.43 +local supporter = Supporter:new()
   44.44 +supporter.initiative_id = initiative.id
   44.45 +supporter.member_id = app.session.member.id
   44.46 +supporter.draft_id = draft.id
   44.47 +supporter:save()
   44.48 +
   44.49 +db:query("COMMIT")
   44.50 +
   44.51 +slot.put_into("notice", _"Initiative successfully created")
   44.52 +
   44.53 +request.redirect{
   44.54 +  module = "initiative",
   44.55 +  view = "show",
   44.56 +  id = initiative.id
   44.57 +}
   44.58 \ No newline at end of file
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/app/main/initiative/_action/remove_support.lua	Wed Nov 18 12:00:00 2009 +0100
    45.3 @@ -0,0 +1,12 @@
    45.4 +local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
    45.5 +
    45.6 +local member = app.session.member
    45.7 +
    45.8 +local supporter = Supporter:by_pk(initiative.id, member.id)
    45.9 +
   45.10 +if supporter then  
   45.11 +  supporter:destroy()
   45.12 +  slot.put_into("notice", _"Your support has been removed from this initiative")
   45.13 +else
   45.14 +  slot.put_into("notice", _"You are already not supporting this initiative")
   45.15 +end
   45.16 \ No newline at end of file
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/app/main/initiative/_list.lua	Wed Nov 18 12:00:00 2009 +0100
    46.3 @@ -0,0 +1,116 @@
    46.4 +local initiatives_selector = param.get("initiatives_selector", "table")
    46.5 +initiatives_selector:join("issue", nil, "issue.id = initiative.issue_id")
    46.6 +
    46.7 +local issue = param.get("issue", "table")
    46.8 +
    46.9 +local order_options = {}
   46.10 +
   46.11 +if issue and issue.ranks_available then
   46.12 +  order_options[#order_options+1] = {
   46.13 +    name = "rank",
   46.14 +    label = _"Rank",
   46.15 +    order_by = "initiative.rank"
   46.16 +  }
   46.17 +end
   46.18 +
   46.19 +order_options[#order_options+1] = {
   46.20 +  name = "support",
   46.21 +  label = _"Support",
   46.22 +  order_by = "initiative.supporter_count::float / issue.population::float DESC"
   46.23 +}
   46.24 +
   46.25 +order_options[#order_options+1] = {
   46.26 +  name = "support_si",
   46.27 +  label = _"Support S+I",
   46.28 +  order_by = "initiative.satisfied_informed_supporter_count::float / issue.population::float DESC"
   46.29 +}
   46.30 +
   46.31 +order_options[#order_options+1] = {
   46.32 +  name = "newest",
   46.33 +  label = _"Newest",
   46.34 +  order_by = "initiative.created DESC"
   46.35 +}
   46.36 +
   46.37 +order_options[#order_options+1] = {
   46.38 +  name = "oldest",
   46.39 +  label = _"Oldest",
   46.40 +  order_by = "initiative.created"
   46.41 +}
   46.42 +
   46.43 +local name = "initiative_list"
   46.44 +if issue then
   46.45 +  name = "issue_" .. tostring(issue.id) ..  "_initiative_list"
   46.46 +end
   46.47 +
   46.48 +ui.order{
   46.49 +  name = name,
   46.50 +  selector = initiatives_selector,
   46.51 +  options = order_options,
   46.52 +  content = function()
   46.53 +    ui.paginate{
   46.54 +      selector = initiatives_selector,
   46.55 +      content = function()
   46.56 +        local initiatives = initiatives_selector:exec()
   46.57 +        local columns = {}
   46.58 +        local issue = initiatives[1] and initiatives[1].issue or {}
   46.59 +        if issue.accepted and issue.closed and issue.ranks_available then 
   46.60 +          columns[#columns+1] = {
   46.61 +            content = function(record)
   46.62 +              ui.field.rank{ value = record.rank }
   46.63 +            end
   46.64 +          }
   46.65 +          columns[#columns+1] = {
   46.66 +            content = function(record)
   46.67 +              if record.negative_votes and record.positive_votes then
   46.68 +                local max_value = record.issue.voter_count
   46.69 + trace.debug(record.issue.voter_count)
   46.70 +                ui.bargraph{
   46.71 +                  max_value = max_value,
   46.72 +                  width = 100,
   46.73 +                  bars = {
   46.74 +                    { color = "#0a0", value = record.positive_votes },
   46.75 +                    { color = "#aaa", value = max_value - record.negative_votes - record.positive_votes },
   46.76 +                    { color = "#a00", value = record.negative_votes },
   46.77 +                  }
   46.78 +                }
   46.79 +              end
   46.80 +            end
   46.81 +          }
   46.82 +        else
   46.83 +          columns[#columns+1] = {
   46.84 +            content = function(record)
   46.85 +              local max_value = (record.issue.population or 0)
   46.86 +              ui.bargraph{
   46.87 +                max_value = max_value,
   46.88 +                width = 100,
   46.89 +                bars = {
   46.90 +                  { color = "#0a0", value = (record.satisfied_informed_supporter_count or 0) },
   46.91 +                  { color = "#8f8", value = (record.supporter_count or 0) - (record.satisfied_informed_supporter_count or 0) },
   46.92 +                  { color = "#ddd", value = max_value - (record.supporter_count or 0) },
   46.93 +                }
   46.94 +              }
   46.95 +            end
   46.96 +          }
   46.97 +        end
   46.98 +        columns[#columns+1] = {
   46.99 +          content = function(record)
  46.100 +            ui.link{
  46.101 +              content = function()
  46.102 +                util.put_highlighted_string(record.shortened_name)
  46.103 +              end,
  46.104 +              module = "initiative",
  46.105 +              view = "show",
  46.106 +              id = record.id
  46.107 +            }
  46.108 +          end
  46.109 +        }
  46.110 +
  46.111 +        ui.list{
  46.112 +          attr = { class = "initiatives" },
  46.113 +          records = initiatives,
  46.114 +          columns = columns
  46.115 +        }
  46.116 +      end
  46.117 +    }
  46.118 +  end
  46.119 +}
  46.120 \ No newline at end of file
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/app/main/initiative/new.lua	Wed Nov 18 12:00:00 2009 +0100
    47.3 @@ -0,0 +1,45 @@
    47.4 +local issue
    47.5 +local area
    47.6 +
    47.7 +local issue_id = param.get("issue_id", atom.integer)
    47.8 +if issue_id then
    47.9 +  issue = Issue:new_selector():add_where{"id=?",issue_id}:single_object_mode():exec()
   47.10 +  area = issue.area
   47.11 +
   47.12 +else
   47.13 +  local area_id = param.get("area_id", atom.integer)
   47.14 +  area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
   47.15 +end
   47.16 +
   47.17 +if issue_id then
   47.18 +  slot.put_into("title", _"Add new initiative to issue")
   47.19 +else
   47.20 +  slot.put_into("title", _"Create new issue")
   47.21 +end
   47.22 +
   47.23 +ui.form{
   47.24 +  module = "initiative",
   47.25 +  action = "create",
   47.26 +  params = {
   47.27 +    area_id = area.id,
   47.28 +    issue_id = issue and issue.id or nil
   47.29 +  },
   47.30 +  attr = { class = "vertical" },
   47.31 +  content = function()
   47.32 +    ui.field.text{ label = _"Area",  value = area.name }
   47.33 +    if issue_id then
   47.34 +      ui.field.text{ label = _"Issue",  value = issue_id }
   47.35 +    else
   47.36 +      ui.field.select{
   47.37 +        label = _"Policy",
   47.38 +        name = "policy_id",
   47.39 +        foreign_records = Policy:new_selector():exec(),
   47.40 +        foreign_id = "id",
   47.41 +        foreign_name = "name"
   47.42 +      }
   47.43 +    end
   47.44 +    ui.field.text{ label = _"Name",  name = "name" }
   47.45 +    ui.field.text{ label = _"Draft", name = "draft", multiline = true }
   47.46 +    ui.submit{ text = _"Save" }
   47.47 +  end
   47.48 +}
   47.49 \ No newline at end of file
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/app/main/initiative/show.lua	Wed Nov 18 12:00:00 2009 +0100
    48.3 @@ -0,0 +1,176 @@
    48.4 +local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
    48.5 +
    48.6 +slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(initiative.id) .. '.rss" />')
    48.7 +
    48.8 +execute.view{
    48.9 +  module = "supporter",
   48.10 +  view = "_show_box",
   48.11 +  params = { initiative = initiative }
   48.12 +}
   48.13 +
   48.14 +execute.view{
   48.15 +  module = "delegation",
   48.16 +  view = "_show_box",
   48.17 +  params = { issue_id = initiative.issue_id }
   48.18 +}
   48.19 +
   48.20 +
   48.21 +slot.select("path", function()
   48.22 +  ui.link{
   48.23 +    content = _"Area '#{name}'":gsub("#{name}", initiative.issue.area.name),
   48.24 +    module = "area",
   48.25 +    view = "show",
   48.26 +    id = initiative.issue.area.id
   48.27 +  }
   48.28 +  ui.container{ content = "::" }
   48.29 +  ui.link{
   48.30 +    content = _"Issue ##{id} (#{policy_name})":gsub("#{id}", initiative.issue.id):gsub("#{policy_name}", initiative.issue.policy.name),
   48.31 +    module = "issue",
   48.32 +    view = "show",
   48.33 +    id = initiative.issue.id
   48.34 +  }
   48.35 +end)
   48.36 +
   48.37 +slot.put_into("title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) ))
   48.38 +
   48.39 +slot.select("actions", function()
   48.40 +
   48.41 +  ui.twitter("http://example.com/i" .. tostring(initiative.id) .. " " .. initiative.name)
   48.42 +
   48.43 +end)
   48.44 +
   48.45 +
   48.46 +ui.container{
   48.47 +  attr = {  id = "add_suggestion_form", class = "hidden_inline_form" },
   48.48 +  content = function()
   48.49 +
   48.50 +    ui.link{
   48.51 +      content = _"Close",
   48.52 +      attr = {
   48.53 +        onclick = "document.getElementById('add_suggestion_form').style.display='none';return(false)",
   48.54 +        style = "float: right;"
   48.55 +      }
   48.56 +    }
   48.57 +
   48.58 +    ui.field.text{ attr = { class = "head" }, value = _"Add new suggestion" }
   48.59 +
   48.60 +
   48.61 +    ui.form{
   48.62 +      module = "suggestion",
   48.63 +      action = "add",
   48.64 +      params = { initiative_id = initiative.id },
   48.65 +      routing = {
   48.66 +        default = {
   48.67 +          mode = "redirect",
   48.68 +          module = "initiative",
   48.69 +          view = "show",
   48.70 +          id = initiative.id,
   48.71 +          params = { tab = "suggestion" }
   48.72 +        }
   48.73 +      },
   48.74 +      attr = { class = "vertical" },
   48.75 +      content = function()
   48.76 +        ui.field.text{ label = _"Name",        name = "name" }
   48.77 +        ui.field.text{ label = _"Description", name = "description", multiline = true }
   48.78 +        ui.field.select{ 
   48.79 +          label = _"Degree", 
   48.80 +          name = "degree",
   48.81 +          foreign_records = { 
   48.82 +            { id =  1, name = _"should"},
   48.83 +            { id =  2, name = _"must"},
   48.84 +          },
   48.85 +          foreign_id = "id",
   48.86 +          foreign_name = "name"
   48.87 +        }
   48.88 +        ui.submit{ text = _"Commit suggestion" }
   48.89 +      end
   48.90 +    }
   48.91 +  end
   48.92 +}
   48.93 +
   48.94 +
   48.95 +ui.tabs{
   48.96 +  {
   48.97 +    name = "current_draft",
   48.98 +    label = _"Current draft",
   48.99 +    content = function()
  48.100 +      execute.view{ module = "draft", view = "_show", params = { draft = initiative.current_draft } }
  48.101 +      if Initiator:by_pk(initiative.id, app.session.member.id) then
  48.102 +        ui.link{
  48.103 +          content = function()
  48.104 +            ui.image{ static = "icons/16/script_add.png" }
  48.105 +            slot.put(_"Add new draft")
  48.106 +          end,
  48.107 +          module = "draft",
  48.108 +          view = "new",
  48.109 +          params = { initiative_id = initiative.id }
  48.110 +        }
  48.111 +      end
  48.112 +    end
  48.113 +  },
  48.114 +  {
  48.115 +    name = "details",
  48.116 +    label = _"Details",
  48.117 +    content = function()
  48.118 +      ui.form{
  48.119 +        attr = { class = "vertical" },
  48.120 +        record = initiative,
  48.121 +        readonly = true,
  48.122 +        content = function()
  48.123 +          ui.field.text{ label = _"Issue policy", value = initiative.issue.policy.name }
  48.124 +          ui.field.text{
  48.125 +            label = _"Created at",
  48.126 +            value = tostring(initiative.created)
  48.127 +          }
  48.128 +          ui.field.text{
  48.129 +            label = _"Created at",
  48.130 +            value = format.timestamp(initiative.created)
  48.131 +          }
  48.132 +          ui.field.date{ label = _"Revoked at", name = "revoked" }
  48.133 +          ui.field.boolean{ label = _"Admitted", name = "admitted" }
  48.134 +        end
  48.135 +      }
  48.136 +    end
  48.137 +  },
  48.138 +  {
  48.139 +    name = "suggestion",
  48.140 +    label = _"Suggestions",
  48.141 +    content = function()
  48.142 +      execute.view{ module = "suggestion", view = "_list", params = { suggestions_selector = initiative:get_reference_selector("suggestions") } }
  48.143 +      slot.put("<br />")
  48.144 +      if not initiative.issue.frozen and not initiative.issue.closed then
  48.145 +        ui.link{
  48.146 +          content = function()
  48.147 +            ui.image{ static = "icons/16/comment_add.png" }
  48.148 +            slot.put(_"Add new suggestion")
  48.149 +          end,
  48.150 +          attr = { onclick = "document.getElementById('add_suggestion_form').style.display='block';return(false)" },
  48.151 +          static = "#"
  48.152 +        }
  48.153 +      end
  48.154 +    end
  48.155 +  },
  48.156 +  {
  48.157 +    name = "supporter",
  48.158 +    label = _"Supporter",
  48.159 +    content = function()
  48.160 +      execute.view{ module = "member", view = "_list", params = { members_selector = initiative:get_reference_selector("supporting_members") } }
  48.161 +    end
  48.162 +  },
  48.163 +  {
  48.164 +    name = "initiators",
  48.165 +    label = _"Initiators",
  48.166 +    content = function()
  48.167 +      execute.view{ module = "member", view = "_list", params = { members_selector = initiative:get_reference_selector("initiating_members") } }
  48.168 +    end
  48.169 +  },
  48.170 +  {
  48.171 +    name = "drafts",
  48.172 +    label = _"Old drafts",
  48.173 +    content = function()
  48.174 +      execute.view{ module = "draft", view = "_list", params = { drafts = initiative.drafts } }
  48.175 +    end
  48.176 +  },
  48.177 +}
  48.178 +
  48.179 +
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/app/main/initiative/show.rss.lua	Wed Nov 18 12:00:00 2009 +0100
    49.3 @@ -0,0 +1,49 @@
    49.4 +slot.set_layout("rss")
    49.5 +
    49.6 +local function rss_channel(channel)
    49.7 +  for key, val in pairs(channel) do
    49.8 +    slot.put("<", key, ">", val, "</", key, ">")
    49.9 +  end
   49.10 +end
   49.11 +
   49.12 +local function rss_item(item)
   49.13 +  slot.put("<item>")
   49.14 +  for key, val in pairs(item) do
   49.15 +    slot.put("<", key, ">", val, "</", key, ">")
   49.16 +  end
   49.17 +  slot.put("</item>")
   49.18 +end
   49.19 +
   49.20 +
   49.21 +local initiative = Initiative:by_id(param.get_id())
   49.22 +
   49.23 +rss_channel{
   49.24 +  title = initiative.name,
   49.25 +  description = initiative.current_draft.content,
   49.26 +  language = "de",
   49.27 +  copyright = initiative.current_draft.author.name,
   49.28 +  pubDate = "Tue, 8 Jul 2008 2:43:19"
   49.29 +}
   49.30 +
   49.31 +for i, suggestion in ipairs(initiative.suggestions) do
   49.32 +  
   49.33 +  local text = suggestion.name
   49.34 +
   49.35 +  text = text .. " ("
   49.36 +  text = text .. tostring(suggestion.plus2_unfulfilled_count + suggestion.plus2_unfulfilled_count) .. "++ "
   49.37 +  text = text .. tostring(suggestion.plus1_unfulfilled_count + suggestion.plus1_unfulfilled_count) .. "+ "
   49.38 +  text = text .. tostring(suggestion.minus1_unfulfilled_count + suggestion.minus1_unfulfilled_count) .. "- "
   49.39 +  text = text .. tostring(suggestion.minus2_unfulfilled_count + suggestion.minus2_unfulfilled_count) .. "--"
   49.40 +
   49.41 +  text = text .. ")"
   49.42 +
   49.43 +  rss_item{
   49.44 +    title = text,
   49.45 +    description = suggestion.content,
   49.46 +    link = "http://localhost/lf/suggestion/show/" .. tostring(suggestion.id) .. ".html",
   49.47 +    author = "",
   49.48 +    guid = "guid",
   49.49 +    pubDate = "Tue, 8 Jul 2008 2:43:19"
   49.50 +  }
   49.51 +
   49.52 +end
   49.53 \ No newline at end of file
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/app/main/interest/_action/update.lua	Wed Nov 18 12:00:00 2009 +0100
    50.3 @@ -0,0 +1,28 @@
    50.4 +local issue_id = assert(param.get("issue_id", atom.integer), "no issue id given")
    50.5 +local interest = Interest:by_pk(issue_id, app.session.member.id)
    50.6 +
    50.7 +if param.get("delete", atom.boolean) then
    50.8 +  if interest then
    50.9 +    interest:destroy()
   50.10 +    slot.put_into("notice", _"Interest removed")
   50.11 +  else
   50.12 +    slot.put_into("notice", _"Interest not existant")
   50.13 +  end
   50.14 +  return
   50.15 +end
   50.16 +
   50.17 +if not interest then
   50.18 +  interest = Interest:new()
   50.19 +  interest.issue_id   = issue_id
   50.20 +  interest.member_id  = app.session.member_id
   50.21 +  interest.autoreject = false
   50.22 +end
   50.23 +
   50.24 +local autoreject = param.get("autoreject", atom.boolean)
   50.25 +if autoreject ~= nil then
   50.26 +  interest.autoreject = autoreject
   50.27 +end
   50.28 +
   50.29 +interest:save()
   50.30 +
   50.31 +slot.put_into("notice", _"Interest updated")
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/app/main/interest/_show_box.lua	Wed Nov 18 12:00:00 2009 +0100
    51.3 @@ -0,0 +1,71 @@
    51.4 +
    51.5 +local issue = param.get("issue", "table")
    51.6 +
    51.7 +
    51.8 +slot.select("interest", function()
    51.9 +  local interest = Interest:by_pk(issue.id, app.session.member.id)
   51.10 +
   51.11 +  ui.container{
   51.12 +    attr = { 
   51.13 +      class = "head",
   51.14 +      onclick = "document.getElementById('interest_content').style.display = 'block';"
   51.15 +    },
   51.16 +    content = function()
   51.17 +      if interest then
   51.18 +        ui.field.text{ value = _"You are interested. [more]" }
   51.19 +      else
   51.20 +        ui.field.text{ value = _"You are not interested. [more]" }
   51.21 +      end
   51.22 +    end
   51.23 +  }
   51.24 +
   51.25 +  ui.container{
   51.26 +    attr = { class = "content", id = "interest_content" },
   51.27 +    content = function()
   51.28 +      if interest then
   51.29 +        ui.link{
   51.30 +          content = _"Remove my interest",
   51.31 +          module = "interest",
   51.32 +          action = "update",
   51.33 +          params = { issue_id = issue.id, delete = true },
   51.34 +          routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
   51.35 +        }
   51.36 +        if interest.autoreject then
   51.37 +          ui.field.text{ value = _"Autoreject is on." }
   51.38 +          ui.link{
   51.39 +            content = _"Remove autoreject",
   51.40 +            module = "interest",
   51.41 +            action = "update",
   51.42 +            params = { issue_id = issue.id, autoreject = false },
   51.43 +            routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
   51.44 +          }
   51.45 +        else
   51.46 +          ui.field.text{ value = _"Autoreject is off." }
   51.47 +          ui.link{
   51.48 +            content = _"Set autoreject",
   51.49 +            module = "interest",
   51.50 +            action = "update",
   51.51 +            params = { issue_id = issue.id, autoreject = true },
   51.52 +            routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
   51.53 +          }
   51.54 +        end
   51.55 +      else
   51.56 +        ui.link{
   51.57 +          content = _"Add my interest to this issue",
   51.58 +          module = "interest",
   51.59 +          action = "update",
   51.60 +          params = { issue_id = issue.id },
   51.61 +          routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
   51.62 +        }
   51.63 +      end
   51.64 +        ui.container{
   51.65 +          attr = {
   51.66 +            class = "head",
   51.67 +            style = "cursor: pointer;",
   51.68 +            onclick = "document.getElementById('interest_content').style.display = 'none';"
   51.69 +          },
   51.70 +          content = _"Click here to close."
   51.71 +        }
   51.72 +    end
   51.73 +  }
   51.74 +end)
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/app/main/issue/_list.lua	Wed Nov 18 12:00:00 2009 +0100
    52.3 @@ -0,0 +1,89 @@
    52.4 +local issues_selector = param.get("issues_selector", "table")
    52.5 +
    52.6 +local paginate = ui.paginate
    52.7 +
    52.8 +local issues
    52.9 +
   52.10 +if not issues_selector then
   52.11 +  issues = param.get("issues", "table")
   52.12 +  paginate = function(args)
   52.13 +    args.content()
   52.14 +  end
   52.15 +end
   52.16 +
   52.17 +ui.order{
   52.18 +  name = "issue_list",
   52.19 +  selector = issues_selector,
   52.20 +  options = {
   52.21 +    {
   52.22 +      name = "population",
   52.23 +      label = _"Population",
   52.24 +      order_by = "issue.population DESC"
   52.25 +    },
   52.26 +    {
   52.27 +      name = "newest",
   52.28 +      label = _"Newest",
   52.29 +      order_by = "issue.created DESC"
   52.30 +    },
   52.31 +    {
   52.32 +      name = "oldest",
   52.33 +      label = _"Oldest",
   52.34 +      order_by = "issue.created"
   52.35 +    }
   52.36 +  },
   52.37 +  content = function()
   52.38 +    paginate{
   52.39 +      selector = issues_selector,
   52.40 +      content = function()
   52.41 +        local highlight_string = param.get("highlight_string", "string")
   52.42 +        ui.list{
   52.43 +          attr = { class = "issues" },
   52.44 +          records = issues or issues_selector:exec(),
   52.45 +          columns = {
   52.46 +            {
   52.47 +              label = _"Issue",
   52.48 +              content = function(record)
   52.49 +                if not param.get("for_area_list", atom.boolean) then
   52.50 +                  ui.field.text{
   52.51 +                    value = record.area.name
   52.52 +                  }
   52.53 +                  slot.put("<br />")
   52.54 +                end
   52.55 +                ui.link{
   52.56 +                  text = _"Issue ##{id}":gsub("#{id}", tostring(record.id)),
   52.57 +                  module = "issue",
   52.58 +                  view = "show",
   52.59 +                  id = record.id
   52.60 +                }
   52.61 +                slot.put("<br />")
   52.62 +                slot.put("<br />")
   52.63 +              end
   52.64 +            },
   52.65 +            {
   52.66 +              label = _"State",
   52.67 +              content = function(record)
   52.68 +                ui.field.issue_state{ value = record.state }
   52.69 +              end
   52.70 +            },
   52.71 +            {
   52.72 +              label = _"Initiatives",
   52.73 +              content = function(record)
   52.74 +                execute.view{
   52.75 +                  module = "initiative",
   52.76 +                  view = "_list",
   52.77 +                  params = {
   52.78 +                    issue = record,
   52.79 +                    initiatives_selector = record:get_reference_selector("initiatives"),
   52.80 +                    highlight_string = highlight_string,
   52.81 +                    limit = 3
   52.82 +                  }
   52.83 +                }
   52.84 +              end
   52.85 +            },
   52.86 +          }
   52.87 +        }
   52.88 +    
   52.89 +      end
   52.90 +    }
   52.91 +  end
   52.92 +}
   52.93 \ No newline at end of file
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/app/main/issue/list.lua	Wed Nov 18 12:00:00 2009 +0100
    53.3 @@ -0,0 +1,7 @@
    53.4 +local issues_selector = Issue:new_selector()
    53.5 +
    53.6 +execute.view{
    53.7 +  module = "issue",
    53.8 +  view = "_list",
    53.9 +  params = { issues_selector = issues_selector }
   53.10 +}
   53.11 \ No newline at end of file
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/app/main/issue/show.lua	Wed Nov 18 12:00:00 2009 +0100
    54.3 @@ -0,0 +1,110 @@
    54.4 +local issue = Issue:by_id(param.get_id())
    54.5 +
    54.6 +slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(issue.id) .. '.rss" />')
    54.7 +
    54.8 +slot.select("path", function()
    54.9 +  ui.link{
   54.10 +    content = _"Area '#{name}'":gsub("#{name}", issue.area.name),
   54.11 +    module = "area",
   54.12 +    view = "show",
   54.13 +    id = issue.area.id
   54.14 +  }
   54.15 +end)
   54.16 +
   54.17 +slot.put_into("title", encode.html(_"Issue ##{id} (#{policy_name})":gsub("#{id}", issue.id):gsub("#{policy_name}", issue.policy.name)))
   54.18 +
   54.19 +slot.select("actions", function()
   54.20 +  if not issue.closed then
   54.21 +    ui.link{
   54.22 +      content = function()
   54.23 +        ui.image{ static = "icons/16/table_go.png" }
   54.24 +        slot.put(_"Delegate")
   54.25 +      end,
   54.26 +      module = "delegation",
   54.27 +      view = "new",
   54.28 +      params = { issue_id = issue.id }
   54.29 +    }
   54.30 +  end
   54.31 +
   54.32 +  ui.twitter("http://example.com/t" .. tostring(issue.id))
   54.33 +
   54.34 +end)
   54.35 +
   54.36 +execute.view{
   54.37 +  module = "interest",
   54.38 +  view = "_show_box",
   54.39 +  params = { issue = issue }
   54.40 +}
   54.41 +
   54.42 +execute.view{
   54.43 +  module = "delegation",
   54.44 +  view = "_show_box",
   54.45 +  params = { issue_id = issue.id }
   54.46 +}
   54.47 +
   54.48 +ui.tabs{
   54.49 +  {
   54.50 +    name = "initiatives",
   54.51 +    label = _"Initiatives",
   54.52 +    content = function()
   54.53 +      execute.view{
   54.54 +        module = "initiative",
   54.55 +        view = "_list",
   54.56 +        params = { 
   54.57 +          issue = issue,
   54.58 +          initiatives_selector = issue:get_reference_selector("initiatives")
   54.59 +        }
   54.60 +      }
   54.61 +      slot.put("<br />")
   54.62 +      if not issue.frozen and not issue.closed then
   54.63 +        ui.link{
   54.64 +          attr = { class = "action" },
   54.65 +          content = function()
   54.66 +            ui.image{ static = "icons/16/script_add.png" }
   54.67 +            slot.put(_"Add new initiative to issue")
   54.68 +          end,
   54.69 +          module = "initiative",
   54.70 +          view = "new",
   54.71 +          params = { issue_id = issue.id }
   54.72 +        }
   54.73 +      end
   54.74 +    end
   54.75 +  },
   54.76 +--[[  {
   54.77 +    name = "voting_requests",
   54.78 +    label = _"Voting requests",
   54.79 +    content = function()
   54.80 +      execute.view{
   54.81 +        module = "issue_voting_request",
   54.82 +        view = "_list",
   54.83 +        params = { issue = issue }
   54.84 +      }
   54.85 +    end
   54.86 +  },
   54.87 +--]]
   54.88 +  {
   54.89 +    name = "details",
   54.90 +    label = _"Details",
   54.91 +    content = function()
   54.92 +      ui.form{
   54.93 +        record = issue,
   54.94 +        readonly = true,
   54.95 +        attr = { class = "vertical" },
   54.96 +        content = function()
   54.97 +          trace.debug(issue.created)
   54.98 +          ui.field.text{ label = _"State", name = "state" }
   54.99 +          ui.field.timestamp{ label = _"Created at", name = "created" }
  54.100 +          ui.field.timestamp{ label = _"Accepted", name = "accepted" }
  54.101 +          ui.field.timestamp{ label = _"Half frozen", name = "half_frozen" }
  54.102 +          ui.field.timestamp{ label = _"Fully frozen", name = "fully_frozen" }
  54.103 +          ui.field.timestamp{ label = _"Closed", name = "closed" }
  54.104 +          ui.field.potential_issue_weight{ label = _"Potential weight", name = "potential_weight" }
  54.105 +          ui.field.vote_now{ label = _"Vote now", name = "vote_now" }
  54.106 +          ui.field.vote_later{ label = _"Vote later", name = "vote_later" }
  54.107 +        end
  54.108 +      }
  54.109 +    end
  54.110 +  },
  54.111 +}
  54.112 +
  54.113 +
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/app/main/issue/show.rss.lua	Wed Nov 18 12:00:00 2009 +0100
    55.3 @@ -0,0 +1,35 @@
    55.4 +slot.set_layout("rss")
    55.5 +
    55.6 +local function rss_channel(channel)
    55.7 +  for key, val in pairs(channel) do
    55.8 +    slot.put("<", key, ">", encode.html(val), "</", key, ">")
    55.9 +  end
   55.10 +end
   55.11 +
   55.12 +local function rss_item(item)
   55.13 +  slot.put("<item>")
   55.14 +  for key, val in pairs(item) do
   55.15 +    slot.put("<", key, ">", encode.html(val), "</", key, ">")
   55.16 +  end
   55.17 +  slot.put("</item>")
   55.18 +end
   55.19 +
   55.20 +
   55.21 +local issue = Issue:by_id(param.get_id())
   55.22 +
   55.23 +rss_channel{
   55.24 +  title = issue.area.name .. " :: Issue #" .. tostring(issue.id),
   55.25 +  language = "de",
   55.26 +  pubDate = "Tue, 8 Jul 2008 2:43:19"
   55.27 +}
   55.28 +
   55.29 +for i, initiative in ipairs(issue.initiatives) do
   55.30 +  rss_item{
   55.31 +    title = initiative.name,
   55.32 +    description = initiative.current_draft.content,
   55.33 +    link = "http://localhost/lf/initiative/show/" .. tostring(initiative.id) .. ".html",
   55.34 +    author = initiative.current_draft.author.name,
   55.35 +    guid = "guid",
   55.36 +    pubDate = "Tue, 8 Jul 2008 2:43:19"
   55.37 +  }
   55.38 +end
   55.39 \ No newline at end of file
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/app/main/member/_action/update.lua	Wed Nov 18 12:00:00 2009 +0100
    56.3 @@ -0,0 +1,6 @@
    56.4 +param.update(app.session.member, "name")
    56.5 +
    56.6 +app.session.member:save()
    56.7 +
    56.8 +
    56.9 +slot.put_into("notice", _"Your page has been updated")
   56.10 \ No newline at end of file
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/app/main/member/_action/update_avatar.lua	Wed Nov 18 12:00:00 2009 +0100
    57.3 @@ -0,0 +1,20 @@
    57.4 +local data = param.get("avatar")
    57.5 +
    57.6 +if param.get("avatar_delete", atom.boolean) then
    57.7 +  app.session.member.avatar = nil
    57.8 +  app.session.member:save()
    57.9 +  slot.put_into("notice", _"Avatar has been deleted")
   57.10 +  return
   57.11 +end
   57.12 +
   57.13 +local data, err, status = os.pfilter(data, "convert", "-", "-thumbnail", "48x48", "-")
   57.14 +
   57.15 +if status ~= 0 or data == nil then
   57.16 + error("error while converting image")
   57.17 +end
   57.18 +
   57.19 +if data and #data > 0 then
   57.20 +  db:query{ 'UPDATE member SET avatar = $ WHERE id = ?', { db:quote_binary(data) }, app.session.member.id }
   57.21 +end
   57.22 +
   57.23 +slot.put_into("notice", _"Avatar has been updated")
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/app/main/member/_list.lua	Wed Nov 18 12:00:00 2009 +0100
    58.3 @@ -0,0 +1,81 @@
    58.4 +local members_selector = param.get("members_selector", "table")
    58.5 +
    58.6 +ui.paginate{
    58.7 +  selector = members_selector,
    58.8 +  content = function() 
    58.9 +    ui.list{
   58.10 +      records = members_selector:exec(),
   58.11 +      columns = {
   58.12 +        {
   58.13 +          content    = function(record)
   58.14 +            ui.image{
   58.15 +              attr = { style="height: 24px;" },
   58.16 +              module = "member",
   58.17 +              view = "avatar",
   58.18 +              extension = "jpg",
   58.19 +              id = record.id
   58.20 +            }
   58.21 +          end
   58.22 +        },
   58.23 +        {
   58.24 +          label = _"Login",
   58.25 +          content    = function(record)
   58.26 +            ui.link{
   58.27 +              text   = record.login,
   58.28 +              module = "member",
   58.29 +              view   = "show",
   58.30 +              id     = record.id
   58.31 +            }
   58.32 +          end
   58.33 +        },
   58.34 +        {
   58.35 +          label = _"Name",
   58.36 +          content = function(record)
   58.37 +            ui.link{
   58.38 +              content = function()
   58.39 +                util.put_highlighted_string(record.name)
   58.40 +              end,
   58.41 +              module = "member",
   58.42 +              view   = "show",
   58.43 +              id     = record.id
   58.44 +            }
   58.45 +          end
   58.46 +        },
   58.47 +        {
   58.48 +          label = _"Ident number",
   58.49 +          name = "ident_number"
   58.50 +        },
   58.51 +        {
   58.52 +          label = _"Admin?",
   58.53 +          name = "admin"
   58.54 +        },
   58.55 +        {
   58.56 +          label = "Locked?",
   58.57 +          content = function(record)
   58.58 +            ui.field.boolean{ value = record.locked }
   58.59 +          end
   58.60 +        },
   58.61 +        {
   58.62 +         content    = function(record)
   58.63 +            ui.link{
   58.64 +              attr   = { class = "action" },
   58.65 +              text   = _"Add to my contacts",
   58.66 +              module = "contact",
   58.67 +              action = "add_member",
   58.68 +              id     = record.id,
   58.69 +              routing = {
   58.70 +                default = {
   58.71 +                  mode = "redirect",
   58.72 +                  module = request.get_module(),
   58.73 +                  view = request.get_view(),
   58.74 +                  id = param.get_id_cgi(),
   58.75 +                  params = param.get_all_cgi()
   58.76 +                }
   58.77 +              }
   58.78 +            }
   58.79 +          end
   58.80 +        }
   58.81 +      }
   58.82 +    }
   58.83 +  end
   58.84 +}
   58.85 \ No newline at end of file
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/app/main/member/_show.lua	Wed Nov 18 12:00:00 2009 +0100
    59.3 @@ -0,0 +1,84 @@
    59.4 +local member = param.get("member", "table")
    59.5 +
    59.6 +ui.form{
    59.7 +  attr = { class = "vertical" },
    59.8 +  record = member,
    59.9 +  readonly = true,
   59.10 +  content = function()
   59.11 +    ui.field.text{    label = _"Login",        name = "login" }
   59.12 +    ui.field.text{    label = _"Name",         name = "name" }
   59.13 +    ui.field.boolean{ label = _"Admin?",       name = "admin" }
   59.14 +    ui.field.boolean{ label = _"Locked?",      name = "locked" }
   59.15 +    ui.field.text{    label = _"Ident number", name = "ident_number" }
   59.16 +    ui.submit{        text  = _"Save" }
   59.17 +  end
   59.18 +}
   59.19 +
   59.20 +ui.tabs{
   59.21 +  {
   59.22 +    name = "areas",
   59.23 +    label = _"Areas",
   59.24 +    content = function()
   59.25 +      execute.view{
   59.26 +        module = "area",
   59.27 +        view = "_list",
   59.28 +        params = { areas_selector = member:get_reference_selector("areas") }
   59.29 +      }
   59.30 +    end
   59.31 +  },
   59.32 +  {
   59.33 +    name = "issues",
   59.34 +    label = _"Issues",
   59.35 +    content = function()
   59.36 +      execute.view{
   59.37 +        module = "issue",
   59.38 +        view = "_list",
   59.39 +        params = { issues_selector = member:get_reference_selector("issues") }
   59.40 +      }
   59.41 +    end
   59.42 +  },
   59.43 +  {
   59.44 +    name = "initiatives",
   59.45 +    label = _"Initiatives",
   59.46 +    content = function()
   59.47 +      execute.view{
   59.48 +        module = "initiative",
   59.49 +        view = "_list",
   59.50 +        params = { initiatives_selector = member:get_reference_selector("supported_initiatives") }
   59.51 +      }
   59.52 +    end
   59.53 +  },
   59.54 +  {
   59.55 +    name = "incoming_delegations",
   59.56 +    label = _"Incoming delegations",
   59.57 +    content = function()
   59.58 +      execute.view{
   59.59 +        module = "delegation",
   59.60 +        view = "_list",
   59.61 +        params = { selector = member:get_reference_selector("incoming_delegations") }
   59.62 +      }
   59.63 +    end
   59.64 +  },
   59.65 +  {
   59.66 +    name = "outgoing_delegations",
   59.67 +    label = _"Outgoing delegations",
   59.68 +    content = function()
   59.69 +      execute.view{
   59.70 +        module = "delegation",
   59.71 +        view = "_list",
   59.72 +        params = { selector = member:get_reference_selector("outgoing_delegations") }
   59.73 +      }
   59.74 +    end
   59.75 +  },
   59.76 +  {
   59.77 +    name = "contacts",
   59.78 +    label = _"Published contacts",
   59.79 +    content = function()
   59.80 +      execute.view{
   59.81 +        module = "member",
   59.82 +        view = "_list",
   59.83 +        params = { members_selector = member:get_reference_selector("saved_members"):add_where("public") }
   59.84 +      }
   59.85 +    end
   59.86 +  },
   59.87 +}
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/app/main/member/avatar.lua	Wed Nov 18 12:00:00 2009 +0100
    60.3 @@ -0,0 +1,15 @@
    60.4 +local record = Member:by_id(param.get_id())
    60.5 +
    60.6 +if false and (not record or not record.avatar) then
    60.7 +  print('Location: ' .. encode.url{ static = 'no_image.png' } .. '\n\n')
    60.8 +  exit()
    60.9 +end
   60.10 +
   60.11 +print('Content-type: image/jpg\n')
   60.12 +
   60.13 +if record then
   60.14 +  io.stdout:write(record.avatar)
   60.15 +else
   60.16 +end
   60.17 +
   60.18 +exit()
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/app/main/member/edit.lua	Wed Nov 18 12:00:00 2009 +0100
    61.3 @@ -0,0 +1,30 @@
    61.4 +slot.put_into("title", _"Edit my page")
    61.5 +
    61.6 +slot.select("actions", function()
    61.7 +  ui.link{
    61.8 +    content = function()
    61.9 +        ui.image{ static = "icons/16/cancel.png" }
   61.10 +        slot.put(_"Cancel")
   61.11 +    end,
   61.12 +    module = "index",
   61.13 +    view = "index"
   61.14 +  }
   61.15 +end)
   61.16 +
   61.17 +ui.form{
   61.18 +  record = app.session.member,
   61.19 +  attr = { class = "vertical" },
   61.20 +  module = "member",
   61.21 +  action = "update",
   61.22 +  routing = {
   61.23 +    ok = {
   61.24 +      mode = "redirect",
   61.25 +      module = "index",
   61.26 +      view = "index"
   61.27 +    }
   61.28 +  },
   61.29 +  content = function()
   61.30 +    ui.field.text{ label = _"Name", name = "name" }
   61.31 +    ui.submit{ value = _"Save" }
   61.32 +  end
   61.33 +}
   61.34 \ No newline at end of file
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/app/main/member/edit_avatar.lua	Wed Nov 18 12:00:00 2009 +0100
    62.3 @@ -0,0 +1,33 @@
    62.4 +slot.put_into("title", _"Upload avatar")
    62.5 +
    62.6 +slot.select("actions", function()
    62.7 +  ui.link{
    62.8 +    content = function()
    62.9 +        ui.image{ static = "icons/16/cancel.png" }
   62.10 +        slot.put(_"Cancel")
   62.11 +    end,
   62.12 +    module = "index",
   62.13 +    view = "index"
   62.14 +  }
   62.15 +end)
   62.16 +
   62.17 +ui.form{
   62.18 +  record = app.session.member,
   62.19 +  attr = { 
   62.20 +    class = "vertical",
   62.21 +    enctype = 'multipart/form-data'
   62.22 +  },
   62.23 +  module = "member",
   62.24 +  action = "update_avatar",
   62.25 +  routing = {
   62.26 +    ok = {
   62.27 +      mode = "redirect",
   62.28 +      module = "index",
   62.29 +      view = "index"
   62.30 +    }
   62.31 +  },
   62.32 +  content = function()
   62.33 +    ui.field.image{ field_name = "avatar", label = _"Avatar" }
   62.34 +    ui.submit{ value = _"Save" }
   62.35 +  end
   62.36 +}
   62.37 \ No newline at end of file
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/app/main/member/list.lua	Wed Nov 18 12:00:00 2009 +0100
    63.3 @@ -0,0 +1,7 @@
    63.4 +slot.put_into("title", _"Member list")
    63.5 +
    63.6 +execute.view{
    63.7 +  module = "member",
    63.8 +  view = "_list",
    63.9 +  params = { members_selector = Member:new_selector():add_order_by("login") }
   63.10 +}
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/app/main/member/show.lua	Wed Nov 18 12:00:00 2009 +0100
    64.3 @@ -0,0 +1,37 @@
    64.4 +local member = Member:by_id(param.get_id())
    64.5 +
    64.6 +slot.select("title", function()
    64.7 +  ui.image{
    64.8 +    attr = { class = "avatar" },
    64.9 +    module = "member",
   64.10 +    view = "avatar",
   64.11 +    extension = "jpg",
   64.12 +    id = member.id
   64.13 +  }
   64.14 +end)
   64.15 +
   64.16 +slot.put_into("title", encode.html(_"Member '#{member}'":gsub("#{member}", member.name)))
   64.17 +
   64.18 +if member.id == app.session.member.id then
   64.19 +  slot.put_into("actions", _"That's me!")
   64.20 +else
   64.21 +  slot.select("actions", function()
   64.22 +    ui.link{
   64.23 +      content = function()
   64.24 +        ui.image{ static = "icons/16/book_add.png" }
   64.25 +        slot.put(encode.html(_"Add to my contacts"))
   64.26 +      end,
   64.27 +      module  = "contact",
   64.28 +      action  = "add_member",
   64.29 +      id      = member.id
   64.30 +    }
   64.31 +  end)
   64.32 +end
   64.33 +
   64.34 +
   64.35 +execute.view{
   64.36 +  module = "member",
   64.37 +  view = "_show",
   64.38 +  params = { member = member }
   64.39 +}
   64.40 +
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/app/main/membership/_action/update.lua	Wed Nov 18 12:00:00 2009 +0100
    65.3 @@ -0,0 +1,28 @@
    65.4 +local area_id = assert(param.get("area_id", atom.integer), "no area id given")
    65.5 +local membership = Membership:by_pk(area_id, app.session.member.id)
    65.6 +
    65.7 +if param.get("delete", atom.boolean) then
    65.8 +  if membership then
    65.9 +    membership:destroy()
   65.10 +    slot.put_into("notice", _"Membership removed")
   65.11 +  else
   65.12 +    slot.put_into("notice", _"Membership not existant")
   65.13 +  end
   65.14 +  return
   65.15 +end
   65.16 +
   65.17 +if not membership then
   65.18 +  membership = Membership:new()
   65.19 +  membership.area_id    = area_id
   65.20 +  membership.member_id  = app.session.member_id
   65.21 +  membership.autoreject = false
   65.22 +end
   65.23 +
   65.24 +local autoreject = param.get("autoreject", atom.boolean)
   65.25 +if autoreject ~= nil then
   65.26 +  membership.autoreject = autoreject
   65.27 +end
   65.28 +
   65.29 +membership:save()
   65.30 +
   65.31 +slot.put_into("notice", _"Membership updated")
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/app/main/membership/_show_box.lua	Wed Nov 18 12:00:00 2009 +0100
    66.3 @@ -0,0 +1,69 @@
    66.4 +local area = param.get("area", "table")
    66.5 +
    66.6 +slot.select("interest", function()
    66.7 +  local membership = Membership:by_pk(area.id, app.session.member.id)
    66.8 +
    66.9 +  ui.container{
   66.10 +    attr = { 
   66.11 +      class = "head",
   66.12 +      onclick = "document.getElementById('interest_content').style.display = 'block';"
   66.13 +    },
   66.14 +    content = function()
   66.15 +      if membership then
   66.16 +        ui.field.text{ value = _"You are member. [more]" }
   66.17 +      else
   66.18 +        ui.field.text{ value = _"You are not a member. [more]" }
   66.19 +      end
   66.20 +    end
   66.21 +  }
   66.22 +
   66.23 +  ui.container{
   66.24 +    attr = { class = "content", id = "interest_content" },
   66.25 +    content = function()
   66.26 +      if membership then
   66.27 +        ui.link{
   66.28 +          content = _"Remove my membership",
   66.29 +          module = "membership",
   66.30 +          action = "update",
   66.31 +          params = { area_id = area.id, delete = true },
   66.32 +          routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
   66.33 +        }
   66.34 +        if membership.autoreject then
   66.35 +          ui.field.text{ value = _"Autoreject is on." }
   66.36 +          ui.link{
   66.37 +            content = _"Remove autoreject",
   66.38 +            module = "membership",
   66.39 +            action = "update",
   66.40 +            params = { area_id = area.id, autoreject = false },
   66.41 +            routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
   66.42 +          }
   66.43 +        else
   66.44 +          ui.field.text{ value = _"Autoreject is off." }
   66.45 +          ui.link{
   66.46 +            content = _"Set autoreject",
   66.47 +            module = "membership",
   66.48 +            action = "update",
   66.49 +            params = { area_id = area.id, autoreject = true },
   66.50 +            routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
   66.51 +          }
   66.52 +        end
   66.53 +      else
   66.54 +        ui.link{
   66.55 +          content = _"Add my membership to this area",
   66.56 +          module = "membership",
   66.57 +          action = "update",
   66.58 +          params = { area_id = area.id },
   66.59 +          routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
   66.60 +        }
   66.61 +      end
   66.62 +        ui.container{
   66.63 +          attr = {
   66.64 +            class = "head",
   66.65 +            style = "cursor: pointer;",
   66.66 +            onclick = "document.getElementById('interest_content').style.display = 'none';"
   66.67 +          },
   66.68 +          content = _"Click here to close."
   66.69 +        }
   66.70 +    end
   66.71 +  }
   66.72 +end)
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/app/main/opinion/_action/update.lua	Wed Nov 18 12:00:00 2009 +0100
    67.3 @@ -0,0 +1,33 @@
    67.4 +local member_id = app.session.member.id
    67.5 +
    67.6 +local suggestion_id = param.get("suggestion_id", atom.integer)
    67.7 +
    67.8 +local opinion = Opinion:by_pk(member_id, suggestion_id)
    67.9 +
   67.10 +if opinion and param.get("delete") then
   67.11 +  opinion:destroy()
   67.12 +  slot.put_into("notice", _"Your opinion has been updated")
   67.13 +  return
   67.14 +end
   67.15 +
   67.16 +if not opinion then
   67.17 +  opinion = Opinion:new()
   67.18 +  opinion.member_id     = member_id
   67.19 +  opinion.suggestion_id = suggestion_id
   67.20 +  opinion.fulfilled     = false
   67.21 +end
   67.22 +
   67.23 +local degree = param.get("degree", atom.number)
   67.24 +local fulfilled = param.get("fulfilled", atom.boolean)
   67.25 +
   67.26 +if degree ~= nil then
   67.27 +  opinion.degree = degree
   67.28 +end
   67.29 +
   67.30 +if fulfilled ~= nil then
   67.31 +  opinion.fulfilled = fulfilled
   67.32 +end
   67.33 +
   67.34 +opinion:save()
   67.35 +
   67.36 +slot.put_into("notice", _"Your opinion has been updated")
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/app/main/opinion/_list.lua	Wed Nov 18 12:00:00 2009 +0100
    68.3 @@ -0,0 +1,23 @@
    68.4 +local opinions_selector = param.get("opinions_selector", "table")
    68.5 +
    68.6 +ui.list{
    68.7 +  records = opinions_selector:exec(),
    68.8 +  columns = {
    68.9 +    {
   68.10 +      label = _"Member login",
   68.11 +      name = "member_login"
   68.12 +    },
   68.13 +    {
   68.14 +      label = _"Member name",
   68.15 +      name = "member_name"
   68.16 +    },
   68.17 +    {
   68.18 +      label = _"Degree",
   68.19 +      name = "degree"
   68.20 +    },
   68.21 +    {
   68.22 +      label = _"Fulfilled",
   68.23 +      name = "fulfilled"
   68.24 +    },
   68.25 +  }
   68.26 +}
   68.27 \ No newline at end of file
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/app/main/suggestion/_action/add.lua	Wed Nov 18 12:00:00 2009 +0100
    69.3 @@ -0,0 +1,20 @@
    69.4 +db:query("BEGIN")
    69.5 +
    69.6 +local suggestion = Suggestion:new()
    69.7 +
    69.8 +suggestion.author_id = app.session.member.id
    69.9 +param.update(suggestion, "name", "description", "initiative_id")
   69.10 +suggestion:save()
   69.11 +
   69.12 +local opinion = Opinion:new()
   69.13 +
   69.14 +opinion.suggestion_id = suggestion.id
   69.15 +opinion.member_id     = app.session.member.id
   69.16 +opinion.degree        = param.get("degree", atom.integer)
   69.17 +opinion.fulfilled     = false
   69.18 +
   69.19 +opinion:save()
   69.20 +
   69.21 +db:query("COMMIT")
   69.22 +
   69.23 +slot.put_into("notice", _"Your suggestion has been added")
   69.24 \ No newline at end of file
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/app/main/suggestion/_list.lua	Wed Nov 18 12:00:00 2009 +0100
    70.3 @@ -0,0 +1,185 @@
    70.4 +local suggestions_selector = param.get("suggestions_selector", "table")
    70.5 +
    70.6 +ui.paginate{
    70.7 +  selector = suggestions_selector,
    70.8 +  content = function()
    70.9 +    ui.list{
   70.10 +      records = suggestions_selector:exec(),
   70.11 +      columns = {
   70.12 +        {
   70.13 +          label = _"Name",
   70.14 +          content = function(record)
   70.15 +            ui.link{
   70.16 +              text = record.name,
   70.17 +              module = "suggestion",
   70.18 +              view = "show",
   70.19 +              id = record.id
   70.20 +            }
   70.21 +          end
   70.22 +        },
   70.23 +        {
   70.24 +          label = _"Support",
   70.25 +          content = function(record)
   70.26 +            if record.minus2_unfulfilled_count then
   70.27 +              local max_value = record.initiative.supporter_count
   70.28 +              ui.bargraph{
   70.29 +                max_value = max_value,
   70.30 +                width = 50,
   70.31 +                bars = {
   70.32 +                  { color = "#ddd", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count - record.minus2_fulfilled_count - record.minus1_fulfilled_count },
   70.33 +                  { color = "#f88", value = record.minus1_unfulfilled_count + record.minus1_fulfilled_count },
   70.34 +                  { color = "#a00", value = record.minus2_unfulfilled_count + record.minus2_fulfilled_count },
   70.35 +                  { color = "#0a0", value = record.plus2_unfulfilled_count + record.plus2_fulfilled_count },
   70.36 +                  { color = "#8f8", value = record.plus1_unfulfilled_count + record.plus1_fulfilled_count },
   70.37 +                  { color = "#ddd", value = max_value - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count - record.plus1_fulfilled_count - record.plus2_fulfilled_count },
   70.38 +                }
   70.39 +              }
   70.40 +            end
   70.41 +          end
   70.42 +        },
   70.43 +        {
   70.44 +          content = function(record)
   70.45 +            local degree
   70.46 +            local opinion = Opinion:by_pk(app.session.member.id, record.id)
   70.47 +            if opinion then
   70.48 +              degree = opinion.degree
   70.49 +            end
   70.50 +            ui.link{
   70.51 +              attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
   70.52 +              text = _"must not",
   70.53 +              module = "opinion",
   70.54 +              action = "update",
   70.55 +              routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
   70.56 +              params = {
   70.57 +                suggestion_id = record.id,
   70.58 +                degree = -2
   70.59 +              }
   70.60 +            }
   70.61 +            ui.link{
   70.62 +              attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
   70.63 +              text = _"should not",
   70.64 +              module = "opinion",
   70.65 +              action = "update",
   70.66 +              routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
   70.67 +              params = {
   70.68 +                suggestion_id = record.id,
   70.69 +                degree = -1
   70.70 +              }
   70.71 +            }
   70.72 +            ui.link{
   70.73 +              attr = { class = "action" .. (degree == nil and " active" or "") },
   70.74 +              text = _"neutral",
   70.75 +              module = "opinion",
   70.76 +              action = "update",
   70.77 +              routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
   70.78 +              params = {
   70.79 +                suggestion_id = record.id,
   70.80 +                delete = true
   70.81 +              }
   70.82 +            }
   70.83 +            ui.link{
   70.84 +              attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
   70.85 +              text = _"should",
   70.86 +              module = "opinion",
   70.87 +              action = "update",
   70.88 +              routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
   70.89 +              params = {
   70.90 +                suggestion_id = record.id,
   70.91 +                degree = 1
   70.92 +              }
   70.93 +            }
   70.94 +            ui.link{
   70.95 +              attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
   70.96 +              text = _"must",
   70.97 +              module = "opinion",
   70.98 +              action = "update",
   70.99 +              routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  70.100 +              params = {
  70.101 +                suggestion_id = record.id,
  70.102 +                degree = 2
  70.103 +              }
  70.104 +            }
  70.105 +          end
  70.106 +        },
  70.107 +        {
  70.108 +          label = _"Not fullfilled",
  70.109 +          content = function(record)
  70.110 +            if record.minus2_unfulfilled_count then
  70.111 +              local max_value = record.initiative.supporter_count
  70.112 +              ui.bargraph{
  70.113 +                max_value = max_value,
  70.114 +                width = 50,
  70.115 +                bars = {
  70.116 +                  { color = "#ddd", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count },
  70.117 +                  { color = "#f88", value = record.minus1_unfulfilled_count },
  70.118 +                  { color = "#a00", value = record.minus2_unfulfilled_count },
  70.119 +                  { color = "#0a0", value = record.plus2_unfulfilled_count },
  70.120 +                  { color = "#8f8", value = record.plus1_unfulfilled_count },
  70.121 +                  { color = "#ddd", value = max_value - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count },
  70.122 +                }
  70.123 +              }
  70.124 +            end
  70.125 +          end
  70.126 +        },
  70.127 +        {
  70.128 +          label = _"Fullfilled",
  70.129 +          content = function(record)
  70.130 +            if record.minus2_fulfilled_count then
  70.131 +              local max_value = record.initiative.supporter_count
  70.132 +              ui.bargraph{
  70.133 +                max_value = max_value,
  70.134 +                width = 50,
  70.135 +                bars = {
  70.136 +                  { color = "#ddd", value = max_value - record.minus2_fulfilled_count - record.minus1_fulfilled_count },
  70.137 +                  { color = "#f88", value = record.minus1_fulfilled_count },
  70.138 +                  { color = "#a00", value = record.minus2_fulfilled_count },
  70.139 +                  { color = "#0a0", value = record.plus2_fulfilled_count },
  70.140 +                  { color = "#8f8", value = record.plus1_fulfilled_count },
  70.141 +                  { color = "#ddd", value = max_value - record.plus1_fulfilled_count - record.plus2_fulfilled_count },
  70.142 +                }
  70.143 +              }
  70.144 +            end
  70.145 +          end
  70.146 +        },
  70.147 +        {
  70.148 +          content = function(record)
  70.149 +            local degree
  70.150 +            local opinion = Opinion:by_pk(app.session.member.id, record.id)
  70.151 +            if opinion then
  70.152 +              degree = opinion.degree
  70.153 +            end
  70.154 +            if opinion then
  70.155 +              if not opinion.fulfilled then
  70.156 +                ui.image{ static = "icons/16/cross.png" }
  70.157 +                ui.link{
  70.158 +                  attr = { class = "action" },
  70.159 +                  text = _"set fulfilled",
  70.160 +                  module = "opinion",
  70.161 +                  action = "update",
  70.162 +                  routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  70.163 +                  params = {
  70.164 +                    suggestion_id = record.id,
  70.165 +                    fulfilled = true
  70.166 +                  }
  70.167 +                }
  70.168 +              else
  70.169 +                ui.image{ static = "icons/16/tick.png" }
  70.170 +                ui.link{
  70.171 +                  attr = { class = "action" },
  70.172 +                  text = _"remove fulfilled",
  70.173 +                  module = "opinion",
  70.174 +                  action = "update",
  70.175 +                  routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
  70.176 +                  params = {
  70.177 +                    suggestion_id = record.id,
  70.178 +                    fulfilled = false
  70.179 +                  }
  70.180 +                }
  70.181 +              end
  70.182 +            end
  70.183 +          end
  70.184 +        },
  70.185 +      }
  70.186 +    }
  70.187 +  end
  70.188 +}
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/app/main/suggestion/show.lua	Wed Nov 18 12:00:00 2009 +0100
    71.3 @@ -0,0 +1,32 @@
    71.4 +local suggestion = Suggestion:by_id(param.get_id())
    71.5 +
    71.6 +slot.put_into("title", encode.html(_"Suggestion for initiative: '#{name}'":gsub("#{name}", suggestion.initiative.name) ))
    71.7 +
    71.8 +ui.form{
    71.9 +  attr = { class = "vertical" },
   71.10 +  record = suggestion,
   71.11 +  readonly = true,
   71.12 +  content = function()
   71.13 +    ui.field.text{ label = _"Name",        name = "name" }
   71.14 +    ui.field.text{ label = _"Description", name = "description" }
   71.15 +  end
   71.16 +}
   71.17 +
   71.18 +execute.view{
   71.19 +  module = "suggestion",
   71.20 +  view = "_list",
   71.21 +  params = { suggestions_selector = Suggestion:new_selector():add_where{ "id = ?", suggestion.id } }
   71.22 +}
   71.23 +
   71.24 +execute.view{
   71.25 +  module = "opinion",
   71.26 +  view = "_list",
   71.27 +  params = { 
   71.28 +    opinions_selector = Opinion:new_selector()
   71.29 +      :add_field("member.login", "member_login")
   71.30 +      :add_field("member.name", "member_name")
   71.31 +      :add_where{ "suggestion_id = ?", suggestion.id }
   71.32 +      :join("member", nil, "member.id = opinion.member_id")
   71.33 +      :add_order_by("member.id DESC")
   71.34 +  }
   71.35 +}
   71.36 \ No newline at end of file
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/app/main/supporter/_show_box.lua	Wed Nov 18 12:00:00 2009 +0100
    72.3 @@ -0,0 +1,55 @@
    72.4 +    
    72.5 +
    72.6 +slot.select("support", function()
    72.7 +
    72.8 +  local initiative = param.get("initiative", "table")
    72.9 +
   72.10 +  if not initiative.issue.frozen and not initiative.issue.closed then
   72.11 +
   72.12 +    local supported = Supporter:by_pk(initiative.id, app.session.member.id) and true or false
   72.13 +
   72.14 +    local text
   72.15 +    if supported then
   72.16 +      text = _"Direct supporter [change]"
   72.17 +    else
   72.18 +      text = _"No supporter [change]"
   72.19 +    end
   72.20 +    ui.container{
   72.21 +      attr = {
   72.22 +        class = "head",
   72.23 +        style = "cursor: pointer;",
   72.24 +        onclick = "document.getElementById('support_content').style.display = 'block';"
   72.25 +      },
   72.26 +      content = text
   72.27 +    }
   72.28 +
   72.29 +
   72.30 +    ui.container{
   72.31 +      attr = { class = "content", id = "support_content" },
   72.32 +      content = function()
   72.33 +        if supported then
   72.34 +          ui.link{
   72.35 +            content = function()
   72.36 +              ui.image{ static = "icons/16/thumb_down_red.png" }
   72.37 +              slot.put(_"Remove my support from this initiative")
   72.38 +            end,
   72.39 +            module = "initiative",
   72.40 +            action = "remove_support",
   72.41 +            id = initiative.id
   72.42 +          }
   72.43 +        else
   72.44 +          ui.link{
   72.45 +            content = function()
   72.46 +              ui.image{ static = "icons/16/thumb_up_green.png" }
   72.47 +              slot.put(_"Support this initiative")
   72.48 +            end,
   72.49 +            module = "initiative",
   72.50 +            action = "add_support",
   72.51 +            id = initiative.id
   72.52 +          }
   72.53 +        end
   72.54 +      end
   72.55 +    }
   72.56 +  end
   72.57 +
   72.58 +end)
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/config/default.lua	Wed Nov 18 12:00:00 2009 +0100
    73.3 @@ -0,0 +1,48 @@
    73.4 +config.app_name = "LiquidFeedback"
    73.5 +config.app_version = "alpha1"
    73.6 +
    73.7 +config.app_title = config.app_name .. " (" .. request.get_config_name() .. " environment)"
    73.8 +
    73.9 +config.app_service_provider = "Snake Oil<br/>10000 Berlin<br/>Germany"
   73.10 +
   73.11 +-- uncomment the following two lines to use C implementations of chosen
   73.12 +-- functions and to disable garbage collection during the request, to
   73.13 +-- increase speed:
   73.14 +--
   73.15 +-- require 'webmcp_accelerator'
   73.16 +-- collectgarbage("stop")
   73.17 +
   73.18 +-- open and set default database handle
   73.19 +db = assert(mondelefant.connect{
   73.20 +  engine='postgresql',
   73.21 +  dbname='liquid_feedback'
   73.22 +})
   73.23 +at_exit(function() 
   73.24 +  db:close()
   73.25 +end)
   73.26 +function mondelefant.class_prototype:get_db_conn() return db end
   73.27 +
   73.28 +-- enable output of SQL commands in trace system
   73.29 +function db:sql_tracer(command)
   73.30 +  return function(error_info)
   73.31 +    local error_info = error_info or {}
   73.32 +    trace.sql{ command = command, error_position = error_info.position }
   73.33 +  end
   73.34 +end
   73.35 +
   73.36 +-- 'request.get_relative_baseurl()' should be replaced by the absolute
   73.37 +-- base URL of the application, as otherwise HTTP redirects will not be
   73.38 +-- standard compliant
   73.39 +request.set_absolute_baseurl(request.get_relative_baseurl())
   73.40 +
   73.41 +
   73.42 +
   73.43 +
   73.44 +-- get record by id
   73.45 +function mondelefant.class_prototype:by_id(id)
   73.46 +  local selector = self:new_selector()
   73.47 +  selector:add_where{ 'id = ?', id }
   73.48 +  selector:optional_object_mode()
   73.49 +  return selector:exec()
   73.50 +end
   73.51 +
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/config/development.lua	Wed Nov 18 12:00:00 2009 +0100
    74.3 @@ -0,0 +1,2 @@
    74.4 +execute.config("default")
    74.5 +
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/config/testing.lua	Wed Nov 18 12:00:00 2009 +0100
    75.3 @@ -0,0 +1,6 @@
    75.4 +execute.config("default")
    75.5 +
    75.6 +
    75.7 +
    75.8 +
    75.9 +
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/db/demodata.lua	Wed Nov 18 12:00:00 2009 +0100
    76.3 @@ -0,0 +1,102 @@
    76.4 +#!/usr/bin/env lua
    76.5 +
    76.6 +member_count = 10000
    76.7 +area_count = 24
    76.8 +issue_count = 1000
    76.9 +policy_count = 3  -- do not change
   76.10 +
   76.11 +function write(...)
   76.12 +  io.stdout:write(...)
   76.13 +end
   76.14 +function writeln(...)
   76.15 +  write(...)
   76.16 +  write("\n")
   76.17 +end
   76.18 +
   76.19 +math.randomseed(os.time())
   76.20 +
   76.21 +writeln('BEGIN;')
   76.22 +
   76.23 +for i = 2, member_count do
   76.24 +  writeln('INSERT INTO "member" ("login", "name", "ident_number") VALUES (', "'testuser", i, "', 'Benutzer #", i, "', 'TEST", i, "');")
   76.25 +end
   76.26 +
   76.27 +for i = 1, member_count do
   76.28 +  local is_linked = {}
   76.29 +  while math.random(4) > 1 do
   76.30 +    local k = math.random(member_count)
   76.31 +    if not is_linked[k] then
   76.32 +      local public = math.random(2) == 1 and "TRUE" or "FALSE"
   76.33 +      writeln('INSERT INTO "contact" ("member_id", "other_member_id", "public") VALUES (', i, ", ", k, ", ", public, ");")
   76.34 +      is_linked[k] = true
   76.35 +    end
   76.36 +  end
   76.37 +end
   76.38 +
   76.39 +for i = 2, area_count do
   76.40 +  writeln('INSERT INTO "area" ("name") VALUES (', "'Area #", i, "');")
   76.41 +end
   76.42 +
   76.43 +local memberships = {}
   76.44 +
   76.45 +for i = 1, area_count do
   76.46 +  memberships[i] = {}
   76.47 +  for j = 1, member_count do
   76.48 +    if math.random(4) == 1 then
   76.49 +      memberships[i][j] = true
   76.50 +      local autoreject = math.random(2) == 1 and "TRUE" or "FALSE"
   76.51 +      writeln('INSERT INTO "membership" ("member_id", "area_id", "autoreject") VALUES (', j, ", ", i, ", ", autoreject, ");")
   76.52 +    end
   76.53 +  end
   76.54 +end
   76.55 +
   76.56 +do
   76.57 +  local issue_initiative_count = {}
   76.58 +  local initiative_draft_count = {}
   76.59 +  local initiative_idx = 1
   76.60 +  local draft_count = 0
   76.61 +  for i = 1, issue_count do
   76.62 +    local area = math.random(area_count)
   76.63 +    writeln('INSERT INTO "issue" ("area_id", "policy_id") VALUES (', area, ", ", math.random(policy_count), ");")
   76.64 +    issue_initiative_count[i] = 1
   76.65 +    while math.random(3) > 1 do
   76.66 +      issue_initiative_count[i] = issue_initiative_count[i] + 1
   76.67 +    end
   76.68 +    for j = 1, issue_initiative_count[i] do
   76.69 +      writeln('INSERT INTO "initiative" ("issue_id", "name") VALUES (', i, ", 'Initiative #", initiative_idx, "');")
   76.70 +      initiative_draft_count[i] = 1
   76.71 +      while math.random(4) > 1 do
   76.72 +        initiative_draft_count[i] = initiative_draft_count[i] + 1
   76.73 +      end
   76.74 +      local initiators = {}
   76.75 +      local is_used = {}
   76.76 +      repeat
   76.77 +        local member = math.random(member_count)
   76.78 +        if not is_used[member] then
   76.79 +          initiators[#initiators+1] = member
   76.80 +          is_used[member] = true
   76.81 +        end
   76.82 +      until math.random(2) == 1
   76.83 +      for k = 1, initiative_draft_count[i] do
   76.84 +        draft_count = draft_count + 1
   76.85 +        writeln('INSERT INTO "draft" ("initiative_id", "author_id", "content") VALUES (', initiative_idx, ", ", initiators[math.random(#initiators)], ", 'Lorem ipsum... (#", draft_count, ")');")
   76.86 +      end
   76.87 +      for k = 1, #initiators do
   76.88 +        local member = math.random(member_count)
   76.89 +        writeln('INSERT INTO "initiator" ("member_id", "initiative_id") VALUES (', initiators[k], ", ", initiative_idx, ");")
   76.90 +        if math.random(50) > 1 then
   76.91 +          writeln('INSERT INTO "supporter" ("member_id", "initiative_id", "draft_id") VALUES (', initiators[k], ", ", initiative_idx, ", ", draft_count - math.random(initiative_draft_count[i]) + 1, ");")
   76.92 +        end
   76.93 +      end
   76.94 +      local probability = math.random(99) + 1
   76.95 +      for k = 1, member_count do
   76.96 +        if not is_used[k] and (memberships[area][k] and math.random(probability) <= 4 or math.random(probability) == 1) then
   76.97 +          writeln('INSERT INTO "supporter" ("member_id", "initiative_id", "draft_id") VALUES (', k, ", ", initiative_idx, ", ", draft_count - math.random(initiative_draft_count[i]) + 1, ");")
   76.98 +        end
   76.99 +      end
  76.100 +      initiative_idx = initiative_idx + 1
  76.101 +    end
  76.102 +  end
  76.103 +end
  76.104 +
  76.105 +writeln('END;')
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/db/vote-test.sql	Wed Nov 18 12:00:00 2009 +0100
    77.3 @@ -0,0 +1,134 @@
    77.4 +BEGIN;
    77.5 +
    77.6 +INSERT INTO "member" ("login", "name", "ident_number") VALUES
    77.7 +  ('bernd',    'Bernd',    '002'),
    77.8 +  ('cesar',    'Cesar',    '003'),
    77.9 +  ('doris',    'Doris',    '004'),
   77.10 +  ('emil',     'Emil',     '005'),
   77.11 +  ('frank',    'Frank',    '006'),
   77.12 +  ('gerhard',  'Gerhard',  '007'),
   77.13 +  ('hugo',     'Hugo',     '008'),
   77.14 +  ('ines',     'Ines',     '009'),
   77.15 +  ('johann',   'Johann',   '010'),
   77.16 +  ('klaus',    'Klaus',    '011'),
   77.17 +  ('lisa',     'Lisa',     '012'),
   77.18 +  ('monika',   'Monika',   '013'),
   77.19 +  ('norbert',  'Norbert',  '014'),
   77.20 +  ('olaf',     'Olaf',     '015'),
   77.21 +  ('peter',    'Peter',    '016'),
   77.22 +  ('quinn',    'Quinn',    '017'),
   77.23 +  ('ralf',     'Ralf',     '018'),
   77.24 +  ('sabine',   'Sabine',   '019'),
   77.25 +  ('tobias',   'Tobias',   '020'),
   77.26 +  ('ulla',     'Ulla',     '021'),
   77.27 +  ('vincent',  'Vincent',  '022'),
   77.28 +  ('wolfgang', 'Wolfgang', '023'),
   77.29 +  ('xavier',   'Xavier',   '024'),
   77.30 +  ('yoko',     'Yoko',     '025'),
   77.31 +  ('zareb',    'Zareb',    '026');
   77.32 +
   77.33 +INSERT INTO "issue" ("area_id", "policy_id") VALUES (1, 3);
   77.34 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #1');
   77.35 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #2');
   77.36 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #3');
   77.37 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #4');
   77.38 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #5');
   77.39 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #6');
   77.40 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #7');
   77.41 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #8');
   77.42 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #9');
   77.43 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #10');
   77.44 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #11');
   77.45 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #12');
   77.46 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #13');
   77.47 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #14');
   77.48 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #15');
   77.49 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #16');
   77.50 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #17');
   77.51 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #18');
   77.52 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #19');
   77.53 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #20');
   77.54 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #21');
   77.55 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #22');
   77.56 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #23');
   77.57 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #24');
   77.58 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #25');
   77.59 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #26');
   77.60 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #27');
   77.61 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #28');
   77.62 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #29');
   77.63 +INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #30');
   77.64 +
   77.65 +INSERT INTO "draft" ("initiative_id", "content") SELECT "id", 'Lorem ipsum ...' FROM "initiative";
   77.66 +INSERT INTO "initiator" ("member_id", "initiative_id") SELECT 1, "id" FROM "initiative";
   77.67 +INSERT INTO "supporter" ("member_id", "initiative_id", "draft_id") SELECT "member"."id", "initiative"."id", "initiative"."id" FROM "member", "initiative";
   77.68 +
   77.69 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 1, 1);
   77.70 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 2, 2);
   77.71 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 3, 3);
   77.72 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 4, 4);
   77.73 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 5, 5);
   77.74 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 6, 6);
   77.75 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 7, 7);
   77.76 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 8, 8);
   77.77 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 9, 9);
   77.78 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 10, 10);
   77.79 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 11, 11);
   77.80 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 12, 12);
   77.81 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 13, 13);
   77.82 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 14, 14);
   77.83 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 15, 15);
   77.84 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 16, 16);
   77.85 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 17, 17);
   77.86 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 18, 18);
   77.87 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 19, 19);
   77.88 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 20, 20);
   77.89 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 21, 21);
   77.90 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 22, 22);
   77.91 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 23, 23);
   77.92 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 24, 24);
   77.93 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 25, 25);
   77.94 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 26, 26);
   77.95 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 27, 27);
   77.96 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 28, 28);
   77.97 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 29, 29);
   77.98 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 30, 30);
   77.99 +
  77.100 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 1, 2);
  77.101 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 2, 1);
  77.102 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 3, 3);
  77.103 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 4, 4);
  77.104 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 5, 5);
  77.105 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 6, 6);
  77.106 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 7, 7);
  77.107 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 8, 8);
  77.108 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 9, 9);
  77.109 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 10, 10);
  77.110 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 11, 11);
  77.111 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 12, 12);
  77.112 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 13, 13);
  77.113 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 14, 14);
  77.114 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 15, 15);
  77.115 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 16, 16);
  77.116 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 17, 17);
  77.117 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 18, 18);
  77.118 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 19, 19);
  77.119 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 20, 20);
  77.120 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 21, 21);
  77.121 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 22, 22);
  77.122 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 23, 23);
  77.123 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 24, 24);
  77.124 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 25, 25);
  77.125 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 26, 26);
  77.126 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 27, 27);
  77.127 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 28, 28);
  77.128 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 29, 29);
  77.129 +INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 30, 30);
  77.130 +
  77.131 +
  77.132 +SELECT check_issues();
  77.133 +UPDATE issue SET frozen = now();
  77.134 +
  77.135 +END;
  77.136 +
  77.137 +-- UPDATE issue SET closed = now();
    78.1 Binary file doc/delegation.dia has changed
    79.1 Binary file doc/delegation.png has changed
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/env/ui/bargraph.lua	Wed Nov 18 12:00:00 2009 +0100
    80.3 @@ -0,0 +1,19 @@
    80.4 +function ui.bargraph(args)
    80.5 +  ui.container{
    80.6 +    attr = {
    80.7 +      class = "bargraph",
    80.8 +    },
    80.9 +    content = function()
   80.10 +      for i, bar in ipairs(args.bars) do
   80.11 +        local value = bar.value * args.width / args.max_value / 2 
   80.12 +        ui.container{
   80.13 +          attr = {
   80.14 +            style = "width: " .. tostring(value) .. "px; background-color: " .. bar.color .. ";",
   80.15 +            title = tostring(bar.value)
   80.16 +          },
   80.17 +          content = function() slot.put("&nbsp;") end
   80.18 +        }
   80.19 +      end
   80.20 +    end
   80.21 +  }
   80.22 +end
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/env/ui/field/image.lua	Wed Nov 18 12:00:00 2009 +0100
    81.3 @@ -0,0 +1,16 @@
    81.4 +function ui.field.image(args)
    81.5 +  ui.form_element(args, {}, function(args)
    81.6 +    local value_string = atom.dump(args.value)
    81.7 +    local attr = table.new(args.attr)
    81.8 +    attr.name  = args.field_name
    81.9 +    attr.type  = "file"
   81.10 +    attr.value = value_string
   81.11 +    ui.tag{ tag  = "input", attr = attr }
   81.12 +    local attr = table.new(args.attr)
   81.13 +    attr.name  = args.field_name .. '_' .. 'delete'
   81.14 +    attr.type  = "checkbox"
   81.15 +    attr.value = '1'
   81.16 +    ui.tag{ tag  = "input", attr = attr }
   81.17 +    slot.put(_'delete<br /><br />')
   81.18 +  end)
   81.19 +end
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/env/ui/field/issue_state.lua	Wed Nov 18 12:00:00 2009 +0100
    82.3 @@ -0,0 +1,15 @@
    82.4 +function ui.field.issue_state(args)
    82.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    82.6 +    local value = args.value
    82.7 +    local state_name = Issue:get_state_name_for_state(value)
    82.8 +    ui.tag{
    82.9 +      attr = { class = "vote_now" },
   82.10 +      content = function()
   82.11 +        ui.tag{
   82.12 +          attr = { class = "value" },
   82.13 +          content = tostring(state_name)
   82.14 +        }
   82.15 +      end
   82.16 +    }
   82.17 +  end)
   82.18 +end
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/env/ui/field/negative_votes.lua	Wed Nov 18 12:00:00 2009 +0100
    83.3 @@ -0,0 +1,19 @@
    83.4 +function ui.field.negative_votes(args)
    83.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    83.6 +    local value = args.value
    83.7 +    ui.container{
    83.8 +      attr = { class = "negative_votes" },
    83.9 +      content = function()
   83.10 +        ui.tag{
   83.11 +          attr = { class = "value" },
   83.12 +          content = function()
   83.13 +            slot.put(tostring(value) .. '&nbsp;')
   83.14 +            ui.image{
   83.15 +              static = "icons/16/delete.png"
   83.16 +            }
   83.17 +          end
   83.18 +        }
   83.19 +      end
   83.20 +    }
   83.21 +  end)
   83.22 +end
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/env/ui/field/positive_votes.lua	Wed Nov 18 12:00:00 2009 +0100
    84.3 @@ -0,0 +1,19 @@
    84.4 +function ui.field.positive_votes(args)
    84.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    84.6 +    local value = args.value
    84.7 +    ui.container{
    84.8 +      attr = { class = "positive_votes" },
    84.9 +      content = function()
   84.10 +        ui.tag{
   84.11 +          attr = { class = "value" },
   84.12 +          content = function()
   84.13 +            slot.put(tostring(value) .. '&nbsp;')
   84.14 +            ui.image{
   84.15 +              static = "icons/16/add.png"
   84.16 +            }
   84.17 +          end
   84.18 +        }
   84.19 +      end
   84.20 +    }
   84.21 +  end)
   84.22 +end
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/env/ui/field/potential_initiative_weight.lua	Wed Nov 18 12:00:00 2009 +0100
    85.3 @@ -0,0 +1,14 @@
    85.4 +function ui.field.potential_initiative_weight(args)
    85.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    85.6 +    local value = args.value
    85.7 +    ui.tag{
    85.8 +      attr = { class = "potential_weight" },
    85.9 +      content = function()
   85.10 +        ui.tag{
   85.11 +          attr = { class = "value" },
   85.12 +          content = "(" .. tostring(value) .. ")"
   85.13 +        }
   85.14 +      end
   85.15 +    }
   85.16 +  end)
   85.17 +end
   85.18 \ No newline at end of file
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/env/ui/field/potential_issue_weight.lua	Wed Nov 18 12:00:00 2009 +0100
    86.3 @@ -0,0 +1,14 @@
    86.4 +function ui.field.potential_issue_weight(args)
    86.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    86.6 +    local value = args.value
    86.7 +    ui.tag{
    86.8 +      attr = { class = "potential_weight" },
    86.9 +      content = function()
   86.10 +        ui.tag{
   86.11 +          attr = { class = "value" },
   86.12 +          content = tostring(value)
   86.13 +        }
   86.14 +      end
   86.15 +    }
   86.16 +  end)
   86.17 +end
   86.18 \ No newline at end of file
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/env/ui/field/rank.lua	Wed Nov 18 12:00:00 2009 +0100
    87.3 @@ -0,0 +1,23 @@
    87.4 +function ui.field.rank(args)
    87.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    87.6 +    local value = args.value
    87.7 +    ui.tag{
    87.8 +      attr = { class = "rank" },
    87.9 +      content = function()
   87.10 +        if value == 1 then
   87.11 +            ui.image{ static = "icons/16/award_star_gold_2.png" }
   87.12 +        elseif value then
   87.13 +            ui.image{ static = "icons/16/award_star_silver_2.png" }
   87.14 +        else
   87.15 +            ui.image{ static = "icons/16/cross.png" }
   87.16 +        end
   87.17 +        if value then
   87.18 +          ui.tag{
   87.19 +            attr = { class = "value" },
   87.20 +            content = tostring(value)
   87.21 +          }
   87.22 +        end
   87.23 +      end
   87.24 +    }
   87.25 +  end)
   87.26 +end
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/env/ui/field/satisfaction_informed.lua	Wed Nov 18 12:00:00 2009 +0100
    88.3 @@ -0,0 +1,20 @@
    88.4 +function ui.field.satisfaction_informed(args)
    88.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    88.6 +    local value = args.value
    88.7 +    ui.tag{
    88.8 +      attr = { class = "satisfaction_informed" },
    88.9 +      content = function()
   88.10 +        ui.tag{
   88.11 +          attr = { class = "value" },
   88.12 +          content = function()
   88.13 +            slot.put(tostring(value) .. '&nbsp;')
   88.14 +            ui.image{
   88.15 +              static = "icons/16/thumb_up_green.png"
   88.16 +            }
   88.17 +          end
   88.18 +        }
   88.19 +      end
   88.20 +    }
   88.21 +  end)
   88.22 +end
   88.23 +
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/env/ui/field/satisfaction_total.lua	Wed Nov 18 12:00:00 2009 +0100
    89.3 @@ -0,0 +1,22 @@
    89.4 +function ui.field.satisfaction_total(args)
    89.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    89.6 +    local value = args.value
    89.7 +    ui.tag{
    89.8 +      attr = { class = "satisfaction_total" },
    89.9 +      content = function()
   89.10 +        ui.tag{
   89.11 +          attr = { class = "value" },
   89.12 +          content = function()
   89.13 +            slot.put("(")
   89.14 +            slot.put(tostring(value) .. '&nbsp;')
   89.15 +            ui.image{
   89.16 +              static = "icons/16/thumb_up_green.png"
   89.17 +            }
   89.18 +            slot.put(")")
   89.19 +          end
   89.20 +        }
   89.21 +      end
   89.22 +    }
   89.23 +  end)
   89.24 +end
   89.25 +
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/env/ui/field/timestamp.lua	Wed Nov 18 12:00:00 2009 +0100
    90.3 @@ -0,0 +1,14 @@
    90.4 +function ui.field.timestamp(args)
    90.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    90.6 +    local value = args.value
    90.7 +    ui.tag{
    90.8 +      attr = { class = "ui_field_timestamp" },
    90.9 +      content = function()
   90.10 +        ui.tag{
   90.11 +          attr = { class = "value" },
   90.12 +          content = tostring(value)
   90.13 +        }
   90.14 +      end
   90.15 +    }
   90.16 +  end)
   90.17 +end
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/env/ui/field/vote_later.lua	Wed Nov 18 12:00:00 2009 +0100
    91.3 @@ -0,0 +1,14 @@
    91.4 +function ui.field.vote_later(args)
    91.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    91.6 +    local value = args.value
    91.7 +    ui.tag{
    91.8 +      attr = { class = "vote_later" },
    91.9 +      content = function()
   91.10 +        ui.tag{
   91.11 +          attr = { class = "value" },
   91.12 +          content = tostring(value)
   91.13 +        }
   91.14 +      end
   91.15 +    }
   91.16 +  end)
   91.17 +end
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/env/ui/field/vote_now.lua	Wed Nov 18 12:00:00 2009 +0100
    92.3 @@ -0,0 +1,14 @@
    92.4 +function ui.field.vote_now(args)
    92.5 +  ui.form_element(args, {fetch_value = true}, function(args)
    92.6 +    local value = args.value
    92.7 +    ui.tag{
    92.8 +      attr = { class = "vote_now" },
    92.9 +      content = function()
   92.10 +        ui.tag{
   92.11 +          attr = { class = "value" },
   92.12 +          content = tostring(value)
   92.13 +        }
   92.14 +      end
   92.15 +    }
   92.16 +  end)
   92.17 +end
    93.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.2 +++ b/env/ui/order.lua	Wed Nov 18 12:00:00 2009 +0100
    93.3 @@ -0,0 +1,40 @@
    93.4 +function ui.order(args)
    93.5 +  local name = args.name or "order"
    93.6 +  local current_order = atom.string:load(cgi.params[name]) or args.options[1].name
    93.7 +  local id     = param.get_id_cgi()
    93.8 +  local params = param.get_all_cgi()
    93.9 +  ui.container{
   93.10 +    attr = { class = "ui_order" },
   93.11 +    content = function()
   93.12 +      ui.container{
   93.13 +        attr = { class = "ui_order_head" },
   93.14 +        content = function()
   93.15 +          slot.put(_"Order by")
   93.16 +          slot.put(": ")
   93.17 +          for i, option in ipairs(args.options) do
   93.18 +            params[name] = option.name
   93.19 +            local attr = {}
   93.20 +            if current_order == option.name then
   93.21 +              attr.class = "active"
   93.22 +              args.selector:add_order_by(option.order_by)
   93.23 +            end
   93.24 +            ui.link{
   93.25 +              attr    = attr,
   93.26 +              module  = request.get_module(),
   93.27 +              view    = request.get_view(),
   93.28 +              id      = id,
   93.29 +              params  = params,
   93.30 +              content = option.label
   93.31 +            }
   93.32 +          end
   93.33 +        end
   93.34 +      }
   93.35 +      ui.container{
   93.36 +        attr = { class = "ui_order_content" },
   93.37 +        content = function()
   93.38 +          args.content()
   93.39 +        end
   93.40 +      }
   93.41 +    end
   93.42 +  }
   93.43 +end
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/env/ui/tabs.lua	Wed Nov 18 12:00:00 2009 +0100
    94.3 @@ -0,0 +1,40 @@
    94.4 +function ui.tabs(tabs)
    94.5 +  ui.container{
    94.6 +    attr = { class = "ui_tabs" },
    94.7 +    content = function()
    94.8 +      local params = param.get_all_cgi()
    94.9 +      local current_tab = params["tab"]
   94.10 +      ui.container{
   94.11 +        attr = { class = "ui_tabs_links" },
   94.12 +        content = function()
   94.13 +          for i, tab in ipairs(tabs) do
   94.14 +            params["tab"] = i > 1 and tab.name or nil
   94.15 +            ui.link{
   94.16 +              attr = { 
   94.17 +                class = (
   94.18 +                  tab.name == current_tab and "selected" or
   94.19 +                  not current_tab and i == 1 and "selected" or
   94.20 +                  ""
   94.21 +                )
   94.22 +              },
   94.23 +              module = request.get_module(),
   94.24 +              view = request.get_view(),
   94.25 +              id = param.get_id_cgi(),
   94.26 +              text = tab.label,
   94.27 +              params = params
   94.28 +            }
   94.29 +          end
   94.30 +        end
   94.31 +      }
   94.32 +      for i, tab in ipairs(tabs) do
   94.33 +        if tab.name == current_tab or not current_tab and i == 1 then
   94.34 +          ui.container{
   94.35 +            attr = { class = "ui_tabs_content" },
   94.36 +            content = tab.content
   94.37 +          }
   94.38 +        end
   94.39 +      end
   94.40 +    end
   94.41 +  }
   94.42 +end
   94.43 +
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/env/ui/twitter.lua	Wed Nov 18 12:00:00 2009 +0100
    95.3 @@ -0,0 +1,10 @@
    95.4 +function ui.twitter(message)
    95.5 +  ui.link{
    95.6 +    attr = { target = "_blank" },
    95.7 +    content = function()
    95.8 +      ui.image{ static = "icons/16/user_comment.png" }
    95.9 +      slot.put(encode.html("tweet it"))
   95.10 +    end,
   95.11 +    external = "http://twitter.com/?status=" .. encode.url_part(message)
   95.12 +  }
   95.13 +end
   95.14 \ No newline at end of file
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/env/util/put_highlighted_string.lua	Wed Nov 18 12:00:00 2009 +0100
    96.3 @@ -0,0 +1,14 @@
    96.4 +function util.put_highlighted_string(string)
    96.5 +  local highlight_string = param.get("highlight_string")
    96.6 +  if highlight_string then
    96.7 +    local highlighted_string = slot.use_temporary(function()
    96.8 +      ui.tag{
    96.9 +        tag = "span",
   96.10 +        attr = { class = "highlighted" },
   96.11 +        content = highlight_string
   96.12 +      }
   96.13 +    end)
   96.14 +    string = string:gsub(highlight_string, highlighted_string)
   96.15 +  end
   96.16 +  slot.put(string)
   96.17 +end
   96.18 \ No newline at end of file
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/locale/translations.de.lua	Wed Nov 18 12:00:00 2009 +0100
    97.3 @@ -0,0 +1,193 @@
    97.4 +#!/usr/bin/env lua
    97.5 +return {
    97.6 +["A-Z"] = false;
    97.7 +["About"] = false;
    97.8 +["About LiquidFeedback"] = "Über LiquidFeedback";
    97.9 +["Accepted"] = "Akzeptiert";
   97.10 +["Active?"] = "Aktiv?";
   97.11 +["Add my interest to this issue"] = "Mein Interesse am Thema anmelden";
   97.12 +["Add my membership to this area"] = "Mitglied im Themenbereich werden";
   97.13 +["Add new draft"] = "Neuen Entwurf hinzufügen";
   97.14 +["Add new initiative to issue"] = "Neue Initiative zum Thema hinzufügen";
   97.15 +["Add new suggestion"] = "Neue Anregung hinzufügen";
   97.16 +["Add to my contacts"] = "Zu meinen Kontakten hinzufügen";
   97.17 +["Admin"] = "Admin";
   97.18 +["Admin menu"] = "Admin Menü";
   97.19 +["Admin?"] = "Admin?";
   97.20 +["Admitted"] = "zugelassen";
   97.21 +["Area"] = "Themenbereich";
   97.22 +["Area '#{name}'"] = "Themenbereich '#{name}'";
   97.23 +["Area list"] = "Liste der Themenbereiche";
   97.24 +["Area successfully updated"] = "Themenbereich erfolgreich aktualisiert";
   97.25 +["Areas"] = "Themenbereiche";
   97.26 +["Author"] = "Autor";
   97.27 +["Autoreject is off."] = "Auto-Ablehnen ist aus";
   97.28 +["Autoreject is on."] = "Auto-Ablehnen ist an";
   97.29 +["Cancel"] = false;
   97.30 +["Cancelled"] = "Abgebrochen";
   97.31 +["Change password"] = "Kennwort ändern";
   97.32 +["Click here to close."] = "Zum Schließen hier klicken";
   97.33 +["Close"] = "Schließen";
   97.34 +["Closed"] = "geschlossen";
   97.35 +["Commit suggestion"] = "Anregung speichern";
   97.36 +["Contacts"] = "Kontakte";
   97.37 +["Content"] = "Inhalt";
   97.38 +["Create new area"] = "Neuen Themenbereich anlegen";
   97.39 +["Create new issue"] = "Neues Thema anlegen";
   97.40 +["Created at"] = "Erzeugt am/um";
   97.41 +["Current draft"] = "Aktueller Entwurf";
   97.42 +["Degree"] = "Grad";
   97.43 +["Delegate"] = "Delegieren";
   97.44 +["Description"] = "Beschreibung";
   97.45 +["Details"] = "Details";
   97.46 +["Direct member count"] = "Anzahl Direktmitglieder";
   97.47 +["Direct supporter [change]"] = "Direkte Unterstützung [ändern]";
   97.48 +["Draft"] = "Entwurf";
   97.49 +["Edit"] = "Bearbeiten";
   97.50 +["Edit my page"] = "Meine Seite bearbeiten";
   97.51 +["Error while updating member, database reported:<br /><br /> (#{errormessage})"] = "Fehler beim aktualisieren des Mitglieds, die Datenbank berichtet folgenden Fehler:<br /><br /> (#{errormessage})";
   97.52 +["Finished"] = "Abgeschlossen";
   97.53 +["Frozen"] = "Eingefroren";
   97.54 +["Fulfilled"] = "Erfüllt";
   97.55 +["Fullfilled"] = "Erfüllt";
   97.56 +["Fully frozen"] = false;
   97.57 +["Global delegation"] = "Globale Delegation";
   97.58 +["Half frozen"] = false;
   97.59 +["Hide"] = "Verstecken";
   97.60 +["Home"] = "Startseite";
   97.61 +["Id"] = "Id";
   97.62 +["Ident number"] = "Ident-Nummer";
   97.63 +["In discussion"] = "In Diskussion";
   97.64 +["Incoming delegations"] = "Eingehende Delegationen";
   97.65 +["Initiative"] = "Initiative";
   97.66 +["Initiative successfully created"] = "Initiative erfolgreich erzeugt";
   97.67 +["Initiative: '#{name}'"] = "Initiative: '#{name}'";
   97.68 +["Initiatives"] = "Initiativen";
   97.69 +["Initiators"] = "Initiatoren";
   97.70 +["Interest not existant"] = false;
   97.71 +["Interest removed"] = "Interesse entfernt";
   97.72 +["Interest updated"] = "Interesse aktualisiert";
   97.73 +["Invalid username or password!"] = "Ungültiger Benutzername oder Kennwort";
   97.74 +["Issue"] = "Thema";
   97.75 +["Issue ##{id}"] = "Issue ##{id}";
   97.76 +["Issue ##{id} (#{policy_name})"] = "Thema ##{id} (#{policy_name})";
   97.77 +["Issue policy"] = "Regelwerk für Thema";
   97.78 +["Issues"] = "Themen";
   97.79 +["License"] = "Lizenz";
   97.80 +["Locked?"] = "Gesperrt?";
   97.81 +["Logged in as:"] = "Angemeldet als:";
   97.82 +["Login"] = "Anmeldung";
   97.83 +["Login successful!"] = "Anmeldung erfolgreich";
   97.84 +["Logout"] = "Abmelden";
   97.85 +["Logout successful"] = "Abmeldung erfolgreich";
   97.86 +["Me"] = "Ich";
   97.87 +["Member '#{member}'"] = "Mitglied '#{member}'";
   97.88 +["Member has been removed from your contacts"] = "Mitglied wurde aus Deinen Kontakten entfernt";
   97.89 +["Member has been saved as private contact"] = "Mitglied wurde als privater Kontakt gespeichert";
   97.90 +["Member has been saved as public contact"] = "Mitglied wurde als öffentlicher Kontakt gespeichert";
   97.91 +["Member is already saved in your contacts!"] = "Mitglied ist schon in Deinen Kontakten!";
   97.92 +["Member list"] = "Mitgliederliste";
   97.93 +["Member login"] = "Mitglied Login";
   97.94 +["Member name"] = "Mitglied Name";
   97.95 +["Member successfully registered"] = "Mitglied erfolgreich registriert";
   97.96 +["Member successfully updated"] = "Mitglied erfolgreich aktualisert";
   97.97 +["Member: '#{login}' (#{name})"] = "Mitlied: '#{login}' (#{name})";
   97.98 +["Members"] = "Mitglieder";
   97.99 +["Membership not existant"] = false;
  97.100 +["Membership removed"] = "Mitgliedschaft entfernt";
  97.101 +["Membership updated"] = "Mitgliedschaft aktualisiert";
  97.102 +["Name"] = "Name";
  97.103 +["New"] = "Neu";
  97.104 +["New draft has been added to initiative"] = "Neuer Entwurf wurde der Initiative hinzugefügt";
  97.105 +["New password"] = "Neues Kennwort";
  97.106 +["New passwords does not match."] = "Du hast nicht zweimal das gleiche Kennwort eingegeben";
  97.107 +["New passwords is too short."] = "Das neue Kennwort ist zu kurz";
  97.108 +["Newest"] = "Neueste";
  97.109 +["No supporter [change]"] = "Keine Unterstützung (ändern)";
  97.110 +["Not fullfilled"] = "Nicht erfüllt";
  97.111 +["OK"] = "OK";
  97.112 +["Old drafts"] = "Alte Entwürfe";
  97.113 +["Old password"] = "Altes Kennwort";
  97.114 +["Old password is wrong"] = "Das alte Kennwort ist falsch";
  97.115 +["Oldest"] = "Älteste";
  97.116 +["Order by"] = "Sortieren nach";
  97.117 +["Outgoing delegations"] = "Ausgehende Delegationen";
  97.118 +["Password"] = "Kennwort";
  97.119 +["Policy"] = "Regelwerk";
  97.120 +["Population"] = "Grundgesamtheit";
  97.121 +["Potential weight"] = "Potentielles Gewicht";
  97.122 +["Publish"] = "Veröffentlichen";
  97.123 +["Published"] = "veröffentlicht";
  97.124 +["Published contacts"] = "Veröffentlichte Kontakte";
  97.125 +["Rank"] = "Rang";
  97.126 +["Register new member"] = "Neues Mitglied registrieren";
  97.127 +["Remove"] = "Entfernen";
  97.128 +["Remove autoreject"] = "Auto-Ablehnen abschalten";
  97.129 +["Remove my interest"] = "Interesse abmelden";
  97.130 +["Remove my membership"] = "Mitgliedschaft aufgeben";
  97.131 +["Remove my support from this initiative"] = "Meine Unterstützung der Initiative entziehen";
  97.132 +["Repeat new password"] = "Neues Kennwort wiederholen";
  97.133 +["Revoke"] = "Widerrufen";
  97.134 +["Revoked at"] = "Zurückgezogen am/um";
  97.135 +["Save"] = "Speichern";
  97.136 +["Search"] = "Suchen";
  97.137 +["Search initiatives"] = "Suche Initiativen";
  97.138 +["Search issues"] = "Suche Themen";
  97.139 +["Search members"] = "Suche Mitglieder";
  97.140 +["Search results for: '#{search}'"] = "Suchergebnisse für: '#{search}'";
  97.141 +["Set autoreject"] = "Auto-Ablehnen anschalten";
  97.142 +["Set delegation for Area '#{name}'"] = "Delegation für Themengebiet '#{name}' festlegen";
  97.143 +["Set delegation for Issue ##{number} in Area '#{area_name}'"] = "Delegation für Thema ##{number} im Themenbereich '#{area_name}' festlegen";
  97.144 +["Show"] = "Zeige";
  97.145 +["Show active members"] = "Zeige aktive Mitglieder";
  97.146 +["Show areas in use"] = "Zeige verwendete Themenbereiche";
  97.147 +["Show areas not in use"] = "Zeige nicht verwendente Themenbereiche";
  97.148 +["Show locked members"] = "Zeige gesperrte Mitglieder";
  97.149 +["Software"] = false;
  97.150 +["State"] = "Zustand";
  97.151 +["Suggestion for initiative: '#{name}'"] = "Anregung für Initiative '#{name}'";
  97.152 +["Suggestions"] = "Anregungen";
  97.153 +["Support"] = "Unterstützung";
  97.154 +["Support S+I"] = "Unterstütung S+I";
  97.155 +["Support this initiative"] = "Diese Initiative unterstützen";
  97.156 +["Supporter"] = "Unterstützer";
  97.157 +["That's me!"] = "Das bin ich";
  97.158 +["Trustee"] = "Bevollmächtigter";
  97.159 +["Truster"] = "Delegierender";
  97.160 +["Unknown author"] = "Unbekannter Autor";
  97.161 +["Upload avatar"] = "Avatar hochladen";
  97.162 +["Username"] = "Benutzername";
  97.163 +["Version"] = false;
  97.164 +["Vote later"] = "Später abstimmen";
  97.165 +["Vote now"] = "Jetzt abstimmen";
  97.166 +["Voting"] = "Abstimmung";
  97.167 +["Voting requests"] = "Abstimmanträge";
  97.168 +["You are already not supporting this initiative"] = "Diese Initiative hat bereits keine Unterstützung von Dir";
  97.169 +["You are already supporting the latest draft"] = "Du unterstützt bereits den neuesten Entwurf";
  97.170 +["You are interested. [more]"] = "Du bist interessiert. [mehr]";
  97.171 +["You are member. [more]"] = "Du bist Mitglied. [mehr]";
  97.172 +["You are not a member. [more]"] = "Du bist kein Mitglied. [mehr]";
  97.173 +["You are not interested. [more]"] = "Du bist nicht interessiert. [mehr]";
  97.174 +["You didn't saved any member as contact yet."] = "Du hast noch kein Mitglied als Kontakt gespeichert!";
  97.175 +["Your delegation for this area has been deleted."] = "Deine Delegation für dieses Themengebiet wurde gelöscht";
  97.176 +["Your delegation for this area has been updated."] = "Deine Delegation für dieses Themengebiet wurde geändert";
  97.177 +["Your delegation for this issue has been deleted."] = "Deine Delegation für dieses Thema wurde gelöscht";
  97.178 +["Your delegation for this issue has been updated."] = "Deine Delegation für dieses Thema wurde geändert";
  97.179 +["Your global delegation has been deleted."] = "Deine globale Delegation wurde gelöscht";
  97.180 +["Your global delegation has been updated."] = "Deine globale Delegation würde geändert";
  97.181 +["Your opinion has been updated"] = "Deine Meinung wurde aktualisiert";
  97.182 +["Your password has been updated successfully"] = "Das Kennwort wurde erfolgreich geändert";
  97.183 +["Your suggestion has been added"] = "Deine Anregung wurde hinzufügt";
  97.184 +["Your support has been added to this initiative"] = "Deine Unterstützung wurde der Initiative hinzugefügt";
  97.185 +["Your support has been removed from this initiative"] = "Deine Unterstützung wurde der Initiave entzogen";
  97.186 +["Your support has been updated to the latest draft"] = "Deine Unterstützung wurde auf den neuesten Entwurf aktualisiert";
  97.187 +["Your vote is delegated. [more]"] = "Deine Stimme ist delegiert. [mehr]";
  97.188 +["Z-A"] = false;
  97.189 +["must"] = "muss";
  97.190 +["must not"] = "darf nicht";
  97.191 +["neutral"] = "neutral";
  97.192 +["remove fulfilled"] = "erfüllt entfernen";
  97.193 +["set fulfilled"] = "erfüllt setzten";
  97.194 +["should"] = "soll";
  97.195 +["should not"] = "soll nicht";
  97.196 +}
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/locale/translations.en.lua	Wed Nov 18 12:00:00 2009 +0100
    98.3 @@ -0,0 +1,15 @@
    98.4 +#!/usr/bin/env lua
    98.5 +return {
    98.6 +["Error compile"] = false;
    98.7 +["Error no file"] = false;
    98.8 +["Error runtime"] = false;
    98.9 +["Home"] = false;
   98.10 +["Invalid username or password!"] = false;
   98.11 +["Login"] = false;
   98.12 +["Login successful!"] = false;
   98.13 +["Logout"] = false;
   98.14 +["Logout successful"] = false;
   98.15 +["Password"] = false;
   98.16 +["Password login"] = false;
   98.17 +["Username"] = false;
   98.18 +}
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/model/area.lua	Wed Nov 18 12:00:00 2009 +0100
    99.3 @@ -0,0 +1,31 @@
    99.4 +Area = mondelefant.new_class()
    99.5 +Area.table = 'area'
    99.6 +
    99.7 +Area:add_reference{
    99.8 +  mode          = '1m',
    99.9 +  to            = "Issue",
   99.10 +  this_key      = 'id',
   99.11 +  that_key      = 'area_id',
   99.12 +  ref           = 'issues',
   99.13 +  back_ref      = 'area'
   99.14 +}
   99.15 +
   99.16 +Area:add_reference{
   99.17 +  mode          = '1m',
   99.18 +  to            = "Membership",
   99.19 +  this_key      = 'id',
   99.20 +  that_key      = 'area_id',
   99.21 +  ref           = 'memberships',
   99.22 +  back_ref      = 'area'
   99.23 +}
   99.24 +
   99.25 +Area:add_reference{
   99.26 +  mode                  = 'mm',
   99.27 +  to                    = "Member",
   99.28 +  this_key              = 'id',
   99.29 +  that_key              = 'id',
   99.30 +  connected_by_table    = 'membership',
   99.31 +  connected_by_this_key = 'area_id',
   99.32 +  connected_by_that_key = 'member_id',
   99.33 +  ref                   = 'members'
   99.34 +}
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/model/contact.lua	Wed Nov 18 12:00:00 2009 +0100
   100.3 @@ -0,0 +1,28 @@
   100.4 +Contact = mondelefant.new_class()
   100.5 +Contact.table = 'contact'
   100.6 +Contact.primary_key = { "member_id", "other_member_id" }
   100.7 +
   100.8 +Contact:add_reference{
   100.9 +  mode          = 'm1',
  100.10 +  to            = "Member",
  100.11 +  this_key      = 'member_id',
  100.12 +  that_key      = 'id',
  100.13 +  ref           = 'member',
  100.14 +}
  100.15 +
  100.16 +Contact:add_reference{
  100.17 +  mode          = 'm1',
  100.18 +  to            = "Member",
  100.19 +  this_key      = 'other_member_id',
  100.20 +  that_key      = 'id',
  100.21 +  ref           = 'other_member',
  100.22 +}
  100.23 +
  100.24 +
  100.25 +function Contact:by_pk(member_id, other_member_id)
  100.26 +  return self:new_selector()
  100.27 +    :add_where{ "member_id = ?", member_id }
  100.28 +    :add_where{ "other_member_id = ?", other_member_id }
  100.29 +    :optional_object_mode()
  100.30 +    :exec()
  100.31 +end
   101.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.2 +++ b/model/delegation.lua	Wed Nov 18 12:00:00 2009 +0100
   101.3 @@ -0,0 +1,50 @@
   101.4 +Delegation = mondelefant.new_class()
   101.5 +Delegation.table = 'delegation'
   101.6 +
   101.7 +Delegation:add_reference{
   101.8 +  mode          = 'm1',
   101.9 +  to            = "Member",
  101.10 +  this_key      = 'truster_id',
  101.11 +  that_key      = 'id',
  101.12 +  ref           = 'truster',
  101.13 +}
  101.14 +
  101.15 +Delegation:add_reference{
  101.16 +  mode          = 'm1',
  101.17 +  to            = "Member",
  101.18 +  this_key      = 'trustee_id',
  101.19 +  that_key      = 'id',
  101.20 +  ref           = 'trustee',
  101.21 +}
  101.22 +
  101.23 +Delegation:add_reference{
  101.24 +  mode          = 'm1',
  101.25 +  to            = "Area",
  101.26 +  this_key      = 'area_id',
  101.27 +  that_key      = 'id',
  101.28 +  ref           = 'area',
  101.29 +}
  101.30 +
  101.31 +Delegation:add_reference{
  101.32 +  mode          = 'm1',
  101.33 +  to            = "Issue",
  101.34 +  this_key      = 'issue_id',
  101.35 +  that_key      = 'id',
  101.36 +  ref           = 'issue',
  101.37 +}
  101.38 +
  101.39 +function Delegation:by_pk(truster_id, area_id, issue_id)
  101.40 +  local selector = self:new_selector():optional_object_mode()
  101.41 +  selector:add_where{ "truster_id = ?", truster_id }
  101.42 +  if area_id then
  101.43 +    selector:add_where{ "area_id = ?",    area_id }
  101.44 +  else
  101.45 +    selector:add_where("area_id ISNULL")
  101.46 +  end
  101.47 +  if issue_id then
  101.48 +    selector:add_where{ "issue_id = ? ",  issue_id }
  101.49 +  else
  101.50 +    selector:add_where("issue_id ISNULL ")
  101.51 +  end
  101.52 +  return selector:exec()
  101.53 +end
  101.54 \ No newline at end of file
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/model/direct_voter.lua	Wed Nov 18 12:00:00 2009 +0100
   102.3 @@ -0,0 +1,18 @@
   102.4 +DirectVoter = mondelefant.new_class()
   102.5 +DirectVoter.table = 'member'
   102.6 +
   102.7 +DirectVoter:add_reference{
   102.8 +  mode          = 'm1',
   102.9 +  to            = "Issue",
  102.10 +  this_key      = 'issue_id',
  102.11 +  that_key      = 'id',
  102.12 +  ref           = 'issue',
  102.13 +}
  102.14 +
  102.15 +DirectVoter:add_reference{
  102.16 +  mode          = 'm1',
  102.17 +  to            = "Member",
  102.18 +  this_key      = 'member_id',
  102.19 +  that_key      = 'id',
  102.20 +  ref           = 'member',
  102.21 +}
   103.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.2 +++ b/model/draft.lua	Wed Nov 18 12:00:00 2009 +0100
   103.3 @@ -0,0 +1,24 @@
   103.4 +Draft = mondelefant.new_class()
   103.5 +Draft.table = 'draft'
   103.6 +
   103.7 +Draft:add_reference{
   103.8 +  mode          = 'm1',
   103.9 +  to            = "Initiative",
  103.10 +  this_key      = 'initiative_id',
  103.11 +  that_key      = 'id',
  103.12 +  ref           = 'initiative',
  103.13 +}
  103.14 +
  103.15 +Draft:add_reference{
  103.16 +  mode          = 'm1',
  103.17 +  to            = "Member",
  103.18 +  this_key      = 'author_id',
  103.19 +  that_key      = 'id',
  103.20 +  ref           = 'author',
  103.21 +}
  103.22 +
  103.23 +-- reference to supporter probably not needed
  103.24 +
  103.25 +function Draft.object_get:author_name()
  103.26 +  return self.author and self.author.name or _"Unknown author"
  103.27 +end
   104.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.2 +++ b/model/initiative.lua	Wed Nov 18 12:00:00 2009 +0100
   104.3 @@ -0,0 +1,114 @@
   104.4 +Initiative = mondelefant.new_class()
   104.5 +Initiative.table = 'initiative'
   104.6 +
   104.7 +Initiative:add_reference{
   104.8 +  mode          = 'm1',
   104.9 +  to            = "Issue",
  104.10 +  this_key      = 'issue_id',
  104.11 +  that_key      = 'id',
  104.12 +  ref           = 'issue',
  104.13 +}
  104.14 +
  104.15 +Initiative:add_reference{
  104.16 +  mode          = '1m',
  104.17 +  to            = "Draft",
  104.18 +  this_key      = 'id',
  104.19 +  that_key      = 'initiative_id',
  104.20 +  ref           = 'drafts',
  104.21 +  back_ref      = 'initiative',
  104.22 +  default_order = '"id"'
  104.23 +}
  104.24 +
  104.25 +Initiative:add_reference{
  104.26 +  mode          = '1m',
  104.27 +  to            = "Suggestion",
  104.28 +  this_key      = 'id',
  104.29 +  that_key      = 'initiative_id',
  104.30 +  ref           = 'suggestions',
  104.31 +  back_ref      = 'initiative',
  104.32 +  default_order = '"id"'
  104.33 +}
  104.34 +
  104.35 +Initiative:add_reference{
  104.36 +  mode          = '1m',
  104.37 +  to            = "Initiator",
  104.38 +  this_key      = 'id',
  104.39 +  that_key      = 'initiative_id',
  104.40 +  ref           = 'initiators',
  104.41 +  back_ref      = 'initiative',
  104.42 +  default_order = '"id"'
  104.43 +}
  104.44 +
  104.45 +Initiative:add_reference{
  104.46 +  mode          = '1m',
  104.47 +  to            = "Supporter",
  104.48 +  this_key      = 'id',
  104.49 +  that_key      = 'initiative_id',
  104.50 +  ref           = 'supporters',
  104.51 +  back_ref      = 'initiative',
  104.52 +  default_order = '"id"'
  104.53 +}
  104.54 +
  104.55 +Initiative:add_reference{
  104.56 +  mode          = '1m',
  104.57 +  to            = "Opinion",
  104.58 +  this_key      = 'id',
  104.59 +  that_key      = 'initiative_id',
  104.60 +  ref           = 'opinions',
  104.61 +  back_ref      = 'initiative',
  104.62 +  default_order = '"id"'
  104.63 +}
  104.64 +
  104.65 +Initiative:add_reference{
  104.66 +  mode          = '1m',
  104.67 +  to            = "Vote",
  104.68 +  this_key      = 'id',
  104.69 +  that_key      = 'initiative_id',
  104.70 +  ref           = 'votes',
  104.71 +  back_ref      = 'initiative',
  104.72 +  default_order = '"member_id"'
  104.73 +}
  104.74 +
  104.75 +Initiative:add_reference{
  104.76 +  mode                  = 'mm',
  104.77 +  to                    = "Member",
  104.78 +  this_key              = 'id',
  104.79 +  that_key              = 'id',
  104.80 +  connected_by_table    = '"initiator"',
  104.81 +  connected_by_this_key = 'initiative_id',
  104.82 +  connected_by_that_key = 'member_id',
  104.83 +  ref                   = 'initiating_members'
  104.84 +}
  104.85 +
  104.86 +Initiative:add_reference{
  104.87 +  mode                  = 'mm',
  104.88 +  to                    = "Member",
  104.89 +  this_key              = 'id',
  104.90 +  that_key              = 'id',
  104.91 +  connected_by_table    = '"supporter"',
  104.92 +  connected_by_this_key = 'initiative_id',
  104.93 +  connected_by_that_key = 'member_id',
  104.94 +  ref                   = 'supporting_members'
  104.95 +}
  104.96 +
  104.97 +function Initiative:search(search_string)
  104.98 +  return self:new_selector()
  104.99 +    :add_where{ '"initiative"."name" ILIKE ?', "%" .. search_string:gsub("%%", "") .. "%" }
 104.100 +    :exec()
 104.101 +end
 104.102 +
 104.103 +function Initiative.object_get:current_draft()
 104.104 +  return Draft:new_selector()
 104.105 +    :add_where{ '"initiative_id" = ?', self.id }
 104.106 +    :add_order_by('"id" DESC')
 104.107 +    :single_object_mode()
 104.108 +    :exec()
 104.109 +end
 104.110 +
 104.111 +function Initiative.object_get:shortened_name()
 104.112 +  local name = self.name
 104.113 +  if #name > 100 then
 104.114 +    name = name:sub(1,100) .. "..."
 104.115 +  end
 104.116 +  return name
 104.117 +end
   105.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.2 +++ b/model/initiator.lua	Wed Nov 18 12:00:00 2009 +0100
   105.3 @@ -0,0 +1,27 @@
   105.4 +Initiator = mondelefant.new_class()
   105.5 +Initiator.table = 'initiator'
   105.6 +Initiator.primary_key = { "initiative_id", "member_id" }
   105.7 +
   105.8 +Initiator:add_reference{
   105.9 +  mode          = 'm1',
  105.10 +  to            = "Initiative",
  105.11 +  this_key      = 'initiative_id',
  105.12 +  that_key      = 'id',
  105.13 +  ref           = 'initiative',
  105.14 +}
  105.15 +
  105.16 +Initiator:add_reference{
  105.17 +  mode          = 'm1',
  105.18 +  to            = "Member",
  105.19 +  this_key      = 'member_id',
  105.20 +  that_key      = 'id',
  105.21 +  ref           = 'member',
  105.22 +}
  105.23 +
  105.24 +function Initiator:by_pk(initiative_id, member_id)
  105.25 +  return self:new_selector()
  105.26 +    :add_where{ "initiative_id = ?", initiative_id }
  105.27 +    :add_where{ "member_id = ?", member_id }
  105.28 +    :optional_object_mode()
  105.29 +    :exec()
  105.30 +end
   106.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.2 +++ b/model/interest.lua	Wed Nov 18 12:00:00 2009 +0100
   106.3 @@ -0,0 +1,25 @@
   106.4 +Interest = mondelefant.new_class()
   106.5 +Interest.table = 'interest'
   106.6 +Interest.primary_key = { "issue_id", "member_id" }
   106.7 +Interest:add_reference{
   106.8 +  mode          = 'm1',
   106.9 +  to            = "Member",
  106.10 +  this_key      = 'member_id',
  106.11 +  that_key      = 'id',
  106.12 +  ref           = 'member',
  106.13 +}
  106.14 +
  106.15 +Interest:add_reference{
  106.16 +  mode          = 'm1',
  106.17 +  to            = "Issue",
  106.18 +  this_key      = 'issue_id',
  106.19 +  that_key      = 'id',
  106.20 +  ref           = 'issue',
  106.21 +}
  106.22 +
  106.23 +function Interest:by_pk(issue_id, member_id)
  106.24 +  return self:new_selector()
  106.25 +    :add_where{ "issue_id = ? AND member_id = ?", issue_id, member_id }
  106.26 +    :optional_object_mode()
  106.27 +    :exec()
  106.28 +end
  106.29 \ No newline at end of file
   107.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.2 +++ b/model/issue.lua	Wed Nov 18 12:00:00 2009 +0100
   107.3 @@ -0,0 +1,109 @@
   107.4 +Issue = mondelefant.new_class()
   107.5 +Issue.table = 'issue'
   107.6 +
   107.7 +Issue:add_reference{
   107.8 +  mode          = 'm1',
   107.9 +  to            = "Area",
  107.10 +  this_key      = 'area_id',
  107.11 +  that_key      = 'id',
  107.12 +  ref           = 'area',
  107.13 +}
  107.14 +
  107.15 +Issue:add_reference{
  107.16 +  mode          = 'm1',
  107.17 +  to            = "Policy",
  107.18 +  this_key      = 'policy_id',
  107.19 +  that_key      = 'id',
  107.20 +  ref           = 'policy',
  107.21 +}
  107.22 +
  107.23 +Issue:add_reference{
  107.24 +  mode          = '1m',
  107.25 +  to            = "Initiative",
  107.26 +  this_key      = 'id',
  107.27 +  that_key      = 'issue_id',
  107.28 +  ref           = 'initiatives',
  107.29 +  back_ref      = 'issue'
  107.30 +}
  107.31 +
  107.32 +Issue:add_reference{
  107.33 +  mode          = '1m',
  107.34 +  to            = "Interest",
  107.35 +  this_key      = 'id',
  107.36 +  that_key      = 'issue_id',
  107.37 +  ref           = 'interests',
  107.38 +  back_ref      = 'issue',
  107.39 +  default_order = '"id"'
  107.40 +}
  107.41 +
  107.42 +Issue:add_reference{
  107.43 +  mode          = '1m',
  107.44 +  to            = "Supporter",
  107.45 +  this_key      = 'id',
  107.46 +  that_key      = 'issue_id',
  107.47 +  ref           = 'supporters',
  107.48 +  back_ref      = 'issue',
  107.49 +  default_order = '"id"'
  107.50 +}
  107.51 +
  107.52 +Issue:add_reference{
  107.53 +  mode          = '1m',
  107.54 +  to            = "DirectVoter",
  107.55 +  this_key      = 'id',
  107.56 +  that_key      = 'issue_id',
  107.57 +  ref           = 'direct_voters',
  107.58 +  back_ref      = 'issue',
  107.59 +  default_order = '"member_id"'
  107.60 +}
  107.61 +
  107.62 +Issue:add_reference{
  107.63 +  mode          = '1m',
  107.64 +  to            = "Vote",
  107.65 +  this_key      = 'id',
  107.66 +  that_key      = 'issue_id',
  107.67 +  ref           = 'votes',
  107.68 +  back_ref      = 'issue',
  107.69 +  default_order = '"member_id", "initiative_id"'
  107.70 +}
  107.71 +
  107.72 +Issue:add_reference{
  107.73 +  mode                  = 'mm',
  107.74 +  to                    = "Member",
  107.75 +  this_key              = 'id',
  107.76 +  that_key              = 'id',
  107.77 +  connected_by_table    = 'interest',
  107.78 +  connected_by_this_key = 'issue_id',
  107.79 +  connected_by_that_key = 'member_id',
  107.80 +  ref                   = 'members'
  107.81 +}
  107.82 +
  107.83 +function Issue:get_state_name_for_state(value)
  107.84 +  local state_name_table = {}
  107.85 +  return state_name_table[value] or value
  107.86 +end
  107.87 +
  107.88 +function Issue:search(search_string)
  107.89 +  return self:new_selector()
  107.90 +    :join('"initiative"', nil, '"initiative"."issue_id" = "issue"."id"')
  107.91 +    :add_where{ '"initiative"."name" ILIKE ?', "%" .. search_string:gsub("%%", "") .. "%" }
  107.92 +    :set_distinct()
  107.93 +    :exec()
  107.94 +end
  107.95 +
  107.96 +function Issue.object_get:state()
  107.97 +  if self.accepted then
  107.98 +    if self.frozen then
  107.99 +      return "frozen"
 107.100 +    elseif self.closed then
 107.101 +      return "closed"
 107.102 +    else
 107.103 +      return "accepted"
 107.104 +    end
 107.105 +  else
 107.106 +    if self.closed then
 107.107 +      return "closed"
 107.108 +    else
 107.109 +      return "new"
 107.110 +    end
 107.111 +  end
 107.112 +end
 107.113 \ No newline at end of file
   108.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.2 +++ b/model/member.lua	Wed Nov 18 12:00:00 2009 +0100
   108.3 @@ -0,0 +1,256 @@
   108.4 +Member = mondelefant.new_class()
   108.5 +Member.table = 'member'
   108.6 +
   108.7 +Member:add_reference{
   108.8 +  mode          = '1m',
   108.9 +  to            = "Contact",
  108.10 +  this_key      = 'id',
  108.11 +  that_key      = 'member_id',
  108.12 +  ref           = 'contacts',
  108.13 +  back_ref      = 'member',
  108.14 +  default_order = '"other_member_id"'
  108.15 +}
  108.16 +
  108.17 +Member:add_reference{
  108.18 +  mode          = '1m',
  108.19 +  to            = "Contact",
  108.20 +  this_key      = 'id',
  108.21 +  that_key      = 'member_id',
  108.22 +  ref           = 'foreign_contacts',
  108.23 +  back_ref      = 'other_member',
  108.24 +  default_order = '"member_id"'
  108.25 +}
  108.26 +
  108.27 +Member:add_reference{
  108.28 +  mode          = '1m',
  108.29 +  to            = "Session",
  108.30 +  this_key      = 'id',
  108.31 +  that_key      = 'member_id',
  108.32 +  ref           = 'sessions',
  108.33 +  back_ref      = 'member',
  108.34 +  default_order = '"ident"'
  108.35 +}
  108.36 +
  108.37 +Member:add_reference{
  108.38 +  mode          = '1m',
  108.39 +  to            = "Draft",
  108.40 +  this_key      = 'id',
  108.41 +  that_key      = 'author_id',
  108.42 +  ref           = 'drafts',
  108.43 +  back_ref      = 'author',
  108.44 +  default_order = '"id"'
  108.45 +}
  108.46 +
  108.47 +Member:add_reference{
  108.48 +  mode          = '1m',
  108.49 +  to            = "Suggestion",
  108.50 +  this_key      = 'id',
  108.51 +  that_key      = 'author_id',
  108.52 +  ref           = 'suggestions',
  108.53 +  back_ref      = 'author',
  108.54 +  default_order = '"id"'
  108.55 +}
  108.56 +
  108.57 +Member:add_reference{
  108.58 +  mode          = '1m',
  108.59 +  to            = "Membership",
  108.60 +  this_key      = 'id',
  108.61 +  that_key      = 'member_id',
  108.62 +  ref           = 'memberships',
  108.63 +  back_ref      = 'member',
  108.64 +  default_order = '"area_id"'
  108.65 +}
  108.66 +
  108.67 +Member:add_reference{
  108.68 +  mode          = '1m',
  108.69 +  to            = "Interest",
  108.70 +  this_key      = 'id',
  108.71 +  that_key      = 'member_id',
  108.72 +  ref           = 'interests',
  108.73 +  back_ref      = 'member',
  108.74 +  default_order = '"id"'
  108.75 +}
  108.76 +
  108.77 +Member:add_reference{
  108.78 +  mode          = '1m',
  108.79 +  to            = "Initiator",
  108.80 +  this_key      = 'id',
  108.81 +  that_key      = 'member_id',
  108.82 +  ref           = 'initiators',
  108.83 +  back_ref      = 'member',
  108.84 +  default_order = '"id"'
  108.85 +}
  108.86 +
  108.87 +Member:add_reference{
  108.88 +  mode          = '1m',
  108.89 +  to            = "Supporter",
  108.90 +  this_key      = 'id',
  108.91 +  that_key      = 'member_id',
  108.92 +  ref           = 'supporters',
  108.93 +  back_ref      = 'member',
  108.94 +  default_order = '"id"'
  108.95 +}
  108.96 +
  108.97 +Member:add_reference{
  108.98 +  mode          = '1m',
  108.99 +  to            = "Opinion",
 108.100 +  this_key      = 'id',
 108.101 +  that_key      = 'member_id',
 108.102 +  ref           = 'opinions',
 108.103 +  back_ref      = 'member',
 108.104 +  default_order = '"id"'
 108.105 +}
 108.106 +
 108.107 +Member:add_reference{
 108.108 +  mode          = '1m',
 108.109 +  to            = "Delegation",
 108.110 +  this_key      = 'id',
 108.111 +  that_key      = 'truster_id',
 108.112 +  ref           = 'outgoing_delegations',
 108.113 +  back_ref      = 'truster',
 108.114 +  default_order = '"id"'
 108.115 +}
 108.116 +
 108.117 +Member:add_reference{
 108.118 +  mode          = '1m',
 108.119 +  to            = "Delegation",
 108.120 +  this_key      = 'id',
 108.121 +  that_key      = 'trustee_id',
 108.122 +  ref           = 'incoming_delegations',
 108.123 +  back_ref      = 'trustee',
 108.124 +  default_order = '"id"'
 108.125 +}
 108.126 +
 108.127 +Member:add_reference{
 108.128 +  mode          = '1m',
 108.129 +  to            = "DirectVoter",
 108.130 +  this_key      = 'id',
 108.131 +  that_key      = 'member_id',
 108.132 +  ref           = 'direct_voter',
 108.133 +  back_ref      = 'member',
 108.134 +  default_order = '"issue_id"'
 108.135 +}
 108.136 +
 108.137 +Member:add_reference{
 108.138 +  mode          = '1m',
 108.139 +  to            = "Vote",
 108.140 +  this_key      = 'id',
 108.141 +  that_key      = 'member_id',
 108.142 +  ref           = 'vote',
 108.143 +  back_ref      = 'member',
 108.144 +  default_order = '"issue_id", "initiative_id"'
 108.145 +}
 108.146 +
 108.147 +Member:add_reference{
 108.148 +  mode                  = 'mm',
 108.149 +  to                    = "Member",
 108.150 +  this_key              = 'id',
 108.151 +  that_key              = 'id',
 108.152 +  connected_by_table    = 'contact',
 108.153 +  connected_by_this_key = 'member_id',
 108.154 +  connected_by_that_key = 'other_member_id',
 108.155 +  ref                   = 'saved_members',
 108.156 +}
 108.157 +
 108.158 +Member:add_reference{
 108.159 +  mode                  = 'mm',
 108.160 +  to                    = "Member",
 108.161 +  this_key              = 'id',
 108.162 +  that_key              = 'id',
 108.163 +  connected_by_table    = 'contact',
 108.164 +  connected_by_this_key = 'other_member_id',
 108.165 +  connected_by_that_key = 'member_id',
 108.166 +  ref                   = 'saved_by_members',
 108.167 +}
 108.168 +
 108.169 +Member:add_reference{
 108.170 +  mode                  = 'mm',
 108.171 +  to                    = "Area",
 108.172 +  this_key              = 'id',
 108.173 +  that_key              = 'id',
 108.174 +  connected_by_table    = 'membership',
 108.175 +  connected_by_this_key = 'member_id',
 108.176 +  connected_by_that_key = 'area_id',
 108.177 +  ref                   = 'areas'
 108.178 +}
 108.179 +
 108.180 +Member:add_reference{
 108.181 +  mode                  = 'mm',
 108.182 +  to                    = "Issue",
 108.183 +  this_key              = 'id',
 108.184 +  that_key              = 'id',
 108.185 +  connected_by_table    = 'interest',
 108.186 +  connected_by_this_key = 'member_id',
 108.187 +  connected_by_that_key = 'issue_id',
 108.188 +  ref                   = 'issues'
 108.189 +}
 108.190 +
 108.191 +Member:add_reference{
 108.192 +  mode                  = 'mm',
 108.193 +  to                    = "Initiative",
 108.194 +  this_key              = 'id',
 108.195 +  that_key              = 'id',
 108.196 +  connected_by_table    = 'initiator',
 108.197 +  connected_by_this_key = 'member_id',
 108.198 +  connected_by_that_key = 'initiative_id',
 108.199 +  ref                   = 'initiated_initiatives'
 108.200 +}
 108.201 +
 108.202 +Member:add_reference{
 108.203 +  mode                  = 'mm',
 108.204 +  to                    = "Initiative",
 108.205 +  this_key              = 'id',
 108.206 +  that_key              = 'id',
 108.207 +  connected_by_table    = 'supporter',
 108.208 +  connected_by_this_key = 'member_id',
 108.209 +  connected_by_that_key = 'initiative_id',
 108.210 +  ref                   = 'supported_initiatives'
 108.211 +}
 108.212 +
 108.213 +function Member.object:set_password(password)
 108.214 +  local hash = os.crypt(
 108.215 +    password,
 108.216 +    "$1$" .. multirand.string(
 108.217 +      8,
 108.218 +      "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"
 108.219 +    )
 108.220 +  )
 108.221 +  assert(hash, "os.crypt failed")
 108.222 +  self.password = hash
 108.223 +end
 108.224 +
 108.225 +function Member.object:check_password(password)
 108.226 +  if type(password) == "string" and type(self.password) == "string" then
 108.227 +    return os.crypt(password, self.password) == self.password
 108.228 +  else
 108.229 +    return false
 108.230 +  end
 108.231 +end
 108.232 +
 108.233 +function Member.object_get:published_contacts()
 108.234 +  return Member:new_selector()
 108.235 +    :join('"contact"', nil, '"contact"."other_member_id" = "member"."id"')
 108.236 +    :add_where{ '"contact"."member_id" = ?', self.id }
 108.237 +    :add_where("public")
 108.238 +    :exec()
 108.239 +end
 108.240 +
 108.241 +function Member:by_login_and_password(login, password)
 108.242 +  local selector = self:new_selector()
 108.243 +  selector:add_where{'"login" = ?', login, password }
 108.244 +  selector:add_where('"active"')
 108.245 +  selector:optional_object_mode()
 108.246 +  local member = selector:exec()
 108.247 +  if member and member:check_password(password) then
 108.248 +    return member
 108.249 +  else
 108.250 +    return nil
 108.251 +  end
 108.252 +end
 108.253 +
 108.254 +function Member:search(search_string)
 108.255 +  return self:new_selector()
 108.256 +    :add_where{ '"member"."name" ILIKE ?', "%" .. search_string:gsub("%%", "") .. "%" }
 108.257 +    :add_where("active")
 108.258 +    :exec()
 108.259 +end
   109.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.2 +++ b/model/member_count.lua	Wed Nov 18 12:00:00 2009 +0100
   109.3 @@ -0,0 +1,6 @@
   109.4 +MemberCount = mondelefant.new_class()
   109.5 +MemberCount.table = 'member_count'
   109.6 +
   109.7 +function MemberCount:get()
   109.8 +  return self:new_selector():single_object_mode():exec().total_count
   109.9 +end
  109.10 \ No newline at end of file
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/model/membership.lua	Wed Nov 18 12:00:00 2009 +0100
   110.3 @@ -0,0 +1,26 @@
   110.4 +Membership = mondelefant.new_class()
   110.5 +Membership.table = 'membership'
   110.6 +Membership.primary_key = { "area_id", "member_id" }
   110.7 +
   110.8 +Membership:add_reference{
   110.9 +  mode          = 'm1',
  110.10 +  to            = "Member",
  110.11 +  this_key      = 'member_id',
  110.12 +  that_key      = 'id',
  110.13 +  ref           = 'member',
  110.14 +}
  110.15 +
  110.16 +Membership:add_reference{
  110.17 +  mode          = 'm1',
  110.18 +  to            = "Area",
  110.19 +  this_key      = 'area_id',
  110.20 +  that_key      = 'id',
  110.21 +  ref           = 'area',
  110.22 +}
  110.23 +
  110.24 +function Membership:by_pk(area_id, member_id)
  110.25 +  return self:new_selector()
  110.26 +    :add_where{ "area_id = ? AND member_id = ?", area_id, member_id }
  110.27 +    :optional_object_mode()
  110.28 +    :exec()
  110.29 +end
  110.30 \ No newline at end of file
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/model/opinion.lua	Wed Nov 18 12:00:00 2009 +0100
   111.3 @@ -0,0 +1,35 @@
   111.4 +Opinion = mondelefant.new_class()
   111.5 +Opinion.table = 'opinion'
   111.6 +Opinion.primary_key = { "member_id", "suggestion_id" } 
   111.7 +
   111.8 +Opinion:add_reference{
   111.9 +  mode          = 'm1',
  111.10 +  to            = "Initiative",
  111.11 +  this_key      = 'initiative_id',
  111.12 +  that_key      = 'id',
  111.13 +  ref           = 'initiative',
  111.14 +}
  111.15 +
  111.16 +Opinion:add_reference{
  111.17 +  mode          = 'm1',
  111.18 +  to            = "Suggestion",
  111.19 +  this_key      = 'suggestion_id',
  111.20 +  that_key      = 'id',
  111.21 +  ref           = 'suggestion',
  111.22 +}
  111.23 +
  111.24 +Opinion:add_reference{
  111.25 +  mode          = 'm1',
  111.26 +  to            = "Member",
  111.27 +  this_key      = 'member_id',
  111.28 +  that_key      = 'id',
  111.29 +  ref           = 'member',
  111.30 +}
  111.31 +
  111.32 +function Opinion:by_pk(member_id, suggestion_id)
  111.33 +  return self:new_selector()
  111.34 +    :add_where{ "member_id = ?",     member_id }
  111.35 +    :add_where{ "suggestion_id = ?", suggestion_id }
  111.36 +    :optional_object_mode()
  111.37 +    :exec()
  111.38 +end
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/model/policy.lua	Wed Nov 18 12:00:00 2009 +0100
   112.3 @@ -0,0 +1,12 @@
   112.4 +Policy = mondelefant.new_class()
   112.5 +Policy.table = 'policy'
   112.6 +
   112.7 +Policy:add_reference{
   112.8 +  mode          = '1m',
   112.9 +  to            = "Issue",
  112.10 +  this_key      = 'id',
  112.11 +  that_key      = 'policy_id',
  112.12 +  ref           = 'issues',
  112.13 +  back_ref      = 'policy',
  112.14 +  default_order = '"created", "id"'
  112.15 +}
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/model/session.lua	Wed Nov 18 12:00:00 2009 +0100
   113.3 @@ -0,0 +1,33 @@
   113.4 +Session = mondelefant.new_class()
   113.5 +Session.table = 'session'
   113.6 +Session.primary_key = { 'ident' } 
   113.7 +
   113.8 +Session:add_reference{
   113.9 +  mode          = 'm1',
  113.10 +  to            = "Member",
  113.11 +  this_key      = 'member_id',
  113.12 +  that_key      = 'id',
  113.13 +  ref           = 'member',
  113.14 +}
  113.15 +
  113.16 +local function random_string()
  113.17 +  return multirand.string(
  113.18 +    32,
  113.19 +    '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
  113.20 +  )
  113.21 +end
  113.22 +
  113.23 +function Session:new()
  113.24 +  local session = self.prototype.new(self)  -- super call
  113.25 +  session.ident             = random_string()
  113.26 +  session.additional_secret = random_string()
  113.27 +  session:save() 
  113.28 +  return session
  113.29 +end
  113.30 +
  113.31 +function Session:by_ident(ident)
  113.32 +  local selector = self:new_selector()
  113.33 +  selector:add_where{ 'ident = ?', ident }
  113.34 +  selector:optional_object_mode()
  113.35 +  return selector:exec()
  113.36 +end
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/model/suggestion.lua	Wed Nov 18 12:00:00 2009 +0100
   114.3 @@ -0,0 +1,28 @@
   114.4 +Suggestion = mondelefant.new_class()
   114.5 +Suggestion.table = 'suggestion'
   114.6 +
   114.7 +Suggestion:add_reference{
   114.8 +  mode          = 'm1',
   114.9 +  to            = "Initiative",
  114.10 +  this_key      = 'initiative_id',
  114.11 +  that_key      = 'id',
  114.12 +  ref           = 'initiative',
  114.13 +}
  114.14 +
  114.15 +Suggestion:add_reference{
  114.16 +  mode          = 'm1',
  114.17 +  to            = "Member",
  114.18 +  this_key      = 'author_id',
  114.19 +  that_key      = 'id',
  114.20 +  ref           = 'author',
  114.21 +}
  114.22 +
  114.23 +Suggestion:add_reference{
  114.24 +  mode          = '1m',
  114.25 +  to            = "Opinion",
  114.26 +  this_key      = 'id',
  114.27 +  that_key      = 'issue_id',
  114.28 +  ref           = 'opinions',
  114.29 +  back_ref      = 'issue',
  114.30 +  default_order = '"id"'
  114.31 +}
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/model/supporter.lua	Wed Nov 18 12:00:00 2009 +0100
   115.3 @@ -0,0 +1,27 @@
   115.4 +Supporter = mondelefant.new_class()
   115.5 +Supporter.table = 'supporter'
   115.6 +Supporter.primary_key = { "initiative_id", "member_id" }
   115.7 +
   115.8 +Supporter:add_reference{
   115.9 +  mode          = 'm1',
  115.10 +  to            = "Initiative",
  115.11 +  this_key      = 'initiative_id',
  115.12 +  that_key      = 'id',
  115.13 +  ref           = 'initiative',
  115.14 +}
  115.15 +
  115.16 +Supporter:add_reference{
  115.17 +  mode          = 'm1',
  115.18 +  to            = "Member",
  115.19 +  this_key      = 'member_id',
  115.20 +  that_key      = 'id',
  115.21 +  ref           = 'member',
  115.22 +}
  115.23 +
  115.24 +function Supporter:by_pk(initiative_id, member_id)
  115.25 +  return self:new_selector()
  115.26 +    :add_where{ "initiative_id = ?", initiative_id }
  115.27 +    :add_where{ "member_id = ?", member_id }
  115.28 +    :optional_object_mode()
  115.29 +    :exec()
  115.30 +end
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/model/vote.lua	Wed Nov 18 12:00:00 2009 +0100
   116.3 @@ -0,0 +1,26 @@
   116.4 +Vote = mondelefant.new_class()
   116.5 +Vote.table = 'vote'
   116.6 +
   116.7 +Vote:add_reference{
   116.8 +  mode          = 'm1',
   116.9 +  to            = "Issue",
  116.10 +  this_key      = 'issue_id',
  116.11 +  that_key      = 'id',
  116.12 +  ref           = 'issue',
  116.13 +}
  116.14 +
  116.15 +Vote:add_reference{
  116.16 +  mode          = 'm1',
  116.17 +  to            = "Initiative",
  116.18 +  this_key      = 'initiative_id',
  116.19 +  that_key      = 'id',
  116.20 +  ref           = 'initiative',
  116.21 +}
  116.22 +
  116.23 +Vote:add_reference{
  116.24 +  mode          = 'm1',
  116.25 +  to            = "Member",
  116.26 +  this_key      = 'author_id',
  116.27 +  that_key      = 'id',
  116.28 +  ref           = 'author',
  116.29 +}
   117.1 Binary file static/icons/16/add.png has changed
   118.1 Binary file static/icons/16/application_form.png has changed
   119.1 Binary file static/icons/16/award_star_gold_2.png has changed
   120.1 Binary file static/icons/16/award_star_silver_2.png has changed
   121.1 Binary file static/icons/16/book_add.png has changed
   122.1 Binary file static/icons/16/book_edit.png has changed
   123.1 Binary file static/icons/16/cancel.png has changed
   124.1 Binary file static/icons/16/cog.png has changed
   125.1 Binary file static/icons/16/comment_add.png has changed
   126.1 Binary file static/icons/16/cross.png has changed
   127.1 Binary file static/icons/16/delete.png has changed
   128.1 Binary file static/icons/16/folder.png has changed
   129.1 Binary file static/icons/16/folder_add.png has changed
   130.1 Binary file static/icons/16/group.png has changed
   131.1 Binary file static/icons/16/house.png has changed
   132.1 Binary file static/icons/16/information.png has changed
   133.1 Binary file static/icons/16/key.png has changed
   134.1 Binary file static/icons/16/package.png has changed
   135.1 Binary file static/icons/16/page.png has changed
   136.1 Binary file static/icons/16/page_add.png has changed
   137.1 Binary file static/icons/16/script.png has changed
   138.1 Binary file static/icons/16/script_add.png has changed
   139.1 Binary file static/icons/16/stop.png has changed
   140.1 Binary file static/icons/16/table_go.png has changed
   141.1 Binary file static/icons/16/thumb_down_red.png has changed
   142.1 Binary file static/icons/16/thumb_up_green.png has changed
   143.1 Binary file static/icons/16/tick.png has changed
   144.1 Binary file static/icons/16/user_comment.png has changed
   145.1 Binary file static/icons/16/user_gray.png has changed
   146.1 Binary file static/lang/de.png has changed
   147.1 Binary file static/lang/en.png has changed
   148.1 Binary file static/lang/es.png has changed
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/static/style.css	Wed Nov 18 12:00:00 2009 +0100
   149.3 @@ -0,0 +1,559 @@
   149.4 +/*************************************************************************
   149.5 + * Some global definitions 
   149.6 + */
   149.7 +
   149.8 +body, th, td {
   149.9 +  font-family: sans-serif;
  149.10 +  font-size: 14px;
  149.11 +  padding: 0;
  149.12 +  margin: 0;
  149.13 +}
  149.14 +
  149.15 +body, a {
  149.16 +  color: #000;
  149.17 +}
  149.18 +
  149.19 +img {
  149.20 +  border: none;
  149.21 +}
  149.22 +
  149.23 +table {
  149.24 +  border-collapse: collapse;
  149.25 +  border: none;
  149.26 +}
  149.27 +
  149.28 +td, th {
  149.29 +  vertical-align: top;
  149.30 +  padding: 0.5ex 0.5em 0.5ex 0.5em;
  149.31 +}
  149.32 +
  149.33 +a.active {
  149.34 +  color: #fff; 
  149.35 +}
  149.36 +
  149.37 +.highlighted {
  149.38 +  background-color: #fa7;
  149.39 +  color: #000;
  149.40 +}
  149.41 +
  149.42 +.admin_only {
  149.43 +  font-style: italic;
  149.44 +}
  149.45 +
  149.46 +/*************************************************************************
  149.47 + * Notices, warnings and errors
  149.48 + */
  149.49 +
  149.50 +.layout_notice, .layout_error, .layout_warning {
  149.51 +        background: #fff;
  149.52 +        font-weight: bold;
  149.53 +        right: 2ex;
  149.54 +        line-height: 1.7em;
  149.55 +        position: absolute;
  149.56 +        top: 6ex;
  149.57 +        width: 60ex;
  149.58 +        -moz-opacity:0.7;
  149.59 +}
  149.60 +
  149.61 +.slot_notice, .slot_warning, .slot_error {
  149.62 +        padding: 2ex;
  149.63 +}
  149.64 +
  149.65 +.slot_notice {
  149.66 +        color: green;
  149.67 +        border: 2px solid green;
  149.68 +}
  149.69 +
  149.70 +.slot_warning {
  149.71 +        color: orange;
  149.72 +        border: 2px solid orange;
  149.73 +}
  149.74 +
  149.75 +.slot_error {
  149.76 +        color: red;
  149.77 +        border: 2px solid red;
  149.78 +}
  149.79 +
  149.80 +/*************************************************************************
  149.81 + * Navigation, search and language chooser bar 
  149.82 + */
  149.83 +
  149.84 +.topbar {
  149.85 +  margin-bottom: 1em;
  149.86 +  background-color: #444;
  149.87 +  color: #fff;
  149.88 +  font-size: 75%;
  149.89 +}
  149.90 +
  149.91 +.topbar a {
  149.92 +  color: #fff;
  149.93 +}
  149.94 +
  149.95 +.topbar  a:hover {
  149.96 +  background-color: #fff;
  149.97 +  color: #000;
  149.98 +}
  149.99 +
 149.100 +.navigation,
 149.101 +.logout_button {
 149.102 +  line-height: 250%;
 149.103 +}
 149.104 +
 149.105 +.navigation img,
 149.106 +.logout_button img {
 149.107 +  margin-right: 0.5em;
 149.108 +  vertical-align: middle;
 149.109 +}
 149.110 +
 149.111 +.navigation a,
 149.112 +.logout_button a {
 149.113 +  padding: 1ex;
 149.114 +}
 149.115 +
 149.116 +.logout_button {
 149.117 +  float: right;
 149.118 +}
 149.119 +
 149.120 +.searchbox {
 149.121 +  padding: 0.5ex 1em 0ex 1em;
 149.122 +  float: right;
 149.123 +  line-height: 250%;
 149.124 +}
 149.125 +
 149.126 +.searchbox div {
 149.127 +  display: inline;
 149.128 +}
 149.129 +
 149.130 +.searchbox select {
 149.131 +  margin-left: 0.3em;
 149.132 +  margin-right: 0.4em;
 149.133 +  font-size: 100%;
 149.134 +  width: 8em;
 149.135 +}
 149.136 +
 149.137 +.searchbox input[type=text] {
 149.138 +  width: 8em;
 149.139 +  padding: 0.25ex 0.25em 0.25ex 0.25em;
 149.140 +  margin-right: 0.5em;
 149.141 +  font-size: 100%;
 149.142 +}
 149.143 +
 149.144 +.searchbox input[type=submit] {
 149.145 +  font-size: 100%;
 149.146 +  width: 2.5em;
 149.147 +}
 149.148 +
 149.149 +/*************************************************************************
 149.150 + * Title of current page including path and actions
 149.151 + */
 149.152 +
 149.153 +.title_bar {
 149.154 +  border-bottom: 1px solid #000;
 149.155 +  margin-bottom: 2ex;
 149.156 +}
 149.157 +
 149.158 +.path {
 149.159 +  color: #444;
 149.160 +  xbackground-color: #ddd;
 149.161 +}
 149.162 +
 149.163 +.path div {
 149.164 +  margin-left: 1em;
 149.165 +  font-size: 100%;
 149.166 +  line-height: 180%;
 149.167 +}
 149.168 +
 149.169 +.path a {
 149.170 +  color: #444;
 149.171 +}
 149.172 +
 149.173 +.slot_path div {
 149.174 +  display: inline;
 149.175 +  margin-left: 1em;
 149.176 +  margin-right: 1em;
 149.177 +}
 149.178 +
 149.179 +.title {
 149.180 +  color: #000;
 149.181 +  margin-bottom: 0.5ex;
 149.182 +}
 149.183 +
 149.184 +.slot_title {
 149.185 +}
 149.186 +
 149.187 +.title div {
 149.188 +  margin-left: 0.66em;
 149.189 +  font-weight: bold;
 149.190 +  font-size: 135%;
 149.191 +  line-height: 110%;
 149.192 +}
 149.193 +
 149.194 +.title a {
 149.195 +  color: #fff;
 149.196 +}
 149.197 +
 149.198 +.avatar {
 149.199 +  float: left;
 149.200 +  margin-right: 0.5em;
 149.201 +}
 149.202 +
 149.203 +.actions {
 149.204 +  display: inline;
 149.205 +  font-size: 75%;
 149.206 +  line-height: 200%;
 149.207 +}
 149.208 +
 149.209 +.slot_actions {
 149.210 +  margin-left: 1em;
 149.211 +  display: inline;
 149.212 +}
 149.213 +
 149.214 +.actions a {
 149.215 +  padding: 0.5ex 0.5em 0.5ex 0.0em;
 149.216 +  margin-right: 1em;
 149.217 +  vertical-align: middle;
 149.218 +}
 149.219 +
 149.220 +.actions a:hover {
 149.221 +  background-color: #d7d7d7;
 149.222 +}
 149.223 +
 149.224 +.actions img {
 149.225 +  padding-left: 0.2em;
 149.226 +  padding-right: 0.2em;
 149.227 +}
 149.228 +
 149.229 +/*************************************************************************
 149.230 + * Main content
 149.231 + */
 149.232 +
 149.233 +.main {
 149.234 +  margin-left: 1em;
 149.235 +  margin-right: 1em;
 149.236 +}
 149.237 +
 149.238 +
 149.239 +/*************************************************************************
 149.240 + * ui.tab
 149.241 + */
 149.242 +
 149.243 +.ui_tabs_links {
 149.244 +  margin-top: 4ex;
 149.245 +  font-size: 75%;
 149.246 +}
 149.247 +
 149.248 +.ui_tabs_links a {
 149.249 +  padding: 1ex;
 149.250 +  margin-left: 0.5em;
 149.251 +  background-color: #e7e7e7;
 149.252 +}
 149.253 +
 149.254 +.ui_tabs_links a:hover {
 149.255 +  background-color: #d7d7d7;
 149.256 +}
 149.257 +
 149.258 +.ui_tabs_links a.selected {
 149.259 +  background-color: #444;
 149.260 +  color: #fff;
 149.261 +  text-decoration: none;
 149.262 +  padding: 1ex;
 149.263 +}
 149.264 +
 149.265 +.ui_tabs_content {
 149.266 +  border: 1px solid #444;
 149.267 +  padding: 1ex 1ex 1ex 1ex;
 149.268 +}
 149.269 +
 149.270 +/*************************************************************************
 149.271 + * ui.order
 149.272 + */
 149.273 +
 149.274 +.ui_order_head {
 149.275 +  color: #777;
 149.276 +  text-align: right;
 149.277 +  margin-bottom: 1ex;
 149.278 +  font-size: 75%;
 149.279 +}
 149.280 +
 149.281 +.ui_order_head a {
 149.282 +  color: #777;
 149.283 +  padding: 0.5ex;
 149.284 +}
 149.285 +
 149.286 +.ui_order_head a.active{
 149.287 +  color: #fff;
 149.288 +  background-color: #777;
 149.289 +  padding: 0.5ex;
 149.290 +}
 149.291 +
 149.292 +/*************************************************************************
 149.293 + * ui.paginate
 149.294 + */
 149.295 +
 149.296 +.ui_paginate_select a {
 149.297 +  padding: 0.5ex;
 149.298 +}
 149.299 +
 149.300 +/*************************************************************************
 149.301 + * ui.bargraph
 149.302 + */
 149.303 +
 149.304 +.bargraph {
 149.305 +  width: 50px;
 149.306 +}
 149.307 +
 149.308 +.bargraph div {
 149.309 +  float: left;
 149.310 +  margin-top: 0.5ex;
 149.311 +  height: 1ex;
 149.312 +}
 149.313 +
 149.314 +/*************************************************************************
 149.315 + * vertical ui.form
 149.316 + */
 149.317 +
 149.318 +.login input[type=text],
 149.319 +.vertical input[type=text],
 149.320 +.login input[type=password],
 149.321 +.vertical input[type=password],
 149.322 +.vertical textarea,
 149.323 +.vertical select {
 149.324 +  font-family: sans-serif;
 149.325 +  font-size: 100%;
 149.326 +  border: 1px solid #444;
 149.327 +  width: 40em;
 149.328 +  padding: 0.2ex 0.2em 0.2ex 0.2em;
 149.329 +  margin-bottom: 1ex;
 149.330 +}
 149.331 +
 149.332 +.login input[type=password],
 149.333 +.vertical input[type=password] {
 149.334 +  width: 16em;
 149.335 +}
 149.336 +
 149.337 +.vertical select {
 149.338 +  padding-right: 0;
 149.339 +}
 149.340 +
 149.341 +.login .ui_field_label,
 149.342 +.vertical .ui_field_label {
 149.343 +  text-transform: uppercase;
 149.344 +  font-size: 70%;
 149.345 +  line-height: 190%;
 149.346 +  font-weight: bold;
 149.347 +  color: #777;
 149.348 +  width: 15em;
 149.349 +  display: block;
 149.350 +  float: left;
 149.351 +  clear: left;
 149.352 +  text-align: right;
 149.353 +  padding-right: 0.5em;
 149.354 +}
 149.355 +
 149.356 +.login input[type=text],
 149.357 +.login input[type=password] {
 149.358 +  width: 10em;
 149.359 +}
 149.360 +
 149.361 +.login div,
 149.362 +.vertical div {
 149.363 +  clear: left;
 149.364 +}
 149.365 +
 149.366 +.vertical span {
 149.367 +  display: block;
 149.368 +  margin-bottom: 0.5ex;
 149.369 +}
 149.370 +
 149.371 +.vertical span:after {
 149.372 +  content: " ";
 149.373 +}
 149.374 +
 149.375 +.vertical span span {
 149.376 +  display: inline;
 149.377 +  margin-bottom: 0;
 149.378 +}
 149.379 +
 149.380 +.login input[type=submit],
 149.381 +.vertical input[type=submit] {
 149.382 +  font-size: 100%;
 149.383 +  margin-left: 11em;
 149.384 +  background-color: #444444;
 149.385 +  color: #fff;
 149.386 +  border: none;
 149.387 +  padding: 0.75ex;
 149.388 +}
 149.389 +
 149.390 +.login input[type=submit]:hover,
 149.391 +.vertical input[type=submit]:hover {
 149.392 +  background-color: #444444;
 149.393 +}
 149.394 +
 149.395 +/*************************************************************************
 149.396 + * Tables
 149.397 + */
 149.398 +
 149.399 +
 149.400 +table a.action {
 149.401 +  font-size: 70%;
 149.402 +  line-height: 190%;
 149.403 +  padding: 0.5ex;
 149.404 +  color: #777;
 149.405 +}
 149.406 +
 149.407 +table a.active {
 149.408 +  color: #fff; 
 149.409 +}
 149.410 +
 149.411 +th {
 149.412 +  text-align: left;
 149.413 +  border-bottom: 1px solid #000;
 149.414 +}
 149.415 +
 149.416 +tr:hover td {
 149.417 +  background-color: #ddd;
 149.418 +}
 149.419 +
 149.420 +
 149.421 +tr table tr:hover td {
 149.422 +  background-color: #fff;
 149.423 +}
 149.424 +
 149.425 +
 149.426 +/*************************************************************************
 149.427 + * Hidden inline form
 149.428 + */
 149.429 +
 149.430 +.hidden_inline_form {
 149.431 +  display: none;
 149.432 +  border: 1px solid #444;
 149.433 +  width: 42em;
 149.434 +  position: absolute;
 149.435 +  background-color: #fff;
 149.436 +  left: 5em;
 149.437 +  top: 20ex;
 149.438 +}
 149.439 +
 149.440 +.hidden_inline_form a {
 149.441 +  padding: 0.5ex;
 149.442 +  color: #fff;
 149.443 +}
 149.444 +
 149.445 +
 149.446 +.hidden_inline_form .head {
 149.447 +  background-color: #444;
 149.448 +  color: #fff;
 149.449 +  display: block;
 149.450 +  padding: 0.5ex;
 149.451 +}
 149.452 +
 149.453 +.hidden_inline_form input[type=text],
 149.454 +.hidden_inline_form textarea,
 149.455 +.hidden_inline_form select {
 149.456 +  width: 30em;
 149.457 +}
 149.458 +
 149.459 +/*************************************************************************
 149.460 + * Positive / Negtive votes
 149.461 + */
 149.462 +
 149.463 +
 149.464 +.positive_votes span {
 149.465 +  display: inline;
 149.466 +}
 149.467 +
 149.468 +.positive_votes {
 149.469 +  display: inline;
 149.470 +  background-color: #cfc;
 149.471 +  padding: 0.3ex 0.5em 0.3ex 0.5em;
 149.472 +}
 149.473 +
 149.474 +.negative_votes span {
 149.475 +  display: inline;
 149.476 +}
 149.477 +
 149.478 +.negative_votes {
 149.479 +  display: inline;
 149.480 +  background-color: #fcc;
 149.481 +  padding: 0.3ex 0.5em 0.3ex 0.5em;
 149.482 +}
 149.483 +
 149.484 +
 149.485 +
 149.486 +.active {
 149.487 +  background-color: #444;
 149.488 +  color: #fff;
 149.489 +}
 149.490 +
 149.491 +.active_red2 { background-color: #a00; color: #fff !important; }
 149.492 +.active_red1 { background-color: #f88; color: #000 !important; }
 149.493 +.active_green1 { background-color: #8f8; color: #000 !important; }
 149.494 +.active_green2 { background-color: #0a0; color: #000 !important; }
 149.495 +
 149.496 +
 149.497 +
 149.498 +
 149.499 +/*************************************************************************
 149.500 + * Issues
 149.501 + */
 149.502 +
 149.503 +.issues tr {
 149.504 +  border-bottom: 1px solid #444;
 149.505 +}
 149.506 +
 149.507 +.issues tr tr {
 149.508 +  border-bottom: none;
 149.509 +}
 149.510 +
 149.511 +/*************************************************************************
 149.512 + * delegation 
 149.513 + */
 149.514 +
 149.515 +.infobox {
 149.516 +  float: right;
 149.517 +  margin-right: 1em;
 149.518 +}
 149.519 +
 149.520 +.slot_interest,
 149.521 +.slot_support,
 149.522 +.slot_delegation {
 149.523 +  border: 2px solid #444;
 149.524 +  width: 20em;
 149.525 +  font-size: 75%;
 149.526 +  padding: 0;
 149.527 +  margin-bottom: 0.5ex;
 149.528 +}
 149.529 +
 149.530 +.infobox .head {
 149.531 +  margin: 0.5ex;
 149.532 +}
 149.533 +
 149.534 +.infobox .content {
 149.535 +  display: none;
 149.536 +  position: absolute;
 149.537 +  z-index: 10;
 149.538 +  width: 20em;
 149.539 +  background-color: #fff;
 149.540 +  border: 2px solid #444;
 149.541 +}
 149.542 +
 149.543 +.infobox .text {
 149.544 +  margin: 0.5ex;
 149.545 +  margin-bottom: 1ex;
 149.546 +}
 149.547 +
 149.548 +.infobox .member {
 149.549 +  margin: 0.5ex;
 149.550 +  display: block;
 149.551 +  font-weight: bold;
 149.552 +  margin-bottom: 1ex;
 149.553 +}
 149.554 +
 149.555 +.delegation .revoke {
 149.556 +  margin: 0.5ex;
 149.557 +}
 149.558 +
 149.559 +.lang_chooser {
 149.560 +  float: right;
 149.561 +  margin-right: 0.5em;
 149.562 +}
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/static/trace.css	Wed Nov 18 12:00:00 2009 +0100
   150.3 @@ -0,0 +1,154 @@
   150.4 +.layout_trace {
   150.5 +  position: absolute;
   150.6 +  right: 0;
   150.7 +  margin-top: 20px;
   150.8 +  border: 1px solid #404040;
   150.9 +  font-size: 70%;
  150.10 +  padding: 5px;
  150.11 +  background: #ffe0c0;
  150.12 +}
  150.13 +
  150.14 +#trace_show {
  150.15 +  cursor: pointer;
  150.16 +}
  150.17 +
  150.18 +.trace_list {
  150.19 +  margin: 0px;
  150.20 +  margin-bottom: 10px;
  150.21 +  padding: 0px;
  150.22 +  list-style-type: none;
  150.23 +}
  150.24 +
  150.25 +.trace_list .trace_list {
  150.26 +  border-top: 1px solid;
  150.27 +  margin-bottom: 0px;
  150.28 +}
  150.29 +
  150.30 +.trace_list li {
  150.31 +  margin: 3px;
  150.32 +  padding: 0px;
  150.33 +}
  150.34 +
  150.35 +.trace_head {
  150.36 +  font-weight: bold;
  150.37 +  margin: 1px;
  150.38 +}
  150.39 +
  150.40 +.trace_error {
  150.41 +  border: 3px solid red;
  150.42 +  background-color: black;
  150.43 +  color: #c00000;
  150.44 +  text-align: center;
  150.45 +  text-decoration: blink;
  150.46 +}
  150.47 +
  150.48 +.trace_error_position {
  150.49 +  color: red;
  150.50 +  text-decoration: blink;
  150.51 +  font-weight: bold;
  150.52 +}
  150.53 +
  150.54 +.trace_config {
  150.55 +  border: 1px solid #608000;
  150.56 +  background-color: #ffffff;
  150.57 +  color: #608000;
  150.58 +}
  150.59 +
  150.60 +.trace_config .trace_list {
  150.61 +  border-color: #608000;
  150.62 +}
  150.63 +
  150.64 +.trace_request {
  150.65 +  border: 1px solid #6000ff;
  150.66 +  background-color: #c080ff;
  150.67 +  color: #6000ff;
  150.68 +}
  150.69 +
  150.70 +.trace_request .trace_list {
  150.71 +  border-color: #6000ff;
  150.72 +}
  150.73 +
  150.74 +.trace_filter {
  150.75 +  border: 1px solid #606060;
  150.76 +  background-color: #c0c0c0;
  150.77 +  color: #606060;
  150.78 +}
  150.79 +
  150.80 +.trace_filter .trace_list {
  150.81 +  border-color: #606060;
  150.82 +}
  150.83 +
  150.84 +.trace_view {
  150.85 +  border: 1px solid #0000ff;
  150.86 +  background-color: #40c0ff;
  150.87 +  color: #0000ff;
  150.88 +}
  150.89 +
  150.90 +.trace_view .trace_list {
  150.91 +  border-color: #0000ff;
  150.92 +}
  150.93 +
  150.94 +.trace_action_success {
  150.95 +  border: 1px solid #006000;
  150.96 +  background-color: #80ff80;
  150.97 +  color: #006000;
  150.98 +}
  150.99 +
 150.100 +.trace_action_success .trace_list {
 150.101 +  border-color: #006000;
 150.102 +}
 150.103 +
 150.104 +.trace_action_softfail {
 150.105 +  border: 1px solid #600000;
 150.106 +  background-color: #ff6020;
 150.107 +  color: #600000;
 150.108 +}
 150.109 +
 150.110 +.trace_action_softfail .trace_list {
 150.111 +  border-color: #600000;
 150.112 +}
 150.113 +
 150.114 +.trace_action_status {
 150.115 +  font-weight: bold;
 150.116 +}
 150.117 +
 150.118 +.trace_action_neutral {
 150.119 +  border: 1px solid #600000;
 150.120 +  background-color: #ffc040;
 150.121 +  color: #600000;
 150.122 +}
 150.123 +
 150.124 +.trace_action_neutral .trace_list {
 150.125 +  border-color: #600000;
 150.126 +}
 150.127 +
 150.128 +.trace_redirect, .trace_forward {
 150.129 +  border: 1px solid #404000;
 150.130 +  background-color: #c08040;
 150.131 +  color: #404000;
 150.132 +}
 150.133 +
 150.134 +.trace_redirect .trace_list, .trace_forward .trace_list {
 150.135 +  border-color: #404000;
 150.136 +}
 150.137 +
 150.138 +.trace_exectime {
 150.139 +  border: 1px solid black;
 150.140 +  background-color: #404040;
 150.141 +  color: white;
 150.142 +}
 150.143 +
 150.144 +.trace_exectime .trace_list {
 150.145 +  border-color: white;
 150.146 +}
 150.147 +
 150.148 +.trace_close {
 150.149 +  border: 1px solid black;
 150.150 +  background-color: #605040;
 150.151 +  margin: 3px;
 150.152 +  padding: 3px;
 150.153 +  color: white;
 150.154 +  text-align: center;
 150.155 +  cursor: pointer;
 150.156 +}
 150.157 +

Impressum / About Us