# HG changeset patch
# User bsw/jbe
# Date 1258542000 -3600
# Node ID 3bfb2fcf7ab9925828422913068c8a1f30b9f216
Version alpha1
diff -r 000000000000 -r 3bfb2fcf7ab9 LICENSE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,27 @@
+Copyright (c) 2009 Public Software Group e. V., Berlin, Germany
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+3rd party license information:
+
+The icons used in Liquid Feedback (except national flags) are from Silk
+icon set 1.3 by Mark James. [ http://www.famfamfam.com/lab/icons/silk/ ]
+His work is licensed under a Creative Commons Attribution 2.5 License.
+[ http://creativecommons.org/licenses/by/2.5/ ]
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+default:
+
+
+db:
+ create_db liquid_feedback
+ psql liquid_feedback -f db/core.sql
+
+demo-db: db
+ psql liquid_feedback -f db/demo.sql
+
+
+translations-de:
+ cd ../webmcp/framework/bin/ && ./langtool.lua ~/workspace/liquid_feedback/locale/translations.de.lua ~/workspace/liquid_feedback/app ~/workspace/liquid_feedback/locale/translations.de.lua
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/_filter/20_session.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/_filter/20_session.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,13 @@
+if cgi.cookies.liquid_feedback_session then
+ app.session = Session:by_ident(cgi.cookies.liquid_feedback_session)
+end
+if not app.session then
+ app.session = Session:new()
+ cgi.add_header('Set-Cookie: liquid_feedback_session=' .. app.session.ident .. '; path=/' )
+end
+
+request.set_csrf_secret(app.session.additional_secret)
+
+locale.set{lang = app.session.lang or "en"}
+
+execute.inner()
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/_filter/21_auth.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/_filter/21_auth.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,33 @@
+local auth_needed = not (
+ request.get_module() == 'index'
+ and (
+ request.get_view() == 'login'
+ or request.get_action() == 'login'
+ or request.get_view() == "about"
+ )
+)
+
+-- if not app.session.user_id then
+-- trace.debug("DEBUG: AUTHENTICATION BYPASS ENABLED")
+-- app.session.user_id = 1
+-- end
+
+if auth_needed and app.session.member == nil then
+ trace.debug("Not authenticated yet.")
+ request.redirect{ module = 'index', view = 'login' }
+elseif auth_needed and app.session.member.locked then
+ trace.debug("Member locked.")
+ request.redirect{ module = 'index', view = 'login' }
+else
+ if auth_needed then
+ trace.debug("Authentication accepted.")
+ else
+ trace.debug("No authentication needed.")
+ end
+
+ --db:query("SELECT check_everything()")
+
+ execute.inner()
+ trace.debug("End of authentication filter.")
+end
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/_filter_view/30_navigation.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/_filter_view/30_navigation.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,94 @@
+slot.put_into("app_name", config.app_title)
+
+-- display navigation only, if user is logged in
+if app.session.member == nil then
+ slot.select('navigation', function()
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/key.png" }
+ slot.put('Login')
+ end,
+ module = 'index',
+ view = 'login'
+ }
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/information.png" }
+ slot.put('About / Impressum')
+ end,
+ module = 'index',
+ view = 'about'
+ }
+ end)
+ execute.inner()
+ return
+end
+
+slot.select('navigation', function()
+
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/house.png" }
+ slot.put(_'Home')
+ end,
+ module = 'index',
+ view = 'index'
+ }
+
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/package.png" }
+ slot.put(_'Areas')
+ end,
+ module = 'area',
+ view = 'list'
+ }
+
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/group.png" }
+ slot.put(_'Members')
+ end,
+ module = 'member',
+ view = 'list'
+ }
+
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/book_edit.png" }
+ slot.put(_'Contacts')
+ end,
+ module = 'contact',
+ view = 'list'
+ }
+
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/information.png" }
+ slot.put(_'About')
+ end,
+ module = 'index',
+ view = 'about'
+ }
+
+ if app.session.member.admin then
+
+ slot.put(" ")
+
+ ui.link{
+ attr = { class = { "admin_only" } },
+ content = function()
+ ui.image{ static = "icons/16/cog.png" }
+ slot.put(_'Admin')
+ end,
+ module = 'admin',
+ view = 'index'
+ }
+
+ end
+
+end)
+
+execute.inner()
+
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/_filter_view/31_logout_button.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/_filter_view/31_logout_button.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,17 @@
+if app.session.member == nil then
+ execute.inner()
+ return
+end
+
+slot.select('logout_button', function()
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/stop.png" }
+ slot.put(_'Logout')
+ end,
+ module = 'index',
+ action = 'logout'
+ }
+end)
+
+execute.inner()
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/_filter_view/32_searchbox.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/_filter_view/32_searchbox.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,34 @@
+if app.session.member == nil then
+ execute.inner()
+ return
+end
+
+slot.select('searchbox', function()
+
+ ui.form{
+ module = "index",
+ view = "search",
+ method = "get",
+ content = function()
+
+ ui.field.select{
+ name = "search_for",
+ foreign_records = {
+ { key = "global", name = _"Search" },
+ { key = "member", name = _"Search members" },
+ { key = "initiative", name = _"Search initiatives" },
+ { key = "issue", name = _"Search issues" },
+ },
+ foreign_id = "key",
+ foreign_name = "name"
+ }
+
+ ui.field.text{ name = "search", value = "" }
+ ui.submit{ text = _"OK" }
+
+ end
+ }
+
+end)
+
+execute.inner();
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/_layout/default.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/_layout/default.html Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/_layout/rss.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/_layout/rss.html Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/_layout/system_error.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/_layout/system_error.html Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,41 @@
+
+
+
+ Liquid Democracy System Error
+
+
+
+
+
+
+
+
+
+ System message
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
index
+
+
+
+
+
+
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/admin/_action/member_update.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/admin/_action/member_update.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,37 @@
+if not app.session.member.admin then
+ error('access denied')
+end
+
+local id = param.get_id()
+
+local member
+
+if id then
+ member = Member:new_selector():add_where{"id = ?", id}:single_object_mode():exec()
+else
+ member = Member:new()
+end
+
+param.update(member, "login", "admin", "name", "ident_number", "active")
+
+local password = param.get("password")
+if password == "********" or #password == 0 then
+ password = nil
+end
+
+if password then
+ member:set_password(password)
+end
+
+local err = member:try_save()
+
+if err then
+ slot.put_into("error", (_("Error while updating member, database reported:
(#{errormessage})"):gsub("#{errormessage}", tostring(err.message))))
+ return false
+else
+ if id then
+ slot.put_into("notice", _"Member successfully updated")
+ else
+ slot.put_into("notice", _"Member successfully registered")
+ end
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/admin/area_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/admin/area_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,62 @@
+local show_not_in_use = param.get("show_not_in_use", atom.boolean)
+
+local selector = Area:new_selector()
+if show_not_in_use then
+ selector:add_where("NOT active")
+else
+ selector:add_where("active")
+end
+
+local areas = selector:exec()
+
+slot.put_into("title", _"Area list")
+
+if app.session.member.admin then
+ slot.select("actions", function()
+ if show_not_in_use then
+ ui.link{
+ attr = { class = { "admin_only" } },
+ text = _"Show areas in use",
+ module = "admin",
+ view = "area_list"
+ }
+ else
+ ui.link{
+ attr = { class = { "admin_only" } },
+ text = _"Create new area",
+ module = "admin",
+ view = "area_show"
+ }
+ ui.link{
+ attr = { class = { "admin_only" } },
+ text = _"Show areas not in use",
+ module = "admin",
+ view = "area_list",
+ params = { show_not_in_use = true }
+ }
+ end
+ end)
+end
+
+ui.list{
+ records = areas,
+ columns = {
+ {
+ label = _"Area",
+ name = "name"
+ },
+ {
+ content = function(record)
+ if app.session.member.admin then
+ ui.link{
+ attr = { class = { "action admin_only" } },
+ text = _"Edit",
+ module = "admin",
+ view = "area_show",
+ id = record.id
+ }
+ end
+ end
+ }
+ }
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/admin/area_show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/admin/area_show.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,29 @@
+local id = param.get_id()
+
+local area
+if id then
+ area = Area:new_selector():add_where{ "id = ?", id }:single_object_mode():exec()
+end
+
+slot.put_into("title", _"Create new area")
+
+ui.form{
+ attr = { class = "vertical" },
+ record = area,
+ module = "area",
+ action = "update",
+ routing = {
+ default = {
+ mode = "redirect",
+ module = "admin",
+ view = "area_list"
+ }
+ },
+ id = area and area.id or nil,
+ content = function()
+ ui.field.text{ label = _"Name", name = "name" }
+ ui.field.boolean{ label = _"Active?", name = "active" }
+ ui.field.text{ label = _"Description", name = "description", multiline = true }
+ ui.submit{ text = _"Save" }
+ end
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/admin/index.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/admin/index.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,25 @@
+slot.put_into("title", _"Admin menu")
+
+ui.link{
+ text = "Members",
+ module = "admin",
+ view = "member_list",
+}
+
+slot.put("
")
+
+ui.link{
+ text = "Areas",
+ module = "admin",
+ view = "area_list",
+}
+
+slot.put("
")
+
+
+ui.link{
+ text = "Policies",
+ module = "admin",
+ view = "policy_list",
+}
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/admin/member_edit.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/admin/member_edit.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,34 @@
+local id = param.get_id()
+
+local member
+if id then
+ member = Member:new_selector():add_where{"id = ?", id}:optional_object_mode():exec()
+ slot.put_into("title", encode.html(_("Member: '#{login}' (#{name})", { login = member.login, name = member.name })))
+else
+ slot.put_into("title", encode.html(_"Register new member"))
+end
+
+ui.form{
+ attr = { class = "vertical" },
+ module = "admin",
+ action = "member_update",
+ id = member and member.id,
+ record = member,
+ readonly = not app.session.member.admin,
+ routing = {
+ default = {
+ mode = "redirect",
+ modules = "admin",
+ view = "member_list"
+ }
+ },
+ content = function()
+ ui.field.text{ label = _"Login", name = "login" }
+ ui.field.text{ label = _"Name", name = "name" }
+ ui.field.password{ label = _"Password", name = "password", value = (member and member.password) and "********" or "" }
+ ui.field.boolean{ label = _"Admin?", name = "admin" }
+ ui.field.boolean{ label = _"Active?", name = "active" }
+ ui.field.text{ label = _"Ident number", name = "ident_number" }
+ ui.submit{ text = _"Save" }
+ end
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/admin/member_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/admin/member_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,92 @@
+slot.put_into("title", _"Member list")
+
+slot.select("actions", function()
+ ui.link{
+ attr = { class = { "admin_only" } },
+ text = _"Register new member",
+ module = "admin",
+ view = "member_edit"
+ }
+ if param.get("show_locked") then
+ ui.link{
+ attr = { class = { "admin_only" } },
+ text = _"Show active members",
+ module = "admin",
+ view = "member_list"
+ }
+ else
+ ui.link{
+ attr = { class = { "admin_only" } },
+ text = _"Show locked members",
+ module = "admin",
+ view = "member_list",
+ params = { show_locked = true }
+ }
+ end
+end)
+
+local members_selector
+
+if param.get("show_locked", atom.boolean) then
+ members_selector = Member:new_selector()
+ :add_where("not active")
+ :add_order_by("login")
+else
+ members_selector = Member:new_selector()
+ :add_where("active")
+ :add_order_by("login")
+end
+
+ui.paginate{
+ selector = members_selector,
+ content = function()
+ ui.list{
+ records = members_selector:exec(),
+ columns = {
+ {
+ field_attr = { style = "text-align: right;" },
+ label = _"Id",
+ name = "id"
+ },
+ {
+ label = _"Login",
+ name = "login"
+ },
+ {
+ label = _"Name",
+ content = function(record)
+ util.put_highlighted_string(record.name)
+ end
+ },
+ {
+ label = _"Ident number",
+ name = "ident_number"
+ },
+ {
+ label = _"Admin?",
+ name = "admin"
+ },
+ {
+ content = function(record)
+ if app.session.member.admin and not record.active then
+ ui.field.text{ value = "locked" }
+ end
+ end
+ },
+ {
+ content = function(record)
+ if app.session.member.admin then
+ ui.link{
+ attr = { class = "action admin_only" },
+ text = _"Edit",
+ module = "admin",
+ view = "member_edit",
+ id = record.id
+ }
+ end
+ end
+ }
+ }
+ }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/area/_action/update.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/area/_action/update.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,15 @@
+local id = param.get_id()
+
+local area
+if id then
+ area = Area:new_selector():add_where{ "id = ?", id }:single_object_mode():exec()
+else
+ area = Area:new()
+end
+
+
+param.update(area, "name", "description", "active")
+
+area:save()
+
+slot.put_into("notice", _"Area successfully updated")
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/area/_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/area/_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,61 @@
+local areas_selector = param.get("areas_selector", "table")
+
+ui.order{
+ name = name,
+ selector = areas_selector,
+ options = {
+ {
+ name = "member_weight",
+ label = _"Population",
+ order_by = "area.member_weight DESC"
+ },
+ {
+ name = "direct_member_count",
+ label = _"Direct member count",
+ order_by = "area.direct_member_count DESC"
+ },
+ {
+ name = "az",
+ label = _"A-Z",
+ order_by = "area.name"
+ },
+ {
+ name = "za",
+ label = _"Z-A",
+ order_by = "area.name DESC"
+ }
+ },
+ content = function()
+ ui.list{
+ records = areas_selector:exec(),
+ columns = {
+ {
+ content = function(record)
+ if record.member_weight and record.direct_member_count then
+ local max_value = MemberCount:get()
+ ui.bargraph{
+ max_value = max_value,
+ width = 100,
+ bars = {
+ { color = "#444", value = record.direct_member_count },
+ { color = "#777", value = record.member_weight - record.direct_member_count },
+ { color = "#ddd", value = max_value - record.member_weight },
+ }
+ }
+ end
+ end
+ },
+ {
+ content = function(record)
+ ui.link{
+ text = record.name,
+ module = "area",
+ view = "show",
+ id = record.id
+ }
+ end
+ }
+ }
+ }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/area/list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/area/list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+slot.put_into("title", _'Area list')
+
+local areas_selector = Area:new_selector():add_where("active")
+
+execute.view{
+ module = "area",
+ view = "_list",
+ params = { areas_selector = areas_selector }
+}
+
+execute.view{
+ module = "delegation",
+ view = "_show_box"
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/area/show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/area/show.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,114 @@
+local area = Area:new_selector():add_where{ "id = ?", param.get_id() }:single_object_mode():exec()
+
+slot.put_into("title", encode.html(_"Area '#{name}'":gsub("#{name}", area.name)))
+
+ui.container{
+ attr = { class = "vertical"},
+ content = function()
+ ui.field.text{ value = area.description }
+ end
+}
+
+
+slot.select("actions", function()
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/folder_add.png" }
+ slot.put(_"Create new issue")
+ end,
+ module = "initiative",
+ view = "new",
+ params = { area_id = area.id }
+ }
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/table_go.png" }
+ slot.put(_"Delegate")
+ end,
+ module = "delegation",
+ view = "new",
+ params = { area_id = area.id }
+ }
+end)
+
+execute.view{
+ module = "membership",
+ view = "_show_box",
+ params = { area = area }
+}
+
+execute.view{
+ module = "delegation",
+ view = "_show_box",
+ params = { area_id = area.id }
+}
+
+ui.tabs{
+ {
+ name = "new",
+ label = _"New",
+ content = function()
+ execute.view{
+ module = "issue",
+ view = "_list",
+ params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.accepted ISNULL AND issue.closed ISNULL"), for_area_list = true }
+ }
+ end
+ },
+ {
+ name = "accepted",
+ label = _"In discussion",
+ content = function()
+ execute.view{
+ module = "issue",
+ view = "_list",
+ 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 }
+ }
+ end
+ },
+ {
+ name = "half_frozen",
+ label = _"Frozen",
+ content = function()
+ execute.view{
+ module = "issue",
+ view = "_list",
+ params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.half_frozen NOTNULL AND issue.closed ISNULL"), for_area_list = true }
+ }
+ end
+ },
+ {
+ name = "frozen",
+ label = _"Voting",
+ content = function()
+ execute.view{
+ module = "issue",
+ view = "_list",
+ params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL"), for_area_list = true }
+ }
+ end
+ },
+ {
+ name = "finished",
+ label = _"Finished",
+ content = function()
+ execute.view{
+ module = "issue",
+ view = "_list",
+ params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.closed NOTNULL AND ranks_available"), for_area_list = true }
+ }
+ end
+ },
+ {
+ name = "cancelled",
+ label = _"Cancelled",
+ content = function()
+ execute.view{
+ module = "issue",
+ view = "_list",
+ params = { issues_selector = area:get_reference_selector("issues"):add_where("issue.closed NOTNULL AND NOT ranks_available"), for_area_list = true }
+ }
+ end
+ },
+}
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/contact/_action/add_member.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/contact/_action/add_member.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,27 @@
+local member = app.session.member
+local other_member = Member:by_id(param.get_id())
+
+local public = param.get("public", atom.boolean)
+
+local contact = Contact:by_pk(member.id, other_member.id)
+
+if public == nil and contact then
+ slot.put_into("error", _"Member is already saved in your contacts!")
+ return false
+end
+
+if contact then
+ contact:destroy()
+end
+
+contact = Contact:new()
+contact.member_id = member.id
+contact.other_member_id = other_member.id
+contact.public = public or false
+contact:save()
+
+if public then
+ slot.put_into("notice", _"Member has been saved as public contact")
+else
+ slot.put_into("notice", _"Member has been saved as private contact")
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/contact/_action/remove_member.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/contact/_action/remove_member.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,7 @@
+local member = app.session.member
+local other_member = Member:by_id(param.get_id())
+
+local contact = Contact:by_pk(member.id, other_member.id)
+contact:destroy()
+
+slot.put_into("notice", _"Member has been removed from your contacts")
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/contact/_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/contact/_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,132 @@
+
+local contacts_selector = Contact:new_selector()
+ :add_where{ "member_id = ?", app.session.member.id }
+ :join("member", nil, "member.id = contact.other_member_id")
+ :add_order_by("member.login")
+
+ui.paginate{
+ selector = contacts_selector,
+ content = function()
+ local contacts = contacts_selector:exec()
+ if #contacts == 0 then
+ ui.field.text{ value = _"You didn't saved any member as contact yet." }
+ else
+ ui.list{
+ records = contacts,
+ columns = {
+ {
+ label = _"Login",
+ content = function(record)
+ ui.link{
+ text = record.other_member.login,
+ module = "member",
+ view = "show",
+ id = record.other_member_id
+ }
+ end
+ },
+ {
+ label = _"Name",
+ content = function(record)
+ ui.link{
+ text = record.other_member.name,
+ module = "member",
+ view = "show",
+ id = record.other_member_id
+ }
+ end
+ },
+ {
+ label = _"Published",
+ content = function(record)
+ ui.field.boolean{ value = record.public }
+ end
+ },
+ {
+ content = function(record)
+ if record.public then
+ ui.link{
+ attr = { class = "action" },
+ text = _"Hide",
+ module = "contact",
+ action = "add_member",
+ id = record.other_member_id,
+ params = { public = false },
+ routing = {
+ default = {
+ mode = "redirect",
+ module = request.get_module(),
+ view = request.get_view(),
+ id = param.get_id_cgi(),
+ params = param.get_all_cgi()
+ }
+ }
+ }
+ else
+ ui.link{
+ attr = { class = "action" },
+ text = _"Publish",
+ module = "contact",
+ action = "add_member",
+ id = record.other_member_id,
+ params = { public = true },
+ routing = {
+ default = {
+ mode = "redirect",
+ module = request.get_module(),
+ view = request.get_view(),
+ id = param.get_id_cgi(),
+ params = param.get_all_cgi()
+ }
+ }
+ }
+ end
+ end
+ },
+ {
+ content = function(record)
+ ui.link{
+ attr = { class = "action" },
+ text = _"Remove",
+ module = "contact",
+ action = "remove_member",
+ id = record.other_member_id,
+ routing = {
+ default = {
+ mode = "redirect",
+ module = request.get_module(),
+ view = request.get_view(),
+ id = param.get_id_cgi(),
+ params = param.get_all_cgi()
+ }
+ }
+ }
+ end
+ },
+ {
+ content = function(record)
+ ui.link{
+ attr = { class = "action" },
+ text = _"Global delegation",
+ module = "delegation",
+ action = "update",
+ params = {
+ trustee_id = record.other_member_id,
+ },
+ routing = {
+ default = {
+ mode = "redirect",
+ module = request.get_module(),
+ view = request.get_view(),
+ id = param.get_id_cgi(),
+ params = param.get_all_cgi()
+ }
+ }
+ }
+ end
+ }
+ }
+ }
+ end
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/contact/list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/contact/list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,7 @@
+slot.put_into("title", _"Contacts")
+
+execute.view{
+ module = "contact",
+ view = "_list",
+ params = { contacts_selector = app.session.member:get_reference_selector("contacts") }
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/delegation/_action/update.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/delegation/_action/update.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,53 @@
+local truster_id = app.session.member.id
+
+local trustee_id = param.get("trustee_id", atom.integer)
+
+local area_id = param.get("area_id", atom.integer)
+
+local issue_id = param.get("issue_id", atom.integer)
+
+if issue_id then
+ area_id = nil
+end
+
+local delegation = Delegation:by_pk(truster_id, area_id, issue_id)
+
+if param.get("delete") then
+
+ if delegation then
+
+ delegation:destroy()
+
+ if issue_id then
+ slot.put_into("notice", _"Your delegation for this issue has been deleted.")
+ elseif area_id then
+ slot.put_into("notice", _"Your delegation for this area has been deleted.")
+ else
+ slot.put_into("notice", _"Your global delegation has been deleted.")
+ end
+
+ end
+
+else
+
+ if not delegation then
+ delegation = Delegation:new()
+ delegation.truster_id = truster_id
+ delegation.area_id = area_id
+ delegation.issue_id = issue_id
+ end
+
+ delegation.trustee_id = trustee_id
+
+ delegation:save()
+
+ if issue_id then
+ slot.put_into("notice", _"Your delegation for this issue has been updated.")
+ elseif area_id then
+ slot.put_into("notice", _"Your delegation for this area has been updated.")
+ else
+ slot.put_into("notice", _"Your global delegation has been updated.")
+ end
+
+end
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/delegation/_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/delegation/_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,50 @@
+local selector = param.get("selector", "table")
+
+ui.paginate{
+ selector = selector,
+ content = function()
+ ui.list{
+ records = selector:exec(),
+ columns = {
+ {
+ label = _"Truster",
+ content = function(record)
+ ui.link{
+ content = record.truster.name,
+ module = "member",
+ view = "show",
+ id = record.truster.id
+ }
+ end
+ },
+ {
+ label = _"Trustee",
+ content = function(record)
+ ui.link{
+ content = record.trustee.name,
+ module = "member",
+ view = "show",
+ id = record.trustee.id
+ }
+ end
+ },
+ {
+ label = _"Area",
+ content = function(record)
+ if record.area then
+ ui.field.text{ value = record.area.name }
+ end
+ end
+ },
+ {
+ label = _"Issue",
+ content = function(record)
+ if record.issue then
+ ui.field.text{ value = record.issue.id }
+ end
+ end
+ },
+ }
+ }
+ end
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/delegation/_show_box.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/delegation/_show_box.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,114 @@
+slot.select("delegation", function()
+
+ local delegation
+ local area_id
+ local issue_id
+
+ local scope = "global"
+
+ if param.get("initiative_id", atom.integer) then
+ issue_id = Initiative:by_id(param.get("initiative_id", atom.integer)).issue_id
+ scope = "issue"
+ end
+
+ if param.get("issue_id", atom.integer) then
+ issue_id = param.get("issue_id", atom.integer)
+ scope = "issue"
+ end
+
+ if param.get("area_id", atom.integer) then
+ area_id = param.get("area_id", atom.integer)
+ scope = "area"
+ end
+
+
+
+ local delegation
+
+ if issue_id then
+ delegation = Delegation:by_pk(app.session.member.id, nil, issue_id)
+ if not delegation then
+ local issue = Issue:by_id(issue_id)
+ delegation = Delegation:by_pk(app.session.member.id, issue.area_id)
+ end
+ elseif area_id then
+ delegation = Delegation:by_pk(app.session.member.id, area_id)
+ end
+
+ if not delegation then
+ delegation = Delegation:by_pk(app.session.member.id)
+ end
+ if delegation then
+ ui.container{
+ attr = {
+ class = "head",
+ style = "cursor: pointer;",
+ onclick = "document.getElementById('delegation_content').style.display = 'block';"
+ },
+ content = _"Your vote is delegated. [more]"
+ }
+ ui.container{
+ attr = { class = "content", id = "delegation_content" },
+ content = function()
+
+ 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 }
+
+ for i, record in ipairs(delegation_chain) do
+ local style
+ if record.participation then
+ style = "font-weight: bold;"
+ end
+ if record.overridden then
+ style = "color: #777;"
+ end
+ if not record.active then
+ style = "text-decoration: line-through;"
+ end
+ if record.scope_in then
+ ui.field.text{
+ value = " v " .. record.scope_in .. " v "
+ }
+ end
+ local name = record.name
+ if record.member_id == app.session.member.id then
+ name = _"Me"
+ end
+ ui.field.text{
+ attr = { style = style },
+ value = name
+ }
+ end
+
+ ui.link{
+ attr = { class = "revoke" },
+ content = function()
+ ui.image{ static = "icons/16/delete.png" }
+ slot.put(_"Revoke")
+ end,
+ module = "delegation",
+ action = "update",
+ params = { issue_id = delegation.issue_id, area_id = delegation.area_id, delete = true },
+ routing = {
+ default = {
+ mode = "redirect",
+ module = request.get_module(),
+ view = request.get_view(),
+ id = param.get_id_cgi(),
+ params = param.get_all_cgi()
+ }
+ }
+ }
+
+ ui.container{
+ attr = {
+ class = "head",
+ style = "cursor: pointer;",
+ onclick = "document.getElementById('delegation_content').style.display = 'none';"
+ },
+ content = _"Click here to close."
+ }
+ end
+ }
+ end
+
+end)
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/delegation/new.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/delegation/new.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,45 @@
+local area = Area:by_id(param.get("area_id", atom.integer))
+if area then
+ slot.put_into("title", encode.html(_"Set delegation for Area '#{name}'":gsub("#{name}", area.name)))
+end
+
+local issue = Issue:by_id(param.get("issue_id", atom.integer))
+if issue then
+ 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)))
+end
+
+
+local contact_members = Member:new_selector()
+ :add_where{ "contact.member_id = ?", app.session.member.id }
+ :join("contact", nil, "member.id = contact.other_member_id")
+ :add_order_by("member.login")
+ :exec()
+
+
+ui.form{
+ attr = { class = "vertical" },
+ module = "delegation",
+ action = "update",
+ params = {
+ area_id = area and area.id or nil,
+ issue_id = issue and issue.id or nil,
+ },
+ routing = {
+ default = {
+ mode = "redirect",
+ module = area and "area" or "issue",
+ view = "show",
+ id = area and area.id or issue.id,
+ }
+ },
+ content = function()
+ ui.field.select{
+ label = _"Trustee",
+ name = "trustee_id",
+ foreign_records = contact_members,
+ foreign_id = "id",
+ foreign_name = "name"
+ }
+ ui.submit{ text = _"Save" }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/draft/_action/add.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/draft/_action/add.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+local initiative = Initiative:by_id(param.get("initiative_id", atom.integer))
+
+if Initiator:by_pk(initiative.id, app.session.member.id) then
+ local draft = Draft:new()
+ draft.author_id = app.session.member.id
+ draft.initiative_id = initiative.id
+ draft.content = param.get("content")
+ draft:save()
+
+ slot.put_into("notice", _"New draft has been added to initiative")
+
+else
+ error('access denied')
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/draft/_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/draft/_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,30 @@
+ui.list{
+ records = param.get("drafts", "table"),
+ columns = {
+ {
+ label = _"Id",
+ name = "id"
+ },
+ {
+ label = _"Created at",
+ content = function(record)
+ ui.field.text{ value = format.timestamp(record.created) }
+ end
+ },
+ {
+ label = _"Author",
+ name = "author_name"
+ },
+ {
+ content = function(record)
+ ui.link{
+ attr = { class = "action" },
+ text = _"Show",
+ module = "draft",
+ view = "show",
+ id = record.id
+ }
+ end
+ }
+ }
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/draft/_show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/draft/_show.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+local draft = param.get("draft", "table")
+
+ui.form{
+ attr = { class = "vertical" },
+ record = draft,
+ readonly = true,
+ content = function()
+
+ ui.field.text{ label = _"Initiative", value = draft.initiative.name }
+ ui.field.text{ label = _"Author", name = "author_name" }
+ ui.field.text{ label = _"Content", name = "content" }
+
+ end
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/draft/new.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/draft/new.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,25 @@
+slot.put_into("title", _"Add new draft")
+
+local initiative_id = param.get("initiative_id")
+
+ui.form{
+ attr = { class = "vertical" },
+ module = "draft",
+ action = "add",
+ params = { initiative_id = initiative_id },
+ routing = {
+ default = {
+ mode = "redirect",
+ module = "initiative",
+ view = "show",
+ id = initiative_id
+ }
+ },
+ content = function()
+
+ ui.field.text{ label = _"Author", value = app.session.member.name, readonly = true }
+ ui.field.text{ label = _"Content", name = "content", multiline = true }
+
+ ui.submit{ text = _"Save" }
+ end
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/draft/show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/draft/show.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,7 @@
+local draft = Draft:new_selector():add_where{ "id = ?", param.get_id() }:single_object_mode():exec()
+
+execute.view{
+ module = "draft",
+ view = "_show",
+ params = { draft = draft }
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/index/_action/login.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/index/_action/login.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,16 @@
+local member = Member:by_login_and_password(param.get('login'), param.get('password'))
+
+if member then
+ app.session.member = member
+ app.session:save()
+ slot.select("notice", function()
+ ui.tag{ content = _'Login successful!' }
+ end)
+ trace.debug('User authenticated')
+else
+ slot.select("notice", function()
+ ui.tag{ content = _'Invalid username or password!' }
+ end)
+ trace.debug('User NOT authenticated')
+ return false
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/index/_action/logout.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/index/_action/logout.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,4 @@
+if app.session then
+ app.session:destroy()
+ slot.put_into("notice", _"Logout successful")
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/index/_action/set_lang.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/index/_action/set_lang.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,3 @@
+app.session.lang = param.get("lang")
+
+app.session:save()
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/index/_action/update_password.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/index/_action/update_password.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,23 @@
+local old_password = param.get("old_password")
+local new_password1 = param.get("new_password1")
+local new_password2 = param.get("new_password2")
+
+if not Member:by_login_and_password(app.session.member.login, old_password) then
+ slot.put_into("error", _"Old password is wrong")
+ return false
+end
+
+if new_password1 ~= new_password2 then
+ slot.put_into("error", _"New passwords does not match.")
+ return false
+end
+
+if #new_password1 < 8 then
+ slot.put_into("error", _"New passwords is too short.")
+ return false
+end
+
+app.session.member:set_password(new_password1)
+app.session.member:save()
+
+slot.put_into("notice", _"Your password has been updated successfully")
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/index/about.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/index/about.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,92 @@
+slot.put_into("title", encode.html(_"About LiquidFeedback"))
+
+
+slot.put("
")
+ui.field.text{ attr = { style = "font-weight: bold;" }, value = "Diensteanbieter:" }
+slot.put("
")
+
+slot.put(config.app_service_provider)
+
+slot.put("
")
+slot.put("
")
+slot.put("
")
+
+
+ui.field.text{ attr = { style = "font-weight: bold;" }, value = "Dieser Dienst ist mit folgender Software realisiert worden:" }
+slot.put("
")
+
+local tmp = {
+ {
+ name = "LiquidFeedback Frontend",
+ url = "http://www.public-software-group.org/liquid_feedback",
+ version = config.app_version,
+ license = "MIT/X11",
+ license_url = "http://www.public-software-group.org/licenses"
+ },
+ {
+ name = "LiquidFeedback Core",
+ url = "http://www.public-software-group.org/liquid_feedback",
+ version = db:query("SELECT * from liquid_feedback_version;")[1].string,
+ license = "MIT/X11",
+ license_url = "http://www.public-software-group.org/licenses"
+ },
+ {
+ name = "WebMCP",
+ url = "http://www.public-software-group.org/webmcp",
+ version = _WEBMCP_VERSION,
+ license = "MIT/X11",
+ license_url = "http://www.public-software-group.org/licenses"
+ },
+ {
+ name = "Lua",
+ url = "http://www.lua.org",
+ version = _VERSION:gsub("Lua ", ""),
+ license = "MIT/X11",
+ license_url = "http://www.lua.org/license.html"
+ },
+ {
+ name = "PostgreSQL",
+ url = "http://www.postgresql.org/",
+ version = db:query("SELECT version();")[1].version:gsub("PostgreSQL ", ""):gsub("on.*", ""),
+ license = "BSD",
+ license_url = "http://www.postgresql.org/about/licence"
+ },
+}
+
+ui.list{
+ records = tmp,
+ columns = {
+ {
+ label = _"Software",
+ content = function(record)
+ ui.link{
+ content = record.name,
+ external = record.url
+ }
+ end
+ },
+ {
+ label = _"Version",
+ content = function(record) ui.field.text{ value = record.version } end
+ },
+ {
+ label = _"License",
+ content = function(record)
+ ui.link{
+ content = record.license,
+ external = record.license_url
+ }
+ end
+
+ }
+ }
+}
+
+slot.put("
")
+slot.put("
")
+slot.put("
")
+
+ui.field.text{ attr = { style = "font-weight: bold;" }, value = "3rd party license information:" }
+slot.put("
")
+slot.put('The icons used in Liquid Feedback (except national flags) are from Silk icon set 1.3 by Mark James. His work is licensed under a Creative Commons Attribution 2.5 License.')
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/index/change_password.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/index/change_password.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,32 @@
+
+slot.put_into("title", _"Change password")
+
+slot.select("actions", function()
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/cancel.png" }
+ slot.put(_"Cancel")
+ end,
+ module = "index",
+ view = "index"
+ }
+end)
+
+ui.form{
+ attr = { class = "vertical" },
+ module = "index",
+ action = "update_password",
+ routing = {
+ ok = {
+ mode = "redirect",
+ module = "index",
+ view = "index"
+ }
+ },
+ content = function()
+ ui.field.password{ label = _"Old password", name = "old_password" }
+ ui.field.password{ label = _"New password", name = "new_password1" }
+ ui.field.password{ label = _"Repeat new password", name = "new_password2" }
+ ui.submit{ value = _"Change password" }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/index/index.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/index/index.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,82 @@
+slot.select("title", function()
+ ui.image{
+ attr = { class = "avatar" },
+ module = "member",
+ view = "avatar",
+ extension = "jpg",
+ id = app.session.member.id
+ }
+end)
+
+slot.select("title", function()
+ ui.container{
+ attr = { class = "lang_chooser" },
+ content = function()
+ for i, lang in ipairs{"en", "de"} do
+ ui.link{
+ content = function()
+ ui.image{
+ static = "lang/" .. lang .. ".png",
+ attr = { style = "margin-left: 0.5em;", alt = lang }
+ }
+ end,
+ module = "index",
+ action = "set_lang",
+ params = { lang = lang },
+ routing = {
+ default = {
+ mode = "redirect",
+ module = request.get_module(),
+ view = request.get_view(),
+ id = param.get_id_cgi(),
+ params = param.get_all_cgi()
+ }
+ }
+ }
+ end
+ end
+ }
+end)
+
+slot.put_into("title", encode.html(config.app_title))
+
+slot.select("actions", function()
+ slot.put(_"Logged in as:")
+ slot.put(" ")
+ slot.put(app.session.member.login)
+ slot.put(" | ")
+
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/user_gray.png" }
+ slot.put(_"Upload avatar")
+ end,
+ module = "member",
+ view = "edit_avatar"
+ }
+
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/application_form.png" }
+ slot.put(_"Edit my page")
+ end,
+ module = "member",
+ view = "edit"
+ }
+
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/key.png" }
+ slot.put(_"Change password")
+ end,
+ module = "index",
+ view = "change_password"
+ }
+end)
+
+execute.view{
+ module = "member",
+ view = "_show",
+ params = { member = app.session.member }
+}
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/index/login.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/index/login.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,41 @@
+slot.put_into("title", encode.html(config.app_title))
+
+ui.tag{
+ tag = 'p',
+ content = 'You need to be logged in, to use this system.'
+}
+
+ui.form{
+ attr = { class = "login" },
+ module = 'index',
+ action = 'login',
+ routing = {
+ ok = {
+ mode = 'redirect',
+ module = 'index',
+ view = 'index'
+ },
+ error = {
+ mode = 'forward',
+ module = 'index',
+ view = 'login',
+ }
+ },
+ content = function()
+ ui.field.text{
+ attr = { id = "username_field" },
+ label = _'Username',
+ html_name = 'login',
+ value = ''
+ }
+ ui.script{ script = 'document.getElementById("username_field").focus();' }
+ ui.field.password{
+ label = _'Password',
+ html_name = 'password',
+ value = ''
+ }
+ ui.submit{
+ text = _'Login'
+ }
+ end
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/index/search.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/index/search.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,53 @@
+local search_for = param.get("search_for", atom.string)
+local search_string = param.get("search", atom.string)
+
+search_for = search_for or "global"
+
+slot.put_into("title", _("Search results for: '#{search}'", { search = search_string }))
+
+
+local members = {}
+local issues = {}
+local initiatives = {}
+
+
+if search_for == "global" or search_for == "member" then
+ members = Member:search(search_string)
+end
+
+if search_for == "global" or search_for == "issue" then
+ issues = Issue:search(search_string)
+end
+
+if search_for == "initiative" then
+ initiatives = Initiative:search(search_string)
+end
+
+
+if #members > 0 then
+ ui.heading{ content = _"Members" }
+ execute.view{
+ module = "member",
+ view = "_list",
+ params = { members = members, highlight_string = search_string },
+ }
+end
+
+if #issues > 0 then
+ ui.heading{ content = _"Issues" }
+ execute.view{
+ module = "issue",
+ view = "_list",
+ params = { issues = issues, highlight_string = search_string },
+ }
+end
+
+if #initiatives > 0 then
+ ui.heading{ content = _"Initiatives" }
+ execute.view{
+ module = "initiative",
+ view = "_list",
+ params = { initiatives = initiatives, highlight_string = search_string },
+ }
+end
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/initiative/_action/add_support.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/initiative/_action/add_support.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,27 @@
+local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
+
+local member = app.session.member
+
+local supporter = Supporter:by_pk(initiative.id, member.id)
+
+local last_draft = Draft:new_selector()
+ :add_where{ "initiative_id = ?", initiative.id }
+ :add_order_by("id DESC")
+ :limit(1)
+ :single_object_mode()
+ :exec()
+
+if not supporter then
+ supporter = Supporter:new()
+ supporter.member_id = member.id
+ supporter.initiative_id = initiative.id
+ supporter.draft_id = last_draft.id
+ supporter:save()
+ slot.put_into("notice", _"Your support has been added to this initiative")
+elseif supporter.draft_id ~= last_draft.id then
+ supporter.draft_id = last_draft.id
+ supporter:save()
+ slot.put_into("notice", _"Your support has been updated to the latest draft")
+else
+ slot.put_into("notice", _"You are already supporting the latest draft")
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/initiative/_action/create.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/initiative/_action/create.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,54 @@
+local issue
+local area
+
+db:query("BEGIN")
+
+local issue_id = param.get("issue_id", atom.integer)
+if issue_id then
+ issue = Issue:new_selector():add_where{"id=?",issue_id}:single_object_mode():exec()
+ area = issue.area
+
+else
+ local area_id = param.get("area_id", atom.integer)
+ area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
+end
+
+local initiative = Initiative:new()
+
+if not issue then
+ issue = Issue:new()
+ issue.area_id = area.id
+ issue.policy_id = param.get("policy_id", atom.integer)
+ issue:save()
+end
+
+initiative.issue_id = issue.id
+param.update(initiative, "name")
+initiative:save()
+
+local draft = Draft:new()
+draft.initiative_id = initiative.id
+draft.content = param.get("draft")
+draft.author_id = app.session.member.id
+draft:save()
+
+local initiator = Initiator:new()
+initiator.initiative_id = initiative.id
+initiator.member_id = app.session.member.id
+initiator:save()
+
+local supporter = Supporter:new()
+supporter.initiative_id = initiative.id
+supporter.member_id = app.session.member.id
+supporter.draft_id = draft.id
+supporter:save()
+
+db:query("COMMIT")
+
+slot.put_into("notice", _"Initiative successfully created")
+
+request.redirect{
+ module = "initiative",
+ view = "show",
+ id = initiative.id
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/initiative/_action/remove_support.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/initiative/_action/remove_support.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,12 @@
+local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
+
+local member = app.session.member
+
+local supporter = Supporter:by_pk(initiative.id, member.id)
+
+if supporter then
+ supporter:destroy()
+ slot.put_into("notice", _"Your support has been removed from this initiative")
+else
+ slot.put_into("notice", _"You are already not supporting this initiative")
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/initiative/_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/initiative/_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,116 @@
+local initiatives_selector = param.get("initiatives_selector", "table")
+initiatives_selector:join("issue", nil, "issue.id = initiative.issue_id")
+
+local issue = param.get("issue", "table")
+
+local order_options = {}
+
+if issue and issue.ranks_available then
+ order_options[#order_options+1] = {
+ name = "rank",
+ label = _"Rank",
+ order_by = "initiative.rank"
+ }
+end
+
+order_options[#order_options+1] = {
+ name = "support",
+ label = _"Support",
+ order_by = "initiative.supporter_count::float / issue.population::float DESC"
+}
+
+order_options[#order_options+1] = {
+ name = "support_si",
+ label = _"Support S+I",
+ order_by = "initiative.satisfied_informed_supporter_count::float / issue.population::float DESC"
+}
+
+order_options[#order_options+1] = {
+ name = "newest",
+ label = _"Newest",
+ order_by = "initiative.created DESC"
+}
+
+order_options[#order_options+1] = {
+ name = "oldest",
+ label = _"Oldest",
+ order_by = "initiative.created"
+}
+
+local name = "initiative_list"
+if issue then
+ name = "issue_" .. tostring(issue.id) .. "_initiative_list"
+end
+
+ui.order{
+ name = name,
+ selector = initiatives_selector,
+ options = order_options,
+ content = function()
+ ui.paginate{
+ selector = initiatives_selector,
+ content = function()
+ local initiatives = initiatives_selector:exec()
+ local columns = {}
+ local issue = initiatives[1] and initiatives[1].issue or {}
+ if issue.accepted and issue.closed and issue.ranks_available then
+ columns[#columns+1] = {
+ content = function(record)
+ ui.field.rank{ value = record.rank }
+ end
+ }
+ columns[#columns+1] = {
+ content = function(record)
+ if record.negative_votes and record.positive_votes then
+ local max_value = record.issue.voter_count
+ trace.debug(record.issue.voter_count)
+ ui.bargraph{
+ max_value = max_value,
+ width = 100,
+ bars = {
+ { color = "#0a0", value = record.positive_votes },
+ { color = "#aaa", value = max_value - record.negative_votes - record.positive_votes },
+ { color = "#a00", value = record.negative_votes },
+ }
+ }
+ end
+ end
+ }
+ else
+ columns[#columns+1] = {
+ content = function(record)
+ local max_value = (record.issue.population or 0)
+ ui.bargraph{
+ max_value = max_value,
+ width = 100,
+ bars = {
+ { color = "#0a0", value = (record.satisfied_informed_supporter_count or 0) },
+ { color = "#8f8", value = (record.supporter_count or 0) - (record.satisfied_informed_supporter_count or 0) },
+ { color = "#ddd", value = max_value - (record.supporter_count or 0) },
+ }
+ }
+ end
+ }
+ end
+ columns[#columns+1] = {
+ content = function(record)
+ ui.link{
+ content = function()
+ util.put_highlighted_string(record.shortened_name)
+ end,
+ module = "initiative",
+ view = "show",
+ id = record.id
+ }
+ end
+ }
+
+ ui.list{
+ attr = { class = "initiatives" },
+ records = initiatives,
+ columns = columns
+ }
+ end
+ }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/initiative/new.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/initiative/new.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,45 @@
+local issue
+local area
+
+local issue_id = param.get("issue_id", atom.integer)
+if issue_id then
+ issue = Issue:new_selector():add_where{"id=?",issue_id}:single_object_mode():exec()
+ area = issue.area
+
+else
+ local area_id = param.get("area_id", atom.integer)
+ area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
+end
+
+if issue_id then
+ slot.put_into("title", _"Add new initiative to issue")
+else
+ slot.put_into("title", _"Create new issue")
+end
+
+ui.form{
+ module = "initiative",
+ action = "create",
+ params = {
+ area_id = area.id,
+ issue_id = issue and issue.id or nil
+ },
+ attr = { class = "vertical" },
+ content = function()
+ ui.field.text{ label = _"Area", value = area.name }
+ if issue_id then
+ ui.field.text{ label = _"Issue", value = issue_id }
+ else
+ ui.field.select{
+ label = _"Policy",
+ name = "policy_id",
+ foreign_records = Policy:new_selector():exec(),
+ foreign_id = "id",
+ foreign_name = "name"
+ }
+ end
+ ui.field.text{ label = _"Name", name = "name" }
+ ui.field.text{ label = _"Draft", name = "draft", multiline = true }
+ ui.submit{ text = _"Save" }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/initiative/show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/initiative/show.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,176 @@
+local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
+
+slot.put_into("html_head", '')
+
+execute.view{
+ module = "supporter",
+ view = "_show_box",
+ params = { initiative = initiative }
+}
+
+execute.view{
+ module = "delegation",
+ view = "_show_box",
+ params = { issue_id = initiative.issue_id }
+}
+
+
+slot.select("path", function()
+ ui.link{
+ content = _"Area '#{name}'":gsub("#{name}", initiative.issue.area.name),
+ module = "area",
+ view = "show",
+ id = initiative.issue.area.id
+ }
+ ui.container{ content = "::" }
+ ui.link{
+ content = _"Issue ##{id} (#{policy_name})":gsub("#{id}", initiative.issue.id):gsub("#{policy_name}", initiative.issue.policy.name),
+ module = "issue",
+ view = "show",
+ id = initiative.issue.id
+ }
+end)
+
+slot.put_into("title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) ))
+
+slot.select("actions", function()
+
+ ui.twitter("http://example.com/i" .. tostring(initiative.id) .. " " .. initiative.name)
+
+end)
+
+
+ui.container{
+ attr = { id = "add_suggestion_form", class = "hidden_inline_form" },
+ content = function()
+
+ ui.link{
+ content = _"Close",
+ attr = {
+ onclick = "document.getElementById('add_suggestion_form').style.display='none';return(false)",
+ style = "float: right;"
+ }
+ }
+
+ ui.field.text{ attr = { class = "head" }, value = _"Add new suggestion" }
+
+
+ ui.form{
+ module = "suggestion",
+ action = "add",
+ params = { initiative_id = initiative.id },
+ routing = {
+ default = {
+ mode = "redirect",
+ module = "initiative",
+ view = "show",
+ id = initiative.id,
+ params = { tab = "suggestion" }
+ }
+ },
+ attr = { class = "vertical" },
+ content = function()
+ ui.field.text{ label = _"Name", name = "name" }
+ ui.field.text{ label = _"Description", name = "description", multiline = true }
+ ui.field.select{
+ label = _"Degree",
+ name = "degree",
+ foreign_records = {
+ { id = 1, name = _"should"},
+ { id = 2, name = _"must"},
+ },
+ foreign_id = "id",
+ foreign_name = "name"
+ }
+ ui.submit{ text = _"Commit suggestion" }
+ end
+ }
+ end
+}
+
+
+ui.tabs{
+ {
+ name = "current_draft",
+ label = _"Current draft",
+ content = function()
+ execute.view{ module = "draft", view = "_show", params = { draft = initiative.current_draft } }
+ if Initiator:by_pk(initiative.id, app.session.member.id) then
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/script_add.png" }
+ slot.put(_"Add new draft")
+ end,
+ module = "draft",
+ view = "new",
+ params = { initiative_id = initiative.id }
+ }
+ end
+ end
+ },
+ {
+ name = "details",
+ label = _"Details",
+ content = function()
+ ui.form{
+ attr = { class = "vertical" },
+ record = initiative,
+ readonly = true,
+ content = function()
+ ui.field.text{ label = _"Issue policy", value = initiative.issue.policy.name }
+ ui.field.text{
+ label = _"Created at",
+ value = tostring(initiative.created)
+ }
+ ui.field.text{
+ label = _"Created at",
+ value = format.timestamp(initiative.created)
+ }
+ ui.field.date{ label = _"Revoked at", name = "revoked" }
+ ui.field.boolean{ label = _"Admitted", name = "admitted" }
+ end
+ }
+ end
+ },
+ {
+ name = "suggestion",
+ label = _"Suggestions",
+ content = function()
+ execute.view{ module = "suggestion", view = "_list", params = { suggestions_selector = initiative:get_reference_selector("suggestions") } }
+ slot.put("
")
+ if not initiative.issue.frozen and not initiative.issue.closed then
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/comment_add.png" }
+ slot.put(_"Add new suggestion")
+ end,
+ attr = { onclick = "document.getElementById('add_suggestion_form').style.display='block';return(false)" },
+ static = "#"
+ }
+ end
+ end
+ },
+ {
+ name = "supporter",
+ label = _"Supporter",
+ content = function()
+ execute.view{ module = "member", view = "_list", params = { members_selector = initiative:get_reference_selector("supporting_members") } }
+ end
+ },
+ {
+ name = "initiators",
+ label = _"Initiators",
+ content = function()
+ execute.view{ module = "member", view = "_list", params = { members_selector = initiative:get_reference_selector("initiating_members") } }
+ end
+ },
+ {
+ name = "drafts",
+ label = _"Old drafts",
+ content = function()
+ execute.view{ module = "draft", view = "_list", params = { drafts = initiative.drafts } }
+ end
+ },
+}
+
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/initiative/show.rss.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/initiative/show.rss.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,49 @@
+slot.set_layout("rss")
+
+local function rss_channel(channel)
+ for key, val in pairs(channel) do
+ slot.put("<", key, ">", val, "", key, ">")
+ end
+end
+
+local function rss_item(item)
+ slot.put("- ")
+ for key, val in pairs(item) do
+ slot.put("<", key, ">", val, "", key, ">")
+ end
+ slot.put("
")
+end
+
+
+local initiative = Initiative:by_id(param.get_id())
+
+rss_channel{
+ title = initiative.name,
+ description = initiative.current_draft.content,
+ language = "de",
+ copyright = initiative.current_draft.author.name,
+ pubDate = "Tue, 8 Jul 2008 2:43:19"
+}
+
+for i, suggestion in ipairs(initiative.suggestions) do
+
+ local text = suggestion.name
+
+ text = text .. " ("
+ text = text .. tostring(suggestion.plus2_unfulfilled_count + suggestion.plus2_unfulfilled_count) .. "++ "
+ text = text .. tostring(suggestion.plus1_unfulfilled_count + suggestion.plus1_unfulfilled_count) .. "+ "
+ text = text .. tostring(suggestion.minus1_unfulfilled_count + suggestion.minus1_unfulfilled_count) .. "- "
+ text = text .. tostring(suggestion.minus2_unfulfilled_count + suggestion.minus2_unfulfilled_count) .. "--"
+
+ text = text .. ")"
+
+ rss_item{
+ title = text,
+ description = suggestion.content,
+ link = "http://localhost/lf/suggestion/show/" .. tostring(suggestion.id) .. ".html",
+ author = "",
+ guid = "guid",
+ pubDate = "Tue, 8 Jul 2008 2:43:19"
+ }
+
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/interest/_action/update.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/interest/_action/update.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,28 @@
+local issue_id = assert(param.get("issue_id", atom.integer), "no issue id given")
+local interest = Interest:by_pk(issue_id, app.session.member.id)
+
+if param.get("delete", atom.boolean) then
+ if interest then
+ interest:destroy()
+ slot.put_into("notice", _"Interest removed")
+ else
+ slot.put_into("notice", _"Interest not existant")
+ end
+ return
+end
+
+if not interest then
+ interest = Interest:new()
+ interest.issue_id = issue_id
+ interest.member_id = app.session.member_id
+ interest.autoreject = false
+end
+
+local autoreject = param.get("autoreject", atom.boolean)
+if autoreject ~= nil then
+ interest.autoreject = autoreject
+end
+
+interest:save()
+
+slot.put_into("notice", _"Interest updated")
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/interest/_show_box.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/interest/_show_box.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,71 @@
+
+local issue = param.get("issue", "table")
+
+
+slot.select("interest", function()
+ local interest = Interest:by_pk(issue.id, app.session.member.id)
+
+ ui.container{
+ attr = {
+ class = "head",
+ onclick = "document.getElementById('interest_content').style.display = 'block';"
+ },
+ content = function()
+ if interest then
+ ui.field.text{ value = _"You are interested. [more]" }
+ else
+ ui.field.text{ value = _"You are not interested. [more]" }
+ end
+ end
+ }
+
+ ui.container{
+ attr = { class = "content", id = "interest_content" },
+ content = function()
+ if interest then
+ ui.link{
+ content = _"Remove my interest",
+ module = "interest",
+ action = "update",
+ params = { issue_id = issue.id, delete = true },
+ routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
+ }
+ if interest.autoreject then
+ ui.field.text{ value = _"Autoreject is on." }
+ ui.link{
+ content = _"Remove autoreject",
+ module = "interest",
+ action = "update",
+ params = { issue_id = issue.id, autoreject = false },
+ routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
+ }
+ else
+ ui.field.text{ value = _"Autoreject is off." }
+ ui.link{
+ content = _"Set autoreject",
+ module = "interest",
+ action = "update",
+ params = { issue_id = issue.id, autoreject = true },
+ routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
+ }
+ end
+ else
+ ui.link{
+ content = _"Add my interest to this issue",
+ module = "interest",
+ action = "update",
+ params = { issue_id = issue.id },
+ routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } }
+ }
+ end
+ ui.container{
+ attr = {
+ class = "head",
+ style = "cursor: pointer;",
+ onclick = "document.getElementById('interest_content').style.display = 'none';"
+ },
+ content = _"Click here to close."
+ }
+ end
+ }
+end)
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/issue/_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/issue/_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,89 @@
+local issues_selector = param.get("issues_selector", "table")
+
+local paginate = ui.paginate
+
+local issues
+
+if not issues_selector then
+ issues = param.get("issues", "table")
+ paginate = function(args)
+ args.content()
+ end
+end
+
+ui.order{
+ name = "issue_list",
+ selector = issues_selector,
+ options = {
+ {
+ name = "population",
+ label = _"Population",
+ order_by = "issue.population DESC"
+ },
+ {
+ name = "newest",
+ label = _"Newest",
+ order_by = "issue.created DESC"
+ },
+ {
+ name = "oldest",
+ label = _"Oldest",
+ order_by = "issue.created"
+ }
+ },
+ content = function()
+ paginate{
+ selector = issues_selector,
+ content = function()
+ local highlight_string = param.get("highlight_string", "string")
+ ui.list{
+ attr = { class = "issues" },
+ records = issues or issues_selector:exec(),
+ columns = {
+ {
+ label = _"Issue",
+ content = function(record)
+ if not param.get("for_area_list", atom.boolean) then
+ ui.field.text{
+ value = record.area.name
+ }
+ slot.put("
")
+ end
+ ui.link{
+ text = _"Issue ##{id}":gsub("#{id}", tostring(record.id)),
+ module = "issue",
+ view = "show",
+ id = record.id
+ }
+ slot.put("
")
+ slot.put("
")
+ end
+ },
+ {
+ label = _"State",
+ content = function(record)
+ ui.field.issue_state{ value = record.state }
+ end
+ },
+ {
+ label = _"Initiatives",
+ content = function(record)
+ execute.view{
+ module = "initiative",
+ view = "_list",
+ params = {
+ issue = record,
+ initiatives_selector = record:get_reference_selector("initiatives"),
+ highlight_string = highlight_string,
+ limit = 3
+ }
+ }
+ end
+ },
+ }
+ }
+
+ end
+ }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/issue/list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/issue/list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,7 @@
+local issues_selector = Issue:new_selector()
+
+execute.view{
+ module = "issue",
+ view = "_list",
+ params = { issues_selector = issues_selector }
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/issue/show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/issue/show.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,110 @@
+local issue = Issue:by_id(param.get_id())
+
+slot.put_into("html_head", '')
+
+slot.select("path", function()
+ ui.link{
+ content = _"Area '#{name}'":gsub("#{name}", issue.area.name),
+ module = "area",
+ view = "show",
+ id = issue.area.id
+ }
+end)
+
+slot.put_into("title", encode.html(_"Issue ##{id} (#{policy_name})":gsub("#{id}", issue.id):gsub("#{policy_name}", issue.policy.name)))
+
+slot.select("actions", function()
+ if not issue.closed then
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/table_go.png" }
+ slot.put(_"Delegate")
+ end,
+ module = "delegation",
+ view = "new",
+ params = { issue_id = issue.id }
+ }
+ end
+
+ ui.twitter("http://example.com/t" .. tostring(issue.id))
+
+end)
+
+execute.view{
+ module = "interest",
+ view = "_show_box",
+ params = { issue = issue }
+}
+
+execute.view{
+ module = "delegation",
+ view = "_show_box",
+ params = { issue_id = issue.id }
+}
+
+ui.tabs{
+ {
+ name = "initiatives",
+ label = _"Initiatives",
+ content = function()
+ execute.view{
+ module = "initiative",
+ view = "_list",
+ params = {
+ issue = issue,
+ initiatives_selector = issue:get_reference_selector("initiatives")
+ }
+ }
+ slot.put("
")
+ if not issue.frozen and not issue.closed then
+ ui.link{
+ attr = { class = "action" },
+ content = function()
+ ui.image{ static = "icons/16/script_add.png" }
+ slot.put(_"Add new initiative to issue")
+ end,
+ module = "initiative",
+ view = "new",
+ params = { issue_id = issue.id }
+ }
+ end
+ end
+ },
+--[[ {
+ name = "voting_requests",
+ label = _"Voting requests",
+ content = function()
+ execute.view{
+ module = "issue_voting_request",
+ view = "_list",
+ params = { issue = issue }
+ }
+ end
+ },
+--]]
+ {
+ name = "details",
+ label = _"Details",
+ content = function()
+ ui.form{
+ record = issue,
+ readonly = true,
+ attr = { class = "vertical" },
+ content = function()
+ trace.debug(issue.created)
+ ui.field.text{ label = _"State", name = "state" }
+ ui.field.timestamp{ label = _"Created at", name = "created" }
+ ui.field.timestamp{ label = _"Accepted", name = "accepted" }
+ ui.field.timestamp{ label = _"Half frozen", name = "half_frozen" }
+ ui.field.timestamp{ label = _"Fully frozen", name = "fully_frozen" }
+ ui.field.timestamp{ label = _"Closed", name = "closed" }
+ ui.field.potential_issue_weight{ label = _"Potential weight", name = "potential_weight" }
+ ui.field.vote_now{ label = _"Vote now", name = "vote_now" }
+ ui.field.vote_later{ label = _"Vote later", name = "vote_later" }
+ end
+ }
+ end
+ },
+}
+
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/issue/show.rss.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/issue/show.rss.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,35 @@
+slot.set_layout("rss")
+
+local function rss_channel(channel)
+ for key, val in pairs(channel) do
+ slot.put("<", key, ">", encode.html(val), "", key, ">")
+ end
+end
+
+local function rss_item(item)
+ slot.put("- ")
+ for key, val in pairs(item) do
+ slot.put("<", key, ">", encode.html(val), "", key, ">")
+ end
+ slot.put("
")
+end
+
+
+local issue = Issue:by_id(param.get_id())
+
+rss_channel{
+ title = issue.area.name .. " :: Issue #" .. tostring(issue.id),
+ language = "de",
+ pubDate = "Tue, 8 Jul 2008 2:43:19"
+}
+
+for i, initiative in ipairs(issue.initiatives) do
+ rss_item{
+ title = initiative.name,
+ description = initiative.current_draft.content,
+ link = "http://localhost/lf/initiative/show/" .. tostring(initiative.id) .. ".html",
+ author = initiative.current_draft.author.name,
+ guid = "guid",
+ pubDate = "Tue, 8 Jul 2008 2:43:19"
+ }
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/member/_action/update.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/member/_action/update.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,6 @@
+param.update(app.session.member, "name")
+
+app.session.member:save()
+
+
+slot.put_into("notice", _"Your page has been updated")
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/member/_action/update_avatar.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/member/_action/update_avatar.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,20 @@
+local data = param.get("avatar")
+
+if param.get("avatar_delete", atom.boolean) then
+ app.session.member.avatar = nil
+ app.session.member:save()
+ slot.put_into("notice", _"Avatar has been deleted")
+ return
+end
+
+local data, err, status = os.pfilter(data, "convert", "-", "-thumbnail", "48x48", "-")
+
+if status ~= 0 or data == nil then
+ error("error while converting image")
+end
+
+if data and #data > 0 then
+ db:query{ 'UPDATE member SET avatar = $ WHERE id = ?', { db:quote_binary(data) }, app.session.member.id }
+end
+
+slot.put_into("notice", _"Avatar has been updated")
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/member/_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/member/_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,81 @@
+local members_selector = param.get("members_selector", "table")
+
+ui.paginate{
+ selector = members_selector,
+ content = function()
+ ui.list{
+ records = members_selector:exec(),
+ columns = {
+ {
+ content = function(record)
+ ui.image{
+ attr = { style="height: 24px;" },
+ module = "member",
+ view = "avatar",
+ extension = "jpg",
+ id = record.id
+ }
+ end
+ },
+ {
+ label = _"Login",
+ content = function(record)
+ ui.link{
+ text = record.login,
+ module = "member",
+ view = "show",
+ id = record.id
+ }
+ end
+ },
+ {
+ label = _"Name",
+ content = function(record)
+ ui.link{
+ content = function()
+ util.put_highlighted_string(record.name)
+ end,
+ module = "member",
+ view = "show",
+ id = record.id
+ }
+ end
+ },
+ {
+ label = _"Ident number",
+ name = "ident_number"
+ },
+ {
+ label = _"Admin?",
+ name = "admin"
+ },
+ {
+ label = "Locked?",
+ content = function(record)
+ ui.field.boolean{ value = record.locked }
+ end
+ },
+ {
+ content = function(record)
+ ui.link{
+ attr = { class = "action" },
+ text = _"Add to my contacts",
+ module = "contact",
+ action = "add_member",
+ id = record.id,
+ routing = {
+ default = {
+ mode = "redirect",
+ module = request.get_module(),
+ view = request.get_view(),
+ id = param.get_id_cgi(),
+ params = param.get_all_cgi()
+ }
+ }
+ }
+ end
+ }
+ }
+ }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/member/_show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/member/_show.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,84 @@
+local member = param.get("member", "table")
+
+ui.form{
+ attr = { class = "vertical" },
+ record = member,
+ readonly = true,
+ content = function()
+ ui.field.text{ label = _"Login", name = "login" }
+ ui.field.text{ label = _"Name", name = "name" }
+ ui.field.boolean{ label = _"Admin?", name = "admin" }
+ ui.field.boolean{ label = _"Locked?", name = "locked" }
+ ui.field.text{ label = _"Ident number", name = "ident_number" }
+ ui.submit{ text = _"Save" }
+ end
+}
+
+ui.tabs{
+ {
+ name = "areas",
+ label = _"Areas",
+ content = function()
+ execute.view{
+ module = "area",
+ view = "_list",
+ params = { areas_selector = member:get_reference_selector("areas") }
+ }
+ end
+ },
+ {
+ name = "issues",
+ label = _"Issues",
+ content = function()
+ execute.view{
+ module = "issue",
+ view = "_list",
+ params = { issues_selector = member:get_reference_selector("issues") }
+ }
+ end
+ },
+ {
+ name = "initiatives",
+ label = _"Initiatives",
+ content = function()
+ execute.view{
+ module = "initiative",
+ view = "_list",
+ params = { initiatives_selector = member:get_reference_selector("supported_initiatives") }
+ }
+ end
+ },
+ {
+ name = "incoming_delegations",
+ label = _"Incoming delegations",
+ content = function()
+ execute.view{
+ module = "delegation",
+ view = "_list",
+ params = { selector = member:get_reference_selector("incoming_delegations") }
+ }
+ end
+ },
+ {
+ name = "outgoing_delegations",
+ label = _"Outgoing delegations",
+ content = function()
+ execute.view{
+ module = "delegation",
+ view = "_list",
+ params = { selector = member:get_reference_selector("outgoing_delegations") }
+ }
+ end
+ },
+ {
+ name = "contacts",
+ label = _"Published contacts",
+ content = function()
+ execute.view{
+ module = "member",
+ view = "_list",
+ params = { members_selector = member:get_reference_selector("saved_members"):add_where("public") }
+ }
+ end
+ },
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/member/avatar.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/member/avatar.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,15 @@
+local record = Member:by_id(param.get_id())
+
+if false and (not record or not record.avatar) then
+ print('Location: ' .. encode.url{ static = 'no_image.png' } .. '\n\n')
+ exit()
+end
+
+print('Content-type: image/jpg\n')
+
+if record then
+ io.stdout:write(record.avatar)
+else
+end
+
+exit()
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/member/edit.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/member/edit.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,30 @@
+slot.put_into("title", _"Edit my page")
+
+slot.select("actions", function()
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/cancel.png" }
+ slot.put(_"Cancel")
+ end,
+ module = "index",
+ view = "index"
+ }
+end)
+
+ui.form{
+ record = app.session.member,
+ attr = { class = "vertical" },
+ module = "member",
+ action = "update",
+ routing = {
+ ok = {
+ mode = "redirect",
+ module = "index",
+ view = "index"
+ }
+ },
+ content = function()
+ ui.field.text{ label = _"Name", name = "name" }
+ ui.submit{ value = _"Save" }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/member/edit_avatar.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/member/edit_avatar.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,33 @@
+slot.put_into("title", _"Upload avatar")
+
+slot.select("actions", function()
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/cancel.png" }
+ slot.put(_"Cancel")
+ end,
+ module = "index",
+ view = "index"
+ }
+end)
+
+ui.form{
+ record = app.session.member,
+ attr = {
+ class = "vertical",
+ enctype = 'multipart/form-data'
+ },
+ module = "member",
+ action = "update_avatar",
+ routing = {
+ ok = {
+ mode = "redirect",
+ module = "index",
+ view = "index"
+ }
+ },
+ content = function()
+ ui.field.image{ field_name = "avatar", label = _"Avatar" }
+ ui.submit{ value = _"Save" }
+ end
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/member/list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/member/list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,7 @@
+slot.put_into("title", _"Member list")
+
+execute.view{
+ module = "member",
+ view = "_list",
+ params = { members_selector = Member:new_selector():add_order_by("login") }
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/member/show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/member/show.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,37 @@
+local member = Member:by_id(param.get_id())
+
+slot.select("title", function()
+ ui.image{
+ attr = { class = "avatar" },
+ module = "member",
+ view = "avatar",
+ extension = "jpg",
+ id = member.id
+ }
+end)
+
+slot.put_into("title", encode.html(_"Member '#{member}'":gsub("#{member}", member.name)))
+
+if member.id == app.session.member.id then
+ slot.put_into("actions", _"That's me!")
+else
+ slot.select("actions", function()
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/book_add.png" }
+ slot.put(encode.html(_"Add to my contacts"))
+ end,
+ module = "contact",
+ action = "add_member",
+ id = member.id
+ }
+ end)
+end
+
+
+execute.view{
+ module = "member",
+ view = "_show",
+ params = { member = member }
+}
+
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/membership/_action/update.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/membership/_action/update.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,28 @@
+local area_id = assert(param.get("area_id", atom.integer), "no area id given")
+local membership = Membership:by_pk(area_id, app.session.member.id)
+
+if param.get("delete", atom.boolean) then
+ if membership then
+ membership:destroy()
+ slot.put_into("notice", _"Membership removed")
+ else
+ slot.put_into("notice", _"Membership not existant")
+ end
+ return
+end
+
+if not membership then
+ membership = Membership:new()
+ membership.area_id = area_id
+ membership.member_id = app.session.member_id
+ membership.autoreject = false
+end
+
+local autoreject = param.get("autoreject", atom.boolean)
+if autoreject ~= nil then
+ membership.autoreject = autoreject
+end
+
+membership:save()
+
+slot.put_into("notice", _"Membership updated")
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/membership/_show_box.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/membership/_show_box.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,69 @@
+local area = param.get("area", "table")
+
+slot.select("interest", function()
+ local membership = Membership:by_pk(area.id, app.session.member.id)
+
+ ui.container{
+ attr = {
+ class = "head",
+ onclick = "document.getElementById('interest_content').style.display = 'block';"
+ },
+ content = function()
+ if membership then
+ ui.field.text{ value = _"You are member. [more]" }
+ else
+ ui.field.text{ value = _"You are not a member. [more]" }
+ end
+ end
+ }
+
+ ui.container{
+ attr = { class = "content", id = "interest_content" },
+ content = function()
+ if membership then
+ ui.link{
+ content = _"Remove my membership",
+ module = "membership",
+ action = "update",
+ params = { area_id = area.id, delete = true },
+ routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
+ }
+ if membership.autoreject then
+ ui.field.text{ value = _"Autoreject is on." }
+ ui.link{
+ content = _"Remove autoreject",
+ module = "membership",
+ action = "update",
+ params = { area_id = area.id, autoreject = false },
+ routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
+ }
+ else
+ ui.field.text{ value = _"Autoreject is off." }
+ ui.link{
+ content = _"Set autoreject",
+ module = "membership",
+ action = "update",
+ params = { area_id = area.id, autoreject = true },
+ routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
+ }
+ end
+ else
+ ui.link{
+ content = _"Add my membership to this area",
+ module = "membership",
+ action = "update",
+ params = { area_id = area.id },
+ routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } }
+ }
+ end
+ ui.container{
+ attr = {
+ class = "head",
+ style = "cursor: pointer;",
+ onclick = "document.getElementById('interest_content').style.display = 'none';"
+ },
+ content = _"Click here to close."
+ }
+ end
+ }
+end)
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/opinion/_action/update.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/opinion/_action/update.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,33 @@
+local member_id = app.session.member.id
+
+local suggestion_id = param.get("suggestion_id", atom.integer)
+
+local opinion = Opinion:by_pk(member_id, suggestion_id)
+
+if opinion and param.get("delete") then
+ opinion:destroy()
+ slot.put_into("notice", _"Your opinion has been updated")
+ return
+end
+
+if not opinion then
+ opinion = Opinion:new()
+ opinion.member_id = member_id
+ opinion.suggestion_id = suggestion_id
+ opinion.fulfilled = false
+end
+
+local degree = param.get("degree", atom.number)
+local fulfilled = param.get("fulfilled", atom.boolean)
+
+if degree ~= nil then
+ opinion.degree = degree
+end
+
+if fulfilled ~= nil then
+ opinion.fulfilled = fulfilled
+end
+
+opinion:save()
+
+slot.put_into("notice", _"Your opinion has been updated")
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/opinion/_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/opinion/_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,23 @@
+local opinions_selector = param.get("opinions_selector", "table")
+
+ui.list{
+ records = opinions_selector:exec(),
+ columns = {
+ {
+ label = _"Member login",
+ name = "member_login"
+ },
+ {
+ label = _"Member name",
+ name = "member_name"
+ },
+ {
+ label = _"Degree",
+ name = "degree"
+ },
+ {
+ label = _"Fulfilled",
+ name = "fulfilled"
+ },
+ }
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/suggestion/_action/add.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/suggestion/_action/add.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,20 @@
+db:query("BEGIN")
+
+local suggestion = Suggestion:new()
+
+suggestion.author_id = app.session.member.id
+param.update(suggestion, "name", "description", "initiative_id")
+suggestion:save()
+
+local opinion = Opinion:new()
+
+opinion.suggestion_id = suggestion.id
+opinion.member_id = app.session.member.id
+opinion.degree = param.get("degree", atom.integer)
+opinion.fulfilled = false
+
+opinion:save()
+
+db:query("COMMIT")
+
+slot.put_into("notice", _"Your suggestion has been added")
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/suggestion/_list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/suggestion/_list.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,185 @@
+local suggestions_selector = param.get("suggestions_selector", "table")
+
+ui.paginate{
+ selector = suggestions_selector,
+ content = function()
+ ui.list{
+ records = suggestions_selector:exec(),
+ columns = {
+ {
+ label = _"Name",
+ content = function(record)
+ ui.link{
+ text = record.name,
+ module = "suggestion",
+ view = "show",
+ id = record.id
+ }
+ end
+ },
+ {
+ label = _"Support",
+ content = function(record)
+ if record.minus2_unfulfilled_count then
+ local max_value = record.initiative.supporter_count
+ ui.bargraph{
+ max_value = max_value,
+ width = 50,
+ bars = {
+ { color = "#ddd", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count - record.minus2_fulfilled_count - record.minus1_fulfilled_count },
+ { color = "#f88", value = record.minus1_unfulfilled_count + record.minus1_fulfilled_count },
+ { color = "#a00", value = record.minus2_unfulfilled_count + record.minus2_fulfilled_count },
+ { color = "#0a0", value = record.plus2_unfulfilled_count + record.plus2_fulfilled_count },
+ { color = "#8f8", value = record.plus1_unfulfilled_count + record.plus1_fulfilled_count },
+ { color = "#ddd", value = max_value - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count - record.plus1_fulfilled_count - record.plus2_fulfilled_count },
+ }
+ }
+ end
+ end
+ },
+ {
+ content = function(record)
+ local degree
+ local opinion = Opinion:by_pk(app.session.member.id, record.id)
+ if opinion then
+ degree = opinion.degree
+ end
+ ui.link{
+ attr = { class = "action" .. (degree == -2 and " active_red2" or "") },
+ text = _"must not",
+ module = "opinion",
+ action = "update",
+ routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
+ params = {
+ suggestion_id = record.id,
+ degree = -2
+ }
+ }
+ ui.link{
+ attr = { class = "action" .. (degree == -1 and " active_red1" or "") },
+ text = _"should not",
+ module = "opinion",
+ action = "update",
+ routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
+ params = {
+ suggestion_id = record.id,
+ degree = -1
+ }
+ }
+ ui.link{
+ attr = { class = "action" .. (degree == nil and " active" or "") },
+ text = _"neutral",
+ module = "opinion",
+ action = "update",
+ routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
+ params = {
+ suggestion_id = record.id,
+ delete = true
+ }
+ }
+ ui.link{
+ attr = { class = "action" .. (degree == 1 and " active_green1" or "") },
+ text = _"should",
+ module = "opinion",
+ action = "update",
+ routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
+ params = {
+ suggestion_id = record.id,
+ degree = 1
+ }
+ }
+ ui.link{
+ attr = { class = "action" .. (degree == 2 and " active_green2" or "") },
+ text = _"must",
+ module = "opinion",
+ action = "update",
+ routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
+ params = {
+ suggestion_id = record.id,
+ degree = 2
+ }
+ }
+ end
+ },
+ {
+ label = _"Not fullfilled",
+ content = function(record)
+ if record.minus2_unfulfilled_count then
+ local max_value = record.initiative.supporter_count
+ ui.bargraph{
+ max_value = max_value,
+ width = 50,
+ bars = {
+ { color = "#ddd", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count },
+ { color = "#f88", value = record.minus1_unfulfilled_count },
+ { color = "#a00", value = record.minus2_unfulfilled_count },
+ { color = "#0a0", value = record.plus2_unfulfilled_count },
+ { color = "#8f8", value = record.plus1_unfulfilled_count },
+ { color = "#ddd", value = max_value - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count },
+ }
+ }
+ end
+ end
+ },
+ {
+ label = _"Fullfilled",
+ content = function(record)
+ if record.minus2_fulfilled_count then
+ local max_value = record.initiative.supporter_count
+ ui.bargraph{
+ max_value = max_value,
+ width = 50,
+ bars = {
+ { color = "#ddd", value = max_value - record.minus2_fulfilled_count - record.minus1_fulfilled_count },
+ { color = "#f88", value = record.minus1_fulfilled_count },
+ { color = "#a00", value = record.minus2_fulfilled_count },
+ { color = "#0a0", value = record.plus2_fulfilled_count },
+ { color = "#8f8", value = record.plus1_fulfilled_count },
+ { color = "#ddd", value = max_value - record.plus1_fulfilled_count - record.plus2_fulfilled_count },
+ }
+ }
+ end
+ end
+ },
+ {
+ content = function(record)
+ local degree
+ local opinion = Opinion:by_pk(app.session.member.id, record.id)
+ if opinion then
+ degree = opinion.degree
+ end
+ if opinion then
+ if not opinion.fulfilled then
+ ui.image{ static = "icons/16/cross.png" }
+ ui.link{
+ attr = { class = "action" },
+ text = _"set fulfilled",
+ module = "opinion",
+ action = "update",
+ routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
+ params = {
+ suggestion_id = record.id,
+ fulfilled = true
+ }
+ }
+ else
+ ui.image{ static = "icons/16/tick.png" }
+ ui.link{
+ attr = { class = "action" },
+ text = _"remove fulfilled",
+ module = "opinion",
+ action = "update",
+ routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } },
+ params = {
+ suggestion_id = record.id,
+ fulfilled = false
+ }
+ }
+ end
+ end
+ end
+ },
+ }
+ }
+ end
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/suggestion/show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/suggestion/show.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,32 @@
+local suggestion = Suggestion:by_id(param.get_id())
+
+slot.put_into("title", encode.html(_"Suggestion for initiative: '#{name}'":gsub("#{name}", suggestion.initiative.name) ))
+
+ui.form{
+ attr = { class = "vertical" },
+ record = suggestion,
+ readonly = true,
+ content = function()
+ ui.field.text{ label = _"Name", name = "name" }
+ ui.field.text{ label = _"Description", name = "description" }
+ end
+}
+
+execute.view{
+ module = "suggestion",
+ view = "_list",
+ params = { suggestions_selector = Suggestion:new_selector():add_where{ "id = ?", suggestion.id } }
+}
+
+execute.view{
+ module = "opinion",
+ view = "_list",
+ params = {
+ opinions_selector = Opinion:new_selector()
+ :add_field("member.login", "member_login")
+ :add_field("member.name", "member_name")
+ :add_where{ "suggestion_id = ?", suggestion.id }
+ :join("member", nil, "member.id = opinion.member_id")
+ :add_order_by("member.id DESC")
+ }
+}
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 app/main/supporter/_show_box.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main/supporter/_show_box.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,55 @@
+
+
+slot.select("support", function()
+
+ local initiative = param.get("initiative", "table")
+
+ if not initiative.issue.frozen and not initiative.issue.closed then
+
+ local supported = Supporter:by_pk(initiative.id, app.session.member.id) and true or false
+
+ local text
+ if supported then
+ text = _"Direct supporter [change]"
+ else
+ text = _"No supporter [change]"
+ end
+ ui.container{
+ attr = {
+ class = "head",
+ style = "cursor: pointer;",
+ onclick = "document.getElementById('support_content').style.display = 'block';"
+ },
+ content = text
+ }
+
+
+ ui.container{
+ attr = { class = "content", id = "support_content" },
+ content = function()
+ if supported then
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/thumb_down_red.png" }
+ slot.put(_"Remove my support from this initiative")
+ end,
+ module = "initiative",
+ action = "remove_support",
+ id = initiative.id
+ }
+ else
+ ui.link{
+ content = function()
+ ui.image{ static = "icons/16/thumb_up_green.png" }
+ slot.put(_"Support this initiative")
+ end,
+ module = "initiative",
+ action = "add_support",
+ id = initiative.id
+ }
+ end
+ end
+ }
+ end
+
+end)
diff -r 000000000000 -r 3bfb2fcf7ab9 config/default.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/config/default.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,48 @@
+config.app_name = "LiquidFeedback"
+config.app_version = "alpha1"
+
+config.app_title = config.app_name .. " (" .. request.get_config_name() .. " environment)"
+
+config.app_service_provider = "Snake Oil
10000 Berlin
Germany"
+
+-- uncomment the following two lines to use C implementations of chosen
+-- functions and to disable garbage collection during the request, to
+-- increase speed:
+--
+-- require 'webmcp_accelerator'
+-- collectgarbage("stop")
+
+-- open and set default database handle
+db = assert(mondelefant.connect{
+ engine='postgresql',
+ dbname='liquid_feedback'
+})
+at_exit(function()
+ db:close()
+end)
+function mondelefant.class_prototype:get_db_conn() return db end
+
+-- enable output of SQL commands in trace system
+function db:sql_tracer(command)
+ return function(error_info)
+ local error_info = error_info or {}
+ trace.sql{ command = command, error_position = error_info.position }
+ end
+end
+
+-- 'request.get_relative_baseurl()' should be replaced by the absolute
+-- base URL of the application, as otherwise HTTP redirects will not be
+-- standard compliant
+request.set_absolute_baseurl(request.get_relative_baseurl())
+
+
+
+
+-- get record by id
+function mondelefant.class_prototype:by_id(id)
+ local selector = self:new_selector()
+ selector:add_where{ 'id = ?', id }
+ selector:optional_object_mode()
+ return selector:exec()
+end
+
diff -r 000000000000 -r 3bfb2fcf7ab9 config/development.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/config/development.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,2 @@
+execute.config("default")
+
diff -r 000000000000 -r 3bfb2fcf7ab9 config/testing.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/config/testing.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,6 @@
+execute.config("default")
+
+
+
+
+
diff -r 000000000000 -r 3bfb2fcf7ab9 db/demodata.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/db/demodata.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,102 @@
+#!/usr/bin/env lua
+
+member_count = 10000
+area_count = 24
+issue_count = 1000
+policy_count = 3 -- do not change
+
+function write(...)
+ io.stdout:write(...)
+end
+function writeln(...)
+ write(...)
+ write("\n")
+end
+
+math.randomseed(os.time())
+
+writeln('BEGIN;')
+
+for i = 2, member_count do
+ writeln('INSERT INTO "member" ("login", "name", "ident_number") VALUES (', "'testuser", i, "', 'Benutzer #", i, "', 'TEST", i, "');")
+end
+
+for i = 1, member_count do
+ local is_linked = {}
+ while math.random(4) > 1 do
+ local k = math.random(member_count)
+ if not is_linked[k] then
+ local public = math.random(2) == 1 and "TRUE" or "FALSE"
+ writeln('INSERT INTO "contact" ("member_id", "other_member_id", "public") VALUES (', i, ", ", k, ", ", public, ");")
+ is_linked[k] = true
+ end
+ end
+end
+
+for i = 2, area_count do
+ writeln('INSERT INTO "area" ("name") VALUES (', "'Area #", i, "');")
+end
+
+local memberships = {}
+
+for i = 1, area_count do
+ memberships[i] = {}
+ for j = 1, member_count do
+ if math.random(4) == 1 then
+ memberships[i][j] = true
+ local autoreject = math.random(2) == 1 and "TRUE" or "FALSE"
+ writeln('INSERT INTO "membership" ("member_id", "area_id", "autoreject") VALUES (', j, ", ", i, ", ", autoreject, ");")
+ end
+ end
+end
+
+do
+ local issue_initiative_count = {}
+ local initiative_draft_count = {}
+ local initiative_idx = 1
+ local draft_count = 0
+ for i = 1, issue_count do
+ local area = math.random(area_count)
+ writeln('INSERT INTO "issue" ("area_id", "policy_id") VALUES (', area, ", ", math.random(policy_count), ");")
+ issue_initiative_count[i] = 1
+ while math.random(3) > 1 do
+ issue_initiative_count[i] = issue_initiative_count[i] + 1
+ end
+ for j = 1, issue_initiative_count[i] do
+ writeln('INSERT INTO "initiative" ("issue_id", "name") VALUES (', i, ", 'Initiative #", initiative_idx, "');")
+ initiative_draft_count[i] = 1
+ while math.random(4) > 1 do
+ initiative_draft_count[i] = initiative_draft_count[i] + 1
+ end
+ local initiators = {}
+ local is_used = {}
+ repeat
+ local member = math.random(member_count)
+ if not is_used[member] then
+ initiators[#initiators+1] = member
+ is_used[member] = true
+ end
+ until math.random(2) == 1
+ for k = 1, initiative_draft_count[i] do
+ draft_count = draft_count + 1
+ writeln('INSERT INTO "draft" ("initiative_id", "author_id", "content") VALUES (', initiative_idx, ", ", initiators[math.random(#initiators)], ", 'Lorem ipsum... (#", draft_count, ")');")
+ end
+ for k = 1, #initiators do
+ local member = math.random(member_count)
+ writeln('INSERT INTO "initiator" ("member_id", "initiative_id") VALUES (', initiators[k], ", ", initiative_idx, ");")
+ if math.random(50) > 1 then
+ writeln('INSERT INTO "supporter" ("member_id", "initiative_id", "draft_id") VALUES (', initiators[k], ", ", initiative_idx, ", ", draft_count - math.random(initiative_draft_count[i]) + 1, ");")
+ end
+ end
+ local probability = math.random(99) + 1
+ for k = 1, member_count do
+ if not is_used[k] and (memberships[area][k] and math.random(probability) <= 4 or math.random(probability) == 1) then
+ writeln('INSERT INTO "supporter" ("member_id", "initiative_id", "draft_id") VALUES (', k, ", ", initiative_idx, ", ", draft_count - math.random(initiative_draft_count[i]) + 1, ");")
+ end
+ end
+ initiative_idx = initiative_idx + 1
+ end
+ end
+end
+
+writeln('END;')
diff -r 000000000000 -r 3bfb2fcf7ab9 db/vote-test.sql
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/db/vote-test.sql Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,134 @@
+BEGIN;
+
+INSERT INTO "member" ("login", "name", "ident_number") VALUES
+ ('bernd', 'Bernd', '002'),
+ ('cesar', 'Cesar', '003'),
+ ('doris', 'Doris', '004'),
+ ('emil', 'Emil', '005'),
+ ('frank', 'Frank', '006'),
+ ('gerhard', 'Gerhard', '007'),
+ ('hugo', 'Hugo', '008'),
+ ('ines', 'Ines', '009'),
+ ('johann', 'Johann', '010'),
+ ('klaus', 'Klaus', '011'),
+ ('lisa', 'Lisa', '012'),
+ ('monika', 'Monika', '013'),
+ ('norbert', 'Norbert', '014'),
+ ('olaf', 'Olaf', '015'),
+ ('peter', 'Peter', '016'),
+ ('quinn', 'Quinn', '017'),
+ ('ralf', 'Ralf', '018'),
+ ('sabine', 'Sabine', '019'),
+ ('tobias', 'Tobias', '020'),
+ ('ulla', 'Ulla', '021'),
+ ('vincent', 'Vincent', '022'),
+ ('wolfgang', 'Wolfgang', '023'),
+ ('xavier', 'Xavier', '024'),
+ ('yoko', 'Yoko', '025'),
+ ('zareb', 'Zareb', '026');
+
+INSERT INTO "issue" ("area_id", "policy_id") VALUES (1, 3);
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #1');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #2');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #3');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #4');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #5');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #6');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #7');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #8');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #9');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #10');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #11');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #12');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #13');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #14');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #15');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #16');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #17');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #18');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #19');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #20');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #21');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #22');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #23');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #24');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #25');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #26');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #27');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #28');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #29');
+INSERT INTO "initiative" ("issue_id", "name") VALUES (1, 'Initiative #30');
+
+INSERT INTO "draft" ("initiative_id", "content") SELECT "id", 'Lorem ipsum ...' FROM "initiative";
+INSERT INTO "initiator" ("member_id", "initiative_id") SELECT 1, "id" FROM "initiative";
+INSERT INTO "supporter" ("member_id", "initiative_id", "draft_id") SELECT "member"."id", "initiative"."id", "initiative"."id" FROM "member", "initiative";
+
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 1, 1);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 2, 2);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 3, 3);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 4, 4);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 5, 5);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 6, 6);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 7, 7);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 8, 8);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 9, 9);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 10, 10);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 11, 11);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 12, 12);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 13, 13);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 14, 14);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 15, 15);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 16, 16);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 17, 17);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 18, 18);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 19, 19);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 20, 20);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 21, 21);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 22, 22);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 23, 23);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 24, 24);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 25, 25);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 26, 26);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 27, 27);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 28, 28);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 29, 29);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (1, 1, 30, 30);
+
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 1, 2);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 2, 1);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 3, 3);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 4, 4);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 5, 5);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 6, 6);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 7, 7);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 8, 8);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 9, 9);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 10, 10);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 11, 11);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 12, 12);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 13, 13);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 14, 14);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 15, 15);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 16, 16);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 17, 17);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 18, 18);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 19, 19);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 20, 20);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 21, 21);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 22, 22);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 23, 23);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 24, 24);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 25, 25);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 26, 26);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 27, 27);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 28, 28);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 29, 29);
+INSERT INTO "vote" ("member_id", "issue_id", "initiative_id", "grade") VALUES (2, 1, 30, 30);
+
+
+SELECT check_issues();
+UPDATE issue SET frozen = now();
+
+END;
+
+-- UPDATE issue SET closed = now();
diff -r 000000000000 -r 3bfb2fcf7ab9 doc/delegation.dia
Binary file doc/delegation.dia has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 doc/delegation.png
Binary file doc/delegation.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/bargraph.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/bargraph.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,19 @@
+function ui.bargraph(args)
+ ui.container{
+ attr = {
+ class = "bargraph",
+ },
+ content = function()
+ for i, bar in ipairs(args.bars) do
+ local value = bar.value * args.width / args.max_value / 2
+ ui.container{
+ attr = {
+ style = "width: " .. tostring(value) .. "px; background-color: " .. bar.color .. ";",
+ title = tostring(bar.value)
+ },
+ content = function() slot.put(" ") end
+ }
+ end
+ end
+ }
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/image.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/image.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,16 @@
+function ui.field.image(args)
+ ui.form_element(args, {}, function(args)
+ local value_string = atom.dump(args.value)
+ local attr = table.new(args.attr)
+ attr.name = args.field_name
+ attr.type = "file"
+ attr.value = value_string
+ ui.tag{ tag = "input", attr = attr }
+ local attr = table.new(args.attr)
+ attr.name = args.field_name .. '_' .. 'delete'
+ attr.type = "checkbox"
+ attr.value = '1'
+ ui.tag{ tag = "input", attr = attr }
+ slot.put(_'delete
')
+ end)
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/issue_state.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/issue_state.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,15 @@
+function ui.field.issue_state(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ local state_name = Issue:get_state_name_for_state(value)
+ ui.tag{
+ attr = { class = "vote_now" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = tostring(state_name)
+ }
+ end
+ }
+ end)
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/negative_votes.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/negative_votes.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,19 @@
+function ui.field.negative_votes(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.container{
+ attr = { class = "negative_votes" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = function()
+ slot.put(tostring(value) .. ' ')
+ ui.image{
+ static = "icons/16/delete.png"
+ }
+ end
+ }
+ end
+ }
+ end)
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/positive_votes.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/positive_votes.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,19 @@
+function ui.field.positive_votes(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.container{
+ attr = { class = "positive_votes" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = function()
+ slot.put(tostring(value) .. ' ')
+ ui.image{
+ static = "icons/16/add.png"
+ }
+ end
+ }
+ end
+ }
+ end)
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/potential_initiative_weight.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/potential_initiative_weight.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+function ui.field.potential_initiative_weight(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.tag{
+ attr = { class = "potential_weight" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = "(" .. tostring(value) .. ")"
+ }
+ end
+ }
+ end)
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/potential_issue_weight.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/potential_issue_weight.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+function ui.field.potential_issue_weight(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.tag{
+ attr = { class = "potential_weight" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = tostring(value)
+ }
+ end
+ }
+ end)
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/rank.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/rank.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,23 @@
+function ui.field.rank(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.tag{
+ attr = { class = "rank" },
+ content = function()
+ if value == 1 then
+ ui.image{ static = "icons/16/award_star_gold_2.png" }
+ elseif value then
+ ui.image{ static = "icons/16/award_star_silver_2.png" }
+ else
+ ui.image{ static = "icons/16/cross.png" }
+ end
+ if value then
+ ui.tag{
+ attr = { class = "value" },
+ content = tostring(value)
+ }
+ end
+ end
+ }
+ end)
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/satisfaction_informed.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/satisfaction_informed.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,20 @@
+function ui.field.satisfaction_informed(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.tag{
+ attr = { class = "satisfaction_informed" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = function()
+ slot.put(tostring(value) .. ' ')
+ ui.image{
+ static = "icons/16/thumb_up_green.png"
+ }
+ end
+ }
+ end
+ }
+ end)
+end
+
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/satisfaction_total.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/satisfaction_total.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,22 @@
+function ui.field.satisfaction_total(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.tag{
+ attr = { class = "satisfaction_total" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = function()
+ slot.put("(")
+ slot.put(tostring(value) .. ' ')
+ ui.image{
+ static = "icons/16/thumb_up_green.png"
+ }
+ slot.put(")")
+ end
+ }
+ end
+ }
+ end)
+end
+
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/timestamp.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/timestamp.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+function ui.field.timestamp(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.tag{
+ attr = { class = "ui_field_timestamp" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = tostring(value)
+ }
+ end
+ }
+ end)
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/vote_later.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/vote_later.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+function ui.field.vote_later(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.tag{
+ attr = { class = "vote_later" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = tostring(value)
+ }
+ end
+ }
+ end)
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/field/vote_now.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/field/vote_now.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+function ui.field.vote_now(args)
+ ui.form_element(args, {fetch_value = true}, function(args)
+ local value = args.value
+ ui.tag{
+ attr = { class = "vote_now" },
+ content = function()
+ ui.tag{
+ attr = { class = "value" },
+ content = tostring(value)
+ }
+ end
+ }
+ end)
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/order.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/order.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,40 @@
+function ui.order(args)
+ local name = args.name or "order"
+ local current_order = atom.string:load(cgi.params[name]) or args.options[1].name
+ local id = param.get_id_cgi()
+ local params = param.get_all_cgi()
+ ui.container{
+ attr = { class = "ui_order" },
+ content = function()
+ ui.container{
+ attr = { class = "ui_order_head" },
+ content = function()
+ slot.put(_"Order by")
+ slot.put(": ")
+ for i, option in ipairs(args.options) do
+ params[name] = option.name
+ local attr = {}
+ if current_order == option.name then
+ attr.class = "active"
+ args.selector:add_order_by(option.order_by)
+ end
+ ui.link{
+ attr = attr,
+ module = request.get_module(),
+ view = request.get_view(),
+ id = id,
+ params = params,
+ content = option.label
+ }
+ end
+ end
+ }
+ ui.container{
+ attr = { class = "ui_order_content" },
+ content = function()
+ args.content()
+ end
+ }
+ end
+ }
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/tabs.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/tabs.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,40 @@
+function ui.tabs(tabs)
+ ui.container{
+ attr = { class = "ui_tabs" },
+ content = function()
+ local params = param.get_all_cgi()
+ local current_tab = params["tab"]
+ ui.container{
+ attr = { class = "ui_tabs_links" },
+ content = function()
+ for i, tab in ipairs(tabs) do
+ params["tab"] = i > 1 and tab.name or nil
+ ui.link{
+ attr = {
+ class = (
+ tab.name == current_tab and "selected" or
+ not current_tab and i == 1 and "selected" or
+ ""
+ )
+ },
+ module = request.get_module(),
+ view = request.get_view(),
+ id = param.get_id_cgi(),
+ text = tab.label,
+ params = params
+ }
+ end
+ end
+ }
+ for i, tab in ipairs(tabs) do
+ if tab.name == current_tab or not current_tab and i == 1 then
+ ui.container{
+ attr = { class = "ui_tabs_content" },
+ content = tab.content
+ }
+ end
+ end
+ end
+ }
+end
+
diff -r 000000000000 -r 3bfb2fcf7ab9 env/ui/twitter.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/ui/twitter.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,10 @@
+function ui.twitter(message)
+ ui.link{
+ attr = { target = "_blank" },
+ content = function()
+ ui.image{ static = "icons/16/user_comment.png" }
+ slot.put(encode.html("tweet it"))
+ end,
+ external = "http://twitter.com/?status=" .. encode.url_part(message)
+ }
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 env/util/put_highlighted_string.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/env/util/put_highlighted_string.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,14 @@
+function util.put_highlighted_string(string)
+ local highlight_string = param.get("highlight_string")
+ if highlight_string then
+ local highlighted_string = slot.use_temporary(function()
+ ui.tag{
+ tag = "span",
+ attr = { class = "highlighted" },
+ content = highlight_string
+ }
+ end)
+ string = string:gsub(highlight_string, highlighted_string)
+ end
+ slot.put(string)
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 locale/translations.de.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/locale/translations.de.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,193 @@
+#!/usr/bin/env lua
+return {
+["A-Z"] = false;
+["About"] = false;
+["About LiquidFeedback"] = "Über LiquidFeedback";
+["Accepted"] = "Akzeptiert";
+["Active?"] = "Aktiv?";
+["Add my interest to this issue"] = "Mein Interesse am Thema anmelden";
+["Add my membership to this area"] = "Mitglied im Themenbereich werden";
+["Add new draft"] = "Neuen Entwurf hinzufügen";
+["Add new initiative to issue"] = "Neue Initiative zum Thema hinzufügen";
+["Add new suggestion"] = "Neue Anregung hinzufügen";
+["Add to my contacts"] = "Zu meinen Kontakten hinzufügen";
+["Admin"] = "Admin";
+["Admin menu"] = "Admin Menü";
+["Admin?"] = "Admin?";
+["Admitted"] = "zugelassen";
+["Area"] = "Themenbereich";
+["Area '#{name}'"] = "Themenbereich '#{name}'";
+["Area list"] = "Liste der Themenbereiche";
+["Area successfully updated"] = "Themenbereich erfolgreich aktualisiert";
+["Areas"] = "Themenbereiche";
+["Author"] = "Autor";
+["Autoreject is off."] = "Auto-Ablehnen ist aus";
+["Autoreject is on."] = "Auto-Ablehnen ist an";
+["Cancel"] = false;
+["Cancelled"] = "Abgebrochen";
+["Change password"] = "Kennwort ändern";
+["Click here to close."] = "Zum Schließen hier klicken";
+["Close"] = "Schließen";
+["Closed"] = "geschlossen";
+["Commit suggestion"] = "Anregung speichern";
+["Contacts"] = "Kontakte";
+["Content"] = "Inhalt";
+["Create new area"] = "Neuen Themenbereich anlegen";
+["Create new issue"] = "Neues Thema anlegen";
+["Created at"] = "Erzeugt am/um";
+["Current draft"] = "Aktueller Entwurf";
+["Degree"] = "Grad";
+["Delegate"] = "Delegieren";
+["Description"] = "Beschreibung";
+["Details"] = "Details";
+["Direct member count"] = "Anzahl Direktmitglieder";
+["Direct supporter [change]"] = "Direkte Unterstützung [ändern]";
+["Draft"] = "Entwurf";
+["Edit"] = "Bearbeiten";
+["Edit my page"] = "Meine Seite bearbeiten";
+["Error while updating member, database reported:
(#{errormessage})"] = "Fehler beim aktualisieren des Mitglieds, die Datenbank berichtet folgenden Fehler:
(#{errormessage})";
+["Finished"] = "Abgeschlossen";
+["Frozen"] = "Eingefroren";
+["Fulfilled"] = "Erfüllt";
+["Fullfilled"] = "Erfüllt";
+["Fully frozen"] = false;
+["Global delegation"] = "Globale Delegation";
+["Half frozen"] = false;
+["Hide"] = "Verstecken";
+["Home"] = "Startseite";
+["Id"] = "Id";
+["Ident number"] = "Ident-Nummer";
+["In discussion"] = "In Diskussion";
+["Incoming delegations"] = "Eingehende Delegationen";
+["Initiative"] = "Initiative";
+["Initiative successfully created"] = "Initiative erfolgreich erzeugt";
+["Initiative: '#{name}'"] = "Initiative: '#{name}'";
+["Initiatives"] = "Initiativen";
+["Initiators"] = "Initiatoren";
+["Interest not existant"] = false;
+["Interest removed"] = "Interesse entfernt";
+["Interest updated"] = "Interesse aktualisiert";
+["Invalid username or password!"] = "Ungültiger Benutzername oder Kennwort";
+["Issue"] = "Thema";
+["Issue ##{id}"] = "Issue ##{id}";
+["Issue ##{id} (#{policy_name})"] = "Thema ##{id} (#{policy_name})";
+["Issue policy"] = "Regelwerk für Thema";
+["Issues"] = "Themen";
+["License"] = "Lizenz";
+["Locked?"] = "Gesperrt?";
+["Logged in as:"] = "Angemeldet als:";
+["Login"] = "Anmeldung";
+["Login successful!"] = "Anmeldung erfolgreich";
+["Logout"] = "Abmelden";
+["Logout successful"] = "Abmeldung erfolgreich";
+["Me"] = "Ich";
+["Member '#{member}'"] = "Mitglied '#{member}'";
+["Member has been removed from your contacts"] = "Mitglied wurde aus Deinen Kontakten entfernt";
+["Member has been saved as private contact"] = "Mitglied wurde als privater Kontakt gespeichert";
+["Member has been saved as public contact"] = "Mitglied wurde als öffentlicher Kontakt gespeichert";
+["Member is already saved in your contacts!"] = "Mitglied ist schon in Deinen Kontakten!";
+["Member list"] = "Mitgliederliste";
+["Member login"] = "Mitglied Login";
+["Member name"] = "Mitglied Name";
+["Member successfully registered"] = "Mitglied erfolgreich registriert";
+["Member successfully updated"] = "Mitglied erfolgreich aktualisert";
+["Member: '#{login}' (#{name})"] = "Mitlied: '#{login}' (#{name})";
+["Members"] = "Mitglieder";
+["Membership not existant"] = false;
+["Membership removed"] = "Mitgliedschaft entfernt";
+["Membership updated"] = "Mitgliedschaft aktualisiert";
+["Name"] = "Name";
+["New"] = "Neu";
+["New draft has been added to initiative"] = "Neuer Entwurf wurde der Initiative hinzugefügt";
+["New password"] = "Neues Kennwort";
+["New passwords does not match."] = "Du hast nicht zweimal das gleiche Kennwort eingegeben";
+["New passwords is too short."] = "Das neue Kennwort ist zu kurz";
+["Newest"] = "Neueste";
+["No supporter [change]"] = "Keine Unterstützung (ändern)";
+["Not fullfilled"] = "Nicht erfüllt";
+["OK"] = "OK";
+["Old drafts"] = "Alte Entwürfe";
+["Old password"] = "Altes Kennwort";
+["Old password is wrong"] = "Das alte Kennwort ist falsch";
+["Oldest"] = "Älteste";
+["Order by"] = "Sortieren nach";
+["Outgoing delegations"] = "Ausgehende Delegationen";
+["Password"] = "Kennwort";
+["Policy"] = "Regelwerk";
+["Population"] = "Grundgesamtheit";
+["Potential weight"] = "Potentielles Gewicht";
+["Publish"] = "Veröffentlichen";
+["Published"] = "veröffentlicht";
+["Published contacts"] = "Veröffentlichte Kontakte";
+["Rank"] = "Rang";
+["Register new member"] = "Neues Mitglied registrieren";
+["Remove"] = "Entfernen";
+["Remove autoreject"] = "Auto-Ablehnen abschalten";
+["Remove my interest"] = "Interesse abmelden";
+["Remove my membership"] = "Mitgliedschaft aufgeben";
+["Remove my support from this initiative"] = "Meine Unterstützung der Initiative entziehen";
+["Repeat new password"] = "Neues Kennwort wiederholen";
+["Revoke"] = "Widerrufen";
+["Revoked at"] = "Zurückgezogen am/um";
+["Save"] = "Speichern";
+["Search"] = "Suchen";
+["Search initiatives"] = "Suche Initiativen";
+["Search issues"] = "Suche Themen";
+["Search members"] = "Suche Mitglieder";
+["Search results for: '#{search}'"] = "Suchergebnisse für: '#{search}'";
+["Set autoreject"] = "Auto-Ablehnen anschalten";
+["Set delegation for Area '#{name}'"] = "Delegation für Themengebiet '#{name}' festlegen";
+["Set delegation for Issue ##{number} in Area '#{area_name}'"] = "Delegation für Thema ##{number} im Themenbereich '#{area_name}' festlegen";
+["Show"] = "Zeige";
+["Show active members"] = "Zeige aktive Mitglieder";
+["Show areas in use"] = "Zeige verwendete Themenbereiche";
+["Show areas not in use"] = "Zeige nicht verwendente Themenbereiche";
+["Show locked members"] = "Zeige gesperrte Mitglieder";
+["Software"] = false;
+["State"] = "Zustand";
+["Suggestion for initiative: '#{name}'"] = "Anregung für Initiative '#{name}'";
+["Suggestions"] = "Anregungen";
+["Support"] = "Unterstützung";
+["Support S+I"] = "Unterstütung S+I";
+["Support this initiative"] = "Diese Initiative unterstützen";
+["Supporter"] = "Unterstützer";
+["That's me!"] = "Das bin ich";
+["Trustee"] = "Bevollmächtigter";
+["Truster"] = "Delegierender";
+["Unknown author"] = "Unbekannter Autor";
+["Upload avatar"] = "Avatar hochladen";
+["Username"] = "Benutzername";
+["Version"] = false;
+["Vote later"] = "Später abstimmen";
+["Vote now"] = "Jetzt abstimmen";
+["Voting"] = "Abstimmung";
+["Voting requests"] = "Abstimmanträge";
+["You are already not supporting this initiative"] = "Diese Initiative hat bereits keine Unterstützung von Dir";
+["You are already supporting the latest draft"] = "Du unterstützt bereits den neuesten Entwurf";
+["You are interested. [more]"] = "Du bist interessiert. [mehr]";
+["You are member. [more]"] = "Du bist Mitglied. [mehr]";
+["You are not a member. [more]"] = "Du bist kein Mitglied. [mehr]";
+["You are not interested. [more]"] = "Du bist nicht interessiert. [mehr]";
+["You didn't saved any member as contact yet."] = "Du hast noch kein Mitglied als Kontakt gespeichert!";
+["Your delegation for this area has been deleted."] = "Deine Delegation für dieses Themengebiet wurde gelöscht";
+["Your delegation for this area has been updated."] = "Deine Delegation für dieses Themengebiet wurde geändert";
+["Your delegation for this issue has been deleted."] = "Deine Delegation für dieses Thema wurde gelöscht";
+["Your delegation for this issue has been updated."] = "Deine Delegation für dieses Thema wurde geändert";
+["Your global delegation has been deleted."] = "Deine globale Delegation wurde gelöscht";
+["Your global delegation has been updated."] = "Deine globale Delegation würde geändert";
+["Your opinion has been updated"] = "Deine Meinung wurde aktualisiert";
+["Your password has been updated successfully"] = "Das Kennwort wurde erfolgreich geändert";
+["Your suggestion has been added"] = "Deine Anregung wurde hinzufügt";
+["Your support has been added to this initiative"] = "Deine Unterstützung wurde der Initiative hinzugefügt";
+["Your support has been removed from this initiative"] = "Deine Unterstützung wurde der Initiave entzogen";
+["Your support has been updated to the latest draft"] = "Deine Unterstützung wurde auf den neuesten Entwurf aktualisiert";
+["Your vote is delegated. [more]"] = "Deine Stimme ist delegiert. [mehr]";
+["Z-A"] = false;
+["must"] = "muss";
+["must not"] = "darf nicht";
+["neutral"] = "neutral";
+["remove fulfilled"] = "erfüllt entfernen";
+["set fulfilled"] = "erfüllt setzten";
+["should"] = "soll";
+["should not"] = "soll nicht";
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 locale/translations.en.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/locale/translations.en.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,15 @@
+#!/usr/bin/env lua
+return {
+["Error compile"] = false;
+["Error no file"] = false;
+["Error runtime"] = false;
+["Home"] = false;
+["Invalid username or password!"] = false;
+["Login"] = false;
+["Login successful!"] = false;
+["Logout"] = false;
+["Logout successful"] = false;
+["Password"] = false;
+["Password login"] = false;
+["Username"] = false;
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 model/area.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/area.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,31 @@
+Area = mondelefant.new_class()
+Area.table = 'area'
+
+Area:add_reference{
+ mode = '1m',
+ to = "Issue",
+ this_key = 'id',
+ that_key = 'area_id',
+ ref = 'issues',
+ back_ref = 'area'
+}
+
+Area:add_reference{
+ mode = '1m',
+ to = "Membership",
+ this_key = 'id',
+ that_key = 'area_id',
+ ref = 'memberships',
+ back_ref = 'area'
+}
+
+Area:add_reference{
+ mode = 'mm',
+ to = "Member",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = 'membership',
+ connected_by_this_key = 'area_id',
+ connected_by_that_key = 'member_id',
+ ref = 'members'
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 model/contact.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/contact.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,28 @@
+Contact = mondelefant.new_class()
+Contact.table = 'contact'
+Contact.primary_key = { "member_id", "other_member_id" }
+
+Contact:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'member_id',
+ that_key = 'id',
+ ref = 'member',
+}
+
+Contact:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'other_member_id',
+ that_key = 'id',
+ ref = 'other_member',
+}
+
+
+function Contact:by_pk(member_id, other_member_id)
+ return self:new_selector()
+ :add_where{ "member_id = ?", member_id }
+ :add_where{ "other_member_id = ?", other_member_id }
+ :optional_object_mode()
+ :exec()
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 model/delegation.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/delegation.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,50 @@
+Delegation = mondelefant.new_class()
+Delegation.table = 'delegation'
+
+Delegation:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'truster_id',
+ that_key = 'id',
+ ref = 'truster',
+}
+
+Delegation:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'trustee_id',
+ that_key = 'id',
+ ref = 'trustee',
+}
+
+Delegation:add_reference{
+ mode = 'm1',
+ to = "Area",
+ this_key = 'area_id',
+ that_key = 'id',
+ ref = 'area',
+}
+
+Delegation:add_reference{
+ mode = 'm1',
+ to = "Issue",
+ this_key = 'issue_id',
+ that_key = 'id',
+ ref = 'issue',
+}
+
+function Delegation:by_pk(truster_id, area_id, issue_id)
+ local selector = self:new_selector():optional_object_mode()
+ selector:add_where{ "truster_id = ?", truster_id }
+ if area_id then
+ selector:add_where{ "area_id = ?", area_id }
+ else
+ selector:add_where("area_id ISNULL")
+ end
+ if issue_id then
+ selector:add_where{ "issue_id = ? ", issue_id }
+ else
+ selector:add_where("issue_id ISNULL ")
+ end
+ return selector:exec()
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 model/direct_voter.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/direct_voter.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,18 @@
+DirectVoter = mondelefant.new_class()
+DirectVoter.table = 'member'
+
+DirectVoter:add_reference{
+ mode = 'm1',
+ to = "Issue",
+ this_key = 'issue_id',
+ that_key = 'id',
+ ref = 'issue',
+}
+
+DirectVoter:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'member_id',
+ that_key = 'id',
+ ref = 'member',
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 model/draft.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/draft.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,24 @@
+Draft = mondelefant.new_class()
+Draft.table = 'draft'
+
+Draft:add_reference{
+ mode = 'm1',
+ to = "Initiative",
+ this_key = 'initiative_id',
+ that_key = 'id',
+ ref = 'initiative',
+}
+
+Draft:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'author_id',
+ that_key = 'id',
+ ref = 'author',
+}
+
+-- reference to supporter probably not needed
+
+function Draft.object_get:author_name()
+ return self.author and self.author.name or _"Unknown author"
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 model/initiative.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/initiative.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,114 @@
+Initiative = mondelefant.new_class()
+Initiative.table = 'initiative'
+
+Initiative:add_reference{
+ mode = 'm1',
+ to = "Issue",
+ this_key = 'issue_id',
+ that_key = 'id',
+ ref = 'issue',
+}
+
+Initiative:add_reference{
+ mode = '1m',
+ to = "Draft",
+ this_key = 'id',
+ that_key = 'initiative_id',
+ ref = 'drafts',
+ back_ref = 'initiative',
+ default_order = '"id"'
+}
+
+Initiative:add_reference{
+ mode = '1m',
+ to = "Suggestion",
+ this_key = 'id',
+ that_key = 'initiative_id',
+ ref = 'suggestions',
+ back_ref = 'initiative',
+ default_order = '"id"'
+}
+
+Initiative:add_reference{
+ mode = '1m',
+ to = "Initiator",
+ this_key = 'id',
+ that_key = 'initiative_id',
+ ref = 'initiators',
+ back_ref = 'initiative',
+ default_order = '"id"'
+}
+
+Initiative:add_reference{
+ mode = '1m',
+ to = "Supporter",
+ this_key = 'id',
+ that_key = 'initiative_id',
+ ref = 'supporters',
+ back_ref = 'initiative',
+ default_order = '"id"'
+}
+
+Initiative:add_reference{
+ mode = '1m',
+ to = "Opinion",
+ this_key = 'id',
+ that_key = 'initiative_id',
+ ref = 'opinions',
+ back_ref = 'initiative',
+ default_order = '"id"'
+}
+
+Initiative:add_reference{
+ mode = '1m',
+ to = "Vote",
+ this_key = 'id',
+ that_key = 'initiative_id',
+ ref = 'votes',
+ back_ref = 'initiative',
+ default_order = '"member_id"'
+}
+
+Initiative:add_reference{
+ mode = 'mm',
+ to = "Member",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = '"initiator"',
+ connected_by_this_key = 'initiative_id',
+ connected_by_that_key = 'member_id',
+ ref = 'initiating_members'
+}
+
+Initiative:add_reference{
+ mode = 'mm',
+ to = "Member",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = '"supporter"',
+ connected_by_this_key = 'initiative_id',
+ connected_by_that_key = 'member_id',
+ ref = 'supporting_members'
+}
+
+function Initiative:search(search_string)
+ return self:new_selector()
+ :add_where{ '"initiative"."name" ILIKE ?', "%" .. search_string:gsub("%%", "") .. "%" }
+ :exec()
+end
+
+function Initiative.object_get:current_draft()
+ return Draft:new_selector()
+ :add_where{ '"initiative_id" = ?', self.id }
+ :add_order_by('"id" DESC')
+ :single_object_mode()
+ :exec()
+end
+
+function Initiative.object_get:shortened_name()
+ local name = self.name
+ if #name > 100 then
+ name = name:sub(1,100) .. "..."
+ end
+ return name
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 model/initiator.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/initiator.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,27 @@
+Initiator = mondelefant.new_class()
+Initiator.table = 'initiator'
+Initiator.primary_key = { "initiative_id", "member_id" }
+
+Initiator:add_reference{
+ mode = 'm1',
+ to = "Initiative",
+ this_key = 'initiative_id',
+ that_key = 'id',
+ ref = 'initiative',
+}
+
+Initiator:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'member_id',
+ that_key = 'id',
+ ref = 'member',
+}
+
+function Initiator:by_pk(initiative_id, member_id)
+ return self:new_selector()
+ :add_where{ "initiative_id = ?", initiative_id }
+ :add_where{ "member_id = ?", member_id }
+ :optional_object_mode()
+ :exec()
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 model/interest.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/interest.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,25 @@
+Interest = mondelefant.new_class()
+Interest.table = 'interest'
+Interest.primary_key = { "issue_id", "member_id" }
+Interest:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'member_id',
+ that_key = 'id',
+ ref = 'member',
+}
+
+Interest:add_reference{
+ mode = 'm1',
+ to = "Issue",
+ this_key = 'issue_id',
+ that_key = 'id',
+ ref = 'issue',
+}
+
+function Interest:by_pk(issue_id, member_id)
+ return self:new_selector()
+ :add_where{ "issue_id = ? AND member_id = ?", issue_id, member_id }
+ :optional_object_mode()
+ :exec()
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 model/issue.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/issue.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,109 @@
+Issue = mondelefant.new_class()
+Issue.table = 'issue'
+
+Issue:add_reference{
+ mode = 'm1',
+ to = "Area",
+ this_key = 'area_id',
+ that_key = 'id',
+ ref = 'area',
+}
+
+Issue:add_reference{
+ mode = 'm1',
+ to = "Policy",
+ this_key = 'policy_id',
+ that_key = 'id',
+ ref = 'policy',
+}
+
+Issue:add_reference{
+ mode = '1m',
+ to = "Initiative",
+ this_key = 'id',
+ that_key = 'issue_id',
+ ref = 'initiatives',
+ back_ref = 'issue'
+}
+
+Issue:add_reference{
+ mode = '1m',
+ to = "Interest",
+ this_key = 'id',
+ that_key = 'issue_id',
+ ref = 'interests',
+ back_ref = 'issue',
+ default_order = '"id"'
+}
+
+Issue:add_reference{
+ mode = '1m',
+ to = "Supporter",
+ this_key = 'id',
+ that_key = 'issue_id',
+ ref = 'supporters',
+ back_ref = 'issue',
+ default_order = '"id"'
+}
+
+Issue:add_reference{
+ mode = '1m',
+ to = "DirectVoter",
+ this_key = 'id',
+ that_key = 'issue_id',
+ ref = 'direct_voters',
+ back_ref = 'issue',
+ default_order = '"member_id"'
+}
+
+Issue:add_reference{
+ mode = '1m',
+ to = "Vote",
+ this_key = 'id',
+ that_key = 'issue_id',
+ ref = 'votes',
+ back_ref = 'issue',
+ default_order = '"member_id", "initiative_id"'
+}
+
+Issue:add_reference{
+ mode = 'mm',
+ to = "Member",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = 'interest',
+ connected_by_this_key = 'issue_id',
+ connected_by_that_key = 'member_id',
+ ref = 'members'
+}
+
+function Issue:get_state_name_for_state(value)
+ local state_name_table = {}
+ return state_name_table[value] or value
+end
+
+function Issue:search(search_string)
+ return self:new_selector()
+ :join('"initiative"', nil, '"initiative"."issue_id" = "issue"."id"')
+ :add_where{ '"initiative"."name" ILIKE ?', "%" .. search_string:gsub("%%", "") .. "%" }
+ :set_distinct()
+ :exec()
+end
+
+function Issue.object_get:state()
+ if self.accepted then
+ if self.frozen then
+ return "frozen"
+ elseif self.closed then
+ return "closed"
+ else
+ return "accepted"
+ end
+ else
+ if self.closed then
+ return "closed"
+ else
+ return "new"
+ end
+ end
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 model/member.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/member.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,256 @@
+Member = mondelefant.new_class()
+Member.table = 'member'
+
+Member:add_reference{
+ mode = '1m',
+ to = "Contact",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'contacts',
+ back_ref = 'member',
+ default_order = '"other_member_id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Contact",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'foreign_contacts',
+ back_ref = 'other_member',
+ default_order = '"member_id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Session",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'sessions',
+ back_ref = 'member',
+ default_order = '"ident"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Draft",
+ this_key = 'id',
+ that_key = 'author_id',
+ ref = 'drafts',
+ back_ref = 'author',
+ default_order = '"id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Suggestion",
+ this_key = 'id',
+ that_key = 'author_id',
+ ref = 'suggestions',
+ back_ref = 'author',
+ default_order = '"id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Membership",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'memberships',
+ back_ref = 'member',
+ default_order = '"area_id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Interest",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'interests',
+ back_ref = 'member',
+ default_order = '"id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Initiator",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'initiators',
+ back_ref = 'member',
+ default_order = '"id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Supporter",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'supporters',
+ back_ref = 'member',
+ default_order = '"id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Opinion",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'opinions',
+ back_ref = 'member',
+ default_order = '"id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Delegation",
+ this_key = 'id',
+ that_key = 'truster_id',
+ ref = 'outgoing_delegations',
+ back_ref = 'truster',
+ default_order = '"id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Delegation",
+ this_key = 'id',
+ that_key = 'trustee_id',
+ ref = 'incoming_delegations',
+ back_ref = 'trustee',
+ default_order = '"id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "DirectVoter",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'direct_voter',
+ back_ref = 'member',
+ default_order = '"issue_id"'
+}
+
+Member:add_reference{
+ mode = '1m',
+ to = "Vote",
+ this_key = 'id',
+ that_key = 'member_id',
+ ref = 'vote',
+ back_ref = 'member',
+ default_order = '"issue_id", "initiative_id"'
+}
+
+Member:add_reference{
+ mode = 'mm',
+ to = "Member",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = 'contact',
+ connected_by_this_key = 'member_id',
+ connected_by_that_key = 'other_member_id',
+ ref = 'saved_members',
+}
+
+Member:add_reference{
+ mode = 'mm',
+ to = "Member",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = 'contact',
+ connected_by_this_key = 'other_member_id',
+ connected_by_that_key = 'member_id',
+ ref = 'saved_by_members',
+}
+
+Member:add_reference{
+ mode = 'mm',
+ to = "Area",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = 'membership',
+ connected_by_this_key = 'member_id',
+ connected_by_that_key = 'area_id',
+ ref = 'areas'
+}
+
+Member:add_reference{
+ mode = 'mm',
+ to = "Issue",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = 'interest',
+ connected_by_this_key = 'member_id',
+ connected_by_that_key = 'issue_id',
+ ref = 'issues'
+}
+
+Member:add_reference{
+ mode = 'mm',
+ to = "Initiative",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = 'initiator',
+ connected_by_this_key = 'member_id',
+ connected_by_that_key = 'initiative_id',
+ ref = 'initiated_initiatives'
+}
+
+Member:add_reference{
+ mode = 'mm',
+ to = "Initiative",
+ this_key = 'id',
+ that_key = 'id',
+ connected_by_table = 'supporter',
+ connected_by_this_key = 'member_id',
+ connected_by_that_key = 'initiative_id',
+ ref = 'supported_initiatives'
+}
+
+function Member.object:set_password(password)
+ local hash = os.crypt(
+ password,
+ "$1$" .. multirand.string(
+ 8,
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"
+ )
+ )
+ assert(hash, "os.crypt failed")
+ self.password = hash
+end
+
+function Member.object:check_password(password)
+ if type(password) == "string" and type(self.password) == "string" then
+ return os.crypt(password, self.password) == self.password
+ else
+ return false
+ end
+end
+
+function Member.object_get:published_contacts()
+ return Member:new_selector()
+ :join('"contact"', nil, '"contact"."other_member_id" = "member"."id"')
+ :add_where{ '"contact"."member_id" = ?', self.id }
+ :add_where("public")
+ :exec()
+end
+
+function Member:by_login_and_password(login, password)
+ local selector = self:new_selector()
+ selector:add_where{'"login" = ?', login, password }
+ selector:add_where('"active"')
+ selector:optional_object_mode()
+ local member = selector:exec()
+ if member and member:check_password(password) then
+ return member
+ else
+ return nil
+ end
+end
+
+function Member:search(search_string)
+ return self:new_selector()
+ :add_where{ '"member"."name" ILIKE ?', "%" .. search_string:gsub("%%", "") .. "%" }
+ :add_where("active")
+ :exec()
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 model/member_count.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/member_count.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,6 @@
+MemberCount = mondelefant.new_class()
+MemberCount.table = 'member_count'
+
+function MemberCount:get()
+ return self:new_selector():single_object_mode():exec().total_count
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 model/membership.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/membership.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,26 @@
+Membership = mondelefant.new_class()
+Membership.table = 'membership'
+Membership.primary_key = { "area_id", "member_id" }
+
+Membership:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'member_id',
+ that_key = 'id',
+ ref = 'member',
+}
+
+Membership:add_reference{
+ mode = 'm1',
+ to = "Area",
+ this_key = 'area_id',
+ that_key = 'id',
+ ref = 'area',
+}
+
+function Membership:by_pk(area_id, member_id)
+ return self:new_selector()
+ :add_where{ "area_id = ? AND member_id = ?", area_id, member_id }
+ :optional_object_mode()
+ :exec()
+end
\ No newline at end of file
diff -r 000000000000 -r 3bfb2fcf7ab9 model/opinion.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/opinion.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,35 @@
+Opinion = mondelefant.new_class()
+Opinion.table = 'opinion'
+Opinion.primary_key = { "member_id", "suggestion_id" }
+
+Opinion:add_reference{
+ mode = 'm1',
+ to = "Initiative",
+ this_key = 'initiative_id',
+ that_key = 'id',
+ ref = 'initiative',
+}
+
+Opinion:add_reference{
+ mode = 'm1',
+ to = "Suggestion",
+ this_key = 'suggestion_id',
+ that_key = 'id',
+ ref = 'suggestion',
+}
+
+Opinion:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'member_id',
+ that_key = 'id',
+ ref = 'member',
+}
+
+function Opinion:by_pk(member_id, suggestion_id)
+ return self:new_selector()
+ :add_where{ "member_id = ?", member_id }
+ :add_where{ "suggestion_id = ?", suggestion_id }
+ :optional_object_mode()
+ :exec()
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 model/policy.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/policy.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,12 @@
+Policy = mondelefant.new_class()
+Policy.table = 'policy'
+
+Policy:add_reference{
+ mode = '1m',
+ to = "Issue",
+ this_key = 'id',
+ that_key = 'policy_id',
+ ref = 'issues',
+ back_ref = 'policy',
+ default_order = '"created", "id"'
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 model/session.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/session.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,33 @@
+Session = mondelefant.new_class()
+Session.table = 'session'
+Session.primary_key = { 'ident' }
+
+Session:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'member_id',
+ that_key = 'id',
+ ref = 'member',
+}
+
+local function random_string()
+ return multirand.string(
+ 32,
+ '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
+ )
+end
+
+function Session:new()
+ local session = self.prototype.new(self) -- super call
+ session.ident = random_string()
+ session.additional_secret = random_string()
+ session:save()
+ return session
+end
+
+function Session:by_ident(ident)
+ local selector = self:new_selector()
+ selector:add_where{ 'ident = ?', ident }
+ selector:optional_object_mode()
+ return selector:exec()
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 model/suggestion.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/suggestion.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,28 @@
+Suggestion = mondelefant.new_class()
+Suggestion.table = 'suggestion'
+
+Suggestion:add_reference{
+ mode = 'm1',
+ to = "Initiative",
+ this_key = 'initiative_id',
+ that_key = 'id',
+ ref = 'initiative',
+}
+
+Suggestion:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'author_id',
+ that_key = 'id',
+ ref = 'author',
+}
+
+Suggestion:add_reference{
+ mode = '1m',
+ to = "Opinion",
+ this_key = 'id',
+ that_key = 'issue_id',
+ ref = 'opinions',
+ back_ref = 'issue',
+ default_order = '"id"'
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 model/supporter.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/supporter.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,27 @@
+Supporter = mondelefant.new_class()
+Supporter.table = 'supporter'
+Supporter.primary_key = { "initiative_id", "member_id" }
+
+Supporter:add_reference{
+ mode = 'm1',
+ to = "Initiative",
+ this_key = 'initiative_id',
+ that_key = 'id',
+ ref = 'initiative',
+}
+
+Supporter:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'member_id',
+ that_key = 'id',
+ ref = 'member',
+}
+
+function Supporter:by_pk(initiative_id, member_id)
+ return self:new_selector()
+ :add_where{ "initiative_id = ?", initiative_id }
+ :add_where{ "member_id = ?", member_id }
+ :optional_object_mode()
+ :exec()
+end
diff -r 000000000000 -r 3bfb2fcf7ab9 model/vote.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/model/vote.lua Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,26 @@
+Vote = mondelefant.new_class()
+Vote.table = 'vote'
+
+Vote:add_reference{
+ mode = 'm1',
+ to = "Issue",
+ this_key = 'issue_id',
+ that_key = 'id',
+ ref = 'issue',
+}
+
+Vote:add_reference{
+ mode = 'm1',
+ to = "Initiative",
+ this_key = 'initiative_id',
+ that_key = 'id',
+ ref = 'initiative',
+}
+
+Vote:add_reference{
+ mode = 'm1',
+ to = "Member",
+ this_key = 'author_id',
+ that_key = 'id',
+ ref = 'author',
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/add.png
Binary file static/icons/16/add.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/application_form.png
Binary file static/icons/16/application_form.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/award_star_gold_2.png
Binary file static/icons/16/award_star_gold_2.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/award_star_silver_2.png
Binary file static/icons/16/award_star_silver_2.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/book_add.png
Binary file static/icons/16/book_add.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/book_edit.png
Binary file static/icons/16/book_edit.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/cancel.png
Binary file static/icons/16/cancel.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/cog.png
Binary file static/icons/16/cog.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/comment_add.png
Binary file static/icons/16/comment_add.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/cross.png
Binary file static/icons/16/cross.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/delete.png
Binary file static/icons/16/delete.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/folder.png
Binary file static/icons/16/folder.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/folder_add.png
Binary file static/icons/16/folder_add.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/group.png
Binary file static/icons/16/group.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/house.png
Binary file static/icons/16/house.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/information.png
Binary file static/icons/16/information.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/key.png
Binary file static/icons/16/key.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/package.png
Binary file static/icons/16/package.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/page.png
Binary file static/icons/16/page.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/page_add.png
Binary file static/icons/16/page_add.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/script.png
Binary file static/icons/16/script.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/script_add.png
Binary file static/icons/16/script_add.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/stop.png
Binary file static/icons/16/stop.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/table_go.png
Binary file static/icons/16/table_go.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/thumb_down_red.png
Binary file static/icons/16/thumb_down_red.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/thumb_up_green.png
Binary file static/icons/16/thumb_up_green.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/tick.png
Binary file static/icons/16/tick.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/user_comment.png
Binary file static/icons/16/user_comment.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/icons/16/user_gray.png
Binary file static/icons/16/user_gray.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/lang/de.png
Binary file static/lang/de.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/lang/en.png
Binary file static/lang/en.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/lang/es.png
Binary file static/lang/es.png has changed
diff -r 000000000000 -r 3bfb2fcf7ab9 static/style.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/style.css Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,559 @@
+/*************************************************************************
+ * Some global definitions
+ */
+
+body, th, td {
+ font-family: sans-serif;
+ font-size: 14px;
+ padding: 0;
+ margin: 0;
+}
+
+body, a {
+ color: #000;
+}
+
+img {
+ border: none;
+}
+
+table {
+ border-collapse: collapse;
+ border: none;
+}
+
+td, th {
+ vertical-align: top;
+ padding: 0.5ex 0.5em 0.5ex 0.5em;
+}
+
+a.active {
+ color: #fff;
+}
+
+.highlighted {
+ background-color: #fa7;
+ color: #000;
+}
+
+.admin_only {
+ font-style: italic;
+}
+
+/*************************************************************************
+ * Notices, warnings and errors
+ */
+
+.layout_notice, .layout_error, .layout_warning {
+ background: #fff;
+ font-weight: bold;
+ right: 2ex;
+ line-height: 1.7em;
+ position: absolute;
+ top: 6ex;
+ width: 60ex;
+ -moz-opacity:0.7;
+}
+
+.slot_notice, .slot_warning, .slot_error {
+ padding: 2ex;
+}
+
+.slot_notice {
+ color: green;
+ border: 2px solid green;
+}
+
+.slot_warning {
+ color: orange;
+ border: 2px solid orange;
+}
+
+.slot_error {
+ color: red;
+ border: 2px solid red;
+}
+
+/*************************************************************************
+ * Navigation, search and language chooser bar
+ */
+
+.topbar {
+ margin-bottom: 1em;
+ background-color: #444;
+ color: #fff;
+ font-size: 75%;
+}
+
+.topbar a {
+ color: #fff;
+}
+
+.topbar a:hover {
+ background-color: #fff;
+ color: #000;
+}
+
+.navigation,
+.logout_button {
+ line-height: 250%;
+}
+
+.navigation img,
+.logout_button img {
+ margin-right: 0.5em;
+ vertical-align: middle;
+}
+
+.navigation a,
+.logout_button a {
+ padding: 1ex;
+}
+
+.logout_button {
+ float: right;
+}
+
+.searchbox {
+ padding: 0.5ex 1em 0ex 1em;
+ float: right;
+ line-height: 250%;
+}
+
+.searchbox div {
+ display: inline;
+}
+
+.searchbox select {
+ margin-left: 0.3em;
+ margin-right: 0.4em;
+ font-size: 100%;
+ width: 8em;
+}
+
+.searchbox input[type=text] {
+ width: 8em;
+ padding: 0.25ex 0.25em 0.25ex 0.25em;
+ margin-right: 0.5em;
+ font-size: 100%;
+}
+
+.searchbox input[type=submit] {
+ font-size: 100%;
+ width: 2.5em;
+}
+
+/*************************************************************************
+ * Title of current page including path and actions
+ */
+
+.title_bar {
+ border-bottom: 1px solid #000;
+ margin-bottom: 2ex;
+}
+
+.path {
+ color: #444;
+ xbackground-color: #ddd;
+}
+
+.path div {
+ margin-left: 1em;
+ font-size: 100%;
+ line-height: 180%;
+}
+
+.path a {
+ color: #444;
+}
+
+.slot_path div {
+ display: inline;
+ margin-left: 1em;
+ margin-right: 1em;
+}
+
+.title {
+ color: #000;
+ margin-bottom: 0.5ex;
+}
+
+.slot_title {
+}
+
+.title div {
+ margin-left: 0.66em;
+ font-weight: bold;
+ font-size: 135%;
+ line-height: 110%;
+}
+
+.title a {
+ color: #fff;
+}
+
+.avatar {
+ float: left;
+ margin-right: 0.5em;
+}
+
+.actions {
+ display: inline;
+ font-size: 75%;
+ line-height: 200%;
+}
+
+.slot_actions {
+ margin-left: 1em;
+ display: inline;
+}
+
+.actions a {
+ padding: 0.5ex 0.5em 0.5ex 0.0em;
+ margin-right: 1em;
+ vertical-align: middle;
+}
+
+.actions a:hover {
+ background-color: #d7d7d7;
+}
+
+.actions img {
+ padding-left: 0.2em;
+ padding-right: 0.2em;
+}
+
+/*************************************************************************
+ * Main content
+ */
+
+.main {
+ margin-left: 1em;
+ margin-right: 1em;
+}
+
+
+/*************************************************************************
+ * ui.tab
+ */
+
+.ui_tabs_links {
+ margin-top: 4ex;
+ font-size: 75%;
+}
+
+.ui_tabs_links a {
+ padding: 1ex;
+ margin-left: 0.5em;
+ background-color: #e7e7e7;
+}
+
+.ui_tabs_links a:hover {
+ background-color: #d7d7d7;
+}
+
+.ui_tabs_links a.selected {
+ background-color: #444;
+ color: #fff;
+ text-decoration: none;
+ padding: 1ex;
+}
+
+.ui_tabs_content {
+ border: 1px solid #444;
+ padding: 1ex 1ex 1ex 1ex;
+}
+
+/*************************************************************************
+ * ui.order
+ */
+
+.ui_order_head {
+ color: #777;
+ text-align: right;
+ margin-bottom: 1ex;
+ font-size: 75%;
+}
+
+.ui_order_head a {
+ color: #777;
+ padding: 0.5ex;
+}
+
+.ui_order_head a.active{
+ color: #fff;
+ background-color: #777;
+ padding: 0.5ex;
+}
+
+/*************************************************************************
+ * ui.paginate
+ */
+
+.ui_paginate_select a {
+ padding: 0.5ex;
+}
+
+/*************************************************************************
+ * ui.bargraph
+ */
+
+.bargraph {
+ width: 50px;
+}
+
+.bargraph div {
+ float: left;
+ margin-top: 0.5ex;
+ height: 1ex;
+}
+
+/*************************************************************************
+ * vertical ui.form
+ */
+
+.login input[type=text],
+.vertical input[type=text],
+.login input[type=password],
+.vertical input[type=password],
+.vertical textarea,
+.vertical select {
+ font-family: sans-serif;
+ font-size: 100%;
+ border: 1px solid #444;
+ width: 40em;
+ padding: 0.2ex 0.2em 0.2ex 0.2em;
+ margin-bottom: 1ex;
+}
+
+.login input[type=password],
+.vertical input[type=password] {
+ width: 16em;
+}
+
+.vertical select {
+ padding-right: 0;
+}
+
+.login .ui_field_label,
+.vertical .ui_field_label {
+ text-transform: uppercase;
+ font-size: 70%;
+ line-height: 190%;
+ font-weight: bold;
+ color: #777;
+ width: 15em;
+ display: block;
+ float: left;
+ clear: left;
+ text-align: right;
+ padding-right: 0.5em;
+}
+
+.login input[type=text],
+.login input[type=password] {
+ width: 10em;
+}
+
+.login div,
+.vertical div {
+ clear: left;
+}
+
+.vertical span {
+ display: block;
+ margin-bottom: 0.5ex;
+}
+
+.vertical span:after {
+ content: " ";
+}
+
+.vertical span span {
+ display: inline;
+ margin-bottom: 0;
+}
+
+.login input[type=submit],
+.vertical input[type=submit] {
+ font-size: 100%;
+ margin-left: 11em;
+ background-color: #444444;
+ color: #fff;
+ border: none;
+ padding: 0.75ex;
+}
+
+.login input[type=submit]:hover,
+.vertical input[type=submit]:hover {
+ background-color: #444444;
+}
+
+/*************************************************************************
+ * Tables
+ */
+
+
+table a.action {
+ font-size: 70%;
+ line-height: 190%;
+ padding: 0.5ex;
+ color: #777;
+}
+
+table a.active {
+ color: #fff;
+}
+
+th {
+ text-align: left;
+ border-bottom: 1px solid #000;
+}
+
+tr:hover td {
+ background-color: #ddd;
+}
+
+
+tr table tr:hover td {
+ background-color: #fff;
+}
+
+
+/*************************************************************************
+ * Hidden inline form
+ */
+
+.hidden_inline_form {
+ display: none;
+ border: 1px solid #444;
+ width: 42em;
+ position: absolute;
+ background-color: #fff;
+ left: 5em;
+ top: 20ex;
+}
+
+.hidden_inline_form a {
+ padding: 0.5ex;
+ color: #fff;
+}
+
+
+.hidden_inline_form .head {
+ background-color: #444;
+ color: #fff;
+ display: block;
+ padding: 0.5ex;
+}
+
+.hidden_inline_form input[type=text],
+.hidden_inline_form textarea,
+.hidden_inline_form select {
+ width: 30em;
+}
+
+/*************************************************************************
+ * Positive / Negtive votes
+ */
+
+
+.positive_votes span {
+ display: inline;
+}
+
+.positive_votes {
+ display: inline;
+ background-color: #cfc;
+ padding: 0.3ex 0.5em 0.3ex 0.5em;
+}
+
+.negative_votes span {
+ display: inline;
+}
+
+.negative_votes {
+ display: inline;
+ background-color: #fcc;
+ padding: 0.3ex 0.5em 0.3ex 0.5em;
+}
+
+
+
+.active {
+ background-color: #444;
+ color: #fff;
+}
+
+.active_red2 { background-color: #a00; color: #fff !important; }
+.active_red1 { background-color: #f88; color: #000 !important; }
+.active_green1 { background-color: #8f8; color: #000 !important; }
+.active_green2 { background-color: #0a0; color: #000 !important; }
+
+
+
+
+/*************************************************************************
+ * Issues
+ */
+
+.issues tr {
+ border-bottom: 1px solid #444;
+}
+
+.issues tr tr {
+ border-bottom: none;
+}
+
+/*************************************************************************
+ * delegation
+ */
+
+.infobox {
+ float: right;
+ margin-right: 1em;
+}
+
+.slot_interest,
+.slot_support,
+.slot_delegation {
+ border: 2px solid #444;
+ width: 20em;
+ font-size: 75%;
+ padding: 0;
+ margin-bottom: 0.5ex;
+}
+
+.infobox .head {
+ margin: 0.5ex;
+}
+
+.infobox .content {
+ display: none;
+ position: absolute;
+ z-index: 10;
+ width: 20em;
+ background-color: #fff;
+ border: 2px solid #444;
+}
+
+.infobox .text {
+ margin: 0.5ex;
+ margin-bottom: 1ex;
+}
+
+.infobox .member {
+ margin: 0.5ex;
+ display: block;
+ font-weight: bold;
+ margin-bottom: 1ex;
+}
+
+.delegation .revoke {
+ margin: 0.5ex;
+}
+
+.lang_chooser {
+ float: right;
+ margin-right: 0.5em;
+}
diff -r 000000000000 -r 3bfb2fcf7ab9 static/trace.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/trace.css Wed Nov 18 12:00:00 2009 +0100
@@ -0,0 +1,154 @@
+.layout_trace {
+ position: absolute;
+ right: 0;
+ margin-top: 20px;
+ border: 1px solid #404040;
+ font-size: 70%;
+ padding: 5px;
+ background: #ffe0c0;
+}
+
+#trace_show {
+ cursor: pointer;
+}
+
+.trace_list {
+ margin: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ list-style-type: none;
+}
+
+.trace_list .trace_list {
+ border-top: 1px solid;
+ margin-bottom: 0px;
+}
+
+.trace_list li {
+ margin: 3px;
+ padding: 0px;
+}
+
+.trace_head {
+ font-weight: bold;
+ margin: 1px;
+}
+
+.trace_error {
+ border: 3px solid red;
+ background-color: black;
+ color: #c00000;
+ text-align: center;
+ text-decoration: blink;
+}
+
+.trace_error_position {
+ color: red;
+ text-decoration: blink;
+ font-weight: bold;
+}
+
+.trace_config {
+ border: 1px solid #608000;
+ background-color: #ffffff;
+ color: #608000;
+}
+
+.trace_config .trace_list {
+ border-color: #608000;
+}
+
+.trace_request {
+ border: 1px solid #6000ff;
+ background-color: #c080ff;
+ color: #6000ff;
+}
+
+.trace_request .trace_list {
+ border-color: #6000ff;
+}
+
+.trace_filter {
+ border: 1px solid #606060;
+ background-color: #c0c0c0;
+ color: #606060;
+}
+
+.trace_filter .trace_list {
+ border-color: #606060;
+}
+
+.trace_view {
+ border: 1px solid #0000ff;
+ background-color: #40c0ff;
+ color: #0000ff;
+}
+
+.trace_view .trace_list {
+ border-color: #0000ff;
+}
+
+.trace_action_success {
+ border: 1px solid #006000;
+ background-color: #80ff80;
+ color: #006000;
+}
+
+.trace_action_success .trace_list {
+ border-color: #006000;
+}
+
+.trace_action_softfail {
+ border: 1px solid #600000;
+ background-color: #ff6020;
+ color: #600000;
+}
+
+.trace_action_softfail .trace_list {
+ border-color: #600000;
+}
+
+.trace_action_status {
+ font-weight: bold;
+}
+
+.trace_action_neutral {
+ border: 1px solid #600000;
+ background-color: #ffc040;
+ color: #600000;
+}
+
+.trace_action_neutral .trace_list {
+ border-color: #600000;
+}
+
+.trace_redirect, .trace_forward {
+ border: 1px solid #404000;
+ background-color: #c08040;
+ color: #404000;
+}
+
+.trace_redirect .trace_list, .trace_forward .trace_list {
+ border-color: #404000;
+}
+
+.trace_exectime {
+ border: 1px solid black;
+ background-color: #404040;
+ color: white;
+}
+
+.trace_exectime .trace_list {
+ border-color: white;
+}
+
+.trace_close {
+ border: 1px solid black;
+ background-color: #605040;
+ margin: 3px;
+ padding: 3px;
+ color: white;
+ text-align: center;
+ cursor: pointer;
+}
+
diff -r 000000000000 -r 3bfb2fcf7ab9 tmp/.keep