# 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 @@ + + + + <!-- WEBMCP SLOTNODIV app_name --> + + + + + +
+
+ +
+ + +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+
TRACE
+ +
+ +
+ +
+
+ +
+
+ +
+ + + \ 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 +
+
+
+
+ +
+ +
close
+
+
+ + \ 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, "") + end +end + +local function rss_item(item) + slot.put("") + for key, val in pairs(item) do + slot.put("<", key, ">", val, "") + 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), "") + end +end + +local function rss_item(item) + slot.put("") + for key, val in pairs(item) do + slot.put("<", key, ">", encode.html(val), "") + 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